@constructive-io/graphql-codegen 4.41.0 → 4.41.2
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/core/codegen/cli/docs-generator.js +28 -0
- package/core/codegen/cli/executor-generator.d.ts +2 -6
- package/core/codegen/cli/executor-generator.js +12 -48
- package/core/codegen/cli/index.d.ts +0 -2
- package/core/codegen/cli/index.js +2 -16
- package/core/codegen/cli/utils-generator.d.ts +0 -8
- package/core/codegen/cli/utils-generator.js +0 -14
- package/core/codegen/hooks-docs-generator.js +26 -0
- package/core/codegen/orm/client-generator.d.ts +1 -3
- package/core/codegen/orm/client-generator.js +1 -1
- package/core/codegen/orm/docs-generator.js +55 -1
- package/core/codegen/orm/index.js +1 -1
- package/core/codegen/templates/select-types.ts +1 -1
- package/core/generate.js +2 -19
- package/esm/core/codegen/cli/docs-generator.js +28 -0
- package/esm/core/codegen/cli/executor-generator.d.ts +2 -6
- package/esm/core/codegen/cli/executor-generator.js +12 -48
- package/esm/core/codegen/cli/index.d.ts +0 -2
- package/esm/core/codegen/cli/index.js +3 -17
- package/esm/core/codegen/cli/utils-generator.d.ts +0 -8
- package/esm/core/codegen/cli/utils-generator.js +0 -13
- package/esm/core/codegen/hooks-docs-generator.js +27 -1
- package/esm/core/codegen/orm/client-generator.d.ts +1 -3
- package/esm/core/codegen/orm/client-generator.js +1 -1
- package/esm/core/codegen/orm/docs-generator.js +55 -1
- package/esm/core/codegen/orm/index.js +1 -1
- package/esm/core/generate.js +2 -19
- package/esm/types/config.d.ts +0 -18
- package/package.json +4 -4
- package/types/config.d.ts +0 -18
- package/core/codegen/templates/node-fetch.ts +0 -198
|
@@ -111,6 +111,18 @@ function generateReadme(tables, customOperations, toolName, registry) {
|
|
|
111
111
|
lines.push(`| \`create\` | Create a new ${singularName} |`);
|
|
112
112
|
lines.push(`| \`update\` | Update an existing ${singularName} |`);
|
|
113
113
|
lines.push(`| \`delete\` | Delete a ${singularName} |`);
|
|
114
|
+
if (table.query?.bulkInsert) {
|
|
115
|
+
lines.push(`| \`bulk-create\` | Bulk create ${singularName} records |`);
|
|
116
|
+
}
|
|
117
|
+
if (table.query?.bulkUpsert) {
|
|
118
|
+
lines.push(`| \`bulk-upsert\` | Bulk upsert ${singularName} records |`);
|
|
119
|
+
}
|
|
120
|
+
if (table.query?.bulkUpdate) {
|
|
121
|
+
lines.push(`| \`bulk-update\` | Bulk update ${singularName} records |`);
|
|
122
|
+
}
|
|
123
|
+
if (table.query?.bulkDelete) {
|
|
124
|
+
lines.push(`| \`bulk-delete\` | Bulk delete ${singularName} records |`);
|
|
125
|
+
}
|
|
114
126
|
lines.push('');
|
|
115
127
|
lines.push('**Fields:**');
|
|
116
128
|
lines.push('');
|
|
@@ -403,6 +415,10 @@ function generateSkills(tables, customOperations, toolName, targetName, registry
|
|
|
403
415
|
`${toolName} ${kebab} create ${createFlags}`,
|
|
404
416
|
`${toolName} ${kebab} update --${pk.name} <${(0, docs_utils_1.cleanTypeName)(pk.gqlType)}> ${editableFields.map((f) => `[--${f.name} <${(0, docs_utils_1.cleanTypeName)(f.type.gqlType)}>]`).join(' ')}`,
|
|
405
417
|
`${toolName} ${kebab} delete --${pk.name} <${(0, docs_utils_1.cleanTypeName)(pk.gqlType)}>`,
|
|
418
|
+
...(table.query?.bulkInsert ? [`${toolName} ${kebab} bulk-create --data '<JSON array>'`] : []),
|
|
419
|
+
...(table.query?.bulkUpsert ? [`${toolName} ${kebab} bulk-upsert --data '<JSON array>'`] : []),
|
|
420
|
+
...(table.query?.bulkUpdate ? [`${toolName} ${kebab} bulk-update --where '<JSON>' --data '<JSON>'`] : []),
|
|
421
|
+
...(table.query?.bulkDelete ? [`${toolName} ${kebab} bulk-delete --where '<JSON>'`] : []),
|
|
406
422
|
],
|
|
407
423
|
examples: [
|
|
408
424
|
{
|
|
@@ -694,6 +710,18 @@ function generateMultiTargetReadme(input) {
|
|
|
694
710
|
lines.push(`| \`create\` | Create a new ${singularName} |`);
|
|
695
711
|
lines.push(`| \`update\` | Update an existing ${singularName} |`);
|
|
696
712
|
lines.push(`| \`delete\` | Delete a ${singularName} |`);
|
|
713
|
+
if (table.query?.bulkInsert) {
|
|
714
|
+
lines.push(`| \`bulk-create\` | Bulk create ${singularName} records |`);
|
|
715
|
+
}
|
|
716
|
+
if (table.query?.bulkUpsert) {
|
|
717
|
+
lines.push(`| \`bulk-upsert\` | Bulk upsert ${singularName} records |`);
|
|
718
|
+
}
|
|
719
|
+
if (table.query?.bulkUpdate) {
|
|
720
|
+
lines.push(`| \`bulk-update\` | Bulk update ${singularName} records |`);
|
|
721
|
+
}
|
|
722
|
+
if (table.query?.bulkDelete) {
|
|
723
|
+
lines.push(`| \`bulk-delete\` | Bulk delete ${singularName} records |`);
|
|
724
|
+
}
|
|
697
725
|
lines.push('');
|
|
698
726
|
lines.push('**Fields:**');
|
|
699
727
|
lines.push('');
|
|
@@ -7,9 +7,5 @@ export interface MultiTargetExecutorInput {
|
|
|
7
7
|
endpoint: string;
|
|
8
8
|
ormImportPath: string;
|
|
9
9
|
}
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
nodeHttpAdapter?: boolean;
|
|
13
|
-
}
|
|
14
|
-
export declare function generateExecutorFile(toolName: string, options?: ExecutorOptions): GeneratedFile;
|
|
15
|
-
export declare function generateMultiTargetExecutorFile(toolName: string, targets: MultiTargetExecutorInput[], options?: ExecutorOptions): GeneratedFile;
|
|
10
|
+
export declare function generateExecutorFile(toolName: string): GeneratedFile;
|
|
11
|
+
export declare function generateMultiTargetExecutorFile(toolName: string, targets: MultiTargetExecutorInput[]): GeneratedFile;
|
|
@@ -44,12 +44,8 @@ function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false
|
|
|
44
44
|
decl.importKind = typeOnly ? 'type' : 'value';
|
|
45
45
|
return decl;
|
|
46
46
|
}
|
|
47
|
-
function generateExecutorFile(toolName
|
|
47
|
+
function generateExecutorFile(toolName) {
|
|
48
48
|
const statements = [];
|
|
49
|
-
// Import NodeHttpAdapter for *.localhost subdomain routing
|
|
50
|
-
if (options?.nodeHttpAdapter) {
|
|
51
|
-
statements.push(createImportDeclaration('./node-fetch', ['NodeHttpAdapter']));
|
|
52
|
-
}
|
|
53
49
|
statements.push(createImportDeclaration('appstash', ['createConfigStore']));
|
|
54
50
|
statements.push(createImportDeclaration('../orm', ['createClient']));
|
|
55
51
|
statements.push(t.variableDeclaration('const', [
|
|
@@ -109,26 +105,12 @@ function generateExecutorFile(toolName, options) {
|
|
|
109
105
|
]))),
|
|
110
106
|
])),
|
|
111
107
|
])),
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
t.
|
|
116
|
-
t.objectExpression([
|
|
117
|
-
t.objectProperty(t.identifier('adapter'), t.newExpression(t.identifier('NodeHttpAdapter'), [
|
|
118
|
-
t.memberExpression(t.identifier('ctx'), t.identifier('endpoint')),
|
|
119
|
-
t.identifier('headers'),
|
|
120
|
-
])),
|
|
121
|
-
]),
|
|
122
|
-
])),
|
|
123
|
-
]
|
|
124
|
-
: [
|
|
125
|
-
t.returnStatement(t.callExpression(t.identifier('createClient'), [
|
|
126
|
-
t.objectExpression([
|
|
127
|
-
t.objectProperty(t.identifier('endpoint'), t.memberExpression(t.identifier('ctx'), t.identifier('endpoint'))),
|
|
128
|
-
t.objectProperty(t.identifier('headers'), t.identifier('headers')),
|
|
129
|
-
]),
|
|
130
|
-
])),
|
|
108
|
+
t.returnStatement(t.callExpression(t.identifier('createClient'), [
|
|
109
|
+
t.objectExpression([
|
|
110
|
+
t.objectProperty(t.identifier('endpoint'), t.memberExpression(t.identifier('ctx'), t.identifier('endpoint'))),
|
|
111
|
+
t.objectProperty(t.identifier('headers'), t.identifier('headers')),
|
|
131
112
|
]),
|
|
113
|
+
])),
|
|
132
114
|
]);
|
|
133
115
|
const getClientFunc = t.functionDeclaration(t.identifier('getClient'), [contextNameParam], getClientBody);
|
|
134
116
|
statements.push(t.exportNamedDeclaration(getClientFunc));
|
|
@@ -139,12 +121,8 @@ function generateExecutorFile(toolName, options) {
|
|
|
139
121
|
content: header + '\n' + code,
|
|
140
122
|
};
|
|
141
123
|
}
|
|
142
|
-
function generateMultiTargetExecutorFile(toolName, targets
|
|
124
|
+
function generateMultiTargetExecutorFile(toolName, targets) {
|
|
143
125
|
const statements = [];
|
|
144
|
-
// Import NodeHttpAdapter for *.localhost subdomain routing
|
|
145
|
-
if (options?.nodeHttpAdapter) {
|
|
146
|
-
statements.push(createImportDeclaration('./node-fetch', ['NodeHttpAdapter']));
|
|
147
|
-
}
|
|
148
126
|
statements.push(createImportDeclaration('appstash', ['createConfigStore']));
|
|
149
127
|
for (const target of targets) {
|
|
150
128
|
const aliasName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}Client`;
|
|
@@ -235,26 +213,12 @@ function generateMultiTargetExecutorFile(toolName, targets, options) {
|
|
|
235
213
|
]), t.blockStatement([
|
|
236
214
|
t.expressionStatement(t.assignmentExpression('=', t.identifier('endpoint'), t.logicalExpression('||', t.memberExpression(t.identifier('defaultEndpoints'), t.identifier('targetName'), true), t.stringLiteral('')))),
|
|
237
215
|
])),
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
t.
|
|
242
|
-
t.objectExpression([
|
|
243
|
-
t.objectProperty(t.identifier('adapter'), t.newExpression(t.identifier('NodeHttpAdapter'), [
|
|
244
|
-
t.identifier('endpoint'),
|
|
245
|
-
t.identifier('headers'),
|
|
246
|
-
])),
|
|
247
|
-
]),
|
|
248
|
-
])),
|
|
249
|
-
]
|
|
250
|
-
: [
|
|
251
|
-
t.returnStatement(t.callExpression(t.identifier('createFn'), [
|
|
252
|
-
t.objectExpression([
|
|
253
|
-
t.objectProperty(t.identifier('endpoint'), t.identifier('endpoint')),
|
|
254
|
-
t.objectProperty(t.identifier('headers'), t.identifier('headers')),
|
|
255
|
-
]),
|
|
256
|
-
])),
|
|
216
|
+
t.returnStatement(t.callExpression(t.identifier('createFn'), [
|
|
217
|
+
t.objectExpression([
|
|
218
|
+
t.objectProperty(t.identifier('endpoint'), t.identifier('endpoint')),
|
|
219
|
+
t.objectProperty(t.identifier('headers'), t.identifier('headers')),
|
|
257
220
|
]),
|
|
221
|
+
])),
|
|
258
222
|
]);
|
|
259
223
|
const getClientFunc = t.functionDeclaration(t.identifier('getClient'), [targetNameParam, contextNameParam], getClientBody);
|
|
260
224
|
statements.push(t.exportNamedDeclaration(getClientFunc));
|
|
@@ -39,8 +39,6 @@ export interface GenerateMultiTargetCliOptions {
|
|
|
39
39
|
toolName: string;
|
|
40
40
|
builtinNames?: BuiltinNames;
|
|
41
41
|
targets: MultiTargetCliTarget[];
|
|
42
|
-
/** Enable NodeHttpAdapter for *.localhost subdomain routing */
|
|
43
|
-
nodeHttpAdapter?: boolean;
|
|
44
42
|
/** Generate a runnable index.ts entry point */
|
|
45
43
|
entryPoint?: boolean;
|
|
46
44
|
}
|
|
@@ -19,11 +19,7 @@ function generateCli(options) {
|
|
|
19
19
|
const toolName = typeof cliConfig === 'object' && cliConfig.toolName
|
|
20
20
|
? cliConfig.toolName
|
|
21
21
|
: 'app';
|
|
22
|
-
|
|
23
|
-
const useNodeHttpAdapter = !!config.nodeHttpAdapter;
|
|
24
|
-
const executorFile = (0, executor_generator_1.generateExecutorFile)(toolName, {
|
|
25
|
-
nodeHttpAdapter: useNodeHttpAdapter,
|
|
26
|
-
});
|
|
22
|
+
const executorFile = (0, executor_generator_1.generateExecutorFile)(toolName);
|
|
27
23
|
files.push(executorFile);
|
|
28
24
|
const utilsFile = (0, utils_generator_1.generateUtilsFile)();
|
|
29
25
|
files.push(utilsFile);
|
|
@@ -32,10 +28,6 @@ function generateCli(options) {
|
|
|
32
28
|
if (hasAnyEmbeddings) {
|
|
33
29
|
files.push((0, utils_generator_1.generateEmbedderFile)());
|
|
34
30
|
}
|
|
35
|
-
// Generate node HTTP adapter if configured (for *.localhost subdomain routing)
|
|
36
|
-
if (useNodeHttpAdapter) {
|
|
37
|
-
files.push((0, utils_generator_1.generateNodeFetchFile)());
|
|
38
|
-
}
|
|
39
31
|
const contextFile = (0, infra_generator_1.generateContextCommand)(toolName);
|
|
40
32
|
files.push(contextFile);
|
|
41
33
|
const authFile = (0, infra_generator_1.generateAuthCommand)(toolName);
|
|
@@ -97,9 +89,7 @@ function generateMultiTargetCli(options) {
|
|
|
97
89
|
endpoint: t.endpoint,
|
|
98
90
|
ormImportPath: t.ormImportPath,
|
|
99
91
|
}));
|
|
100
|
-
const executorFile = (0, executor_generator_1.generateMultiTargetExecutorFile)(toolName, executorInputs
|
|
101
|
-
nodeHttpAdapter: !!options.nodeHttpAdapter,
|
|
102
|
-
});
|
|
92
|
+
const executorFile = (0, executor_generator_1.generateMultiTargetExecutorFile)(toolName, executorInputs);
|
|
103
93
|
files.push(executorFile);
|
|
104
94
|
const utilsFile = (0, utils_generator_1.generateUtilsFile)();
|
|
105
95
|
files.push(utilsFile);
|
|
@@ -108,10 +98,6 @@ function generateMultiTargetCli(options) {
|
|
|
108
98
|
if (hasAnyMtEmbeddings) {
|
|
109
99
|
files.push((0, utils_generator_1.generateEmbedderFile)());
|
|
110
100
|
}
|
|
111
|
-
// Generate node HTTP adapter if configured (for *.localhost subdomain routing)
|
|
112
|
-
if (options.nodeHttpAdapter) {
|
|
113
|
-
files.push((0, utils_generator_1.generateNodeFetchFile)());
|
|
114
|
-
}
|
|
115
101
|
const contextFile = (0, infra_generator_1.generateMultiTargetContextCommand)(toolName, builtinNames.context, targets.map((t) => ({ name: t.name, endpoint: t.endpoint })));
|
|
116
102
|
files.push(contextFile);
|
|
117
103
|
const authFile = (0, infra_generator_1.generateAuthCommandWithName)(toolName, builtinNames.auth);
|
|
@@ -8,14 +8,6 @@ import type { GeneratedFile } from './executor-generator';
|
|
|
8
8
|
* and mutation input parsing.
|
|
9
9
|
*/
|
|
10
10
|
export declare function generateUtilsFile(): GeneratedFile;
|
|
11
|
-
/**
|
|
12
|
-
* Generate a node-fetch.ts file with NodeHttpAdapter for CLI.
|
|
13
|
-
*
|
|
14
|
-
* Provides a GraphQLAdapter implementation using node:http/node:https
|
|
15
|
-
* instead of the Fetch API. This cleanly handles *.localhost subdomain
|
|
16
|
-
* routing (DNS resolution + Host header) without any global patching.
|
|
17
|
-
*/
|
|
18
|
-
export declare function generateNodeFetchFile(): GeneratedFile;
|
|
19
11
|
/**
|
|
20
12
|
* Generate an index.ts entry point file for the CLI.
|
|
21
13
|
*
|
|
@@ -34,7 +34,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.generateUtilsFile = generateUtilsFile;
|
|
37
|
-
exports.generateNodeFetchFile = generateNodeFetchFile;
|
|
38
37
|
exports.generateEntryPointFile = generateEntryPointFile;
|
|
39
38
|
exports.generateEmbedderFile = generateEmbedderFile;
|
|
40
39
|
const fs = __importStar(require("fs"));
|
|
@@ -79,19 +78,6 @@ function generateUtilsFile() {
|
|
|
79
78
|
content: readTemplateFile('cli-utils.ts', 'CLI utility functions for type coercion and input handling'),
|
|
80
79
|
};
|
|
81
80
|
}
|
|
82
|
-
/**
|
|
83
|
-
* Generate a node-fetch.ts file with NodeHttpAdapter for CLI.
|
|
84
|
-
*
|
|
85
|
-
* Provides a GraphQLAdapter implementation using node:http/node:https
|
|
86
|
-
* instead of the Fetch API. This cleanly handles *.localhost subdomain
|
|
87
|
-
* routing (DNS resolution + Host header) without any global patching.
|
|
88
|
-
*/
|
|
89
|
-
function generateNodeFetchFile() {
|
|
90
|
-
return {
|
|
91
|
-
fileName: 'node-fetch.ts',
|
|
92
|
-
content: readTemplateFile('node-fetch.ts', 'Node HTTP adapter for localhost subdomain routing'),
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
81
|
/**
|
|
96
82
|
* Generate an index.ts entry point file for the CLI.
|
|
97
83
|
*
|
|
@@ -52,6 +52,18 @@ function generateHooksReadme(tables, customOperations, registry) {
|
|
|
52
52
|
lines.push(`| \`${(0, utils_1.getUpdateMutationHookName)(table)}\` | Mutation | ${table.description || `Update a ${singularName}`} |`);
|
|
53
53
|
lines.push(`| \`${(0, utils_1.getDeleteMutationHookName)(table)}\` | Mutation | ${table.description || `Delete a ${singularName}`} |`);
|
|
54
54
|
}
|
|
55
|
+
if (table.query?.bulkInsert) {
|
|
56
|
+
lines.push(`| \`${(0, utils_1.getBulkCreateMutationHookName)(table)}\` | Mutation | Bulk create ${pluralName} |`);
|
|
57
|
+
}
|
|
58
|
+
if (table.query?.bulkUpsert) {
|
|
59
|
+
lines.push(`| \`${(0, utils_1.getBulkUpsertMutationHookName)(table)}\` | Mutation | Bulk upsert ${pluralName} |`);
|
|
60
|
+
}
|
|
61
|
+
if (table.query?.bulkUpdate) {
|
|
62
|
+
lines.push(`| \`${(0, utils_1.getBulkUpdateMutationHookName)(table)}\` | Mutation | Bulk update ${pluralName} |`);
|
|
63
|
+
}
|
|
64
|
+
if (table.query?.bulkDelete) {
|
|
65
|
+
lines.push(`| \`${(0, utils_1.getBulkDeleteMutationHookName)(table)}\` | Mutation | Bulk delete ${pluralName} |`);
|
|
66
|
+
}
|
|
55
67
|
}
|
|
56
68
|
for (const op of customOperations) {
|
|
57
69
|
lines.push(`| \`${getCustomHookName(op)}\` | ${(0, utils_1.ucFirst)(op.kind)} | ${op.description || op.name} |`);
|
|
@@ -85,6 +97,14 @@ function generateHooksReadme(tables, customOperations, registry) {
|
|
|
85
97
|
lines.push(` selection: { fields: { ${pk.name}: true } },`);
|
|
86
98
|
lines.push('});');
|
|
87
99
|
lines.push(`create({ ${scalarFields.filter((f) => f.name !== pk.name && f.name !== 'nodeId' && f.name !== 'createdAt' && f.name !== 'updatedAt').map((f) => `${f.name}: ${(0, docs_utils_1.fieldPlaceholder)(f)}`).join(', ')} });`);
|
|
100
|
+
if (table.query?.bulkInsert) {
|
|
101
|
+
lines.push('');
|
|
102
|
+
lines.push(`// Bulk create ${pluralName}`);
|
|
103
|
+
lines.push(`const { mutate: bulkCreate } = ${(0, utils_1.getBulkCreateMutationHookName)(table)}({`);
|
|
104
|
+
lines.push(` selection: { fields: { ${pk.name}: true } },`);
|
|
105
|
+
lines.push('});');
|
|
106
|
+
lines.push(`bulkCreate({ data: [{ ${scalarFields.filter((f) => f.name !== pk.name && f.name !== 'nodeId' && f.name !== 'createdAt' && f.name !== 'updatedAt').map((f) => `${f.name}: ${(0, docs_utils_1.fieldPlaceholder)(f)}`).join(', ')} }] });`);
|
|
107
|
+
}
|
|
88
108
|
lines.push('```');
|
|
89
109
|
lines.push('');
|
|
90
110
|
}
|
|
@@ -155,6 +175,7 @@ function generateHooksAgentsDocs(tables, customOperations) {
|
|
|
155
175
|
lines.push('');
|
|
156
176
|
lines.push('- Query hooks: `use<PluralName>Query`, `use<SingularName>Query`');
|
|
157
177
|
lines.push('- Mutation hooks: `useCreate<Name>Mutation`, `useUpdate<Name>Mutation`, `useDelete<Name>Mutation`');
|
|
178
|
+
lines.push('- Bulk mutation hooks (when enabled): `useBulkCreate<Name>Mutation`, `useBulkUpsert<Name>Mutation`, `useBulkUpdate<Name>Mutation`, `useBulkDelete<Name>Mutation`');
|
|
158
179
|
lines.push('- All hooks accept a `selection` parameter to pick fields');
|
|
159
180
|
lines.push('');
|
|
160
181
|
lines.push('## Boundaries');
|
|
@@ -200,6 +221,10 @@ function generateHooksSkills(tables, customOperations, targetName, registry) {
|
|
|
200
221
|
`${(0, utils_1.getDeleteMutationHookName)(table)}({})`,
|
|
201
222
|
]
|
|
202
223
|
: []),
|
|
224
|
+
...(table.query?.bulkInsert ? [`${(0, utils_1.getBulkCreateMutationHookName)(table)}() — bulk create with data array`] : []),
|
|
225
|
+
...(table.query?.bulkUpsert ? [`${(0, utils_1.getBulkUpsertMutationHookName)(table)}() — bulk upsert with onConflict`] : []),
|
|
226
|
+
...(table.query?.bulkUpdate ? [`${(0, utils_1.getBulkUpdateMutationHookName)(table)}() — bulk update with where + data`] : []),
|
|
227
|
+
...(table.query?.bulkDelete ? [`${(0, utils_1.getBulkDeleteMutationHookName)(table)}() — bulk delete with where`] : []),
|
|
203
228
|
],
|
|
204
229
|
examples: [
|
|
205
230
|
{
|
|
@@ -275,6 +300,7 @@ function generateHooksSkills(tables, customOperations, targetName, registry) {
|
|
|
275
300
|
'',
|
|
276
301
|
`// Query hooks: use<Model>Query, use<Model>sQuery`,
|
|
277
302
|
`// Mutation hooks: useCreate<Model>Mutation, useUpdate<Model>Mutation, useDelete<Model>Mutation`,
|
|
303
|
+
`// Bulk mutation hooks (when enabled): useBulkCreate<Model>Mutation, useBulkUpsert<Model>Mutation, etc.`,
|
|
278
304
|
'',
|
|
279
305
|
`const { data, isLoading } = ${hookExamples[0] || 'useModelQuery'}({`,
|
|
280
306
|
` selection: { fields: { id: true } },`,
|
|
@@ -31,6 +31,4 @@ export declare function generateSelectTypesFile(): GeneratedClientFile;
|
|
|
31
31
|
/**
|
|
32
32
|
* Generate the main index.ts with createClient factory
|
|
33
33
|
*/
|
|
34
|
-
export declare function generateCreateClientFile(tables: Table[], hasCustomQueries: boolean, hasCustomMutations: boolean
|
|
35
|
-
nodeHttpAdapter?: boolean;
|
|
36
|
-
}): GeneratedClientFile;
|
|
34
|
+
export declare function generateCreateClientFile(tables: Table[], hasCustomQueries: boolean, hasCustomMutations: boolean): GeneratedClientFile;
|
|
@@ -126,7 +126,7 @@ function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false
|
|
|
126
126
|
/**
|
|
127
127
|
* Generate the main index.ts with createClient factory
|
|
128
128
|
*/
|
|
129
|
-
function generateCreateClientFile(tables, hasCustomQueries, hasCustomMutations
|
|
129
|
+
function generateCreateClientFile(tables, hasCustomQueries, hasCustomMutations) {
|
|
130
130
|
const statements = [];
|
|
131
131
|
// Add imports
|
|
132
132
|
// Import OrmClient (value) and OrmClientConfig (type) separately
|
|
@@ -26,7 +26,17 @@ function generateOrmReadme(tables, customOperations, registry) {
|
|
|
26
26
|
lines.push('|-------|------------|');
|
|
27
27
|
for (const table of tables) {
|
|
28
28
|
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
29
|
-
|
|
29
|
+
const bulkOps = [];
|
|
30
|
+
if (table.query?.bulkInsert)
|
|
31
|
+
bulkOps.push('bulkCreate');
|
|
32
|
+
if (table.query?.bulkUpsert)
|
|
33
|
+
bulkOps.push('bulkUpsert');
|
|
34
|
+
if (table.query?.bulkUpdate)
|
|
35
|
+
bulkOps.push('bulkUpdate');
|
|
36
|
+
if (table.query?.bulkDelete)
|
|
37
|
+
bulkOps.push('bulkDelete');
|
|
38
|
+
const ops = ['findMany', 'findOne', 'create', 'update', 'delete', ...bulkOps].join(', ');
|
|
39
|
+
lines.push(`| \`${singularName}\` | ${ops} |`);
|
|
30
40
|
}
|
|
31
41
|
lines.push('');
|
|
32
42
|
if (tables.length > 0) {
|
|
@@ -67,6 +77,26 @@ function generateOrmReadme(tables, customOperations, registry) {
|
|
|
67
77
|
lines.push('');
|
|
68
78
|
lines.push(`// Delete`);
|
|
69
79
|
lines.push(`const deleted = await db.${singularName}.delete({ where: { ${pk.name}: ${(0, docs_utils_1.pkPlaceholder)(pk)} } }).execute();`);
|
|
80
|
+
if (table.query?.bulkInsert) {
|
|
81
|
+
lines.push('');
|
|
82
|
+
lines.push(`// Bulk Create`);
|
|
83
|
+
lines.push(`const bulkCreated = await db.${singularName}.bulkCreate({ data: [{ ${editableFields.map((f) => `${f.name}: ${(0, docs_utils_1.fieldPlaceholder)(f)}`).join(', ')} }], select: { ${pk.name}: true } }).execute();`);
|
|
84
|
+
}
|
|
85
|
+
if (table.query?.bulkUpsert) {
|
|
86
|
+
lines.push('');
|
|
87
|
+
lines.push(`// Bulk Upsert`);
|
|
88
|
+
lines.push(`const bulkUpserted = await db.${singularName}.bulkUpsert({ data: [{ ${editableFields.map((f) => `${f.name}: ${(0, docs_utils_1.fieldPlaceholder)(f)}`).join(', ')} }], onConflict: { constraint: 'PRIMARY_KEY', action: 'UPDATE' }, select: { ${pk.name}: true } }).execute();`);
|
|
89
|
+
}
|
|
90
|
+
if (table.query?.bulkUpdate) {
|
|
91
|
+
lines.push('');
|
|
92
|
+
lines.push(`// Bulk Update`);
|
|
93
|
+
lines.push(`const bulkUpdated = await db.${singularName}.bulkUpdate({ where: { ${editableFields[0]?.name || 'field'}: { equalTo: ${editableFields[0] ? (0, docs_utils_1.fieldPlaceholder)(editableFields[0]) : "'<String>'"} } }, data: { ${editableFields[0]?.name || 'field'}: ${editableFields[0] ? (0, docs_utils_1.fieldPlaceholder)(editableFields[0]) : "'<String>'"} }, select: { ${pk.name}: true } }).execute();`);
|
|
94
|
+
}
|
|
95
|
+
if (table.query?.bulkDelete) {
|
|
96
|
+
lines.push('');
|
|
97
|
+
lines.push(`// Bulk Delete`);
|
|
98
|
+
lines.push(`const bulkDeleted = await db.${singularName}.bulkDelete({ where: { ${pk.name}: { equalTo: ${(0, docs_utils_1.pkPlaceholder)(pk)} } } }).execute();`);
|
|
99
|
+
}
|
|
70
100
|
lines.push('```');
|
|
71
101
|
lines.push('');
|
|
72
102
|
const ormSpecialGroups = (0, docs_utils_1.categorizeSpecialFields)(table);
|
|
@@ -170,6 +200,7 @@ function generateOrmAgentsDocs(tables, customOperations) {
|
|
|
170
200
|
lines.push('');
|
|
171
201
|
lines.push('- Access models via `db.<ModelName>` (e.g. `db.User`)');
|
|
172
202
|
lines.push('- CRUD methods: `findMany`, `findOne`, `create`, `update`, `delete`');
|
|
203
|
+
lines.push('- Bulk methods (when enabled via smart tags): `bulkCreate`, `bulkUpsert`, `bulkUpdate`, `bulkDelete`');
|
|
173
204
|
lines.push('- Chain `.execute().unwrap()` to run and throw on error, or `.execute()` alone for discriminated union result');
|
|
174
205
|
lines.push('- Custom operations via `db.query.<name>` or `db.mutation.<name>`');
|
|
175
206
|
lines.push('');
|
|
@@ -200,6 +231,19 @@ function generateOrmSkills(tables, customOperations, targetName, registry) {
|
|
|
200
231
|
? ormSkillBaseDesc + '\n\n' +
|
|
201
232
|
ormSkillSpecialGroups.map((g) => `**${g.label}:** ${g.fields.map((f) => `\`${f.name}\``).join(', ')}\n${g.description}`).join('\n\n')
|
|
202
233
|
: ormSkillBaseDesc;
|
|
234
|
+
const bulkUsageLines = [];
|
|
235
|
+
if (table.query?.bulkInsert) {
|
|
236
|
+
bulkUsageLines.push(`db.${modelName}.bulkCreate({ data: [...], select: { id: true } }).execute()`);
|
|
237
|
+
}
|
|
238
|
+
if (table.query?.bulkUpsert) {
|
|
239
|
+
bulkUsageLines.push(`db.${modelName}.bulkUpsert({ data: [...], onConflict: { constraint: '...', action: 'UPDATE' }, select: { id: true } }).execute()`);
|
|
240
|
+
}
|
|
241
|
+
if (table.query?.bulkUpdate) {
|
|
242
|
+
bulkUsageLines.push(`db.${modelName}.bulkUpdate({ where: {...}, data: {...}, select: { id: true } }).execute()`);
|
|
243
|
+
}
|
|
244
|
+
if (table.query?.bulkDelete) {
|
|
245
|
+
bulkUsageLines.push(`db.${modelName}.bulkDelete({ where: {...} }).execute()`);
|
|
246
|
+
}
|
|
203
247
|
files.push({
|
|
204
248
|
fileName: `${skillName}/references/${refName}.md`,
|
|
205
249
|
content: (0, docs_utils_1.buildSkillReference)({
|
|
@@ -212,6 +256,7 @@ function generateOrmSkills(tables, customOperations, targetName, registry) {
|
|
|
212
256
|
`db.${modelName}.create({ data: { ${editableFields.map((f) => `${f.name}: ${(0, docs_utils_1.fieldPlaceholder)(f)}`).join(', ')} }, select: { id: true } }).execute()`,
|
|
213
257
|
`db.${modelName}.update({ where: { ${pk.name}: ${(0, docs_utils_1.pkPlaceholder)(pk)} }, data: { ${editableFields[0]?.name || 'field'}: ${editableFields[0] ? (0, docs_utils_1.fieldPlaceholder)(editableFields[0]) : "'<String>'"} }, select: { id: true } }).execute()`,
|
|
214
258
|
`db.${modelName}.delete({ where: { ${pk.name}: ${(0, docs_utils_1.pkPlaceholder)(pk)} } }).execute()`,
|
|
259
|
+
...bulkUsageLines,
|
|
215
260
|
],
|
|
216
261
|
examples: [
|
|
217
262
|
{
|
|
@@ -261,6 +306,7 @@ function generateOrmSkills(tables, customOperations, targetName, registry) {
|
|
|
261
306
|
}
|
|
262
307
|
// Generate the overview SKILL.md
|
|
263
308
|
const tableNames = tables.map((t) => (0, utils_1.lcFirst)((0, utils_1.getTableNames)(t).singularName));
|
|
309
|
+
const hasBulkTables = tables.some((t) => t.query?.bulkInsert || t.query?.bulkUpsert || t.query?.bulkUpdate || t.query?.bulkDelete);
|
|
264
310
|
files.push({
|
|
265
311
|
fileName: `${skillName}/SKILL.md`,
|
|
266
312
|
content: (0, docs_utils_1.buildSkillFile)({
|
|
@@ -277,6 +323,14 @@ function generateOrmSkills(tables, customOperations, targetName, registry) {
|
|
|
277
323
|
`db.<model>.create({ data: { ... }, select: { id: true } }).execute()`,
|
|
278
324
|
`db.<model>.update({ where: { id: '<UUID>' }, data: { ... }, select: { id: true } }).execute()`,
|
|
279
325
|
`db.<model>.delete({ where: { id: '<UUID>' } }).execute()`,
|
|
326
|
+
...(hasBulkTables ? [
|
|
327
|
+
'',
|
|
328
|
+
`// Bulk operations (on tables with @behavior +bulkInsert/+bulkUpsert/+bulkUpdate/+bulkDelete)`,
|
|
329
|
+
`db.<model>.bulkCreate({ data: [...], select: { id: true } }).execute()`,
|
|
330
|
+
`db.<model>.bulkUpsert({ data: [...], onConflict: { constraint: '...', action: 'UPDATE' }, select: { id: true } }).execute()`,
|
|
331
|
+
`db.<model>.bulkUpdate({ where: {...}, data: {...}, select: { id: true } }).execute()`,
|
|
332
|
+
`db.<model>.bulkDelete({ where: {...} }).execute()`,
|
|
333
|
+
] : []),
|
|
280
334
|
],
|
|
281
335
|
examples: [
|
|
282
336
|
{
|
|
@@ -94,7 +94,7 @@ function generateOrm(options) {
|
|
|
94
94
|
const typesBarrel = (0, barrel_1.generateTypesBarrel)(useSharedTypes);
|
|
95
95
|
files.push({ path: typesBarrel.fileName, content: typesBarrel.content });
|
|
96
96
|
// 7. Generate main index.ts with createClient
|
|
97
|
-
const indexFile = (0, client_generator_1.generateCreateClientFile)(tables, hasCustomQueries, hasCustomMutations
|
|
97
|
+
const indexFile = (0, client_generator_1.generateCreateClientFile)(tables, hasCustomQueries, hasCustomMutations);
|
|
98
98
|
files.push({ path: indexFile.fileName, content: indexFile.content });
|
|
99
99
|
return {
|
|
100
100
|
files,
|
|
@@ -21,7 +21,7 @@ export interface PageInfo {
|
|
|
21
21
|
endCursor?: string | null;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export interface FindManyArgs<TSelect, TWhere, TOrderBy
|
|
24
|
+
export interface FindManyArgs<TSelect, TWhere, TOrderBy> {
|
|
25
25
|
select?: TSelect;
|
|
26
26
|
where?: TWhere;
|
|
27
27
|
orderBy?: TOrderBy[];
|
package/core/generate.js
CHANGED
|
@@ -89,9 +89,6 @@ async function generate(options = {}, internalOptions) {
|
|
|
89
89
|
const runReactQuery = config.reactQuery ?? false;
|
|
90
90
|
const runCli = internalOptions?.skipCli ? false : !!config.cli;
|
|
91
91
|
const runOrm = runReactQuery || !!config.cli || (options.orm !== undefined ? !!options.orm : false);
|
|
92
|
-
// Auto-enable nodeHttpAdapter when CLI is enabled, unless explicitly set to false
|
|
93
|
-
const useNodeHttpAdapter = options.nodeHttpAdapter === true ||
|
|
94
|
-
(runCli && options.nodeHttpAdapter !== false);
|
|
95
92
|
const schemaEnabled = !!options.schema?.enabled;
|
|
96
93
|
if (!schemaEnabled && !runReactQuery && !runOrm && !runCli) {
|
|
97
94
|
return {
|
|
@@ -226,22 +223,13 @@ async function generate(options = {}, internalOptions) {
|
|
|
226
223
|
mutations: customOperations.mutations,
|
|
227
224
|
typeRegistry: customOperations.typeRegistry,
|
|
228
225
|
},
|
|
229
|
-
config
|
|
226
|
+
config,
|
|
230
227
|
sharedTypesPath: bothEnabled ? '..' : undefined,
|
|
231
228
|
});
|
|
232
229
|
filesToWrite.push(...files.map((file) => ({
|
|
233
230
|
...file,
|
|
234
231
|
path: node_path_1.default.posix.join('orm', file.path),
|
|
235
232
|
})));
|
|
236
|
-
// Generate NodeHttpAdapter in ORM output when enabled
|
|
237
|
-
if (useNodeHttpAdapter) {
|
|
238
|
-
const { generateNodeFetchFile } = await Promise.resolve().then(() => __importStar(require('./codegen/cli/utils-generator')));
|
|
239
|
-
const nodeFetchFile = generateNodeFetchFile();
|
|
240
|
-
filesToWrite.push({
|
|
241
|
-
path: node_path_1.default.posix.join('orm', nodeFetchFile.fileName),
|
|
242
|
-
content: nodeFetchFile.content,
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
233
|
}
|
|
246
234
|
// Generate CLI commands
|
|
247
235
|
if (runCli) {
|
|
@@ -252,7 +240,7 @@ async function generate(options = {}, internalOptions) {
|
|
|
252
240
|
queries: customOperations.queries,
|
|
253
241
|
mutations: customOperations.mutations,
|
|
254
242
|
},
|
|
255
|
-
config
|
|
243
|
+
config,
|
|
256
244
|
typeRegistry: customOperations.typeRegistry,
|
|
257
245
|
});
|
|
258
246
|
filesToWrite.push(...files.map((file) => ({
|
|
@@ -582,16 +570,11 @@ async function generateMulti(options) {
|
|
|
582
570
|
if (useUnifiedCli && cliTargets.length > 0 && !dryRun) {
|
|
583
571
|
const cliConfig = typeof unifiedCli === 'object' ? unifiedCli : {};
|
|
584
572
|
const toolName = cliConfig.toolName ?? 'app';
|
|
585
|
-
// Auto-enable nodeHttpAdapter for unified CLI unless explicitly disabled
|
|
586
|
-
// Check first target config for explicit nodeHttpAdapter setting
|
|
587
573
|
const firstTargetConfig = configs[names[0]];
|
|
588
|
-
const multiNodeHttpAdapter = firstTargetConfig?.nodeHttpAdapter === true ||
|
|
589
|
-
(firstTargetConfig?.nodeHttpAdapter !== false);
|
|
590
574
|
const { files } = (0, cli_1.generateMultiTargetCli)({
|
|
591
575
|
toolName,
|
|
592
576
|
builtinNames: cliConfig.builtinNames,
|
|
593
577
|
targets: cliTargets,
|
|
594
|
-
nodeHttpAdapter: multiNodeHttpAdapter,
|
|
595
578
|
entryPoint: cliConfig.entryPoint,
|
|
596
579
|
});
|
|
597
580
|
const cliFilesToWrite = files.map((file) => ({
|
|
@@ -101,6 +101,18 @@ export function generateReadme(tables, customOperations, toolName, registry) {
|
|
|
101
101
|
lines.push(`| \`create\` | Create a new ${singularName} |`);
|
|
102
102
|
lines.push(`| \`update\` | Update an existing ${singularName} |`);
|
|
103
103
|
lines.push(`| \`delete\` | Delete a ${singularName} |`);
|
|
104
|
+
if (table.query?.bulkInsert) {
|
|
105
|
+
lines.push(`| \`bulk-create\` | Bulk create ${singularName} records |`);
|
|
106
|
+
}
|
|
107
|
+
if (table.query?.bulkUpsert) {
|
|
108
|
+
lines.push(`| \`bulk-upsert\` | Bulk upsert ${singularName} records |`);
|
|
109
|
+
}
|
|
110
|
+
if (table.query?.bulkUpdate) {
|
|
111
|
+
lines.push(`| \`bulk-update\` | Bulk update ${singularName} records |`);
|
|
112
|
+
}
|
|
113
|
+
if (table.query?.bulkDelete) {
|
|
114
|
+
lines.push(`| \`bulk-delete\` | Bulk delete ${singularName} records |`);
|
|
115
|
+
}
|
|
104
116
|
lines.push('');
|
|
105
117
|
lines.push('**Fields:**');
|
|
106
118
|
lines.push('');
|
|
@@ -393,6 +405,10 @@ export function generateSkills(tables, customOperations, toolName, targetName, r
|
|
|
393
405
|
`${toolName} ${kebab} create ${createFlags}`,
|
|
394
406
|
`${toolName} ${kebab} update --${pk.name} <${cleanTypeName(pk.gqlType)}> ${editableFields.map((f) => `[--${f.name} <${cleanTypeName(f.type.gqlType)}>]`).join(' ')}`,
|
|
395
407
|
`${toolName} ${kebab} delete --${pk.name} <${cleanTypeName(pk.gqlType)}>`,
|
|
408
|
+
...(table.query?.bulkInsert ? [`${toolName} ${kebab} bulk-create --data '<JSON array>'`] : []),
|
|
409
|
+
...(table.query?.bulkUpsert ? [`${toolName} ${kebab} bulk-upsert --data '<JSON array>'`] : []),
|
|
410
|
+
...(table.query?.bulkUpdate ? [`${toolName} ${kebab} bulk-update --where '<JSON>' --data '<JSON>'`] : []),
|
|
411
|
+
...(table.query?.bulkDelete ? [`${toolName} ${kebab} bulk-delete --where '<JSON>'`] : []),
|
|
396
412
|
],
|
|
397
413
|
examples: [
|
|
398
414
|
{
|
|
@@ -684,6 +700,18 @@ export function generateMultiTargetReadme(input) {
|
|
|
684
700
|
lines.push(`| \`create\` | Create a new ${singularName} |`);
|
|
685
701
|
lines.push(`| \`update\` | Update an existing ${singularName} |`);
|
|
686
702
|
lines.push(`| \`delete\` | Delete a ${singularName} |`);
|
|
703
|
+
if (table.query?.bulkInsert) {
|
|
704
|
+
lines.push(`| \`bulk-create\` | Bulk create ${singularName} records |`);
|
|
705
|
+
}
|
|
706
|
+
if (table.query?.bulkUpsert) {
|
|
707
|
+
lines.push(`| \`bulk-upsert\` | Bulk upsert ${singularName} records |`);
|
|
708
|
+
}
|
|
709
|
+
if (table.query?.bulkUpdate) {
|
|
710
|
+
lines.push(`| \`bulk-update\` | Bulk update ${singularName} records |`);
|
|
711
|
+
}
|
|
712
|
+
if (table.query?.bulkDelete) {
|
|
713
|
+
lines.push(`| \`bulk-delete\` | Bulk delete ${singularName} records |`);
|
|
714
|
+
}
|
|
687
715
|
lines.push('');
|
|
688
716
|
lines.push('**Fields:**');
|
|
689
717
|
lines.push('');
|
|
@@ -7,9 +7,5 @@ export interface MultiTargetExecutorInput {
|
|
|
7
7
|
endpoint: string;
|
|
8
8
|
ormImportPath: string;
|
|
9
9
|
}
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
nodeHttpAdapter?: boolean;
|
|
13
|
-
}
|
|
14
|
-
export declare function generateExecutorFile(toolName: string, options?: ExecutorOptions): GeneratedFile;
|
|
15
|
-
export declare function generateMultiTargetExecutorFile(toolName: string, targets: MultiTargetExecutorInput[], options?: ExecutorOptions): GeneratedFile;
|
|
10
|
+
export declare function generateExecutorFile(toolName: string): GeneratedFile;
|
|
11
|
+
export declare function generateMultiTargetExecutorFile(toolName: string, targets: MultiTargetExecutorInput[]): GeneratedFile;
|