@constructive-io/graphql-codegen 2.23.3 → 2.24.1

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 (92) hide show
  1. package/README.md +147 -2
  2. package/cli/codegen/babel-ast.d.ts +53 -0
  3. package/cli/codegen/babel-ast.js +160 -0
  4. package/cli/codegen/barrel.d.ts +7 -2
  5. package/cli/codegen/barrel.js +193 -102
  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 +236 -335
  11. package/cli/codegen/gql-ast.js +22 -1
  12. package/cli/codegen/index.d.ts +3 -0
  13. package/cli/codegen/index.js +73 -3
  14. package/cli/codegen/invalidation.d.ts +20 -0
  15. package/cli/codegen/invalidation.js +327 -0
  16. package/cli/codegen/mutation-keys.d.ts +24 -0
  17. package/cli/codegen/mutation-keys.js +247 -0
  18. package/cli/codegen/mutations.d.ts +5 -19
  19. package/cli/codegen/mutations.js +385 -383
  20. package/cli/codegen/orm/barrel.d.ts +1 -1
  21. package/cli/codegen/orm/barrel.js +42 -10
  22. package/cli/codegen/orm/client-generator.d.ts +1 -19
  23. package/cli/codegen/orm/client-generator.js +108 -77
  24. package/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
  25. package/cli/codegen/orm/custom-ops-generator.js +192 -235
  26. package/cli/codegen/orm/input-types-generator.d.ts +13 -1
  27. package/cli/codegen/orm/input-types-generator.js +425 -147
  28. package/cli/codegen/orm/model-generator.d.ts +1 -19
  29. package/cli/codegen/orm/model-generator.js +229 -234
  30. package/cli/codegen/queries.d.ts +4 -12
  31. package/cli/codegen/queries.js +660 -390
  32. package/cli/codegen/query-keys.d.ts +15 -0
  33. package/cli/codegen/query-keys.js +477 -0
  34. package/cli/codegen/scalars.js +1 -0
  35. package/cli/codegen/schema-types-generator.d.ts +15 -10
  36. package/cli/codegen/schema-types-generator.js +87 -175
  37. package/cli/codegen/type-resolver.d.ts +1 -30
  38. package/cli/codegen/type-resolver.js +0 -53
  39. package/cli/codegen/types.d.ts +1 -1
  40. package/cli/codegen/types.js +76 -21
  41. package/cli/codegen/utils.d.ts +6 -0
  42. package/cli/codegen/utils.js +19 -0
  43. package/esm/cli/codegen/babel-ast.d.ts +53 -0
  44. package/esm/cli/codegen/babel-ast.js +111 -0
  45. package/esm/cli/codegen/barrel.d.ts +7 -2
  46. package/esm/cli/codegen/barrel.js +161 -103
  47. package/esm/cli/codegen/client.js +61 -0
  48. package/esm/cli/codegen/custom-mutations.d.ts +2 -12
  49. package/esm/cli/codegen/custom-mutations.js +83 -124
  50. package/esm/cli/codegen/custom-queries.d.ts +2 -10
  51. package/esm/cli/codegen/custom-queries.js +204 -336
  52. package/esm/cli/codegen/gql-ast.js +23 -2
  53. package/esm/cli/codegen/index.d.ts +3 -0
  54. package/esm/cli/codegen/index.js +69 -2
  55. package/esm/cli/codegen/invalidation.d.ts +20 -0
  56. package/esm/cli/codegen/invalidation.js +291 -0
  57. package/esm/cli/codegen/mutation-keys.d.ts +24 -0
  58. package/esm/cli/codegen/mutation-keys.js +211 -0
  59. package/esm/cli/codegen/mutations.d.ts +5 -19
  60. package/esm/cli/codegen/mutations.js +353 -384
  61. package/esm/cli/codegen/orm/barrel.d.ts +1 -1
  62. package/esm/cli/codegen/orm/barrel.js +10 -11
  63. package/esm/cli/codegen/orm/client-generator.d.ts +1 -19
  64. package/esm/cli/codegen/orm/client-generator.js +76 -78
  65. package/esm/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
  66. package/esm/cli/codegen/orm/custom-ops-generator.js +160 -236
  67. package/esm/cli/codegen/orm/input-types-generator.d.ts +13 -1
  68. package/esm/cli/codegen/orm/input-types-generator.js +393 -148
  69. package/esm/cli/codegen/orm/model-generator.d.ts +1 -19
  70. package/esm/cli/codegen/orm/model-generator.js +197 -235
  71. package/esm/cli/codegen/queries.d.ts +4 -12
  72. package/esm/cli/codegen/queries.js +628 -391
  73. package/esm/cli/codegen/query-keys.d.ts +15 -0
  74. package/esm/cli/codegen/query-keys.js +441 -0
  75. package/esm/cli/codegen/scalars.js +1 -0
  76. package/esm/cli/codegen/schema-types-generator.d.ts +15 -10
  77. package/esm/cli/codegen/schema-types-generator.js +54 -175
  78. package/esm/cli/codegen/type-resolver.d.ts +1 -30
  79. package/esm/cli/codegen/type-resolver.js +0 -49
  80. package/esm/cli/codegen/types.d.ts +1 -1
  81. package/esm/cli/codegen/types.js +44 -22
  82. package/esm/cli/codegen/utils.d.ts +6 -0
  83. package/esm/cli/codegen/utils.js +18 -0
  84. package/esm/types/config.d.ts +75 -0
  85. package/esm/types/config.js +18 -0
  86. package/package.json +6 -4
  87. package/types/config.d.ts +75 -0
  88. package/types/config.js +19 -1
  89. package/cli/codegen/ts-ast.d.ts +0 -124
  90. package/cli/codegen/ts-ast.js +0 -280
  91. package/esm/cli/codegen/ts-ast.d.ts +0 -124
  92. package/esm/cli/codegen/ts-ast.js +0 -260
