@constructive-io/graphql-codegen 4.7.3 → 4.8.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/core/codegen/cli/docs-generator.d.ts +1 -1
- package/core/codegen/cli/docs-generator.js +137 -54
- package/core/codegen/docs-utils.d.ts +12 -1
- package/core/codegen/docs-utils.js +49 -1
- package/core/codegen/hooks-docs-generator.d.ts +1 -1
- package/core/codegen/hooks-docs-generator.js +47 -7
- package/core/codegen/orm/docs-generator.d.ts +1 -1
- package/core/codegen/orm/docs-generator.js +57 -20
- package/core/generate.d.ts +5 -0
- package/core/generate.js +48 -12
- package/core/workspace.d.ts +13 -0
- package/core/workspace.js +92 -0
- package/esm/core/codegen/cli/docs-generator.d.ts +1 -1
- package/esm/core/codegen/cli/docs-generator.js +138 -55
- package/esm/core/codegen/docs-utils.d.ts +12 -1
- package/esm/core/codegen/docs-utils.js +48 -1
- package/esm/core/codegen/hooks-docs-generator.d.ts +1 -1
- package/esm/core/codegen/hooks-docs-generator.js +48 -8
- package/esm/core/codegen/orm/docs-generator.d.ts +1 -1
- package/esm/core/codegen/orm/docs-generator.js +58 -21
- package/esm/core/generate.d.ts +5 -0
- package/esm/core/generate.js +48 -12
- package/esm/core/workspace.d.ts +13 -0
- package/esm/core/workspace.js +89 -0
- package/esm/types/config.d.ts +12 -4
- package/package.json +22 -22
- package/types/config.d.ts +12 -4
|
@@ -5,7 +5,7 @@ export type { GeneratedDocFile, McpTool } from '../docs-utils';
|
|
|
5
5
|
export declare function generateReadme(tables: CleanTable[], customOperations: CleanOperation[], toolName: string): GeneratedDocFile;
|
|
6
6
|
export declare function generateAgentsDocs(tables: CleanTable[], customOperations: CleanOperation[], toolName: string): GeneratedDocFile;
|
|
7
7
|
export declare function getCliMcpTools(tables: CleanTable[], customOperations: CleanOperation[], toolName: string): McpTool[];
|
|
8
|
-
export declare function generateSkills(tables: CleanTable[], customOperations: CleanOperation[], toolName: string): GeneratedDocFile[];
|
|
8
|
+
export declare function generateSkills(tables: CleanTable[], customOperations: CleanOperation[], toolName: string, targetName: string): GeneratedDocFile[];
|
|
9
9
|
export interface MultiTargetDocsInput {
|
|
10
10
|
toolName: string;
|
|
11
11
|
builtinNames: {
|
|
@@ -525,12 +525,16 @@ function getCliMcpTools(tables, customOperations, toolName) {
|
|
|
525
525
|
}
|
|
526
526
|
return tools;
|
|
527
527
|
}
|
|
528
|
-
function generateSkills(tables, customOperations, toolName) {
|
|
528
|
+
function generateSkills(tables, customOperations, toolName, targetName) {
|
|
529
529
|
const files = [];
|
|
530
|
+
const skillName = `cli-${targetName}`;
|
|
531
|
+
const referenceNames = [];
|
|
532
|
+
// Context reference
|
|
533
|
+
referenceNames.push('context');
|
|
530
534
|
files.push({
|
|
531
|
-
fileName:
|
|
532
|
-
content: (0, docs_utils_1.
|
|
533
|
-
|
|
535
|
+
fileName: `${skillName}/references/context.md`,
|
|
536
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
537
|
+
title: 'Context Management',
|
|
534
538
|
description: `Manage API endpoint contexts for ${toolName}`,
|
|
535
539
|
usage: [
|
|
536
540
|
`${toolName} context create <name> --endpoint <url>`,
|
|
@@ -554,10 +558,12 @@ function generateSkills(tables, customOperations, toolName) {
|
|
|
554
558
|
],
|
|
555
559
|
}),
|
|
556
560
|
});
|
|
561
|
+
// Auth reference
|
|
562
|
+
referenceNames.push('auth');
|
|
557
563
|
files.push({
|
|
558
|
-
fileName:
|
|
559
|
-
content: (0, docs_utils_1.
|
|
560
|
-
|
|
564
|
+
fileName: `${skillName}/references/auth.md`,
|
|
565
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
566
|
+
title: 'Authentication',
|
|
561
567
|
description: `Manage authentication tokens for ${toolName}`,
|
|
562
568
|
usage: [
|
|
563
569
|
`${toolName} auth set-token <token>`,
|
|
@@ -576,15 +582,17 @@ function generateSkills(tables, customOperations, toolName) {
|
|
|
576
582
|
],
|
|
577
583
|
}),
|
|
578
584
|
});
|
|
585
|
+
// Table references
|
|
579
586
|
for (const table of tables) {
|
|
580
587
|
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
581
588
|
const kebab = (0, komoji_1.toKebabCase)(singularName);
|
|
582
589
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
583
590
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
591
|
+
referenceNames.push(kebab);
|
|
584
592
|
files.push({
|
|
585
|
-
fileName:
|
|
586
|
-
content: (0, docs_utils_1.
|
|
587
|
-
|
|
593
|
+
fileName: `${skillName}/references/${kebab}.md`,
|
|
594
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
595
|
+
title: singularName,
|
|
588
596
|
description: `CRUD operations for ${table.name} records via ${toolName} CLI`,
|
|
589
597
|
usage: [
|
|
590
598
|
`${toolName} ${kebab} list`,
|
|
@@ -608,29 +616,21 @@ function generateSkills(tables, customOperations, toolName) {
|
|
|
608
616
|
description: `Get a ${singularName} by ${pk.name}`,
|
|
609
617
|
code: [`${toolName} ${kebab} get --${pk.name} <value>`],
|
|
610
618
|
},
|
|
611
|
-
{
|
|
612
|
-
description: `Update a ${singularName}`,
|
|
613
|
-
code: [
|
|
614
|
-
`${toolName} ${kebab} update --${pk.name} <value> --${editableFields[0]?.name || 'field'} "new-value"`,
|
|
615
|
-
],
|
|
616
|
-
},
|
|
617
|
-
{
|
|
618
|
-
description: `Delete a ${singularName}`,
|
|
619
|
-
code: [`${toolName} ${kebab} delete --${pk.name} <value>`],
|
|
620
|
-
},
|
|
621
619
|
],
|
|
622
620
|
}),
|
|
623
621
|
});
|
|
624
622
|
}
|
|
623
|
+
// Custom operation references
|
|
625
624
|
for (const op of customOperations) {
|
|
626
625
|
const kebab = (0, komoji_1.toKebabCase)(op.name);
|
|
627
626
|
const usage = op.args.length > 0
|
|
628
627
|
? `${toolName} ${kebab} ${op.args.map((a) => `--${a.name} <value>`).join(' ')}`
|
|
629
628
|
: `${toolName} ${kebab}`;
|
|
629
|
+
referenceNames.push(kebab);
|
|
630
630
|
files.push({
|
|
631
|
-
fileName:
|
|
632
|
-
content: (0, docs_utils_1.
|
|
633
|
-
|
|
631
|
+
fileName: `${skillName}/references/${kebab}.md`,
|
|
632
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
633
|
+
title: op.name,
|
|
634
634
|
description: op.description || `Execute the ${op.name} ${op.kind}`,
|
|
635
635
|
usage: [usage],
|
|
636
636
|
examples: [
|
|
@@ -642,6 +642,39 @@ function generateSkills(tables, customOperations, toolName) {
|
|
|
642
642
|
}),
|
|
643
643
|
});
|
|
644
644
|
}
|
|
645
|
+
// Overview SKILL.md
|
|
646
|
+
const tableKebabs = tables.slice(0, 5).map((t) => (0, komoji_1.toKebabCase)((0, utils_1.getTableNames)(t).singularName));
|
|
647
|
+
files.push({
|
|
648
|
+
fileName: `${skillName}/SKILL.md`,
|
|
649
|
+
content: (0, docs_utils_1.buildSkillFile)({
|
|
650
|
+
name: skillName,
|
|
651
|
+
description: `CLI tool (${toolName}) for the ${targetName} API — provides CRUD commands for ${tables.length} tables and ${customOperations.length} custom operations`,
|
|
652
|
+
usage: [
|
|
653
|
+
`# Context management`,
|
|
654
|
+
`${toolName} context create <name> --endpoint <url>`,
|
|
655
|
+
`${toolName} context use <name>`,
|
|
656
|
+
'',
|
|
657
|
+
`# Authentication`,
|
|
658
|
+
`${toolName} auth set-token <token>`,
|
|
659
|
+
'',
|
|
660
|
+
`# CRUD for any table (e.g. ${tableKebabs[0] || 'model'})`,
|
|
661
|
+
`${toolName} ${tableKebabs[0] || 'model'} list`,
|
|
662
|
+
`${toolName} ${tableKebabs[0] || 'model'} get --id <value>`,
|
|
663
|
+
`${toolName} ${tableKebabs[0] || 'model'} create --<field> <value>`,
|
|
664
|
+
],
|
|
665
|
+
examples: [
|
|
666
|
+
{
|
|
667
|
+
description: 'Set up and query',
|
|
668
|
+
code: [
|
|
669
|
+
`${toolName} context create local --endpoint http://localhost:5000/graphql`,
|
|
670
|
+
`${toolName} context use local`,
|
|
671
|
+
`${toolName} auth set-token <token>`,
|
|
672
|
+
`${toolName} ${tableKebabs[0] || 'model'} list`,
|
|
673
|
+
],
|
|
674
|
+
},
|
|
675
|
+
],
|
|
676
|
+
}, referenceNames),
|
|
677
|
+
});
|
|
645
678
|
return files;
|
|
646
679
|
}
|
|
647
680
|
function generateMultiTargetReadme(input) {
|
|
@@ -1268,22 +1301,26 @@ function getMultiTargetCliMcpTools(input) {
|
|
|
1268
1301
|
function generateMultiTargetSkills(input) {
|
|
1269
1302
|
const { toolName, builtinNames, targets } = input;
|
|
1270
1303
|
const files = [];
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
`${toolName} ${builtinNames.context} use <name>`,
|
|
1275
|
-
`${toolName} ${builtinNames.context} current`,
|
|
1276
|
-
`${toolName} ${builtinNames.context} delete <name>`,
|
|
1277
|
-
];
|
|
1304
|
+
// Generate one skill per target, plus a shared cli-common skill for context/auth
|
|
1305
|
+
const commonSkillName = 'cli-common';
|
|
1306
|
+
const commonReferenceNames = [];
|
|
1278
1307
|
const contextCreateFlags = targets
|
|
1279
1308
|
.map((t) => `--${t.name}-endpoint <url>`)
|
|
1280
1309
|
.join(' ');
|
|
1310
|
+
// Context reference
|
|
1311
|
+
commonReferenceNames.push('context');
|
|
1281
1312
|
files.push({
|
|
1282
|
-
fileName:
|
|
1283
|
-
content: (0, docs_utils_1.
|
|
1284
|
-
|
|
1313
|
+
fileName: `${commonSkillName}/references/context.md`,
|
|
1314
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
1315
|
+
title: 'Context Management',
|
|
1285
1316
|
description: `Manage API endpoint contexts for ${toolName} (multi-target: ${targets.map((t) => t.name).join(', ')})`,
|
|
1286
|
-
usage:
|
|
1317
|
+
usage: [
|
|
1318
|
+
`${toolName} ${builtinNames.context} create <name>`,
|
|
1319
|
+
`${toolName} ${builtinNames.context} list`,
|
|
1320
|
+
`${toolName} ${builtinNames.context} use <name>`,
|
|
1321
|
+
`${toolName} ${builtinNames.context} current`,
|
|
1322
|
+
`${toolName} ${builtinNames.context} delete <name>`,
|
|
1323
|
+
],
|
|
1287
1324
|
examples: [
|
|
1288
1325
|
{
|
|
1289
1326
|
description: 'Create a context for local development (accept all defaults)',
|
|
@@ -1299,20 +1336,15 @@ function generateMultiTargetSkills(input) {
|
|
|
1299
1336
|
`${toolName} ${builtinNames.context} use production`,
|
|
1300
1337
|
],
|
|
1301
1338
|
},
|
|
1302
|
-
{
|
|
1303
|
-
description: 'List and switch contexts',
|
|
1304
|
-
code: [
|
|
1305
|
-
`${toolName} ${builtinNames.context} list`,
|
|
1306
|
-
`${toolName} ${builtinNames.context} use staging`,
|
|
1307
|
-
],
|
|
1308
|
-
},
|
|
1309
1339
|
],
|
|
1310
1340
|
}),
|
|
1311
1341
|
});
|
|
1342
|
+
// Auth reference
|
|
1343
|
+
commonReferenceNames.push('auth');
|
|
1312
1344
|
files.push({
|
|
1313
|
-
fileName:
|
|
1314
|
-
content: (0, docs_utils_1.
|
|
1315
|
-
|
|
1345
|
+
fileName: `${commonSkillName}/references/auth.md`,
|
|
1346
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
1347
|
+
title: 'Authentication',
|
|
1316
1348
|
description: `Manage authentication tokens for ${toolName} (shared across all targets)`,
|
|
1317
1349
|
usage: [
|
|
1318
1350
|
`${toolName} ${builtinNames.auth} set-token <token>`,
|
|
@@ -1331,17 +1363,48 @@ function generateMultiTargetSkills(input) {
|
|
|
1331
1363
|
],
|
|
1332
1364
|
}),
|
|
1333
1365
|
});
|
|
1366
|
+
// Common SKILL.md
|
|
1367
|
+
files.push({
|
|
1368
|
+
fileName: `${commonSkillName}/SKILL.md`,
|
|
1369
|
+
content: (0, docs_utils_1.buildSkillFile)({
|
|
1370
|
+
name: commonSkillName,
|
|
1371
|
+
description: `Shared CLI utilities for ${toolName} — context management and authentication across targets: ${targets.map((t) => t.name).join(', ')}`,
|
|
1372
|
+
usage: [
|
|
1373
|
+
`# Context management`,
|
|
1374
|
+
`${toolName} ${builtinNames.context} create <name>`,
|
|
1375
|
+
`${toolName} ${builtinNames.context} use <name>`,
|
|
1376
|
+
'',
|
|
1377
|
+
`# Authentication`,
|
|
1378
|
+
`${toolName} ${builtinNames.auth} set-token <token>`,
|
|
1379
|
+
`${toolName} ${builtinNames.auth} status`,
|
|
1380
|
+
],
|
|
1381
|
+
examples: [
|
|
1382
|
+
{
|
|
1383
|
+
description: 'Set up and authenticate',
|
|
1384
|
+
code: [
|
|
1385
|
+
`${toolName} ${builtinNames.context} create local`,
|
|
1386
|
+
`${toolName} ${builtinNames.context} use local`,
|
|
1387
|
+
`${toolName} ${builtinNames.auth} set-token <token>`,
|
|
1388
|
+
],
|
|
1389
|
+
},
|
|
1390
|
+
],
|
|
1391
|
+
}, commonReferenceNames),
|
|
1392
|
+
});
|
|
1393
|
+
// Generate one skill per target with table/op references
|
|
1334
1394
|
for (const tgt of targets) {
|
|
1395
|
+
const tgtSkillName = `cli-${tgt.name}`;
|
|
1396
|
+
const tgtReferenceNames = [];
|
|
1335
1397
|
for (const table of tgt.tables) {
|
|
1336
1398
|
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
1337
1399
|
const kebab = (0, komoji_1.toKebabCase)(singularName);
|
|
1338
1400
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
1339
1401
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
1340
1402
|
const cmd = `${tgt.name}:${kebab}`;
|
|
1403
|
+
tgtReferenceNames.push(kebab);
|
|
1341
1404
|
files.push({
|
|
1342
|
-
fileName:
|
|
1343
|
-
content: (0, docs_utils_1.
|
|
1344
|
-
|
|
1405
|
+
fileName: `${tgtSkillName}/references/${kebab}.md`,
|
|
1406
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
1407
|
+
title: singularName,
|
|
1345
1408
|
description: `CRUD operations for ${table.name} records via ${toolName} CLI (${tgt.name} target)`,
|
|
1346
1409
|
usage: [
|
|
1347
1410
|
`${toolName} ${cmd} list`,
|
|
@@ -1361,10 +1424,6 @@ function generateMultiTargetSkills(input) {
|
|
|
1361
1424
|
`${toolName} ${cmd} create ${editableFields.map((f) => `--${f.name} "value"`).join(' ')}`,
|
|
1362
1425
|
],
|
|
1363
1426
|
},
|
|
1364
|
-
{
|
|
1365
|
-
description: `Get a ${singularName} by ${pk.name}`,
|
|
1366
|
-
code: [`${toolName} ${cmd} get --${pk.name} <value>`],
|
|
1367
|
-
},
|
|
1368
1427
|
],
|
|
1369
1428
|
}),
|
|
1370
1429
|
});
|
|
@@ -1379,10 +1438,11 @@ function generateMultiTargetSkills(input) {
|
|
|
1379
1438
|
if (tgt.isAuthTarget && op.kind === 'mutation') {
|
|
1380
1439
|
usageLines.push(`${baseUsage} --save-token`);
|
|
1381
1440
|
}
|
|
1441
|
+
tgtReferenceNames.push(kebab);
|
|
1382
1442
|
files.push({
|
|
1383
|
-
fileName:
|
|
1384
|
-
content: (0, docs_utils_1.
|
|
1385
|
-
|
|
1443
|
+
fileName: `${tgtSkillName}/references/${kebab}.md`,
|
|
1444
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
1445
|
+
title: op.name,
|
|
1386
1446
|
description: `${op.description || `Execute the ${op.name} ${op.kind}`} (${tgt.name} target)`,
|
|
1387
1447
|
usage: usageLines,
|
|
1388
1448
|
examples: [
|
|
@@ -1394,6 +1454,29 @@ function generateMultiTargetSkills(input) {
|
|
|
1394
1454
|
}),
|
|
1395
1455
|
});
|
|
1396
1456
|
}
|
|
1457
|
+
// Target SKILL.md
|
|
1458
|
+
const firstKebab = tgt.tables.length > 0
|
|
1459
|
+
? (0, komoji_1.toKebabCase)((0, utils_1.getTableNames)(tgt.tables[0]).singularName)
|
|
1460
|
+
: 'model';
|
|
1461
|
+
files.push({
|
|
1462
|
+
fileName: `${tgtSkillName}/SKILL.md`,
|
|
1463
|
+
content: (0, docs_utils_1.buildSkillFile)({
|
|
1464
|
+
name: tgtSkillName,
|
|
1465
|
+
description: `CLI commands for the ${tgt.name} API target — ${tgt.tables.length} tables and ${tgt.customOperations.length} custom operations via ${toolName}`,
|
|
1466
|
+
usage: [
|
|
1467
|
+
`# CRUD for ${tgt.name} tables (e.g. ${firstKebab})`,
|
|
1468
|
+
`${toolName} ${tgt.name}:${firstKebab} list`,
|
|
1469
|
+
`${toolName} ${tgt.name}:${firstKebab} get --id <value>`,
|
|
1470
|
+
`${toolName} ${tgt.name}:${firstKebab} create --<field> <value>`,
|
|
1471
|
+
],
|
|
1472
|
+
examples: [
|
|
1473
|
+
{
|
|
1474
|
+
description: `Query ${tgt.name} records`,
|
|
1475
|
+
code: [`${toolName} ${tgt.name}:${firstKebab} list`],
|
|
1476
|
+
},
|
|
1477
|
+
],
|
|
1478
|
+
}, tgtReferenceNames),
|
|
1479
|
+
});
|
|
1397
1480
|
}
|
|
1398
1481
|
return files;
|
|
1399
1482
|
}
|
|
@@ -20,6 +20,16 @@ export interface SkillDefinition {
|
|
|
20
20
|
}[];
|
|
21
21
|
language?: string;
|
|
22
22
|
}
|
|
23
|
+
export interface SkillReferenceDefinition {
|
|
24
|
+
title: string;
|
|
25
|
+
description: string;
|
|
26
|
+
usage: string[];
|
|
27
|
+
examples: {
|
|
28
|
+
description: string;
|
|
29
|
+
code: string[];
|
|
30
|
+
}[];
|
|
31
|
+
language?: string;
|
|
32
|
+
}
|
|
23
33
|
export declare function getReadmeHeader(title: string): string[];
|
|
24
34
|
export declare function getReadmeFooter(): string[];
|
|
25
35
|
export declare function resolveDocsConfig(docs: DocsConfig | boolean | undefined): DocsConfig;
|
|
@@ -27,4 +37,5 @@ export declare function formatArgType(arg: CleanOperation['args'][number]): stri
|
|
|
27
37
|
export declare function formatTypeRef(t: CleanOperation['args'][number]['type']): string;
|
|
28
38
|
export declare function getEditableFields(table: CleanTable): CleanField[];
|
|
29
39
|
export declare function gqlTypeToJsonSchemaType(gqlType: string): string;
|
|
30
|
-
export declare function buildSkillFile(skill: SkillDefinition): string;
|
|
40
|
+
export declare function buildSkillFile(skill: SkillDefinition, referenceNames?: string[]): string;
|
|
41
|
+
export declare function buildSkillReference(ref: SkillReferenceDefinition): string;
|
|
@@ -8,6 +8,7 @@ exports.formatTypeRef = formatTypeRef;
|
|
|
8
8
|
exports.getEditableFields = getEditableFields;
|
|
9
9
|
exports.gqlTypeToJsonSchemaType = gqlTypeToJsonSchemaType;
|
|
10
10
|
exports.buildSkillFile = buildSkillFile;
|
|
11
|
+
exports.buildSkillReference = buildSkillReference;
|
|
11
12
|
const utils_1 = require("./utils");
|
|
12
13
|
const CONSTRUCTIVE_LOGO_URL = 'https://raw.githubusercontent.com/constructive-io/constructive/refs/heads/main/assets/outline-logo.svg';
|
|
13
14
|
const CONSTRUCTIVE_REPO = 'https://github.com/constructive-io/constructive';
|
|
@@ -89,9 +90,15 @@ function gqlTypeToJsonSchemaType(gqlType) {
|
|
|
89
90
|
return 'string';
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
|
-
function buildSkillFile(skill) {
|
|
93
|
+
function buildSkillFile(skill, referenceNames) {
|
|
93
94
|
const lang = skill.language ?? 'bash';
|
|
94
95
|
const lines = [];
|
|
96
|
+
// YAML frontmatter (Agent Skills format)
|
|
97
|
+
lines.push('---');
|
|
98
|
+
lines.push(`name: ${skill.name}`);
|
|
99
|
+
lines.push(`description: ${skill.description}`);
|
|
100
|
+
lines.push('---');
|
|
101
|
+
lines.push('');
|
|
95
102
|
lines.push(`# ${skill.name}`);
|
|
96
103
|
lines.push('');
|
|
97
104
|
lines.push('<!-- @constructive-io/graphql-codegen - DO NOT EDIT -->');
|
|
@@ -118,5 +125,46 @@ function buildSkillFile(skill) {
|
|
|
118
125
|
lines.push('```');
|
|
119
126
|
lines.push('');
|
|
120
127
|
}
|
|
128
|
+
if (referenceNames && referenceNames.length > 0) {
|
|
129
|
+
lines.push('## References');
|
|
130
|
+
lines.push('');
|
|
131
|
+
lines.push('See the `references/` directory for detailed per-entity API documentation:');
|
|
132
|
+
lines.push('');
|
|
133
|
+
for (const name of referenceNames) {
|
|
134
|
+
lines.push(`- [${name}](references/${name}.md)`);
|
|
135
|
+
}
|
|
136
|
+
lines.push('');
|
|
137
|
+
}
|
|
138
|
+
return lines.join('\n');
|
|
139
|
+
}
|
|
140
|
+
function buildSkillReference(ref) {
|
|
141
|
+
const lang = ref.language ?? 'bash';
|
|
142
|
+
const lines = [];
|
|
143
|
+
lines.push(`# ${ref.title}`);
|
|
144
|
+
lines.push('');
|
|
145
|
+
lines.push('<!-- @constructive-io/graphql-codegen - DO NOT EDIT -->');
|
|
146
|
+
lines.push('');
|
|
147
|
+
lines.push(ref.description);
|
|
148
|
+
lines.push('');
|
|
149
|
+
lines.push('## Usage');
|
|
150
|
+
lines.push('');
|
|
151
|
+
lines.push(`\`\`\`${lang}`);
|
|
152
|
+
for (const u of ref.usage) {
|
|
153
|
+
lines.push(u);
|
|
154
|
+
}
|
|
155
|
+
lines.push('```');
|
|
156
|
+
lines.push('');
|
|
157
|
+
lines.push('## Examples');
|
|
158
|
+
lines.push('');
|
|
159
|
+
for (const ex of ref.examples) {
|
|
160
|
+
lines.push(`### ${ex.description}`);
|
|
161
|
+
lines.push('');
|
|
162
|
+
lines.push(`\`\`\`${lang}`);
|
|
163
|
+
for (const cmd of ex.code) {
|
|
164
|
+
lines.push(cmd);
|
|
165
|
+
}
|
|
166
|
+
lines.push('```');
|
|
167
|
+
lines.push('');
|
|
168
|
+
}
|
|
121
169
|
return lines.join('\n');
|
|
122
170
|
}
|
|
@@ -3,4 +3,4 @@ import type { GeneratedDocFile, McpTool } from './docs-utils';
|
|
|
3
3
|
export declare function generateHooksReadme(tables: CleanTable[], customOperations: CleanOperation[]): GeneratedDocFile;
|
|
4
4
|
export declare function generateHooksAgentsDocs(tables: CleanTable[], customOperations: CleanOperation[]): GeneratedDocFile;
|
|
5
5
|
export declare function getHooksMcpTools(tables: CleanTable[], customOperations: CleanOperation[]): McpTool[];
|
|
6
|
-
export declare function generateHooksSkills(tables: CleanTable[], customOperations: CleanOperation[]): GeneratedDocFile[];
|
|
6
|
+
export declare function generateHooksSkills(tables: CleanTable[], customOperations: CleanOperation[], targetName: string): GeneratedDocFile[];
|
|
@@ -4,6 +4,7 @@ exports.generateHooksReadme = generateHooksReadme;
|
|
|
4
4
|
exports.generateHooksAgentsDocs = generateHooksAgentsDocs;
|
|
5
5
|
exports.getHooksMcpTools = getHooksMcpTools;
|
|
6
6
|
exports.generateHooksSkills = generateHooksSkills;
|
|
7
|
+
const komoji_1 = require("komoji");
|
|
7
8
|
const docs_utils_1 = require("./docs-utils");
|
|
8
9
|
const utils_1 = require("./utils");
|
|
9
10
|
function getCustomHookName(op) {
|
|
@@ -377,8 +378,11 @@ function getHooksMcpTools(tables, customOperations) {
|
|
|
377
378
|
}
|
|
378
379
|
return tools;
|
|
379
380
|
}
|
|
380
|
-
function generateHooksSkills(tables, customOperations) {
|
|
381
|
+
function generateHooksSkills(tables, customOperations, targetName) {
|
|
381
382
|
const files = [];
|
|
383
|
+
const skillName = `hooks-${targetName}`;
|
|
384
|
+
const referenceNames = [];
|
|
385
|
+
// Generate reference files for each table
|
|
382
386
|
for (const table of tables) {
|
|
383
387
|
const { singularName, pluralName } = (0, utils_1.getTableNames)(table);
|
|
384
388
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
@@ -386,10 +390,12 @@ function generateHooksSkills(tables, customOperations) {
|
|
|
386
390
|
const selectFields = scalarFields
|
|
387
391
|
.map((f) => `${f.name}: true`)
|
|
388
392
|
.join(', ');
|
|
393
|
+
const refName = (0, komoji_1.toKebabCase)(singularName);
|
|
394
|
+
referenceNames.push(refName);
|
|
389
395
|
files.push({
|
|
390
|
-
fileName:
|
|
391
|
-
content: (0, docs_utils_1.
|
|
392
|
-
|
|
396
|
+
fileName: `${skillName}/references/${refName}.md`,
|
|
397
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
398
|
+
title: singularName,
|
|
393
399
|
description: table.description || `React Query hooks for ${table.name} data operations`,
|
|
394
400
|
language: 'typescript',
|
|
395
401
|
usage: [
|
|
@@ -429,15 +435,18 @@ function generateHooksSkills(tables, customOperations) {
|
|
|
429
435
|
}),
|
|
430
436
|
});
|
|
431
437
|
}
|
|
438
|
+
// Generate reference files for custom operations
|
|
432
439
|
for (const op of customOperations) {
|
|
433
440
|
const hookName = getCustomHookName(op);
|
|
434
441
|
const callArgs = op.args.length > 0
|
|
435
442
|
? `{ ${op.args.map((a) => `${a.name}: '<value>'`).join(', ')} }`
|
|
436
443
|
: '';
|
|
444
|
+
const refName = (0, komoji_1.toKebabCase)(op.name);
|
|
445
|
+
referenceNames.push(refName);
|
|
437
446
|
files.push({
|
|
438
|
-
fileName:
|
|
439
|
-
content: (0, docs_utils_1.
|
|
440
|
-
|
|
447
|
+
fileName: `${skillName}/references/${refName}.md`,
|
|
448
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
449
|
+
title: op.name,
|
|
441
450
|
description: op.description ||
|
|
442
451
|
`React Query ${op.kind} hook for ${op.name}`,
|
|
443
452
|
language: 'typescript',
|
|
@@ -464,5 +473,36 @@ function generateHooksSkills(tables, customOperations) {
|
|
|
464
473
|
}),
|
|
465
474
|
});
|
|
466
475
|
}
|
|
476
|
+
// Generate the overview SKILL.md
|
|
477
|
+
const hookExamples = tables.slice(0, 3).map((t) => (0, utils_1.getListQueryHookName)(t));
|
|
478
|
+
files.push({
|
|
479
|
+
fileName: `${skillName}/SKILL.md`,
|
|
480
|
+
content: (0, docs_utils_1.buildSkillFile)({
|
|
481
|
+
name: skillName,
|
|
482
|
+
description: `React Query hooks for the ${targetName} API — provides typed query and mutation hooks for ${tables.length} tables and ${customOperations.length} custom operations`,
|
|
483
|
+
language: 'typescript',
|
|
484
|
+
usage: [
|
|
485
|
+
`// Import hooks`,
|
|
486
|
+
`import { ${hookExamples[0] || 'useModelQuery'} } from './hooks';`,
|
|
487
|
+
'',
|
|
488
|
+
`// Query hooks: use<Model>Query, use<Model>sQuery`,
|
|
489
|
+
`// Mutation hooks: useCreate<Model>Mutation, useUpdate<Model>Mutation, useDelete<Model>Mutation`,
|
|
490
|
+
'',
|
|
491
|
+
`const { data, isLoading } = ${hookExamples[0] || 'useModelQuery'}({`,
|
|
492
|
+
` selection: { fields: { id: true } },`,
|
|
493
|
+
`});`,
|
|
494
|
+
],
|
|
495
|
+
examples: [
|
|
496
|
+
{
|
|
497
|
+
description: 'Query records',
|
|
498
|
+
code: [
|
|
499
|
+
`const { data, isLoading } = ${hookExamples[0] || 'useModelQuery'}({`,
|
|
500
|
+
' selection: { fields: { id: true } },',
|
|
501
|
+
'});',
|
|
502
|
+
],
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
}, referenceNames),
|
|
506
|
+
});
|
|
467
507
|
return files;
|
|
468
508
|
}
|
|
@@ -3,4 +3,4 @@ import type { GeneratedDocFile, McpTool } from '../docs-utils';
|
|
|
3
3
|
export declare function generateOrmReadme(tables: CleanTable[], customOperations: CleanOperation[]): GeneratedDocFile;
|
|
4
4
|
export declare function generateOrmAgentsDocs(tables: CleanTable[], customOperations: CleanOperation[]): GeneratedDocFile;
|
|
5
5
|
export declare function getOrmMcpTools(tables: CleanTable[], customOperations: CleanOperation[]): McpTool[];
|
|
6
|
-
export declare function generateOrmSkills(tables: CleanTable[], customOperations: CleanOperation[]): GeneratedDocFile[];
|
|
6
|
+
export declare function generateOrmSkills(tables: CleanTable[], customOperations: CleanOperation[], targetName: string): GeneratedDocFile[];
|
|
@@ -4,6 +4,7 @@ exports.generateOrmReadme = generateOrmReadme;
|
|
|
4
4
|
exports.generateOrmAgentsDocs = generateOrmAgentsDocs;
|
|
5
5
|
exports.getOrmMcpTools = getOrmMcpTools;
|
|
6
6
|
exports.generateOrmSkills = generateOrmSkills;
|
|
7
|
+
const komoji_1 = require("komoji");
|
|
7
8
|
const docs_utils_1 = require("../docs-utils");
|
|
8
9
|
const utils_1 = require("../utils");
|
|
9
10
|
function generateOrmReadme(tables, customOperations) {
|
|
@@ -346,30 +347,36 @@ function getOrmMcpTools(tables, customOperations) {
|
|
|
346
347
|
}
|
|
347
348
|
return tools;
|
|
348
349
|
}
|
|
349
|
-
function generateOrmSkills(tables, customOperations) {
|
|
350
|
+
function generateOrmSkills(tables, customOperations, targetName) {
|
|
350
351
|
const files = [];
|
|
352
|
+
const skillName = `orm-${targetName}`;
|
|
353
|
+
const referenceNames = [];
|
|
354
|
+
// Generate reference files for each table
|
|
351
355
|
for (const table of tables) {
|
|
352
356
|
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
353
357
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
354
358
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
359
|
+
const modelName = (0, utils_1.lcFirst)(singularName);
|
|
360
|
+
const refName = (0, komoji_1.toKebabCase)(singularName);
|
|
361
|
+
referenceNames.push(refName);
|
|
355
362
|
files.push({
|
|
356
|
-
fileName:
|
|
357
|
-
content: (0, docs_utils_1.
|
|
358
|
-
|
|
363
|
+
fileName: `${skillName}/references/${refName}.md`,
|
|
364
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
365
|
+
title: singularName,
|
|
359
366
|
description: table.description || `ORM operations for ${table.name} records`,
|
|
360
367
|
language: 'typescript',
|
|
361
368
|
usage: [
|
|
362
|
-
`db.${
|
|
363
|
-
`db.${
|
|
364
|
-
`db.${
|
|
365
|
-
`db.${
|
|
366
|
-
`db.${
|
|
369
|
+
`db.${modelName}.findMany({ select: { id: true } }).execute()`,
|
|
370
|
+
`db.${modelName}.findOne({ ${pk.name}: '<value>', select: { id: true } }).execute()`,
|
|
371
|
+
`db.${modelName}.create({ data: { ${editableFields.map((f) => `${f.name}: '<value>'`).join(', ')} }, select: { id: true } }).execute()`,
|
|
372
|
+
`db.${modelName}.update({ where: { ${pk.name}: '<value>' }, data: { ${editableFields[0]?.name || 'field'}: '<new>' }, select: { id: true } }).execute()`,
|
|
373
|
+
`db.${modelName}.delete({ where: { ${pk.name}: '<value>' } }).execute()`,
|
|
367
374
|
],
|
|
368
375
|
examples: [
|
|
369
376
|
{
|
|
370
377
|
description: `List all ${singularName} records`,
|
|
371
378
|
code: [
|
|
372
|
-
`const items = await db.${
|
|
379
|
+
`const items = await db.${modelName}.findMany({`,
|
|
373
380
|
` select: { ${pk.name}: true, ${editableFields[0]?.name || 'name'}: true }`,
|
|
374
381
|
'}).execute();',
|
|
375
382
|
],
|
|
@@ -377,7 +384,7 @@ function generateOrmSkills(tables, customOperations) {
|
|
|
377
384
|
{
|
|
378
385
|
description: `Create a ${singularName}`,
|
|
379
386
|
code: [
|
|
380
|
-
`const item = await db.${
|
|
387
|
+
`const item = await db.${modelName}.create({`,
|
|
381
388
|
` data: { ${editableFields.map((f) => `${f.name}: 'value'`).join(', ')} },`,
|
|
382
389
|
` select: { ${pk.name}: true }`,
|
|
383
390
|
'}).execute();',
|
|
@@ -387,30 +394,60 @@ function generateOrmSkills(tables, customOperations) {
|
|
|
387
394
|
}),
|
|
388
395
|
});
|
|
389
396
|
}
|
|
397
|
+
// Generate reference files for custom operations
|
|
390
398
|
for (const op of customOperations) {
|
|
391
399
|
const accessor = op.kind === 'query' ? 'query' : 'mutation';
|
|
392
400
|
const callArgs = op.args.length > 0
|
|
393
401
|
? `{ ${op.args.map((a) => `${a.name}: '<value>'`).join(', ')} }`
|
|
394
402
|
: '';
|
|
403
|
+
const refName = (0, komoji_1.toKebabCase)(op.name);
|
|
404
|
+
referenceNames.push(refName);
|
|
395
405
|
files.push({
|
|
396
|
-
fileName:
|
|
397
|
-
content: (0, docs_utils_1.
|
|
398
|
-
|
|
406
|
+
fileName: `${skillName}/references/${refName}.md`,
|
|
407
|
+
content: (0, docs_utils_1.buildSkillReference)({
|
|
408
|
+
title: op.name,
|
|
399
409
|
description: op.description || `Execute the ${op.name} ${op.kind}`,
|
|
400
410
|
language: 'typescript',
|
|
401
|
-
usage: [
|
|
402
|
-
`db.${accessor}.${op.name}(${callArgs}).execute()`,
|
|
403
|
-
],
|
|
411
|
+
usage: [`db.${accessor}.${op.name}(${callArgs}).execute()`],
|
|
404
412
|
examples: [
|
|
405
413
|
{
|
|
406
414
|
description: `Run ${op.name}`,
|
|
407
|
-
code: [
|
|
408
|
-
`const result = await db.${accessor}.${op.name}(${callArgs}).execute();`,
|
|
409
|
-
],
|
|
415
|
+
code: [`const result = await db.${accessor}.${op.name}(${callArgs}).execute();`],
|
|
410
416
|
},
|
|
411
417
|
],
|
|
412
418
|
}),
|
|
413
419
|
});
|
|
414
420
|
}
|
|
421
|
+
// Generate the overview SKILL.md
|
|
422
|
+
const tableNames = tables.map((t) => (0, utils_1.lcFirst)((0, utils_1.getTableNames)(t).singularName));
|
|
423
|
+
files.push({
|
|
424
|
+
fileName: `${skillName}/SKILL.md`,
|
|
425
|
+
content: (0, docs_utils_1.buildSkillFile)({
|
|
426
|
+
name: skillName,
|
|
427
|
+
description: `ORM client for the ${targetName} API — provides typed CRUD operations for ${tables.length} tables and ${customOperations.length} custom operations`,
|
|
428
|
+
language: 'typescript',
|
|
429
|
+
usage: [
|
|
430
|
+
`// Import the ORM client`,
|
|
431
|
+
`import { db } from './orm';`,
|
|
432
|
+
'',
|
|
433
|
+
`// Available models: ${tableNames.slice(0, 8).join(', ')}${tableNames.length > 8 ? ', ...' : ''}`,
|
|
434
|
+
`db.<model>.findMany({ select: { id: true } }).execute()`,
|
|
435
|
+
`db.<model>.findOne({ id: '<value>', select: { id: true } }).execute()`,
|
|
436
|
+
`db.<model>.create({ data: { ... }, select: { id: true } }).execute()`,
|
|
437
|
+
`db.<model>.update({ where: { id: '<value>' }, data: { ... }, select: { id: true } }).execute()`,
|
|
438
|
+
`db.<model>.delete({ where: { id: '<value>' } }).execute()`,
|
|
439
|
+
],
|
|
440
|
+
examples: [
|
|
441
|
+
{
|
|
442
|
+
description: 'Query records',
|
|
443
|
+
code: [
|
|
444
|
+
`const items = await db.${tableNames[0] || 'model'}.findMany({`,
|
|
445
|
+
' select: { id: true }',
|
|
446
|
+
'}).execute();',
|
|
447
|
+
],
|
|
448
|
+
},
|
|
449
|
+
],
|
|
450
|
+
}, referenceNames),
|
|
451
|
+
});
|
|
415
452
|
return files;
|
|
416
453
|
}
|
package/core/generate.d.ts
CHANGED
|
@@ -33,6 +33,11 @@ export interface GenerateResult {
|
|
|
33
33
|
*/
|
|
34
34
|
export interface GenerateInternalOptions {
|
|
35
35
|
skipCli?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Internal-only name for the target when generating skills.
|
|
38
|
+
* Used by generateMulti() so skill names are stable and composable.
|
|
39
|
+
*/
|
|
40
|
+
targetName?: string;
|
|
36
41
|
}
|
|
37
42
|
export declare function generate(options?: GenerateOptions, internalOptions?: GenerateInternalOptions): Promise<GenerateResult>;
|
|
38
43
|
export declare function expandApiNamesToMultiTarget(config: GraphQLSDKConfigTarget): Record<string, GraphQLSDKConfigTarget> | null;
|