@constructive-io/graphql-codegen 3.3.2 → 4.0.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 +0 -4
- package/core/ast.js +6 -5
- package/core/codegen/custom-mutations.js +22 -22
- package/core/codegen/custom-queries.js +24 -17
- package/core/codegen/hooks-ast.d.ts +1 -1
- package/core/codegen/hooks-ast.js +22 -5
- package/core/codegen/index.d.ts +1 -1
- package/core/codegen/mutations.js +16 -12
- package/core/codegen/orm/custom-ops-generator.js +37 -3
- package/core/codegen/orm/input-types-generator.js +161 -89
- package/core/codegen/orm/model-generator.js +72 -73
- package/core/codegen/orm/select-types.d.ts +27 -17
- package/core/codegen/queries.js +37 -25
- package/core/codegen/schema-types-generator.js +21 -0
- package/core/codegen/templates/hooks-selection.ts +12 -0
- package/core/codegen/templates/query-builder.ts +103 -59
- package/core/codegen/templates/select-types.ts +59 -33
- package/core/codegen/types.js +26 -0
- package/core/codegen/utils.d.ts +1 -1
- package/core/codegen/utils.js +1 -1
- package/core/custom-ast.js +9 -8
- package/core/database/index.js +2 -3
- package/core/index.d.ts +2 -0
- package/core/index.js +2 -0
- package/core/introspect/infer-tables.js +144 -58
- package/core/introspect/transform-schema.d.ts +1 -1
- package/core/introspect/transform-schema.js +3 -1
- package/esm/core/ast.js +6 -5
- package/esm/core/codegen/custom-mutations.js +23 -23
- package/esm/core/codegen/custom-queries.js +25 -18
- package/esm/core/codegen/hooks-ast.d.ts +1 -1
- package/esm/core/codegen/hooks-ast.js +22 -5
- package/esm/core/codegen/index.d.ts +1 -1
- package/esm/core/codegen/mutations.js +16 -12
- package/esm/core/codegen/orm/custom-ops-generator.js +38 -4
- package/esm/core/codegen/orm/input-types-generator.js +163 -91
- package/esm/core/codegen/orm/model-generator.js +73 -74
- package/esm/core/codegen/orm/select-types.d.ts +27 -17
- package/esm/core/codegen/queries.js +37 -25
- package/esm/core/codegen/schema-types-generator.js +21 -0
- package/esm/core/codegen/types.js +26 -0
- package/esm/core/codegen/utils.d.ts +1 -1
- package/esm/core/codegen/utils.js +1 -1
- package/esm/core/custom-ast.js +9 -8
- package/esm/core/database/index.js +2 -3
- package/esm/core/index.d.ts +2 -0
- package/esm/core/index.js +2 -0
- package/esm/core/introspect/infer-tables.js +144 -58
- package/esm/core/introspect/transform-schema.d.ts +1 -1
- package/esm/core/introspect/transform-schema.js +3 -1
- package/esm/generators/field-selector.js +1 -0
- package/esm/generators/index.d.ts +3 -0
- package/esm/generators/index.js +3 -0
- package/esm/generators/mutations.js +4 -4
- package/esm/generators/select.js +4 -4
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/types/schema.d.ts +5 -3
- package/generators/field-selector.js +1 -0
- package/generators/index.d.ts +3 -0
- package/generators/index.js +3 -0
- package/generators/mutations.js +3 -3
- package/generators/select.js +3 -3
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +10 -10
- package/types/schema.d.ts +5 -3
package/README.md
CHANGED
|
@@ -183,8 +183,6 @@ interface GraphQLSDKConfigTarget {
|
|
|
183
183
|
// Generator flags
|
|
184
184
|
reactQuery?: boolean; // Generate React Query hooks (output: {output}/hooks)
|
|
185
185
|
orm?: boolean; // Generate ORM client (output: {output}/orm)
|
|
186
|
-
browserCompatible?: boolean; // Generate browser-compatible code (default: true)
|
|
187
|
-
// Set to false for Node.js with localhost DNS fix
|
|
188
186
|
|
|
189
187
|
// Table filtering (for CRUD operations from _meta)
|
|
190
188
|
tables?: {
|
|
@@ -685,8 +683,6 @@ Generator Options:
|
|
|
685
683
|
-o, --output <dir> Output directory
|
|
686
684
|
-t, --target <name> Target name (for multi-target configs)
|
|
687
685
|
-a, --authorization <token> Authorization header value
|
|
688
|
-
--browser-compatible Generate browser-compatible code (default: true)
|
|
689
|
-
Set to false for Node.js with localhost DNS fix
|
|
690
686
|
--skip-custom-operations Only generate table CRUD operations
|
|
691
687
|
--dry-run Preview without writing files
|
|
692
688
|
-v, --verbose Show detailed output
|
package/core/ast.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.deleteOne = exports.patchOne = exports.createOne = exports.getOne = exports.getMany = exports.getCount = exports.getAll = void 0;
|
|
37
37
|
exports.getSelections = getSelections;
|
|
38
38
|
const t = __importStar(require("gql-ast"));
|
|
39
|
+
const graphql_1 = require("graphql");
|
|
39
40
|
const inflekt_1 = require("inflekt");
|
|
40
41
|
const custom_ast_1 = require("./custom-ast");
|
|
41
42
|
const NON_MUTABLE_PROPS = ['createdAt', 'createdBy', 'updatedAt', 'updatedBy'];
|
|
@@ -76,7 +77,7 @@ const createGqlMutation = ({ operationName, mutationName, selectArgs, selections
|
|
|
76
77
|
return t.document({
|
|
77
78
|
definitions: [
|
|
78
79
|
t.operationDefinition({
|
|
79
|
-
operation:
|
|
80
|
+
operation: graphql_1.OperationTypeNode.MUTATION,
|
|
80
81
|
name: mutationName,
|
|
81
82
|
variableDefinitions,
|
|
82
83
|
selectionSet: t.selectionSet({ selections: opSel }),
|
|
@@ -105,7 +106,7 @@ const getAll = ({ queryName, operationName, selection, }) => {
|
|
|
105
106
|
const ast = t.document({
|
|
106
107
|
definitions: [
|
|
107
108
|
t.operationDefinition({
|
|
108
|
-
operation:
|
|
109
|
+
operation: graphql_1.OperationTypeNode.QUERY,
|
|
109
110
|
name: queryName,
|
|
110
111
|
selectionSet: t.selectionSet({ selections: opSel }),
|
|
111
112
|
}),
|
|
@@ -149,7 +150,7 @@ const getCount = ({ queryName, operationName, query, }) => {
|
|
|
149
150
|
const ast = t.document({
|
|
150
151
|
definitions: [
|
|
151
152
|
t.operationDefinition({
|
|
152
|
-
operation:
|
|
153
|
+
operation: graphql_1.OperationTypeNode.QUERY,
|
|
153
154
|
name: queryName,
|
|
154
155
|
variableDefinitions,
|
|
155
156
|
selectionSet: t.selectionSet({ selections: opSel }),
|
|
@@ -249,7 +250,7 @@ const getMany = ({ builder, queryName, operationName, query, selection, }) => {
|
|
|
249
250
|
const ast = t.document({
|
|
250
251
|
definitions: [
|
|
251
252
|
t.operationDefinition({
|
|
252
|
-
operation:
|
|
253
|
+
operation: graphql_1.OperationTypeNode.QUERY,
|
|
253
254
|
name: queryName,
|
|
254
255
|
variableDefinitions,
|
|
255
256
|
selectionSet: t.selectionSet({
|
|
@@ -306,7 +307,7 @@ const getOne = ({ queryName, operationName, query, selection, }) => {
|
|
|
306
307
|
const ast = t.document({
|
|
307
308
|
definitions: [
|
|
308
309
|
t.operationDefinition({
|
|
309
|
-
operation:
|
|
310
|
+
operation: graphql_1.OperationTypeNode.QUERY,
|
|
310
311
|
name: queryName,
|
|
311
312
|
variableDefinitions,
|
|
312
313
|
selectionSet: t.selectionSet({ selections: opSel }),
|
|
@@ -112,7 +112,7 @@ function generateCustomMutationHookInternal(options) {
|
|
|
112
112
|
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/input-types', inputTypeImports, true));
|
|
113
113
|
}
|
|
114
114
|
if (hasSelect) {
|
|
115
|
-
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true));
|
|
115
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect', 'StrictSelect'], true));
|
|
116
116
|
}
|
|
117
117
|
// Re-exports
|
|
118
118
|
if (hasArgs) {
|
|
@@ -127,39 +127,38 @@ function generateCustomMutationHookInternal(options) {
|
|
|
127
127
|
? (0, hooks_ast_1.typeRef)(varTypeName)
|
|
128
128
|
: t.tsVoidKeyword();
|
|
129
129
|
const selectedResultType = (sel) => (0, hooks_ast_1.customSelectResultTypeLiteral)(operation.name, operation.returnType, payloadTypeName, sel);
|
|
130
|
-
|
|
131
|
-
const o1ParamType = t.tsIntersectionType([
|
|
130
|
+
const paramsType = t.tsIntersectionType([
|
|
132
131
|
t.tsTypeLiteral([
|
|
133
132
|
t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(t.tsParenthesizedType(t.tsIntersectionType([
|
|
134
133
|
t.tsTypeLiteral([
|
|
135
|
-
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation((0, hooks_ast_1.sRef)())),
|
|
134
|
+
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(t.tsIntersectionType([(0, hooks_ast_1.sRef)(), (0, hooks_ast_1.typeRef)(selectTypeName)]))),
|
|
135
|
+
]),
|
|
136
|
+
(0, hooks_ast_1.typeRef)('HookStrictSelect', [
|
|
137
|
+
(0, hooks_ast_1.typeRef)('NoInfer', [(0, hooks_ast_1.sRef)()]),
|
|
138
|
+
(0, hooks_ast_1.typeRef)(selectTypeName),
|
|
136
139
|
]),
|
|
137
|
-
(0, hooks_ast_1.typeRef)('StrictSelect', [(0, hooks_ast_1.sRef)(), (0, hooks_ast_1.typeRef)(selectTypeName)]),
|
|
138
140
|
])))),
|
|
139
141
|
]),
|
|
140
142
|
(0, hooks_ast_1.useMutationOptionsType)(selectedResultType((0, hooks_ast_1.sRef)()), mutationVarType),
|
|
141
143
|
]);
|
|
142
|
-
statements.push((0, hooks_ast_1.exportDeclareFunction)(hookName, (0, hooks_ast_1.createSTypeParam)(selectTypeName), [(0, hooks_ast_1.createFunctionParam)('params', o1ParamType)], (0, hooks_ast_1.useMutationResultType)(selectedResultType((0, hooks_ast_1.sRef)()), mutationVarType)));
|
|
143
|
-
// Implementation
|
|
144
|
-
const implSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation((0, hooks_ast_1.selectionConfigType)((0, hooks_ast_1.typeRef)(selectTypeName))));
|
|
145
|
-
const implParamType = t.tsIntersectionType([
|
|
146
|
-
t.tsTypeLiteral([implSelProp]),
|
|
147
|
-
(0, hooks_ast_1.omitType)((0, hooks_ast_1.typeRef)('UseMutationOptions', [
|
|
148
|
-
t.tsAnyKeyword(),
|
|
149
|
-
(0, hooks_ast_1.typeRef)('Error'),
|
|
150
|
-
mutationVarType,
|
|
151
|
-
]), ['mutationFn']),
|
|
152
|
-
]);
|
|
153
144
|
const body = [];
|
|
154
|
-
body.push((0, hooks_ast_1.buildSelectionArgsCall)(
|
|
145
|
+
body.push((0, hooks_ast_1.buildSelectionArgsCall)((0, hooks_ast_1.sRef)()));
|
|
155
146
|
body.push((0, hooks_ast_1.destructureParamsWithSelection)('mutationOptions'));
|
|
156
147
|
body.push((0, hooks_ast_1.voidStatement)('_selection'));
|
|
157
148
|
const mutationKeyExpr = useCentralizedKeys
|
|
158
149
|
? (0, hooks_ast_1.callExpr)(t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), [])
|
|
159
150
|
: undefined;
|
|
160
|
-
|
|
151
|
+
// Cast to ORM's StrictSelect (not HookStrictSelect) since the ORM
|
|
152
|
+
// method signature requires { select: S } & StrictSelect<S, XxxSelect>.
|
|
153
|
+
// Strictness is already enforced at the hook parameter level.
|
|
154
|
+
const selectArgExpr = t.tsAsExpression(t.objectExpression([
|
|
161
155
|
(0, hooks_ast_1.objectProp)('select', t.memberExpression(t.identifier('args'), t.identifier('select'))),
|
|
162
|
-
])
|
|
156
|
+
]), t.tsIntersectionType([
|
|
157
|
+
t.tsTypeLiteral([
|
|
158
|
+
t.tsPropertySignature(t.identifier('select'), t.tsTypeAnnotation((0, hooks_ast_1.sRef)())),
|
|
159
|
+
]),
|
|
160
|
+
(0, hooks_ast_1.typeRef)('StrictSelect', [(0, hooks_ast_1.sRef)(), (0, hooks_ast_1.typeRef)(selectTypeName)]),
|
|
161
|
+
]));
|
|
163
162
|
let mutationFnExpr;
|
|
164
163
|
if (hasArgs) {
|
|
165
164
|
const variablesParam = (0, hooks_ast_1.createFunctionParam)('variables', (0, hooks_ast_1.typeRef)(varTypeName));
|
|
@@ -169,13 +168,14 @@ function generateCustomMutationHookInternal(options) {
|
|
|
169
168
|
mutationFnExpr = t.arrowFunctionExpression([], (0, hooks_ast_1.getClientCustomCallUnwrap)('mutation', operation.name, [], selectArgExpr));
|
|
170
169
|
}
|
|
171
170
|
body.push((0, hooks_ast_1.returnUseMutation)(mutationFnExpr, [(0, hooks_ast_1.spreadObj)(t.identifier('mutationOptions'))], mutationKeyExpr));
|
|
172
|
-
statements.push((0, hooks_ast_1.exportFunction)(hookName,
|
|
171
|
+
statements.push((0, hooks_ast_1.exportFunction)(hookName, (0, hooks_ast_1.createSTypeParam)(selectTypeName), [(0, hooks_ast_1.createFunctionParam)('params', paramsType)], body, (0, hooks_ast_1.useMutationResultType)(selectedResultType((0, hooks_ast_1.sRef)()), mutationVarType)));
|
|
173
172
|
}
|
|
174
173
|
else {
|
|
175
174
|
// Without select: simple hook (scalar return type)
|
|
176
|
-
|
|
175
|
+
(0, type_resolver_1.typeRefToTsType)(operation.returnType, tracker);
|
|
176
|
+
const resultTsType = (0, hooks_ast_1.typeRefToTsTypeAST)(operation.returnType);
|
|
177
177
|
const resultTypeLiteral = t.tsTypeLiteral([
|
|
178
|
-
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(
|
|
178
|
+
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(resultTsType)),
|
|
179
179
|
]);
|
|
180
180
|
const mutationVarType = hasArgs
|
|
181
181
|
? (0, hooks_ast_1.typeRef)(varTypeName)
|
|
@@ -65,10 +65,11 @@ function generateCustomQueryHook(options) {
|
|
|
65
65
|
const tracker = (0, type_resolver_1.createTypeTracker)({ tableTypeNames });
|
|
66
66
|
const hasArgs = operation.args.length > 0;
|
|
67
67
|
const hasRequiredArgs = operation.args.some((arg) => (0, type_resolver_1.isTypeRequired)(arg.type));
|
|
68
|
-
|
|
68
|
+
(0, type_resolver_1.typeRefToTsType)(operation.returnType, tracker);
|
|
69
69
|
for (const arg of operation.args) {
|
|
70
70
|
(0, type_resolver_1.typeRefToTsType)(arg.type, tracker);
|
|
71
71
|
}
|
|
72
|
+
const resultTsType = (0, hooks_ast_1.typeRefToTsTypeAST)(operation.returnType);
|
|
72
73
|
const selectTypeName = (0, select_helpers_1.getSelectTypeName)(operation.returnType);
|
|
73
74
|
const payloadTypeName = (0, type_resolver_1.getTypeBaseName)(operation.returnType);
|
|
74
75
|
const hasSelect = !!selectTypeName && !!payloadTypeName;
|
|
@@ -106,7 +107,7 @@ function generateCustomQueryHook(options) {
|
|
|
106
107
|
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/input-types', inputTypeImports, true));
|
|
107
108
|
}
|
|
108
109
|
if (hasSelect) {
|
|
109
|
-
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', '
|
|
110
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect'], true));
|
|
110
111
|
}
|
|
111
112
|
// Re-exports
|
|
112
113
|
if (hasArgs) {
|
|
@@ -158,9 +159,12 @@ function generateCustomQueryHook(options) {
|
|
|
158
159
|
// Helper to build the fields+StrictSelect intersection type
|
|
159
160
|
const fieldsSelectionType = (s) => t.tsParenthesizedType(t.tsIntersectionType([
|
|
160
161
|
t.tsTypeLiteral([
|
|
161
|
-
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(s)),
|
|
162
|
+
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(t.tsIntersectionType([s, (0, hooks_ast_1.typeRef)(selectTypeName)]))),
|
|
163
|
+
]),
|
|
164
|
+
(0, hooks_ast_1.typeRef)('HookStrictSelect', [
|
|
165
|
+
(0, hooks_ast_1.typeRef)('NoInfer', [s]),
|
|
166
|
+
(0, hooks_ast_1.typeRef)(selectTypeName),
|
|
162
167
|
]),
|
|
163
|
-
(0, hooks_ast_1.typeRef)('StrictSelect', [s, (0, hooks_ast_1.typeRef)(selectTypeName)]),
|
|
164
168
|
]));
|
|
165
169
|
const selectedResultType = (sel) => (0, hooks_ast_1.customSelectResultTypeLiteral)(operation.name, operation.returnType, payloadTypeName, sel);
|
|
166
170
|
// Hook
|
|
@@ -178,10 +182,11 @@ function generateCustomQueryHook(options) {
|
|
|
178
182
|
// Overload 1: with selection.fields
|
|
179
183
|
const o1Props = [];
|
|
180
184
|
if (hasArgs) {
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
+
const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation((0, hooks_ast_1.typeRef)(varTypeName)));
|
|
186
|
+
if (!hasRequiredArgs) {
|
|
187
|
+
varProp.optional = true;
|
|
188
|
+
}
|
|
189
|
+
o1Props.push(varProp);
|
|
185
190
|
}
|
|
186
191
|
o1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType((0, hooks_ast_1.sRef)()))));
|
|
187
192
|
const o1ParamType = t.tsIntersectionType([
|
|
@@ -267,7 +272,7 @@ function generateCustomQueryHook(options) {
|
|
|
267
272
|
else {
|
|
268
273
|
// Without select: simple hook (scalar return type)
|
|
269
274
|
const resultTypeLiteral = t.tsTypeLiteral([
|
|
270
|
-
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(
|
|
275
|
+
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(resultTsType)),
|
|
271
276
|
]);
|
|
272
277
|
const optType = (0, hooks_ast_1.omitType)((0, hooks_ast_1.typeRef)('UseQueryOptions', [
|
|
273
278
|
resultTypeLiteral,
|
|
@@ -346,10 +351,11 @@ function generateCustomQueryHook(options) {
|
|
|
346
351
|
// Overload 1: with fields
|
|
347
352
|
const f1Props = [];
|
|
348
353
|
if (hasArgs) {
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
354
|
+
const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation((0, hooks_ast_1.typeRef)(varTypeName)));
|
|
355
|
+
if (!hasRequiredArgs) {
|
|
356
|
+
varProp.optional = true;
|
|
357
|
+
}
|
|
358
|
+
f1Props.push(varProp);
|
|
353
359
|
}
|
|
354
360
|
f1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType((0, hooks_ast_1.sRef)()))));
|
|
355
361
|
const f1Decl = (0, hooks_ast_1.exportAsyncDeclareFunction)(fetchFnName, (0, hooks_ast_1.createSTypeParam)(selectTypeName), [(0, hooks_ast_1.createFunctionParam)('params', t.tsTypeLiteral(f1Props))], (0, hooks_ast_1.typeRef)('Promise', [selectedResultType((0, hooks_ast_1.sRef)())]));
|
|
@@ -452,10 +458,11 @@ function generateCustomQueryHook(options) {
|
|
|
452
458
|
// Overload 1: with fields
|
|
453
459
|
const p1Props = [];
|
|
454
460
|
if (hasArgs) {
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
461
|
+
const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation((0, hooks_ast_1.typeRef)(varTypeName)));
|
|
462
|
+
if (!hasRequiredArgs) {
|
|
463
|
+
varProp.optional = true;
|
|
464
|
+
}
|
|
465
|
+
p1Props.push(varProp);
|
|
459
466
|
}
|
|
460
467
|
p1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType((0, hooks_ast_1.sRef)()))));
|
|
461
468
|
const p1Decl = (0, hooks_ast_1.exportAsyncDeclareFunction)(prefetchFnName, (0, hooks_ast_1.createSTypeParam)(selectTypeName), [
|
|
@@ -70,6 +70,6 @@ export declare function generateHookFileCode(headerDescription: string, statemen
|
|
|
70
70
|
export declare function scopeTypeLiteral(scopeTypeName: string): t.TSTypeLiteral;
|
|
71
71
|
export declare function wrapInferSelectResultType(typeRefNode: CleanArgument['type'], payloadTypeName: string, selectType: t.TSType): t.TSType;
|
|
72
72
|
export declare function typeRefToTsTypeAST(typeRefNode: CleanArgument['type']): t.TSType;
|
|
73
|
-
export declare function buildSelectionArgsCall(
|
|
73
|
+
export declare function buildSelectionArgsCall(selectType: string | t.TSType): t.VariableDeclaration;
|
|
74
74
|
export declare function buildListSelectionArgsCall(selectTypeName: string, filterTypeName: string, orderByTypeName: string): t.VariableDeclaration;
|
|
75
75
|
export declare function customSelectResultTypeLiteral(opName: string, returnType: CleanArgument['type'], payloadTypeName: string, selectType: t.TSType): t.TSTypeLiteral;
|
|
@@ -194,7 +194,10 @@ function selectionConfigType(selectType) {
|
|
|
194
194
|
return typeRef('SelectionConfig', [selectType]);
|
|
195
195
|
}
|
|
196
196
|
function strictSelectType(selectType, shapeTypeName) {
|
|
197
|
-
return typeRef('
|
|
197
|
+
return typeRef('HookStrictSelect', [
|
|
198
|
+
typeRef('NoInfer', [selectType]),
|
|
199
|
+
typeRef(shapeTypeName),
|
|
200
|
+
]);
|
|
198
201
|
}
|
|
199
202
|
function withFieldsSelectionType(selectType, selectTypeName) {
|
|
200
203
|
return t.tsIntersectionType([
|
|
@@ -463,8 +466,15 @@ function scopeTypeLiteral(scopeTypeName) {
|
|
|
463
466
|
// Type conversion helpers (GraphQL -> AST)
|
|
464
467
|
// ============================================================================
|
|
465
468
|
function wrapInferSelectResultType(typeRefNode, payloadTypeName, selectType) {
|
|
469
|
+
const nonNullable = wrapInferSelectResultTypeNonNullable(typeRefNode, payloadTypeName, selectType);
|
|
470
|
+
if (typeRefNode.kind === 'NON_NULL') {
|
|
471
|
+
return nonNullable;
|
|
472
|
+
}
|
|
473
|
+
return t.tsUnionType([nonNullable, t.tsNullKeyword()]);
|
|
474
|
+
}
|
|
475
|
+
function wrapInferSelectResultTypeNonNullable(typeRefNode, payloadTypeName, selectType) {
|
|
466
476
|
if (typeRefNode.kind === 'NON_NULL' && typeRefNode.ofType) {
|
|
467
|
-
return
|
|
477
|
+
return wrapInferSelectResultTypeNonNullable(typeRefNode.ofType, payloadTypeName, selectType);
|
|
468
478
|
}
|
|
469
479
|
if (typeRefNode.kind === 'LIST' && typeRefNode.ofType) {
|
|
470
480
|
return t.tsArrayType(wrapInferSelectResultType(typeRefNode.ofType, payloadTypeName, selectType));
|
|
@@ -472,8 +482,15 @@ function wrapInferSelectResultType(typeRefNode, payloadTypeName, selectType) {
|
|
|
472
482
|
return inferSelectResultType(payloadTypeName, selectType);
|
|
473
483
|
}
|
|
474
484
|
function typeRefToTsTypeAST(typeRefNode) {
|
|
485
|
+
const nonNullable = typeRefToTsTypeASTNonNullable(typeRefNode);
|
|
486
|
+
if (typeRefNode.kind === 'NON_NULL') {
|
|
487
|
+
return nonNullable;
|
|
488
|
+
}
|
|
489
|
+
return t.tsUnionType([nonNullable, t.tsNullKeyword()]);
|
|
490
|
+
}
|
|
491
|
+
function typeRefToTsTypeASTNonNullable(typeRefNode) {
|
|
475
492
|
if (typeRefNode.kind === 'NON_NULL' && typeRefNode.ofType) {
|
|
476
|
-
return
|
|
493
|
+
return typeRefToTsTypeASTNonNullable(typeRefNode.ofType);
|
|
477
494
|
}
|
|
478
495
|
if (typeRefNode.kind === 'LIST' && typeRefNode.ofType) {
|
|
479
496
|
return t.tsArrayType(typeRefToTsTypeAST(typeRefNode.ofType));
|
|
@@ -490,13 +507,13 @@ function typeRefToTsTypeAST(typeRefNode) {
|
|
|
490
507
|
}
|
|
491
508
|
return typeRef(typeRefNode.name ?? 'unknown');
|
|
492
509
|
}
|
|
493
|
-
function buildSelectionArgsCall(
|
|
510
|
+
function buildSelectionArgsCall(selectType) {
|
|
494
511
|
const call = t.callExpression(t.identifier('buildSelectionArgs'), [
|
|
495
512
|
t.memberExpression(t.identifier('params'), t.identifier('selection')),
|
|
496
513
|
]);
|
|
497
514
|
// @ts-ignore - Babel types support typeParameters on CallExpression for TS
|
|
498
515
|
call.typeParameters = t.tsTypeParameterInstantiation([
|
|
499
|
-
typeRef(
|
|
516
|
+
typeof selectType === 'string' ? typeRef(selectType) : selectType,
|
|
500
517
|
]);
|
|
501
518
|
return constDecl('args', call);
|
|
502
519
|
}
|
package/core/codegen/index.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export interface GenerateResult {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
export interface GenerateOptions {
|
|
45
|
-
/** Tables from
|
|
45
|
+
/** Tables from GraphQL introspection */
|
|
46
46
|
tables: CleanTable[];
|
|
47
47
|
/** Custom operations from __schema introspection */
|
|
48
48
|
customOperations?: {
|
|
@@ -65,9 +65,12 @@ function buildMutationResultType(mutationName, singularName, relationTypeName, s
|
|
|
65
65
|
function buildFieldsSelectionType(s, selectTypeName) {
|
|
66
66
|
return t.tsParenthesizedType(t.tsIntersectionType([
|
|
67
67
|
t.tsTypeLiteral([
|
|
68
|
-
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(s)),
|
|
68
|
+
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(t.tsIntersectionType([s, (0, hooks_ast_1.typeRef)(selectTypeName)]))),
|
|
69
|
+
]),
|
|
70
|
+
(0, hooks_ast_1.typeRef)('HookStrictSelect', [
|
|
71
|
+
(0, hooks_ast_1.typeRef)('NoInfer', [s]),
|
|
72
|
+
(0, hooks_ast_1.typeRef)(selectTypeName),
|
|
69
73
|
]),
|
|
70
|
-
(0, hooks_ast_1.typeRef)('StrictSelect', [s, (0, hooks_ast_1.typeRef)(selectTypeName)]),
|
|
71
74
|
]));
|
|
72
75
|
}
|
|
73
76
|
function generateCreateMutationHook(table, options = {}) {
|
|
@@ -97,7 +100,7 @@ function generateCreateMutationHook(table, options = {}) {
|
|
|
97
100
|
statements.push((0, hooks_ast_1.createImportDeclaration)('../mutation-keys', [mutationKeysName]));
|
|
98
101
|
}
|
|
99
102
|
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/input-types', [selectTypeName, relationTypeName, createInputTypeName], true));
|
|
100
|
-
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', '
|
|
103
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect'], true));
|
|
101
104
|
// Re-exports
|
|
102
105
|
statements.push((0, hooks_ast_1.createTypeReExport)([selectTypeName, relationTypeName, createInputTypeName], '../../orm/input-types'));
|
|
103
106
|
// Variable type: CreateTypeName['singularName']
|
|
@@ -186,6 +189,7 @@ function generateUpdateMutationHook(table, options = {}) {
|
|
|
186
189
|
const patchTypeName = `${typeName}Patch`;
|
|
187
190
|
const pkFields = (0, utils_1.getPrimaryKeyInfo)(table);
|
|
188
191
|
const pkField = pkFields[0];
|
|
192
|
+
const patchFieldName = table.query?.patchFieldName ?? (0, utils_1.lcFirst)(typeName) + 'Patch';
|
|
189
193
|
const pkTsType = pkField.tsType === 'string' ? t.tsStringKeyword() : t.tsNumberKeyword();
|
|
190
194
|
const statements = [];
|
|
191
195
|
// Imports
|
|
@@ -202,13 +206,13 @@ function generateUpdateMutationHook(table, options = {}) {
|
|
|
202
206
|
statements.push((0, hooks_ast_1.createImportDeclaration)('../mutation-keys', [mutationKeysName]));
|
|
203
207
|
}
|
|
204
208
|
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/input-types', [selectTypeName, relationTypeName, patchTypeName], true));
|
|
205
|
-
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', '
|
|
209
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect'], true));
|
|
206
210
|
// Re-exports
|
|
207
211
|
statements.push((0, hooks_ast_1.createTypeReExport)([selectTypeName, relationTypeName, patchTypeName], '../../orm/input-types'));
|
|
208
|
-
// Variable type: { pkField: type;
|
|
212
|
+
// Variable type: { pkField: type; patchFieldName: PatchType }
|
|
209
213
|
const updateVarType = t.tsTypeLiteral([
|
|
210
214
|
t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTsType)),
|
|
211
|
-
t.tsPropertySignature(t.identifier(
|
|
215
|
+
t.tsPropertySignature(t.identifier(patchFieldName), t.tsTypeAnnotation((0, hooks_ast_1.typeRef)(patchTypeName))),
|
|
212
216
|
]);
|
|
213
217
|
const resultType = (sel) => buildMutationResultType(mutationName, singularName, relationTypeName, sel);
|
|
214
218
|
// Overload 1: with fields
|
|
@@ -228,7 +232,7 @@ function generateUpdateMutationHook(table, options = {}) {
|
|
|
228
232
|
' selection: { fields: { id: true, name: true } },',
|
|
229
233
|
'});',
|
|
230
234
|
'',
|
|
231
|
-
`mutate({ ${pkField.name}: 'value-here',
|
|
235
|
+
`mutate({ ${pkField.name}: 'value-here', ${patchFieldName}: { name: 'Updated' } });`,
|
|
232
236
|
'```',
|
|
233
237
|
]);
|
|
234
238
|
statements.push(o1);
|
|
@@ -250,16 +254,16 @@ function generateUpdateMutationHook(table, options = {}) {
|
|
|
250
254
|
const mutationKeyExpr = useCentralizedKeys
|
|
251
255
|
? t.memberExpression(t.identifier(mutationKeysName), t.identifier('all'))
|
|
252
256
|
: undefined;
|
|
253
|
-
// mutationFn: ({ pkField,
|
|
254
|
-
// getClient().singular.update({ where: { pkField }, data:
|
|
257
|
+
// mutationFn: ({ pkField, patchFieldName }: VarType) =>
|
|
258
|
+
// getClient().singular.update({ where: { pkField }, data: patchFieldName, select: ... }).unwrap()
|
|
255
259
|
const destructParam = t.objectPattern([
|
|
256
260
|
(0, hooks_ast_1.shorthandProp)(pkField.name),
|
|
257
|
-
(0, hooks_ast_1.shorthandProp)(
|
|
261
|
+
(0, hooks_ast_1.shorthandProp)(patchFieldName),
|
|
258
262
|
]);
|
|
259
263
|
destructParam.typeAnnotation = t.tsTypeAnnotation(updateVarType);
|
|
260
264
|
const mutationFnExpr = t.arrowFunctionExpression([destructParam], (0, hooks_ast_1.getClientCallUnwrap)(singularName, 'update', t.objectExpression([
|
|
261
265
|
(0, hooks_ast_1.objectProp)('where', t.objectExpression([(0, hooks_ast_1.shorthandProp)(pkField.name)])),
|
|
262
|
-
(0, hooks_ast_1.objectProp)('data', t.identifier(
|
|
266
|
+
(0, hooks_ast_1.objectProp)('data', t.identifier(patchFieldName)),
|
|
263
267
|
(0, hooks_ast_1.objectProp)('select', t.memberExpression(t.identifier('args'), t.identifier('select'))),
|
|
264
268
|
])));
|
|
265
269
|
// onSuccess: invalidate detail and lists
|
|
@@ -327,7 +331,7 @@ function generateDeleteMutationHook(table, options = {}) {
|
|
|
327
331
|
statements.push((0, hooks_ast_1.createImportDeclaration)('../mutation-keys', [mutationKeysName]));
|
|
328
332
|
}
|
|
329
333
|
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/input-types', [selectTypeName, relationTypeName], true));
|
|
330
|
-
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', '
|
|
334
|
+
statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect'], true));
|
|
331
335
|
// Re-exports
|
|
332
336
|
statements.push((0, hooks_ast_1.createTypeReExport)([selectTypeName, relationTypeName], '../../orm/input-types'));
|
|
333
337
|
// Variable type: { pkField: type }
|
|
@@ -142,8 +142,15 @@ function parseTypeAnnotation(typeStr) {
|
|
|
142
142
|
return t.tsTypeReference(t.identifier(typeStr));
|
|
143
143
|
}
|
|
144
144
|
function buildSelectedResultTsType(typeRef, payloadTypeName) {
|
|
145
|
+
const nonNullable = buildSelectedResultTsTypeNonNullable(typeRef, payloadTypeName);
|
|
146
|
+
if (typeRef.kind === 'NON_NULL') {
|
|
147
|
+
return nonNullable;
|
|
148
|
+
}
|
|
149
|
+
return t.tsUnionType([nonNullable, t.tsNullKeyword()]);
|
|
150
|
+
}
|
|
151
|
+
function buildSelectedResultTsTypeNonNullable(typeRef, payloadTypeName) {
|
|
145
152
|
if (typeRef.kind === 'NON_NULL' && typeRef.ofType) {
|
|
146
|
-
return
|
|
153
|
+
return buildSelectedResultTsTypeNonNullable(typeRef.ofType, payloadTypeName);
|
|
147
154
|
}
|
|
148
155
|
if (typeRef.kind === 'LIST' && typeRef.ofType) {
|
|
149
156
|
return t.tsArrayType(buildSelectedResultTsType(typeRef.ofType, payloadTypeName));
|
|
@@ -153,6 +160,34 @@ function buildSelectedResultTsType(typeRef, payloadTypeName) {
|
|
|
153
160
|
t.tsTypeReference(t.identifier('S')),
|
|
154
161
|
]));
|
|
155
162
|
}
|
|
163
|
+
function scalarTsTypeToAst(typeName) {
|
|
164
|
+
if (typeName === 'string')
|
|
165
|
+
return t.tsStringKeyword();
|
|
166
|
+
if (typeName === 'number')
|
|
167
|
+
return t.tsNumberKeyword();
|
|
168
|
+
if (typeName === 'boolean')
|
|
169
|
+
return t.tsBooleanKeyword();
|
|
170
|
+
return t.tsUnknownKeyword();
|
|
171
|
+
}
|
|
172
|
+
function buildRawResultTsType(typeRef) {
|
|
173
|
+
const nonNullable = buildRawResultTsTypeNonNullable(typeRef);
|
|
174
|
+
if (typeRef.kind === 'NON_NULL') {
|
|
175
|
+
return nonNullable;
|
|
176
|
+
}
|
|
177
|
+
return t.tsUnionType([nonNullable, t.tsNullKeyword()]);
|
|
178
|
+
}
|
|
179
|
+
function buildRawResultTsTypeNonNullable(typeRef) {
|
|
180
|
+
if (typeRef.kind === 'NON_NULL' && typeRef.ofType) {
|
|
181
|
+
return buildRawResultTsTypeNonNullable(typeRef.ofType);
|
|
182
|
+
}
|
|
183
|
+
if (typeRef.kind === 'LIST' && typeRef.ofType) {
|
|
184
|
+
return t.tsArrayType(buildRawResultTsType(typeRef.ofType));
|
|
185
|
+
}
|
|
186
|
+
if (typeRef.kind === 'SCALAR') {
|
|
187
|
+
return scalarTsTypeToAst((0, type_resolver_1.scalarToTsType)(typeRef.name ?? 'unknown'));
|
|
188
|
+
}
|
|
189
|
+
return t.tsTypeReference(t.identifier(typeRef.name ?? 'unknown'));
|
|
190
|
+
}
|
|
156
191
|
function buildOperationMethod(op, operationType) {
|
|
157
192
|
const hasArgs = op.args.length > 0;
|
|
158
193
|
const varTypeName = `${(0, utils_1.ucFirst)(op.name)}Variables`;
|
|
@@ -235,10 +270,9 @@ function buildOperationMethod(op, operationType) {
|
|
|
235
270
|
}
|
|
236
271
|
else {
|
|
237
272
|
// Scalar/Connection type: use raw TS type directly
|
|
238
|
-
const rawTsType = (0, type_resolver_1.typeRefToTsType)(op.returnType);
|
|
239
273
|
newExpr.typeParameters = t.tsTypeParameterInstantiation([
|
|
240
274
|
t.tsTypeLiteral([
|
|
241
|
-
t.tsPropertySignature(t.identifier(op.name), t.tsTypeAnnotation(
|
|
275
|
+
t.tsPropertySignature(t.identifier(op.name), t.tsTypeAnnotation(buildRawResultTsType(op.returnType))),
|
|
242
276
|
]),
|
|
243
277
|
]);
|
|
244
278
|
}
|