@constructive-io/graphql-codegen 2.23.3 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +147 -2
  2. package/cli/codegen/babel-ast.d.ts +46 -0
  3. package/cli/codegen/babel-ast.js +145 -0
  4. package/cli/codegen/barrel.d.ts +7 -2
  5. package/cli/codegen/barrel.js +159 -97
  6. package/cli/codegen/client.js +61 -0
  7. package/cli/codegen/custom-mutations.d.ts +2 -12
  8. package/cli/codegen/custom-mutations.js +116 -124
  9. package/cli/codegen/custom-queries.d.ts +2 -10
  10. package/cli/codegen/custom-queries.js +246 -335
  11. package/cli/codegen/index.d.ts +3 -0
  12. package/cli/codegen/index.js +72 -3
  13. package/cli/codegen/invalidation.d.ts +20 -0
  14. package/cli/codegen/invalidation.js +327 -0
  15. package/cli/codegen/mutation-keys.d.ts +24 -0
  16. package/cli/codegen/mutation-keys.js +247 -0
  17. package/cli/codegen/mutations.d.ts +3 -19
  18. package/cli/codegen/mutations.js +372 -383
  19. package/cli/codegen/orm/barrel.d.ts +1 -1
  20. package/cli/codegen/orm/barrel.js +42 -10
  21. package/cli/codegen/orm/client-generator.d.ts +1 -19
  22. package/cli/codegen/orm/client-generator.js +108 -77
  23. package/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
  24. package/cli/codegen/orm/custom-ops-generator.js +192 -235
  25. package/cli/codegen/orm/input-types-generator.d.ts +13 -1
  26. package/cli/codegen/orm/input-types-generator.js +403 -147
  27. package/cli/codegen/orm/model-generator.d.ts +1 -19
  28. package/cli/codegen/orm/model-generator.js +229 -234
  29. package/cli/codegen/queries.d.ts +3 -11
  30. package/cli/codegen/queries.js +582 -389
  31. package/cli/codegen/query-keys.d.ts +15 -0
  32. package/cli/codegen/query-keys.js +477 -0
  33. package/cli/codegen/scalars.js +1 -0
  34. package/cli/codegen/schema-types-generator.d.ts +15 -10
  35. package/cli/codegen/schema-types-generator.js +87 -175
  36. package/cli/codegen/type-resolver.d.ts +1 -30
  37. package/cli/codegen/type-resolver.js +0 -53
  38. package/cli/codegen/types.d.ts +1 -1
  39. package/cli/codegen/types.js +76 -21
  40. package/esm/cli/codegen/babel-ast.d.ts +46 -0
  41. package/esm/cli/codegen/babel-ast.js +97 -0
  42. package/esm/cli/codegen/barrel.d.ts +7 -2
  43. package/esm/cli/codegen/barrel.js +126 -97
  44. package/esm/cli/codegen/client.js +61 -0
  45. package/esm/cli/codegen/custom-mutations.d.ts +2 -12
  46. package/esm/cli/codegen/custom-mutations.js +83 -124
  47. package/esm/cli/codegen/custom-queries.d.ts +2 -10
  48. package/esm/cli/codegen/custom-queries.js +214 -336
  49. package/esm/cli/codegen/index.d.ts +3 -0
  50. package/esm/cli/codegen/index.js +68 -2
  51. package/esm/cli/codegen/invalidation.d.ts +20 -0
  52. package/esm/cli/codegen/invalidation.js +291 -0
  53. package/esm/cli/codegen/mutation-keys.d.ts +24 -0
  54. package/esm/cli/codegen/mutation-keys.js +211 -0
  55. package/esm/cli/codegen/mutations.d.ts +3 -19
  56. package/esm/cli/codegen/mutations.js +340 -384
  57. package/esm/cli/codegen/orm/barrel.d.ts +1 -1
  58. package/esm/cli/codegen/orm/barrel.js +10 -11
  59. package/esm/cli/codegen/orm/client-generator.d.ts +1 -19
  60. package/esm/cli/codegen/orm/client-generator.js +76 -78
  61. package/esm/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
  62. package/esm/cli/codegen/orm/custom-ops-generator.js +160 -236
  63. package/esm/cli/codegen/orm/input-types-generator.d.ts +13 -1
  64. package/esm/cli/codegen/orm/input-types-generator.js +371 -148
  65. package/esm/cli/codegen/orm/model-generator.d.ts +1 -19
  66. package/esm/cli/codegen/orm/model-generator.js +197 -235
  67. package/esm/cli/codegen/queries.d.ts +3 -11
  68. package/esm/cli/codegen/queries.js +550 -390
  69. package/esm/cli/codegen/query-keys.d.ts +15 -0
  70. package/esm/cli/codegen/query-keys.js +441 -0
  71. package/esm/cli/codegen/scalars.js +1 -0
  72. package/esm/cli/codegen/schema-types-generator.d.ts +15 -10
  73. package/esm/cli/codegen/schema-types-generator.js +54 -175
  74. package/esm/cli/codegen/type-resolver.d.ts +1 -30
  75. package/esm/cli/codegen/type-resolver.js +0 -49
  76. package/esm/cli/codegen/types.d.ts +1 -1
  77. package/esm/cli/codegen/types.js +44 -22
  78. package/esm/types/config.d.ts +75 -0
  79. package/esm/types/config.js +18 -0
  80. package/package.json +6 -4
  81. package/types/config.d.ts +75 -0
  82. package/types/config.js +19 -1
  83. package/cli/codegen/ts-ast.d.ts +0 -124
  84. package/cli/codegen/ts-ast.js +0 -280
  85. package/esm/cli/codegen/ts-ast.d.ts +0 -124
  86. package/esm/cli/codegen/ts-ast.js +0 -260
