@constructive-io/graphql-codegen 2.23.2 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +147 -2
- package/cli/codegen/babel-ast.d.ts +46 -0
- package/cli/codegen/babel-ast.js +145 -0
- package/cli/codegen/barrel.d.ts +7 -2
- package/cli/codegen/barrel.js +159 -97
- package/cli/codegen/client.js +61 -0
- package/cli/codegen/custom-mutations.d.ts +2 -12
- package/cli/codegen/custom-mutations.js +116 -124
- package/cli/codegen/custom-queries.d.ts +2 -10
- package/cli/codegen/custom-queries.js +246 -335
- package/cli/codegen/index.d.ts +3 -0
- package/cli/codegen/index.js +72 -3
- package/cli/codegen/invalidation.d.ts +20 -0
- package/cli/codegen/invalidation.js +327 -0
- package/cli/codegen/mutation-keys.d.ts +24 -0
- package/cli/codegen/mutation-keys.js +247 -0
- package/cli/codegen/mutations.d.ts +3 -19
- package/cli/codegen/mutations.js +372 -383
- package/cli/codegen/orm/barrel.d.ts +1 -1
- package/cli/codegen/orm/barrel.js +42 -10
- package/cli/codegen/orm/client-generator.d.ts +1 -19
- package/cli/codegen/orm/client-generator.js +108 -77
- package/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
- package/cli/codegen/orm/custom-ops-generator.js +192 -235
- package/cli/codegen/orm/input-types-generator.d.ts +13 -1
- package/cli/codegen/orm/input-types-generator.js +403 -147
- package/cli/codegen/orm/model-generator.d.ts +1 -19
- package/cli/codegen/orm/model-generator.js +229 -234
- package/cli/codegen/queries.d.ts +3 -11
- package/cli/codegen/queries.js +582 -389
- package/cli/codegen/query-keys.d.ts +15 -0
- package/cli/codegen/query-keys.js +477 -0
- package/cli/codegen/scalars.js +1 -0
- package/cli/codegen/schema-types-generator.d.ts +15 -10
- package/cli/codegen/schema-types-generator.js +87 -175
- package/cli/codegen/type-resolver.d.ts +1 -30
- package/cli/codegen/type-resolver.js +0 -53
- package/cli/codegen/types.d.ts +1 -1
- package/cli/codegen/types.js +76 -21
- package/cli/commands/generate.js +1 -0
- package/cli/index.js +1 -0
- package/esm/cli/codegen/babel-ast.d.ts +46 -0
- package/esm/cli/codegen/babel-ast.js +97 -0
- package/esm/cli/codegen/barrel.d.ts +7 -2
- package/esm/cli/codegen/barrel.js +126 -97
- package/esm/cli/codegen/client.js +61 -0
- package/esm/cli/codegen/custom-mutations.d.ts +2 -12
- package/esm/cli/codegen/custom-mutations.js +83 -124
- package/esm/cli/codegen/custom-queries.d.ts +2 -10
- package/esm/cli/codegen/custom-queries.js +214 -336
- package/esm/cli/codegen/index.d.ts +3 -0
- package/esm/cli/codegen/index.js +68 -2
- package/esm/cli/codegen/invalidation.d.ts +20 -0
- package/esm/cli/codegen/invalidation.js +291 -0
- package/esm/cli/codegen/mutation-keys.d.ts +24 -0
- package/esm/cli/codegen/mutation-keys.js +211 -0
- package/esm/cli/codegen/mutations.d.ts +3 -19
- package/esm/cli/codegen/mutations.js +340 -384
- package/esm/cli/codegen/orm/barrel.d.ts +1 -1
- package/esm/cli/codegen/orm/barrel.js +10 -11
- package/esm/cli/codegen/orm/client-generator.d.ts +1 -19
- package/esm/cli/codegen/orm/client-generator.js +76 -78
- package/esm/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
- package/esm/cli/codegen/orm/custom-ops-generator.js +160 -236
- package/esm/cli/codegen/orm/input-types-generator.d.ts +13 -1
- package/esm/cli/codegen/orm/input-types-generator.js +371 -148
- package/esm/cli/codegen/orm/model-generator.d.ts +1 -19
- package/esm/cli/codegen/orm/model-generator.js +197 -235
- package/esm/cli/codegen/queries.d.ts +3 -11
- package/esm/cli/codegen/queries.js +550 -390
- package/esm/cli/codegen/query-keys.d.ts +15 -0
- package/esm/cli/codegen/query-keys.js +441 -0
- package/esm/cli/codegen/scalars.js +1 -0
- package/esm/cli/codegen/schema-types-generator.d.ts +15 -10
- package/esm/cli/codegen/schema-types-generator.js +54 -175
- package/esm/cli/codegen/type-resolver.d.ts +1 -30
- package/esm/cli/codegen/type-resolver.js +0 -49
- package/esm/cli/codegen/types.d.ts +1 -1
- package/esm/cli/codegen/types.js +44 -22
- package/esm/cli/commands/generate.js +1 -0
- package/esm/cli/index.js +1 -0
- package/esm/types/config.d.ts +75 -0
- package/esm/types/config.js +19 -1
- package/package.json +6 -4
- package/types/config.d.ts +75 -0
- package/types/config.js +20 -2
- package/cli/codegen/ts-ast.d.ts +0 -124
- package/cli/codegen/ts-ast.js +0 -280
- package/esm/cli/codegen/ts-ast.d.ts +0 -124
- package/esm/cli/codegen/ts-ast.js +0 -260
package/cli/commands/generate.js
CHANGED
|
@@ -195,6 +195,7 @@ async function loadConfig(options) {
|
|
|
195
195
|
hooks: baseConfig.hooks,
|
|
196
196
|
postgraphile: baseConfig.postgraphile,
|
|
197
197
|
codegen: baseConfig.codegen,
|
|
198
|
+
reactQuery: baseConfig.reactQuery,
|
|
198
199
|
};
|
|
199
200
|
// Validate at least one source is provided
|
|
200
201
|
if (!mergedConfig.endpoint && !mergedConfig.schema) {
|
package/cli/index.js
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Babel AST utilities for code generation
|
|
3
|
+
*
|
|
4
|
+
* Provides minimal helper functions for building TypeScript AST nodes.
|
|
5
|
+
* Use raw t.* calls for most operations - only helpers that provide
|
|
6
|
+
* real value beyond simple wrapping are included here.
|
|
7
|
+
*/
|
|
8
|
+
import generate from '@babel/generator';
|
|
9
|
+
import * as t from '@babel/types';
|
|
10
|
+
export { t, generate };
|
|
11
|
+
/**
|
|
12
|
+
* Generate code from an array of statements
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateCode(statements: t.Statement[]): string;
|
|
15
|
+
/**
|
|
16
|
+
* Create a block comment
|
|
17
|
+
*/
|
|
18
|
+
export declare const commentBlock: (value: string) => t.CommentBlock;
|
|
19
|
+
/**
|
|
20
|
+
* Create a line comment
|
|
21
|
+
*/
|
|
22
|
+
export declare const commentLine: (value: string) => t.CommentLine;
|
|
23
|
+
/**
|
|
24
|
+
* Add a leading JSDoc comment to a node
|
|
25
|
+
*/
|
|
26
|
+
export declare function addJSDocComment<T extends t.Node>(node: T, lines: string[]): T;
|
|
27
|
+
/**
|
|
28
|
+
* Add a leading single-line comment to a node
|
|
29
|
+
*/
|
|
30
|
+
export declare function addLineComment<T extends t.Node>(node: T, text: string): T;
|
|
31
|
+
/**
|
|
32
|
+
* Create an 'as const' assertion - common pattern worth abstracting
|
|
33
|
+
*/
|
|
34
|
+
export declare function asConst(expression: t.Expression): t.TSAsExpression;
|
|
35
|
+
/**
|
|
36
|
+
* Create an array expression with 'as const' - very common pattern
|
|
37
|
+
*/
|
|
38
|
+
export declare function constArray(elements: (t.Expression | t.SpreadElement)[]): t.TSAsExpression;
|
|
39
|
+
/**
|
|
40
|
+
* Create a typed parameter - saves boilerplate for type annotations
|
|
41
|
+
*/
|
|
42
|
+
export declare function typedParam(name: string, typeAnnotation: t.TSType, optional?: boolean): t.Identifier;
|
|
43
|
+
/**
|
|
44
|
+
* Create keyof typeof expression - complex nested type operators
|
|
45
|
+
*/
|
|
46
|
+
export declare function keyofTypeof(name: string): t.TSTypeOperator;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Babel AST utilities for code generation
|
|
3
|
+
*
|
|
4
|
+
* Provides minimal helper functions for building TypeScript AST nodes.
|
|
5
|
+
* Use raw t.* calls for most operations - only helpers that provide
|
|
6
|
+
* real value beyond simple wrapping are included here.
|
|
7
|
+
*/
|
|
8
|
+
import generate from '@babel/generator';
|
|
9
|
+
import * as t from '@babel/types';
|
|
10
|
+
// Re-export for convenience
|
|
11
|
+
export { t, generate };
|
|
12
|
+
/**
|
|
13
|
+
* Generate code from an array of statements
|
|
14
|
+
*/
|
|
15
|
+
export function generateCode(statements) {
|
|
16
|
+
const program = t.program(statements);
|
|
17
|
+
// @ts-ignore - Babel types mismatch
|
|
18
|
+
return generate(program).code;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a block comment
|
|
22
|
+
*/
|
|
23
|
+
export const commentBlock = (value) => {
|
|
24
|
+
return {
|
|
25
|
+
type: 'CommentBlock',
|
|
26
|
+
value,
|
|
27
|
+
start: null,
|
|
28
|
+
end: null,
|
|
29
|
+
loc: null,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Create a line comment
|
|
34
|
+
*/
|
|
35
|
+
export const commentLine = (value) => {
|
|
36
|
+
return {
|
|
37
|
+
type: 'CommentLine',
|
|
38
|
+
value,
|
|
39
|
+
start: null,
|
|
40
|
+
end: null,
|
|
41
|
+
loc: null,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Add a leading JSDoc comment to a node
|
|
46
|
+
*/
|
|
47
|
+
export function addJSDocComment(node, lines) {
|
|
48
|
+
const commentText = lines.length === 1
|
|
49
|
+
? `* ${lines[0]} `
|
|
50
|
+
: `*\n${lines.map(line => ` * ${line}`).join('\n')}\n `;
|
|
51
|
+
if (!node.leadingComments) {
|
|
52
|
+
node.leadingComments = [];
|
|
53
|
+
}
|
|
54
|
+
node.leadingComments.push(commentBlock(commentText));
|
|
55
|
+
return node;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Add a leading single-line comment to a node
|
|
59
|
+
*/
|
|
60
|
+
export function addLineComment(node, text) {
|
|
61
|
+
if (!node.leadingComments) {
|
|
62
|
+
node.leadingComments = [];
|
|
63
|
+
}
|
|
64
|
+
node.leadingComments.push(commentLine(` ${text}`));
|
|
65
|
+
return node;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create an 'as const' assertion - common pattern worth abstracting
|
|
69
|
+
*/
|
|
70
|
+
export function asConst(expression) {
|
|
71
|
+
return t.tsAsExpression(expression, t.tsTypeReference(t.identifier('const')));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create an array expression with 'as const' - very common pattern
|
|
75
|
+
*/
|
|
76
|
+
export function constArray(elements) {
|
|
77
|
+
return asConst(t.arrayExpression(elements));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Create a typed parameter - saves boilerplate for type annotations
|
|
81
|
+
*/
|
|
82
|
+
export function typedParam(name, typeAnnotation, optional = false) {
|
|
83
|
+
const param = t.identifier(name);
|
|
84
|
+
param.typeAnnotation = t.tsTypeAnnotation(typeAnnotation);
|
|
85
|
+
param.optional = optional;
|
|
86
|
+
return param;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Create keyof typeof expression - complex nested type operators
|
|
90
|
+
*/
|
|
91
|
+
export function keyofTypeof(name) {
|
|
92
|
+
const typeofOp = t.tsTypeOperator(t.tsTypeReference(t.identifier(name)));
|
|
93
|
+
typeofOp.operator = 'typeof';
|
|
94
|
+
const keyofOp = t.tsTypeOperator(typeofOp);
|
|
95
|
+
keyofOp.operator = 'keyof';
|
|
96
|
+
return keyofOp;
|
|
97
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Barrel file generators - creates index.ts files for exports
|
|
3
3
|
*
|
|
4
|
-
* Using
|
|
5
|
-
* and ts-morph has issues with insertText + addStatements combination.
|
|
4
|
+
* Using Babel AST for generating barrel (index.ts) files with re-exports.
|
|
6
5
|
*/
|
|
7
6
|
import type { CleanTable } from '../../types/schema';
|
|
8
7
|
/**
|
|
@@ -22,6 +21,12 @@ export declare function generateMutationsBarrel(tables: CleanTable[]): string;
|
|
|
22
21
|
export interface MainBarrelOptions {
|
|
23
22
|
hasSchemaTypes?: boolean;
|
|
24
23
|
hasMutations?: boolean;
|
|
24
|
+
/** Whether query-keys.ts was generated */
|
|
25
|
+
hasQueryKeys?: boolean;
|
|
26
|
+
/** Whether mutation-keys.ts was generated */
|
|
27
|
+
hasMutationKeys?: boolean;
|
|
28
|
+
/** Whether invalidation.ts was generated */
|
|
29
|
+
hasInvalidation?: boolean;
|
|
25
30
|
}
|
|
26
31
|
export declare function generateMainBarrel(tables: CleanTable[], options?: MainBarrelOptions | boolean): string;
|
|
27
32
|
/**
|
|
@@ -1,102 +1,131 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import { generateCode, addJSDocComment } from './babel-ast';
|
|
2
3
|
import { getListQueryHookName, getSingleQueryHookName, getCreateMutationHookName, getUpdateMutationHookName, getDeleteMutationHookName, } from './utils';
|
|
3
4
|
import { getOperationHookName } from './type-resolver';
|
|
5
|
+
/**
|
|
6
|
+
* Helper to create export * from './module' statement
|
|
7
|
+
*/
|
|
8
|
+
function exportAllFrom(modulePath) {
|
|
9
|
+
return t.exportAllDeclaration(t.stringLiteral(modulePath));
|
|
10
|
+
}
|
|
4
11
|
/**
|
|
5
12
|
* Generate the queries/index.ts barrel file
|
|
6
13
|
*/
|
|
7
14
|
export function generateQueriesBarrel(tables) {
|
|
8
|
-
const
|
|
15
|
+
const statements = [];
|
|
9
16
|
// Export all query hooks
|
|
10
17
|
for (const table of tables) {
|
|
11
18
|
const listHookName = getListQueryHookName(table);
|
|
12
19
|
const singleHookName = getSingleQueryHookName(table);
|
|
13
|
-
|
|
14
|
-
|
|
20
|
+
statements.push(exportAllFrom(`./${listHookName}`));
|
|
21
|
+
statements.push(exportAllFrom(`./${singleHookName}`));
|
|
22
|
+
}
|
|
23
|
+
// Add file header as leading comment on first statement
|
|
24
|
+
if (statements.length > 0) {
|
|
25
|
+
addJSDocComment(statements[0], [
|
|
26
|
+
'Query hooks barrel export',
|
|
27
|
+
'@generated by @constructive-io/graphql-codegen',
|
|
28
|
+
'DO NOT EDIT - changes will be overwritten',
|
|
29
|
+
]);
|
|
15
30
|
}
|
|
16
|
-
return
|
|
31
|
+
return generateCode(statements);
|
|
17
32
|
}
|
|
18
33
|
/**
|
|
19
34
|
* Generate the mutations/index.ts barrel file
|
|
20
35
|
*/
|
|
21
36
|
export function generateMutationsBarrel(tables) {
|
|
22
|
-
const
|
|
23
|
-
createFileHeader('Mutation hooks barrel export'),
|
|
24
|
-
'',
|
|
25
|
-
];
|
|
37
|
+
const statements = [];
|
|
26
38
|
// Export all mutation hooks
|
|
27
39
|
for (const table of tables) {
|
|
28
40
|
const createHookName = getCreateMutationHookName(table);
|
|
29
41
|
const updateHookName = getUpdateMutationHookName(table);
|
|
30
42
|
const deleteHookName = getDeleteMutationHookName(table);
|
|
31
|
-
|
|
43
|
+
statements.push(exportAllFrom(`./${createHookName}`));
|
|
32
44
|
// Only add update/delete if they exist
|
|
33
45
|
if (table.query?.update !== null) {
|
|
34
|
-
|
|
46
|
+
statements.push(exportAllFrom(`./${updateHookName}`));
|
|
35
47
|
}
|
|
36
48
|
if (table.query?.delete !== null) {
|
|
37
|
-
|
|
49
|
+
statements.push(exportAllFrom(`./${deleteHookName}`));
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
|
-
|
|
52
|
+
// Add file header as leading comment on first statement
|
|
53
|
+
if (statements.length > 0) {
|
|
54
|
+
addJSDocComment(statements[0], [
|
|
55
|
+
'Mutation hooks barrel export',
|
|
56
|
+
'@generated by @constructive-io/graphql-codegen',
|
|
57
|
+
'DO NOT EDIT - changes will be overwritten',
|
|
58
|
+
]);
|
|
59
|
+
}
|
|
60
|
+
return generateCode(statements);
|
|
41
61
|
}
|
|
42
62
|
export function generateMainBarrel(tables, options = {}) {
|
|
43
63
|
// Support legacy signature where second arg was just hasSchemaTypes boolean
|
|
44
64
|
const opts = typeof options === 'boolean'
|
|
45
65
|
? { hasSchemaTypes: options, hasMutations: true }
|
|
46
66
|
: options;
|
|
47
|
-
const { hasSchemaTypes = false, hasMutations = true } = opts;
|
|
48
|
-
const tableNames = tables.map((
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
67
|
+
const { hasSchemaTypes = false, hasMutations = true, hasQueryKeys = false, hasMutationKeys = false, hasInvalidation = false, } = opts;
|
|
68
|
+
const tableNames = tables.map((tbl) => tbl.name).join(', ');
|
|
69
|
+
const statements = [];
|
|
70
|
+
// Client configuration
|
|
71
|
+
statements.push(exportAllFrom('./client'));
|
|
72
|
+
// Entity and filter types
|
|
73
|
+
statements.push(exportAllFrom('./types'));
|
|
74
|
+
// Schema types (input, payload, enum types)
|
|
75
|
+
if (hasSchemaTypes) {
|
|
76
|
+
statements.push(exportAllFrom('./schema-types'));
|
|
77
|
+
}
|
|
78
|
+
// Centralized query keys (for cache management)
|
|
79
|
+
if (hasQueryKeys) {
|
|
80
|
+
statements.push(exportAllFrom('./query-keys'));
|
|
81
|
+
}
|
|
82
|
+
// Centralized mutation keys (for tracking in-flight mutations)
|
|
83
|
+
if (hasMutationKeys) {
|
|
84
|
+
statements.push(exportAllFrom('./mutation-keys'));
|
|
85
|
+
}
|
|
86
|
+
// Cache invalidation helpers
|
|
87
|
+
if (hasInvalidation) {
|
|
88
|
+
statements.push(exportAllFrom('./invalidation'));
|
|
89
|
+
}
|
|
90
|
+
// Query hooks
|
|
91
|
+
statements.push(exportAllFrom('./queries'));
|
|
92
|
+
// Mutation hooks
|
|
93
|
+
if (hasMutations) {
|
|
94
|
+
statements.push(exportAllFrom('./mutations'));
|
|
95
|
+
}
|
|
96
|
+
// Add file header as leading comment on first statement
|
|
97
|
+
if (statements.length > 0) {
|
|
98
|
+
addJSDocComment(statements[0], [
|
|
99
|
+
'Auto-generated GraphQL SDK',
|
|
100
|
+
'@generated by @constructive-io/graphql-codegen',
|
|
101
|
+
'',
|
|
102
|
+
`Tables: ${tableNames}`,
|
|
103
|
+
'',
|
|
104
|
+
'Usage:',
|
|
105
|
+
'',
|
|
106
|
+
'1. Configure the client:',
|
|
107
|
+
'```ts',
|
|
108
|
+
"import { configure } from './generated';",
|
|
109
|
+
'',
|
|
110
|
+
'configure({',
|
|
111
|
+
" endpoint: 'https://api.example.com/graphql',",
|
|
112
|
+
" headers: { Authorization: 'Bearer <token>' },",
|
|
113
|
+
'});',
|
|
114
|
+
'```',
|
|
115
|
+
'',
|
|
116
|
+
'2. Use the hooks:',
|
|
117
|
+
'```tsx',
|
|
118
|
+
"import { useCarsQuery, useCreateCarMutation } from './generated';",
|
|
119
|
+
'',
|
|
120
|
+
'function MyComponent() {',
|
|
121
|
+
' const { data, isLoading } = useCarsQuery({ first: 10 });',
|
|
122
|
+
' const { mutate } = useCreateCarMutation();',
|
|
123
|
+
' // ...',
|
|
124
|
+
'}',
|
|
125
|
+
'```',
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
return generateCode(statements);
|
|
100
129
|
}
|
|
101
130
|
// ============================================================================
|
|
102
131
|
// Custom operation barrels (includes both table and custom hooks)
|
|
@@ -105,60 +134,60 @@ ${mutationsExport}`;
|
|
|
105
134
|
* Generate queries barrel including custom query operations
|
|
106
135
|
*/
|
|
107
136
|
export function generateCustomQueriesBarrel(tables, customQueryNames) {
|
|
108
|
-
const
|
|
109
|
-
createFileHeader('Query hooks barrel export'),
|
|
110
|
-
'',
|
|
111
|
-
'// Table-based query hooks',
|
|
112
|
-
];
|
|
137
|
+
const statements = [];
|
|
113
138
|
// Export all table query hooks
|
|
114
139
|
for (const table of tables) {
|
|
115
140
|
const listHookName = getListQueryHookName(table);
|
|
116
141
|
const singleHookName = getSingleQueryHookName(table);
|
|
117
|
-
|
|
118
|
-
|
|
142
|
+
statements.push(exportAllFrom(`./${listHookName}`));
|
|
143
|
+
statements.push(exportAllFrom(`./${singleHookName}`));
|
|
119
144
|
}
|
|
120
145
|
// Add custom query hooks
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
146
|
+
for (const name of customQueryNames) {
|
|
147
|
+
const hookName = getOperationHookName(name, 'query');
|
|
148
|
+
statements.push(exportAllFrom(`./${hookName}`));
|
|
149
|
+
}
|
|
150
|
+
// Add file header as leading comment on first statement
|
|
151
|
+
if (statements.length > 0) {
|
|
152
|
+
addJSDocComment(statements[0], [
|
|
153
|
+
'Query hooks barrel export',
|
|
154
|
+
'@generated by @constructive-io/graphql-codegen',
|
|
155
|
+
'DO NOT EDIT - changes will be overwritten',
|
|
156
|
+
]);
|
|
128
157
|
}
|
|
129
|
-
return
|
|
158
|
+
return generateCode(statements);
|
|
130
159
|
}
|
|
131
160
|
/**
|
|
132
161
|
* Generate mutations barrel including custom mutation operations
|
|
133
162
|
*/
|
|
134
163
|
export function generateCustomMutationsBarrel(tables, customMutationNames) {
|
|
135
|
-
const
|
|
136
|
-
createFileHeader('Mutation hooks barrel export'),
|
|
137
|
-
'',
|
|
138
|
-
'// Table-based mutation hooks',
|
|
139
|
-
];
|
|
164
|
+
const statements = [];
|
|
140
165
|
// Export all table mutation hooks
|
|
141
166
|
for (const table of tables) {
|
|
142
167
|
const createHookName = getCreateMutationHookName(table);
|
|
143
168
|
const updateHookName = getUpdateMutationHookName(table);
|
|
144
169
|
const deleteHookName = getDeleteMutationHookName(table);
|
|
145
|
-
|
|
170
|
+
statements.push(exportAllFrom(`./${createHookName}`));
|
|
146
171
|
// Only add update/delete if they exist
|
|
147
172
|
if (table.query?.update !== null) {
|
|
148
|
-
|
|
173
|
+
statements.push(exportAllFrom(`./${updateHookName}`));
|
|
149
174
|
}
|
|
150
175
|
if (table.query?.delete !== null) {
|
|
151
|
-
|
|
176
|
+
statements.push(exportAllFrom(`./${deleteHookName}`));
|
|
152
177
|
}
|
|
153
178
|
}
|
|
154
179
|
// Add custom mutation hooks
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
for (const name of customMutationNames) {
|
|
181
|
+
const hookName = getOperationHookName(name, 'mutation');
|
|
182
|
+
statements.push(exportAllFrom(`./${hookName}`));
|
|
183
|
+
}
|
|
184
|
+
// Add file header as leading comment on first statement
|
|
185
|
+
if (statements.length > 0) {
|
|
186
|
+
addJSDocComment(statements[0], [
|
|
187
|
+
'Mutation hooks barrel export',
|
|
188
|
+
'@generated by @constructive-io/graphql-codegen',
|
|
189
|
+
'DO NOT EDIT - changes will be overwritten',
|
|
190
|
+
]);
|
|
162
191
|
}
|
|
163
|
-
return
|
|
192
|
+
return generateCode(statements);
|
|
164
193
|
}
|
|
@@ -196,5 +196,66 @@ export async function executeWithErrors<TData = unknown, TVariables = Record<str
|
|
|
196
196
|
errors: json.errors ?? null,
|
|
197
197
|
};
|
|
198
198
|
}
|
|
199
|
+
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// QueryClient Factory
|
|
202
|
+
// ============================================================================
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Default QueryClient configuration optimized for GraphQL
|
|
206
|
+
*
|
|
207
|
+
* These defaults provide a good balance between freshness and performance:
|
|
208
|
+
* - staleTime: 1 minute - data considered fresh, won't refetch
|
|
209
|
+
* - gcTime: 5 minutes - unused data kept in cache
|
|
210
|
+
* - refetchOnWindowFocus: false - don't refetch when tab becomes active
|
|
211
|
+
* - retry: 1 - retry failed requests once
|
|
212
|
+
*/
|
|
213
|
+
export const defaultQueryClientOptions = {
|
|
214
|
+
defaultOptions: {
|
|
215
|
+
queries: {
|
|
216
|
+
staleTime: 1000 * 60, // 1 minute
|
|
217
|
+
gcTime: 1000 * 60 * 5, // 5 minutes
|
|
218
|
+
refetchOnWindowFocus: false,
|
|
219
|
+
retry: 1,
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* QueryClient options type for createQueryClient
|
|
226
|
+
*/
|
|
227
|
+
export interface CreateQueryClientOptions {
|
|
228
|
+
defaultOptions?: {
|
|
229
|
+
queries?: {
|
|
230
|
+
staleTime?: number;
|
|
231
|
+
gcTime?: number;
|
|
232
|
+
refetchOnWindowFocus?: boolean;
|
|
233
|
+
retry?: number | boolean;
|
|
234
|
+
retryDelay?: number | ((attemptIndex: number) => number);
|
|
235
|
+
};
|
|
236
|
+
mutations?: {
|
|
237
|
+
retry?: number | boolean;
|
|
238
|
+
retryDelay?: number | ((attemptIndex: number) => number);
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Note: createQueryClient is available when using with @tanstack/react-query
|
|
244
|
+
// Import QueryClient from '@tanstack/react-query' and use these options:
|
|
245
|
+
//
|
|
246
|
+
// import { QueryClient } from '@tanstack/react-query';
|
|
247
|
+
// const queryClient = new QueryClient(defaultQueryClientOptions);
|
|
248
|
+
//
|
|
249
|
+
// Or merge with your own options:
|
|
250
|
+
// const queryClient = new QueryClient({
|
|
251
|
+
// ...defaultQueryClientOptions,
|
|
252
|
+
// defaultOptions: {
|
|
253
|
+
// ...defaultQueryClientOptions.defaultOptions,
|
|
254
|
+
// queries: {
|
|
255
|
+
// ...defaultQueryClientOptions.defaultOptions.queries,
|
|
256
|
+
// staleTime: 30000, // Override specific options
|
|
257
|
+
// },
|
|
258
|
+
// },
|
|
259
|
+
// });
|
|
199
260
|
`;
|
|
200
261
|
}
|
|
@@ -21,28 +21,18 @@ export interface GenerateCustomMutationHookOptions {
|
|
|
21
21
|
typeRegistry: TypeRegistry;
|
|
22
22
|
maxDepth?: number;
|
|
23
23
|
skipQueryField?: boolean;
|
|
24
|
-
/** Whether to generate React Query hooks (default: true for backwards compatibility) */
|
|
25
24
|
reactQueryEnabled?: boolean;
|
|
26
|
-
/** Table entity type names (for import path resolution) */
|
|
27
25
|
tableTypeNames?: Set<string>;
|
|
26
|
+
useCentralizedKeys?: boolean;
|
|
28
27
|
}
|
|
29
|
-
/**
|
|
30
|
-
* Generate a custom mutation hook file
|
|
31
|
-
* When reactQueryEnabled is false, returns null since mutations require React Query
|
|
32
|
-
*/
|
|
33
28
|
export declare function generateCustomMutationHook(options: GenerateCustomMutationHookOptions): GeneratedCustomMutationFile | null;
|
|
34
29
|
export interface GenerateAllCustomMutationHooksOptions {
|
|
35
30
|
operations: CleanOperation[];
|
|
36
31
|
typeRegistry: TypeRegistry;
|
|
37
32
|
maxDepth?: number;
|
|
38
33
|
skipQueryField?: boolean;
|
|
39
|
-
/** Whether to generate React Query hooks (default: true for backwards compatibility) */
|
|
40
34
|
reactQueryEnabled?: boolean;
|
|
41
|
-
/** Table entity type names (for import path resolution) */
|
|
42
35
|
tableTypeNames?: Set<string>;
|
|
36
|
+
useCentralizedKeys?: boolean;
|
|
43
37
|
}
|
|
44
|
-
/**
|
|
45
|
-
* Generate all custom mutation hook files
|
|
46
|
-
* When reactQueryEnabled is false, returns empty array since mutations require React Query
|
|
47
|
-
*/
|
|
48
38
|
export declare function generateAllCustomMutationHooks(options: GenerateAllCustomMutationHooksOptions): GeneratedCustomMutationFile[];
|