Skip to content

fix(codegen): create is optional like update/delete - #1986

Merged
pyramation merged 2 commits into
mainfrom
feat/codegen-optional-create
Nov 11, 2026
Merged

pyramation merged 2 commits into
mainfrom
feat/codegen-optional-create

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

Summary

Table inference fabricated a create mutation name when the schema had none:

// graphql/query/src/introspect/infer-tables.ts
- create: mutationOps.create ?? `create${entityName}`,
+ create: mutationOps.create,          // TableQueryNames.create: string | null

so a table whose create is hidden (e.g. a storage files table, where upload<Files> is the only way a row is created — constructive-db#4335) still got a create* ORM method, useCreate*Mutation hook, CLI create subcommand and docs/skills, all calling a mutation that does not exist. update/delete were already nullable; create now follows the same rule:

  • graphql/query: create nullable; the create op is only registered/generated when present.
  • graphql/codegen: hasCreateMutation(table) gates the create hook + its barrel export, the ORM model create method (and m2n add<Relation> when the junction has no create), the CLI create subcommand/handler, and the CLI/ORM/hooks docs.

Unit tests: infer-tables returns create: null for a table without a create mutation; the model generator emits update/delete but no create for it.

Link to Devin session: https://app.devin.ai/sessions/7ffa2e370d49424bb81161cc2390ba12
Open in Devin Desktop: https://app.devin.ai/desktop/session/7ffa2e370d49424bb81161cc2390ba12?variant=devin
Requested by: @pyramation

…ook, model method, CLI command or docs for a table without one
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@tenki-reviewer

tenki-reviewer Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Review complete. 🟡 2 medium

📍 Findings outside the diff (2) — 🟡 2 medium — defects on lines GitHub can't attach comments to

🟡 Medium — Widen stale inline create: string type · transform-schema.ts:347 · unchanged line

// graphql/query/src/introspect/transform-schema.ts
347	      create: string;

TableQueryNames.create was widened to string | null in both packages' schema types, but the inline structural type of the tables parameter of getTableOperationNames still declares create: string (graphql/query/src/introspect/transform-schema.ts:347). The sole pipeline caller passes introspected Table[] typed with the widened interface (graphql/codegen/src/core/pipeline/index.ts:152), so the argument no longer type-checks against the declared parameter. Typed consumers get a compile error or a misleading contract that claims create is always a string.


🟡 Medium — Multi-target skill refs omit the create guard · docs-generator.ts:1219–1250 · unchanged line

// graphql/codegen/src/core/codegen/cli/docs-generator.ts
1219	            `${toolName} ${cmd} create ${createFlags}`,
1220	            `${toolName} ${cmd} update --${pk.name} <${cleanTypeName(pk.gqlType)}> ${editableFields.map((f) => `[--${f.name} <${cleanTypeName(f.type.gqlType)}>]`).join(' ')}`,
1221	            `${toolName} ${cmd} delete --${pk.name} <${cleanTypeName(pk.gqlType)}>`,
1222	          ],
1223	          examples: [
1224	            {
1225	              description: `List ${singularName} records`,
1226	              code: [`${toolName} ${cmd} list`],
1227	            },
1228	            {
1229	              description: `List ${singularName} records with pagination`,
1230	              code: [`${toolName} ${cmd} list --limit 10 --offset 0`],

The PR guards create usage entries and examples in the single-target skill references (graphql/codegen/src/core/codegen/cli/docs-generator.ts:474), but the multi-target loop still pushes ${toolName} ${cmd} create ${createFlags} and a 'Create a ...' example unconditionally (graphql/codegen/src/core/codegen/cli/docs-generator.ts:1219). Since the CLI command generator now omits the create subcommand for tables with create: null (graphql/codegen/src/core/codegen/cli/table-command-generator.ts:1763), the generated multi-target skill instructs users to run a subcommand that does not exist. Every such invocation fails.


The change widens TableQueryNames.create from string to string | null so tables without a create mutation no longer fall back to a synthesized create<TypeName> name, and every generator downstream of that contract is updated to skip create-specific output when it is absent.

Files Change
graphql/query/src/types/schema.ts, graphql/codegen/src/types/schema.ts Widen TableQueryNames.create to string | null in both packages.
graphql/query/src/introspect/infer-tables.ts, graphql/query/src/introspect/transform-schema.ts Stop defaulting create to a synthesized name; add a null guard where mutation names are collected.
graphql/codegen/src/core/codegen/orm/model-generator.ts, graphql/codegen/src/core/codegen/mutations.ts, graphql/codegen/src/core/codegen/utils.ts Gate create-input and create<TypeName> hook generation on the create mutation existing.
graphql/codegen/src/core/codegen/barrel.ts Conditionally emit barrel re-exports for create-hook files that may no longer be generated.
graphql/codegen/src/core/codegen/cli/table-command-generator.ts Omit the create subcommand from generated CLI commands when absent.
graphql/codegen/src/core/codegen/cli/docs-generator.ts, graphql/codegen/src/core/codegen/hooks-docs-generator.ts, graphql/codegen/src/core/codegen/orm/docs-generator.ts Conditionally omit create usage/examples from README, skill, and hooks docs generation.
graphql/codegen/src/__tests__/codegen/model-generator.test.ts, graphql/codegen/src/__tests__/introspect/infer-tables.test.ts Update tests to cover the optional-create behavior.

Reviewed commit: 62c6315

@pyramation
pyramation merged commit 81df9e5 into main Nov 11, 2026
20 checks passed
@pyramation
pyramation deleted the feat/codegen-optional-create branch November 11, 2026 05:42
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