@constructive-io/graphql-codegen 4.24.5 → 4.26.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.
Files changed (36) hide show
  1. package/core/codegen/cli/docs-generator.d.ts +2 -4
  2. package/core/codegen/cli/docs-generator.js +74 -472
  3. package/core/codegen/cli/index.d.ts +2 -2
  4. package/core/codegen/cli/index.js +1 -3
  5. package/core/codegen/cli/table-command-generator.js +165 -16
  6. package/core/codegen/docs-utils.d.ts +0 -6
  7. package/core/codegen/docs-utils.js +13 -7
  8. package/core/codegen/hooks-docs-generator.d.ts +1 -2
  9. package/core/codegen/hooks-docs-generator.js +0 -113
  10. package/core/codegen/orm/docs-generator.d.ts +1 -2
  11. package/core/codegen/orm/docs-generator.js +0 -126
  12. package/core/codegen/target-docs-generator.d.ts +1 -2
  13. package/core/codegen/target-docs-generator.js +0 -13
  14. package/core/codegen/templates/cli-utils.ts +117 -0
  15. package/core/codegen/utils.d.ts +2 -2
  16. package/core/codegen/utils.js +2 -2
  17. package/core/generate.js +0 -26
  18. package/esm/core/codegen/cli/docs-generator.d.ts +2 -4
  19. package/esm/core/codegen/cli/docs-generator.js +75 -471
  20. package/esm/core/codegen/cli/index.d.ts +2 -2
  21. package/esm/core/codegen/cli/index.js +1 -1
  22. package/esm/core/codegen/cli/table-command-generator.js +166 -17
  23. package/esm/core/codegen/docs-utils.d.ts +0 -6
  24. package/esm/core/codegen/docs-utils.js +13 -7
  25. package/esm/core/codegen/hooks-docs-generator.d.ts +1 -2
  26. package/esm/core/codegen/hooks-docs-generator.js +2 -114
  27. package/esm/core/codegen/orm/docs-generator.d.ts +1 -2
  28. package/esm/core/codegen/orm/docs-generator.js +1 -126
  29. package/esm/core/codegen/target-docs-generator.d.ts +1 -2
  30. package/esm/core/codegen/target-docs-generator.js +0 -12
  31. package/esm/core/codegen/utils.d.ts +2 -2
  32. package/esm/core/codegen/utils.js +2 -2
  33. package/esm/core/generate.js +4 -30
  34. package/esm/types/config.d.ts +1 -8
  35. package/package.json +16 -16
  36. package/types/config.d.ts +1 -8
@@ -39,6 +39,7 @@ const t = __importStar(require("@babel/types"));
39
39
  const komoji_1 = require("komoji");
40
40
  const babel_ast_1 = require("../babel-ast");
41
41
  const utils_1 = require("../utils");
