@constructive-io/graphql-codegen 4.8.1 → 4.12.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/arg-mapper.d.ts +1 -1
- package/core/codegen/cli/arg-mapper.js +15 -11
- package/core/codegen/cli/custom-command-generator.js +4 -3
- package/core/codegen/cli/docs-generator.d.ts +6 -5
- package/core/codegen/cli/docs-generator.js +167 -64
- package/core/codegen/cli/table-command-generator.d.ts +15 -0
- package/core/codegen/cli/table-command-generator.js +29 -3
- package/core/codegen/docs-utils.d.ts +26 -1
- package/core/codegen/docs-utils.js +105 -0
- package/core/codegen/orm/input-types-generator.js +112 -14
- package/core/codegen/orm/model-generator.js +8 -0
- package/core/codegen/orm/select-types.d.ts +4 -2
- package/core/codegen/scalars.js +8 -0
- package/core/codegen/templates/cli-entry.ts +2 -2
- package/core/codegen/templates/cli-utils.ts +28 -0
- package/core/codegen/templates/query-builder.ts +28 -5
- package/core/codegen/templates/select-types.ts +4 -2
- package/core/generate.js +14 -4
- package/esm/core/codegen/cli/arg-mapper.d.ts +1 -1
- package/esm/core/codegen/cli/arg-mapper.js +15 -11
- package/esm/core/codegen/cli/custom-command-generator.js +4 -3
- package/esm/core/codegen/cli/docs-generator.d.ts +6 -5
- package/esm/core/codegen/cli/docs-generator.js +168 -65
- package/esm/core/codegen/cli/table-command-generator.d.ts +15 -0
- package/esm/core/codegen/cli/table-command-generator.js +29 -5
- package/esm/core/codegen/docs-utils.d.ts +26 -1
- package/esm/core/codegen/docs-utils.js +102 -0
- package/esm/core/codegen/orm/input-types-generator.js +112 -14
- package/esm/core/codegen/orm/model-generator.js +8 -0
- package/esm/core/codegen/orm/select-types.d.ts +4 -2
- package/esm/core/codegen/scalars.js +8 -0
- package/esm/core/generate.js +14 -4
- package/package.json +11 -11
|
@@ -12,9 +12,10 @@ exports.generateMultiTargetSkills = generateMultiTargetSkills;
|
|
|
12
12
|
const komoji_1 = require("komoji");
|
|
13
13
|
const docs_utils_1 = require("../docs-utils");
|
|
14
14
|
const utils_1 = require("../utils");
|
|
15
|
+
const table_command_generator_1 = require("./table-command-generator");
|
|
15
16
|
var docs_utils_2 = require("../docs-utils");
|
|
16
17
|
Object.defineProperty(exports, "resolveDocsConfig", { enumerable: true, get: function () { return docs_utils_2.resolveDocsConfig; } });
|
|
17
|
-
function generateReadme(tables, customOperations, toolName) {
|
|
18
|
+
function generateReadme(tables, customOperations, toolName, registry) {
|
|
18
19
|
const lines = [];
|
|
19
20
|
lines.push(...(0, docs_utils_1.getReadmeHeader)(`${toolName} CLI`));
|
|
20
21
|
lines.push('## Setup');
|
|
@@ -98,10 +99,21 @@ function generateReadme(tables, customOperations, toolName) {
|
|
|
98
99
|
lines.push('| Field | Type |');
|
|
99
100
|
lines.push('|-------|------|');
|
|
100
101
|
for (const f of scalarFields) {
|
|
101
|
-
lines.push(`| \`${f.name}\` | ${f.type.gqlType} |`);
|
|
102
|
+
lines.push(`| \`${f.name}\` | ${(0, docs_utils_1.cleanTypeName)(f.type.gqlType)} |`);
|
|
102
103
|
}
|
|
103
104
|
lines.push('');
|
|
104
|
-
|
|
105
|
+
const defaultFields = (0, table_command_generator_1.getFieldsWithDefaults)(table, registry);
|
|
106
|
+
const requiredCreate = editableFields.filter((f) => !defaultFields.has(f.name));
|
|
107
|
+
const optionalCreate = editableFields.filter((f) => defaultFields.has(f.name));
|
|
108
|
+
if (requiredCreate.length > 0) {
|
|
109
|
+
lines.push(`**Required create fields:** ${requiredCreate.map((f) => `\`${f.name}\``).join(', ')}`);
|
|
110
|
+
}
|
|
111
|
+
if (optionalCreate.length > 0) {
|
|
112
|
+
lines.push(`**Optional create fields (backend defaults):** ${optionalCreate.map((f) => `\`${f.name}\``).join(', ')}`);
|
|
113
|
+
}
|
|
114
|
+
if (requiredCreate.length === 0 && optionalCreate.length === 0) {
|
|
115
|
+
lines.push(`**Create fields:** ${editableFields.map((f) => `\`${f.name}\``).join(', ')}`);
|
|
116
|
+
}
|
|
105
117
|
lines.push('');
|
|
106
118
|
}
|
|
107
119
|
}
|
|
@@ -110,18 +122,20 @@ function generateReadme(tables, customOperations, toolName) {
|
|
|
110
122
|
lines.push('');
|
|
111
123
|
for (const op of customOperations) {
|
|
112
124
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
125
|
+
const flat = (0, docs_utils_1.flattenArgs)(op.args, registry);
|
|
113
126
|
lines.push(`### \`${kebab}\``);
|
|
114
127
|
lines.push('');
|
|
115
128
|
lines.push(op.description || op.name);
|
|
116
129
|
lines.push('');
|
|
117
130
|
lines.push(`- **Type:** ${op.kind}`);
|
|
118
|
-
if (
|
|
131
|
+
if (flat.length > 0) {
|
|
119
132
|
lines.push('- **Arguments:**');
|
|
120
133
|
lines.push('');
|
|
121
134
|
lines.push(' | Argument | Type |');
|
|
122
135
|
lines.push(' |----------|------|');
|
|
123
|
-
for (const
|
|
124
|
-
|
|
136
|
+
for (const a of flat) {
|
|
137
|
+
const reqLabel = a.required ? ' (required)' : '';
|
|
138
|
+
lines.push(` | \`--${a.flag}\` | ${a.type}${reqLabel} |`);
|
|
125
139
|
}
|
|
126
140
|
}
|
|
127
141
|
else {
|
|
@@ -139,13 +153,21 @@ function generateReadme(tables, customOperations, toolName) {
|
|
|
139
153
|
lines.push(`${toolName} car get --id <uuid> | jq '.'`);
|
|
140
154
|
lines.push('```');
|
|
141
155
|
lines.push('');
|
|
156
|
+
lines.push('## Non-Interactive Mode');
|
|
157
|
+
lines.push('');
|
|
158
|
+
lines.push('Use `--no-tty` to skip all interactive prompts (useful for scripts and CI):');
|
|
159
|
+
lines.push('');
|
|
160
|
+
lines.push('```bash');
|
|
161
|
+
lines.push(`${toolName} --no-tty car create --name "Sedan" --year 2024`);
|
|
162
|
+
lines.push('```');
|
|
163
|
+
lines.push('');
|
|
142
164
|
lines.push(...(0, docs_utils_1.getReadmeFooter)());
|
|
143
165
|
return {
|
|
144
166
|
fileName: 'README.md',
|
|
145
167
|
content: lines.join('\n'),
|
|
146
168
|
};
|
|
147
169
|
}
|
|
148
|
-
function generateAgentsDocs(tables, customOperations, toolName) {
|
|
170
|
+
function generateAgentsDocs(tables, customOperations, toolName, registry) {
|
|
149
171
|
const lines = [];
|
|
150
172
|
lines.push(`# ${toolName} CLI - Agent Reference`);
|
|
151
173
|
lines.push('');
|
|
@@ -217,6 +239,13 @@ function generateAgentsDocs(tables, customOperations, toolName) {
|
|
|
217
239
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
218
240
|
const scalarFields = (0, utils_1.getScalarFields)(table);
|
|
219
241
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
242
|
+
const defaultFields = (0, table_command_generator_1.getFieldsWithDefaults)(table, registry);
|
|
243
|
+
const requiredCreateFields = editableFields.filter((f) => !defaultFields.has(f.name));
|
|
244
|
+
const optionalCreateFields = editableFields.filter((f) => defaultFields.has(f.name));
|
|
245
|
+
const createFlags = [
|
|
246
|
+
...requiredCreateFields.map((f) => `--${f.name} <value>`),
|
|
247
|
+
...optionalCreateFields.map((f) => `[--${f.name} <value>]`),
|
|
248
|
+
].join(' ');
|
|
220
249
|
lines.push(`### TOOL: ${kebab}`);
|
|
221
250
|
lines.push('');
|
|
222
251
|
lines.push(`CRUD operations for ${table.name} records.`);
|
|
@@ -225,19 +254,20 @@ function generateAgentsDocs(tables, customOperations, toolName) {
|
|
|
225
254
|
lines.push('SUBCOMMANDS:');
|
|
226
255
|
lines.push(` ${toolName} ${kebab} list List all records`);
|
|
227
256
|
lines.push(` ${toolName} ${kebab} get --${pk.name} <value> Get one record`);
|
|
228
|
-
lines.push(` ${toolName} ${kebab} create ${
|
|
257
|
+
lines.push(` ${toolName} ${kebab} create ${createFlags}`);
|
|
229
258
|
lines.push(` ${toolName} ${kebab} update --${pk.name} <value> ${editableFields.map((f) => `[--${f.name} <value>]`).join(' ')}`);
|
|
230
259
|
lines.push(` ${toolName} ${kebab} delete --${pk.name} <value> Delete one record`);
|
|
231
260
|
lines.push('');
|
|
232
261
|
lines.push('INPUT FIELDS:');
|
|
233
262
|
for (const f of scalarFields) {
|
|
234
263
|
const isPk = f.name === pk.name;
|
|
235
|
-
lines.push(` ${f.name}: ${f.type.gqlType}${isPk ? ' (primary key)' : ''}`);
|
|
264
|
+
lines.push(` ${f.name}: ${(0, docs_utils_1.cleanTypeName)(f.type.gqlType)}${isPk ? ' (primary key)' : ''}`);
|
|
236
265
|
}
|
|
237
266
|
lines.push('');
|
|
238
267
|
lines.push('EDITABLE FIELDS (for create/update):');
|
|
239
268
|
for (const f of editableFields) {
|
|
240
|
-
|
|
269
|
+
const optLabel = defaultFields.has(f.name) ? ' (optional, has backend default)' : '';
|
|
270
|
+
lines.push(` ${f.name}: ${(0, docs_utils_1.cleanTypeName)(f.type.gqlType)}${optLabel}`);
|
|
241
271
|
}
|
|
242
272
|
lines.push('');
|
|
243
273
|
lines.push('OUTPUT: JSON');
|
|
@@ -251,19 +281,21 @@ function generateAgentsDocs(tables, customOperations, toolName) {
|
|
|
251
281
|
}
|
|
252
282
|
for (const op of customOperations) {
|
|
253
283
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
284
|
+
const flat = (0, docs_utils_1.flattenArgs)(op.args, registry);
|
|
254
285
|
lines.push(`### TOOL: ${kebab}`);
|
|
255
286
|
lines.push('');
|
|
256
287
|
lines.push(op.description || op.name);
|
|
257
288
|
lines.push('');
|
|
258
289
|
lines.push('```');
|
|
259
290
|
lines.push(`TYPE: ${op.kind}`);
|
|
260
|
-
if (
|
|
261
|
-
const flags =
|
|
291
|
+
if (flat.length > 0) {
|
|
292
|
+
const flags = (0, docs_utils_1.flattenedArgsToFlags)(flat);
|
|
262
293
|
lines.push(`USAGE: ${toolName} ${kebab} ${flags}`);
|
|
263
294
|
lines.push('');
|
|
264
295
|
lines.push('INPUT:');
|
|
265
|
-
for (const
|
|
266
|
-
|
|
296
|
+
for (const a of flat) {
|
|
297
|
+
const reqLabel = a.required ? ' (required)' : '';
|
|
298
|
+
lines.push(` ${a.flag}: ${a.type}${reqLabel}`);
|
|
267
299
|
}
|
|
268
300
|
}
|
|
269
301
|
else {
|
|
@@ -341,7 +373,7 @@ function generateAgentsDocs(tables, customOperations, toolName) {
|
|
|
341
373
|
content: lines.join('\n'),
|
|
342
374
|
};
|
|
343
375
|
}
|
|
344
|
-
function getCliMcpTools(tables, customOperations, toolName) {
|
|
376
|
+
function getCliMcpTools(tables, customOperations, toolName, registry) {
|
|
345
377
|
const tools = [];
|
|
346
378
|
tools.push({
|
|
347
379
|
name: `${toolName}_context_create`,
|
|
@@ -414,6 +446,10 @@ function getCliMcpTools(tables, customOperations, toolName) {
|
|
|
414
446
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
415
447
|
const scalarFields = (0, utils_1.getScalarFields)(table);
|
|
416
448
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
449
|
+
const defaultFields = (0, table_command_generator_1.getFieldsWithDefaults)(table, registry);
|
|
450
|
+
const requiredCreateFieldNames = editableFields
|
|
451
|
+
.filter((f) => !defaultFields.has(f.name))
|
|
452
|
+
.map((f) => f.name);
|
|
417
453
|
tools.push({
|
|
418
454
|
name: `${toolName}_${kebab}_list`,
|
|
419
455
|
description: `List all ${table.name} records`,
|
|
@@ -436,7 +472,7 @@ function getCliMcpTools(tables, customOperations, toolName) {
|
|
|
436
472
|
const createProps = {};
|
|
437
473
|
for (const f of editableFields) {
|
|
438
474
|
createProps[f.name] = {
|
|
439
|
-
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(f.type.gqlType),
|
|
475
|
+
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)((0, docs_utils_1.cleanTypeName)(f.type.gqlType)),
|
|
440
476
|
description: `${table.name} ${f.name}`,
|
|
441
477
|
};
|
|
442
478
|
}
|
|
@@ -446,7 +482,7 @@ function getCliMcpTools(tables, customOperations, toolName) {
|
|
|
446
482
|
inputSchema: {
|
|
447
483
|
type: 'object',
|
|
448
484
|
properties: createProps,
|
|
449
|
-
required:
|
|
485
|
+
...(requiredCreateFieldNames.length > 0 ? { required: requiredCreateFieldNames } : {}),
|
|
450
486
|
},
|
|
451
487
|
});
|
|
452
488
|
const updateProps = {
|
|
@@ -457,7 +493,7 @@ function getCliMcpTools(tables, customOperations, toolName) {
|
|
|
457
493
|
};
|
|
458
494
|
for (const f of editableFields) {
|
|
459
495
|
updateProps[f.name] = {
|
|
460
|
-
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(f.type.gqlType),
|
|
496
|
+
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)((0, docs_utils_1.cleanTypeName)(f.type.gqlType)),
|
|
461
497
|
description: `${table.name} ${f.name}`,
|
|
462
498
|
};
|
|
463
499
|
}
|
|
@@ -491,7 +527,7 @@ function getCliMcpTools(tables, customOperations, toolName) {
|
|
|
491
527
|
_meta: {
|
|
492
528
|
fields: scalarFields.map((f) => ({
|
|
493
529
|
name: f.name,
|
|
494
|
-
type: f.type.gqlType,
|
|
530
|
+
type: (0, docs_utils_1.cleanTypeName)(f.type.gqlType),
|
|
495
531
|
editable: editableFields.some((ef) => ef.name === f.name),
|
|
496
532
|
primaryKey: f.name === pk.name,
|
|
497
533
|
})),
|
|
@@ -500,17 +536,16 @@ function getCliMcpTools(tables, customOperations, toolName) {
|
|
|
500
536
|
}
|
|
501
537
|
for (const op of customOperations) {
|
|
502
538
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
539
|
+
const flat = (0, docs_utils_1.flattenArgs)(op.args, registry);
|
|
503
540
|
const props = {};
|
|
504
541
|
const required = [];
|
|
505
|
-
for (const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(baseType.name ?? 'String'),
|
|
510
|
-
description: arg.description || arg.name,
|
|
542
|
+
for (const a of flat) {
|
|
543
|
+
props[a.flag] = {
|
|
544
|
+
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(a.type),
|
|
545
|
+
description: a.description || a.flag,
|
|
511
546
|
};
|
|
512
|
-
if (
|
|
513
|
-
required.push(
|
|
547
|
+
if (a.required) {
|
|
548
|
+
required.push(a.flag);
|
|
514
549
|
}
|
|
515
550
|
}
|
|
516
551
|
tools.push({
|
|
@@ -525,7 +560,7 @@ function getCliMcpTools(tables, customOperations, toolName) {
|
|
|
525
560
|
}
|
|
526
561
|
return tools;
|
|
527
562
|
}
|
|
528
|
-
function generateSkills(tables, customOperations, toolName, targetName) {
|
|
563
|
+
function generateSkills(tables, customOperations, toolName, targetName, registry) {
|
|
529
564
|
const files = [];
|
|
530
565
|
const skillName = `cli-${targetName}`;
|
|
531
566
|
const referenceNames = [];
|
|
@@ -588,6 +623,11 @@ function generateSkills(tables, customOperations, toolName, targetName) {
|
|
|
588
623
|
const kebab = (0, komoji_1.toKebabCase)(singularName);
|
|
589
624
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
590
625
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
626
|
+
const defaultFields = (0, table_command_generator_1.getFieldsWithDefaults)(table, registry);
|
|
627
|
+
const createFlags = [
|
|
628
|
+
...editableFields.filter((f) => !defaultFields.has(f.name)).map((f) => `--${f.name} <value>`),
|
|
629
|
+
...editableFields.filter((f) => defaultFields.has(f.name)).map((f) => `[--${f.name} <value>]`),
|
|
630
|
+
].join(' ');
|
|
591
631
|
referenceNames.push(kebab);
|
|
592
632
|
files.push({
|
|
593
633
|
fileName: `${skillName}/references/${kebab}.md`,
|
|
@@ -597,7 +637,7 @@ function generateSkills(tables, customOperations, toolName, targetName) {
|
|
|
597
637
|
usage: [
|
|
598
638
|
`${toolName} ${kebab} list`,
|
|
599
639
|
`${toolName} ${kebab} get --${pk.name} <value>`,
|
|
600
|
-
`${toolName} ${kebab} create ${
|
|
640
|
+
`${toolName} ${kebab} create ${createFlags}`,
|
|
601
641
|
`${toolName} ${kebab} update --${pk.name} <value> ${editableFields.map((f) => `[--${f.name} <value>]`).join(' ')}`,
|
|
602
642
|
`${toolName} ${kebab} delete --${pk.name} <value>`,
|
|
603
643
|
],
|
|
@@ -609,7 +649,7 @@ function generateSkills(tables, customOperations, toolName, targetName) {
|
|
|
609
649
|
{
|
|
610
650
|
description: `Create a ${singularName}`,
|
|
611
651
|
code: [
|
|
612
|
-
`${toolName} ${kebab} create ${
|
|
652
|
+
`${toolName} ${kebab} create ${createFlags}`,
|
|
613
653
|
],
|
|
614
654
|
},
|
|
615
655
|
{
|
|
@@ -623,8 +663,9 @@ function generateSkills(tables, customOperations, toolName, targetName) {
|
|
|
623
663
|
// Custom operation references
|
|
624
664
|
for (const op of customOperations) {
|
|
625
665
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
626
|
-
const
|
|
627
|
-
|
|
666
|
+
const flat = (0, docs_utils_1.flattenArgs)(op.args, registry);
|
|
667
|
+
const usage = flat.length > 0
|
|
668
|
+
? `${toolName} ${kebab} ${(0, docs_utils_1.flattenedArgsToFlags)(flat)}`
|
|
628
669
|
: `${toolName} ${kebab}`;
|
|
629
670
|
referenceNames.push(kebab);
|
|
630
671
|
files.push({
|
|
@@ -661,6 +702,9 @@ function generateSkills(tables, customOperations, toolName, targetName) {
|
|
|
661
702
|
`${toolName} ${tableKebabs[0] || 'model'} list`,
|
|
662
703
|
`${toolName} ${tableKebabs[0] || 'model'} get --id <value>`,
|
|
663
704
|
`${toolName} ${tableKebabs[0] || 'model'} create --<field> <value>`,
|
|
705
|
+
'',
|
|
706
|
+
`# Non-interactive mode (skip all prompts, use flags only)`,
|
|
707
|
+
`${toolName} --no-tty ${tableKebabs[0] || 'model'} list`,
|
|
664
708
|
],
|
|
665
709
|
examples: [
|
|
666
710
|
{
|
|
@@ -672,13 +716,19 @@ function generateSkills(tables, customOperations, toolName, targetName) {
|
|
|
672
716
|
`${toolName} ${tableKebabs[0] || 'model'} list`,
|
|
673
717
|
],
|
|
674
718
|
},
|
|
719
|
+
{
|
|
720
|
+
description: 'Non-interactive mode (for scripts and CI)',
|
|
721
|
+
code: [
|
|
722
|
+
`${toolName} --no-tty ${tableKebabs[0] || 'model'} create --<field> <value>`,
|
|
723
|
+
],
|
|
724
|
+
},
|
|
675
725
|
],
|
|
676
726
|
}, referenceNames),
|
|
677
727
|
});
|
|
678
728
|
return files;
|
|
679
729
|
}
|
|
680
730
|
function generateMultiTargetReadme(input) {
|
|
681
|
-
const { toolName, builtinNames, targets } = input;
|
|
731
|
+
const { toolName, builtinNames, targets, registry } = input;
|
|
682
732
|
const lines = [];
|
|
683
733
|
lines.push(...(0, docs_utils_1.getReadmeHeader)(`${toolName} CLI`));
|
|
684
734
|
lines.push('## Setup');
|
|
@@ -803,6 +853,7 @@ function generateMultiTargetReadme(input) {
|
|
|
803
853
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
804
854
|
const scalarFields = (0, utils_1.getScalarFields)(table);
|
|
805
855
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
856
|
+
const defaultFields = (0, table_command_generator_1.getFieldsWithDefaults)(table, registry);
|
|
806
857
|
lines.push(`### \`${tgt.name}:${kebab}\``);
|
|
807
858
|
lines.push('');
|
|
808
859
|
lines.push(`CRUD operations for ${table.name} records.`);
|
|
@@ -820,26 +871,38 @@ function generateMultiTargetReadme(input) {
|
|
|
820
871
|
lines.push('| Field | Type |');
|
|
821
872
|
lines.push('|-------|------|');
|
|
822
873
|
for (const f of scalarFields) {
|
|
823
|
-
lines.push(`| \`${f.name}\` | ${f.type.gqlType} |`);
|
|
874
|
+
lines.push(`| \`${f.name}\` | ${(0, docs_utils_1.cleanTypeName)(f.type.gqlType)} |`);
|
|
824
875
|
}
|
|
825
876
|
lines.push('');
|
|
826
|
-
|
|
877
|
+
const requiredCreate = editableFields.filter((f) => !defaultFields.has(f.name));
|
|
878
|
+
const optionalCreate = editableFields.filter((f) => defaultFields.has(f.name));
|
|
879
|
+
if (requiredCreate.length > 0) {
|
|
880
|
+
lines.push(`**Required create fields:** ${requiredCreate.map((f) => `\`${f.name}\``).join(', ')}`);
|
|
881
|
+
}
|
|
882
|
+
if (optionalCreate.length > 0) {
|
|
883
|
+
lines.push(`**Optional create fields (backend defaults):** ${optionalCreate.map((f) => `\`${f.name}\``).join(', ')}`);
|
|
884
|
+
}
|
|
885
|
+
if (requiredCreate.length === 0 && optionalCreate.length === 0) {
|
|
886
|
+
lines.push(`**Create fields:** ${editableFields.map((f) => `\`${f.name}\``).join(', ')}`);
|
|
887
|
+
}
|
|
827
888
|
lines.push('');
|
|
828
889
|
}
|
|
829
890
|
for (const op of tgt.customOperations) {
|
|
830
891
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
892
|
+
const flat = (0, docs_utils_1.flattenArgs)(op.args, registry);
|
|
831
893
|
lines.push(`### \`${tgt.name}:${kebab}\``);
|
|
832
894
|
lines.push('');
|
|
833
895
|
lines.push(op.description || op.name);
|
|
834
896
|
lines.push('');
|
|
835
897
|
lines.push(`- **Type:** ${op.kind}`);
|
|
836
|
-
if (
|
|
898
|
+
if (flat.length > 0) {
|
|
837
899
|
lines.push('- **Arguments:**');
|
|
838
900
|
lines.push('');
|
|
839
901
|
lines.push(' | Argument | Type |');
|
|
840
902
|
lines.push(' |----------|------|');
|
|
841
|
-
for (const
|
|
842
|
-
|
|
903
|
+
for (const a of flat) {
|
|
904
|
+
const reqLabel = a.required ? ' (required)' : '';
|
|
905
|
+
lines.push(` | \`--${a.flag}\` | ${a.type}${reqLabel} |`);
|
|
843
906
|
}
|
|
844
907
|
}
|
|
845
908
|
else {
|
|
@@ -864,6 +927,18 @@ function generateMultiTargetReadme(input) {
|
|
|
864
927
|
}
|
|
865
928
|
lines.push('```');
|
|
866
929
|
lines.push('');
|
|
930
|
+
lines.push('## Non-Interactive Mode');
|
|
931
|
+
lines.push('');
|
|
932
|
+
lines.push('Use `--no-tty` to skip all interactive prompts (useful for scripts and CI):');
|
|
933
|
+
lines.push('');
|
|
934
|
+
lines.push('```bash');
|
|
935
|
+
if (targets.length > 0 && targets[0].tables.length > 0) {
|
|
936
|
+
const tgt = targets[0];
|
|
937
|
+
const kebab = (0, komoji_1.toKebabCase)((0, utils_1.getTableNames)(tgt.tables[0]).singularName);
|
|
938
|
+
lines.push(`${toolName} --no-tty ${tgt.name}:${kebab} create --name "Example"`);
|
|
939
|
+
}
|
|
940
|
+
lines.push('```');
|
|
941
|
+
lines.push('');
|
|
867
942
|
lines.push(...(0, docs_utils_1.getReadmeFooter)());
|
|
868
943
|
return {
|
|
869
944
|
fileName: 'README.md',
|
|
@@ -871,7 +946,7 @@ function generateMultiTargetReadme(input) {
|
|
|
871
946
|
};
|
|
872
947
|
}
|
|
873
948
|
function generateMultiTargetAgentsDocs(input) {
|
|
874
|
-
const { toolName, builtinNames, targets } = input;
|
|
949
|
+
const { toolName, builtinNames, targets, registry } = input;
|
|
875
950
|
const lines = [];
|
|
876
951
|
lines.push(`# ${toolName} CLI - Agent Reference`);
|
|
877
952
|
lines.push('');
|
|
@@ -964,6 +1039,13 @@ function generateMultiTargetAgentsDocs(input) {
|
|
|
964
1039
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
965
1040
|
const scalarFields = (0, utils_1.getScalarFields)(table);
|
|
966
1041
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
1042
|
+
const defaultFields = (0, table_command_generator_1.getFieldsWithDefaults)(table, registry);
|
|
1043
|
+
const requiredCreateFields = editableFields.filter((f) => !defaultFields.has(f.name));
|
|
1044
|
+
const optionalCreateFields = editableFields.filter((f) => defaultFields.has(f.name));
|
|
1045
|
+
const createFlags = [
|
|
1046
|
+
...requiredCreateFields.map((f) => `--${f.name} <value>`),
|
|
1047
|
+
...optionalCreateFields.map((f) => `[--${f.name} <value>]`),
|
|
1048
|
+
].join(' ');
|
|
967
1049
|
lines.push(`### TOOL: ${tgt.name}:${kebab}`);
|
|
968
1050
|
lines.push('');
|
|
969
1051
|
lines.push(`CRUD operations for ${table.name} records (${tgt.name} target).`);
|
|
@@ -972,19 +1054,20 @@ function generateMultiTargetAgentsDocs(input) {
|
|
|
972
1054
|
lines.push('SUBCOMMANDS:');
|
|
973
1055
|
lines.push(` ${toolName} ${tgt.name}:${kebab} list List all records`);
|
|
974
1056
|
lines.push(` ${toolName} ${tgt.name}:${kebab} get --${pk.name} <value> Get one record`);
|
|
975
|
-
lines.push(` ${toolName} ${tgt.name}:${kebab} create ${
|
|
1057
|
+
lines.push(` ${toolName} ${tgt.name}:${kebab} create ${createFlags}`);
|
|
976
1058
|
lines.push(` ${toolName} ${tgt.name}:${kebab} update --${pk.name} <value> ${editableFields.map((f) => `[--${f.name} <value>]`).join(' ')}`);
|
|
977
1059
|
lines.push(` ${toolName} ${tgt.name}:${kebab} delete --${pk.name} <value> Delete one record`);
|
|
978
1060
|
lines.push('');
|
|
979
1061
|
lines.push('INPUT FIELDS:');
|
|
980
1062
|
for (const f of scalarFields) {
|
|
981
1063
|
const isPk = f.name === pk.name;
|
|
982
|
-
lines.push(` ${f.name}: ${f.type.gqlType}${isPk ? ' (primary key)' : ''}`);
|
|
1064
|
+
lines.push(` ${f.name}: ${(0, docs_utils_1.cleanTypeName)(f.type.gqlType)}${isPk ? ' (primary key)' : ''}`);
|
|
983
1065
|
}
|
|
984
1066
|
lines.push('');
|
|
985
1067
|
lines.push('EDITABLE FIELDS (for create/update):');
|
|
986
1068
|
for (const f of editableFields) {
|
|
987
|
-
|
|
1069
|
+
const optLabel = defaultFields.has(f.name) ? ' (optional, has backend default)' : '';
|
|
1070
|
+
lines.push(` ${f.name}: ${(0, docs_utils_1.cleanTypeName)(f.type.gqlType)}${optLabel}`);
|
|
988
1071
|
}
|
|
989
1072
|
lines.push('');
|
|
990
1073
|
lines.push('OUTPUT: JSON');
|
|
@@ -998,19 +1081,21 @@ function generateMultiTargetAgentsDocs(input) {
|
|
|
998
1081
|
}
|
|
999
1082
|
for (const op of tgt.customOperations) {
|
|
1000
1083
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
1084
|
+
const flat = (0, docs_utils_1.flattenArgs)(op.args, registry);
|
|
1001
1085
|
lines.push(`### TOOL: ${tgt.name}:${kebab}`);
|
|
1002
1086
|
lines.push('');
|
|
1003
1087
|
lines.push(op.description || op.name);
|
|
1004
1088
|
lines.push('');
|
|
1005
1089
|
lines.push('```');
|
|
1006
1090
|
lines.push(`TYPE: ${op.kind}`);
|
|
1007
|
-
if (
|
|
1008
|
-
const flags =
|
|
1091
|
+
if (flat.length > 0) {
|
|
1092
|
+
const flags = (0, docs_utils_1.flattenedArgsToFlags)(flat);
|
|
1009
1093
|
lines.push(`USAGE: ${toolName} ${tgt.name}:${kebab} ${flags}`);
|
|
1010
1094
|
lines.push('');
|
|
1011
1095
|
lines.push('INPUT:');
|
|
1012
|
-
for (const
|
|
1013
|
-
|
|
1096
|
+
for (const a of flat) {
|
|
1097
|
+
const reqLabel = a.required ? ' (required)' : '';
|
|
1098
|
+
lines.push(` ${a.flag}: ${a.type}${reqLabel}`);
|
|
1014
1099
|
}
|
|
1015
1100
|
}
|
|
1016
1101
|
else {
|
|
@@ -1099,7 +1184,7 @@ function generateMultiTargetAgentsDocs(input) {
|
|
|
1099
1184
|
};
|
|
1100
1185
|
}
|
|
1101
1186
|
function getMultiTargetCliMcpTools(input) {
|
|
1102
|
-
const { toolName, builtinNames, targets } = input;
|
|
1187
|
+
const { toolName, builtinNames, targets, registry } = input;
|
|
1103
1188
|
const tools = [];
|
|
1104
1189
|
const contextEndpointProps = {
|
|
1105
1190
|
name: { type: 'string', description: 'Context name' },
|
|
@@ -1179,6 +1264,10 @@ function getMultiTargetCliMcpTools(input) {
|
|
|
1179
1264
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
1180
1265
|
const scalarFields = (0, utils_1.getScalarFields)(table);
|
|
1181
1266
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
1267
|
+
const defaultFields = (0, table_command_generator_1.getFieldsWithDefaults)(table, registry);
|
|
1268
|
+
const requiredCreateFieldNames = editableFields
|
|
1269
|
+
.filter((f) => !defaultFields.has(f.name))
|
|
1270
|
+
.map((f) => f.name);
|
|
1182
1271
|
const prefix = `${toolName}_${tgt.name}_${kebab}`;
|
|
1183
1272
|
tools.push({
|
|
1184
1273
|
name: `${prefix}_list`,
|
|
@@ -1202,7 +1291,7 @@ function getMultiTargetCliMcpTools(input) {
|
|
|
1202
1291
|
const createProps = {};
|
|
1203
1292
|
for (const f of editableFields) {
|
|
1204
1293
|
createProps[f.name] = {
|
|
1205
|
-
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(f.type.gqlType),
|
|
1294
|
+
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)((0, docs_utils_1.cleanTypeName)(f.type.gqlType)),
|
|
1206
1295
|
description: `${table.name} ${f.name}`,
|
|
1207
1296
|
};
|
|
1208
1297
|
}
|
|
@@ -1212,7 +1301,7 @@ function getMultiTargetCliMcpTools(input) {
|
|
|
1212
1301
|
inputSchema: {
|
|
1213
1302
|
type: 'object',
|
|
1214
1303
|
properties: createProps,
|
|
1215
|
-
required:
|
|
1304
|
+
...(requiredCreateFieldNames.length > 0 ? { required: requiredCreateFieldNames } : {}),
|
|
1216
1305
|
},
|
|
1217
1306
|
});
|
|
1218
1307
|
const updateProps = {
|
|
@@ -1223,7 +1312,7 @@ function getMultiTargetCliMcpTools(input) {
|
|
|
1223
1312
|
};
|
|
1224
1313
|
for (const f of editableFields) {
|
|
1225
1314
|
updateProps[f.name] = {
|
|
1226
|
-
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(f.type.gqlType),
|
|
1315
|
+
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)((0, docs_utils_1.cleanTypeName)(f.type.gqlType)),
|
|
1227
1316
|
description: `${table.name} ${f.name}`,
|
|
1228
1317
|
};
|
|
1229
1318
|
}
|
|
@@ -1257,7 +1346,7 @@ function getMultiTargetCliMcpTools(input) {
|
|
|
1257
1346
|
_meta: {
|
|
1258
1347
|
fields: scalarFields.map((f) => ({
|
|
1259
1348
|
name: f.name,
|
|
1260
|
-
type: f.type.gqlType,
|
|
1349
|
+
type: (0, docs_utils_1.cleanTypeName)(f.type.gqlType),
|
|
1261
1350
|
editable: editableFields.some((ef) => ef.name === f.name),
|
|
1262
1351
|
primaryKey: f.name === pk.name,
|
|
1263
1352
|
})),
|
|
@@ -1266,17 +1355,16 @@ function getMultiTargetCliMcpTools(input) {
|
|
|
1266
1355
|
}
|
|
1267
1356
|
for (const op of tgt.customOperations) {
|
|
1268
1357
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
1358
|
+
const flat = (0, docs_utils_1.flattenArgs)(op.args, registry);
|
|
1269
1359
|
const props = {};
|
|
1270
1360
|
const required = [];
|
|
1271
|
-
for (const
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(baseType.name ?? 'String'),
|
|
1276
|
-
description: arg.description || arg.name,
|
|
1361
|
+
for (const a of flat) {
|
|
1362
|
+
props[a.flag] = {
|
|
1363
|
+
type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(a.type),
|
|
1364
|
+
description: a.description || a.flag,
|
|
1277
1365
|
};
|
|
1278
|
-
if (
|
|
1279
|
-
required.push(
|
|
1366
|
+
if (a.required) {
|
|
1367
|
+
required.push(a.flag);
|
|
1280
1368
|
}
|
|
1281
1369
|
}
|
|
1282
1370
|
if (tgt.isAuthTarget && op.kind === 'mutation') {
|
|
@@ -1299,7 +1387,7 @@ function getMultiTargetCliMcpTools(input) {
|
|
|
1299
1387
|
return tools;
|
|
1300
1388
|
}
|
|
1301
1389
|
function generateMultiTargetSkills(input) {
|
|
1302
|
-
const { toolName, builtinNames, targets } = input;
|
|
1390
|
+
const { toolName, builtinNames, targets, registry } = input;
|
|
1303
1391
|
const files = [];
|
|
1304
1392
|
// Generate one skill per target, plus a shared cli-common skill for context/auth
|
|
1305
1393
|
const commonSkillName = 'cli-common';
|
|
@@ -1399,6 +1487,11 @@ function generateMultiTargetSkills(input) {
|
|
|
1399
1487
|
const kebab = (0, komoji_1.toKebabCase)(singularName);
|
|
1400
1488
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
1401
1489
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
1490
|
+
const defaultFields = (0, table_command_generator_1.getFieldsWithDefaults)(table, registry);
|
|
1491
|
+
const createFlags = [
|
|
1492
|
+
...editableFields.filter((f) => !defaultFields.has(f.name)).map((f) => `--${f.name} <value>`),
|
|
1493
|
+
...editableFields.filter((f) => defaultFields.has(f.name)).map((f) => `[--${f.name} <value>]`),
|
|
1494
|
+
].join(' ');
|
|
1402
1495
|
const cmd = `${tgt.name}:${kebab}`;
|
|
1403
1496
|
tgtReferenceNames.push(kebab);
|
|
1404
1497
|
files.push({
|
|
@@ -1409,7 +1502,7 @@ function generateMultiTargetSkills(input) {
|
|
|
1409
1502
|
usage: [
|
|
1410
1503
|
`${toolName} ${cmd} list`,
|
|
1411
1504
|
`${toolName} ${cmd} get --${pk.name} <value>`,
|
|
1412
|
-
`${toolName} ${cmd} create ${
|
|
1505
|
+
`${toolName} ${cmd} create ${createFlags}`,
|
|
1413
1506
|
`${toolName} ${cmd} update --${pk.name} <value> ${editableFields.map((f) => `[--${f.name} <value>]`).join(' ')}`,
|
|
1414
1507
|
`${toolName} ${cmd} delete --${pk.name} <value>`,
|
|
1415
1508
|
],
|
|
@@ -1421,7 +1514,7 @@ function generateMultiTargetSkills(input) {
|
|
|
1421
1514
|
{
|
|
1422
1515
|
description: `Create a ${singularName}`,
|
|
1423
1516
|
code: [
|
|
1424
|
-
`${toolName} ${cmd} create ${
|
|
1517
|
+
`${toolName} ${cmd} create ${createFlags}`,
|
|
1425
1518
|
],
|
|
1426
1519
|
},
|
|
1427
1520
|
],
|
|
@@ -1431,8 +1524,9 @@ function generateMultiTargetSkills(input) {
|
|
|
1431
1524
|
for (const op of tgt.customOperations) {
|
|
1432
1525
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
1433
1526
|
const cmd = `${tgt.name}:${kebab}`;
|
|
1434
|
-
const
|
|
1435
|
-
|
|
1527
|
+
const flat = (0, docs_utils_1.flattenArgs)(op.args, registry);
|
|
1528
|
+
const baseUsage = flat.length > 0
|
|
1529
|
+
? `${toolName} ${cmd} ${(0, docs_utils_1.flattenedArgsToFlags)(flat)}`
|
|
1436
1530
|
: `${toolName} ${cmd}`;
|
|
1437
1531
|
const usageLines = [baseUsage];
|
|
1438
1532
|
if (tgt.isAuthTarget && op.kind === 'mutation') {
|
|
@@ -1468,12 +1562,21 @@ function generateMultiTargetSkills(input) {
|
|
|
1468
1562
|
`${toolName} ${tgt.name}:${firstKebab} list`,
|
|
1469
1563
|
`${toolName} ${tgt.name}:${firstKebab} get --id <value>`,
|
|
1470
1564
|
`${toolName} ${tgt.name}:${firstKebab} create --<field> <value>`,
|
|
1565
|
+
'',
|
|
1566
|
+
`# Non-interactive mode (skip all prompts, use flags only)`,
|
|
1567
|
+
`${toolName} --no-tty ${tgt.name}:${firstKebab} list`,
|
|
1471
1568
|
],
|
|
1472
1569
|
examples: [
|
|
1473
1570
|
{
|
|
1474
1571
|
description: `Query ${tgt.name} records`,
|
|
1475
1572
|
code: [`${toolName} ${tgt.name}:${firstKebab} list`],
|
|
1476
1573
|
},
|
|
1574
|
+
{
|
|
1575
|
+
description: 'Non-interactive mode (for scripts and CI)',
|
|
1576
|
+
code: [
|
|
1577
|
+
`${toolName} --no-tty ${tgt.name}:${firstKebab} create --<field> <value>`,
|
|
1578
|
+
],
|
|
1579
|
+
},
|
|
1477
1580
|
],
|
|
1478
1581
|
}, tgtReferenceNames),
|
|
1479
1582
|
});
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import type { CleanTable, TypeRegistry } from '../../../types/schema';
|
|
2
2
|
import type { GeneratedFile } from './executor-generator';
|
|
3
|
+
/**
|
|
4
|
+
* Get the set of field names that have defaults in the create input type.
|
|
5
|
+
* Looks up the CreateXInput -> inner input type (e.g. DatabaseInput) in the
|
|
6
|
+
* TypeRegistry and checks each field's defaultValue from introspection.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the inner input type from a CreateXInput or UpdateXInput type.
|
|
10
|
+
* The CreateXInput has an inner field (e.g. "database" of type DatabaseInput)
|
|
11
|
+
* that contains the actual field definitions.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveInnerInputType(inputTypeName: string, typeRegistry: TypeRegistry): {
|
|
14
|
+
name: string;
|
|
15
|
+
fields: Set<string>;
|
|
16
|
+
} | null;
|
|
17
|
+
export declare function getFieldsWithDefaults(table: CleanTable, typeRegistry?: TypeRegistry): Set<string>;
|
|
3
18
|
export interface TableCommandOptions {
|
|
4
19
|
targetName?: string;
|
|
5
20
|
executorImportPath?: string;
|