@constructive-io/graphql-codegen 2.24.0 → 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.
- package/cli/codegen/babel-ast.d.ts +7 -0
- package/cli/codegen/babel-ast.js +15 -0
- package/cli/codegen/barrel.js +43 -14
- package/cli/codegen/custom-mutations.js +4 -4
- package/cli/codegen/custom-queries.js +12 -22
- package/cli/codegen/gql-ast.js +22 -1
- package/cli/codegen/index.js +1 -0
- package/cli/codegen/mutations.d.ts +2 -0
- package/cli/codegen/mutations.js +26 -13
- package/cli/codegen/orm/input-types-generator.js +22 -0
- package/cli/codegen/queries.d.ts +1 -1
- package/cli/codegen/queries.js +112 -35
- package/cli/codegen/utils.d.ts +6 -0
- package/cli/codegen/utils.js +19 -0
- package/esm/cli/codegen/babel-ast.d.ts +7 -0
- package/esm/cli/codegen/babel-ast.js +14 -0
- package/esm/cli/codegen/barrel.js +44 -15
- package/esm/cli/codegen/custom-mutations.js +5 -5
- package/esm/cli/codegen/custom-queries.js +13 -23
- package/esm/cli/codegen/gql-ast.js +23 -2
- package/esm/cli/codegen/index.js +1 -0
- package/esm/cli/codegen/mutations.d.ts +2 -0
- package/esm/cli/codegen/mutations.js +27 -14
- package/esm/cli/codegen/orm/input-types-generator.js +22 -0
- package/esm/cli/codegen/queries.d.ts +1 -1
- package/esm/cli/codegen/queries.js +114 -37
- package/esm/cli/codegen/utils.d.ts +6 -0
- package/esm/cli/codegen/utils.js +18 -0
- package/package.json +2 -2
|
@@ -44,3 +44,10 @@ export declare function typedParam(name: string, typeAnnotation: t.TSType, optio
|
|
|
44
44
|
* Create keyof typeof expression - complex nested type operators
|
|
45
45
|
*/
|
|
46
46
|
export declare function keyofTypeof(name: string): t.TSTypeOperator;
|
|
47
|
+
/**
|
|
48
|
+
* Create a call expression with TypeScript type parameters
|
|
49
|
+
*
|
|
50
|
+
* This is used to generate typed function calls like:
|
|
51
|
+
* execute<ResultType, VariablesType>(document, variables)
|
|
52
|
+
*/
|
|
53
|
+
export declare function createTypedCallExpression(callee: t.Expression, args: (t.Expression | t.SpreadElement)[], typeParams: t.TSType[]): t.CallExpression;
|
package/cli/codegen/babel-ast.js
CHANGED
|
@@ -44,6 +44,7 @@ exports.asConst = asConst;
|
|
|
44
44
|
exports.constArray = constArray;
|
|
45
45
|
exports.typedParam = typedParam;
|
|
46
46
|
exports.keyofTypeof = keyofTypeof;
|
|
47
|
+
exports.createTypedCallExpression = createTypedCallExpression;
|
|
47
48
|
/**
|
|
48
49
|
* Babel AST utilities for code generation
|
|
49
50
|
*
|
|
@@ -143,3 +144,17 @@ function keyofTypeof(name) {
|
|
|
143
144
|
keyofOp.operator = 'keyof';
|
|
144
145
|
return keyofOp;
|
|
145
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Create a call expression with TypeScript type parameters
|
|
149
|
+
*
|
|
150
|
+
* This is used to generate typed function calls like:
|
|
151
|
+
* execute<ResultType, VariablesType>(document, variables)
|
|
152
|
+
*/
|
|
153
|
+
function createTypedCallExpression(callee, args, typeParams) {
|
|
154
|
+
const call = t.callExpression(callee, args);
|
|
155
|
+
if (typeParams.length > 0) {
|
|
156
|
+
// @ts-ignore - Babel types support typeParameters on CallExpression for TS
|
|
157
|
+
call.typeParameters = t.tsTypeParameterInstantiation(typeParams);
|
|
158
|
+
}
|
|
159
|
+
return call;
|
|
160
|
+
}
|
package/cli/codegen/barrel.js
CHANGED
|
@@ -56,9 +56,12 @@ function generateQueriesBarrel(tables) {
|
|
|
56
56
|
// Export all query hooks
|
|
57
57
|
for (const table of tables) {
|
|
58
58
|
const listHookName = (0, utils_1.getListQueryHookName)(table);
|
|
59
|
-
const singleHookName = (0, utils_1.getSingleQueryHookName)(table);
|
|
60
59
|
statements.push(exportAllFrom(`./${listHookName}`));
|
|
61
|
-
|
|
60
|
+
// Only export single query hook if table has valid primary key
|
|
61
|
+
if ((0, utils_1.hasValidPrimaryKey)(table)) {
|
|
62
|
+
const singleHookName = (0, utils_1.getSingleQueryHookName)(table);
|
|
63
|
+
statements.push(exportAllFrom(`./${singleHookName}`));
|
|
64
|
+
}
|
|
62
65
|
}
|
|
63
66
|
// Add file header as leading comment on first statement
|
|
64
67
|
if (statements.length > 0) {
|
|
@@ -175,17 +178,30 @@ function generateMainBarrel(tables, options = {}) {
|
|
|
175
178
|
*/
|
|
176
179
|
function generateCustomQueriesBarrel(tables, customQueryNames) {
|
|
177
180
|
const statements = [];
|
|
181
|
+
const exportedHooks = new Set();
|
|
178
182
|
// Export all table query hooks
|
|
179
183
|
for (const table of tables) {
|
|
180
184
|
const listHookName = (0, utils_1.getListQueryHookName)(table);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
185
|
+
if (!exportedHooks.has(listHookName)) {
|
|
186
|
+
statements.push(exportAllFrom(`./${listHookName}`));
|
|
187
|
+
exportedHooks.add(listHookName);
|
|
188
|
+
}
|
|
189
|
+
// Only export single query hook if table has valid primary key
|
|
190
|
+
if ((0, utils_1.hasValidPrimaryKey)(table)) {
|
|
191
|
+
const singleHookName = (0, utils_1.getSingleQueryHookName)(table);
|
|
192
|
+
if (!exportedHooks.has(singleHookName)) {
|
|
193
|
+
statements.push(exportAllFrom(`./${singleHookName}`));
|
|
194
|
+
exportedHooks.add(singleHookName);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
184
197
|
}
|
|
185
|
-
// Add custom query hooks
|
|
198
|
+
// Add custom query hooks (skip if already exported from table hooks)
|
|
186
199
|
for (const name of customQueryNames) {
|
|
187
200
|
const hookName = (0, type_resolver_1.getOperationHookName)(name, 'query');
|
|
188
|
-
|
|
201
|
+
if (!exportedHooks.has(hookName)) {
|
|
202
|
+
statements.push(exportAllFrom(`./${hookName}`));
|
|
203
|
+
exportedHooks.add(hookName);
|
|
204
|
+
}
|
|
189
205
|
}
|
|
190
206
|
// Add file header as leading comment on first statement
|
|
191
207
|
if (statements.length > 0) {
|
|
@@ -202,24 +218,37 @@ function generateCustomQueriesBarrel(tables, customQueryNames) {
|
|
|
202
218
|
*/
|
|
203
219
|
function generateCustomMutationsBarrel(tables, customMutationNames) {
|
|
204
220
|
const statements = [];
|
|
221
|
+
const exportedHooks = new Set();
|
|
205
222
|
// Export all table mutation hooks
|
|
206
223
|
for (const table of tables) {
|
|
207
224
|
const createHookName = (0, utils_1.getCreateMutationHookName)(table);
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
225
|
+
if (!exportedHooks.has(createHookName)) {
|
|
226
|
+
statements.push(exportAllFrom(`./${createHookName}`));
|
|
227
|
+
exportedHooks.add(createHookName);
|
|
228
|
+
}
|
|
211
229
|
// Only add update/delete if they exist
|
|
212
230
|
if (table.query?.update !== null) {
|
|
213
|
-
|
|
231
|
+
const updateHookName = (0, utils_1.getUpdateMutationHookName)(table);
|
|
232
|
+
if (!exportedHooks.has(updateHookName)) {
|
|
233
|
+
statements.push(exportAllFrom(`./${updateHookName}`));
|
|
234
|
+
exportedHooks.add(updateHookName);
|
|
235
|
+
}
|
|
214
236
|
}
|
|
215
237
|
if (table.query?.delete !== null) {
|
|
216
|
-
|
|
238
|
+
const deleteHookName = (0, utils_1.getDeleteMutationHookName)(table);
|
|
239
|
+
if (!exportedHooks.has(deleteHookName)) {
|
|
240
|
+
statements.push(exportAllFrom(`./${deleteHookName}`));
|
|
241
|
+
exportedHooks.add(deleteHookName);
|
|
242
|
+
}
|
|
217
243
|
}
|
|
218
244
|
}
|
|
219
|
-
// Add custom mutation hooks
|
|
245
|
+
// Add custom mutation hooks (skip if already exported from table hooks)
|
|
220
246
|
for (const name of customMutationNames) {
|
|
221
247
|
const hookName = (0, type_resolver_1.getOperationHookName)(name, 'mutation');
|
|
222
|
-
|
|
248
|
+
if (!exportedHooks.has(hookName)) {
|
|
249
|
+
statements.push(exportAllFrom(`./${hookName}`));
|
|
250
|
+
exportedHooks.add(hookName);
|
|
251
|
+
}
|
|
223
252
|
}
|
|
224
253
|
// Add file header as leading comment on first statement
|
|
225
254
|
if (statements.length > 0) {
|
|
@@ -131,13 +131,13 @@ function generateCustomMutationHookInternal(options) {
|
|
|
131
131
|
mutationOptions.push(t.objectProperty(t.identifier('mutationKey'), t.callExpression(t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), [])));
|
|
132
132
|
}
|
|
133
133
|
if (hasArgs) {
|
|
134
|
-
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(variablesTypeName)))],
|
|
135
|
-
t.identifier(
|
|
136
|
-
t.identifier(
|
|
134
|
+
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(variablesTypeName)))], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName), t.identifier('variables')], [
|
|
135
|
+
t.tsTypeReference(t.identifier(resultTypeName)),
|
|
136
|
+
t.tsTypeReference(t.identifier(variablesTypeName)),
|
|
137
137
|
]))));
|
|
138
138
|
}
|
|
139
139
|
else {
|
|
140
|
-
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([],
|
|
140
|
+
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName)], [t.tsTypeReference(t.identifier(resultTypeName))]))));
|
|
141
141
|
}
|
|
142
142
|
mutationOptions.push(t.spreadElement(t.identifier('options')));
|
|
143
143
|
hookBodyStatements.push(t.returnStatement(t.callExpression(t.identifier('useMutation'), [t.objectExpression(mutationOptions)])));
|
|
@@ -152,9 +152,9 @@ function generateCustomQueryHook(options) {
|
|
|
152
152
|
const useQueryOptions = [];
|
|
153
153
|
if (hasArgs) {
|
|
154
154
|
useQueryOptions.push(t.objectProperty(t.identifier('queryKey'), t.callExpression(t.identifier(queryKeyName), [t.identifier('variables')])));
|
|
155
|
-
useQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([],
|
|
156
|
-
t.identifier(
|
|
157
|
-
t.identifier(
|
|
155
|
+
useQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName), t.identifier('variables')], [
|
|
156
|
+
t.tsTypeReference(t.identifier(resultTypeName)),
|
|
157
|
+
t.tsTypeReference(t.identifier(variablesTypeName)),
|
|
158
158
|
]))));
|
|
159
159
|
if (hasRequiredArgs) {
|
|
160
160
|
useQueryOptions.push(t.objectProperty(t.identifier('enabled'), t.logicalExpression('&&', t.unaryExpression('!', t.unaryExpression('!', t.identifier('variables'))), t.binaryExpression('!==', t.optionalMemberExpression(t.identifier('options'), t.identifier('enabled'), false, true), t.booleanLiteral(false)))));
|
|
@@ -162,7 +162,7 @@ function generateCustomQueryHook(options) {
|
|
|
162
162
|
}
|
|
163
163
|
else {
|
|
164
164
|
useQueryOptions.push(t.objectProperty(t.identifier('queryKey'), t.callExpression(t.identifier(queryKeyName), [])));
|
|
165
|
-
useQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([],
|
|
165
|
+
useQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName)], [t.tsTypeReference(t.identifier(resultTypeName))]))));
|
|
166
166
|
}
|
|
167
167
|
useQueryOptions.push(t.spreadElement(t.identifier('options')));
|
|
168
168
|
hookBodyStatements.push(t.returnStatement(t.callExpression(t.identifier('useQuery'), [t.objectExpression(useQueryOptions)])));
|
|
@@ -199,18 +199,13 @@ function generateCustomQueryHook(options) {
|
|
|
199
199
|
const hasRequiredArgs = operation.args.some((arg) => (0, type_resolver_1.isTypeRequired)(arg.type));
|
|
200
200
|
const fetchBodyStatements = [];
|
|
201
201
|
if (hasArgs) {
|
|
202
|
-
fetchBodyStatements.push(t.returnStatement(
|
|
203
|
-
t.identifier(
|
|
204
|
-
t.identifier(
|
|
205
|
-
t.identifier('options'),
|
|
202
|
+
fetchBodyStatements.push(t.returnStatement((0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName), t.identifier('variables'), t.identifier('options')], [
|
|
203
|
+
t.tsTypeReference(t.identifier(resultTypeName)),
|
|
204
|
+
t.tsTypeReference(t.identifier(variablesTypeName)),
|
|
206
205
|
])));
|
|
207
206
|
}
|
|
208
207
|
else {
|
|
209
|
-
fetchBodyStatements.push(t.returnStatement(
|
|
210
|
-
t.identifier(documentConstName),
|
|
211
|
-
t.identifier('undefined'),
|
|
212
|
-
t.identifier('options'),
|
|
213
|
-
])));
|
|
208
|
+
fetchBodyStatements.push(t.returnStatement((0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName), t.identifier('undefined'), t.identifier('options')], [t.tsTypeReference(t.identifier(resultTypeName))])));
|
|
214
209
|
}
|
|
215
210
|
const fetchParams = [];
|
|
216
211
|
if (hasArgs) {
|
|
@@ -238,19 +233,14 @@ function generateCustomQueryHook(options) {
|
|
|
238
233
|
const prefetchQueryOptions = [];
|
|
239
234
|
if (hasArgs) {
|
|
240
235
|
prefetchQueryOptions.push(t.objectProperty(t.identifier('queryKey'), t.callExpression(t.identifier(queryKeyName), [t.identifier('variables')])));
|
|
241
|
-
prefetchQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([],
|
|
242
|
-
t.identifier(
|
|
243
|
-
t.identifier(
|
|
244
|
-
t.identifier('options'),
|
|
236
|
+
prefetchQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName), t.identifier('variables'), t.identifier('options')], [
|
|
237
|
+
t.tsTypeReference(t.identifier(resultTypeName)),
|
|
238
|
+
t.tsTypeReference(t.identifier(variablesTypeName)),
|
|
245
239
|
]))));
|
|
246
240
|
}
|
|
247
241
|
else {
|
|
248
242
|
prefetchQueryOptions.push(t.objectProperty(t.identifier('queryKey'), t.callExpression(t.identifier(queryKeyName), [])));
|
|
249
|
-
prefetchQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([],
|
|
250
|
-
t.identifier(documentConstName),
|
|
251
|
-
t.identifier('undefined'),
|
|
252
|
-
t.identifier('options'),
|
|
253
|
-
]))));
|
|
243
|
+
prefetchQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName), t.identifier('undefined'), t.identifier('options')], [t.tsTypeReference(t.identifier(resultTypeName))]))));
|
|
254
244
|
}
|
|
255
245
|
prefetchBodyStatements.push(t.expressionStatement(t.awaitExpression(t.callExpression(t.memberExpression(t.identifier('queryClient'), t.identifier('prefetchQuery')), [t.objectExpression(prefetchQueryOptions)]))));
|
|
256
246
|
const prefetchParams = [
|
package/cli/codegen/gql-ast.js
CHANGED
|
@@ -80,22 +80,39 @@ function buildListQueryAST(config) {
|
|
|
80
80
|
const { table } = config;
|
|
81
81
|
const queryName = (0, utils_1.getAllRowsQueryName)(table);
|
|
82
82
|
const filterType = (0, utils_1.getFilterTypeName)(table);
|
|
83
|
+
const conditionType = (0, utils_1.getConditionTypeName)(table);
|
|
83
84
|
const orderByType = (0, utils_1.getOrderByTypeName)(table);
|
|
84
85
|
const scalarFields = (0, utils_1.getScalarFields)(table);
|
|
85
|
-
// Variable definitions
|
|
86
|
+
// Variable definitions - all pagination arguments from PostGraphile
|
|
86
87
|
const variableDefinitions = [
|
|
87
88
|
t.variableDefinition({
|
|
88
89
|
variable: t.variable({ name: 'first' }),
|
|
89
90
|
type: t.namedType({ type: 'Int' }),
|
|
90
91
|
}),
|
|
92
|
+
t.variableDefinition({
|
|
93
|
+
variable: t.variable({ name: 'last' }),
|
|
94
|
+
type: t.namedType({ type: 'Int' }),
|
|
95
|
+
}),
|
|
91
96
|
t.variableDefinition({
|
|
92
97
|
variable: t.variable({ name: 'offset' }),
|
|
93
98
|
type: t.namedType({ type: 'Int' }),
|
|
94
99
|
}),
|
|
100
|
+
t.variableDefinition({
|
|
101
|
+
variable: t.variable({ name: 'before' }),
|
|
102
|
+
type: t.namedType({ type: 'Cursor' }),
|
|
103
|
+
}),
|
|
104
|
+
t.variableDefinition({
|
|
105
|
+
variable: t.variable({ name: 'after' }),
|
|
106
|
+
type: t.namedType({ type: 'Cursor' }),
|
|
107
|
+
}),
|
|
95
108
|
t.variableDefinition({
|
|
96
109
|
variable: t.variable({ name: 'filter' }),
|
|
97
110
|
type: t.namedType({ type: filterType }),
|
|
98
111
|
}),
|
|
112
|
+
t.variableDefinition({
|
|
113
|
+
variable: t.variable({ name: 'condition' }),
|
|
114
|
+
type: t.namedType({ type: conditionType }),
|
|
115
|
+
}),
|
|
99
116
|
t.variableDefinition({
|
|
100
117
|
variable: t.variable({ name: 'orderBy' }),
|
|
101
118
|
type: t.listType({
|
|
@@ -106,8 +123,12 @@ function buildListQueryAST(config) {
|
|
|
106
123
|
// Query arguments
|
|
107
124
|
const args = [
|
|
108
125
|
t.argument({ name: 'first', value: t.variable({ name: 'first' }) }),
|
|
126
|
+
t.argument({ name: 'last', value: t.variable({ name: 'last' }) }),
|
|
109
127
|
t.argument({ name: 'offset', value: t.variable({ name: 'offset' }) }),
|
|
128
|
+
t.argument({ name: 'before', value: t.variable({ name: 'before' }) }),
|
|
129
|
+
t.argument({ name: 'after', value: t.variable({ name: 'after' }) }),
|
|
110
130
|
t.argument({ name: 'filter', value: t.variable({ name: 'filter' }) }),
|
|
131
|
+
t.argument({ name: 'condition', value: t.variable({ name: 'condition' }) }),
|
|
111
132
|
t.argument({ name: 'orderBy', value: t.variable({ name: 'orderBy' }) }),
|
|
112
133
|
];
|
|
113
134
|
// Field selections
|
package/cli/codegen/index.js
CHANGED
|
@@ -17,6 +17,8 @@ export interface MutationGeneratorOptions {
|
|
|
17
17
|
enumsFromSchemaTypes?: string[];
|
|
18
18
|
useCentralizedKeys?: boolean;
|
|
19
19
|
hasRelationships?: boolean;
|
|
20
|
+
/** All table type names for determining which types to import from types.ts vs schema-types.ts */
|
|
21
|
+
tableTypeNames?: Set<string>;
|
|
20
22
|
}
|
|
21
23
|
export declare function generateCreateMutationHook(table: CleanTable, options?: MutationGeneratorOptions): GeneratedMutationFile | null;
|
|
22
24
|
export declare function generateUpdateMutationHook(table: CleanTable, options?: MutationGeneratorOptions): GeneratedMutationFile | null;
|
package/cli/codegen/mutations.js
CHANGED
|
@@ -53,7 +53,7 @@ function isAutoGeneratedField(fieldName, pkFieldNames) {
|
|
|
53
53
|
return timestampPatterns.includes(name);
|
|
54
54
|
}
|
|
55
55
|
function generateCreateMutationHook(table, options = {}) {
|
|
56
|
-
const { reactQueryEnabled = true, enumsFromSchemaTypes = [], useCentralizedKeys = true, hasRelationships = false, } = options;
|
|
56
|
+
const { reactQueryEnabled = true, enumsFromSchemaTypes = [], useCentralizedKeys = true, hasRelationships = false, tableTypeNames = new Set(), } = options;
|
|
57
57
|
if (!reactQueryEnabled) {
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
@@ -67,11 +67,16 @@ function generateCreateMutationHook(table, options = {}) {
|
|
|
67
67
|
const scalarFields = (0, utils_1.getScalarFields)(table);
|
|
68
68
|
const pkFieldNames = new Set((0, utils_1.getPrimaryKeyInfo)(table).map((pk) => pk.name));
|
|
69
69
|
const usedEnums = new Set();
|
|
70
|
+
const usedTableTypes = new Set();
|
|
70
71
|
for (const field of scalarFields) {
|
|
71
72
|
const cleanType = field.type.gqlType.replace(/!/g, '');
|
|
72
73
|
if (enumSet.has(cleanType)) {
|
|
73
74
|
usedEnums.add(cleanType);
|
|
74
75
|
}
|
|
76
|
+
else if (tableTypeNames.has(cleanType) && cleanType !== typeName) {
|
|
77
|
+
// Track table types used in scalar fields (excluding the main type which is already imported)
|
|
78
|
+
usedTableTypes.add(cleanType);
|
|
79
|
+
}
|
|
75
80
|
}
|
|
76
81
|
const mutationAST = (0, gql_ast_1.buildCreateMutationAST)({ table });
|
|
77
82
|
const mutationDocument = (0, gql_ast_1.printGraphQL)(mutationAST);
|
|
@@ -86,7 +91,9 @@ function generateCreateMutationHook(table, options = {}) {
|
|
|
86
91
|
statements.push(reactQueryTypeImport);
|
|
87
92
|
const clientImport = t.importDeclaration([t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], t.stringLiteral('../client'));
|
|
88
93
|
statements.push(clientImport);
|
|
89
|
-
|
|
94
|
+
// Import the main type and any other table types used in scalar fields
|
|
95
|
+
const allTypesToImport = [typeName, ...Array.from(usedTableTypes)].sort();
|
|
96
|
+
const typesImport = t.importDeclaration(allTypesToImport.map((t_) => t.importSpecifier(t.identifier(t_), t.identifier(t_))), t.stringLiteral('../types'));
|
|
90
97
|
typesImport.importKind = 'type';
|
|
91
98
|
statements.push(typesImport);
|
|
92
99
|
if (usedEnums.size > 0) {
|
|
@@ -147,9 +154,9 @@ function generateCreateMutationHook(table, options = {}) {
|
|
|
147
154
|
if (useCentralizedKeys) {
|
|
148
155
|
mutationOptions.push(t.objectProperty(t.identifier('mutationKey'), t.callExpression(t.memberExpression(t.identifier(mutationKeysName), t.identifier('create')), [])));
|
|
149
156
|
}
|
|
150
|
-
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)))],
|
|
151
|
-
t.identifier(`${mutationName}
|
|
152
|
-
t.identifier(
|
|
157
|
+
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)))], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(`${mutationName}MutationDocument`), t.identifier('variables')], [
|
|
158
|
+
t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationResult`)),
|
|
159
|
+
t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)),
|
|
153
160
|
]))));
|
|
154
161
|
const invalidateQueryKey = useCentralizedKeys
|
|
155
162
|
? t.callExpression(t.memberExpression(t.identifier(keysName), t.identifier('lists')), [])
|
|
@@ -190,7 +197,7 @@ function generateCreateMutationHook(table, options = {}) {
|
|
|
190
197
|
};
|
|
191
198
|
}
|
|
192
199
|
function generateUpdateMutationHook(table, options = {}) {
|
|
193
|
-
const { reactQueryEnabled = true, enumsFromSchemaTypes = [], useCentralizedKeys = true, hasRelationships = false, } = options;
|
|
200
|
+
const { reactQueryEnabled = true, enumsFromSchemaTypes = [], useCentralizedKeys = true, hasRelationships = false, tableTypeNames = new Set(), } = options;
|
|
194
201
|
if (!reactQueryEnabled) {
|
|
195
202
|
return null;
|
|
196
203
|
}
|
|
@@ -209,11 +216,15 @@ function generateUpdateMutationHook(table, options = {}) {
|
|
|
209
216
|
const pkField = pkFields[0];
|
|
210
217
|
const pkFieldNames = new Set(pkFields.map((pk) => pk.name));
|
|
211
218
|
const usedEnums = new Set();
|
|
219
|
+
const usedTableTypes = new Set();
|
|
212
220
|
for (const field of scalarFields) {
|
|
213
221
|
const cleanType = field.type.gqlType.replace(/!/g, '');
|
|
214
222
|
if (enumSet.has(cleanType)) {
|
|
215
223
|
usedEnums.add(cleanType);
|
|
216
224
|
}
|
|
225
|
+
else if (tableTypeNames.has(cleanType) && cleanType !== typeName) {
|
|
226
|
+
usedTableTypes.add(cleanType);
|
|
227
|
+
}
|
|
217
228
|
}
|
|
218
229
|
const mutationAST = (0, gql_ast_1.buildUpdateMutationAST)({ table });
|
|
219
230
|
const mutationDocument = (0, gql_ast_1.printGraphQL)(mutationAST);
|
|
@@ -228,7 +239,9 @@ function generateUpdateMutationHook(table, options = {}) {
|
|
|
228
239
|
statements.push(reactQueryTypeImport);
|
|
229
240
|
const clientImport = t.importDeclaration([t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], t.stringLiteral('../client'));
|
|
230
241
|
statements.push(clientImport);
|
|
231
|
-
|
|
242
|
+
// Import the main type and any other table types used in scalar fields
|
|
243
|
+
const allTypesToImportUpdate = [typeName, ...Array.from(usedTableTypes)].sort();
|
|
244
|
+
const typesImport = t.importDeclaration(allTypesToImportUpdate.map((t_) => t.importSpecifier(t.identifier(t_), t.identifier(t_))), t.stringLiteral('../types'));
|
|
232
245
|
typesImport.importKind = 'type';
|
|
233
246
|
statements.push(typesImport);
|
|
234
247
|
if (usedEnums.size > 0) {
|
|
@@ -295,9 +308,9 @@ function generateUpdateMutationHook(table, options = {}) {
|
|
|
295
308
|
if (useCentralizedKeys) {
|
|
296
309
|
mutationOptions.push(t.objectProperty(t.identifier('mutationKey'), t.memberExpression(t.identifier(mutationKeysName), t.identifier('all'))));
|
|
297
310
|
}
|
|
298
|
-
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)))],
|
|
299
|
-
t.identifier(`${mutationName}
|
|
300
|
-
t.identifier(
|
|
311
|
+
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)))], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(`${mutationName}MutationDocument`), t.identifier('variables')], [
|
|
312
|
+
t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationResult`)),
|
|
313
|
+
t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)),
|
|
301
314
|
]))));
|
|
302
315
|
const detailQueryKey = useCentralizedKeys
|
|
303
316
|
? t.callExpression(t.memberExpression(t.identifier(keysName), t.identifier('detail')), [t.memberExpression(t.memberExpression(t.identifier('variables'), t.identifier('input')), t.identifier(pkField.name))])
|
|
@@ -417,9 +430,9 @@ function generateDeleteMutationHook(table, options = {}) {
|
|
|
417
430
|
if (useCentralizedKeys) {
|
|
418
431
|
mutationOptions.push(t.objectProperty(t.identifier('mutationKey'), t.memberExpression(t.identifier(mutationKeysName), t.identifier('all'))));
|
|
419
432
|
}
|
|
420
|
-
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)))],
|
|
421
|
-
t.identifier(`${mutationName}
|
|
422
|
-
t.identifier(
|
|
433
|
+
mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)))], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(`${mutationName}MutationDocument`), t.identifier('variables')], [
|
|
434
|
+
t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationResult`)),
|
|
435
|
+
t.tsTypeReference(t.identifier(`${(0, utils_1.ucFirst)(mutationName)}MutationVariables`)),
|
|
423
436
|
]))));
|
|
424
437
|
const detailQueryKey = useCentralizedKeys
|
|
425
438
|
? t.callExpression(t.memberExpression(t.identifier(keysName), t.identifier('detail')), [t.memberExpression(t.memberExpression(t.identifier('variables'), t.identifier('input')), t.identifier(pkField.name))])
|
|
@@ -231,6 +231,22 @@ const SCALAR_FILTER_CONFIGS = [
|
|
|
231
231
|
operators: ['equality', 'distinct', 'inArray', 'comparison', 'inet'],
|
|
232
232
|
},
|
|
233
233
|
{ name: 'FullTextFilter', tsType: 'string', operators: ['fulltext'] },
|
|
234
|
+
// List filters (for array fields like string[], int[], uuid[])
|
|
235
|
+
{
|
|
236
|
+
name: 'StringListFilter',
|
|
237
|
+
tsType: 'string[]',
|
|
238
|
+
operators: ['equality', 'distinct', 'comparison', 'listArray'],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: 'IntListFilter',
|
|
242
|
+
tsType: 'number[]',
|
|
243
|
+
operators: ['equality', 'distinct', 'comparison', 'listArray'],
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: 'UUIDListFilter',
|
|
247
|
+
tsType: 'string[]',
|
|
248
|
+
operators: ['equality', 'distinct', 'comparison', 'listArray'],
|
|
249
|
+
},
|
|
234
250
|
];
|
|
235
251
|
/**
|
|
236
252
|
* Build filter properties based on operator sets
|
|
@@ -270,6 +286,12 @@ function buildScalarFilterProperties(config) {
|
|
|
270
286
|
if (operators.includes('fulltext')) {
|
|
271
287
|
props.push({ name: 'matches', type: 'string', optional: true });
|
|
272
288
|
}
|
|
289
|
+
// List/Array operators (contains, overlaps, anyEqualTo, etc.)
|
|
290
|
+
if (operators.includes('listArray')) {
|
|
291
|
+
// Extract base type from array type (e.g., 'string[]' -> 'string')
|
|
292
|
+
const baseType = tsType.replace('[]', '');
|
|
293
|
+
props.push({ name: 'contains', type: tsType, optional: true }, { name: 'containedBy', type: tsType, optional: true }, { name: 'overlaps', type: tsType, optional: true }, { name: 'anyEqualTo', type: baseType, optional: true }, { name: 'anyNotEqualTo', type: baseType, optional: true }, { name: 'anyLessThan', type: baseType, optional: true }, { name: 'anyLessThanOrEqualTo', type: baseType, optional: true }, { name: 'anyGreaterThan', type: baseType, optional: true }, { name: 'anyGreaterThanOrEqualTo', type: baseType, optional: true });
|
|
294
|
+
}
|
|
273
295
|
return props;
|
|
274
296
|
}
|
|
275
297
|
/**
|
package/cli/codegen/queries.d.ts
CHANGED
|
@@ -17,5 +17,5 @@ export interface QueryGeneratorOptions {
|
|
|
17
17
|
hasRelationships?: boolean;
|
|
18
18
|
}
|
|
19
19
|
export declare function generateListQueryHook(table: CleanTable, options?: QueryGeneratorOptions): GeneratedQueryFile;
|
|
20
|
-
export declare function generateSingleQueryHook(table: CleanTable, options?: QueryGeneratorOptions): GeneratedQueryFile;
|
|
20
|
+
export declare function generateSingleQueryHook(table: CleanTable, options?: QueryGeneratorOptions): GeneratedQueryFile | null;
|
|
21
21
|
export declare function generateAllQueryHooks(tables: CleanTable[], options?: QueryGeneratorOptions): GeneratedQueryFile[];
|