42
+ const docs_utils_1 = require("../docs-utils");
42
43
  function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false) {
43
44
  const specifiers = namedImports.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
44
45
  const decl = t.importDeclaration(specifiers, t.stringLiteral(moduleSpecifier));
@@ -190,7 +191,7 @@ function buildArgvType() {
190
191
  }
191
192
  function buildSubcommandSwitch(subcommands, handlerPrefix, usageVarName) {
192
193
  const cases = subcommands.map((sub) => t.switchCase(t.stringLiteral(sub), [
193
- t.returnStatement(t.callExpression(t.identifier(`${handlerPrefix}${(0, utils_1.ucFirst)(sub)}`), [
194
+ t.returnStatement(t.callExpression(t.identifier(`${handlerPrefix}${(0, utils_1.toPascalCase)(sub)}`), [
194
195
  t.identifier('argv'),
195
196
  t.identifier('prompter'),
196
197
  ])),
@@ -203,17 +204,27 @@ function buildSubcommandSwitch(subcommands, handlerPrefix, usageVarName) {
203
204
  }
204
205
  function buildListHandler(table, targetName, typeRegistry) {
205
206
  const { singularName } = (0, utils_1.getTableNames)(table);
206
- const selectObj = buildSelectObject(table, typeRegistry);
207
- const tryBody = [
208
- buildGetClientStatement(targetName),
209
- t.variableDeclaration('const', [
210
- t.variableDeclarator(t.identifier('result'), t.awaitExpression(buildOrmCall(singularName, 'findMany', t.objectExpression([
211
- t.objectProperty(t.identifier('select'), selectObj),
212
- ])))),
213
- ]),
214
- buildJsonLog(t.identifier('result')),
215
- ];
216
- const argvParam = t.identifier('_argv');
207
+ const defaultSelectObj = buildSelectObject(table, typeRegistry);
208
+ // --- Build the try body ---
209
+ const tryBody = [];
210
+ // const defaultSelect = { id: true, name: true, ... };
211
+ tryBody.push(t.variableDeclaration('const', [
212
+ t.variableDeclarator(t.identifier('defaultSelect'), defaultSelectObj),
213
+ ]));
214
+ // const findManyArgs = parseFindManyArgs(argv, defaultSelect);
215
+ tryBody.push(t.variableDeclaration('const', [
216
+ t.variableDeclarator(t.identifier('findManyArgs'), t.callExpression(t.identifier('parseFindManyArgs'), [
217
+ t.identifier('argv'),
218
+ t.identifier('defaultSelect'),
219
+ ])),
220
+ ]));
221
+ tryBody.push(buildGetClientStatement(targetName));
222
+ // const result = await client.<singular>.findMany(findManyArgs).execute();
223
+ tryBody.push(t.variableDeclaration('const', [
224
+ t.variableDeclarator(t.identifier('result'), t.awaitExpression(t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.memberExpression(t.identifier('client'), t.identifier(singularName)), t.identifier('findMany')), [t.identifier('findManyArgs')]), t.identifier('execute')), []))),
225
+ ]));
226
+ tryBody.push(buildJsonLog(t.identifier('result')));
227
+ const argvParam = t.identifier('argv');
217
228
  argvParam.typeAnnotation = buildArgvType();
218
229
  const prompterParam = t.identifier('_prompter');
219
230
  prompterParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Inquirerer')));
@@ -221,6 +232,129 @@ function buildListHandler(table, targetName, typeRegistry) {
221
232
  t.tryStatement(t.blockStatement(tryBody), buildErrorCatch('Failed to list records.')),
222
233
  ]), false, true);
223
234
  }
235
+ /**
236
+ * Build a `handleFindFirst` function — CLI equivalent of the TS SDK's findFirst().
237
+ * Accepts --fields, --where.<field>.<op>, --condition.<field>.<op> flags.
238
+ * Internally calls findMany with first:1 and returns a single record (or null).
239
+ */
240
+ function buildFindFirstHandler(table, targetName, typeRegistry) {
241
+ const { singularName } = (0, utils_1.getTableNames)(table);
242
+ const defaultSelectObj = buildSelectObject(table, typeRegistry);
243
+ const tryBody = [];
244
+ // const defaultSelect = { ... };
245
+ tryBody.push(t.variableDeclaration('const', [
246
+ t.variableDeclarator(t.identifier('defaultSelect'), defaultSelectObj),
247
+ ]));
248
+ // const findFirstArgs = parseFindFirstArgs(argv, defaultSelect);
249
+ tryBody.push(t.variableDeclaration('const', [
250
+ t.variableDeclarator(t.identifier('findFirstArgs'), t.callExpression(t.identifier('parseFindFirstArgs'), [
251
+ t.identifier('argv'),
252
+ t.identifier('defaultSelect'),
253
+ ])),
254
+ ]));
255
+ tryBody.push(buildGetClientStatement(targetName));
256
+ // const result = await client.<singular>.findFirst(findFirstArgs).execute();
257
+ tryBody.push(t.variableDeclaration('const', [
258
+ t.variableDeclarator(t.identifier('result'), t.awaitExpression(t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.memberExpression(t.identifier('client'), t.identifier(singularName)), t.identifier('findFirst')), [t.identifier('findFirstArgs')]), t.identifier('execute')), []))),
259
+ ]));
260
+ tryBody.push(buildJsonLog(t.identifier('result')));
261
+ const argvParam = t.identifier('argv');
262
+ argvParam.typeAnnotation = buildArgvType();
263
+ const prompterParam = t.identifier('_prompter');
264
+ prompterParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Inquirerer')));
265
+ return t.functionDeclaration(t.identifier('handleFindFirst'), [argvParam, prompterParam], t.blockStatement([
266
+ t.tryStatement(t.blockStatement(tryBody), buildErrorCatch('Failed to find record.')),
267
+ ]), false, true);
268
+ }
269
+ /**
270
+ * Build a `handleSearch` function for tables with search-capable fields.
271
+ * Extracts the first positional arg as the query string and auto-builds a
272
+ * `where` clause that targets all detected search fields (tsvector, BM25,
273
+ * trigram, vector embedding). Supports --limit, --offset, --fields, --orderBy.
274
+ */
275
+ function buildSearchHandler(table, specialGroups, targetName, typeRegistry) {
276
+ const { singularName } = (0, utils_1.getTableNames)(table);
277
+ const defaultSelectObj = buildSelectObject(table, typeRegistry);
278
+ const tryBody = [];
279
+ // const query = Array.isArray(argv._) && argv._.length > 0 ? String(argv._[0]) : undefined;
280
+ tryBody.push(t.variableDeclaration('const', [
281
+ t.variableDeclarator(t.identifier('query'), t.conditionalExpression(t.logicalExpression('&&', t.callExpression(t.memberExpression(t.identifier('Array'), t.identifier('isArray')), [t.memberExpression(t.identifier('argv'), t.identifier('_'))]), t.binaryExpression('>', t.memberExpression(t.memberExpression(t.identifier('argv'), t.identifier('_')), t.identifier('length')), t.numericLiteral(0))), t.callExpression(t.identifier('String'), [
282
+ t.memberExpression(t.memberExpression(t.identifier('argv'), t.identifier('_')), t.numericLiteral(0), true),
283
+ ]), t.identifier('undefined'))),
284
+ ]));
285
+ // if (!query) { console.error('Usage: ... search <query>'); process.exit(1); }
286
+ tryBody.push(t.ifStatement(t.unaryExpression('!', t.identifier('query')), t.blockStatement([
287
+ t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('error')), [t.stringLiteral('Error: search requires a <query> argument')])),
288
+ t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('process'), t.identifier('exit')), [t.numericLiteral(1)])),
289
+ ])));
290
+ // Build the where clause properties from detected search fields
291
+ // e.g. { tsvContent: { query }, bm25Body: { query }, trgmTitle: { value: query, threshold: 0.3 }, vectorEmbedding: { value: query } }
292
+ const whereProps = [];
293
+ for (const group of specialGroups) {
294
+ for (const field of group.fields) {
295
+ if (field.type.gqlType === 'FullText' && !field.type.isArray) {
296
+ // tsvector field: { query }
297
+ whereProps.push(t.objectProperty(t.identifier(field.name), t.objectExpression([
298
+ t.objectProperty(t.identifier('query'), t.identifier('query'), false, true),
299
+ ])));
300
+ }
301
+ else if (/Bm25Score$/.test(field.name)) {
302
+ // BM25 computed score field — derive the input field name:
303
+ // bodyBm25Score -> bm25Body (strip trailing "Bm25Score", prefix with "bm25")
304
+ const baseName = field.name.replace(/Bm25Score$/, '');
305
+ const inputFieldName = `bm25${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}`;
306
+ whereProps.push(t.objectProperty(t.identifier(inputFieldName), t.objectExpression([
307
+ t.objectProperty(t.identifier('query'), t.identifier('query'), false, true),
308
+ ])));
309
+ }
310
+ else if (/TrgmSimilarity$/.test(field.name)) {
311
+ // Trigram computed score field — derive the input field name:
312
+ // titleTrgmSimilarity -> trgmTitle
313
+ const baseName = field.name.replace(/TrgmSimilarity$/, '');
314
+ const inputFieldName = `trgm${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}`;
315
+ whereProps.push(t.objectProperty(t.identifier(inputFieldName), t.objectExpression([
316
+ t.objectProperty(t.identifier('value'), t.identifier('query')),
317
+ t.objectProperty(t.identifier('threshold'), t.numericLiteral(0.3)),
318
+ ])));
319
+ }
320
+ else if (group.category === 'embedding') {
321
+ // Vector embedding field: { value: query }
322
+ whereProps.push(t.objectProperty(t.identifier(field.name), t.objectExpression([
323
+ t.objectProperty(t.identifier('value'), t.identifier('query')),
324
+ ])));
325
+ }
326
+ }
327
+ }
328
+ // const searchWhere = { tsvContent: { query }, ... };
329
+ tryBody.push(t.variableDeclaration('const', [
330
+ t.variableDeclarator(t.identifier('searchWhere'), t.objectExpression(whereProps)),
331
+ ]));
332
+ // const defaultSelect = { ... };
333
+ tryBody.push(t.variableDeclaration('const', [
334
+ t.variableDeclarator(t.identifier('defaultSelect'), defaultSelectObj),
335
+ ]));
336
+ // const findManyArgs = parseFindManyArgs(argv, defaultSelect, searchWhere);
337
+ tryBody.push(t.variableDeclaration('const', [
338
+ t.variableDeclarator(t.identifier('findManyArgs'), t.callExpression(t.identifier('parseFindManyArgs'), [
339
+ t.identifier('argv'),
340
+ t.identifier('defaultSelect'),
341
+ t.identifier('searchWhere'),
342
+ ])),
343
+ ]));
344
+ tryBody.push(buildGetClientStatement(targetName));
345
+ // const result = await client.<singular>.findMany(findManyArgs).execute();
346
+ tryBody.push(t.variableDeclaration('const', [
347
+ t.variableDeclarator(t.identifier('result'), t.awaitExpression(t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.memberExpression(t.identifier('client'), t.identifier(singularName)), t.identifier('findMany')), [t.identifier('findManyArgs')]), t.identifier('execute')), []))),
348
+ ]));
349
+ tryBody.push(buildJsonLog(t.identifier('result')));
350
+ const argvParam = t.identifier('argv');
351
+ argvParam.typeAnnotation = buildArgvType();
352
+ const prompterParam = t.identifier('_prompter');
353
+ prompterParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Inquirerer')));
354
+ return t.functionDeclaration(t.identifier('handleSearch'), [argvParam, prompterParam], t.blockStatement([
355
+ t.tryStatement(t.blockStatement(tryBody), buildErrorCatch('Failed to search records.')),
356
+ ]), false, true);
357
+ }
224
358
  function buildGetHandler(table, targetName, typeRegistry) {
225
359
  const { singularName } = (0, utils_1.getTableNames)(table);
226
360
  const pkFields = (0, utils_1.getPrimaryKeyInfo)(table);
@@ -431,7 +565,7 @@ function generateTableCommand(table, options) {
431
565
  ]));
