@constructive-io/graphql-codegen 3.3.1 → 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 +11 -11
- package/types/schema.d.ts +5 -3
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* ...
|
|
15
15
|
*/
|
|
16
16
|
import * as t from '@babel/types';
|
|
17
|
-
import { buildSelectionArgsCall, callExpr, constDecl, createFunctionParam, createImportDeclaration, createSTypeParam, createTypeReExport, customSelectResultTypeLiteral, destructureParamsWithSelection,
|
|
17
|
+
import { buildSelectionArgsCall, callExpr, constDecl, createFunctionParam, createImportDeclaration, createSTypeParam, createTypeReExport, customSelectResultTypeLiteral, destructureParamsWithSelection, exportFunction, generateHookFileCode, getClientCustomCallUnwrap, objectProp, omitType, returnUseMutation, spreadObj, sRef, typeRef, typeRefToTsTypeAST, useMutationOptionsType, useMutationResultType, voidStatement, } from './hooks-ast';
|
|
18
18
|
import { getSelectTypeName } from './select-helpers';
|
|
19
19
|
import { createTypeTracker, getOperationFileName, getOperationHookName, getTypeBaseName, typeRefToTsType, } from './type-resolver';
|
|
20
20
|
import { ucFirst } from './utils';
|
|
@@ -75,7 +75,7 @@ function generateCustomMutationHookInternal(options) {
|
|
|
75
75
|
statements.push(createImportDeclaration('../../orm/input-types', inputTypeImports, true));
|
|
76
76
|
}
|
|
77
77
|
if (hasSelect) {
|
|
78
|
-
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true));
|
|
78
|
+
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect', 'StrictSelect'], true));
|
|
79
79
|
}
|
|
80
80
|
// Re-exports
|
|
81
81
|
if (hasArgs) {
|
|
@@ -90,39 +90,38 @@ function generateCustomMutationHookInternal(options) {
|
|
|
90
90
|
? typeRef(varTypeName)
|
|
91
91
|
: t.tsVoidKeyword();
|
|
92
92
|
const selectedResultType = (sel) => customSelectResultTypeLiteral(operation.name, operation.returnType, payloadTypeName, sel);
|
|
93
|
-
|
|
94
|
-
const o1ParamType = t.tsIntersectionType([
|
|
93
|
+
const paramsType = t.tsIntersectionType([
|
|
95
94
|
t.tsTypeLiteral([
|
|
96
95
|
t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(t.tsParenthesizedType(t.tsIntersectionType([
|
|
97
96
|
t.tsTypeLiteral([
|
|
98
|
-
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(sRef())),
|
|
97
|
+
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(t.tsIntersectionType([sRef(), typeRef(selectTypeName)]))),
|
|
98
|
+
]),
|
|
99
|
+
typeRef('HookStrictSelect', [
|
|
100
|
+
typeRef('NoInfer', [sRef()]),
|
|
101
|
+
typeRef(selectTypeName),
|
|
99
102
|
]),
|
|
100
|
-
typeRef('StrictSelect', [sRef(), typeRef(selectTypeName)]),
|
|
101
103
|
])))),
|
|
102
104
|
]),
|
|
103
105
|
useMutationOptionsType(selectedResultType(sRef()), mutationVarType),
|
|
104
106
|
]);
|
|
105
|
-
statements.push(exportDeclareFunction(hookName, createSTypeParam(selectTypeName), [createFunctionParam('params', o1ParamType)], useMutationResultType(selectedResultType(sRef()), mutationVarType)));
|
|
106
|
-
// Implementation
|
|
107
|
-
const implSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(selectionConfigType(typeRef(selectTypeName))));
|
|
108
|
-
const implParamType = t.tsIntersectionType([
|
|
109
|
-
t.tsTypeLiteral([implSelProp]),
|
|
110
|
-
omitType(typeRef('UseMutationOptions', [
|
|
111
|
-
t.tsAnyKeyword(),
|
|
112
|
-
typeRef('Error'),
|
|
113
|
-
mutationVarType,
|
|
114
|
-
]), ['mutationFn']),
|
|
115
|
-
]);
|
|
116
107
|
const body = [];
|
|
117
|
-
body.push(buildSelectionArgsCall(
|
|
108
|
+
body.push(buildSelectionArgsCall(sRef()));
|
|
118
109
|
body.push(destructureParamsWithSelection('mutationOptions'));
|
|
119
110
|
body.push(voidStatement('_selection'));
|
|
120
111
|
const mutationKeyExpr = useCentralizedKeys
|
|
121
112
|
? callExpr(t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), [])
|
|
122
113
|
: undefined;
|
|
123
|
-
|
|
114
|
+
// Cast to ORM's StrictSelect (not HookStrictSelect) since the ORM
|
|
115
|
+
// method signature requires { select: S } & StrictSelect<S, XxxSelect>.
|
|
116
|
+
// Strictness is already enforced at the hook parameter level.
|
|
117
|
+
const selectArgExpr = t.tsAsExpression(t.objectExpression([
|
|
124
118
|
objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))),
|
|
125
|
-
])
|
|
119
|
+
]), t.tsIntersectionType([
|
|
120
|
+
t.tsTypeLiteral([
|
|
121
|
+
t.tsPropertySignature(t.identifier('select'), t.tsTypeAnnotation(sRef())),
|
|
122
|
+
]),
|
|
123
|
+
typeRef('StrictSelect', [sRef(), typeRef(selectTypeName)]),
|
|
124
|
+
]));
|
|
126
125
|
let mutationFnExpr;
|
|
127
126
|
if (hasArgs) {
|
|
128
127
|
const variablesParam = createFunctionParam('variables', typeRef(varTypeName));
|
|
@@ -132,13 +131,14 @@ function generateCustomMutationHookInternal(options) {
|
|
|
132
131
|
mutationFnExpr = t.arrowFunctionExpression([], getClientCustomCallUnwrap('mutation', operation.name, [], selectArgExpr));
|
|
133
132
|
}
|
|
134
133
|
body.push(returnUseMutation(mutationFnExpr, [spreadObj(t.identifier('mutationOptions'))], mutationKeyExpr));
|
|
135
|
-
statements.push(exportFunction(hookName,
|
|
134
|
+
statements.push(exportFunction(hookName, createSTypeParam(selectTypeName), [createFunctionParam('params', paramsType)], body, useMutationResultType(selectedResultType(sRef()), mutationVarType)));
|
|
136
135
|
}
|
|
137
136
|
else {
|
|
138
137
|
// Without select: simple hook (scalar return type)
|
|
139
|
-
|
|
138
|
+
typeRefToTsType(operation.returnType, tracker);
|
|
139
|
+
const resultTsType = typeRefToTsTypeAST(operation.returnType);
|
|
140
140
|
const resultTypeLiteral = t.tsTypeLiteral([
|
|
141
|
-
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(
|
|
141
|
+
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(resultTsType)),
|
|
142
142
|
]);
|
|
143
143
|
const mutationVarType = hasArgs
|
|
144
144
|
? typeRef(varTypeName)
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import * as t from '@babel/types';
|
|
17
17
|
import { asConst } from './babel-ast';
|
|
18
|
-
import { addJSDocComment, buildSelectionArgsCall, callExpr, constDecl, createFunctionParam, createImportDeclaration, createSAndTDataTypeParams, createSTypeParam, createTDataTypeParam, createTypeReExport, customSelectResultTypeLiteral, destructureParamsWithSelection, exportAsyncDeclareFunction, exportAsyncFunction, exportDeclareFunction, exportFunction, generateHookFileCode, getClientCustomCallUnwrap, objectProp, omitType, returnUseQuery, selectionConfigType, spreadObj, sRef, typeRef, useQueryOptionsImplType, voidStatement, } from './hooks-ast';
|
|
18
|
+
import { addJSDocComment, buildSelectionArgsCall, callExpr, constDecl, createFunctionParam, createImportDeclaration, createSAndTDataTypeParams, createSTypeParam, createTDataTypeParam, createTypeReExport, customSelectResultTypeLiteral, destructureParamsWithSelection, exportAsyncDeclareFunction, exportAsyncFunction, exportDeclareFunction, exportFunction, generateHookFileCode, getClientCustomCallUnwrap, objectProp, omitType, returnUseQuery, selectionConfigType, spreadObj, sRef, typeRef, typeRefToTsTypeAST, useQueryOptionsImplType, voidStatement, } from './hooks-ast';
|
|
19
19
|
import { getSelectTypeName } from './select-helpers';
|
|
20
20
|
import { createTypeTracker, getOperationFileName, getOperationHookName, getQueryKeyName, getTypeBaseName, isTypeRequired, typeRefToTsType, } from './type-resolver';
|
|
21
21
|
import { ucFirst } from './utils';
|
|
@@ -28,10 +28,11 @@ export function generateCustomQueryHook(options) {
|
|
|
28
28
|
const tracker = createTypeTracker({ tableTypeNames });
|
|
29
29
|
const hasArgs = operation.args.length > 0;
|
|
30
30
|
const hasRequiredArgs = operation.args.some((arg) => isTypeRequired(arg.type));
|
|
31
|
-
|
|
31
|
+
typeRefToTsType(operation.returnType, tracker);
|
|
32
32
|
for (const arg of operation.args) {
|
|
33
33
|
typeRefToTsType(arg.type, tracker);
|
|
34
34
|
}
|
|
35
|
+
const resultTsType = typeRefToTsTypeAST(operation.returnType);
|
|
35
36
|
const selectTypeName = getSelectTypeName(operation.returnType);
|
|
36
37
|
const payloadTypeName = getTypeBaseName(operation.returnType);
|
|
37
38
|
const hasSelect = !!selectTypeName && !!payloadTypeName;
|
|
@@ -69,7 +70,7 @@ export function generateCustomQueryHook(options) {
|
|
|
69
70
|
statements.push(createImportDeclaration('../../orm/input-types', inputTypeImports, true));
|
|
70
71
|
}
|
|
71
72
|
if (hasSelect) {
|
|
72
|
-
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', '
|
|
73
|
+
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect'], true));
|
|
73
74
|
}
|
|
74
75
|
// Re-exports
|
|
75
76
|
if (hasArgs) {
|
|
@@ -121,9 +122,12 @@ export function generateCustomQueryHook(options) {
|
|
|
121
122
|
// Helper to build the fields+StrictSelect intersection type
|
|
122
123
|
const fieldsSelectionType = (s) => t.tsParenthesizedType(t.tsIntersectionType([
|
|
123
124
|
t.tsTypeLiteral([
|
|
124
|
-
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(s)),
|
|
125
|
+
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(t.tsIntersectionType([s, typeRef(selectTypeName)]))),
|
|
126
|
+
]),
|
|
127
|
+
typeRef('HookStrictSelect', [
|
|
128
|
+
typeRef('NoInfer', [s]),
|
|
129
|
+
typeRef(selectTypeName),
|
|
125
130
|
]),
|
|
126
|
-
typeRef('StrictSelect', [s, typeRef(selectTypeName)]),
|
|
127
131
|
]));
|
|
128
132
|
const selectedResultType = (sel) => customSelectResultTypeLiteral(operation.name, operation.returnType, payloadTypeName, sel);
|
|
129
133
|
// Hook
|
|
@@ -141,10 +145,11 @@ export function generateCustomQueryHook(options) {
|
|
|
141
145
|
// Overload 1: with selection.fields
|
|
142
146
|
const o1Props = [];
|
|
143
147
|
if (hasArgs) {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
+
const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName)));
|
|
149
|
+
if (!hasRequiredArgs) {
|
|
150
|
+
varProp.optional = true;
|
|
151
|
+
}
|
|
152
|
+
o1Props.push(varProp);
|
|
148
153
|
}
|
|
149
154
|
o1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType(sRef()))));
|
|
150
155
|
const o1ParamType = t.tsIntersectionType([
|
|
@@ -230,7 +235,7 @@ export function generateCustomQueryHook(options) {
|
|
|
230
235
|
else {
|
|
231
236
|
// Without select: simple hook (scalar return type)
|
|
232
237
|
const resultTypeLiteral = t.tsTypeLiteral([
|
|
233
|
-
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(
|
|
238
|
+
t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(resultTsType)),
|
|
234
239
|
]);
|
|
235
240
|
const optType = omitType(typeRef('UseQueryOptions', [
|
|
236
241
|
resultTypeLiteral,
|
|
@@ -309,10 +314,11 @@ export function generateCustomQueryHook(options) {
|
|
|
309
314
|
// Overload 1: with fields
|
|
310
315
|
const f1Props = [];
|
|
311
316
|
if (hasArgs) {
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
317
|
+
const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName)));
|
|
318
|
+
if (!hasRequiredArgs) {
|
|
319
|
+
varProp.optional = true;
|
|
320
|
+
}
|
|
321
|
+
f1Props.push(varProp);
|
|
316
322
|
}
|
|
317
323
|
f1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType(sRef()))));
|
|
318
324
|
const f1Decl = exportAsyncDeclareFunction(fetchFnName, createSTypeParam(selectTypeName), [createFunctionParam('params', t.tsTypeLiteral(f1Props))], typeRef('Promise', [selectedResultType(sRef())]));
|
|
@@ -415,10 +421,11 @@ export function generateCustomQueryHook(options) {
|
|
|
415
421
|
// Overload 1: with fields
|
|
416
422
|
const p1Props = [];
|
|
417
423
|
if (hasArgs) {
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
424
|
+
const varProp = t.tsPropertySignature(t.identifier('variables'), t.tsTypeAnnotation(typeRef(varTypeName)));
|
|
425
|
+
if (!hasRequiredArgs) {
|
|
426
|
+
varProp.optional = true;
|
|
427
|
+
}
|
|
428
|
+
p1Props.push(varProp);
|
|
422
429
|
}
|
|
423
430
|
p1Props.push(t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(fieldsSelectionType(sRef()))));
|
|
424
431
|
const p1Decl = exportAsyncDeclareFunction(prefetchFnName, 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;
|
|
@@ -96,7 +96,10 @@ export function selectionConfigType(selectType) {
|
|
|
96
96
|
return typeRef('SelectionConfig', [selectType]);
|
|
97
97
|
}
|
|
98
98
|
export function strictSelectType(selectType, shapeTypeName) {
|
|
99
|
-
return typeRef('
|
|
99
|
+
return typeRef('HookStrictSelect', [
|
|
100
|
+
typeRef('NoInfer', [selectType]),
|
|
101
|
+
typeRef(shapeTypeName),
|
|
102
|
+
]);
|
|
100
103
|
}
|
|
101
104
|
export function withFieldsSelectionType(selectType, selectTypeName) {
|
|
102
105
|
return t.tsIntersectionType([
|
|
@@ -365,8 +368,15 @@ export function scopeTypeLiteral(scopeTypeName) {
|
|
|
365
368
|
// Type conversion helpers (GraphQL -> AST)
|
|
366
369
|
// ============================================================================
|
|
367
370
|
export function wrapInferSelectResultType(typeRefNode, payloadTypeName, selectType) {
|
|
371
|
+
const nonNullable = wrapInferSelectResultTypeNonNullable(typeRefNode, payloadTypeName, selectType);
|
|
372
|
+
if (typeRefNode.kind === 'NON_NULL') {
|
|
373
|
+
return nonNullable;
|
|
374
|
+
}
|
|
375
|
+
return t.tsUnionType([nonNullable, t.tsNullKeyword()]);
|
|
376
|
+
}
|
|
377
|
+
function wrapInferSelectResultTypeNonNullable(typeRefNode, payloadTypeName, selectType) {
|
|
368
378
|
if (typeRefNode.kind === 'NON_NULL' && typeRefNode.ofType) {
|
|
369
|
-
return
|
|
379
|
+
return wrapInferSelectResultTypeNonNullable(typeRefNode.ofType, payloadTypeName, selectType);
|
|
370
380
|
}
|
|
371
381
|
if (typeRefNode.kind === 'LIST' && typeRefNode.ofType) {
|
|
372
382
|
return t.tsArrayType(wrapInferSelectResultType(typeRefNode.ofType, payloadTypeName, selectType));
|
|
@@ -374,8 +384,15 @@ export function wrapInferSelectResultType(typeRefNode, payloadTypeName, selectTy
|
|
|
374
384
|
return inferSelectResultType(payloadTypeName, selectType);
|
|
375
385
|
}
|
|
376
386
|
export function typeRefToTsTypeAST(typeRefNode) {
|
|
387
|
+
const nonNullable = typeRefToTsTypeASTNonNullable(typeRefNode);
|
|
388
|
+
if (typeRefNode.kind === 'NON_NULL') {
|
|
389
|
+
return nonNullable;
|
|
390
|
+
}
|
|
391
|
+
return t.tsUnionType([nonNullable, t.tsNullKeyword()]);
|
|
392
|
+
}
|
|
393
|
+
function typeRefToTsTypeASTNonNullable(typeRefNode) {
|
|
377
394
|
if (typeRefNode.kind === 'NON_NULL' && typeRefNode.ofType) {
|
|
378
|
-
return
|
|
395
|
+
return typeRefToTsTypeASTNonNullable(typeRefNode.ofType);
|
|
379
396
|
}
|
|
380
397
|
if (typeRefNode.kind === 'LIST' && typeRefNode.ofType) {
|
|
381
398
|
return t.tsArrayType(typeRefToTsTypeAST(typeRefNode.ofType));
|
|
@@ -392,13 +409,13 @@ export function typeRefToTsTypeAST(typeRefNode) {
|
|
|
392
409
|
}
|
|
393
410
|
return typeRef(typeRefNode.name ?? 'unknown');
|
|
394
411
|
}
|
|
395
|
-
export function buildSelectionArgsCall(
|
|
412
|
+
export function buildSelectionArgsCall(selectType) {
|
|
396
413
|
const call = t.callExpression(t.identifier('buildSelectionArgs'), [
|
|
397
414
|
t.memberExpression(t.identifier('params'), t.identifier('selection')),
|
|
398
415
|
]);
|
|
399
416
|
// @ts-ignore - Babel types support typeParameters on CallExpression for TS
|
|
400
417
|
call.typeParameters = t.tsTypeParameterInstantiation([
|
|
401
|
-
typeRef(
|
|
418
|
+
typeof selectType === 'string' ? typeRef(selectType) : selectType,
|
|
402
419
|
]);
|
|
403
420
|
return constDecl('args', call);
|
|
404
421
|
}
|
|
@@ -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?: {
|
|
@@ -26,9 +26,12 @@ function buildMutationResultType(mutationName, singularName, relationTypeName, s
|
|
|
26
26
|
function buildFieldsSelectionType(s, selectTypeName) {
|
|
27
27
|
return t.tsParenthesizedType(t.tsIntersectionType([
|
|
28
28
|
t.tsTypeLiteral([
|
|
29
|
-
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(s)),
|
|
29
|
+
t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation(t.tsIntersectionType([s, typeRef(selectTypeName)]))),
|
|
30
|
+
]),
|
|
31
|
+
typeRef('HookStrictSelect', [
|
|
32
|
+
typeRef('NoInfer', [s]),
|
|
33
|
+
typeRef(selectTypeName),
|
|
30
34
|
]),
|
|
31
|
-
typeRef('StrictSelect', [s, typeRef(selectTypeName)]),
|
|
32
35
|
]));
|
|
33
36
|
}
|
|
34
37
|
export function generateCreateMutationHook(table, options = {}) {
|
|
@@ -58,7 +61,7 @@ export function generateCreateMutationHook(table, options = {}) {
|
|
|
58
61
|
statements.push(createImportDeclaration('../mutation-keys', [mutationKeysName]));
|
|
59
62
|
}
|
|
60
63
|
statements.push(createImportDeclaration('../../orm/input-types', [selectTypeName, relationTypeName, createInputTypeName], true));
|
|
61
|
-
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', '
|
|
64
|
+
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect'], true));
|
|
62
65
|
// Re-exports
|
|
63
66
|
statements.push(createTypeReExport([selectTypeName, relationTypeName, createInputTypeName], '../../orm/input-types'));
|
|
64
67
|
// Variable type: CreateTypeName['singularName']
|
|
@@ -147,6 +150,7 @@ export function generateUpdateMutationHook(table, options = {}) {
|
|
|
147
150
|
const patchTypeName = `${typeName}Patch`;
|
|
148
151
|
const pkFields = getPrimaryKeyInfo(table);
|
|
149
152
|
const pkField = pkFields[0];
|
|
153
|
+
const patchFieldName = table.query?.patchFieldName ?? lcFirst(typeName) + 'Patch';
|
|
150
154
|
const pkTsType = pkField.tsType === 'string' ? t.tsStringKeyword() : t.tsNumberKeyword();
|
|
151
155
|
const statements = [];
|
|
152
156
|
// Imports
|
|
@@ -163,13 +167,13 @@ export function generateUpdateMutationHook(table, options = {}) {
|
|
|
163
167
|
statements.push(createImportDeclaration('../mutation-keys', [mutationKeysName]));
|
|
164
168
|
}
|
|
165
169
|
statements.push(createImportDeclaration('../../orm/input-types', [selectTypeName, relationTypeName, patchTypeName], true));
|
|
166
|
-
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', '
|
|
170
|
+
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect'], true));
|
|
167
171
|
// Re-exports
|
|
168
172
|
statements.push(createTypeReExport([selectTypeName, relationTypeName, patchTypeName], '../../orm/input-types'));
|
|
169
|
-
// Variable type: { pkField: type;
|
|
173
|
+
// Variable type: { pkField: type; patchFieldName: PatchType }
|
|
170
174
|
const updateVarType = t.tsTypeLiteral([
|
|
171
175
|
t.tsPropertySignature(t.identifier(pkField.name), t.tsTypeAnnotation(pkTsType)),
|
|
172
|
-
t.tsPropertySignature(t.identifier(
|
|
176
|
+
t.tsPropertySignature(t.identifier(patchFieldName), t.tsTypeAnnotation(typeRef(patchTypeName))),
|
|
173
177
|
]);
|
|
174
178
|
const resultType = (sel) => buildMutationResultType(mutationName, singularName, relationTypeName, sel);
|
|
175
179
|
// Overload 1: with fields
|
|
@@ -189,7 +193,7 @@ export function generateUpdateMutationHook(table, options = {}) {
|
|
|
189
193
|
' selection: { fields: { id: true, name: true } },',
|
|
190
194
|
'});',
|
|
191
195
|
'',
|
|
192
|
-
`mutate({ ${pkField.name}: 'value-here',
|
|
196
|
+
`mutate({ ${pkField.name}: 'value-here', ${patchFieldName}: { name: 'Updated' } });`,
|
|
193
197
|
'```',
|
|
194
198
|
]);
|
|
195
199
|
statements.push(o1);
|
|
@@ -211,16 +215,16 @@ export function generateUpdateMutationHook(table, options = {}) {
|
|
|
211
215
|
const mutationKeyExpr = useCentralizedKeys
|
|
212
216
|
? t.memberExpression(t.identifier(mutationKeysName), t.identifier('all'))
|
|
213
217
|
: undefined;
|
|
214
|
-
// mutationFn: ({ pkField,
|
|
215
|
-
// getClient().singular.update({ where: { pkField }, data:
|
|
218
|
+
// mutationFn: ({ pkField, patchFieldName }: VarType) =>
|
|
219
|
+
// getClient().singular.update({ where: { pkField }, data: patchFieldName, select: ... }).unwrap()
|
|
216
220
|
const destructParam = t.objectPattern([
|
|
217
221
|
shorthandProp(pkField.name),
|
|
218
|
-
shorthandProp(
|
|
222
|
+
shorthandProp(patchFieldName),
|
|
219
223
|
]);
|
|
220
224
|
destructParam.typeAnnotation = t.tsTypeAnnotation(updateVarType);
|
|
221
225
|
const mutationFnExpr = t.arrowFunctionExpression([destructParam], getClientCallUnwrap(singularName, 'update', t.objectExpression([
|
|
222
226
|
objectProp('where', t.objectExpression([shorthandProp(pkField.name)])),
|
|
223
|
-
objectProp('data', t.identifier(
|
|
227
|
+
objectProp('data', t.identifier(patchFieldName)),
|
|
224
228
|
objectProp('select', t.memberExpression(t.identifier('args'), t.identifier('select'))),
|
|
225
229
|
])));
|
|
226
230
|
// onSuccess: invalidate detail and lists
|
|
@@ -288,7 +292,7 @@ export function generateDeleteMutationHook(table, options = {}) {
|
|
|
288
292
|
statements.push(createImportDeclaration('../mutation-keys', [mutationKeysName]));
|
|
289
293
|
}
|
|
290
294
|
statements.push(createImportDeclaration('../../orm/input-types', [selectTypeName, relationTypeName], true));
|
|
291
|
-
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', '
|
|
295
|
+
statements.push(createImportDeclaration('../../orm/select-types', ['InferSelectResult', 'HookStrictSelect'], true));
|
|
292
296
|
// Re-exports
|
|
293
297
|
statements.push(createTypeReExport([selectTypeName, relationTypeName], '../../orm/input-types'));
|
|
294
298
|
// Variable type: { pkField: type }
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import * as t from '@babel/types';
|
|
8
8
|
import { generateCode } from '../babel-ast';
|
|
9
9
|
import { NON_SELECT_TYPES, getSelectTypeName } from '../select-helpers';
|
|
10
|
-
import { getTypeBaseName, isTypeRequired, typeRefToTsType, } from '../type-resolver';
|
|
10
|
+
import { getTypeBaseName, isTypeRequired, scalarToTsType, typeRefToTsType, } from '../type-resolver';
|
|
11
11
|
import { getGeneratedFileHeader, ucFirst } from '../utils';
|
|
12
12
|
/**
|
|
13
13
|
* Collect all input type names used by operations
|
|
@@ -105,8 +105,15 @@ function parseTypeAnnotation(typeStr) {
|
|
|
105
105
|
return t.tsTypeReference(t.identifier(typeStr));
|
|
106
106
|
}
|
|
107
107
|
function buildSelectedResultTsType(typeRef, payloadTypeName) {
|
|
108
|
+
const nonNullable = buildSelectedResultTsTypeNonNullable(typeRef, payloadTypeName);
|
|
109
|
+
if (typeRef.kind === 'NON_NULL') {
|
|
110
|
+
return nonNullable;
|
|
111
|
+
}
|
|
112
|
+
return t.tsUnionType([nonNullable, t.tsNullKeyword()]);
|
|
113
|
+
}
|
|
114
|
+
function buildSelectedResultTsTypeNonNullable(typeRef, payloadTypeName) {
|
|
108
115
|
if (typeRef.kind === 'NON_NULL' && typeRef.ofType) {
|
|
109
|
-
return
|
|
116
|
+
return buildSelectedResultTsTypeNonNullable(typeRef.ofType, payloadTypeName);
|
|
110
117
|
}
|
|
111
118
|
if (typeRef.kind === 'LIST' && typeRef.ofType) {
|
|
112
119
|
return t.tsArrayType(buildSelectedResultTsType(typeRef.ofType, payloadTypeName));
|
|
@@ -116,6 +123,34 @@ function buildSelectedResultTsType(typeRef, payloadTypeName) {
|
|
|
116
123
|
t.tsTypeReference(t.identifier('S')),
|
|
117
124
|
]));
|
|
118
125
|
}
|
|
126
|
+
function scalarTsTypeToAst(typeName) {
|
|
127
|
+
if (typeName === 'string')
|
|
128
|
+
return t.tsStringKeyword();
|
|
129
|
+
if (typeName === 'number')
|
|
130
|
+
return t.tsNumberKeyword();
|
|
131
|
+
if (typeName === 'boolean')
|
|
132
|
+
return t.tsBooleanKeyword();
|
|
133
|
+
return t.tsUnknownKeyword();
|
|
134
|
+
}
|
|
135
|
+
function buildRawResultTsType(typeRef) {
|
|
136
|
+
const nonNullable = buildRawResultTsTypeNonNullable(typeRef);
|
|
137
|
+
if (typeRef.kind === 'NON_NULL') {
|
|
138
|
+
return nonNullable;
|
|
139
|
+
}
|
|
140
|
+
return t.tsUnionType([nonNullable, t.tsNullKeyword()]);
|
|
141
|
+
}
|
|
142
|
+
function buildRawResultTsTypeNonNullable(typeRef) {
|
|
143
|
+
if (typeRef.kind === 'NON_NULL' && typeRef.ofType) {
|
|
144
|
+
return buildRawResultTsTypeNonNullable(typeRef.ofType);
|
|
145
|
+
}
|
|
146
|
+
if (typeRef.kind === 'LIST' && typeRef.ofType) {
|
|
147
|
+
return t.tsArrayType(buildRawResultTsType(typeRef.ofType));
|
|
148
|
+
}
|
|
149
|
+
if (typeRef.kind === 'SCALAR') {
|
|
150
|
+
return scalarTsTypeToAst(scalarToTsType(typeRef.name ?? 'unknown'));
|
|
151
|
+
}
|
|
152
|
+
return t.tsTypeReference(t.identifier(typeRef.name ?? 'unknown'));
|
|
153
|
+
}
|
|
119
154
|
function buildOperationMethod(op, operationType) {
|
|
120
155
|
const hasArgs = op.args.length > 0;
|
|
121
156
|
const varTypeName = `${ucFirst(op.name)}Variables`;
|
|
@@ -198,10 +233,9 @@ function buildOperationMethod(op, operationType) {
|
|
|
198
233
|
}
|
|
199
234
|
else {
|
|
200
235
|
// Scalar/Connection type: use raw TS type directly
|
|
201
|
-
const rawTsType = typeRefToTsType(op.returnType);
|
|
202
236
|
newExpr.typeParameters = t.tsTypeParameterInstantiation([
|
|
203
237
|
t.tsTypeLiteral([
|
|
204
|
-
t.tsPropertySignature(t.identifier(op.name), t.tsTypeAnnotation(
|
|
238
|
+
t.tsPropertySignature(t.identifier(op.name), t.tsTypeAnnotation(buildRawResultTsType(op.returnType))),
|
|
205
239
|
]),
|
|
206
240
|
]);
|
|
207
241
|
}
|