@@ -1,19 +1,7 @@
1
1
  /**
2
- * Model class generator for ORM client
2
+ * Model class generator for ORM client (Babel AST-based)
3
3
  *
4
4
  * Generates per-table model classes with findMany, findFirst, create, update, delete methods.
5
- *
6
- * Example output:
7
- * ```typescript
8
- * export class UserModel {
9
- * constructor(private client: OrmClient) {}
10
- *
11
- * findMany<S extends UserSelect>(args?: FindManyArgs<S, UserWhereInput, UserOrderBy>) {
12
- * return new QueryBuilder<...>({ ... });
13
- * }
14
- * // ...
15
- * }
16
- * ```
17
5
  */
18
6
  import type { CleanTable } from '../../../types/schema';
19
7
  export interface GeneratedModelFile {
@@ -22,11 +10,5 @@ export interface GeneratedModelFile {
22
10
  modelName: string;
23
11
  tableName: string;
24
12
  }
25
- /**
26
- * Generate a model class file for a table
27
- */
28
13
  export declare function generateModelFile(table: CleanTable, _useSharedTypes: boolean): GeneratedModelFile;
29
- /**
30
- * Generate all model files for a list of tables
31
- */
32
14
  export declare function generateAllModelFiles(tables: CleanTable[], useSharedTypes: boolean): GeneratedModelFile[];
@@ -1,17 +1,48 @@
1
- import { createProject, createSourceFile, getFormattedOutput, createFileHeader, createImport, } from '../ts-ast';
2
- import { getTableNames, getOrderByTypeName, getFilterTypeName, lcFirst, } from '../utils';
3
- /**
4
- * Generate a model class file for a table
5
- */
1
+ import * as t from '@babel/types';
2
+ import { generateCode } from '../babel-ast';
3
+ import { getTableNames, getOrderByTypeName, getFilterTypeName, lcFirst, getGeneratedFileHeader, } from '../utils';
4
+ function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false) {
5
+ const specifiers = namedImports.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
6
+ const decl = t.importDeclaration(specifiers, t.stringLiteral(moduleSpecifier));
7
+ decl.importKind = typeOnly ? 'type' : 'value';
8
+ return decl;
9
+ }
10
+ function buildMethodBody(builderFn, args, operation, typeName, fieldName) {
11
+ const destructureDecl = t.variableDeclaration('const', [
12
+ t.variableDeclarator(t.objectPattern([
13
+ t.objectProperty(t.identifier('document'), t.identifier('document'), false, true),
14
+ t.objectProperty(t.identifier('variables'), t.identifier('variables'), false, true),
15
+ ]), t.callExpression(t.identifier(builderFn), args)),
16
+ ]);
17
+ const returnStmt = t.returnStatement(t.newExpression(t.identifier('QueryBuilder'), [
18
+ t.objectExpression([
19
+ t.objectProperty(t.identifier('client'), t.memberExpression(t.thisExpression(), t.identifier('client'))),
20
+ t.objectProperty(t.identifier('operation'), t.stringLiteral(operation)),
21
+ t.objectProperty(t.identifier('operationName'), t.stringLiteral(typeName)),
22
+ t.objectProperty(t.identifier('fieldName'), t.stringLiteral(fieldName)),
23
+ t.objectProperty(t.identifier('document'), t.identifier('document'), false, true),
24
+ t.objectProperty(t.identifier('variables'), t.identifier('variables'), false, true),
25
+ ]),
26
+ ]));
27
+ return [destructureDecl, returnStmt];
28
+ }
29
+ function createClassMethod(name, typeParameters, params, returnType, body) {
30
+ const method = t.classMethod('method', t.identifier(name), params, t.blockStatement(body));
31
+ method.typeParameters = typeParameters;
32
+ method.returnType = returnType;
33
+ return method;
34
+ }
35
+ function createConstTypeParam(constraintTypeName) {
36
+ const param = t.tsTypeParameter(t.tsTypeReference(t.identifier(constraintTypeName)), null, 'S');
37
+ param.const = true;
38
+ return t.tsTypeParameterDeclaration([param]);
39
+ }
6
40
  export function generateModelFile(table, _useSharedTypes) {
7
- const project = createProject();
8
41
  const { typeName, singularName, pluralName } = getTableNames(table);
9
42
  const modelName = `${typeName}Model`;
10
- // Avoid "index.ts" which clashes with barrel file
11
43
  const baseFileName = lcFirst(typeName);
12
44
  const fileName = baseFileName === 'index' ? `${baseFileName}Model.ts` : `${baseFileName}.ts`;
13
45
  const entityLower = singularName;
14
- // Type names for this entity - use inflection from table metadata
15
46
  const selectTypeName = `${typeName}Select`;
16
47
  const relationTypeName = `${typeName}WithRelations`;
17
48
  const whereTypeName = getFilterTypeName(table);
@@ -20,244 +51,175 @@ export function generateModelFile(table, _useSharedTypes) {
20
51
  const updateInputTypeName = `Update${typeName}Input`;
21
52
  const deleteInputTypeName = `Delete${typeName}Input`;
22
53
  const patchTypeName = `${typeName}Patch`;
23
- const createDataType = `${createInputTypeName}['${singularName}']`;
24
- // Query names from PostGraphile
25
54
  const pluralQueryName = table.query?.all ?? pluralName;
26
55
  const createMutationName = table.query?.create ?? `create${typeName}`;
27
56
  const updateMutationName = table.query?.update;
28
57
  const deleteMutationName = table.query?.delete;
29
- const sourceFile = createSourceFile(project, fileName);
30
- // Add file header
31
- sourceFile.insertText(0, createFileHeader(`${typeName} model for ORM client`) + '\n\n');
32
- // Add imports - import types from respective modules
33
- sourceFile.addImportDeclarations([
34
- createImport({
35
- moduleSpecifier: '../client',
36
- namedImports: ['OrmClient'],
37
- }),
38
- createImport({
39
- moduleSpecifier: '../query-builder',
40
- namedImports: [
41
- 'QueryBuilder',
42
- 'buildFindManyDocument',
43
- 'buildFindFirstDocument',
44
- 'buildCreateDocument',
45
- 'buildUpdateDocument',
46
- 'buildDeleteDocument',
47
- ],
48
- }),
49
- createImport({
50
- moduleSpecifier: '../select-types',
51
- typeOnlyNamedImports: [
52
- 'ConnectionResult',
53
- 'FindManyArgs',
54
- 'FindFirstArgs',
55
- 'CreateArgs',
56
- 'UpdateArgs',
57
- 'DeleteArgs',
58
- 'InferSelectResult',
59
- ],
60
- }),
61
- ]);
62
- // Build complete set of input-types imports
63
- // Select types are now centralized in input-types.ts with relations included
64
- const inputTypeImports = new Set([
65
- typeName,
66
- relationTypeName,
67
- selectTypeName,
68
- whereTypeName,
69
- orderByTypeName,
70
- createInputTypeName,
71
- updateInputTypeName,
72
- patchTypeName,
73
- ]);
74
- // Add single combined import from input-types
75
- sourceFile.addImportDeclaration(createImport({
76
- moduleSpecifier: '../input-types',
77
- typeOnlyNamedImports: Array.from(inputTypeImports),
78
- }));
79
- // Add Model class
80
- sourceFile.addStatements('\n// ============================================================================');
81
- sourceFile.addStatements('// Model Class');
82
- sourceFile.addStatements('// ============================================================================\n');
83
- // Generate the model class
84
- const classDeclaration = sourceFile.addClass({
85
- name: modelName,
86
- isExported: true,
87
- });
58
+ const statements = [];
59
+ statements.push(createImportDeclaration('../client', ['OrmClient']));
60
+ statements.push(createImportDeclaration('../query-builder', [
61
+ 'QueryBuilder', 'buildFindManyDocument', 'buildFindFirstDocument',
62
+ 'buildCreateDocument', 'buildUpdateDocument', 'buildDeleteDocument',
63
+ ]));
64
+ statements.push(createImportDeclaration('../select-types', [
65
+ 'ConnectionResult', 'FindManyArgs', 'FindFirstArgs', 'CreateArgs',
66
+ 'UpdateArgs', 'DeleteArgs', 'InferSelectResult',
67
+ ], true));
68
+ statements.push(createImportDeclaration('../input-types', [
69
+ typeName, relationTypeName, selectTypeName, whereTypeName, orderByTypeName,
70
+ createInputTypeName, updateInputTypeName, patchTypeName,
71
+ ], true));
72
+ const classBody = [];
88
73
  // Constructor
89
- classDeclaration.addConstructor({
90
- parameters: [
91
- {
92
- name: 'client',
93
- type: 'OrmClient',
94
- scope: 'private',
95
- },
96
- ],
97
- });
98
- // findMany method - uses const generic for proper literal type inference
99
- classDeclaration.addMethod({
100
- name: 'findMany',
101
- typeParameters: [`const S extends ${selectTypeName}`],
102
- parameters: [
103
- {
104
- name: 'args',
105
- type: `FindManyArgs<S, ${whereTypeName}, ${orderByTypeName}>`,
106
- hasQuestionToken: true,
107
- },
108
- ],
109
- returnType: `QueryBuilder<{ ${pluralQueryName}: ConnectionResult<InferSelectResult<${relationTypeName}, S>> }>`,
110
- statements: `const { document, variables } = buildFindManyDocument(
111
- '${typeName}',
112
- '${pluralQueryName}',
113
- args?.select,
114
- {
115
- where: args?.where,
116
- orderBy: args?.orderBy as string[] | undefined,
117
- first: args?.first,
118
- last: args?.last,
119
- after: args?.after,
120
- before: args?.before,
121
- offset: args?.offset,
122
- },
123
- '${whereTypeName}',
124
- '${orderByTypeName}'
125
- );
126
- return new QueryBuilder({
127
- client: this.client,
128
- operation: 'query',
129
- operationName: '${typeName}',
130
- fieldName: '${pluralQueryName}',
131
- document,
132
- variables,
133
- });`,
134
- });
135
- // findFirst method - uses const generic for proper literal type inference
136
- classDeclaration.addMethod({
137
- name: 'findFirst',
138
- typeParameters: [`const S extends ${selectTypeName}`],
139
- parameters: [
140
- {
141
- name: 'args',
142
- type: `FindFirstArgs<S, ${whereTypeName}>`,
143
- hasQuestionToken: true,
144
- },
145
- ],
146
- returnType: `QueryBuilder<{ ${pluralQueryName}: { nodes: InferSelectResult<${relationTypeName}, S>[] } }>`,
147
- statements: `const { document, variables } = buildFindFirstDocument(
148
- '${typeName}',
149
- '${pluralQueryName}',
150
- args?.select,
151
- { where: args?.where },
152
- '${whereTypeName}'
153
- );
154
- return new QueryBuilder({
155
- client: this.client,
156
- operation: 'query',
157
- operationName: '${typeName}',
158
- fieldName: '${pluralQueryName}',
159
- document,
160
- variables,
161
- });`,
162
- });
163
- // create method - uses const generic for proper literal type inference
164
- classDeclaration.addMethod({
165
- name: 'create',
166
- typeParameters: [`const S extends ${selectTypeName}`],
167
- parameters: [
168
- {
169
- name: 'args',
170
- type: `CreateArgs<S, ${createDataType}>`,
171
- },
172
- ],
173
- returnType: `QueryBuilder<{ ${createMutationName}: { ${entityLower}: InferSelectResult<${relationTypeName}, S> } }>`,
174
- statements: `const { document, variables } = buildCreateDocument(
175
- '${typeName}',
176
- '${createMutationName}',
177
- '${entityLower}',
178
- args.select,
179
- args.data,
180
- '${createInputTypeName}'
181
- );
182
- return new QueryBuilder({
183
- client: this.client,
184
- operation: 'mutation',
185
- operationName: '${typeName}',
186
- fieldName: '${createMutationName}',
187
- document,
188
- variables,
189
- });`,
190
- });
191
- // update method (if available) - uses const generic for proper literal type inference
74
+ const constructorParam = t.identifier('client');
75
+ constructorParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('OrmClient')));
76
+ const paramProp = t.tsParameterProperty(constructorParam);
77
+ paramProp.accessibility = 'private';
78
+ classBody.push(t.classMethod('constructor', t.identifier('constructor'), [paramProp], t.blockStatement([])));
79
+ // findMany method
80
+ const findManyParam = t.identifier('args');
81
+ findManyParam.optional = true;
82
+ findManyParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('FindManyArgs'), t.tsTypeParameterInstantiation([
83
+ t.tsTypeReference(t.identifier('S')),
84
+ t.tsTypeReference(t.identifier(whereTypeName)),
85
+ t.tsTypeReference(t.identifier(orderByTypeName)),
86
+ ])));
87
+ const findManyReturnType = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
88
+ t.tsTypeLiteral([
89
+ t.tsPropertySignature(t.identifier(pluralQueryName), t.tsTypeAnnotation(t.tsTypeReference(t.identifier('ConnectionResult'), t.tsTypeParameterInstantiation([
90
+ t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
91
+ t.tsTypeReference(t.identifier(relationTypeName)),
92
+ t.tsTypeReference(t.identifier('S')),
93
+ ])),
94
+ ])))),
95
+ ]),
96
+ ])));
97
+ const findManyArgs = [
98
+ t.stringLiteral(typeName),
99
+ t.stringLiteral(pluralQueryName),
100
+ t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true),
101
+ t.objectExpression([
102
+ t.objectProperty(t.identifier('where'), t.optionalMemberExpression(t.identifier('args'), t.identifier('where'), false, true)),
103
+ t.objectProperty(t.identifier('orderBy'), t.tsAsExpression(t.optionalMemberExpression(t.identifier('args'), t.identifier('orderBy'), false, true), t.tsUnionType([t.tsArrayType(t.tsStringKeyword()), t.tsUndefinedKeyword()]))),
104
+ t.objectProperty(t.identifier('first'), t.optionalMemberExpression(t.identifier('args'), t.identifier('first'), false, true)),
105
+ t.objectProperty(t.identifier('last'), t.optionalMemberExpression(t.identifier('args'), t.identifier('last'), false, true)),
106
+ t.objectProperty(t.identifier('after'), t.optionalMemberExpression(t.identifier('args'), t.identifier('after'), false, true)),
107
+ t.objectProperty(t.identifier('before'), t.optionalMemberExpression(t.identifier('args'), t.identifier('before'), false, true)),
108
+ t.objectProperty(t.identifier('offset'), t.optionalMemberExpression(t.identifier('args'), t.identifier('offset'), false, true)),
109
+ ]),
110
+ t.stringLiteral(whereTypeName),
111
+ t.stringLiteral(orderByTypeName),
112
+ ];
113
+ classBody.push(createClassMethod('findMany', createConstTypeParam(selectTypeName), [findManyParam], findManyReturnType, buildMethodBody('buildFindManyDocument', findManyArgs, 'query', typeName, pluralQueryName)));
114
+ // findFirst method
115
+ const findFirstParam = t.identifier('args');
116
+ findFirstParam.optional = true;
117
+ findFirstParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('FindFirstArgs'), t.tsTypeParameterInstantiation([
118
+ t.tsTypeReference(t.identifier('S')),
119
+ t.tsTypeReference(t.identifier(whereTypeName)),
120
+ ])));
121
+ const findFirstReturnType = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
122
+ t.tsTypeLiteral([
123
+ t.tsPropertySignature(t.identifier(pluralQueryName), t.tsTypeAnnotation(t.tsTypeLiteral([
124
+ t.tsPropertySignature(t.identifier('nodes'), t.tsTypeAnnotation(t.tsArrayType(t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
125
+ t.tsTypeReference(t.identifier(relationTypeName)),
126
+ t.tsTypeReference(t.identifier('S')),
127
+ ]))))),
128
+ ]))),
129
+ ]),
130
+ ])));
131
+ const findFirstArgs = [
132
+ t.stringLiteral(typeName),
133
+ t.stringLiteral(pluralQueryName),
134
+ t.optionalMemberExpression(t.identifier('args'), t.identifier('select'), false, true),
135
+ t.objectExpression([
136
+ t.objectProperty(t.identifier('where'), t.optionalMemberExpression(t.identifier('args'), t.identifier('where'), false, true)),
137
+ ]),
138
+ t.stringLiteral(whereTypeName),
139
+ ];
140
+ classBody.push(createClassMethod('findFirst', createConstTypeParam(selectTypeName), [findFirstParam], findFirstReturnType, buildMethodBody('buildFindFirstDocument', findFirstArgs, 'query', typeName, pluralQueryName)));
141
+ // create method
142
+ const createParam = t.identifier('args');
143
+ createParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('CreateArgs'), t.tsTypeParameterInstantiation([
144
+ t.tsTypeReference(t.identifier('S')),
145
+ t.tsIndexedAccessType(t.tsTypeReference(t.identifier(createInputTypeName)), t.tsLiteralType(t.stringLiteral(singularName))),
146
+ ])));
147
+ const createReturnType = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
148
+ t.tsTypeLiteral([
149
+ t.tsPropertySignature(t.identifier(createMutationName), t.tsTypeAnnotation(t.tsTypeLiteral([
150
+ t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation(t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
151
+ t.tsTypeReference(t.identifier(relationTypeName)),
152
+ t.tsTypeReference(t.identifier('S')),
153
+ ])))),
154
+ ]))),
155
+ ]),
156
+ ])));
157
+ const createArgs = [
158
+ t.stringLiteral(typeName),
159
+ t.stringLiteral(createMutationName),
160
+ t.stringLiteral(entityLower),
161
+ t.memberExpression(t.identifier('args'), t.identifier('select')),
162
+ t.memberExpression(t.identifier('args'), t.identifier('data')),
163
+ t.stringLiteral(createInputTypeName),
164
+ ];
165
+ classBody.push(createClassMethod('create', createConstTypeParam(selectTypeName), [createParam], createReturnType, buildMethodBody('buildCreateDocument', createArgs, 'mutation', typeName, createMutationName)));
166
+ // update method (if available)
192
167
  if (updateMutationName) {
193
- classDeclaration.addMethod({
194
- name: 'update',
195
- typeParameters: [`const S extends ${selectTypeName}`],
196
- parameters: [
197
- {
198
- name: 'args',
199
- type: `UpdateArgs<S, { id: string }, ${patchTypeName}>`,
200
- },
201
- ],
202
- returnType: `QueryBuilder<{ ${updateMutationName}: { ${entityLower}: InferSelectResult<${relationTypeName}, S> } }>`,
203
- statements: `const { document, variables } = buildUpdateDocument(
204
- '${typeName}',
205
- '${updateMutationName}',
206
- '${entityLower}',
207
- args.select,
208
- args.where,
209
- args.data,
210
- '${updateInputTypeName}'
211
- );
212
- return new QueryBuilder({
213
- client: this.client,
214
- operation: 'mutation',
215
- operationName: '${typeName}',
216
- fieldName: '${updateMutationName}',
217
- document,
218
- variables,
219
- });`,
220
- });
168
+ const updateParam = t.identifier('args');
169
+ updateParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('UpdateArgs'), t.tsTypeParameterInstantiation([
170
+ t.tsTypeReference(t.identifier('S')),
171
+ t.tsTypeLiteral([t.tsPropertySignature(t.identifier('id'), t.tsTypeAnnotation(t.tsStringKeyword()))]),
172
+ t.tsTypeReference(t.identifier(patchTypeName)),
173
+ ])));
174
+ const updateReturnType = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
175
+ t.tsTypeLiteral([
176
+ t.tsPropertySignature(t.identifier(updateMutationName), t.tsTypeAnnotation(t.tsTypeLiteral([
177
+ t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation(t.tsTypeReference(t.identifier('InferSelectResult'), t.tsTypeParameterInstantiation([
178
+ t.tsTypeReference(t.identifier(relationTypeName)),
179
+ t.tsTypeReference(t.identifier('S')),
180
+ ])))),
181
+ ]))),
182
+ ]),
183
+ ])));
184
+ const updateArgs = [
185
+ t.stringLiteral(typeName),
186
+ t.stringLiteral(updateMutationName),
187
+ t.stringLiteral(entityLower),
188
+ t.memberExpression(t.identifier('args'), t.identifier('select')),
189
+ t.memberExpression(t.identifier('args'), t.identifier('where')),
190
+ t.memberExpression(t.identifier('args'), t.identifier('data')),
191
+ t.stringLiteral(updateInputTypeName),
192
+ ];
193
+ classBody.push(createClassMethod('update', createConstTypeParam(selectTypeName), [updateParam], updateReturnType, buildMethodBody('buildUpdateDocument', updateArgs, 'mutation', typeName, updateMutationName)));
221
194
  }
