@constructive-io/graphql-codegen 2.23.2 → 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 (90) 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/cli/commands/generate.js +1 -0
  41. package/cli/index.js +1 -0
  42. package/esm/cli/codegen/babel-ast.d.ts +46 -0
  43. package/esm/cli/codegen/babel-ast.js +97 -0
  44. package/esm/cli/codegen/barrel.d.ts +7 -2
  45. package/esm/cli/codegen/barrel.js +126 -97
  46. package/esm/cli/codegen/client.js +61 -0
  47. package/esm/cli/codegen/custom-mutations.d.ts +2 -12
  48. package/esm/cli/codegen/custom-mutations.js +83 -124
  49. package/esm/cli/codegen/custom-queries.d.ts +2 -10
  50. package/esm/cli/codegen/custom-queries.js +214 -336
  51. package/esm/cli/codegen/index.d.ts +3 -0
  52. package/esm/cli/codegen/index.js +68 -2
  53. package/esm/cli/codegen/invalidation.d.ts +20 -0
  54. package/esm/cli/codegen/invalidation.js +291 -0
  55. package/esm/cli/codegen/mutation-keys.d.ts +24 -0
  56. package/esm/cli/codegen/mutation-keys.js +211 -0
  57. package/esm/cli/codegen/mutations.d.ts +3 -19
  58. package/esm/cli/codegen/mutations.js +340 -384
  59. package/esm/cli/codegen/orm/barrel.d.ts +1 -1
  60. package/esm/cli/codegen/orm/barrel.js +10 -11
  61. package/esm/cli/codegen/orm/client-generator.d.ts +1 -19
  62. package/esm/cli/codegen/orm/client-generator.js +76 -78
  63. package/esm/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
  64. package/esm/cli/codegen/orm/custom-ops-generator.js +160 -236
  65. package/esm/cli/codegen/orm/input-types-generator.d.ts +13 -1
  66. package/esm/cli/codegen/orm/input-types-generator.js +371 -148
  67. package/esm/cli/codegen/orm/model-generator.d.ts +1 -19
  68. package/esm/cli/codegen/orm/model-generator.js +197 -235
  69. package/esm/cli/codegen/queries.d.ts +3 -11
  70. package/esm/cli/codegen/queries.js +550 -390
  71. package/esm/cli/codegen/query-keys.d.ts +15 -0
  72. package/esm/cli/codegen/query-keys.js +441 -0
  73. package/esm/cli/codegen/scalars.js +1 -0
  74. package/esm/cli/codegen/schema-types-generator.d.ts +15 -10
  75. package/esm/cli/codegen/schema-types-generator.js +54 -175
  76. package/esm/cli/codegen/type-resolver.d.ts +1 -30
  77. package/esm/cli/codegen/type-resolver.js +0 -49
  78. package/esm/cli/codegen/types.d.ts +1 -1
  79. package/esm/cli/codegen/types.js +44 -22
  80. package/esm/cli/commands/generate.js +1 -0
  81. package/esm/cli/index.js +1 -0
  82. package/esm/types/config.d.ts +75 -0
  83. package/esm/types/config.js +19 -1
  84. package/package.json +6 -4
  85. package/types/config.d.ts +75 -0
  86. package/types/config.js +20 -2
  87. package/cli/codegen/ts-ast.d.ts +0 -124
  88. package/cli/codegen/ts-ast.js +0 -280
  89. package/esm/cli/codegen/ts-ast.d.ts +0 -124
  90. package/esm/cli/codegen/ts-ast.js +0 -260
@@ -1,8 +1,42 @@
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.generateCustomQueryOpsFile = generateCustomQueryOpsFile;
4
37
  exports.generateCustomMutationOpsFile = generateCustomMutationOpsFile;
5
- const ts_ast_1 = require("../ts-ast");
38
+ const t = __importStar(require("@babel/types"));
39
+ const babel_ast_1 = require("../babel-ast");
6
40
  const utils_1 = require("../utils");
7
41
  const type_resolver_1 = require("../type-resolver");
