fix(codegen): eliminate all CLI TypeScript compilation errors#782
fix(codegen): eliminate all CLI TypeScript compilation errors#782pyramation merged 3 commits intomainfrom
Conversation
Fix all CLI codegen template type errors (3,143 → 0) without using
`as any` casts or `// @ts-nocheck` suppression.
Changes by category:
- fieldSchema: add FieldSchema type annotation (fixes ~1,028 TS2345)
- executor headers: add Record<string, string> type (fixes ~30 TS2339)
- prompt results: cast to Record<string, string> (fixes ~100 TS2345/TS2322)
- ORM data objects: use `as never` universal cast (fixes ~2,000 TS2322)
- commandMap: add Record<string, CommandHandler> type (fixes ~4 TS7053)
- array fields: uniform handling via `as never` on data objects
- read-only views: skip get/update/delete for null query operations
- computed fields: filter via getWritableFieldNames
- custom command args: cast through `as never` for Variables types
- infra prompt: double-cast through unknown for Record<string, string>
- custom command select: cast { select } through never for StrictSelect
All 54 codegen tests pass. 9 snapshots updated.
Regenerated CLI code builds with 0 TypeScript errors.
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
- Import and cast { select } to specific Select types (e.g. CheckPasswordPayloadSelect)
instead of Record<string, unknown> to satisfy StrictSelect constraints
- Match ORM's EXCLUDED_MUTATION_FIELDS list to exclude 'id' from create data
for tables with auto-generated PKs (RoleType, MembershipType, Object, etc.)
- Allow non-'id' PKs like NodeTypeRegistry.name in create data
- Use CleanField column-level info instead of unreliable introspection defaults
- Update test snapshots (54 tests pass)
- Regenerate CLI code: 0 TypeScript errors, 0 as-never/as-any/ts-ignore casts
…r pure record types - handleGet was incorrectly removed for 150/152 tables because table.query.one is null for most tables (no dedicated GraphQL findOne query), but the ORM still generates findOne using the PK. - Now: hasGet = true unless one, update, AND delete are all null (pure read-only record types like GetAllRecord, OrgGetManagersRecord, OrgGetSubordinatesRecord). - 0 TypeScript errors, 0 forbidden casts, 54 codegen tests pass.
| // Determine which operations the ORM model supports for this table. | ||
| // Most tables have `one: null` simply because there's no dedicated GraphQL | ||
| // findOne query, but the ORM still generates `findOne` using the PK. | ||
| // The only tables WITHOUT `findOne` are pure record types from SQL functions |
There was a problem hiding this comment.
🔴 hasGet check uses !== null without guarding against undefined, incorrectly enabling 'get' when table.query is undefined
At graphql/codegen/src/core/codegen/cli/table-command-generator.ts:799, hasGet is computed as table.query?.one !== null. When table.query is undefined (which is valid per CleanTable interface at graphql/codegen/src/types/schema.ts:18), the optional chaining evaluates to undefined, and undefined !== null is true. This means hasGet will be true even when the table has no query information at all, causing the generator to emit a get subcommand and handleGet function for tables that may not support findOne. In contrast, hasUpdate and hasDelete on lines 800-801 correctly check !== undefined && !== null, so they don't have this problem.
| // The only tables WITHOUT `findOne` are pure record types from SQL functions | |
| const hasGet = table.query?.one !== undefined && table.query?.one !== null; |
Was this helpful? React with 👍 or 👎 to provide feedback.
fix(codegen): eliminate all CLI TypeScript compilation errors
Summary
Fixes CLI codegen templates in
@constructive-io/graphql-codegento produce type-correct TypeScript output, reducing generated CLI compilation errors from 3,143 → 0 without usingas any,as never,// @ts-nocheck, or// @ts-ignore.Template changes (6 files in
graphql/codegen/src/core/codegen/cli/):utils-generator.tsFieldSchematype for table commands to importtable-command-generator.tsCreateXInput,XPatch), castcleanedDatato concrete types,FieldSchematype annotation,as stringon PK lookups, excludeid/createdAt/updatedAt/nodeIdfrom create data matching ORM'sEXCLUDED_MUTATION_FIELDS, filter computed fields, fixhandleGetdetectionexecutor-generator.tsRecord<string, string>type onheaders = {}command-map-generator.tscreateCommandMapreturn,as stringon prompt resultsinfra-generator.tsas unknown as Record<string, string>,as string/as booleanon field accesscustom-command-generator.tsXxxVariablestypes for ORM args (double-cast viaunknown), importXxxPayloadSelect/XxxSelecttypes for{ select }objects (double-cast viaunknown)Type assertion strategy (no
as neveroras any)stripUndefined(answers, fieldSchema) as CreateXInput['x']— uses the actual ORM create input typestripUndefined(answers, fieldSchema) as XPatch— uses the actual ORM patch typeanswers as unknown as LoginVariables— double-cast throughunknownto the concrete Variables type{ select: selectFields } as unknown as { select: LoginPayloadSelect }— double-cast to satisfy StrictSelect constraintsas string/as booleanon individual fields,as unknown as Record<string, string>on full resultsanswers.id as string— prompt values are always stringsBehavioral changes in generated code
handleGetrestored for all real tables: Previously only 2/152 tables hadhandleGetdue to a bug wheretable.query.one === nullwas treated as "no findOne". In reality,one: nulljust means no dedicated GraphQL findOne query — the ORM still generatesfindOneusing the PK. NowhandleGetis skipped only for pure read-only record types from SQL functions (whereone,update, ANDdeleteare allnull) — affects only 3 tables:GetAllRecord,OrgGetManagersRecord,OrgGetSubordinatesRecord.table.query.delete === nullortable.query.update === nullstill correctly skipdelete/updatehandlers.searchTsvRank,hashUuid) are excluded from create/update data objects.id) correctly excludeidfrom create data, matching the ORM'sEXCLUDED_MUTATION_FIELDSlist; natural-key PKs (e.g.NodeTypeRegistry.name) are still included.// @ts-nocheckdirectives removed from generated files.All 54 codegen tests pass. 46 snapshots pass.
Updates since last revision
Fixed critical
handleGetbug: The initial fix incorrectly removedhandleGetfrom 150/152 tables. The checktable.query?.one !== nullwas wrong because almost all tables haveone: null(no dedicated GraphQL findOne query), but the ORM still generatesfindOneusing the PK. Now correctly generateshandleGetfor all tables except the 3 pure record types from SQL functions where the ORM truly doesn't generatefindOne.Replaced all
as nevercasts with proper ORM input type imports (CreateXInput['x'],XPatch,XxxVariables,XxxPayloadSelect). Noas neveroras anyremains anywhere in generated code.Fixed PK exclusion logic: Now matches the ORM's
EXCLUDED_MUTATION_FIELDS = ['id', 'createdAt', 'updatedAt', 'nodeId']instead of relying onCleanField.hasDefault(which wasnull/undefinedfor some tables). This fixes TS2353 errors forRoleType,MembershipType,Object,SqlMigration,AstMigration.Verified zero forbidden casts: Grepped generated code for
as never|as any|@ts-ignore|@ts-nocheck— all clean.Review & Testing Checklist for Human
Risk level: 🟡 YELLOW — Template changes are localized but blast radius is large (240+ generated files). Type assertions use concrete types but some use double-cast through
unknown.Verify
handleGetheuristic is sound: The detection logichasGet = one !== null || hasUpdate || hasDeleteassumes that tables with update/delete mutations always havefindOne. If a table has update/delete but nofindOnein the ORM, the CLI will generate a brokenhandleGet. Check a few edge cases (e.g., views with triggers that allow updates) to confirm the ORM always generatesfindOnewhen it generatesupdate.Verify ORM_EXCLUDED_FIELDS matches ORM behavior: Confirm that
['id', 'createdAt', 'updatedAt', 'nodeId']matches the ORM'sEXCLUDED_MUTATION_FIELDSininput-types-generator.ts. If these diverge, create operations will fail at runtime.Runtime smoke test (recommended): Generate CLI for a test schema, run a few
get/create/updatecommands with various field types (enums, arrays, booleans, numbers) to verify type assertions hold at runtime. The TypeScript build passes, but runtime validation is the ultimate test.Notes
../../../orm/vs../../orm/) was explained in the user conversation — it's correct for single vs multi-target layouts.