Skip to content

feat(node-type-registry): blueprint type codegen — TS types from node type definitions#908

Merged
pyramation merged 6 commits intomainfrom
devin/1774523989-blueprint-ts-types
Mar 26, 2026
Merged

feat(node-type-registry): blueprint type codegen — TS types from node type definitions#908
pyramation merged 6 commits intomainfrom
devin/1774523989-blueprint-ts-types

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

@pyramation pyramation commented Mar 26, 2026

Summary

Adds a TypeScript codegen script (src/codegen/generate-types.ts) that reads the existing allNodeTypes array and produces blueprint-types.generated.ts — a set of TypeScript types matching the JSONB shape expected by construct_blueprint().

Motivation: Replace the hand-crafted 963-line GraphQL plugin approach (PR #907) with generated client-side types. The GraphQL API stays simple (plain JSONB), while consumers get autocomplete and type safety when building blueprint definitions in TypeScript.

What's generated (916 lines):

  • Per-node-type parameter interfaces derived from parameter_schema JSON Schema (e.g. DataIdParams, AuthzDirectOwnerParams)
  • BlueprintNode discriminated union (string shorthand 'DataId' or typed object { $type: 'DataId', data: DataIdParams })
  • BlueprintRelation discriminated union for 4 relation types
  • Static structural types: BlueprintField, BlueprintPolicy, BlueprintIndex, BlueprintFullTextSearch, BlueprintTable, BlueprintDefinition

Cleanup: removed dead blueprint-types plugin + NodeTypeRegistryPreset

  • Deleted graphile-settings/src/plugins/blueprint-types/ (3 files, ~730 lines) and its test file (~270 lines). These were the hand-crafted GraphQL plugin approach that this codegen replaces — never imported by any preset or consumer on main.
  • Removed blueprint-types exports from graphile-settings/src/plugins/index.ts.
  • Deleted node-type-registry/src/preset.ts (NodeTypeRegistryPreset) — it imported createBlueprintTypesPlugin from the now-deleted plugin. This preset is no longer needed; consumers should use the generated TS types directly instead of GraphQL input types.
  • Removed graphile-settings and graphile-config from node-type-registry dependencies (only used by the deleted preset). This significantly reduces the package's dependency footprint.

AST-based codegen via schema-typescript

Replaced the hand-rolled jsonSchemaToTsType() string concatenation with a pure Babel AST approach:

  • Dependencies: schema-typescript@^0.14.2, @babel/generator@^7.29.0, @babel/types@^7.29.0
  • generate-types.ts rewritten (80%): All type construction uses @babel/types AST nodes. Per-node-type parameter interfaces are produced by schema-typescript's generateTypeScriptTypes() which returns t.ExportNamedDeclaration[] directly. Static structural types (BlueprintTable, BlueprintDefinition, etc.) are built with AST helper functions. Final output via @babel/generator's generate().
  • Numeric/boolean enums handled upstream: schema-typescript@0.14.2 (dev-utils PR #73) fixes getTypeForProp() to use t.numericLiteral() / t.booleanLiteral() for non-string enum and const values. Generated types now include proper numeric literal unions (e.g. dimension?: 2 | 3 | 4).
  • Minimal ensureArrayItems() sanitizer: schema-typescript still throws on array types without an items spec. A small recursive function adds { type: 'string' } as default items for bare arrays — this is the only remaining workaround.
  • No string concatenation anywhere in the codegen pipeline.

Review & Testing Checklist for Human

  • Verify generated output matches codegen: Run cd graphile/node-type-registry && pnpm generate:types and confirm blueprint-types.generated.ts is unchanged (ensures the committed file isn't stale or manually edited)
  • Spot-check static structural types against construct_blueprint(): BlueprintField, BlueprintPolicy, BlueprintTable, BlueprintDefinition are hardcoded in the generator (not derived from schema). Verify field names/types match what the SQL function actually reads — especially BlueprintPolicy.$type, BlueprintTable.grants (unknown[] is very loose), and BlueprintIndex.access_method
  • Verify ensureArrayItems() default is safe: The sanitizer adds items: { type: 'string' } for arrays without an items spec. Check whether any node type schemas have array fields that should resolve to something other than string[]
  • Verify require('@babel/generator') workaround: The @babel/generator import uses const generate = require(…).default ?? require(…) because @types/babel__generator isn't in dependencies. Confirm this works in both CJS and ESM builds
  • Confirm no consumers import NodeTypeRegistryPreset: The preset is deleted — search downstream repos (especially constructive-db) for NodeTypeRegistryPreset or from 'node-type-registry/preset' imports. constructive-db PR refactor(codegen): remove dead maxFieldDepth code and enforce trailing commas #697 removes the only known usage

Notes

Link to Devin session: https://app.devin.ai/sessions/ce1b2dafd42341bea5d7793b0c05ba6c
Requested by: @pyramation

…ypes from node type definitions

Adds generate-types.ts codegen that produces blueprint-types.generated.ts with:
- Per-node-type parameter interfaces (DataIdParams, AuthzDirectOwnerParams, etc.)
- BlueprintNode discriminated union (string shorthand or typed object)
- BlueprintRelation, BlueprintTable, BlueprintDefinition types
- Static types: BlueprintField, BlueprintPolicy, BlueprintIndex, etc.

These are client-side types matching the JSONB shape expected by
construct_blueprint(). The GraphQL API stays simple (plain JSON scalar).

Also:
- Exports generated types from package index
- Adds generate:types npm script
- Updates README with new usage examples
- Deprecates NodeTypeRegistryPreset in favor of generated types
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

…types

The hand-crafted 963-line GraphQL plugin (from PR #907) is replaced by
the codegen approach in node-type-registry. These files were never
imported or referenced from any preset or consumer.

Removes:
- graphile-settings/src/plugins/blueprint-types/ (3 files)
- graphile-settings/__tests__/blueprint-types-plugin.test.ts
…ype codegen

Replace hand-rolled string concatenation with:
- schema-typescript's generateTypeScriptTypes() for JSON Schema -> Babel AST
- @babel/types for all structural type construction
- @babel/generator for final code output

No string concatenation in the codegen pipeline. All 52 node types
generate correctly with proper enum handling and nested object support.
…or numeric enum/const support

- Bump schema-typescript from ^0.14.1 to ^0.14.2
- Remove sanitizeSchema workaround for numeric enums (fixed upstream)
- Keep minimal ensureArrayItems() for array types missing items spec
- Generated types now include proper numeric literals (e.g. dimension?: 2 | 3 | 4)
@pyramation pyramation merged commit f87c2f4 into main Mar 26, 2026
43 checks passed
@pyramation pyramation deleted the devin/1774523989-blueprint-ts-types branch March 26, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant