@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.
- package/README.md +147 -2
- package/cli/codegen/babel-ast.d.ts +46 -0
- package/cli/codegen/babel-ast.js +145 -0
- package/cli/codegen/barrel.d.ts +7 -2
- package/cli/codegen/barrel.js +159 -97
- package/cli/codegen/client.js +61 -0
- package/cli/codegen/custom-mutations.d.ts +2 -12
- package/cli/codegen/custom-mutations.js +116 -124
- package/cli/codegen/custom-queries.d.ts +2 -10
- package/cli/codegen/custom-queries.js +246 -335
- package/cli/codegen/index.d.ts +3 -0
- package/cli/codegen/index.js +72 -3
- package/cli/codegen/invalidation.d.ts +20 -0
- package/cli/codegen/invalidation.js +327 -0
- package/cli/codegen/mutation-keys.d.ts +24 -0
- package/cli/codegen/mutation-keys.js +247 -0
- package/cli/codegen/mutations.d.ts +3 -19
- package/cli/codegen/mutations.js +372 -383
- package/cli/codegen/orm/barrel.d.ts +1 -1
- package/cli/codegen/orm/barrel.js +42 -10
- package/cli/codegen/orm/client-generator.d.ts +1 -19
- package/cli/codegen/orm/client-generator.js +108 -77
- package/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
- package/cli/codegen/orm/custom-ops-generator.js +192 -235
- package/cli/codegen/orm/input-types-generator.d.ts +13 -1
- package/cli/codegen/orm/input-types-generator.js +403 -147
- package/cli/codegen/orm/model-generator.d.ts +1 -19
- package/cli/codegen/orm/model-generator.js +229 -234
- package/cli/codegen/queries.d.ts +3 -11
- package/cli/codegen/queries.js +582 -389
- package/cli/codegen/query-keys.d.ts +15 -0
- package/cli/codegen/query-keys.js +477 -0
- package/cli/codegen/scalars.js +1 -0
- package/cli/codegen/schema-types-generator.d.ts +15 -10
- package/cli/codegen/schema-types-generator.js +87 -175
- package/cli/codegen/type-resolver.d.ts +1 -30
- package/cli/codegen/type-resolver.js +0 -53
- package/cli/codegen/types.d.ts +1 -1
- package/cli/codegen/types.js +76 -21
- package/cli/commands/generate.js +1 -0
- package/cli/index.js +1 -0
- package/esm/cli/codegen/babel-ast.d.ts +46 -0
- package/esm/cli/codegen/babel-ast.js +97 -0
- package/esm/cli/codegen/barrel.d.ts +7 -2
- package/esm/cli/codegen/barrel.js +126 -97
- package/esm/cli/codegen/client.js +61 -0
- package/esm/cli/codegen/custom-mutations.d.ts +2 -12
- package/esm/cli/codegen/custom-mutations.js +83 -124
- package/esm/cli/codegen/custom-queries.d.ts +2 -10
- package/esm/cli/codegen/custom-queries.js +214 -336
- package/esm/cli/codegen/index.d.ts +3 -0
- package/esm/cli/codegen/index.js +68 -2
- package/esm/cli/codegen/invalidation.d.ts +20 -0
- package/esm/cli/codegen/invalidation.js +291 -0
- package/esm/cli/codegen/mutation-keys.d.ts +24 -0
- package/esm/cli/codegen/mutation-keys.js +211 -0
- package/esm/cli/codegen/mutations.d.ts +3 -19
- package/esm/cli/codegen/mutations.js +340 -384
- package/esm/cli/codegen/orm/barrel.d.ts +1 -1
- package/esm/cli/codegen/orm/barrel.js +10 -11
- package/esm/cli/codegen/orm/client-generator.d.ts +1 -19
- package/esm/cli/codegen/orm/client-generator.js +76 -78
- package/esm/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
- package/esm/cli/codegen/orm/custom-ops-generator.js +160 -236
- package/esm/cli/codegen/orm/input-types-generator.d.ts +13 -1
- package/esm/cli/codegen/orm/input-types-generator.js +371 -148
- package/esm/cli/codegen/orm/model-generator.d.ts +1 -19
- package/esm/cli/codegen/orm/model-generator.js +197 -235
- package/esm/cli/codegen/queries.d.ts +3 -11
- package/esm/cli/codegen/queries.js +550 -390
- package/esm/cli/codegen/query-keys.d.ts +15 -0
- package/esm/cli/codegen/query-keys.js +441 -0
- package/esm/cli/codegen/scalars.js +1 -0
- package/esm/cli/codegen/schema-types-generator.d.ts +15 -10
- package/esm/cli/codegen/schema-types-generator.js +54 -175
- package/esm/cli/codegen/type-resolver.d.ts +1 -30
- package/esm/cli/codegen/type-resolver.js +0 -49
- package/esm/cli/codegen/types.d.ts +1 -1
- package/esm/cli/codegen/types.js +44 -22
- package/esm/cli/commands/generate.js +1 -0
- package/esm/cli/index.js +1 -0
- package/esm/types/config.d.ts +75 -0
- package/esm/types/config.js +19 -1
- package/package.json +6 -4
- package/types/config.d.ts +75 -0
- package/types/config.js +20 -2
- package/cli/codegen/ts-ast.d.ts +0 -124
- package/cli/codegen/ts-ast.js +0 -280
- package/esm/cli/codegen/ts-ast.d.ts +0 -124
- package/esm/cli/codegen/ts-ast.js +0 -260
|
@@ -1,385 +1,295 @@
|
|
|
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.generateCustomQueryHook = generateCustomQueryHook;
|
|
4
37
|
exports.generateAllCustomQueryHooks = generateAllCustomQueryHooks;
|
|
5
|
-
const
|
|
38
|
+
const t = __importStar(require("@babel/types"));
|
|
39
|
+
const babel_ast_1 = require("./babel-ast");
|
|
6
40
|
const schema_gql_ast_1 = require("./schema-gql-ast");
|
|
7
41
|
const type_resolver_1 = require("./type-resolver");
|
|
8
42
|
const utils_1 = require("./utils");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
43
|
+
function generateVariablesProperties(args, tracker) {
|
|
44
|
+
return args.map((arg) => ({
|
|
45
|
+
name: arg.name,
|
|
46
|
+
type: (0, type_resolver_1.typeRefToTsType)(arg.type, tracker),
|
|
47
|
+
optional: !(0, type_resolver_1.isTypeRequired)(arg.type),
|
|
48
|
+
docs: arg.description ? [arg.description] : undefined,
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
12
51
|
function generateCustomQueryHook(options) {
|
|
13
|
-
const { operation, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true, tableTypeNames } = options;
|
|
14
|
-
const project = (0, ts_ast_1.createProject)();
|
|
52
|
+
const { operation, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true, tableTypeNames, useCentralizedKeys = true, } = options;
|
|
15
53
|
const hookName = (0, type_resolver_1.getOperationHookName)(operation.name, 'query');
|
|
16
54
|
const fileName = (0, type_resolver_1.getOperationFileName)(operation.name, 'query');
|
|
17
55
|
const variablesTypeName = (0, type_resolver_1.getOperationVariablesTypeName)(operation.name, 'query');
|
|
18
56
|
const resultTypeName = (0, type_resolver_1.getOperationResultTypeName)(operation.name, 'query');
|
|
19
57
|
const documentConstName = (0, type_resolver_1.getDocumentConstName)(operation.name, 'query');
|
|
20
58
|
const queryKeyName = (0, type_resolver_1.getQueryKeyName)(operation.name);
|
|
21
|
-
// Create type tracker to collect referenced types (with table type awareness)
|
|
22
59
|
const tracker = (0, type_resolver_1.createTypeTracker)({ tableTypeNames });
|
|
23
|
-
// Generate GraphQL document
|
|
24
60
|
const queryDocument = (0, schema_gql_ast_1.buildCustomQueryString)({
|
|
25
61
|
operation,
|
|
26
62
|
typeRegistry,
|
|
27
63
|
maxDepth,
|
|
28
64
|
skipQueryField,
|
|
29
65
|
});
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
: `Custom query functions for ${operation.name}`;
|
|
35
|
-
sourceFile.insertText(0, (0, ts_ast_1.createFileHeader)(headerText) + '\n\n');
|
|
36
|
-
// Generate variables interface if there are arguments (with tracking)
|
|
37
|
-
let variablesProps = [];
|
|
38
|
-
if (operation.args.length > 0) {
|
|
39
|
-
variablesProps = generateVariablesProperties(operation.args, tracker);
|
|
40
|
-
}
|
|
41
|
-
// Generate result interface (with tracking)
|
|
66
|
+
const statements = [];
|
|
67
|
+
const variablesProps = operation.args.length > 0
|
|
68
|
+
? generateVariablesProperties(operation.args, tracker)
|
|
69
|
+
: [];
|
|
42
70
|
const resultType = (0, type_resolver_1.typeRefToTsType)(operation.returnType, tracker);
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
];
|
|
46
|
-
// Get importable types from tracker (separated by source)
|
|
47
|
-
const schemaTypes = tracker.getImportableTypes(); // From schema-types.ts
|
|
48
|
-
const tableTypes = tracker.getTableTypes(); // From types.ts
|
|
49
|
-
// Add imports - conditionally include React Query imports
|
|
50
|
-
const imports = [];
|
|
71
|
+
const schemaTypes = tracker.getImportableTypes();
|
|
72
|
+
const tableTypes = tracker.getTableTypes();
|
|
51
73
|
if (reactQueryEnabled) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
74
|
+
const reactQueryImport = t.importDeclaration([t.importSpecifier(t.identifier('useQuery'), t.identifier('useQuery'))], t.stringLiteral('@tanstack/react-query'));
|
|
75
|
+
statements.push(reactQueryImport);
|
|
76
|
+
const reactQueryTypeImport = t.importDeclaration([
|
|
77
|
+
t.importSpecifier(t.identifier('UseQueryOptions'), t.identifier('UseQueryOptions')),
|
|
78
|
+
t.importSpecifier(t.identifier('QueryClient'), t.identifier('QueryClient')),
|
|
79
|
+
], t.stringLiteral('@tanstack/react-query'));
|
|
80
|
+
reactQueryTypeImport.importKind = 'type';
|
|
81
|
+
statements.push(reactQueryTypeImport);
|
|
57
82
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// Add types.ts import for table entity types
|
|
83
|
+
const clientImport = t.importDeclaration([t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], t.stringLiteral('../client'));
|
|
84
|
+
statements.push(clientImport);
|
|
85
|
+
const clientTypeImport = t.importDeclaration([t.importSpecifier(t.identifier('ExecuteOptions'), t.identifier('ExecuteOptions'))], t.stringLiteral('../client'));
|
|
86
|
+
clientTypeImport.importKind = 'type';
|
|
87
|
+
statements.push(clientTypeImport);
|
|
64
88
|
if (tableTypes.length > 0) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}));
|
|
89
|
+
const typesImport = t.importDeclaration(tableTypes.map((tt) => t.importSpecifier(t.identifier(tt), t.identifier(tt))), t.stringLiteral('../types'));
|
|
90
|
+
typesImport.importKind = 'type';
|
|
91
|
+
statements.push(typesImport);
|
|
69
92
|
}
|
|
70
|
-
// Add schema-types import for Input/Payload/Enum types
|
|
71
93
|
if (schemaTypes.length > 0) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}));
|
|
94
|
+
const schemaTypesImport = t.importDeclaration(schemaTypes.map((st) => t.importSpecifier(t.identifier(st), t.identifier(st))), t.stringLiteral('../schema-types'));
|
|
95
|
+
schemaTypesImport.importKind = 'type';
|
|
96
|
+
statements.push(schemaTypesImport);
|
|
76
97
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
docs: ['GraphQL query document'],
|
|
81
|
-
}));
|
|
82
|
-
// Add variables interface
|
|
83
|
-
if (operation.args.length > 0) {
|
|
84
|
-
sourceFile.addInterface((0, ts_ast_1.createInterface)(variablesTypeName, variablesProps));
|
|
98
|
+
if (useCentralizedKeys) {
|
|
99
|
+
const queryKeyImport = t.importDeclaration([t.importSpecifier(t.identifier('customQueryKeys'), t.identifier('customQueryKeys'))], t.stringLiteral('../query-keys'));
|
|
100
|
+
statements.push(queryKeyImport);
|
|
85
101
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
const queryDocConst = t.variableDeclaration('const', [
|
|
103
|
+
t.variableDeclarator(t.identifier(documentConstName), t.templateLiteral([t.templateElement({ raw: '\n' + queryDocument, cooked: '\n' + queryDocument }, true)], [])),
|
|
104
|
+
]);
|
|
105
|
+
const queryDocExport = t.exportNamedDeclaration(queryDocConst);
|
|
106
|
+
(0, babel_ast_1.addJSDocComment)(queryDocExport, ['GraphQL query document']);
|
|
107
|
+
statements.push(queryDocExport);
|
|
89
108
|
if (operation.args.length > 0) {
|
|
90
|
-
|
|
91
|
-
|
|
109
|
+
const variablesInterfaceProps = variablesProps.map((vp) => {
|
|
110
|
+
const prop = t.tsPropertySignature(t.identifier(vp.name), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(vp.type))));
|
|
111
|
+
prop.optional = vp.optional;
|
|
112
|
+
return prop;
|
|
113
|
+
});
|
|
114
|
+
const variablesInterface = t.tsInterfaceDeclaration(t.identifier(variablesTypeName), null, null, t.tsInterfaceBody(variablesInterfaceProps));
|
|
115
|
+
statements.push(t.exportNamedDeclaration(variablesInterface));
|
|
116
|
+
}
|
|
117
|
+
const resultInterfaceBody = t.tsInterfaceBody([
|
|
118
|
+
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(resultType)))),
|
|
119
|
+
]);
|
|
120
|
+
const resultInterface = t.tsInterfaceDeclaration(t.identifier(resultTypeName), null, null, resultInterfaceBody);
|
|
121
|
+
statements.push(t.exportNamedDeclaration(resultInterface));
|
|
122
|
+
if (useCentralizedKeys) {
|
|
123
|
+
const queryKeyConst = t.variableDeclaration('const', [
|
|
124
|
+
t.variableDeclarator(t.identifier(queryKeyName), t.memberExpression(t.identifier('customQueryKeys'), t.identifier(operation.name))),
|
|
125
|
+
]);
|
|
126
|
+
const queryKeyExport = t.exportNamedDeclaration(queryKeyConst);
|
|
127
|
+
(0, babel_ast_1.addJSDocComment)(queryKeyExport, ['Query key factory - re-exported from query-keys.ts']);
|
|
128
|
+
statements.push(queryKeyExport);
|
|
129
|
+
}
|
|
130
|
+
else if (operation.args.length > 0) {
|
|
131
|
+
const queryKeyArrow = t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(variablesTypeName)), true)], t.tsAsExpression(t.arrayExpression([t.stringLiteral(operation.name), t.identifier('variables')]), t.tsTypeReference(t.identifier('const'))));
|
|
132
|
+
const queryKeyConst = t.variableDeclaration('const', [
|
|
133
|
+
t.variableDeclarator(t.identifier(queryKeyName), queryKeyArrow),
|
|
134
|
+
]);
|
|
135
|
+
const queryKeyExport = t.exportNamedDeclaration(queryKeyConst);
|
|
136
|
+
(0, babel_ast_1.addJSDocComment)(queryKeyExport, ['Query key factory for caching']);
|
|
137
|
+
statements.push(queryKeyExport);
|
|
92
138
|
}
|
|
93
139
|
else {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
140
|
+
const queryKeyArrow = t.arrowFunctionExpression([], t.tsAsExpression(t.arrayExpression([t.stringLiteral(operation.name)]), t.tsTypeReference(t.identifier('const'))));
|
|
141
|
+
const queryKeyConst = t.variableDeclaration('const', [
|
|
142
|
+
t.variableDeclarator(t.identifier(queryKeyName), queryKeyArrow),
|
|
143
|
+
]);
|
|
144
|
+
const queryKeyExport = t.exportNamedDeclaration(queryKeyConst);
|
|
145
|
+
(0, babel_ast_1.addJSDocComment)(queryKeyExport, ['Query key factory for caching']);
|
|
146
|
+
statements.push(queryKeyExport);
|
|
97
147
|
}
|
|
98
|
-
// Generate hook function (only if React Query is enabled)
|
|
99
148
|
if (reactQueryEnabled) {
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
149
|
+
const hasArgs = operation.args.length > 0;
|
|
150
|
+
const hasRequiredArgs = operation.args.some((arg) => (0, type_resolver_1.isTypeRequired)(arg.type));
|
|
151
|
+
const hookBodyStatements = [];
|
|
152
|
+
const useQueryOptions = [];
|
|
153
|
+
if (hasArgs) {
|
|
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([], t.callExpression(t.identifier('execute'), [
|
|
156
|
+
t.identifier(documentConstName),
|
|
157
|
+
t.identifier('variables'),
|
|
158
|
+
]))));
|
|
159
|
+
if (hasRequiredArgs) {
|
|
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)))));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
useQueryOptions.push(t.objectProperty(t.identifier('queryKey'), t.callExpression(t.identifier(queryKeyName), [])));
|
|
165
|
+
useQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([], t.callExpression(t.identifier('execute'), [t.identifier(documentConstName)]))));
|
|
166
|
+
}
|
|
167
|
+
useQueryOptions.push(t.spreadElement(t.identifier('options')));
|
|
168
|
+
hookBodyStatements.push(t.returnStatement(t.callExpression(t.identifier('useQuery'), [t.objectExpression(useQueryOptions)])));
|
|
169
|
+
const hookParams = [];
|
|
170
|
+
if (hasArgs) {
|
|
171
|
+
hookParams.push((0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(variablesTypeName)), !hasRequiredArgs));
|
|
172
|
+
}
|
|
173
|
+
const optionsTypeStr = `Omit<UseQueryOptions<${resultTypeName}, Error>, 'queryKey' | 'queryFn'>`;
|
|
174
|
+
const optionsParam = t.identifier('options');
|
|
175
|
+
optionsParam.optional = true;
|
|
176
|
+
optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(optionsTypeStr)));
|
|
177
|
+
hookParams.push(optionsParam);
|
|
178
|
+
const hookFunc = t.functionDeclaration(t.identifier(hookName), hookParams, t.blockStatement(hookBodyStatements));
|
|
179
|
+
const hookExport = t.exportNamedDeclaration(hookFunc);
|
|
180
|
+
const description = operation.description || `Query hook for ${operation.name}`;
|
|
181
|
+
const argNames = operation.args.map((a) => a.name).join(', ');
|
|
182
|
+
const exampleCall = hasArgs ? `${hookName}({ ${argNames} })` : `${hookName}()`;
|
|
183
|
+
(0, babel_ast_1.addJSDocComment)(hookExport, [
|
|
184
|
+
description,
|
|
185
|
+
'',
|
|
186
|
+
'@example',
|
|
187
|
+
'```tsx',
|
|
188
|
+
`const { data, isLoading } = ${exampleCall};`,
|
|
189
|
+
'',
|
|
190
|
+
`if (data?.${operation.name}) {`,
|
|
191
|
+
` console.log(data.${operation.name});`,
|
|
192
|
+
'}',
|
|
193
|
+
'```',
|
|
194
|
+
]);
|
|
195
|
+
statements.push(hookExport);
|
|
110
196
|
}
|
|
111
|
-
// Add standalone functions section
|
|
112
|
-
sourceFile.addStatements('\n// ============================================================================');
|
|
113
|
-
sourceFile.addStatements('// Standalone Functions (non-React)');
|
|
114
|
-
sourceFile.addStatements('// ============================================================================\n');
|
|
115
|
-
// Generate standalone fetch function
|
|
116
197
|
const fetchFnName = `fetch${(0, utils_1.ucFirst)(operation.name)}Query`;
|
|
117
|
-
const fetchParams = generateFetchParameters(operation, variablesTypeName);
|
|
118
|
-
const fetchBody = generateFetchBody(operation, documentConstName, variablesTypeName, resultTypeName);
|
|
119
|
-
const fetchDoc = generateFetchDoc(operation, fetchFnName);
|
|
120
|
-
sourceFile.addFunction({
|
|
121
|
-
name: fetchFnName,
|
|
122
|
-
isExported: true,
|
|
123
|
-
isAsync: true,
|
|
124
|
-
parameters: fetchParams,
|
|
125
|
-
returnType: `Promise<${resultTypeName}>`,
|
|
126
|
-
statements: fetchBody,
|
|
127
|
-
docs: [{ description: fetchDoc }],
|
|
128
|
-
});
|
|
129
|
-
// Generate prefetch function (only if React Query is enabled)
|
|
130
|
-
if (reactQueryEnabled) {
|
|
131
|
-
const prefetchFnName = `prefetch${(0, utils_1.ucFirst)(operation.name)}Query`;
|
|
132
|
-
const prefetchParams = generatePrefetchParameters(operation, variablesTypeName);
|
|
133
|
-
const prefetchBody = generatePrefetchBody(operation, documentConstName, queryKeyName, variablesTypeName, resultTypeName);
|
|
134
|
-
const prefetchDoc = generatePrefetchDoc(operation, prefetchFnName);
|
|
135
|
-
sourceFile.addFunction({
|
|
136
|
-
name: prefetchFnName,
|
|
137
|
-
isExported: true,
|
|
138
|
-
isAsync: true,
|
|
139
|
-
parameters: prefetchParams,
|
|
140
|
-
returnType: 'Promise<void>',
|
|
141
|
-
statements: prefetchBody,
|
|
142
|
-
docs: [{ description: prefetchDoc }],
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
fileName,
|
|
147
|
-
content: (0, ts_ast_1.getFormattedOutput)(sourceFile),
|
|
148
|
-
operationName: operation.name,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
// ============================================================================
|
|
152
|
-
// Helper functions
|
|
153
|
-
// ============================================================================
|
|
154
|
-
/**
|
|
155
|
-
* Generate interface properties from CleanArguments
|
|
156
|
-
*/
|
|
157
|
-
function generateVariablesProperties(args, tracker) {
|
|
158
|
-
return args.map((arg) => ({
|
|
159
|
-
name: arg.name,
|
|
160
|
-
type: (0, type_resolver_1.typeRefToTsType)(arg.type, tracker),
|
|
161
|
-
optional: !(0, type_resolver_1.isTypeRequired)(arg.type),
|
|
162
|
-
docs: arg.description ? [arg.description] : undefined,
|
|
163
|
-
}));
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Generate hook function parameters
|
|
167
|
-
*/
|
|
168
|
-
function generateHookParameters(operation, variablesTypeName, resultTypeName) {
|
|
169
|
-
const params = [];
|
|
170
|
-
// Add variables parameter if there are required args
|
|
171
|
-
const hasRequiredArgs = operation.args.some((arg) => (0, type_resolver_1.isTypeRequired)(arg.type));
|
|
172
|
-
if (operation.args.length > 0) {
|
|
173
|
-
params.push({
|
|
174
|
-
name: 'variables',
|
|
175
|
-
type: variablesTypeName,
|
|
176
|
-
hasQuestionToken: !hasRequiredArgs,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
// Add options parameter
|
|
180
|
-
params.push({
|
|
181
|
-
name: 'options',
|
|
182
|
-
type: `Omit<UseQueryOptions<${resultTypeName}, Error>, 'queryKey' | 'queryFn'>`,
|
|
183
|
-
hasQuestionToken: true,
|
|
184
|
-
});
|
|
185
|
-
return params;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Generate hook function body
|
|
189
|
-
*/
|
|
190
|
-
function generateHookBody(operation, documentConstName, queryKeyName, variablesTypeName, resultTypeName) {
|
|
191
198
|
const hasArgs = operation.args.length > 0;
|
|
192
199
|
const hasRequiredArgs = operation.args.some((arg) => (0, type_resolver_1.isTypeRequired)(arg.type));
|
|
200
|
+
const fetchBodyStatements = [];
|
|
193
201
|
if (hasArgs) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
queryKey: ${queryKeyName}(variables),
|
|
200
|
-
queryFn: () => execute<${resultTypeName}, ${variablesTypeName}>(
|
|
201
|
-
${documentConstName},
|
|
202
|
-
variables
|
|
203
|
-
),
|
|
204
|
-
${enabledCondition}
|
|
205
|
-
...options,
|
|
206
|
-
});`;
|
|
202
|
+
fetchBodyStatements.push(t.returnStatement(t.callExpression(t.identifier('execute'), [
|
|
203
|
+
t.identifier(documentConstName),
|
|
204
|
+
t.identifier('variables'),
|
|
205
|
+
t.identifier('options'),
|
|
206
|
+
])));
|
|
207
207
|
}
|
|
208
208
|
else {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
});`;
|
|
209
|
+
fetchBodyStatements.push(t.returnStatement(t.callExpression(t.identifier('execute'), [
|
|
210
|
+
t.identifier(documentConstName),
|
|
211
|
+
t.identifier('undefined'),
|
|
212
|
+
t.identifier('options'),
|
|
213
|
+
])));
|
|
215
214
|
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Generate hook JSDoc documentation
|
|
219
|
-
*/
|
|
220
|
-
function generateHookDoc(operation, hookName) {
|
|
221
|
-
const description = operation.description
|
|
222
|
-
? operation.description
|
|
223
|
-
: `Query hook for ${operation.name}`;
|
|
224
|
-
const hasArgs = operation.args.length > 0;
|
|
225
|
-
let example;
|
|
215
|
+
const fetchParams = [];
|
|
226
216
|
if (hasArgs) {
|
|
227
|
-
|
|
228
|
-
example = `
|
|
229
|
-
@example
|
|
230
|
-
\`\`\`tsx
|
|
231
|
-
const { data, isLoading } = ${hookName}({ ${argNames} });
|
|
232
|
-
|
|
233
|
-
if (data?.${operation.name}) {
|
|
234
|
-
console.log(data.${operation.name});
|
|
235
|
-
}
|
|
236
|
-
\`\`\``;
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
example = `
|
|
240
|
-
@example
|
|
241
|
-
\`\`\`tsx
|
|
242
|
-
const { data, isLoading } = ${hookName}();
|
|
243
|
-
|
|
244
|
-
if (data?.${operation.name}) {
|
|
245
|
-
console.log(data.${operation.name});
|
|
246
|
-
}
|
|
247
|
-
\`\`\``;
|
|
217
|
+
fetchParams.push((0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(variablesTypeName)), !hasRequiredArgs));
|
|
248
218
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
\`\`\``;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Generate prefetch function parameters
|
|
314
|
-
*/
|
|
315
|
-
function generatePrefetchParameters(operation, variablesTypeName) {
|
|
316
|
-
const params = [
|
|
317
|
-
{ name: 'queryClient', type: 'QueryClient' },
|
|
318
|
-
];
|
|
319
|
-
if (operation.args.length > 0) {
|
|
320
|
-
const hasRequiredArgs = operation.args.some((arg) => (0, type_resolver_1.isTypeRequired)(arg.type));
|
|
321
|
-
params.push({
|
|
322
|
-
name: 'variables',
|
|
323
|
-
type: variablesTypeName,
|
|
324
|
-
hasQuestionToken: !hasRequiredArgs,
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
params.push({
|
|
328
|
-
name: 'options',
|
|
329
|
-
type: 'ExecuteOptions',
|
|
330
|
-
hasQuestionToken: true,
|
|
331
|
-
});
|
|
332
|
-
return params;
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Generate prefetch function body
|
|
336
|
-
*/
|
|
337
|
-
function generatePrefetchBody(operation, documentConstName, queryKeyName, variablesTypeName, resultTypeName) {
|
|
338
|
-
if (operation.args.length > 0) {
|
|
339
|
-
return `await queryClient.prefetchQuery({
|
|
340
|
-
queryKey: ${queryKeyName}(variables),
|
|
341
|
-
queryFn: () => execute<${resultTypeName}, ${variablesTypeName}>(
|
|
342
|
-
${documentConstName},
|
|
343
|
-
variables,
|
|
344
|
-
options
|
|
345
|
-
),
|
|
346
|
-
});`;
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
return `await queryClient.prefetchQuery({
|
|
350
|
-
queryKey: ${queryKeyName}(),
|
|
351
|
-
queryFn: () => execute<${resultTypeName}>(${documentConstName}, undefined, options),
|
|
352
|
-
});`;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Generate prefetch function documentation
|
|
357
|
-
*/
|
|
358
|
-
function generatePrefetchDoc(operation, fnName) {
|
|
359
|
-
const description = `Prefetch ${operation.name} for SSR or cache warming`;
|
|
360
|
-
if (operation.args.length > 0) {
|
|
361
|
-
const argNames = operation.args.map((a) => a.name).join(', ');
|
|
362
|
-
return `${description}
|
|
363
|
-
|
|
364
|
-
@example
|
|
365
|
-
\`\`\`ts
|
|
366
|
-
await ${fnName}(queryClient, { ${argNames} });
|
|
367
|
-
\`\`\``;
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
return `${description}
|
|
371
|
-
|
|
372
|
-
@example
|
|
373
|
-
\`\`\`ts
|
|
374
|
-
await ${fnName}(queryClient);
|
|
375
|
-
\`\`\``;
|
|
219
|
+
fetchParams.push((0, babel_ast_1.typedParam)('options', t.tsTypeReference(t.identifier('ExecuteOptions')), true));
|
|
220
|
+
const fetchFunc = t.functionDeclaration(t.identifier(fetchFnName), fetchParams, t.blockStatement(fetchBodyStatements));
|
|
221
|
+
fetchFunc.async = true;
|
|
222
|
+
fetchFunc.returnType = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Promise'), t.tsTypeParameterInstantiation([t.tsTypeReference(t.identifier(resultTypeName))])));
|
|
223
|
+
const fetchExport = t.exportNamedDeclaration(fetchFunc);
|
|
224
|
+
const argNames = operation.args.map((a) => a.name).join(', ');
|
|
225
|
+
const fetchExampleCall = hasArgs ? `${fetchFnName}({ ${argNames} })` : `${fetchFnName}()`;
|
|
226
|
+
(0, babel_ast_1.addJSDocComment)(fetchExport, [
|
|
227
|
+
`Fetch ${operation.name} without React hooks`,
|
|
228
|
+
'',
|
|
229
|
+
'@example',
|
|
230
|
+
'```ts',
|
|
231
|
+
`const data = await ${fetchExampleCall};`,
|
|
232
|
+
'```',
|
|
233
|
+
]);
|
|
234
|
+
statements.push(fetchExport);
|
|
235
|
+
if (reactQueryEnabled) {
|
|
236
|
+
const prefetchFnName = `prefetch${(0, utils_1.ucFirst)(operation.name)}Query`;
|
|
237
|
+
const prefetchBodyStatements = [];
|
|
238
|
+
const prefetchQueryOptions = [];
|
|
239
|
+
if (hasArgs) {
|
|
240
|
+
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([], t.callExpression(t.identifier('execute'), [
|
|
242
|
+
t.identifier(documentConstName),
|
|
243
|
+
t.identifier('variables'),
|
|
244
|
+
t.identifier('options'),
|
|
245
|
+
]))));
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
prefetchQueryOptions.push(t.objectProperty(t.identifier('queryKey'), t.callExpression(t.identifier(queryKeyName), [])));
|
|
249
|
+
prefetchQueryOptions.push(t.objectProperty(t.identifier('queryFn'), t.arrowFunctionExpression([], t.callExpression(t.identifier('execute'), [
|
|
250
|
+
t.identifier(documentConstName),
|
|
251
|
+
t.identifier('undefined'),
|
|
252
|
+
t.identifier('options'),
|
|
253
|
+
]))));
|
|
254
|
+
}
|
|
255
|
+
prefetchBodyStatements.push(t.expressionStatement(t.awaitExpression(t.callExpression(t.memberExpression(t.identifier('queryClient'), t.identifier('prefetchQuery')), [t.objectExpression(prefetchQueryOptions)]))));
|
|
256
|
+
const prefetchParams = [
|
|
257
|
+
(0, babel_ast_1.typedParam)('queryClient', t.tsTypeReference(t.identifier('QueryClient'))),
|
|
258
|
+
];
|
|
259
|
+
if (hasArgs) {
|
|
260
|
+
prefetchParams.push((0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(variablesTypeName)), !hasRequiredArgs));
|
|
261
|
+
}
|
|
262
|
+
prefetchParams.push((0, babel_ast_1.typedParam)('options', t.tsTypeReference(t.identifier('ExecuteOptions')), true));
|
|
263
|
+
const prefetchFunc = t.functionDeclaration(t.identifier(prefetchFnName), prefetchParams, t.blockStatement(prefetchBodyStatements));
|
|
264
|
+
prefetchFunc.async = true;
|
|
265
|
+
prefetchFunc.returnType = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Promise'), t.tsTypeParameterInstantiation([t.tsVoidKeyword()])));
|
|
266
|
+
const prefetchExport = t.exportNamedDeclaration(prefetchFunc);
|
|
267
|
+
const prefetchExampleCall = hasArgs
|
|
268
|
+
? `${prefetchFnName}(queryClient, { ${argNames} })`
|
|
269
|
+
: `${prefetchFnName}(queryClient)`;
|
|
270
|
+
(0, babel_ast_1.addJSDocComment)(prefetchExport, [
|
|
271
|
+
`Prefetch ${operation.name} for SSR or cache warming`,
|
|
272
|
+
'',
|
|
273
|
+
'@example',
|
|
274
|
+
'```ts',
|
|
275
|
+
`await ${prefetchExampleCall};`,
|
|
276
|
+
'```',
|
|
277
|
+
]);
|
|
278
|
+
statements.push(prefetchExport);
|
|
376
279
|
}
|
|
280
|
+
const code = (0, babel_ast_1.generateCode)(statements);
|
|
281
|
+
const headerText = reactQueryEnabled
|
|
282
|
+
? `Custom query hook for ${operation.name}`
|
|
283
|
+
: `Custom query functions for ${operation.name}`;
|
|
284
|
+
const content = (0, utils_1.getGeneratedFileHeader)(headerText) + '\n\n' + code;
|
|
285
|
+
return {
|
|
286
|
+
fileName,
|
|
287
|
+
content,
|
|
288
|
+
operationName: operation.name,
|
|
289
|
+
};
|
|
377
290
|
}
|
|
378
|
-
/**
|
|
379
|
-
* Generate all custom query hook files
|
|
380
|
-
*/
|
|
381
291
|
function generateAllCustomQueryHooks(options) {
|
|
382
|
-
const { operations, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true, tableTypeNames } = options;
|
|
292
|
+
const { operations, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true, tableTypeNames, useCentralizedKeys = true, } = options;
|
|
383
293
|
return operations
|
|
384
294
|
.filter((op) => op.kind === 'query')
|
|
385
295
|
.map((operation) => generateCustomQueryHook({
|
|
@@ -389,5 +299,6 @@ function generateAllCustomQueryHooks(options) {
|
|
|
389
299
|
skipQueryField,
|
|
390
300
|
reactQueryEnabled,
|
|
391
301
|
tableTypeNames,
|
|
302
|
+
useCentralizedKeys,
|
|
392
303
|
}));
|
|
393
304
|
}
|
package/cli/codegen/index.d.ts
CHANGED
|
@@ -69,3 +69,6 @@ export { generateAllMutationHooks, generateCreateMutationHook, generateUpdateMut
|
|
|
69
69
|
export { generateAllCustomQueryHooks, generateCustomQueryHook, } from './custom-queries';
|
|
70
70
|
export { generateAllCustomMutationHooks, generateCustomMutationHook, } from './custom-mutations';
|
|
71
71
|
export { generateQueriesBarrel, generateMutationsBarrel, generateMainBarrel, generateCustomQueriesBarrel, generateCustomMutationsBarrel, } from './barrel';
|
|
72
|
+
export { generateQueryKeysFile } from './query-keys';
|
|
73
|
+
export { generateMutationKeysFile } from './mutation-keys';
|
|
74
|
+
export { generateInvalidationFile } from './invalidation';
|