222
195
  // delete method (if available)
223
196
  if (deleteMutationName) {
224
- classDeclaration.addMethod({
225
- name: 'delete',
226
- parameters: [
227
- {
228
- name: 'args',
229
- type: `DeleteArgs<{ id: string }>`,
230
- },
231
- ],
232
- returnType: `QueryBuilder<{ ${deleteMutationName}: { ${entityLower}: { id: string } } }>`,
233
- statements: `const { document, variables } = buildDeleteDocument(
234
- '${typeName}',
235
- '${deleteMutationName}',
236
- '${entityLower}',
237
- args.where,
238
- '${deleteInputTypeName}'
239
- );
240
- return new QueryBuilder({
241
- client: this.client,
242
- operation: 'mutation',
243
- operationName: '${typeName}',
244
- fieldName: '${deleteMutationName}',
245
- document,
246
- variables,
247
- });`,
248
- });
197
+ const deleteParam = t.identifier('args');
198
+ deleteParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('DeleteArgs'), t.tsTypeParameterInstantiation([
199
+ t.tsTypeLiteral([t.tsPropertySignature(t.identifier('id'), t.tsTypeAnnotation(t.tsStringKeyword()))]),
200
+ ])));
201
+ const deleteReturnType = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('QueryBuilder'), t.tsTypeParameterInstantiation([
202
+ t.tsTypeLiteral([
203
+ t.tsPropertySignature(t.identifier(deleteMutationName), t.tsTypeAnnotation(t.tsTypeLiteral([
204
+ t.tsPropertySignature(t.identifier(entityLower), t.tsTypeAnnotation(t.tsTypeLiteral([t.tsPropertySignature(t.identifier('id'), t.tsTypeAnnotation(t.tsStringKeyword()))]))),
205
+ ]))),
206
+ ]),
207
+ ])));
208
+ const deleteArgs = [
209
+ t.stringLiteral(typeName),
210
+ t.stringLiteral(deleteMutationName),
211
+ t.stringLiteral(entityLower),
212
+ t.memberExpression(t.identifier('args'), t.identifier('where')),
213
+ t.stringLiteral(deleteInputTypeName),
214
+ ];
215
+ classBody.push(createClassMethod('delete', null, [deleteParam], deleteReturnType, buildMethodBody('buildDeleteDocument', deleteArgs, 'mutation', typeName, deleteMutationName)));
249
216
  }