8
42
  const scalars_1 = require("../scalars");
@@ -65,274 +99,197 @@ function getSelectTypeName(returnType) {
65
99
  }
66
100
  return null;
67
101
  }
102
+ function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false) {
103
+ const specifiers = namedImports.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
104
+ const decl = t.importDeclaration(specifiers, t.stringLiteral(moduleSpecifier));
105
+ decl.importKind = typeOnly ? 'type' : 'value';
106
+ return decl;
107
+ }
108
+ function createVariablesInterface(op) {
109
+ if (op.args.length === 0)
110
+ return null;
111
+ const varTypeName = `${(0, utils_1.ucFirst)(op.name)}Variables`;
112
+ const props = op.args.map((arg) => {
113
+ const optional = !(0, type_resolver_1.isTypeRequired)(arg.type);
114
+ const prop = t.tsPropertySignature(t.identifier(arg.name), t.tsTypeAnnotation(parseTypeAnnotation((0, type_resolver_1.typeRefToTsType)(arg.type))));
115
+ prop.optional = optional;
116
+ return prop;
117
+ });
118
+ const interfaceDecl = t.tsInterfaceDeclaration(t.identifier(varTypeName), null, null, t.tsInterfaceBody(props));
119
+ return t.exportNamedDeclaration(interfaceDecl);
120
+ }
121
+ function parseTypeAnnotation(typeStr) {
122
+ if (typeStr === 'string')
123
+ return t.tsStringKeyword();
124
+ if (typeStr === 'number')
125
+ return t.tsNumberKeyword();
126
+ if (typeStr === 'boolean')
127
+ return t.tsBooleanKeyword();
128
+ if (typeStr === 'null')
129
+ return t.tsNullKeyword();
130
+ if (typeStr === 'undefined')
131
+ return t.tsUndefinedKeyword();
132
+ if (typeStr === 'unknown')
133
+ return t.tsUnknownKeyword();
134
+ if (typeStr.includes(' | ')) {
135
+ const parts = typeStr.split(' | ').map((p) => parseTypeAnnotation(p.trim()));
136
+ return t.tsUnionType(parts);
137
+ }
138
+ if (typeStr.endsWith('[]')) {
139
+ return t.tsArrayType(parseTypeAnnotation(typeStr.slice(0, -2)));
140
+ }
141
+ return t.tsTypeReference(t.identifier(typeStr));
142
+ }
143
+ function buildOperationMethod(op, operationType) {
144
+ const hasArgs = op.args.length > 0;
145
+ const varTypeName = `${(0, utils_1.ucFirst)(op.name)}Variables`;
146
+ const varDefs = op.args.map((arg) => ({
147
+ name: arg.name,
148
+ type: formatGraphQLType(arg.type),
149
+ }));
150
+ const selectTypeName = getSelectTypeName(op.returnType);
151
+ const payloadTypeName = (0, type_resolver_1.getTypeBaseName)(op.returnType);
152
+ // Build the arrow function parameters
153
+ const params = [];
154
+ if (hasArgs) {
155
+ const argsParam = t.identifier('args');
156
+ argsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(varTypeName)));
157
+ params.push(argsParam);
158
+ }
159
+ const optionsParam = t.identifier('options');
160
+ optionsParam.optional = true;
161
+ if (selectTypeName) {
162
+ optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeLiteral([
163
+ (() => {
164
+ const prop = t.tsPropertySignature(t.identifier('select'), t.tsTypeAnnotation(t.tsTypeReference(t.identifier('S'))));
165
+ prop.optional = true;
166
+ return prop;
167
+ })(),
168
+ ]));
169
+ }
170
+ else {
171
+ optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeLiteral([
172
+ (() => {
173
+ const prop = t.tsPropertySignature(t.identifier('select'), t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Record'), t.tsTypeParameterInstantiation([t.tsStringKeyword(), t.tsUnknownKeyword()]))));
174
+ prop.optional = true;
175
+ return prop;
176
+ })(),
177
+ ]));
178
+ }
179
+ params.push(optionsParam);
180
+ // Build the QueryBuilder call
181
+ const queryBuilderArgs = t.objectExpression([
182
+ t.objectProperty(t.identifier('client'), t.identifier('client'), false, true),
183
+ t.objectProperty(t.identifier('operation'), t.stringLiteral(operationType)),
184
+ t.objectProperty(t.identifier('operationName'), t.stringLiteral((0, utils_1.ucFirst)(op.name))),
185
+ t.objectProperty(t.identifier('fieldName'), t.stringLiteral(op.name)),
186
+ t.spreadElement(t.callExpression(t.identifier('buildCustomDocument'), [
187
+ t.stringLiteral(operationType),
188
+ t.stringLiteral((0, utils_1.ucFirst)(op.name)),
189
+ t.stringLiteral(op.name),
190
+ t.optionalMemberExpression(t.identifier('options'), t.identifier('select'), false, true),
191
+ hasArgs ? t.identifier('args') : t.identifier('undefined'),
192
+ t.arrayExpression(varDefs.map((v) => t.objectExpression([
193
+ t.objectProperty(t.identifier('name'), t.stringLiteral(v.name)),
194
+ t.objectProperty(t.identifier('type'), t.stringLiteral(v.type)),
195
+ ]))),
196
+ ])),
197
+ ]);
198
+ const newExpr = t.newExpression(t.identifier('QueryBuilder'), [queryBuilderArgs]);
199
+ // Add type parameter if we have a select type
200
+ if (selectTypeName && payloadTypeName) {
201
+ newExpr.typeParameters = t.tsTypeParameterInstantiation([
202
+ t.tsTypeLiteral([
203
+ t.tsPropertySignature(t.identifier(op.name), t.tsTypeAnnotation(t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
204
+ t.tsTypeReference(t.identifier(payloadTypeName)),
205
+ t.tsTypeReference(t.identifier('S')),
206
+ ])))),
207
+ ]),
208
+ ]);
209
+ }
210
+ const arrowFunc = t.arrowFunctionExpression(params, newExpr);
211
+ // Add type parameters to arrow function if we have a select type
212
+ if (selectTypeName) {
213
+ const typeParam = t.tsTypeParameter(t.tsTypeReference(t.identifier(selectTypeName)), null, 'S');
214
+ typeParam.const = true;
215
+ arrowFunc.typeParameters = t.tsTypeParameterDeclaration([typeParam]);
216
+ }
217
+ return t.objectProperty(t.identifier(op.name), arrowFunc);
218
+ }
68
219
  /**
69
220
  * Generate the query/index.ts file for custom query operations
70
221
  */
