@constructive-io/graphql-codegen 4.7.3 → 4.8.1
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/command-map-generator.js +36 -11
- package/core/codegen/cli/custom-command-generator.js +59 -13
- package/core/codegen/cli/docs-generator.d.ts +1 -1
- package/core/codegen/cli/docs-generator.js +137 -54
- package/core/codegen/cli/executor-generator.js +20 -6
- package/core/codegen/cli/infra-generator.js +17 -14
- package/core/codegen/cli/table-command-generator.js +209 -53
- 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/command-map-generator.js +36 -11
- package/esm/core/codegen/cli/custom-command-generator.js +60 -14
- 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/cli/executor-generator.js +20 -6
- package/esm/core/codegen/cli/infra-generator.js +17 -14
- package/esm/core/codegen/cli/table-command-generator.js +210 -54
- 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
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { toKebabCase } from 'komoji';
|
|
2
|
+
import { buildSkillFile, buildSkillReference, formatArgType, getEditableFields, getReadmeHeader, getReadmeFooter, gqlTypeToJsonSchemaType, } from '../docs-utils';
|
|
2
3
|
import { getScalarFields, getTableNames, getPrimaryKeyInfo, lcFirst, fieldTypeToTs, } from '../utils';
|
|
3
4
|
export function generateOrmReadme(tables, customOperations) {
|
|
4
5
|
const lines = [];
|
|
@@ -340,30 +341,36 @@ export function getOrmMcpTools(tables, customOperations) {
|
|
|
340
341
|
}
|
|
341
342
|
return tools;
|
|
342
343
|
}
|
|
343
|
-
export function generateOrmSkills(tables, customOperations) {
|
|
344
|
+
export function generateOrmSkills(tables, customOperations, targetName) {
|
|
344
345
|
const files = [];
|
|
346
|
+
const skillName = `orm-${targetName}`;
|
|
347
|
+
const referenceNames = [];
|
|
348
|
+
// Generate reference files for each table
|
|
345
349
|
for (const table of tables) {
|
|
346
350
|
const { singularName } = getTableNames(table);
|
|
347
351
|
const pk = getPrimaryKeyInfo(table)[0];
|
|
348
352
|
const editableFields = getEditableFields(table);
|
|
353
|
+
const modelName = lcFirst(singularName);
|
|
354
|
+
const refName = toKebabCase(singularName);
|
|
355
|
+
referenceNames.push(refName);
|
|
349
356
|
files.push({
|
|
350
|
-
fileName:
|
|
351
|
-
content:
|
|
352
|
-
|
|
357
|
+
fileName: `${skillName}/references/${refName}.md`,
|
|
358
|
+
content: buildSkillReference({
|
|
359
|
+
title: singularName,
|
|
353
360
|
description: table.description || `ORM operations for ${table.name} records`,
|
|
354
361
|
language: 'typescript',
|
|
355
362
|
usage: [
|
|
356
|
-
`db.${
|
|
357
|
-
`db.${
|
|
358
|
-
`db.${
|
|
359
|
-
`db.${
|
|
360
|
-
`db.${
|
|
363
|
+
`db.${modelName}.findMany({ select: { id: true } }).execute()`,
|
|
364
|
+
`db.${modelName}.findOne({ ${pk.name}: '<value>', select: { id: true } }).execute()`,
|
|
365
|
+
`db.${modelName}.create({ data: { ${editableFields.map((f) => `${f.name}: '<value>'`).join(', ')} }, select: { id: true } }).execute()`,
|
|
366
|
+
`db.${modelName}.update({ where: { ${pk.name}: '<value>' }, data: { ${editableFields[0]?.name || 'field'}: '<new>' }, select: { id: true } }).execute()`,
|
|
367
|
+
`db.${modelName}.delete({ where: { ${pk.name}: '<value>' } }).execute()`,
|
|
361
368
|
],
|
|
362
369
|
examples: [
|
|
363
370
|
{
|
|
364
371
|
description: `List all ${singularName} records`,
|
|
365
372
|
code: [
|
|
366
|
-
`const items = await db.${
|
|
373
|
+
`const items = await db.${modelName}.findMany({`,
|
|
367
374
|
` select: { ${pk.name}: true, ${editableFields[0]?.name || 'name'}: true }`,
|
|
368
375
|
'}).execute();',
|
|
369
376
|
],
|
|
@@ -371,7 +378,7 @@ export function generateOrmSkills(tables, customOperations) {
|
|
|
371
378
|
{
|
|
372
379
|
description: `Create a ${singularName}`,
|
|
373
380
|
code: [
|
|
374
|
-
`const item = await db.${
|
|
381
|
+
`const item = await db.${modelName}.create({`,
|
|
375
382
|
` data: { ${editableFields.map((f) => `${f.name}: 'value'`).join(', ')} },`,
|
|
376
383
|
` select: { ${pk.name}: true }`,
|
|
377
384
|
'}).execute();',
|
|
@@ -381,30 +388,60 @@ export function generateOrmSkills(tables, customOperations) {
|
|
|
381
388
|
}),
|
|
382
389
|
});
|
|
383
390
|
}
|
|
391
|
+
// Generate reference files for custom operations
|
|
384
392
|
for (const op of customOperations) {
|
|
385
393
|
const accessor = op.kind === 'query' ? 'query' : 'mutation';
|
|
386
394
|
const callArgs = op.args.length > 0
|
|
387
395
|
? `{ ${op.args.map((a) => `${a.name}: '<value>'`).join(', ')} }`
|
|
388
396
|
: '';
|
|
397
|
+
const refName = toKebabCase(op.name);
|
|
398
|
+
referenceNames.push(refName);
|
|
389
399
|
files.push({
|
|
390
|
-
fileName:
|
|
391
|
-
content:
|
|
392
|
-
|
|
400
|
+
fileName: `${skillName}/references/${refName}.md`,
|
|
401
|
+
content: buildSkillReference({
|
|
402
|
+
title: op.name,
|
|
393
403
|
description: op.description || `Execute the ${op.name} ${op.kind}`,
|
|
394
404
|
language: 'typescript',
|
|
395
|
-
usage: [
|
|
396
|
-
`db.${accessor}.${op.name}(${callArgs}).execute()`,
|
|
397
|
-
],
|
|
405
|
+
usage: [`db.${accessor}.${op.name}(${callArgs}).execute()`],
|
|
398
406
|
examples: [
|
|
399
407
|
{
|
|
400
408
|
description: `Run ${op.name}`,
|
|
401
|
-
code: [
|
|
402
|
-
`const result = await db.${accessor}.${op.name}(${callArgs}).execute();`,
|
|
403
|
-
],
|
|
409
|
+
code: [`const result = await db.${accessor}.${op.name}(${callArgs}).execute();`],
|
|
404
410
|
},
|
|
405
411
|
],
|
|
406
412
|
}),
|
|
407
413
|
});
|
|
408
414
|
}
|
|
415
|
+
// Generate the overview SKILL.md
|
|
416
|
+
const tableNames = tables.map((t) => lcFirst(getTableNames(t).singularName));
|
|
417
|
+
files.push({
|
|
418
|
+
fileName: `${skillName}/SKILL.md`,
|
|
419
|
+
content: buildSkillFile({
|
|
420
|
+
name: skillName,
|
|
421
|
+
description: `ORM client for the ${targetName} API — provides typed CRUD operations for ${tables.length} tables and ${customOperations.length} custom operations`,
|
|
422
|
+
language: 'typescript',
|
|
423
|
+
usage: [
|
|
424
|
+
`// Import the ORM client`,
|
|
425
|
+
`import { db } from './orm';`,
|
|
426
|
+
'',
|
|
427
|
+
`// Available models: ${tableNames.slice(0, 8).join(', ')}${tableNames.length > 8 ? ', ...' : ''}`,
|
|
428
|
+
`db.<model>.findMany({ select: { id: true } }).execute()`,
|
|
429
|
+
`db.<model>.findOne({ id: '<value>', select: { id: true } }).execute()`,
|
|
430
|
+
`db.<model>.create({ data: { ... }, select: { id: true } }).execute()`,
|
|
431
|
+
`db.<model>.update({ where: { id: '<value>' }, data: { ... }, select: { id: true } }).execute()`,
|
|
432
|
+
`db.<model>.delete({ where: { id: '<value>' } }).execute()`,
|
|
433
|
+
],
|
|
434
|
+
examples: [
|
|
435
|
+
{
|
|
436
|
+
description: 'Query records',
|
|
437
|
+
code: [
|
|
438
|
+
`const items = await db.${tableNames[0] || 'model'}.findMany({`,
|
|
439
|
+
' select: { id: true }',
|
|
440
|
+
'}).execute();',
|
|
441
|
+
],
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
}, referenceNames),
|
|
445
|
+
});
|
|
409
446
|
return files;
|
|
410
447
|
}
|
package/esm/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;
|
package/esm/core/generate.js
CHANGED
|
@@ -24,6 +24,18 @@ import { generateTargetReadme, generateCombinedMcpConfig, generateRootRootReadme
|
|
|
24
24
|
import { createSchemaSource, validateSourceOptions } from './introspect';
|
|
25
25
|
import { writeGeneratedFiles } from './output';
|
|
26
26
|
import { runCodegenPipeline, validateTablesFound } from './pipeline';
|
|
27
|
+
import { findWorkspaceRoot } from './workspace';
|
|
28
|
+
function resolveSkillsOutputDir(config, outputRoot) {
|
|
29
|
+
const workspaceRoot = findWorkspaceRoot(path.resolve(outputRoot)) ??
|
|
30
|
+
findWorkspaceRoot(process.cwd()) ??
|
|
31
|
+
process.cwd();
|
|
32
|
+
if (config.skillsPath) {
|
|
33
|
+
return path.isAbsolute(config.skillsPath)
|
|
34
|
+
? config.skillsPath
|
|
35
|
+
: path.resolve(workspaceRoot, config.skillsPath);
|
|
36
|
+
}
|
|
37
|
+
return path.resolve(workspaceRoot, 'skills');
|
|
38
|
+
}
|
|
27
39
|
export async function generate(options = {}, internalOptions) {
|
|
28
40
|
// Apply defaults to get resolved config
|
|
29
41
|
const config = getConfigOptions(options);
|
|
@@ -219,6 +231,8 @@ export async function generate(options = {}, internalOptions) {
|
|
|
219
231
|
...(customOperations.mutations ?? []),
|
|
220
232
|
];
|
|
221
233
|
const allMcpTools = [];
|
|
234
|
+
const targetName = internalOptions?.targetName ?? 'default';
|
|
235
|
+
const skillsToWrite = [];
|
|
222
236
|
if (runOrm) {
|
|
223
237
|
if (docsConfig.readme) {
|
|
224
238
|
const readme = generateOrmReadme(tables, allCustomOps);
|
|
@@ -232,8 +246,8 @@ export async function generate(options = {}, internalOptions) {
|
|
|
232
246
|
allMcpTools.push(...getOrmMcpTools(tables, allCustomOps));
|
|
233
247
|
}
|
|
234
248
|
if (docsConfig.skills) {
|
|
235
|
-
for (const skill of generateOrmSkills(tables, allCustomOps)) {
|
|
236
|
-
|
|
249
|
+
for (const skill of generateOrmSkills(tables, allCustomOps, targetName)) {
|
|
250
|
+
skillsToWrite.push({ path: skill.fileName, content: skill.content });
|
|
237
251
|
}
|
|
238
252
|
}
|
|
239
253
|
}
|
|
@@ -250,8 +264,8 @@ export async function generate(options = {}, internalOptions) {
|
|
|
250
264
|
allMcpTools.push(...getHooksMcpTools(tables, allCustomOps));
|
|
251
265
|
}
|
|
252
266
|
if (docsConfig.skills) {
|
|
253
|
-
for (const skill of generateHooksSkills(tables, allCustomOps)) {
|
|
254
|
-
|
|
267
|
+
for (const skill of generateHooksSkills(tables, allCustomOps, targetName)) {
|
|
268
|
+
skillsToWrite.push({ path: skill.fileName, content: skill.content });
|
|
255
269
|
}
|
|
256
270
|
}
|
|
257
271
|
}
|
|
@@ -271,8 +285,8 @@ export async function generate(options = {}, internalOptions) {
|
|
|
271
285
|
allMcpTools.push(...getCliMcpTools(tables, allCustomOps, toolName));
|
|
272
286
|
}
|
|
273
287
|
if (docsConfig.skills) {
|
|
274
|
-
for (const skill of generateCliSkills(tables, allCustomOps, toolName)) {
|
|
275
|
-
|
|
288
|
+
for (const skill of generateCliSkills(tables, allCustomOps, toolName, targetName)) {
|
|
289
|
+
skillsToWrite.push({ path: skill.fileName, content: skill.content });
|
|
276
290
|
}
|
|
277
291
|
}
|
|
278
292
|
}
|
|
@@ -310,6 +324,21 @@ export async function generate(options = {}, internalOptions) {
|
|
|
310
324
|
};
|
|
311
325
|
}
|
|
312
326
|
allFilesWritten.push(...(writeResult.filesWritten ?? []));
|
|
327
|
+
if (skillsToWrite.length > 0) {
|
|
328
|
+
const skillsOutputDir = resolveSkillsOutputDir(config, outputRoot);
|
|
329
|
+
const skillsWriteResult = await writeGeneratedFiles(skillsToWrite, skillsOutputDir, [], {
|
|
330
|
+
pruneStaleFiles: false,
|
|
331
|
+
});
|
|
332
|
+
if (!skillsWriteResult.success) {
|
|
333
|
+
return {
|
|
334
|
+
success: false,
|
|
335
|
+
message: `Failed to write generated skill files: ${skillsWriteResult.errors?.join(', ')}`,
|
|
336
|
+
output: skillsOutputDir,
|
|
337
|
+
errors: skillsWriteResult.errors,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
allFilesWritten.push(...(skillsWriteResult.filesWritten ?? []));
|
|
341
|
+
}
|
|
313
342
|
}
|
|
314
343
|
const generators = [
|
|
315
344
|
runReactQuery && 'React Query',
|
|
@@ -488,7 +517,7 @@ export async function generateMulti(options) {
|
|
|
488
517
|
dryRun,
|
|
489
518
|
schemaOnly,
|
|
490
519
|
schemaOnlyFilename: schemaOnly ? `${name}.graphql` : undefined,
|
|
491
|
-
}, useUnifiedCli ? { skipCli: true } :
|
|
520
|
+
}, useUnifiedCli ? { skipCli: true, targetName: name } : { targetName: name });
|
|
492
521
|
results.push({ name, result });
|
|
493
522
|
if (!result.success) {
|
|
494
523
|
hasError = true;
|
|
@@ -571,17 +600,24 @@ export async function generateMulti(options) {
|
|
|
571
600
|
if (docsConfig.mcp) {
|
|
572
601
|
allMcpTools.push(...getMultiTargetCliMcpTools(docsInput));
|
|
573
602
|
}
|
|
574
|
-
if (docsConfig.skills) {
|
|
575
|
-
for (const skill of generateMultiTargetSkills(docsInput)) {
|
|
576
|
-
cliFilesToWrite.push({ path: path.posix.join('cli', skill.fileName), content: skill.content });
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
603
|
if (docsConfig.mcp && allMcpTools.length > 0) {
|
|
580
604
|
const mcpFile = generateCombinedMcpConfig(allMcpTools, toolName);
|
|
581
605
|
cliFilesToWrite.push({ path: path.posix.join('cli', mcpFile.fileName), content: mcpFile.content });
|
|
582
606
|
}
|
|
583
607
|
const { writeGeneratedFiles: writeFiles } = await import('./output');
|
|
584
608
|
await writeFiles(cliFilesToWrite, '.', [], { pruneStaleFiles: false });
|
|
609
|
+
if (docsConfig.skills) {
|
|
610
|
+
const cliSkillsToWrite = generateMultiTargetSkills(docsInput).map((skill) => ({
|
|
611
|
+
path: skill.fileName,
|
|
612
|
+
content: skill.content,
|
|
613
|
+
}));
|
|
614
|
+
const firstTargetResolved = getConfigOptions({
|
|
615
|
+
...(firstTargetConfig ?? {}),
|
|
616
|
+
...(cliOverrides ?? {}),
|
|
617
|
+
});
|
|
618
|
+
const skillsOutputDir = resolveSkillsOutputDir(firstTargetResolved, firstTargetResolved.output);
|
|
619
|
+
await writeFiles(cliSkillsToWrite, skillsOutputDir, [], { pruneStaleFiles: false });
|
|
620
|
+
}
|
|
585
621
|
}
|
|
586
622
|
// Generate root-root README if multi-target
|
|
587
623
|
if (names.length > 1 && targetInfos.length > 0 && !dryRun) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the workspace root directory.
|
|
3
|
+
*
|
|
4
|
+
* Search order:
|
|
5
|
+
* 1. pnpm-workspace.yaml (pnpm workspaces)
|
|
6
|
+
* 2. lerna.json (lerna workspaces)
|
|
7
|
+
* 3. package.json with "workspaces" field (npm/yarn workspaces)
|
|
8
|
+
* 4. Nearest package.json (fallback for non-workspace projects)
|
|
9
|
+
*
|
|
10
|
+
* @param cwd - Starting directory to search from (defaults to process.cwd())
|
|
11
|
+
* @returns The workspace root path, or null if nothing found
|
|
12
|
+
*/
|
|
13
|
+
export declare function findWorkspaceRoot(cwd?: string): string | null;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace detection utilities
|
|
3
|
+
*
|
|
4
|
+
* Finds the root of a workspace by walking up directories looking for
|
|
5
|
+
* workspace markers (pnpm-workspace.yaml, lerna.json, package.json with workspaces).
|
|
6
|
+
* Falls back to the nearest package.json directory.
|
|
7
|
+
*
|
|
8
|
+
* Inspired by @pgpmjs/env walkUp / resolvePnpmWorkspace patterns.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
11
|
+
import { dirname, resolve, parse as parsePath } from 'node:path';
|
|
12
|
+
/**
|
|
13
|
+
* Walk up directories from startDir looking for a file.
|
|
14
|
+
* Returns the directory containing the file, or null if not found.
|
|
15
|
+
*/
|
|
16
|
+
function walkUp(startDir, filename) {
|
|
17
|
+
let currentDir = resolve(startDir);
|
|
18
|
+
while (currentDir) {
|
|
19
|
+
const targetPath = resolve(currentDir, filename);
|
|
20
|
+
if (existsSync(targetPath)) {
|
|
21
|
+
return currentDir;
|
|
22
|
+
}
|
|
23
|
+
const parentDir = dirname(currentDir);
|
|
24
|
+
if (parentDir === currentDir) {
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
currentDir = parentDir;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Find the first pnpm workspace root by looking for pnpm-workspace.yaml
|
|
33
|
+
*/
|
|
34
|
+
function findPnpmWorkspace(cwd) {
|
|
35
|
+
return walkUp(cwd, 'pnpm-workspace.yaml');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Find the first lerna workspace root by looking for lerna.json
|
|
39
|
+
*/
|
|
40
|
+
function findLernaWorkspace(cwd) {
|
|
41
|
+
return walkUp(cwd, 'lerna.json');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Find the first npm/yarn workspace root by looking for package.json with workspaces field
|
|
45
|
+
*/
|
|
46
|
+
function findNpmWorkspace(cwd) {
|
|
47
|
+
let currentDir = resolve(cwd);
|
|
48
|
+
const root = parsePath(currentDir).root;
|
|
49
|
+
while (currentDir !== root) {
|
|
50
|
+
const packageJsonPath = resolve(currentDir, 'package.json');
|
|
51
|
+
if (existsSync(packageJsonPath)) {
|
|
52
|
+
try {
|
|
53
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
54
|
+
if (packageJson.workspaces) {
|
|
55
|
+
return currentDir;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Ignore JSON parse errors
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
currentDir = dirname(currentDir);
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Find the nearest package.json directory (fallback)
|
|
68
|
+
*/
|
|
69
|
+
function findPackageRoot(cwd) {
|
|
70
|
+
return walkUp(cwd, 'package.json');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Find the workspace root directory.
|
|
74
|
+
*
|
|
75
|
+
* Search order:
|
|
76
|
+
* 1. pnpm-workspace.yaml (pnpm workspaces)
|
|
77
|
+
* 2. lerna.json (lerna workspaces)
|
|
78
|
+
* 3. package.json with "workspaces" field (npm/yarn workspaces)
|
|
79
|
+
* 4. Nearest package.json (fallback for non-workspace projects)
|
|
80
|
+
*
|
|
81
|
+
* @param cwd - Starting directory to search from (defaults to process.cwd())
|
|
82
|
+
* @returns The workspace root path, or null if nothing found
|
|
83
|
+
*/
|
|
84
|
+
export function findWorkspaceRoot(cwd = process.cwd()) {
|
|
85
|
+
return (findPnpmWorkspace(cwd) ??
|
|
86
|
+
findLernaWorkspace(cwd) ??
|
|
87
|
+
findNpmWorkspace(cwd) ??
|
|
88
|
+
findPackageRoot(cwd));
|
|
89
|
+
}
|
package/esm/types/config.d.ts
CHANGED
|
@@ -138,9 +138,9 @@ export interface DocsConfig {
|
|
|
138
138
|
*/
|
|
139
139
|
mcp?: boolean;
|
|
140
140
|
/**
|
|
141
|
-
* Generate skills/ directory — per-
|
|
142
|
-
*
|
|
143
|
-
*
|
|
141
|
+
* Generate skills/ directory — per-entity SKILL.md files with YAML frontmatter.
|
|
142
|
+
* Skills are written to the workspace root skills/ directory (not nested in output).
|
|
143
|
+
* Uses composable naming: orm-{target}-{entity}, hooks-{target}-{entity}, cli-{target}-{entity}.
|
|
144
144
|
* @default false
|
|
145
145
|
*/
|
|
146
146
|
skills?: boolean;
|
|
@@ -328,9 +328,17 @@ export interface GraphQLSDKConfigTarget {
|
|
|
328
328
|
* Controls which doc formats are generated alongside code for each generator target.
|
|
329
329
|
* Applied globally to all enabled generators (ORM, React Query, CLI).
|
|
330
330
|
* Set to `true` to enable all formats, or configure individually.
|
|
331
|
-
* @default { readme: true, agents: true, mcp: false
|
|
331
|
+
* @default { readme: true, agents: true, mcp: false }
|
|
332
332
|
*/
|
|
333
333
|
docs?: DocsConfig | boolean;
|
|
334
|
+
/**
|
|
335
|
+
* Custom path for generated skill files.
|
|
336
|
+
* When set, skills are written to this directory.
|
|
337
|
+
* When undefined (default), skills are written to {workspaceRoot}/skills/
|
|
338
|
+
* where workspaceRoot is auto-detected by walking up from the output directory
|
|
339
|
+
* looking for pnpm-workspace.yaml, lerna.json, or package.json with workspaces.
|
|
340
|
+
*/
|
|
341
|
+
skillsPath?: string;
|
|
334
342
|
/**
|
|
335
343
|
* Query key generation configuration
|
|
336
344
|
* Controls how query keys are structured for cache management
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/graphql-codegen",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.1",
|
|
4
4
|
"description": "GraphQL SDK generator for Constructive databases with React Query hooks",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"graphql",
|
|
@@ -54,28 +54,28 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@0no-co/graphql.web": "^1.1.2",
|
|
57
|
-
"@babel/generator": "^7.
|
|
58
|
-
"@babel/types": "^7.
|
|
59
|
-
"@constructive-io/graphql-query": "^3.3.
|
|
57
|
+
"@babel/generator": "^7.29.1",
|
|
58
|
+
"@babel/types": "^7.29.0",
|
|
59
|
+
"@constructive-io/graphql-query": "^3.3.4",
|
|
60
60
|
"@constructive-io/graphql-types": "^3.1.2",
|
|
61
61
|
"@inquirerer/utils": "^3.3.1",
|
|
62
|
-
"@pgpmjs/core": "^6.4.
|
|
63
|
-
"ajv": "^8.
|
|
62
|
+
"@pgpmjs/core": "^6.4.2",
|
|
63
|
+
"ajv": "^8.18.0",
|
|
64
64
|
"deepmerge": "^4.3.1",
|
|
65
|
-
"find-and-require-package-json": "^0.9.
|
|
66
|
-
"gql-ast": "^3.1.
|
|
67
|
-
"graphile-schema": "^1.3.
|
|
68
|
-
"graphql": "^16.
|
|
69
|
-
"inflekt": "^0.3.
|
|
65
|
+
"find-and-require-package-json": "^0.9.1",
|
|
66
|
+
"gql-ast": "^3.1.1",
|
|
67
|
+
"graphile-schema": "^1.3.4",
|
|
68
|
+
"graphql": "^16.13.0",
|
|
69
|
+
"inflekt": "^0.3.3",
|
|
70
70
|
"inquirerer": "^4.5.2",
|
|
71
71
|
"jiti": "^2.6.1",
|
|
72
|
-
"komoji": "^0.8.
|
|
73
|
-
"oxfmt": "^0.
|
|
74
|
-
"pg-cache": "^3.1.
|
|
72
|
+
"komoji": "^0.8.1",
|
|
73
|
+
"oxfmt": "^0.36.0",
|
|
74
|
+
"pg-cache": "^3.1.1",
|
|
75
75
|
"pg-env": "^1.5.0",
|
|
76
|
-
"pgsql-client": "^3.3.
|
|
77
|
-
"pgsql-seed": "^2.3.
|
|
78
|
-
"undici": "^7.
|
|
76
|
+
"pgsql-client": "^3.3.2",
|
|
77
|
+
"pgsql-seed": "^2.3.2",
|
|
78
|
+
"undici": "^7.22.0"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
81
|
"@tanstack/react-query": "^5.0.0",
|
|
@@ -90,16 +90,16 @@
|
|
|
90
90
|
}
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
|
-
"@tanstack/react-query": "^5.90.
|
|
93
|
+
"@tanstack/react-query": "^5.90.21",
|
|
94
94
|
"@types/babel__generator": "^7.27.0",
|
|
95
95
|
"@types/jest": "^30.0.0",
|
|
96
|
-
"@types/node": "^
|
|
97
|
-
"@types/react": "^19.2.
|
|
96
|
+
"@types/node": "^22.19.11",
|
|
97
|
+
"@types/react": "^19.2.14",
|
|
98
98
|
"jest": "^30.2.0",
|
|
99
|
-
"react": "^19.2.
|
|
99
|
+
"react": "^19.2.4",
|
|
100
100
|
"ts-jest": "^29.2.5",
|
|
101
101
|
"tsx": "^4.21.0",
|
|
102
102
|
"typescript": "^5.9.3"
|
|
103
103
|
},
|
|
104
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "f4176b73429bffca0aec8dc89abe9835bf40e5c6"
|
|
105
105
|
}
|
package/types/config.d.ts
CHANGED
|
@@ -138,9 +138,9 @@ export interface DocsConfig {
|
|
|
138
138
|
*/
|
|
139
139
|
mcp?: boolean;
|
|
140
140
|
/**
|
|
141
|
-
* Generate skills/ directory — per-
|
|
142
|
-
*
|
|
143
|
-
*
|
|
141
|
+
* Generate skills/ directory — per-entity SKILL.md files with YAML frontmatter.
|
|
142
|
+
* Skills are written to the workspace root skills/ directory (not nested in output).
|
|
143
|
+
* Uses composable naming: orm-{target}-{entity}, hooks-{target}-{entity}, cli-{target}-{entity}.
|
|
144
144
|
* @default false
|
|
145
145
|
*/
|
|
146
146
|
skills?: boolean;
|
|
@@ -328,9 +328,17 @@ export interface GraphQLSDKConfigTarget {
|
|
|
328
328
|
* Controls which doc formats are generated alongside code for each generator target.
|
|
329
329
|
* Applied globally to all enabled generators (ORM, React Query, CLI).
|
|
330
330
|
* Set to `true` to enable all formats, or configure individually.
|
|
331
|
-
* @default { readme: true, agents: true, mcp: false
|
|
331
|
+
* @default { readme: true, agents: true, mcp: false }
|
|
332
332
|
*/
|
|
333
333
|
docs?: DocsConfig | boolean;
|
|
334
|
+
/**
|
|
335
|
+
* Custom path for generated skill files.
|
|
336
|
+
* When set, skills are written to this directory.
|
|
337
|
+
* When undefined (default), skills are written to {workspaceRoot}/skills/
|
|
338
|
+
* where workspaceRoot is auto-detected by walking up from the output directory
|
|
339
|
+
* looking for pnpm-workspace.yaml, lerna.json, or package.json with workspaces.
|
|
340
|
+
*/
|
|
341
|
+
skillsPath?: string;
|
|
334
342
|
/**
|
|
335
343
|
* Query key generation configuration
|
|
336
344
|
* Controls how query keys are structured for cache management
|