@@ -1,18 +1,46 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.generateSchemaTypesFile = generateSchemaTypesFile;
4
- const ts_ast_1 = require("./ts-ast");
37
+ const t = __importStar(require("@babel/types"));
38
+ const babel_ast_1 = require("./babel-ast");
5
39
  const type_resolver_1 = require("./type-resolver");
6
40
  const scalars_1 = require("./scalars");
7
- // ============================================================================
8
- // Constants
9
- // ============================================================================
10
- /**
11
- * Types that should not be generated (scalars, built-ins, types generated elsewhere)
12
- */
41
+ const utils_1 = require("./utils");
13
42
  const SKIP_TYPES = new Set([
14
43
  ...scalars_1.SCALAR_NAMES,
15
- // GraphQL built-ins
16
44
  'Query',
17
45
  'Mutation',
18
46
  'Subscription',
@@ -22,27 +50,9 @@ const SKIP_TYPES = new Set([
22
50
  '__InputValue',
23
51
  '__EnumValue',
24
52
  '__Directive',
25
- // Note: PageInfo and Cursor are NOT skipped - they're needed by Connection types
26
- // Base filter types (generated in types.ts via filters.ts)
27
53
  ...scalars_1.BASE_FILTER_TYPE_NAMES,
28
54
  ]);
29
- /**
30
- * Type name patterns to skip (regex patterns)
31
- *
32
- * Note: We intentionally DO NOT skip Connection, Edge, Filter, Patch, Condition,
33
- * or OrderBy types because they may be referenced by custom operations.
34
- * Previously Condition and OrderBy were skipped but they ARE needed for
35
- * custom queries like `schemata`, `apiSchemata`, etc.
36
- */
37
- const SKIP_TYPE_PATTERNS = [
38
- // Currently no patterns are skipped - all types may be needed by custom operations
39
- ];
40
- // ============================================================================
41
- // Type Conversion Utilities
42
- // ============================================================================
43
- /**
44
- * Convert a CleanTypeRef to TypeScript type string
45
- */
55
+ const SKIP_TYPE_PATTERNS = [];
46
56
  function typeRefToTs(typeRef) {
47
57
  if (typeRef.kind === 'NON_NULL') {
48
58
  if (typeRef.ofType) {
@@ -56,48 +66,26 @@ function typeRefToTs(typeRef) {
56
66
  }
57
67
  return 'unknown[]';
58
68
  }
59
- // Scalar or named type
60
69
  const name = typeRef.name ?? 'unknown';
61
70
  return (0, scalars_1.scalarToTsType)(name, { unknownScalar: 'name' });
62
71
  }
63
- /**
64
- * Check if a type is required (NON_NULL)
65
- */
66
72
  function isRequired(typeRef) {
67
73
  return typeRef.kind === 'NON_NULL';
68
74
  }
69
- /**
70
- * Check if a type should be skipped
71
- */
72
75
  function shouldSkipType(typeName, tableTypeNames) {
73
- // Skip scalars and built-ins
74
76
  if (SKIP_TYPES.has(typeName))
75
77
  return true;
76
- // Skip table entity types (already in types.ts)
77
78
  if (tableTypeNames.has(typeName))
78
79
  return true;
79
- // Skip types matching patterns
80
80
  for (const pattern of SKIP_TYPE_PATTERNS) {
81
81
  if (pattern.test(typeName))
82
82
  return true;
83
83
  }
84
- // Skip table-specific types that would conflict with inline types in table-based hooks.
85
- // Note: Patch and CreateInput are now NOT exported from hooks (isExported: false),
86
- // so we only skip Filter types here.
87
- // The Filter and OrderBy types are generated inline (non-exported) by table query hooks,
88
- // but schema-types should still generate them for custom operations that need them.
89
- // Actually, we don't skip any table-based types now since hooks don't export them.
90
84
  return false;
91
85
  }
92
- // ============================================================================
93
- // ENUM Types Generator
94
- // ============================================================================
95
- /**
96
- * Add ENUM types to source file
97
- */
98
- function addEnumTypes(sourceFile, typeRegistry, tableTypeNames) {
86
+ function generateEnumTypes(typeRegistry, tableTypeNames) {
87
+ const statements = [];
99
88
  const generatedTypes = new Set();
100
- (0, ts_ast_1.addSectionComment)(sourceFile, 'Enum Types');
101
89
  for (const [typeName, typeInfo] of typeRegistry) {
102
90
  if (typeInfo.kind !== 'ENUM')
103
91
  continue;
@@ -105,23 +93,17 @@ function addEnumTypes(sourceFile, typeRegistry, tableTypeNames) {
105
93
  continue;
106
94
  if (!typeInfo.enumValues || typeInfo.enumValues.length === 0)
107
95
  continue;
108
- const values = typeInfo.enumValues.map((v) => `'${v}'`).join(' | ');
109
- sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(typeName, values));
96
+ const unionType = t.tsUnionType(typeInfo.enumValues.map((v) => t.tsLiteralType(t.stringLiteral(v))));
97
+ const typeAlias = t.tsTypeAliasDeclaration(t.identifier(typeName), null, unionType);
98
+ statements.push(t.exportNamedDeclaration(typeAlias));
110
99
  generatedTypes.add(typeName);
111
100
  }
112
- return generatedTypes;
101
+ return { statements, generatedTypes };
113
102
  }
114
- // ============================================================================
115
- // INPUT_OBJECT Types Generator
116
- // ============================================================================
117
- /**
118
- * Add INPUT_OBJECT types to source file
119
- * Uses iteration to handle nested input types
120
- */
121
- function addInputObjectTypes(sourceFile, typeRegistry, tableTypeNames, alreadyGenerated) {
103
+ function generateInputObjectTypes(typeRegistry, tableTypeNames, alreadyGenerated) {
104
+ const statements = [];
122
105
  const generatedTypes = new Set(alreadyGenerated);
123
106
  const typesToGenerate = new Set();
124
- // Collect all INPUT_OBJECT types
125
107
  for (const [typeName, typeInfo] of typeRegistry) {
126
108
  if (typeInfo.kind !== 'INPUT_OBJECT')
127
109
  continue;
@@ -131,10 +113,6 @@ function addInputObjectTypes(sourceFile, typeRegistry, tableTypeNames, alreadyGe
131
113
  continue;
132
114
  typesToGenerate.add(typeName);
133
115
  }
134
- if (typesToGenerate.size === 0)
135
- return generatedTypes;
136
- (0, ts_ast_1.addSectionComment)(sourceFile, 'Input Object Types');
137
- // Process all types - no artificial limit
138
116
  while (typesToGenerate.size > 0) {
139
117
  const typeNameResult = typesToGenerate.values().next();
140
118
  if (typeNameResult.done)
@@ -147,18 +125,14 @@ function addInputObjectTypes(sourceFile, typeRegistry, tableTypeNames, alreadyGe
147
125
  if (!typeInfo || typeInfo.kind !== 'INPUT_OBJECT')
148
126
  continue;
149
127
  generatedTypes.add(typeName);
128
+ const properties = [];
150
129
  if (typeInfo.inputFields && typeInfo.inputFields.length > 0) {
151
- const properties = [];
152
130
  for (const field of typeInfo.inputFields) {
153
131
  const optional = !isRequired(field.type);
154
132
  const tsType = typeRefToTs(field.type);
155
- properties.push({
156
- name: field.name,
157
- type: tsType,
158
- optional,
159
- docs: field.description ? [field.description] : undefined,
160
- });
161
- // Follow nested Input types
133
+ const prop = t.tsPropertySignature(t.identifier(field.name), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(tsType))));
134
+ prop.optional = optional;
135
+ properties.push(prop);
162
136
  const baseType = (0, type_resolver_1.getTypeBaseName)(field.type);
163
137
  if (baseType &&
164
138
  !generatedTypes.has(baseType) &&
@@ -169,25 +143,15 @@ function addInputObjectTypes(sourceFile, typeRegistry, tableTypeNames, alreadyGe
169
143
  }
170
144
  }
171
145
  }
172
- sourceFile.addInterface((0, ts_ast_1.createInterface)(typeName, properties));
173
- }
174
- else {
175
- // Empty input object
176
- sourceFile.addInterface((0, ts_ast_1.createInterface)(typeName, []));
177
146
  }
147
+ const interfaceDecl = t.tsInterfaceDeclaration(t.identifier(typeName), null, null, t.tsInterfaceBody(properties));
148
+ statements.push(t.exportNamedDeclaration(interfaceDecl));
178
149
  }
179
- return generatedTypes;
150
+ return { statements, generatedTypes };
180
151
  }
181
- // ============================================================================
182
- // UNION Types Generator
183
- // ============================================================================
184
- /**
185
- * Add UNION types to source file
186
- */
187
- function addUnionTypes(sourceFile, typeRegistry, tableTypeNames, alreadyGenerated) {
152
+ function generateUnionTypes(typeRegistry, tableTypeNames, alreadyGenerated) {
153
+ const statements = [];
188
154
  const generatedTypes = new Set(alreadyGenerated);
189
- const unionTypesToGenerate = new Set();
190
- // Collect all UNION types
191
155
  for (const [typeName, typeInfo] of typeRegistry) {
192
156
  if (typeInfo.kind !== 'UNION')
193
157
  continue;
@@ -195,32 +159,17 @@ function addUnionTypes(sourceFile, typeRegistry, tableTypeNames, alreadyGenerate
195
159
  continue;
196
160
  if (generatedTypes.has(typeName))
197
161
  continue;
198
- unionTypesToGenerate.add(typeName);
199
- }
200
- if (unionTypesToGenerate.size === 0)
201
- return generatedTypes;
202
- (0, ts_ast_1.addSectionComment)(sourceFile, 'Union Types');
203
- for (const typeName of unionTypesToGenerate) {
204
- const typeInfo = typeRegistry.get(typeName);
205
- if (!typeInfo || typeInfo.kind !== 'UNION')
206
- continue;
207
162
  if (!typeInfo.possibleTypes || typeInfo.possibleTypes.length === 0)
208
163
  continue;
209
- // Generate union type as TypeScript union
210
- const unionMembers = typeInfo.possibleTypes.join(' | ');
211
- sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(typeName, unionMembers));
164
+ const unionType = t.tsUnionType(typeInfo.possibleTypes.map((pt) => t.tsTypeReference(t.identifier(pt))));
165
+ const typeAlias = t.tsTypeAliasDeclaration(t.identifier(typeName), null, unionType);
166
+ statements.push(t.exportNamedDeclaration(typeAlias));
212
167
  generatedTypes.add(typeName);
213
168
  }
214
- return generatedTypes;
169
+ return { statements, generatedTypes };
215
170
  }
216
- /**
217
- * Collect return types from Query and Mutation root types
218
- * This dynamically discovers what OBJECT types need to be generated
219
- * based on actual schema structure, not pattern matching
220
- */
221
171
  function collectReturnTypesFromRootTypes(typeRegistry, tableTypeNames) {
222
172
  const returnTypes = new Set();
223
- // Get Query and Mutation root types
224
173
  const queryType = typeRegistry.get('Query');
225
174
  const mutationType = typeRegistry.get('Mutation');
226
175
  const processFields = (fields) => {
@@ -242,30 +191,16 @@ function collectReturnTypesFromRootTypes(typeRegistry, tableTypeNames) {
242
191
  processFields(mutationType.fields);
243
192
  return returnTypes;
244
193
  }
245
- /**
246
- * Add Payload OBJECT types to source file
247
- * These are return types from mutations (e.g., LoginPayload, BootstrapUserPayload)
248
- *
249
- * Also tracks which table entity types are referenced so they can be imported.
250
- *
251
- * Uses dynamic type discovery from Query/Mutation return types instead of pattern matching.
252
- */
253
- function addPayloadObjectTypes(sourceFile, typeRegistry, tableTypeNames, alreadyGenerated) {
194
+ function generatePayloadObjectTypes(typeRegistry, tableTypeNames, alreadyGenerated) {
195
+ const statements = [];
254
196
  const generatedTypes = new Set(alreadyGenerated);
255
197
  const referencedTableTypes = new Set();
256
- // Dynamically collect return types from Query and Mutation
257
198
  const typesToGenerate = collectReturnTypesFromRootTypes(typeRegistry, tableTypeNames);
258
- // Filter out already generated types
259
199
  for (const typeName of Array.from(typesToGenerate)) {
260
200
  if (generatedTypes.has(typeName)) {
261
201
  typesToGenerate.delete(typeName);
262
202
  }
263
203
  }
264
- if (typesToGenerate.size === 0) {
265
- return { generatedTypes, referencedTableTypes };
266
- }
267
- (0, ts_ast_1.addSectionComment)(sourceFile, 'Payload/Return Object Types');
268
- // Process all types - no artificial limit
269
204
  while (typesToGenerate.size > 0) {
270
205
  const typeNameResult = typesToGenerate.values().next();
271
206
  if (typeNameResult.done)
@@ -278,26 +213,21 @@ function addPayloadObjectTypes(sourceFile, typeRegistry, tableTypeNames, already
278
213
  if (!typeInfo || typeInfo.kind !== 'OBJECT')
279
214
  continue;
280
215
  generatedTypes.add(typeName);
216
+ const properties = [];
281
217
  if (typeInfo.fields && typeInfo.fields.length > 0) {
282
- const properties = [];
283
218
  for (const field of typeInfo.fields) {
284
219
  const baseType = (0, type_resolver_1.getTypeBaseName)(field.type);
285
- // Skip Query and Mutation fields
286
220
  if (baseType === 'Query' || baseType === 'Mutation')
287
221
  continue;
288
222
  const tsType = typeRefToTs(field.type);
289
223
  const isNullable = !isRequired(field.type);
290
- properties.push({
291
- name: field.name,
292
- type: isNullable ? `${tsType} | null` : tsType,
293
- optional: isNullable,
294
- docs: field.description ? [field.description] : undefined,
295
- });
296
- // Track table entity types that are referenced
224
+ const finalType = isNullable ? `${tsType} | null` : tsType;
225
+ const prop = t.tsPropertySignature(t.identifier(field.name), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(finalType))));
226
+ prop.optional = isNullable;
227
+ properties.push(prop);
297
228
  if (baseType && tableTypeNames.has(baseType)) {
298
229
  referencedTableTypes.add(baseType);
299
230
  }
300
- // Follow nested OBJECT types that aren't table types
301
231
  if (baseType &&
302
232
  !generatedTypes.has(baseType) &&
303
233
  !shouldSkipType(baseType, tableTypeNames)) {
@@ -307,59 +237,41 @@ function addPayloadObjectTypes(sourceFile, typeRegistry, tableTypeNames, already
307
237
  }
308
238
  }
309
239
  }
310
- sourceFile.addInterface((0, ts_ast_1.createInterface)(typeName, properties));
311
- }
312
- else {
313
- // Empty payload object
314
- sourceFile.addInterface((0, ts_ast_1.createInterface)(typeName, []));
315
240
  }
241
+ const interfaceDecl = t.tsInterfaceDeclaration(t.identifier(typeName), null, null, t.tsInterfaceBody(properties));
242
+ statements.push(t.exportNamedDeclaration(interfaceDecl));
316
243
  }
317
- return { generatedTypes, referencedTableTypes };
244
+ return { statements, generatedTypes, referencedTableTypes };
318
245
  }
319
- // ============================================================================
320
- // Main Generator
321
- // ============================================================================
322
- /**
323
- * Generate comprehensive schema-types.ts file using ts-morph AST
324
- *
325
- * This generates all Input/Payload/Enum types from the TypeRegistry
326
- * that are needed by custom mutation/query hooks.
327
- */
328
246
  function generateSchemaTypesFile(options) {
329
247
  const { typeRegistry, tableTypeNames } = options;
330
- const project = (0, ts_ast_1.createProject)();
331
- const sourceFile = (0, ts_ast_1.createSourceFile)(project, 'schema-types.ts');
332
- // Add file header
333
- sourceFile.insertText(0, (0, ts_ast_1.createFileHeader)('GraphQL schema types for custom operations') + '\n');
334
- // Track all generated types
248
+ const allStatements = [];
335
249
  let generatedTypes = new Set();
336
- // 1. Generate ENUM types
337
- const enumTypes = addEnumTypes(sourceFile, typeRegistry, tableTypeNames);
338
- generatedTypes = new Set([...generatedTypes, ...enumTypes]);
339
- // 2. Generate UNION types
340
- const unionTypes = addUnionTypes(sourceFile, typeRegistry, tableTypeNames, generatedTypes);
341
- generatedTypes = new Set([...generatedTypes, ...unionTypes]);
342
- // 3. Generate INPUT_OBJECT types
343
- const inputTypes = addInputObjectTypes(sourceFile, typeRegistry, tableTypeNames, generatedTypes);
344
- generatedTypes = new Set([...generatedTypes, ...inputTypes]);
345
- // 4. Generate Payload OBJECT types
346
- const payloadResult = addPayloadObjectTypes(sourceFile, typeRegistry, tableTypeNames, generatedTypes);
347
- // 5. Add imports from types.ts (table entity types + base filter types)
250
+ const enumResult = generateEnumTypes(typeRegistry, tableTypeNames);
251
+ generatedTypes = new Set([...generatedTypes, ...enumResult.generatedTypes]);
252
+ const unionResult = generateUnionTypes(typeRegistry, tableTypeNames, generatedTypes);
253
+ generatedTypes = new Set([...generatedTypes, ...unionResult.generatedTypes]);
254
+ const inputResult = generateInputObjectTypes(typeRegistry, tableTypeNames, generatedTypes);
255
+ generatedTypes = new Set([...generatedTypes, ...inputResult.generatedTypes]);
256
+ const payloadResult = generatePayloadObjectTypes(typeRegistry, tableTypeNames, generatedTypes);
348
257
  const referencedTableTypes = Array.from(payloadResult.referencedTableTypes).sort();
349
- // Always import base filter types since generated Filter interfaces reference them
350
258
  const baseFilterImports = Array.from(scalars_1.BASE_FILTER_TYPE_NAMES).sort();
351
259
  const allTypesImports = [...referencedTableTypes, ...baseFilterImports];
352
260
  if (allTypesImports.length > 0) {
353
- // Insert import after the file header comment
354
- const importStatement = `import type { ${allTypesImports.join(', ')} } from './types';\n\n`;
355
- // Find position after header (after first */ + newlines)
356
- const headerEndIndex = sourceFile.getFullText().indexOf('*/') + 3;
357
- sourceFile.insertText(headerEndIndex, '\n' + importStatement);
261
+ const typesImport = t.importDeclaration(allTypesImports.map((ti) => t.importSpecifier(t.identifier(ti), t.identifier(ti))), t.stringLiteral('./types'));
262
+ typesImport.importKind = 'type';
263
+ allStatements.push(typesImport);
358
264
  }
265
+ allStatements.push(...enumResult.statements);
266
+ allStatements.push(...unionResult.statements);
267
+ allStatements.push(...inputResult.statements);
268
+ allStatements.push(...payloadResult.statements);
269
+ const code = (0, babel_ast_1.generateCode)(allStatements);
270
+ const content = (0, utils_1.getGeneratedFileHeader)('GraphQL schema types for custom operations') + '\n\n' + code;
359
271
  return {
360
272
  fileName: 'schema-types.ts',
361
- content: (0, ts_ast_1.getMinimalFormattedOutput)(sourceFile),
362
- generatedEnums: Array.from(enumTypes).sort(),
273
+ content,
274
+ generatedEnums: Array.from(enumResult.generatedTypes).sort(),
363
275
  referencedTableTypes,
364
276
  };
365
277
  }
@@ -4,8 +4,7 @@
4
4
  * Utilities for converting CleanTypeRef and other GraphQL types
5
5
  * into TypeScript type strings and interface definitions.
6
6
  */
7
- import type { CleanTypeRef, CleanArgument, CleanObjectField } from '../../types/schema';
8
- import type { InterfaceProperty } from './ts-ast';
7
+ import type { CleanTypeRef, CleanObjectField } from '../../types/schema';
9
8
  /**
10
9
  * Interface for tracking referenced types during code generation
11
10
  */
@@ -70,34 +69,6 @@ export declare function getTypeBaseName(typeRef: CleanTypeRef): string | null;
70
69
  * Get the base type kind (unwrapping LIST and NON_NULL)
71
70
  */
72
71
  export declare function getBaseTypeKind(typeRef: CleanTypeRef): CleanTypeRef['kind'];
73
- /**
74
- * Convert CleanArgument to InterfaceProperty for ts-morph
75
- *
76
- * @param arg - The GraphQL argument
77
- * @param tracker - Optional TypeTracker to collect referenced types
78
- */
79
- export declare function argumentToInterfaceProperty(arg: CleanArgument, tracker?: TypeTracker): InterfaceProperty;
80
- /**
81
- * Convert CleanObjectField to InterfaceProperty for ts-morph
82
- *
83
- * @param field - The GraphQL object field
84
- * @param tracker - Optional TypeTracker to collect referenced types
85
- */
86
- export declare function fieldToInterfaceProperty(field: CleanObjectField, tracker?: TypeTracker): InterfaceProperty;
87
- /**
88
- * Convert an array of CleanArguments to InterfaceProperty array
89
- *
90
- * @param args - The GraphQL arguments
91
- * @param tracker - Optional TypeTracker to collect referenced types
92
- */
93
- export declare function argumentsToInterfaceProperties(args: CleanArgument[], tracker?: TypeTracker): InterfaceProperty[];
94
- /**
95
- * Convert an array of CleanObjectFields to InterfaceProperty array
96
- *
97
- * @param fields - The GraphQL object fields
98
- * @param tracker - Optional TypeTracker to collect referenced types
99
- */
100
- export declare function fieldsToInterfaceProperties(fields: CleanObjectField[], tracker?: TypeTracker): InterfaceProperty[];
101
72
  /**
102
73
  * Check if a field should be skipped in selections
103
74
  */
@@ -8,10 +8,6 @@ exports.isTypeRequired = isTypeRequired;
8
8
  exports.isTypeList = isTypeList;
9
9
  exports.getTypeBaseName = getTypeBaseName;
10
10
  exports.getBaseTypeKind = getBaseTypeKind;
11
- exports.argumentToInterfaceProperty = argumentToInterfaceProperty;
12
- exports.fieldToInterfaceProperty = fieldToInterfaceProperty;
13
- exports.argumentsToInterfaceProperties = argumentsToInterfaceProperties;
14
- exports.fieldsToInterfaceProperties = fieldsToInterfaceProperties;
15
11
  exports.shouldSkipField = shouldSkipField;
16
12
  exports.getSelectableFields = getSelectableFields;
17
13
  exports.operationNameToPascal = operationNameToPascal;
@@ -184,55 +180,6 @@ function getBaseTypeKind(typeRef) {
184
180
  return typeRef.kind;
185
181
  }
186
182
  // ============================================================================
187
- // Interface Property Generation
188
- // ============================================================================
189
- /**
190
- * Convert CleanArgument to InterfaceProperty for ts-morph
191
- *
192
- * @param arg - The GraphQL argument
193
- * @param tracker - Optional TypeTracker to collect referenced types
194
- */
195
- function argumentToInterfaceProperty(arg, tracker) {
196
- return {
197
- name: arg.name,
198
- type: typeRefToTsType(arg.type, tracker),
199
- optional: !isTypeRequired(arg.type),
200
- docs: arg.description ? [arg.description] : undefined,
201
- };
202
- }
203
- /**
204
- * Convert CleanObjectField to InterfaceProperty for ts-morph
205
- *
206
- * @param field - The GraphQL object field
207
- * @param tracker - Optional TypeTracker to collect referenced types
208
- */
209
- function fieldToInterfaceProperty(field, tracker) {
210
- return {
211
- name: field.name,
212
- type: typeRefToNullableTsType(field.type, tracker),
213
- optional: false, // Fields are always present, just potentially null
214
- docs: field.description ? [field.description] : undefined,
215
- };
216
- }
217
- /**
218
- * Convert an array of CleanArguments to InterfaceProperty array
219
- *
220
- * @param args - The GraphQL arguments
221
- * @param tracker - Optional TypeTracker to collect referenced types
222
- */
223
- function argumentsToInterfaceProperties(args, tracker) {
224
- return args.map((arg) => argumentToInterfaceProperty(arg, tracker));
225
- }
226
- /**
227
- * Convert an array of CleanObjectFields to InterfaceProperty array
228
- *
229
- * @param fields - The GraphQL object fields
230
- * @param tracker - Optional TypeTracker to collect referenced types
231
- */
232
- function fieldsToInterfaceProperties(fields, tracker) {
233
- return fields.map((field) => fieldToInterfaceProperty(field, tracker));
234
- }
235
- // ============================================================================
236
183
  // Type Filtering
237
184
  // ============================================================================
238
185
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Types generator - generates types.ts with entity interfaces using AST
2
+ * Types generator - generates types.ts with entity interfaces using Babel AST
3
3
  */
4
4
  import type { CleanTable } from '../../types/schema';
5
5
  /**
@@ -1,7 +1,41 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.generateTypesFile = generateTypesFile;
4
- const ts_ast_1 = require("./ts-ast");
37
+ const t = __importStar(require("@babel/types"));
38
+ const babel_ast_1 = require("./babel-ast");
5
39
  const utils_1 = require("./utils");
6
40
  /** All filter type configurations - scalar and list filters */
7
41
  const FILTER_CONFIGS = [
@@ -67,16 +101,42 @@ function buildFilterProperties(tsType, operators) {
67
101
  }
68
102
  return props;
69
103
  }
104
+ function parseTypeAnnotation(typeStr) {
105
+ if (typeStr === 'string')
106
+ return t.tsStringKeyword();
107
+ if (typeStr === 'number')
108
+ return t.tsNumberKeyword();
109
+ if (typeStr === 'boolean')
110
+ return t.tsBooleanKeyword();
111
+ if (typeStr === 'unknown')
112
+ return t.tsUnknownKeyword();
113
+ if (typeStr.includes(' | ')) {
114
+ const parts = typeStr.split(' | ').map((p) => parseTypeAnnotation(p.trim()));
115
+ return t.tsUnionType(parts);
116
+ }
117
+ if (typeStr.endsWith('[]')) {
118
+ return t.tsArrayType(parseTypeAnnotation(typeStr.slice(0, -2)));
119
+ }
120
+ if (typeStr === 'null')
121
+ return t.tsNullKeyword();
122
+ return t.tsTypeReference(t.identifier(typeStr));
123
+ }
124
+ function createInterfaceDeclaration(name, properties) {
125
+ const props = properties.map((prop) => {
126
+ const propSig = t.tsPropertySignature(t.identifier(prop.name), t.tsTypeAnnotation(parseTypeAnnotation(prop.type)));
127
+ propSig.optional = prop.optional ?? false;
128
+ return propSig;
129
+ });
130
+ const interfaceDecl = t.tsInterfaceDeclaration(t.identifier(name), null, null, t.tsInterfaceBody(props));
131
+ return t.exportNamedDeclaration(interfaceDecl);
132
+ }
70
133
  /**
71
134
  * Generate types.ts content with all entity interfaces and base filter types
72
135
  */
73
136
  function generateTypesFile(tables, options = {}) {
74
137
  const { enumsFromSchemaTypes = [] } = options;
75
138
  const enumSet = new Set(enumsFromSchemaTypes);
76
- const project = (0, ts_ast_1.createProject)();
77
- const sourceFile = (0, ts_ast_1.createSourceFile)(project, 'types.ts');
78
- // Add file header
79
- sourceFile.insertText(0, (0, ts_ast_1.createFileHeader)('Entity types and filter types') + '\n\n');
139
+ const statements = [];
80
140
  // Collect which enums are actually used by entity fields
81
141
  const usedEnums = new Set();
82
142
  for (const table of tables) {
@@ -91,16 +151,13 @@ function generateTypesFile(tables, options = {}) {
91
151
  }
92
152
  // Add import for enum types from schema-types if any are used
93
153
  if (usedEnums.size > 0) {
94
- sourceFile.addImportDeclaration((0, ts_ast_1.createImport)({
95
- moduleSpecifier: './schema-types',
96
- typeOnlyNamedImports: Array.from(usedEnums).sort(),
97
- }));
98
- sourceFile.addStatements('');
154
+ const specifiers = Array.from(usedEnums)
155
+ .sort()
156
+ .map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
157
+ const importDecl = t.importDeclaration(specifiers, t.stringLiteral('./schema-types'));
158
+ importDecl.importKind = 'type';
159
+ statements.push(importDecl);
99
160
  }
100
- // Add section comment for entity types
101
- sourceFile.addStatements('// ============================================================================');
102
- sourceFile.addStatements('// Entity types');
103
- sourceFile.addStatements('// ============================================================================\n');
104
161
  // Generate entity interfaces
105
162
  for (const table of tables) {
106
163
  const scalarFields = (0, utils_1.getScalarFields)(table);
@@ -108,15 +165,13 @@ function generateTypesFile(tables, options = {}) {
108
165
  name: field.name,
109
166
  type: `${(0, utils_1.fieldTypeToTs)(field.type)} | null`,
110
167
  }));
111
- sourceFile.addInterface((0, ts_ast_1.createInterface)(table.name, properties));
168
+ statements.push(createInterfaceDeclaration(table.name, properties));
112
169
  }
113
- // Add section comment for filter types
114
- sourceFile.addStatements('\n// ============================================================================');
115
- sourceFile.addStatements('// Filter types (shared PostGraphile filter interfaces)');
116
- sourceFile.addStatements('// ============================================================================\n');
117
170
  // Generate all filter types
118
171
  for (const { name, tsType, operators } of FILTER_CONFIGS) {
119
- sourceFile.addInterface((0, ts_ast_1.createInterface)(name, buildFilterProperties(tsType, operators)));
172
+ statements.push(createInterfaceDeclaration(name, buildFilterProperties(tsType, operators)));
120
173
  }
121
- return (0, ts_ast_1.getFormattedOutput)(sourceFile);
174
+ const header = (0, utils_1.getGeneratedFileHeader)('Entity types and filter types');
175
+ const code = (0, babel_ast_1.generateCode)(statements);
176
+ return header + '\n' + code;
122
177
  }