71
222
  function generateCustomQueryOpsFile(operations) {
72
- const project = (0, ts_ast_1.createProject)();
73
- const sourceFile = (0, ts_ast_1.createSourceFile)(project, 'index.ts');
223
+ const statements = [];
74
224
  // Collect all input type names and payload type names
75
225
  const inputTypeNames = collectInputTypeNamesFromOps(operations);
76
226
  const payloadTypeNames = collectPayloadTypeNamesFromOps(operations);
77
- // Generate Select type names for payloads
78
227
  const selectTypeNames = payloadTypeNames.map((p) => `${p}Select`);
79
- // Combine all type imports
80
- const allTypeImports = [
81
- ...new Set([...inputTypeNames, ...payloadTypeNames, ...selectTypeNames]),
82
- ];
83
- // Add file header
84
- sourceFile.insertText(0, (0, ts_ast_1.createFileHeader)('Custom query operations') + '\n\n');
228
+ const allTypeImports = [...new Set([...inputTypeNames, ...payloadTypeNames, ...selectTypeNames])];
85
229
  // Add imports
86
- sourceFile.addImportDeclarations([
87
- (0, ts_ast_1.createImport)({
88
- moduleSpecifier: '../client',
89
- namedImports: ['OrmClient'],
90
- }),
91
- (0, ts_ast_1.createImport)({
92
- moduleSpecifier: '../query-builder',
93
- namedImports: ['QueryBuilder', 'buildCustomDocument'],
94
- }),
95
- (0, ts_ast_1.createImport)({
96
- moduleSpecifier: '../select-types',
97
- typeOnlyNamedImports: ['InferSelectResult'],
98
- }),
99
- ]);
100
- // Import types from input-types if we have any
230
+ statements.push(createImportDeclaration('../client', ['OrmClient']));
231
+ statements.push(createImportDeclaration('../query-builder', ['QueryBuilder', 'buildCustomDocument']));
232
+ statements.push(createImportDeclaration('../select-types', ['InferSelectResult'], true));
101
233
  if (allTypeImports.length > 0) {
102
- sourceFile.addImportDeclarations([
103
- (0, ts_ast_1.createImport)({
104
- moduleSpecifier: '../input-types',
105
- typeOnlyNamedImports: allTypeImports,
106
- }),
107
- ]);
234
+ statements.push(createImportDeclaration('../input-types', allTypeImports, true));
108
235
  }
109
- // Generate variable definitions type for each operation
110
- sourceFile.addStatements('\n// ============================================================================');
111
- sourceFile.addStatements('// Variable Types');
112
- sourceFile.addStatements('// ============================================================================\n');
236
+ // Generate variable interfaces
113
237
  for (const op of operations) {
114
- if (op.args.length > 0) {
115
- const varTypeName = `${(0, utils_1.ucFirst)(op.name)}Variables`;
116
- const props = op.args.map((arg) => {
117
- const optional = !(0, type_resolver_1.isTypeRequired)(arg.type);
118
- return `${arg.name}${optional ? '?' : ''}: ${(0, type_resolver_1.typeRefToTsType)(arg.type)};`;
119
- });
120
- sourceFile.addStatements(`export interface ${varTypeName} {\n ${props.join('\n ')}\n}\n`);
121
- }
238
+ const varInterface = createVariablesInterface(op);
239
+ if (varInterface)
240
+ statements.push(varInterface);
122
241
  }
123
242
  // Generate factory function
124
- sourceFile.addStatements('\n// ============================================================================');
125
- sourceFile.addStatements('// Query Operations Factory');
126
- sourceFile.addStatements('// ============================================================================\n');
127
- // Build the operations object
128
- const operationMethods = operations.map((op) => {
129
- const hasArgs = op.args.length > 0;
130
- const varTypeName = `${(0, utils_1.ucFirst)(op.name)}Variables`;
131
- const varDefs = op.args.map((arg) => ({
132
- name: arg.name,
133
- type: formatGraphQLType(arg.type),
134
- }));
135
- const varDefsJson = JSON.stringify(varDefs);
136
- // Get Select type for return type
137
- const selectTypeName = getSelectTypeName(op.returnType);
138
- const payloadTypeName = (0, type_resolver_1.getTypeBaseName)(op.returnType);
139
- // Use typed select if available, otherwise fall back to Record<string, unknown>
140
- const selectType = selectTypeName ?? 'Record<string, unknown>';
141
- const returnTypePart = selectTypeName && payloadTypeName
142
- ? `{ ${op.name}: InferSelectResult<${payloadTypeName}, S> }`
143
- : 'unknown';
144
- if (hasArgs) {
145
- if (selectTypeName) {
146
- return `${op.name}: <const S extends ${selectType}>(args: ${varTypeName}, options?: { select?: S }) =>
147
- new QueryBuilder<${returnTypePart}>({
148
- client,
149
- operation: 'query',
150
- operationName: '${(0, utils_1.ucFirst)(op.name)}',
151
- fieldName: '${op.name}',
152
- ...buildCustomDocument('query', '${(0, utils_1.ucFirst)(op.name)}', '${op.name}', options?.select, args, ${varDefsJson}),
153
- })`;
154
- }
155
- else {
156
- return `${op.name}: (args: ${varTypeName}, options?: { select?: Record<string, unknown> }) =>
157
- new QueryBuilder({
158
- client,
159
- operation: 'query',
160
- operationName: '${(0, utils_1.ucFirst)(op.name)}',
161
- fieldName: '${op.name}',
162
- ...buildCustomDocument('query', '${(0, utils_1.ucFirst)(op.name)}', '${op.name}', options?.select, args, ${varDefsJson}),
163
- })`;
164
- }
165
- }
166
- else {
167
- // No args - still provide typed select
168
- if (selectTypeName) {
169
- return `${op.name}: <const S extends ${selectType}>(options?: { select?: S }) =>
170
- new QueryBuilder<${returnTypePart}>({
171
- client,
172
- operation: 'query',
173
- operationName: '${(0, utils_1.ucFirst)(op.name)}',
174
- fieldName: '${op.name}',
175
- ...buildCustomDocument('query', '${(0, utils_1.ucFirst)(op.name)}', '${op.name}', options?.select, undefined, []),
176
- })`;
177
- }
178
- else {
179
- return `${op.name}: (options?: { select?: Record<string, unknown> }) =>
180
- new QueryBuilder({
181
- client,
182
- operation: 'query',
183
- operationName: '${(0, utils_1.ucFirst)(op.name)}',
184
- fieldName: '${op.name}',
185
- ...buildCustomDocument('query', '${(0, utils_1.ucFirst)(op.name)}', '${op.name}', options?.select, undefined, []),
186
- })`;
187
- }
188
- }
189
- });
190
- sourceFile.addFunction({
191
- name: 'createQueryOperations',
192
- isExported: true,
193
- parameters: [{ name: 'client', type: 'OrmClient' }],
194
- statements: `return {
195
- ${operationMethods.join(',\n ')},
196
- };`,
197
- });
243
+ const operationProperties = operations.map((op) => buildOperationMethod(op, 'query'));
244
+ const returnObj = t.objectExpression(operationProperties);
245
+ const returnStmt = t.returnStatement(returnObj);
246
+ const clientParam = t.identifier('client');
247
+ clientParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('OrmClient')));
248
+ const factoryFunc = t.functionDeclaration(t.identifier('createQueryOperations'), [clientParam], t.blockStatement([returnStmt]));
249
+ statements.push(t.exportNamedDeclaration(factoryFunc));
250
+ const header = (0, utils_1.getGeneratedFileHeader)('Custom query operations');
251
+ const code = (0, babel_ast_1.generateCode)(statements);
198
252
  return {
199
253
  fileName: 'query/index.ts',
200
- content: (0, ts_ast_1.getFormattedOutput)(sourceFile),
254
+ content: header + '\n' + code,
201
255
  };