250
- return {
251
- fileName,
252
- content: getFormattedOutput(sourceFile),
253
- modelName,
254
- tableName: table.name,
255
- };
217
+ const classDecl = t.classDeclaration(t.identifier(modelName), null, t.classBody(classBody));
218
+ statements.push(t.exportNamedDeclaration(classDecl));
219
+ const header = getGeneratedFileHeader(`${typeName} model for ORM client`);
220
+ const code = generateCode(statements);
221
+ return { fileName, content: header + '\n' + code, modelName, tableName: table.name };
256
222
  }
257
- // Select types with relations are now generated in input-types.ts
258
- /**
259
- * Generate all model files for a list of tables
260
- */
261
223
  export function generateAllModelFiles(tables, useSharedTypes) {
262
224
  return tables.map((table) => generateModelFile(table, useSharedTypes));
263
225
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Query hook generators using AST-based code generation
2
+ * Query hook generators using Babel AST-based code generation
3
3
  *
4
4
  * Output structure:
5
5
  * queries/
@@ -12,18 +12,10 @@ export interface GeneratedQueryFile {
12
12
  content: string;
13
13
  }
14
14
  export interface QueryGeneratorOptions {
15
- /** Whether to generate React Query hooks (default: true for backwards compatibility) */
16
15
  reactQueryEnabled?: boolean;
16
+ useCentralizedKeys?: boolean;
17
+ hasRelationships?: boolean;
17
18
  }
18
- /**
19
- * Generate list query hook file content using AST
20
- */
21
19
  export declare function generateListQueryHook(table: CleanTable, options?: QueryGeneratorOptions): GeneratedQueryFile;
22
- /**
23
- * Generate single item query hook file content using AST
24
- */
25
- export declare function generateSingleQueryHook(table: CleanTable, options?: QueryGeneratorOptions): GeneratedQueryFile;
26
- /**
27
- * Generate all query hook files for all tables
28
- */
20
+ export declare function generateSingleQueryHook(table: CleanTable, options?: QueryGeneratorOptions): GeneratedQueryFile | null;
29
21
  export declare function generateAllQueryHooks(tables: CleanTable[], options?: QueryGeneratorOptions): GeneratedQueryFile[];