@constructive-io/graphql-codegen 2.21.0 → 2.22.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/cli/codegen/barrel.d.ts +4 -1
- package/cli/codegen/barrel.js +18 -12
- package/cli/codegen/client.js +33 -0
- package/cli/codegen/custom-mutations.d.ts +4 -0
- package/cli/codegen/custom-mutations.js +39 -13
- package/cli/codegen/custom-queries.d.ts +4 -0
- package/cli/codegen/custom-queries.js +36 -11
- package/cli/codegen/gql-ast.js +9 -5
- package/cli/codegen/index.js +35 -7
- package/cli/codegen/mutations.d.ts +2 -0
- package/cli/codegen/mutations.js +87 -23
- package/cli/codegen/orm/barrel.js +4 -2
- package/cli/codegen/orm/index.js +17 -0
- package/cli/codegen/orm/input-types-generator.js +83 -29
- package/cli/codegen/orm/model-generator.js +6 -4
- package/cli/codegen/queries.js +36 -27
- package/cli/codegen/scalars.d.ts +6 -4
- package/cli/codegen/scalars.js +17 -9
- package/cli/codegen/schema-types-generator.d.ts +26 -0
- package/cli/codegen/schema-types-generator.js +365 -0
- package/cli/codegen/ts-ast.d.ts +3 -1
- package/cli/codegen/ts-ast.js +2 -2
- package/cli/codegen/type-resolver.d.ts +52 -6
- package/cli/codegen/type-resolver.js +97 -19
- package/cli/codegen/types.d.ts +7 -4
- package/cli/codegen/types.js +94 -41
- package/cli/codegen/utils.d.ts +20 -2
- package/cli/codegen/utils.js +32 -7
- package/cli/commands/generate-orm.js +5 -5
- package/cli/commands/generate.d.ts +4 -1
- package/cli/commands/generate.js +27 -8
- package/cli/introspect/transform-schema.d.ts +33 -21
- package/cli/introspect/transform-schema.js +31 -21
- package/esm/cli/codegen/barrel.d.ts +4 -1
- package/esm/cli/codegen/barrel.js +18 -12
- package/esm/cli/codegen/client.js +33 -0
- package/esm/cli/codegen/custom-mutations.d.ts +4 -0
- package/esm/cli/codegen/custom-mutations.js +40 -14
- package/esm/cli/codegen/custom-queries.d.ts +4 -0
- package/esm/cli/codegen/custom-queries.js +37 -12
- package/esm/cli/codegen/gql-ast.js +10 -6
- package/esm/cli/codegen/index.js +35 -7
- package/esm/cli/codegen/mutations.d.ts +2 -0
- package/esm/cli/codegen/mutations.js +88 -24
- package/esm/cli/codegen/orm/barrel.js +4 -2
- package/esm/cli/codegen/orm/index.js +17 -0
- package/esm/cli/codegen/orm/input-types-generator.js +83 -29
- package/esm/cli/codegen/orm/model-generator.js +7 -5
- package/esm/cli/codegen/queries.js +37 -28
- package/esm/cli/codegen/scalars.d.ts +6 -4
- package/esm/cli/codegen/scalars.js +16 -8
- package/esm/cli/codegen/schema-types-generator.d.ts +26 -0
- package/esm/cli/codegen/schema-types-generator.js +362 -0
- package/esm/cli/codegen/ts-ast.d.ts +3 -1
- package/esm/cli/codegen/ts-ast.js +2 -2
- package/esm/cli/codegen/type-resolver.d.ts +52 -6
- package/esm/cli/codegen/type-resolver.js +97 -20
- package/esm/cli/codegen/types.d.ts +7 -4
- package/esm/cli/codegen/types.js +95 -41
- package/esm/cli/codegen/utils.d.ts +20 -2
- package/esm/cli/codegen/utils.js +31 -7
- package/esm/cli/commands/generate-orm.js +5 -5
- package/esm/cli/commands/generate.d.ts +4 -1
- package/esm/cli/commands/generate.js +27 -8
- package/esm/cli/introspect/transform-schema.d.ts +33 -21
- package/esm/cli/introspect/transform-schema.js +31 -21
- package/esm/types/schema.d.ts +2 -0
- package/package.json +8 -6
- package/types/schema.d.ts +2 -0
- package/__tests__/codegen/input-types-generator.test.d.ts +0 -1
- package/__tests__/codegen/input-types-generator.test.js +0 -635
- package/__tests__/codegen/react-query-optional.test.d.ts +0 -1
- package/__tests__/codegen/react-query-optional.test.js +0 -292
- package/cli/codegen/filters.d.ts +0 -27
- package/cli/codegen/filters.js +0 -357
- package/cli/codegen/orm/input-types-generator.test.d.ts +0 -1
- package/cli/codegen/orm/input-types-generator.test.js +0 -75
- package/cli/codegen/orm/select-types.test.d.ts +0 -11
- package/cli/codegen/orm/select-types.test.js +0 -22
- package/cli/introspect/transform-schema.test.d.ts +0 -1
- package/cli/introspect/transform-schema.test.js +0 -67
- package/esm/__tests__/codegen/input-types-generator.test.d.ts +0 -1
- package/esm/__tests__/codegen/input-types-generator.test.js +0 -633
- package/esm/__tests__/codegen/react-query-optional.test.d.ts +0 -1
- package/esm/__tests__/codegen/react-query-optional.test.js +0 -290
- package/esm/cli/codegen/filters.d.ts +0 -27
- package/esm/cli/codegen/filters.js +0 -351
- package/esm/cli/codegen/orm/input-types-generator.test.d.ts +0 -1
- package/esm/cli/codegen/orm/input-types-generator.test.js +0 -73
- package/esm/cli/codegen/orm/select-types.test.d.ts +0 -11
- package/esm/cli/codegen/orm/select-types.test.js +0 -21
- package/esm/cli/introspect/transform-schema.test.d.ts +0 -1
- package/esm/cli/introspect/transform-schema.test.js +0 -65
package/cli/codegen/barrel.d.ts
CHANGED
|
@@ -15,8 +15,11 @@ export declare function generateQueriesBarrel(tables: CleanTable[]): string;
|
|
|
15
15
|
export declare function generateMutationsBarrel(tables: CleanTable[]): string;
|
|
16
16
|
/**
|
|
17
17
|
* Generate the main index.ts barrel file
|
|
18
|
+
*
|
|
19
|
+
* @param tables - The tables to include in the SDK
|
|
20
|
+
* @param hasSchemaTypes - Whether schema-types.ts was generated
|
|
18
21
|
*/
|
|
19
|
-
export declare function generateMainBarrel(tables: CleanTable[]): string;
|
|
22
|
+
export declare function generateMainBarrel(tables: CleanTable[], hasSchemaTypes?: boolean): string;
|
|
20
23
|
/**
|
|
21
24
|
* Generate queries barrel including custom query operations
|
|
22
25
|
*/
|
package/cli/codegen/barrel.js
CHANGED
|
@@ -12,10 +12,7 @@ const type_resolver_1 = require("./type-resolver");
|
|
|
12
12
|
* Generate the queries/index.ts barrel file
|
|
13
13
|
*/
|
|
14
14
|
function generateQueriesBarrel(tables) {
|
|
15
|
-
const lines = [
|
|
16
|
-
(0, ts_ast_1.createFileHeader)('Query hooks barrel export'),
|
|
17
|
-
'',
|
|
18
|
-
];
|
|
15
|
+
const lines = [(0, ts_ast_1.createFileHeader)('Query hooks barrel export'), ''];
|
|
19
16
|
// Export all query hooks
|
|
20
17
|
for (const table of tables) {
|
|
21
18
|
const listHookName = (0, utils_1.getListQueryHookName)(table);
|
|
@@ -51,31 +48,40 @@ function generateMutationsBarrel(tables) {
|
|
|
51
48
|
}
|
|
52
49
|
/**
|
|
53
50
|
* Generate the main index.ts barrel file
|
|
51
|
+
*
|
|
52
|
+
* @param tables - The tables to include in the SDK
|
|
53
|
+
* @param hasSchemaTypes - Whether schema-types.ts was generated
|
|
54
54
|
*/
|
|
55
|
-
function generateMainBarrel(tables) {
|
|
55
|
+
function generateMainBarrel(tables, hasSchemaTypes = false) {
|
|
56
56
|
const tableNames = tables.map((t) => t.name).join(', ');
|
|
57
|
+
const schemaTypesExport = hasSchemaTypes
|
|
58
|
+
? `
|
|
59
|
+
// Schema types (input, payload, enum types)
|
|
60
|
+
export * from './schema-types';
|
|
61
|
+
`
|
|
62
|
+
: '';
|
|
57
63
|
return `/**
|
|
58
64
|
* Auto-generated GraphQL SDK
|
|
59
65
|
* @generated by @constructive-io/graphql-codegen
|
|
60
|
-
*
|
|
66
|
+
*
|
|
61
67
|
* Tables: ${tableNames}
|
|
62
|
-
*
|
|
68
|
+
*
|
|
63
69
|
* Usage:
|
|
64
|
-
*
|
|
70
|
+
*
|
|
65
71
|
* 1. Configure the client:
|
|
66
72
|
* \`\`\`ts
|
|
67
73
|
* import { configure } from './generated';
|
|
68
|
-
*
|
|
74
|
+
*
|
|
69
75
|
* configure({
|
|
70
76
|
* endpoint: 'https://api.example.com/graphql',
|
|
71
77
|
* headers: { Authorization: 'Bearer <token>' },
|
|
72
78
|
* });
|
|
73
79
|
* \`\`\`
|
|
74
|
-
*
|
|
80
|
+
*
|
|
75
81
|
* 2. Use the hooks:
|
|
76
82
|
* \`\`\`tsx
|
|
77
83
|
* import { useCarsQuery, useCreateCarMutation } from './generated';
|
|
78
|
-
*
|
|
84
|
+
*
|
|
79
85
|
* function MyComponent() {
|
|
80
86
|
* const { data, isLoading } = useCarsQuery({ first: 10 });
|
|
81
87
|
* const { mutate } = useCreateCarMutation();
|
|
@@ -89,7 +95,7 @@ export * from './client';
|
|
|
89
95
|
|
|
90
96
|
// Entity and filter types
|
|
91
97
|
export * from './types';
|
|
92
|
-
|
|
98
|
+
${schemaTypesExport}
|
|
93
99
|
// Query hooks
|
|
94
100
|
export * from './queries';
|
|
95
101
|
|
package/cli/codegen/client.js
CHANGED
|
@@ -56,6 +56,39 @@ export function getConfig(): GraphQLClientConfig {
|
|
|
56
56
|
return globalConfig;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Set a single header value
|
|
61
|
+
* Useful for updating Authorization after login
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* \`\`\`ts
|
|
65
|
+
* setHeader('Authorization', 'Bearer <new-token>');
|
|
66
|
+
* \`\`\`
|
|
67
|
+
*/
|
|
68
|
+
export function setHeader(key: string, value: string): void {
|
|
69
|
+
const config = getConfig();
|
|
70
|
+
globalConfig = {
|
|
71
|
+
...config,
|
|
72
|
+
headers: { ...config.headers, [key]: value },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Merge multiple headers into the current configuration
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* \`\`\`ts
|
|
81
|
+
* setHeaders({ Authorization: 'Bearer <token>', 'X-Custom': 'value' });
|
|
82
|
+
* \`\`\`
|
|
83
|
+
*/
|
|
84
|
+
export function setHeaders(headers: Record<string, string>): void {
|
|
85
|
+
const config = getConfig();
|
|
86
|
+
globalConfig = {
|
|
87
|
+
...config,
|
|
88
|
+
headers: { ...config.headers, ...headers },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
59
92
|
// ============================================================================
|
|
60
93
|
// Error handling
|
|
61
94
|
// ============================================================================
|
|
@@ -23,6 +23,8 @@ export interface GenerateCustomMutationHookOptions {
|
|
|
23
23
|
skipQueryField?: boolean;
|
|
24
24
|
/** Whether to generate React Query hooks (default: true for backwards compatibility) */
|
|
25
25
|
reactQueryEnabled?: boolean;
|
|
26
|
+
/** Table entity type names (for import path resolution) */
|
|
27
|
+
tableTypeNames?: Set<string>;
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
28
30
|
* Generate a custom mutation hook file
|
|
@@ -36,6 +38,8 @@ export interface GenerateAllCustomMutationHooksOptions {
|
|
|
36
38
|
skipQueryField?: boolean;
|
|
37
39
|
/** Whether to generate React Query hooks (default: true for backwards compatibility) */
|
|
38
40
|
reactQueryEnabled?: boolean;
|
|
41
|
+
/** Table entity type names (for import path resolution) */
|
|
42
|
+
tableTypeNames?: Set<string>;
|
|
39
43
|
}
|
|
40
44
|
/**
|
|
41
45
|
* Generate all custom mutation hook files
|
|
@@ -25,13 +25,15 @@ function generateCustomMutationHook(options) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
function generateCustomMutationHookInternal(options) {
|
|
28
|
-
const { operation, typeRegistry, maxDepth = 2, skipQueryField = true } = options;
|
|
28
|
+
const { operation, typeRegistry, maxDepth = 2, skipQueryField = true, tableTypeNames } = options;
|
|
29
29
|
const project = (0, ts_ast_1.createProject)();
|
|
30
30
|
const hookName = (0, type_resolver_1.getOperationHookName)(operation.name, 'mutation');
|
|
31
31
|
const fileName = (0, type_resolver_1.getOperationFileName)(operation.name, 'mutation');
|
|
32
32
|
const variablesTypeName = (0, type_resolver_1.getOperationVariablesTypeName)(operation.name, 'mutation');
|
|
33
33
|
const resultTypeName = (0, type_resolver_1.getOperationResultTypeName)(operation.name, 'mutation');
|
|
34
34
|
const documentConstName = (0, type_resolver_1.getDocumentConstName)(operation.name, 'mutation');
|
|
35
|
+
// Create type tracker to collect referenced types (with table type awareness)
|
|
36
|
+
const tracker = (0, type_resolver_1.createTypeTracker)({ tableTypeNames });
|
|
35
37
|
// Generate GraphQL document
|
|
36
38
|
const mutationDocument = (0, schema_gql_ast_1.buildCustomMutationString)({
|
|
37
39
|
operation,
|
|
@@ -42,8 +44,21 @@ function generateCustomMutationHookInternal(options) {
|
|
|
42
44
|
const sourceFile = (0, ts_ast_1.createSourceFile)(project, fileName);
|
|
43
45
|
// Add file header
|
|
44
46
|
sourceFile.insertText(0, (0, ts_ast_1.createFileHeader)(`Custom mutation hook for ${operation.name}`) + '\n\n');
|
|
47
|
+
// Generate variables interface if there are arguments (with tracking)
|
|
48
|
+
let variablesProps = [];
|
|
49
|
+
if (operation.args.length > 0) {
|
|
50
|
+
variablesProps = generateVariablesProperties(operation.args, tracker);
|
|
51
|
+
}
|
|
52
|
+
// Generate result interface (with tracking)
|
|
53
|
+
const resultType = (0, type_resolver_1.typeRefToTsType)(operation.returnType, tracker);
|
|
54
|
+
const resultProps = [
|
|
55
|
+
{ name: operation.name, type: resultType },
|
|
56
|
+
];
|
|
57
|
+
// Get importable types from tracker (separated by source)
|
|
58
|
+
const schemaTypes = tracker.getImportableTypes(); // From schema-types.ts
|
|
59
|
+
const tableTypes = tracker.getTableTypes(); // From types.ts
|
|
45
60
|
// Add imports
|
|
46
|
-
|
|
61
|
+
const imports = [
|
|
47
62
|
(0, ts_ast_1.createImport)({
|
|
48
63
|
moduleSpecifier: '@tanstack/react-query',
|
|
49
64
|
namedImports: ['useMutation'],
|
|
@@ -53,21 +68,31 @@ function generateCustomMutationHookInternal(options) {
|
|
|
53
68
|
moduleSpecifier: '../client',
|
|
54
69
|
namedImports: ['execute'],
|
|
55
70
|
}),
|
|
56
|
-
]
|
|
71
|
+
];
|
|
72
|
+
// Add types.ts import for table entity types
|
|
73
|
+
if (tableTypes.length > 0) {
|
|
74
|
+
imports.push((0, ts_ast_1.createImport)({
|
|
75
|
+
moduleSpecifier: '../types',
|
|
76
|
+
typeOnlyNamedImports: tableTypes,
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
// Add schema-types import for Input/Payload/Enum types
|
|
80
|
+
if (schemaTypes.length > 0) {
|
|
81
|
+
imports.push((0, ts_ast_1.createImport)({
|
|
82
|
+
moduleSpecifier: '../schema-types',
|
|
83
|
+
typeOnlyNamedImports: schemaTypes,
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
sourceFile.addImportDeclarations(imports);
|
|
57
87
|
// Add mutation document constant
|
|
58
88
|
sourceFile.addVariableStatement((0, ts_ast_1.createConst)(documentConstName, '`\n' + mutationDocument + '`', {
|
|
59
89
|
docs: ['GraphQL mutation document'],
|
|
60
90
|
}));
|
|
61
|
-
//
|
|
91
|
+
// Add variables interface
|
|
62
92
|
if (operation.args.length > 0) {
|
|
63
|
-
const variablesProps = generateVariablesProperties(operation.args);
|
|
64
93
|
sourceFile.addInterface((0, ts_ast_1.createInterface)(variablesTypeName, variablesProps));
|
|
65
94
|
}
|
|
66
|
-
//
|
|
67
|
-
const resultType = (0, type_resolver_1.typeRefToTsType)(operation.returnType);
|
|
68
|
-
const resultProps = [
|
|
69
|
-
{ name: operation.name, type: resultType },
|
|
70
|
-
];
|
|
95
|
+
// Add result interface
|
|
71
96
|
sourceFile.addInterface((0, ts_ast_1.createInterface)(resultTypeName, resultProps));
|
|
72
97
|
// Generate hook function
|
|
73
98
|
const hookParams = generateHookParameters(operation, variablesTypeName, resultTypeName);
|
|
@@ -91,10 +116,10 @@ function generateCustomMutationHookInternal(options) {
|
|
|
91
116
|
/**
|
|
92
117
|
* Generate interface properties from CleanArguments
|
|
93
118
|
*/
|
|
94
|
-
function generateVariablesProperties(args) {
|
|
119
|
+
function generateVariablesProperties(args, tracker) {
|
|
95
120
|
return args.map((arg) => ({
|
|
96
121
|
name: arg.name,
|
|
97
|
-
type: (0, type_resolver_1.typeRefToTsType)(arg.type),
|
|
122
|
+
type: (0, type_resolver_1.typeRefToTsType)(arg.type, tracker),
|
|
98
123
|
optional: !(0, type_resolver_1.isTypeRequired)(arg.type),
|
|
99
124
|
docs: arg.description ? [arg.description] : undefined,
|
|
100
125
|
}));
|
|
@@ -143,7 +168,7 @@ function generateHookBody(operation, documentConstName, variablesTypeName, resul
|
|
|
143
168
|
* When reactQueryEnabled is false, returns empty array since mutations require React Query
|
|
144
169
|
*/
|
|
145
170
|
function generateAllCustomMutationHooks(options) {
|
|
146
|
-
const { operations, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true } = options;
|
|
171
|
+
const { operations, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true, tableTypeNames } = options;
|
|
147
172
|
return operations
|
|
148
173
|
.filter((op) => op.kind === 'mutation')
|
|
149
174
|
.map((operation) => generateCustomMutationHook({
|
|
@@ -152,6 +177,7 @@ function generateAllCustomMutationHooks(options) {
|
|
|
152
177
|
maxDepth,
|
|
153
178
|
skipQueryField,
|
|
154
179
|
reactQueryEnabled,
|
|
180
|
+
tableTypeNames,
|
|
155
181
|
}))
|
|
156
182
|
.filter((result) => result !== null);
|
|
157
183
|
}
|
|
@@ -23,6 +23,8 @@ export interface GenerateCustomQueryHookOptions {
|
|
|
23
23
|
skipQueryField?: boolean;
|
|
24
24
|
/** Whether to generate React Query hooks (default: true for backwards compatibility) */
|
|
25
25
|
reactQueryEnabled?: boolean;
|
|
26
|
+
/** Table entity type names (for import path resolution) */
|
|
27
|
+
tableTypeNames?: Set<string>;
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
28
30
|
* Generate a custom query hook file
|
|
@@ -35,6 +37,8 @@ export interface GenerateAllCustomQueryHooksOptions {
|
|
|
35
37
|
skipQueryField?: boolean;
|
|
36
38
|
/** Whether to generate React Query hooks (default: true for backwards compatibility) */
|
|
37
39
|
reactQueryEnabled?: boolean;
|
|
40
|
+
/** Table entity type names (for import path resolution) */
|
|
41
|
+
tableTypeNames?: Set<string>;
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
40
44
|
* Generate all custom query hook files
|
|
@@ -10,7 +10,7 @@ const utils_1 = require("./utils");
|
|
|
10
10
|
* Generate a custom query hook file
|
|
11
11
|
*/
|
|
12
12
|
function generateCustomQueryHook(options) {
|
|
13
|
-
const { operation, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true } = options;
|
|
13
|
+
const { operation, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true, tableTypeNames } = options;
|
|
14
14
|
const project = (0, ts_ast_1.createProject)();
|
|
15
15
|
const hookName = (0, type_resolver_1.getOperationHookName)(operation.name, 'query');
|
|
16
16
|
const fileName = (0, type_resolver_1.getOperationFileName)(operation.name, 'query');
|
|
@@ -18,6 +18,8 @@ function generateCustomQueryHook(options) {
|
|
|
18
18
|
const resultTypeName = (0, type_resolver_1.getOperationResultTypeName)(operation.name, 'query');
|
|
19
19
|
const documentConstName = (0, type_resolver_1.getDocumentConstName)(operation.name, 'query');
|
|
20
20
|
const queryKeyName = (0, type_resolver_1.getQueryKeyName)(operation.name);
|
|
21
|
+
// Create type tracker to collect referenced types (with table type awareness)
|
|
22
|
+
const tracker = (0, type_resolver_1.createTypeTracker)({ tableTypeNames });
|
|
21
23
|
// Generate GraphQL document
|
|
22
24
|
const queryDocument = (0, schema_gql_ast_1.buildCustomQueryString)({
|
|
23
25
|
operation,
|
|
@@ -31,6 +33,19 @@ function generateCustomQueryHook(options) {
|
|
|
31
33
|
? `Custom query hook for ${operation.name}`
|
|
32
34
|
: `Custom query functions for ${operation.name}`;
|
|
33
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)
|
|
42
|
+
const resultType = (0, type_resolver_1.typeRefToTsType)(operation.returnType, tracker);
|
|
43
|
+
const resultProps = [
|
|
44
|
+
{ name: operation.name, type: resultType },
|
|
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
|
|
34
49
|
// Add imports - conditionally include React Query imports
|
|
35
50
|
const imports = [];
|
|
36
51
|
if (reactQueryEnabled) {
|
|
@@ -45,21 +60,30 @@ function generateCustomQueryHook(options) {
|
|
|
45
60
|
namedImports: ['execute'],
|
|
46
61
|
typeOnlyNamedImports: ['ExecuteOptions'],
|
|
47
62
|
}));
|
|
63
|
+
// Add types.ts import for table entity types
|
|
64
|
+
if (tableTypes.length > 0) {
|
|
65
|
+
imports.push((0, ts_ast_1.createImport)({
|
|
66
|
+
moduleSpecifier: '../types',
|
|
67
|
+
typeOnlyNamedImports: tableTypes,
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
// Add schema-types import for Input/Payload/Enum types
|
|
71
|
+
if (schemaTypes.length > 0) {
|
|
72
|
+
imports.push((0, ts_ast_1.createImport)({
|
|
73
|
+
moduleSpecifier: '../schema-types',
|
|
74
|
+
typeOnlyNamedImports: schemaTypes,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
48
77
|
sourceFile.addImportDeclarations(imports);
|
|
49
78
|
// Add query document constant
|
|
50
79
|
sourceFile.addVariableStatement((0, ts_ast_1.createConst)(documentConstName, '`\n' + queryDocument + '`', {
|
|
51
80
|
docs: ['GraphQL query document'],
|
|
52
81
|
}));
|
|
53
|
-
//
|
|
82
|
+
// Add variables interface
|
|
54
83
|
if (operation.args.length > 0) {
|
|
55
|
-
const variablesProps = generateVariablesProperties(operation.args);
|
|
56
84
|
sourceFile.addInterface((0, ts_ast_1.createInterface)(variablesTypeName, variablesProps));
|
|
57
85
|
}
|
|
58
|
-
//
|
|
59
|
-
const resultType = (0, type_resolver_1.typeRefToTsType)(operation.returnType);
|
|
60
|
-
const resultProps = [
|
|
61
|
-
{ name: operation.name, type: resultType },
|
|
62
|
-
];
|
|
86
|
+
// Add result interface
|
|
63
87
|
sourceFile.addInterface((0, ts_ast_1.createInterface)(resultTypeName, resultProps));
|
|
64
88
|
// Query key factory
|
|
65
89
|
if (operation.args.length > 0) {
|
|
@@ -130,10 +154,10 @@ function generateCustomQueryHook(options) {
|
|
|
130
154
|
/**
|
|
131
155
|
* Generate interface properties from CleanArguments
|
|
132
156
|
*/
|
|
133
|
-
function generateVariablesProperties(args) {
|
|
157
|
+
function generateVariablesProperties(args, tracker) {
|
|
134
158
|
return args.map((arg) => ({
|
|
135
159
|
name: arg.name,
|
|
136
|
-
type: (0, type_resolver_1.typeRefToTsType)(arg.type),
|
|
160
|
+
type: (0, type_resolver_1.typeRefToTsType)(arg.type, tracker),
|
|
137
161
|
optional: !(0, type_resolver_1.isTypeRequired)(arg.type),
|
|
138
162
|
docs: arg.description ? [arg.description] : undefined,
|
|
139
163
|
}));
|
|
@@ -355,7 +379,7 @@ await ${fnName}(queryClient);
|
|
|
355
379
|
* Generate all custom query hook files
|
|
356
380
|
*/
|
|
357
381
|
function generateAllCustomQueryHooks(options) {
|
|
358
|
-
const { operations, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true } = options;
|
|
382
|
+
const { operations, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true, tableTypeNames } = options;
|
|
359
383
|
return operations
|
|
360
384
|
.filter((op) => op.kind === 'query')
|
|
361
385
|
.map((operation) => generateCustomQueryHook({
|
|
@@ -364,5 +388,6 @@ function generateAllCustomQueryHooks(options) {
|
|
|
364
388
|
maxDepth,
|
|
365
389
|
skipQueryField,
|
|
366
390
|
reactQueryEnabled,
|
|
391
|
+
tableTypeNames,
|
|
367
392
|
}));
|
|
368
393
|
}
|
package/cli/codegen/gql-ast.js
CHANGED
|
@@ -147,16 +147,20 @@ function buildSingleQueryAST(config) {
|
|
|
147
147
|
const { table } = config;
|
|
148
148
|
const queryName = (0, utils_1.getSingleRowQueryName)(table);
|
|
149
149
|
const scalarFields = (0, utils_1.getScalarFields)(table);
|
|
150
|
-
//
|
|
150
|
+
// Get primary key info dynamically from table constraints
|
|
151
|
+
const pkFields = (0, utils_1.getPrimaryKeyInfo)(table);
|
|
152
|
+
// For simplicity, use first PK field (most common case)
|
|
153
|
+
const pkField = pkFields[0];
|
|
154
|
+
// Variable definitions - use dynamic PK field name and type
|
|
151
155
|
const variableDefinitions = [
|
|
152
156
|
t.variableDefinition({
|
|
153
|
-
variable: t.variable({ name:
|
|
154
|
-
type: t.nonNullType({ type: t.namedType({ type:
|
|
157
|
+
variable: t.variable({ name: pkField.name }),
|
|
158
|
+
type: t.nonNullType({ type: t.namedType({ type: pkField.gqlType }) }),
|
|
155
159
|
}),
|
|
156
160
|
];
|
|
157
|
-
// Query arguments
|
|
161
|
+
// Query arguments - use dynamic PK field name
|
|
158
162
|
const args = [
|
|
159
|
-
t.argument({ name:
|
|
163
|
+
t.argument({ name: pkField.name, value: t.variable({ name: pkField.name }) }),
|
|
160
164
|
];
|
|
161
165
|
// Field selections
|
|
162
166
|
const fieldSelections = createFieldSelections(scalarFields);
|
package/cli/codegen/index.js
CHANGED
|
@@ -5,11 +5,13 @@ exports.generateAllFiles = generateAllFiles;
|
|
|
5
5
|
exports.generate = generate;
|
|
6
6
|
const client_1 = require("./client");
|
|
7
7
|
const types_1 = require("./types");
|
|
8
|
+
const schema_types_generator_1 = require("./schema-types-generator");
|
|
8
9
|
const queries_1 = require("./queries");
|
|
9
10
|
const mutations_1 = require("./mutations");
|
|
10
11
|
const custom_queries_1 = require("./custom-queries");
|
|
11
12
|
const custom_mutations_1 = require("./custom-mutations");
|
|
12
13
|
const barrel_1 = require("./barrel");
|
|
14
|
+
const utils_1 = require("./utils");
|
|
13
15
|
// ============================================================================
|
|
14
16
|
// Main orchestrator
|
|
15
17
|
// ============================================================================
|
|
@@ -34,12 +36,33 @@ function generate(options) {
|
|
|
34
36
|
path: 'client.ts',
|
|
35
37
|
content: (0, client_1.generateClientFile)(),
|
|
36
38
|
});
|
|
37
|
-
//
|
|
39
|
+
// Collect table type names for import path resolution
|
|
40
|
+
const tableTypeNames = new Set(tables.map((t) => (0, utils_1.getTableNames)(t).typeName));
|
|
41
|
+
// 2. Generate schema-types.ts for custom operations (if any)
|
|
42
|
+
// NOTE: This must come BEFORE types.ts so that types.ts can import enum types
|
|
43
|
+
let hasSchemaTypes = false;
|
|
44
|
+
let generatedEnumNames = [];
|
|
45
|
+
if (customOperations && customOperations.typeRegistry) {
|
|
46
|
+
const schemaTypesResult = (0, schema_types_generator_1.generateSchemaTypesFile)({
|
|
47
|
+
typeRegistry: customOperations.typeRegistry,
|
|
48
|
+
tableTypeNames,
|
|
49
|
+
});
|
|
50
|
+
// Only include if there's meaningful content
|
|
51
|
+
if (schemaTypesResult.content.split('\n').length > 10) {
|
|
52
|
+
files.push({
|
|
53
|
+
path: 'schema-types.ts',
|
|
54
|
+
content: schemaTypesResult.content,
|
|
55
|
+
});
|
|
56
|
+
hasSchemaTypes = true;
|
|
57
|
+
generatedEnumNames = schemaTypesResult.generatedEnums || [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 3. Generate types.ts (can now import enums from schema-types)
|
|
38
61
|
files.push({
|
|
39
62
|
path: 'types.ts',
|
|
40
|
-
content: (0, types_1.generateTypesFile)(tables),
|
|
63
|
+
content: (0, types_1.generateTypesFile)(tables, { enumsFromSchemaTypes: generatedEnumNames }),
|
|
41
64
|
});
|
|
42
|
-
//
|
|
65
|
+
// 4. Generate table-based query hooks (queries/*.ts)
|
|
43
66
|
const queryHooks = (0, queries_1.generateAllQueryHooks)(tables, { reactQueryEnabled });
|
|
44
67
|
for (const hook of queryHooks) {
|
|
45
68
|
files.push({
|
|
@@ -47,7 +70,7 @@ function generate(options) {
|
|
|
47
70
|
content: hook.content,
|
|
48
71
|
});
|
|
49
72
|
}
|
|
50
|
-
//
|
|
73
|
+
// 5. Generate custom query hooks if available
|
|
51
74
|
let customQueryHooks = [];
|
|
52
75
|
if (customOperations && customOperations.queries.length > 0) {
|
|
53
76
|
customQueryHooks = (0, custom_queries_1.generateAllCustomQueryHooks)({
|
|
@@ -56,6 +79,7 @@ function generate(options) {
|
|
|
56
79
|
maxDepth,
|
|
57
80
|
skipQueryField,
|
|
58
81
|
reactQueryEnabled,
|
|
82
|
+
tableTypeNames,
|
|
59
83
|
});
|
|
60
84
|
for (const hook of customQueryHooks) {
|
|
61
85
|
files.push({
|
|
@@ -72,7 +96,10 @@ function generate(options) {
|
|
|
72
96
|
: (0, barrel_1.generateQueriesBarrel)(tables),
|
|
73
97
|
});
|
|
74
98
|
// 6. Generate table-based mutation hooks (mutations/*.ts)
|
|
75
|
-
const mutationHooks = (0, mutations_1.generateAllMutationHooks)(tables, {
|
|
99
|
+
const mutationHooks = (0, mutations_1.generateAllMutationHooks)(tables, {
|
|
100
|
+
reactQueryEnabled,
|
|
101
|
+
enumsFromSchemaTypes: generatedEnumNames,
|
|
102
|
+
});
|
|
76
103
|
for (const hook of mutationHooks) {
|
|
77
104
|
files.push({
|
|
78
105
|
path: `mutations/${hook.fileName}`,
|
|
@@ -88,6 +115,7 @@ function generate(options) {
|
|
|
88
115
|
maxDepth,
|
|
89
116
|
skipQueryField,
|
|
90
117
|
reactQueryEnabled,
|
|
118
|
+
tableTypeNames,
|
|
91
119
|
});
|
|
92
120
|
for (const hook of customMutationHooks) {
|
|
93
121
|
files.push({
|
|
@@ -103,10 +131,10 @@ function generate(options) {
|
|
|
103
131
|
? (0, barrel_1.generateCustomMutationsBarrel)(tables, customMutationHooks.map((h) => h.operationName))
|
|
104
132
|
: (0, barrel_1.generateMutationsBarrel)(tables),
|
|
105
133
|
});
|
|
106
|
-
// 9. Generate main index.ts barrel
|
|
134
|
+
// 9. Generate main index.ts barrel (with schema-types if present)
|
|
107
135
|
files.push({
|
|
108
136
|
path: 'index.ts',
|
|
109
|
-
content: (0, barrel_1.generateMainBarrel)(tables),
|
|
137
|
+
content: (0, barrel_1.generateMainBarrel)(tables, hasSchemaTypes),
|
|
110
138
|
});
|
|
111
139
|
return {
|
|
112
140
|
files,
|
|
@@ -15,6 +15,8 @@ export interface GeneratedMutationFile {
|
|
|
15
15
|
export interface MutationGeneratorOptions {
|
|
16
16
|
/** Whether to generate React Query hooks (default: true for backwards compatibility) */
|
|
17
17
|
reactQueryEnabled?: boolean;
|
|
18
|
+
/** Enum type names that are available from schema-types.ts */
|
|
19
|
+
enumsFromSchemaTypes?: string[];
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
22
|
* Generate create mutation hook file content using AST
|