202
256
  }
203
257
  /**
204
258
  * Generate the mutation/index.ts file for custom mutation operations
205
259
  */
206
260
  function generateCustomMutationOpsFile(operations) {
207
- const project = (0, ts_ast_1.createProject)();
208
- const sourceFile = (0, ts_ast_1.createSourceFile)(project, 'index.ts');
261
+ const statements = [];
209
262
  // Collect all input type names and payload type names
210
263
  const inputTypeNames = collectInputTypeNamesFromOps(operations);
211
264
  const payloadTypeNames = collectPayloadTypeNamesFromOps(operations);
212
- // Generate Select type names for payloads
213
265
  const selectTypeNames = payloadTypeNames.map((p) => `${p}Select`);
214
- // Combine all type imports
215
- const allTypeImports = [
216
- ...new Set([...inputTypeNames, ...payloadTypeNames, ...selectTypeNames]),
217
- ];
218
- // Add file header
219
- sourceFile.insertText(0, (0, ts_ast_1.createFileHeader)('Custom mutation operations') + '\n\n');
266
+ const allTypeImports = [...new Set([...inputTypeNames, ...payloadTypeNames, ...selectTypeNames])];
220
267
  // Add imports
221
- sourceFile.addImportDeclarations([
222
- (0, ts_ast_1.createImport)({
223
- moduleSpecifier: '../client',
224
- namedImports: ['OrmClient'],
225
- }),
226
- (0, ts_ast_1.createImport)({
227
- moduleSpecifier: '../query-builder',
228
- namedImports: ['QueryBuilder', 'buildCustomDocument'],
229
- }),
230
- (0, ts_ast_1.createImport)({
231
- moduleSpecifier: '../select-types',
232
- typeOnlyNamedImports: ['InferSelectResult'],
233
- }),
234
- ]);
235
- // Import types from input-types if we have any
268
+ statements.push(createImportDeclaration('../client', ['OrmClient']));
269
+ statements.push(createImportDeclaration('../query-builder', ['QueryBuilder', 'buildCustomDocument']));
270
+ statements.push(createImportDeclaration('../select-types', ['InferSelectResult'], true));
236
271
  if (allTypeImports.length > 0) {
237
- sourceFile.addImportDeclarations([
238
- (0, ts_ast_1.createImport)({
239
- moduleSpecifier: '../input-types',
240
- typeOnlyNamedImports: allTypeImports,
241
- }),
242
- ]);
272
+ statements.push(createImportDeclaration('../input-types', allTypeImports, true));
243
273
  }
244
- // Generate variable definitions type for each operation
245
- sourceFile.addStatements('\n// ============================================================================');
246
- sourceFile.addStatements('// Variable Types');
247
- sourceFile.addStatements('// ============================================================================\n');
274
+ // Generate variable interfaces
248
275
  for (const op of operations) {
249
- if (op.args.length > 0) {
250
- const varTypeName = `${(0, utils_1.ucFirst)(op.name)}Variables`;
251
- const props = op.args.map((arg) => {
252
- const optional = !(0, type_resolver_1.isTypeRequired)(arg.type);
253
- return `${arg.name}${optional ? '?' : ''}: ${(0, type_resolver_1.typeRefToTsType)(arg.type)};`;
254
- });
255
- sourceFile.addStatements(`export interface ${varTypeName} {\n ${props.join('\n ')}\n}\n`);
256
- }
276
+ const varInterface = createVariablesInterface(op);
277
+ if (varInterface)
278
+ statements.push(varInterface);
257
279
  }
258
280
  // Generate factory function
259
- sourceFile.addStatements('\n// ============================================================================');
260
- sourceFile.addStatements('// Mutation Operations Factory');
261
- sourceFile.addStatements('// ============================================================================\n');
262
- // Build the operations object
263
- const operationMethods = operations.map((op) => {
264
- const hasArgs = op.args.length > 0;
265
- const varTypeName = `${(0, utils_1.ucFirst)(op.name)}Variables`;
266
- const varDefs = op.args.map((arg) => ({
267
- name: arg.name,
268
- type: formatGraphQLType(arg.type),
269
- }));
270
- const varDefsJson = JSON.stringify(varDefs);
271
- // Get Select type for return type
272
- const selectTypeName = getSelectTypeName(op.returnType);
273
- const payloadTypeName = (0, type_resolver_1.getTypeBaseName)(op.returnType);
274
- // Use typed select if available, otherwise fall back to Record<string, unknown>
275
- const selectType = selectTypeName ?? 'Record<string, unknown>';
276
- const returnTypePart = selectTypeName && payloadTypeName
277
- ? `{ ${op.name}: InferSelectResult<${payloadTypeName}, S> }`
278
- : 'unknown';
279
- if (hasArgs) {
280
- if (selectTypeName) {
281
- return `${op.name}: <const S extends ${selectType}>(args: ${varTypeName}, options?: { select?: S }) =>
282
- new QueryBuilder<${returnTypePart}>({
283
- client,
284
- operation: 'mutation',
285
- operationName: '${(0, utils_1.ucFirst)(op.name)}',
286
- fieldName: '${op.name}',
287
- ...buildCustomDocument('mutation', '${(0, utils_1.ucFirst)(op.name)}', '${op.name}', options?.select, args, ${varDefsJson}),
288
- })`;
289
- }
290
- else {
291
- return `${op.name}: (args: ${varTypeName}, options?: { select?: Record<string, unknown> }) =>
292
- new QueryBuilder({
293
- client,
294
- operation: 'mutation',
295
- operationName: '${(0, utils_1.ucFirst)(op.name)}',
296
- fieldName: '${op.name}',
297
- ...buildCustomDocument('mutation', '${(0, utils_1.ucFirst)(op.name)}', '${op.name}', options?.select, args, ${varDefsJson}),
298
- })`;
299
- }
300
- }
301
- else {
302
- // No args - still provide typed select
303
- if (selectTypeName) {
304
- return `${op.name}: <const S extends ${selectType}>(options?: { select?: S }) =>
305
- new QueryBuilder<${returnTypePart}>({
306
- client,
307
- operation: 'mutation',
308
- operationName: '${(0, utils_1.ucFirst)(op.name)}',
309
- fieldName: '${op.name}',
310
- ...buildCustomDocument('mutation', '${(0, utils_1.ucFirst)(op.name)}', '${op.name}', options?.select, undefined, []),
311
- })`;
312
- }
313
- else {
314
- return `${op.name}: (options?: { select?: Record<string, unknown> }) =>
315
- new QueryBuilder({
316
- client,
317
- operation: 'mutation',
318
- operationName: '${(0, utils_1.ucFirst)(op.name)}',
319
- fieldName: '${op.name}',
320
- ...buildCustomDocument('mutation', '${(0, utils_1.ucFirst)(op.name)}', '${op.name}', options?.select, undefined, []),
321
- })`;
322
- }
323
- }
324
- });
325
- sourceFile.addFunction({
326
- name: 'createMutationOperations',
327
- isExported: true,
328
- parameters: [{ name: 'client', type: 'OrmClient' }],
329
- statements: `return {
330
- ${operationMethods.join(',\n ')},
331
- };`,
332
- });
281
+ const operationProperties = operations.map((op) => buildOperationMethod(op, 'mutation'));
282
+ const returnObj = t.objectExpression(operationProperties);
283
+ const returnStmt = t.returnStatement(returnObj);
284
+ const clientParam = t.identifier('client');
285
+ clientParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('OrmClient')));
286
+ const factoryFunc = t.functionDeclaration(t.identifier('createMutationOperations'), [clientParam], t.blockStatement([returnStmt]));
287
+ statements.push(t.exportNamedDeclaration(factoryFunc));
288
+ const header = (0, utils_1.getGeneratedFileHeader)('Custom mutation operations');
289
+ const code = (0, babel_ast_1.generateCode)(statements);
333
290
  return {
334
291
  fileName: 'mutation/index.ts',
335
- content: (0, ts_ast_1.getFormattedOutput)(sourceFile),
292
+ content: header + '\n' + code,
336
293
  };