432
566
  statements.push(createImportDeclaration(executorPath, ['getClient']));
433
567
  const utilsPath = options?.targetName ? '../../utils' : '../utils';
434
- statements.push(createImportDeclaration(utilsPath, ['coerceAnswers', 'stripUndefined']));
568
+ statements.push(createImportDeclaration(utilsPath, ['coerceAnswers', 'parseFindFirstArgs', 'parseFindManyArgs', 'stripUndefined']));
435
569
  statements.push(createImportDeclaration(utilsPath, ['FieldSchema'], true));
436
570
  // Import ORM input types for proper type assertions in mutation handlers.
437
571
  // These types ensure that cleanedData is cast to the correct ORM input type
@@ -463,7 +597,12 @@ function generateTableCommand(table, options) {
463
597
  const hasUpdate = table.query?.update !== undefined && table.query?.update !== null;
464
598
  const hasDelete = table.query?.delete !== undefined && table.query?.delete !== null;
465
599
  const hasGet = table.query?.one !== null || hasUpdate || hasDelete;
466
- const subcommands = ['list'];
600
+ // Detect whether this table has search-capable fields (tsvector, BM25, trgm, vector embedding)
601
+ const specialGroups = (0, docs_utils_1.categorizeSpecialFields)(table, options?.typeRegistry);
602
+ const hasSearchFields = specialGroups.some((g) => g.category === 'search' || g.category === 'embedding');
603
+ const subcommands = ['list', 'find-first'];
604
+ if (hasSearchFields)
605
+ subcommands.push('search');
467
606
  if (hasGet)
468
607
  subcommands.push('get');
469
608
  subcommands.push('create');
@@ -476,8 +615,11 @@ function generateTableCommand(table, options) {
476
615
  `${commandName} <command>`,
477
616
  '',
478
617
  'Commands:',
479
- ` list List all ${singularName} records`,
618
+ ` list List ${singularName} records`,
619
+ ` find-first Find first matching ${singularName} record`,
480
620
  ];
621
+ if (hasSearchFields)
622
+ usageLines.push(` search <query> Search ${singularName} records`);
481
623
  if (hasGet)
482
624
  usageLines.push(` get Get a ${singularName} by ID`);
483
625
  usageLines.push(` create Create a new ${singularName}`);
@@ -485,7 +627,11 @@ function generateTableCommand(table, options) {
485
627
  usageLines.push(` update Update an existing ${singularName}`);
486
628
  if (hasDelete)
487
629
  usageLines.push(` delete Delete a ${singularName}`);
488
- usageLines.push('', ' --help, -h Show this help message', '');
630
+ usageLines.push('', 'List Options:', ' --limit <n> Max number of records to return (forward pagination)', ' --last <n> Number of records from the end (backward pagination)', ' --after <cursor> Cursor for forward pagination', ' --before <cursor> Cursor for backward pagination', ' --offset <n> Number of records to skip', ' --fields <fields> Comma-separated list of fields to return', ' --where.<field>.<op> Filter (dot-notation, e.g. --where.name.equalTo foo)', ' --condition.<f>.<op> Condition filter (dot-notation)', ' --orderBy <values> Comma-separated ordering values (e.g. NAME_ASC,CREATED_AT_DESC)', '', 'Find-First Options:', ' --fields <fields> Comma-separated list of fields to return', ' --where.<field>.<op> Filter (dot-notation, e.g. --where.status.equalTo active)', ' --condition.<f>.<op> Condition filter (dot-notation)', '');
631
+ if (hasSearchFields) {
632
+ usageLines.push('Search Options:', ' <query> Search query string (required)', ' --limit <n> Max number of records to return', ' --offset <n> Number of records to skip', ' --fields <fields> Comma-separated list of fields to return', ' --orderBy <values> Comma-separated list of ordering values', '');
633
+ }
634
+ usageLines.push(' --help, -h Show this help message', '');
489
635
  statements.push(t.variableDeclaration('const', [
490
636
  t.variableDeclarator(t.identifier('usage'), t.stringLiteral(usageLines.join('\n'))),
491
637
  ]));
@@ -547,6 +693,9 @@ function generateTableCommand(table, options) {
547
693
  const tn = options?.targetName;
548
694
  const ormTypes = { createInputTypeName, patchTypeName, innerFieldName };
549
695
  statements.push(buildListHandler(table, tn, options?.typeRegistry));
696
+ statements.push(buildFindFirstHandler(table, tn, options?.typeRegistry));
697
+ if (hasSearchFields)
698
+ statements.push(buildSearchHandler(table, specialGroups, tn, options?.typeRegistry));
550
699
  if (hasGet)
551
700
  statements.push(buildGetHandler(table, tn, options?.typeRegistry));
552
701
  statements.push(buildMutationHandler(table, 'create', tn, options?.typeRegistry, ormTypes));
@@ -4,12 +4,6 @@ export interface GeneratedDocFile {
4
4
  fileName: string;
5
5
  content: string;
6
6
  }
7
- export interface McpTool {
8
- name: string;
9
- description: string;
10
- inputSchema: Record<string, unknown>;
11
- _meta?: Record<string, unknown>;
12
- }
13
7
  export interface SkillDefinition {
14
8
  name: string;
15
9
  description: string;
@@ -50,18 +50,17 @@ function getReadmeFooter() {
50
50
  }
51
51
  function resolveDocsConfig(docs) {
52
52
  if (docs === true) {
53
- return { readme: true, agents: true, mcp: true, skills: true };
53
+ return { readme: true, agents: true, skills: true };
54
54
  }
55
55
  if (docs === false) {
56
- return { readme: false, agents: false, mcp: false, skills: false };
56
+ return { readme: false, agents: false, skills: false };
57
57
  }
58
58
  if (!docs) {
59
- return { readme: true, agents: true, mcp: false, skills: false };
59
+ return { readme: true, agents: true, skills: false };
60
60
  }
61
61
  return {
62
62
  readme: docs.readme ?? true,
63
63
  agents: docs.agents ?? true,
64
- mcp: docs.mcp ?? false,
65
64
  skills: docs.skills ?? false,
66
65
  };
67
66
  }
@@ -118,16 +117,23 @@ function isPostGISField(f) {
118
117
  return false;
119
118
  }
120
119
  function isEmbeddingField(f) {
121
- const pgType = f.type.pgType?.toLowerCase();
122
- if (pgType === 'vector')
120
+ // VectorCodecPlugin maps pgvector `vector` columns to the `Vector` GQL scalar.
121
+ // This is the primary detection path — no _meta or pgType enrichment needed.
122
+ if (f.type.gqlType === 'Vector')
123
123
  return true;
124
+ // Legacy fallback: name-based heuristic for schemas without VectorCodecPlugin
124
125
  if (/embedding$/i.test(f.name) && f.type.isArray && f.type.gqlType === 'Float')
125
126
  return true;
126
127
  return false;
127
128
  }
128
129
  function isTsvectorField(f) {
129
130
  const pgType = f.type.pgType?.toLowerCase();
130
- return pgType === 'tsvector';
131
+ if (pgType === 'tsvector')
132
+ return true;
133
+ // Fallback: PostGraphile maps tsvector columns to the FullText GQL scalar
134
+ if (f.type.gqlType === 'FullText' && !f.type.isArray)
135
+ return true;
136
+ return false;
131
137
  }
132
138
  function isSearchComputedField(f) {
133
139
  if (f.name === 'searchScore')
@@ -1,6 +1,5 @@
1
1
  import type { Operation, Table, TypeRegistry } from '../../types/schema';
2
- import type { GeneratedDocFile, McpTool } from './docs-utils';
2
+ import type { GeneratedDocFile } from './docs-utils';
3
3
  export declare function generateHooksReadme(tables: Table[], customOperations: Operation[], registry?: TypeRegistry): GeneratedDocFile;
4
4
  export declare function generateHooksAgentsDocs(tables: Table[], customOperations: Operation[]): GeneratedDocFile;
5
- export declare function getHooksMcpTools(tables: Table[], customOperations: Operation[]): McpTool[];
6
5
  export declare function generateHooksSkills(tables: Table[], customOperations: Operation[], targetName: string, registry?: TypeRegistry): GeneratedDocFile[];
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateHooksReadme = generateHooksReadme;
4
4
  exports.generateHooksAgentsDocs = generateHooksAgentsDocs;
5
- exports.getHooksMcpTools = getHooksMcpTools;
6
5
  exports.generateHooksSkills = generateHooksSkills;
7
6
  const komoji_1 = require("komoji");
8
7
  const docs_utils_1 = require("./docs-utils");
@@ -167,118 +166,6 @@ function generateHooksAgentsDocs(tables, customOperations) {
167
166
  content: lines.join('\n'),
168
167
  };
169
168
  }
170
- function getHooksMcpTools(tables, customOperations) {
171
- const tools = [];
172
- for (const table of tables) {
173
- const { singularName, pluralName } = (0, utils_1.getTableNames)(table);
174
- const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
175
- const scalarFields = (0, utils_1.getScalarFields)(table);
176
- tools.push({
177
- name: `hooks_${(0, utils_1.lcFirst)(pluralName)}_query`,
178
- description: table.description || `React Query hook to list all ${pluralName}`,
179
- inputSchema: {
180
- type: 'object',
181
- properties: {
182
- fields: {
183
- type: 'object',
184
- description: `Fields to select: { ${scalarFields.map((f) => f.name).join(', ')} }`,
185
- },
186
- },
187
- },
188
- });
189
- if ((0, utils_1.hasValidPrimaryKey)(table)) {
190
- tools.push({
191
- name: `hooks_${(0, utils_1.lcFirst)(singularName)}_query`,
192
- description: table.description || `React Query hook to get a single ${singularName} by ${pk.name}`,
193
- inputSchema: {
194
- type: 'object',
195
- properties: {
196
- [pk.name]: {
197
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(pk.gqlType),
198
- description: `${table.name} ${pk.name}`,
199
- },
200
- },
201
- required: [pk.name],
202
- },
203
- });
204
- }
205
- tools.push({
206
- name: `hooks_create_${(0, utils_1.lcFirst)(singularName)}_mutation`,
207
- description: table.description || `React Query mutation hook to create a ${singularName}`,
208
- inputSchema: {
209
- type: 'object',
210
- properties: Object.fromEntries(scalarFields
211
- .filter((f) => f.name !== pk.name &&
212
- f.name !== 'nodeId' &&
213
- f.name !== 'createdAt' &&
214
- f.name !== 'updatedAt')
215
- .map((f) => [
216
- f.name,
217
- {
218
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(f.type.gqlType),
219
- description: `${table.name} ${f.name}`,
220
- },
221
- ])),
222
- },
223
- });
224
- if ((0, utils_1.hasValidPrimaryKey)(table)) {
225
- tools.push({
226
- name: `hooks_update_${(0, utils_1.lcFirst)(singularName)}_mutation`,
227
- description: table.description || `React Query mutation hook to update a ${singularName}`,
228
- inputSchema: {
229
- type: 'object',
230
- properties: {
231
- [pk.name]: {
232
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(pk.gqlType),
233
- description: `${table.name} ${pk.name}`,
234
- },
235
- },
236
- required: [pk.name],
237
- },
238
- });
239
- tools.push({
240
- name: `hooks_delete_${(0, utils_1.lcFirst)(singularName)}_mutation`,
241
- description: table.description || `React Query mutation hook to delete a ${singularName}`,
242
- inputSchema: {
243
- type: 'object',
244
- properties: {
245
- [pk.name]: {
246
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(pk.gqlType),
247
- description: `${table.name} ${pk.name}`,
248
- },
249
- },
250
- required: [pk.name],
251
- },
252
- });
253
- }
254
- }
255
- for (const op of customOperations) {
256
- const hookName = getCustomHookName(op);
257
- const props = {};
258
- const required = [];
259
- for (const arg of op.args) {
260
- const isRequired = arg.type.kind === 'NON_NULL';
261
- const baseType = isRequired && arg.type.ofType ? arg.type.ofType : arg.type;
262
- props[arg.name] = {
263
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(baseType.name ?? 'String'),
264
- description: arg.description || arg.name,
265
- };
266
- if (isRequired) {
267
- required.push(arg.name);
268
- }
269
- }
270
- tools.push({
271
- name: `hooks_${hookName}`,
272
- description: op.description || `${(0, utils_1.ucFirst)(op.kind)} hook for ${op.name}`,
273
- inputSchema: {
274
- type: 'object',
275
- properties: props,
276
- ...(required.length > 0 ? { required } : {}),
277
- },
278
- });
279
- }
280
- return tools;
281
- }
282
169
  function generateHooksSkills(tables, customOperations, targetName, registry) {
283
170
  const files = [];
284
171
  const skillName = `hooks-${targetName}`;
@@ -1,6 +1,5 @@
1
1
  import type { Operation, Table, TypeRegistry } from '../../../types/schema';
2
- import type { GeneratedDocFile, McpTool } from '../docs-utils';
2
+ import type { GeneratedDocFile } from '../docs-utils';
3
3
  export declare function generateOrmReadme(tables: Table[], customOperations: Operation[], registry?: TypeRegistry): GeneratedDocFile;
4
4
  export declare function generateOrmAgentsDocs(tables: Table[], customOperations: Operation[]): GeneratedDocFile;
5
- export declare function getOrmMcpTools(tables: Table[], customOperations: Operation[]): McpTool[];
6
5
  export declare function generateOrmSkills(tables: Table[], customOperations: Operation[], targetName: string, registry?: TypeRegistry): GeneratedDocFile[];
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateOrmReadme = generateOrmReadme;
4
4
  exports.generateOrmAgentsDocs = generateOrmAgentsDocs;
5
- exports.getOrmMcpTools = getOrmMcpTools;
6
5
  exports.generateOrmSkills = generateOrmSkills;
7
6
  const komoji_1 = require("komoji");
8
7
  const docs_utils_1 = require("../docs-utils");
@@ -160,131 +159,6 @@ function generateOrmAgentsDocs(tables, customOperations) {
160
159
  content: lines.join('\n'),
161
160
  };
162
161
  }
163
- function getOrmMcpTools(tables, customOperations) {
164
- const tools = [];
165
- for (const table of tables) {
166
- const { singularName } = (0, utils_1.getTableNames)(table);
167
- const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
168
- const scalarFields = (0, utils_1.getScalarFields)(table);
169
- const editableFields = (0, docs_utils_1.getEditableFields)(table);
170
- tools.push({
171
- name: `orm_${(0, utils_1.lcFirst)(singularName)}_findMany`,
172
- description: table.description || `List all ${table.name} records via ORM`,
173
- inputSchema: {
174
- type: 'object',
175
- properties: {
176
- first: {
177
- type: 'integer',
178
- description: 'Limit number of results',
179
- },
180
- offset: {
181
- type: 'integer',
182
- description: 'Offset for pagination',
183
- },
184
- },
185
- },
186
- });
187
- tools.push({
188
- name: `orm_${(0, utils_1.lcFirst)(singularName)}_findOne`,
189
- description: table.description || `Get a single ${table.name} record by ${pk.name}`,
190
- inputSchema: {
191
- type: 'object',
192
- properties: {
193
- [pk.name]: {
194
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(pk.gqlType),
195
- description: `${table.name} ${pk.name}`,
196
- },
197
- },
198
- required: [pk.name],
199
- },
200
- });
201
- const createProps = {};
202
- for (const f of editableFields) {
203
- createProps[f.name] = {
204
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(f.type.gqlType),
205
- description: `${table.name} ${f.name}`,
206
- };
207
- }
208
- tools.push({
209
- name: `orm_${(0, utils_1.lcFirst)(singularName)}_create`,
210
- description: table.description || `Create a new ${table.name} record`,
211
- inputSchema: {
212
- type: 'object',
213
- properties: createProps,
214
- required: editableFields.map((f) => f.name),
215
- },
216
- });
217
- const updateProps = {
218
- [pk.name]: {
219
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(pk.gqlType),
220
- description: `${table.name} ${pk.name}`,
221
- },
222
- };
223
- for (const f of editableFields) {
224
- updateProps[f.name] = {
225
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(f.type.gqlType),
226
- description: `${table.name} ${f.name}`,
227
- };
228
- }
229
- tools.push({
230
- name: `orm_${(0, utils_1.lcFirst)(singularName)}_update`,
231
- description: table.description || `Update an existing ${table.name} record`,
232
- inputSchema: {
233
- type: 'object',
234
- properties: updateProps,
235
- required: [pk.name],
236
- },
237
- });
238
- tools.push({
239
- name: `orm_${(0, utils_1.lcFirst)(singularName)}_delete`,
240
- description: table.description || `Delete a ${table.name} record by ${pk.name}`,
241
- inputSchema: {
242
- type: 'object',
243
- properties: {
244
- [pk.name]: {
245
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(pk.gqlType),
246
- description: `${table.name} ${pk.name}`,
247
- },
248
- },
249
- required: [pk.name],
250
- },
251
- _meta: {
252
- fields: scalarFields.map((f) => ({
253
- name: f.name,
254
- type: f.type.gqlType,
255
- editable: editableFields.some((ef) => ef.name === f.name),
256
- primaryKey: f.name === pk.name,
257
- })),
258
- },
259
- });
260
- }
261
- for (const op of customOperations) {
262
- const accessor = op.kind === 'query' ? 'query' : 'mutation';
263
- const props = {};
264
- const required = [];
265
- for (const arg of op.args) {
266
- const isRequired = arg.type.kind === 'NON_NULL';
267
- const baseType = isRequired && arg.type.ofType ? arg.type.ofType : arg.type;
268
- props[arg.name] = {
269
- type: (0, docs_utils_1.gqlTypeToJsonSchemaType)(baseType.name ?? 'String'),
270
- description: arg.description || arg.name,
271
- };
272
- if (isRequired) {
273
- required.push(arg.name);
274
- }
275
- }
276
- tools.push({
277
- name: `orm_${accessor}_${op.name}`,
278
- description: op.description || `Execute ${op.name} ${op.kind}`,
279
- inputSchema: {
280
- type: 'object',
281
- properties: props,
282
- ...(required.length > 0 ? { required } : {}),
283
- },
284
- });
285
- }
286
- return tools;
287
- }
288
162
  function generateOrmSkills(tables, customOperations, targetName, registry) {
289
163
  const files = [];
290
164
  const skillName = `orm-${targetName}`;
@@ -1,5 +1,5 @@
1
1
  import type { GraphQLSDKConfigTarget } from '../../types/config';
2
- import type { GeneratedDocFile, McpTool } from './docs-utils';
2
+ import type { GeneratedDocFile } from './docs-utils';
3
3
  export interface TargetReadmeOptions {
4
4
  hasOrm: boolean;
5
5
  hasHooks: boolean;
@@ -10,7 +10,6 @@ export interface TargetReadmeOptions {
10
10
  config: GraphQLSDKConfigTarget;
11
11
  }
12
12
  export declare function generateTargetReadme(options: TargetReadmeOptions): GeneratedDocFile;
13
- export declare function generateCombinedMcpConfig(tools: McpTool[], name: string): GeneratedDocFile;
14
13
  export interface RootRootReadmeTarget {
15
14
  name: string;
16
15
  output: string;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateTargetReadme = generateTargetReadme;
4
- exports.generateCombinedMcpConfig = generateCombinedMcpConfig;
5
4
  exports.generateRootRootReadme = generateRootRootReadme;
6
5
  const docs_utils_1 = require("./docs-utils");
7
6
  function generateTargetReadme(options) {
@@ -77,18 +76,6 @@ function generateTargetReadme(options) {
77
76
  content: lines.join('\n'),
78
77
  };
79
78
  }
80
- function generateCombinedMcpConfig(tools, name) {
81
- const mcpConfig = {
82
- name,
83
- version: '1.0.0',
84
- description: `MCP tool definitions for ${name} SDK (auto-generated from GraphQL schema)`,
85
- tools,
86
- };
87
- return {
88
- fileName: 'mcp.json',
89
- content: JSON.stringify(mcpConfig, null, 2) + '\n',
90
- };
91
- }
92
79
  function generateRootRootReadme(targets) {
93
80
  const lines = [];
94
81
  lines.push(...(0, docs_utils_1.getReadmeHeader)('GraphQL SDK'));