337
294
  }
338
295
  /**
@@ -1,3 +1,15 @@
1
+ /**
2
+ * Input types generator for ORM client (Babel AST-based)
3
+ *
4
+ * Generates TypeScript interfaces for:
5
+ * 1. Scalar filter types (StringFilter, IntFilter, UUIDFilter, etc.)
6
+ * 2. Entity interfaces (User, Order, etc.)
7
+ * 3. Table filter types (UserFilter, OrderFilter, etc.)
8
+ * 4. OrderBy enums (UsersOrderBy, OrdersOrderBy, etc.)
9
+ * 5. Input types (LoginInput, CreateUserInput, etc.)
10
+ *
11
+ * Uses Babel AST for robust code generation.
12
+ */
1
13
  import type { TypeRegistry, CleanArgument, CleanTable } from '../../../types/schema';
2
14
  export interface GeneratedInputTypesFile {
3
15
  fileName: string;
@@ -16,6 +28,6 @@ export declare function collectPayloadTypeNames(operations: Array<{
16
28
  returnType: CleanArgument['type'];
17
29
  }>): Set<string>;
18
30
  /**
19
- * Generate comprehensive input-types.ts file using ts-morph AST
31
+ * Generate comprehensive input-types.ts file using Babel AST
20
32
  */
21
33
  export declare function generateInputTypesFile(typeRegistry: TypeRegistry, usedInputTypes: Set<string>, tables?: CleanTable[], usedPayloadTypes?: Set<string>): GeneratedInputTypesFile;