@constructive-io/graphql-codegen 4.26.0 → 4.27.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 +9 -9
- package/core/codegen/cli/custom-command-generator.js +2 -2
- package/core/codegen/cli/docs-generator.js +23 -31
- package/core/codegen/cli/index.d.ts +3 -1
- package/core/codegen/cli/index.js +16 -1
- package/core/codegen/cli/table-command-generator.d.ts +2 -0
- package/core/codegen/cli/table-command-generator.js +250 -36
- package/core/codegen/cli/utils-generator.d.ts +8 -0
- package/core/codegen/cli/utils-generator.js +14 -0
- package/core/codegen/docs-utils.d.ts +17 -0
- package/core/codegen/docs-utils.js +127 -0
- package/core/codegen/hooks-docs-generator.js +3 -3
- package/core/codegen/index.js +1 -1
- package/core/codegen/orm/docs-generator.js +3 -3
- package/core/codegen/orm/index.js +1 -1
- package/core/codegen/orm/input-types-generator.js +1 -1
- package/core/codegen/orm/model-generator.js +1 -1
- package/core/codegen/queries.js +1 -1
- package/core/codegen/templates/cli-utils.ts +11 -11
- package/core/codegen/templates/embedder.ts +175 -0
- package/core/generate.js +2 -0
- package/esm/core/codegen/cli/command-map-generator.js +1 -1
- package/esm/core/codegen/cli/custom-command-generator.js +1 -1
- package/esm/core/codegen/cli/docs-generator.js +7 -15
- package/esm/core/codegen/cli/index.d.ts +3 -1
- package/esm/core/codegen/cli/index.js +16 -2
- package/esm/core/codegen/cli/table-command-generator.d.ts +2 -0
- package/esm/core/codegen/cli/table-command-generator.js +250 -36
- package/esm/core/codegen/cli/utils-generator.d.ts +8 -0
- package/esm/core/codegen/cli/utils-generator.js +13 -0
- package/esm/core/codegen/docs-utils.d.ts +17 -0
- package/esm/core/codegen/docs-utils.js +125 -0
- package/esm/core/codegen/hooks-docs-generator.js +1 -1
- package/esm/core/codegen/index.js +1 -1
- package/esm/core/codegen/orm/docs-generator.js +1 -1
- package/esm/core/codegen/orm/index.js +1 -1
- package/esm/core/codegen/orm/input-types-generator.js +1 -1
- package/esm/core/codegen/orm/model-generator.js +1 -1
- package/esm/core/codegen/queries.js +1 -1
- package/esm/core/generate.js +2 -0
- package/package.json +8 -9
|
@@ -36,7 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.getFieldsWithDefaults = getFieldsWithDefaults;
|
|
37
37
|
exports.generateTableCommand = generateTableCommand;
|
|
38
38
|
const t = __importStar(require("@babel/types"));
|
|
39
|
-
const
|
|
39
|
+
const inflekt_1 = require("inflekt");
|
|
40
40
|
const babel_ast_1 = require("../babel-ast");
|
|
41
41
|
const utils_1 = require("../utils");
|
|
42
42
|
const docs_utils_1 = require("../docs-utils");
|
|
@@ -202,7 +202,146 @@ function buildSubcommandSwitch(subcommands, handlerPrefix, usageVarName) {
|
|
|
202
202
|
]));
|
|
203
203
|
return t.switchStatement(t.identifier('subcommand'), cases);
|
|
204
204
|
}
|
|
205
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Build an auto-embed block that resolves the embedder and converts text
|
|
207
|
+
* values in the where clause to vector embeddings.
|
|
208
|
+
*
|
|
209
|
+
* Generates code equivalent to:
|
|
210
|
+
* if (argv['auto-embed']) {
|
|
211
|
+
* const embedder = resolveEmbedder();
|
|
212
|
+
* if (!embedder) {
|
|
213
|
+
* console.error('--auto-embed requires an embedder. Set EMBEDDER_PROVIDER=ollama');
|
|
214
|
+
* process.exit(1);
|
|
215
|
+
* }
|
|
216
|
+
* await autoEmbedWhere(findManyArgs.where ?? {}, ['fieldA', 'fieldB'], embedder);
|
|
217
|
+
* }
|
|
218
|
+
*
|
|
219
|
+
* @param whereExpr - The expression to access the where clause (e.g. findManyArgs.where, searchWhere)
|
|
220
|
+
* @param vectorFieldNames - Names of vector embedding fields detected at codegen time
|
|
221
|
+
* @param assignBack - If true, assigns the result back to findManyArgs.where
|
|
222
|
+
*/
|
|
223
|
+
function buildAutoEmbedBlock(whereExpr, vectorFieldNames, assignBack = false) {
|
|
224
|
+
const fieldNamesArray = t.arrayExpression(vectorFieldNames.map((n) => t.stringLiteral(n)));
|
|
225
|
+
const embedderDecl = t.variableDeclaration('const', [
|
|
226
|
+
t.variableDeclarator(t.identifier('embedder'), t.callExpression(t.identifier('resolveEmbedder'), [])),
|
|
227
|
+
]);
|
|
228
|
+
const noEmbedderCheck = t.ifStatement(t.unaryExpression('!', t.identifier('embedder')), t.blockStatement([
|
|
229
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('error')), [
|
|
230
|
+
t.stringLiteral('--auto-embed requires an embedder. Set EMBEDDER_PROVIDER=ollama (and optionally EMBEDDER_MODEL, EMBEDDER_BASE_URL).'),
|
|
231
|
+
])),
|
|
232
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('process'), t.identifier('exit')), [t.numericLiteral(1)])),
|
|
233
|
+
]));
|
|
234
|
+
const autoEmbedCall = t.awaitExpression(t.callExpression(t.identifier('autoEmbedWhere'), [
|
|
235
|
+
t.logicalExpression('??', whereExpr, t.objectExpression([])),
|
|
236
|
+
fieldNamesArray,
|
|
237
|
+
t.identifier('embedder'),
|
|
238
|
+
]));
|
|
239
|
+
const bodyStatements = [embedderDecl, noEmbedderCheck];
|
|
240
|
+
if (assignBack) {
|
|
241
|
+
// findManyArgs.where = await autoEmbedWhere(findManyArgs.where ?? {}, [...], embedder);
|
|
242
|
+
bodyStatements.push(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier('findManyArgs'), t.identifier('where')), autoEmbedCall)));
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// await autoEmbedWhere(searchWhere, [...], embedder);
|
|
246
|
+
bodyStatements.push(t.expressionStatement(autoEmbedCall));
|
|
247
|
+
}
|
|
248
|
+
return t.ifStatement(t.memberExpression(t.identifier('argv'), t.stringLiteral('auto-embed'), true), t.blockStatement(bodyStatements));
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Build an auto-embed block for mutation handlers (create/update).
|
|
252
|
+
*
|
|
253
|
+
* Generates code equivalent to:
|
|
254
|
+
* if (argv['auto-embed']) {
|
|
255
|
+
* const embedder = resolveEmbedder();
|
|
256
|
+
* if (!embedder) {
|
|
257
|
+
* console.error('--auto-embed requires an embedder. Set EMBEDDER_PROVIDER=ollama');
|
|
258
|
+
* process.exit(1);
|
|
259
|
+
* }
|
|
260
|
+
* await autoEmbedInput(cleanedData, ['embedding'], embedder);
|
|
261
|
+
* }
|
|
262
|
+
*
|
|
263
|
+
* @param vectorFieldNames - Names of vector embedding fields detected at codegen time
|
|
264
|
+
*/
|
|
265
|
+
function buildAutoEmbedInputBlock(vectorFieldNames) {
|
|
266
|
+
const fieldNamesArray = t.arrayExpression(vectorFieldNames.map((n) => t.stringLiteral(n)));
|
|
267
|
+
const embedderDecl = t.variableDeclaration('const', [
|
|
268
|
+
t.variableDeclarator(t.identifier('embedder'), t.callExpression(t.identifier('resolveEmbedder'), [])),
|
|
269
|
+
]);
|
|
270
|
+
const noEmbedderCheck = t.ifStatement(t.unaryExpression('!', t.identifier('embedder')), t.blockStatement([
|
|
271
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('error')), [
|
|
272
|
+
t.stringLiteral('--auto-embed requires an embedder. Set EMBEDDER_PROVIDER=ollama (and optionally EMBEDDER_MODEL, EMBEDDER_BASE_URL).'),
|
|
273
|
+
])),
|
|
274
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('process'), t.identifier('exit')), [t.numericLiteral(1)])),
|
|
275
|
+
]));
|
|
276
|
+
const autoEmbedCall = t.awaitExpression(t.callExpression(t.identifier('autoEmbedInput'), [
|
|
277
|
+
t.identifier('cleanedData'),
|
|
278
|
+
fieldNamesArray,
|
|
279
|
+
t.identifier('embedder'),
|
|
280
|
+
]));
|
|
281
|
+
return t.ifStatement(t.memberExpression(t.identifier('argv'), t.stringLiteral('auto-embed'), true), t.blockStatement([
|
|
282
|
+
embedderDecl,
|
|
283
|
+
noEmbedderCheck,
|
|
284
|
+
t.expressionStatement(autoEmbedCall),
|
|
285
|
+
]));
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Build the FindManyArgs type instantiation for a table:
|
|
289
|
+
* FindManyArgs<SelectType, FilterType, ConditionType, OrderByType> & { select: SelectType }
|
|
290
|
+
*
|
|
291
|
+
* The intersection with { select: SelectType } makes select required,
|
|
292
|
+
* matching what the ORM's findMany method expects. parseFindManyArgs
|
|
293
|
+
* always sets select at runtime (from defaultSelect or --select flag).
|
|
294
|
+
*/
|
|
295
|
+
function buildFindManyArgsType(table, conditionEnabled) {
|
|
296
|
+
const { typeName } = (0, utils_1.getTableNames)(table);
|
|
297
|
+
const selectTypeName = `${typeName}Select`;
|
|
298
|
+
const whereTypeName = (0, utils_1.getFilterTypeName)(table);
|
|
299
|
+
const conditionTypeName = conditionEnabled ? (0, utils_1.getConditionTypeName)(table) : undefined;
|
|
300
|
+
const orderByTypeName = (0, utils_1.getOrderByTypeName)(table);
|
|
301
|
+
const findManyType = t.tsTypeReference(t.identifier('FindManyArgs'), t.tsTypeParameterInstantiation([
|
|
302
|
+
t.tsTypeReference(t.identifier(selectTypeName)),
|
|
303
|
+
t.tsTypeReference(t.identifier(whereTypeName)),
|
|
304
|
+
conditionTypeName
|
|
305
|
+
? t.tsTypeReference(t.identifier(conditionTypeName))
|
|
306
|
+
: t.tsNeverKeyword(),
|
|
307
|
+
t.tsTypeReference(t.identifier(orderByTypeName)),
|
|
308
|
+
]));
|
|
309
|
+
// Intersect with { select: SelectType } to make select required
|
|
310
|
+
return t.tsIntersectionType([
|
|
311
|
+
findManyType,
|
|
312
|
+
t.tsTypeLiteral([
|
|
313
|
+
Object.assign(t.tsPropertySignature(t.identifier('select'), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(selectTypeName)))), { optional: false }),
|
|
314
|
+
]),
|
|
315
|
+
]);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Build the FindFirstArgs type instantiation for a table:
|
|
319
|
+
* FindFirstArgs<SelectType, FilterType, ConditionType> & { select: SelectType }
|
|
320
|
+
*
|
|
321
|
+
* The intersection with { select: SelectType } makes select required,
|
|
322
|
+
* matching what the ORM's findFirst method expects.
|
|
323
|
+
*/
|
|
324
|
+
function buildFindFirstArgsType(table, conditionEnabled) {
|
|
325
|
+
const { typeName } = (0, utils_1.getTableNames)(table);
|
|
326
|
+
const selectTypeName = `${typeName}Select`;
|
|
327
|
+
const whereTypeName = (0, utils_1.getFilterTypeName)(table);
|
|
328
|
+
const conditionTypeName = conditionEnabled ? (0, utils_1.getConditionTypeName)(table) : undefined;
|
|
329
|
+
const findFirstType = t.tsTypeReference(t.identifier('FindFirstArgs'), t.tsTypeParameterInstantiation([
|
|
330
|
+
t.tsTypeReference(t.identifier(selectTypeName)),
|
|
331
|
+
t.tsTypeReference(t.identifier(whereTypeName)),
|
|
332
|
+
conditionTypeName
|
|
333
|
+
? t.tsTypeReference(t.identifier(conditionTypeName))
|
|
334
|
+
: t.tsNeverKeyword(),
|
|
335
|
+
]));
|
|
336
|
+
// Intersect with { select: SelectType } to make select required
|
|
337
|
+
return t.tsIntersectionType([
|
|
338
|
+
findFirstType,
|
|
339
|
+
t.tsTypeLiteral([
|
|
340
|
+
Object.assign(t.tsPropertySignature(t.identifier('select'), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(selectTypeName)))), { optional: false }),
|
|
341
|
+
]),
|
|
342
|
+
]);
|
|
343
|
+
}
|
|
344
|
+
function buildListHandler(table, vectorFieldNames, targetName, typeRegistry, conditionEnabled = false) {
|
|
206
345
|
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
207
346
|
const defaultSelectObj = buildSelectObject(table, typeRegistry);
|
|
208
347
|
// --- Build the try body ---
|
|
@@ -211,13 +350,23 @@ function buildListHandler(table, targetName, typeRegistry) {
|
|
|
211
350
|
tryBody.push(t.variableDeclaration('const', [
|
|
212
351
|
t.variableDeclarator(t.identifier('defaultSelect'), defaultSelectObj),
|
|
213
352
|
]));
|
|
214
|
-
// const findManyArgs = parseFindManyArgs(argv, defaultSelect);
|
|
215
|
-
|
|
216
|
-
|
|
353
|
+
// const findManyArgs = parseFindManyArgs<FindManyArgs<...>>(argv, defaultSelect);
|
|
354
|
+
{
|
|
355
|
+
const callExpr = t.callExpression(t.identifier('parseFindManyArgs'), [
|
|
217
356
|
t.identifier('argv'),
|
|
218
357
|
t.identifier('defaultSelect'),
|
|
219
|
-
])
|
|
220
|
-
|
|
358
|
+
]);
|
|
359
|
+
callExpr.typeParameters = t.tsTypeParameterInstantiation([
|
|
360
|
+
buildFindManyArgsType(table, conditionEnabled),
|
|
361
|
+
]);
|
|
362
|
+
tryBody.push(t.variableDeclaration('const', [
|
|
363
|
+
t.variableDeclarator(t.identifier('findManyArgs'), callExpr),
|
|
364
|
+
]));
|
|
365
|
+
}
|
|
366
|
+
// Auto-embed vector fields in the where clause when --auto-embed is passed
|
|
367
|
+
if (vectorFieldNames.length > 0) {
|
|
368
|
+
tryBody.push(buildAutoEmbedBlock(t.memberExpression(t.identifier('findManyArgs'), t.identifier('where')), vectorFieldNames, true));
|
|
369
|
+
}
|
|
221
370
|
tryBody.push(buildGetClientStatement(targetName));
|
|
222
371
|
// const result = await client.<singular>.findMany(findManyArgs).execute();
|
|
223
372
|
tryBody.push(t.variableDeclaration('const', [
|
|
@@ -234,10 +383,10 @@ function buildListHandler(table, targetName, typeRegistry) {
|
|
|
234
383
|
}
|
|
235
384
|
/**
|
|
236
385
|
* Build a `handleFindFirst` function — CLI equivalent of the TS SDK's findFirst().
|
|
237
|
-
* Accepts --
|
|
386
|
+
* Accepts --select, --where.<field>.<op>, --condition.<field>.<op> flags.
|
|
238
387
|
* Internally calls findMany with first:1 and returns a single record (or null).
|
|
239
388
|
*/
|
|
240
|
-
function buildFindFirstHandler(table, targetName, typeRegistry) {
|
|
389
|
+
function buildFindFirstHandler(table, targetName, typeRegistry, conditionEnabled = false) {
|
|
241
390
|
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
242
391
|
const defaultSelectObj = buildSelectObject(table, typeRegistry);
|
|
243
392
|
const tryBody = [];
|
|
@@ -245,13 +394,19 @@ function buildFindFirstHandler(table, targetName, typeRegistry) {
|
|
|
245
394
|
tryBody.push(t.variableDeclaration('const', [
|
|
246
395
|
t.variableDeclarator(t.identifier('defaultSelect'), defaultSelectObj),
|
|
247
396
|
]));
|
|
248
|
-
// const findFirstArgs = parseFindFirstArgs(argv, defaultSelect);
|
|
249
|
-
|
|
250
|
-
|
|
397
|
+
// const findFirstArgs = parseFindFirstArgs<FindFirstArgs<...>>(argv, defaultSelect);
|
|
398
|
+
{
|
|
399
|
+
const callExpr = t.callExpression(t.identifier('parseFindFirstArgs'), [
|
|
251
400
|
t.identifier('argv'),
|
|
252
401
|
t.identifier('defaultSelect'),
|
|
253
|
-
])
|
|
254
|
-
|
|
402
|
+
]);
|
|
403
|
+
callExpr.typeParameters = t.tsTypeParameterInstantiation([
|
|
404
|
+
buildFindFirstArgsType(table, conditionEnabled),
|
|
405
|
+
]);
|
|
406
|
+
tryBody.push(t.variableDeclaration('const', [
|
|
407
|
+
t.variableDeclarator(t.identifier('findFirstArgs'), callExpr),
|
|
408
|
+
]));
|
|
409
|
+
}
|
|
255
410
|
tryBody.push(buildGetClientStatement(targetName));
|
|
256
411
|
// const result = await client.<singular>.findFirst(findFirstArgs).execute();
|
|
257
412
|
tryBody.push(t.variableDeclaration('const', [
|
|
@@ -270,9 +425,9 @@ function buildFindFirstHandler(table, targetName, typeRegistry) {
|
|
|
270
425
|
* Build a `handleSearch` function for tables with search-capable fields.
|
|
271
426
|
* Extracts the first positional arg as the query string and auto-builds a
|
|
272
427
|
* `where` clause that targets all detected search fields (tsvector, BM25,
|
|
273
|
-
* trigram, vector embedding). Supports --limit, --offset, --
|
|
428
|
+
* trigram, vector embedding). Supports --limit, --offset, --select, --orderBy.
|
|
274
429
|
*/
|
|
275
|
-
function buildSearchHandler(table, specialGroups, targetName, typeRegistry) {
|
|
430
|
+
function buildSearchHandler(table, specialGroups, vectorFieldNames, targetName, typeRegistry, conditionEnabled = false) {
|
|
276
431
|
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
277
432
|
const defaultSelectObj = buildSelectObject(table, typeRegistry);
|
|
278
433
|
const tryBody = [];
|
|
@@ -288,7 +443,7 @@ function buildSearchHandler(table, specialGroups, targetName, typeRegistry) {
|
|
|
288
443
|
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('process'), t.identifier('exit')), [t.numericLiteral(1)])),
|
|
289
444
|
])));
|
|
290
445
|
// Build the where clause properties from detected search fields
|
|
291
|
-
// e.g. { tsvContent: { query }, bm25Body: { query }, trgmTitle: { value: query, threshold: 0.3 }, vectorEmbedding: {
|
|
446
|
+
// e.g. { tsvContent: { query }, bm25Body: { query }, trgmTitle: { value: query, threshold: 0.3 }, vectorEmbedding: { vector: query } }
|
|
292
447
|
const whereProps = [];
|
|
293
448
|
for (const group of specialGroups) {
|
|
294
449
|
for (const field of group.fields) {
|
|
@@ -318,9 +473,10 @@ function buildSearchHandler(table, specialGroups, targetName, typeRegistry) {
|
|
|
318
473
|
])));
|
|
319
474
|
}
|
|
320
475
|
else if (group.category === 'embedding') {
|
|
321
|
-
// Vector embedding field: {
|
|
476
|
+
// Vector embedding field: { vector: query }
|
|
477
|
+
// When --auto-embed is used, autoEmbedWhere will convert the text to a vector
|
|
322
478
|
whereProps.push(t.objectProperty(t.identifier(field.name), t.objectExpression([
|
|
323
|
-
t.objectProperty(t.identifier('
|
|
479
|
+
t.objectProperty(t.identifier('vector'), t.identifier('query')),
|
|
324
480
|
])));
|
|
325
481
|
}
|
|
326
482
|
}
|
|
@@ -329,18 +485,28 @@ function buildSearchHandler(table, specialGroups, targetName, typeRegistry) {
|
|
|
329
485
|
tryBody.push(t.variableDeclaration('const', [
|
|
330
486
|
t.variableDeclarator(t.identifier('searchWhere'), t.objectExpression(whereProps)),
|
|
331
487
|
]));
|
|
488
|
+
// Auto-embed vector fields in the where clause when --auto-embed is passed
|
|
489
|
+
if (vectorFieldNames.length > 0) {
|
|
490
|
+
tryBody.push(buildAutoEmbedBlock(t.identifier('searchWhere'), vectorFieldNames, false));
|
|
491
|
+
}
|
|
332
492
|
// const defaultSelect = { ... };
|
|
333
493
|
tryBody.push(t.variableDeclaration('const', [
|
|
334
494
|
t.variableDeclarator(t.identifier('defaultSelect'), defaultSelectObj),
|
|
335
495
|
]));
|
|
336
|
-
// const findManyArgs = parseFindManyArgs(argv, defaultSelect, searchWhere);
|
|
337
|
-
|
|
338
|
-
|
|
496
|
+
// const findManyArgs = parseFindManyArgs<FindManyArgs<...>>(argv, defaultSelect, searchWhere);
|
|
497
|
+
{
|
|
498
|
+
const callExpr = t.callExpression(t.identifier('parseFindManyArgs'), [
|
|
339
499
|
t.identifier('argv'),
|
|
340
500
|
t.identifier('defaultSelect'),
|
|
341
501
|
t.identifier('searchWhere'),
|
|
342
|
-
])
|
|
343
|
-
|
|
502
|
+
]);
|
|
503
|
+
callExpr.typeParameters = t.tsTypeParameterInstantiation([
|
|
504
|
+
buildFindManyArgsType(table, conditionEnabled),
|
|
505
|
+
]);
|
|
506
|
+
tryBody.push(t.variableDeclaration('const', [
|
|
507
|
+
t.variableDeclarator(t.identifier('findManyArgs'), callExpr),
|
|
508
|
+
]));
|
|
509
|
+
}
|
|
344
510
|
tryBody.push(buildGetClientStatement(targetName));
|
|
345
511
|
// const result = await client.<singular>.findMany(findManyArgs).execute();
|
|
346
512
|
tryBody.push(t.variableDeclaration('const', [
|
|
@@ -412,7 +578,7 @@ function getFieldsWithDefaults(table, typeRegistry) {
|
|
|
412
578
|
}
|
|
413
579
|
return fieldsWithDefaults;
|
|
414
580
|
}
|
|
415
|
-
function buildMutationHandler(table, operation, targetName, typeRegistry, ormTypes) {
|
|
581
|
+
function buildMutationHandler(table, operation, vectorFieldNames, targetName, typeRegistry, ormTypes) {
|
|
416
582
|
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
417
583
|
const pkFields = (0, utils_1.getPrimaryKeyInfo)(table);
|
|
418
584
|
const pk = pkFields[0];
|
|
@@ -540,6 +706,11 @@ function buildMutationHandler(table, operation, targetName, typeRegistry, ormTyp
|
|
|
540
706
|
tryBody.push(t.variableDeclaration('const', [
|
|
541
707
|
t.variableDeclarator(t.identifier('cleanedData'), cleanedDataExpr),
|
|
542
708
|
]));
|
|
709
|
+
// Inject --auto-embed block for create/update when table has vector fields.
|
|
710
|
+
// Converts text strings in vector fields to embeddings before the ORM call.
|
|
711
|
+
if (vectorFieldNames.length > 0) {
|
|
712
|
+
tryBody.push(buildAutoEmbedInputBlock(vectorFieldNames));
|
|
713
|
+
}
|
|
543
714
|
}
|
|
544
715
|
tryBody.push(buildGetClientStatement(targetName), t.variableDeclaration('const', [
|
|
545
716
|
t.variableDeclarator(t.identifier('result'), t.awaitExpression(buildOrmCall(singularName, operation, ormArgs))),
|
|
@@ -554,8 +725,8 @@ function buildMutationHandler(table, operation, targetName, typeRegistry, ormTyp
|
|
|
554
725
|
]), false, true);
|
|
555
726
|
}
|
|
556
727
|
function generateTableCommand(table, options) {
|
|
557
|
-
const { singularName } = (0, utils_1.getTableNames)(table);
|
|
558
|
-
const commandName = (0,
|
|
728
|
+
const { singularName, typeName } = (0, utils_1.getTableNames)(table);
|
|
729
|
+
const commandName = (0, inflekt_1.toKebabCase)(singularName);
|
|
559
730
|
const statements = [];
|
|
560
731
|
const executorPath = options?.executorImportPath ?? '../executor';
|
|
561
732
|
statements.push(createImportDeclaration('inquirerer', [
|
|
@@ -579,7 +750,25 @@ function generateTableCommand(table, options) {
|
|
|
579
750
|
const inputTypesPath = options?.targetName
|
|
580
751
|
? `../../../orm/input-types`
|
|
581
752
|
: `../../orm/input-types`;
|
|
582
|
-
|
|
753
|
+
// Import table-specific ORM types for generic type parameters on parseFindManyArgs/parseFindFirstArgs
|
|
754
|
+
const selectTypeName = `${typeName}Select`;
|
|
755
|
+
const whereTypeName = (0, utils_1.getFilterTypeName)(table);
|
|
756
|
+
const orderByTypeName = (0, utils_1.getOrderByTypeName)(table);
|
|
757
|
+
const conditionEnabled = options?.condition === true;
|
|
758
|
+
const conditionTypeName = conditionEnabled ? (0, utils_1.getConditionTypeName)(table) : undefined;
|
|
759
|
+
statements.push(createImportDeclaration(inputTypesPath, [
|
|
760
|
+
createInputTypeName,
|
|
761
|
+
patchTypeName,
|
|
762
|
+
selectTypeName,
|
|
763
|
+
whereTypeName,
|
|
764
|
+
...(conditionTypeName ? [conditionTypeName] : []),
|
|
765
|
+
orderByTypeName,
|
|
766
|
+
], true));
|
|
767
|
+
// Import FindManyArgs/FindFirstArgs from select-types for proper generic typing
|
|
768
|
+
const selectTypesPath = options?.targetName
|
|
769
|
+
? `../../../orm/select-types`
|
|
770
|
+
: `../../orm/select-types`;
|
|
771
|
+
statements.push(createImportDeclaration(selectTypesPath, ['FindManyArgs', 'FindFirstArgs'], true));
|
|
583
772
|
// Generate field schema for type coercion
|
|
584
773
|
// Use explicit FieldSchema type annotation so TS narrows string literals to FieldType
|
|
585
774
|
const fieldSchemaId = t.identifier('fieldSchema');
|
|
@@ -600,6 +789,21 @@ function generateTableCommand(table, options) {
|
|
|
600
789
|
// Detect whether this table has search-capable fields (tsvector, BM25, trgm, vector embedding)
|
|
601
790
|
const specialGroups = (0, docs_utils_1.categorizeSpecialFields)(table, options?.typeRegistry);
|
|
602
791
|
const hasSearchFields = specialGroups.some((g) => g.category === 'search' || g.category === 'embedding');
|
|
792
|
+
// Collect vector embedding field names for --auto-embed support
|
|
793
|
+
const vectorFieldNames = [];
|
|
794
|
+
for (const group of specialGroups) {
|
|
795
|
+
if (group.category === 'embedding') {
|
|
796
|
+
for (const field of group.fields) {
|
|
797
|
+
vectorFieldNames.push(field.name);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
const hasEmbeddings = vectorFieldNames.length > 0;
|
|
802
|
+
// Import embedder functions when table has vector embedding fields
|
|
803
|
+
if (hasEmbeddings) {
|
|
804
|
+
const embedderPath = options?.targetName ? '../../embedder' : '../embedder';
|
|
805
|
+
statements.push(createImportDeclaration(embedderPath, ['resolveEmbedder', 'autoEmbedWhere', 'autoEmbedInput']));
|
|
806
|
+
}
|
|
603
807
|
const subcommands = ['list', 'find-first'];
|
|
604
808
|
if (hasSearchFields)
|
|
605
809
|
subcommands.push('search');
|
|
@@ -625,11 +829,21 @@ function generateTableCommand(table, options) {
|
|
|
625
829
|
usageLines.push(` create Create a new ${singularName}`);
|
|
626
830
|
if (hasUpdate)
|
|
627
831
|
usageLines.push(` update Update an existing ${singularName}`);
|
|
832
|
+
if (hasEmbeddings) {
|
|
833
|
+
usageLines.push('', 'Create/Update Options:', ' --auto-embed Convert text values in vector fields to embeddings before saving');
|
|
834
|
+
}
|
|
628
835
|
if (hasDelete)
|
|
629
836
|
usageLines.push(` delete Delete a ${singularName}`);
|
|
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', ' --
|
|
837
|
+
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', ' --select <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:', ' --select <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
838
|
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', ' --
|
|
839
|
+
usageLines.push('Search Options:', ' <query> Search query string (required)', ' --limit <n> Max number of records to return', ' --offset <n> Number of records to skip', ' --select <fields> Comma-separated list of fields to return', ' --orderBy <values> Comma-separated list of ordering values');
|
|
840
|
+
if (hasEmbeddings) {
|
|
841
|
+
usageLines.push(' --auto-embed Convert text queries to vectors via configured embedder');
|
|
842
|
+
}
|
|
843
|
+
usageLines.push('');
|
|
844
|
+
}
|
|
845
|
+
if (hasEmbeddings) {
|
|
846
|
+
usageLines.push('Embedding Options (for --auto-embed):', ' Set EMBEDDER_PROVIDER=ollama to enable text-to-vector embedding.', ' Optional: EMBEDDER_MODEL (default: nomic-embed-text)', ' Optional: EMBEDDER_BASE_URL (default: http://localhost:11434)', '');
|
|
633
847
|
}
|
|
634
848
|
usageLines.push(' --help, -h Show this help message', '');
|
|
635
849
|
statements.push(t.variableDeclaration('const', [
|
|
@@ -692,17 +906,17 @@ function generateTableCommand(table, options) {
|
|
|
692
906
|
]), false, true));
|
|
693
907
|
const tn = options?.targetName;
|
|
694
908
|
const ormTypes = { createInputTypeName, patchTypeName, innerFieldName };
|
|
695
|
-
statements.push(buildListHandler(table, tn, options?.typeRegistry));
|
|
696
|
-
statements.push(buildFindFirstHandler(table, tn, options?.typeRegistry));
|
|
909
|
+
statements.push(buildListHandler(table, vectorFieldNames, tn, options?.typeRegistry, conditionEnabled));
|
|
910
|
+
statements.push(buildFindFirstHandler(table, tn, options?.typeRegistry, conditionEnabled));
|
|
697
911
|
if (hasSearchFields)
|
|
698
|
-
statements.push(buildSearchHandler(table, specialGroups, tn, options?.typeRegistry));
|
|
912
|
+
statements.push(buildSearchHandler(table, specialGroups, vectorFieldNames, tn, options?.typeRegistry, conditionEnabled));
|
|
699
913
|
if (hasGet)
|
|
700
914
|
statements.push(buildGetHandler(table, tn, options?.typeRegistry));
|
|
701
|
-
statements.push(buildMutationHandler(table, 'create', tn, options?.typeRegistry, ormTypes));
|
|
915
|
+
statements.push(buildMutationHandler(table, 'create', vectorFieldNames, tn, options?.typeRegistry, ormTypes));
|
|
702
916
|
if (hasUpdate)
|
|
703
|
-
statements.push(buildMutationHandler(table, 'update', tn, options?.typeRegistry, ormTypes));
|
|
917
|
+
statements.push(buildMutationHandler(table, 'update', vectorFieldNames, tn, options?.typeRegistry, ormTypes));
|
|
704
918
|
if (hasDelete)
|
|
705
|
-
statements.push(buildMutationHandler(table, 'delete', tn, options?.typeRegistry, ormTypes));
|
|
919
|
+
statements.push(buildMutationHandler(table, 'delete', vectorFieldNames, tn, options?.typeRegistry, ormTypes));
|
|
706
920
|
const header = (0, utils_1.getGeneratedFileHeader)(`CLI commands for ${table.name}`);
|
|
707
921
|
const code = (0, babel_ast_1.generateCode)(statements);
|
|
708
922
|
return {
|
|
@@ -25,3 +25,11 @@ export declare function generateNodeFetchFile(): GeneratedFile;
|
|
|
25
25
|
* provide their own entry point with custom configuration.
|
|
26
26
|
*/
|
|
27
27
|
export declare function generateEntryPointFile(): GeneratedFile;
|
|
28
|
+
/**
|
|
29
|
+
* Generate an embedder.ts file with pluggable text-to-vector embedding.
|
|
30
|
+
*
|
|
31
|
+
* Provides a runtime embedder registry using @agentic-kit/ollama so that
|
|
32
|
+
* CLI search and list commands can convert text queries into vector arrays
|
|
33
|
+
* for pgvector similarity search when --auto-embed is passed.
|
|
34
|
+
*/
|
|
35
|
+
export declare function generateEmbedderFile(): GeneratedFile;
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.generateUtilsFile = generateUtilsFile;
|
|
37
37
|
exports.generateNodeFetchFile = generateNodeFetchFile;
|
|
38
38
|
exports.generateEntryPointFile = generateEntryPointFile;
|
|
39
|
+
exports.generateEmbedderFile = generateEmbedderFile;
|
|
39
40
|
const fs = __importStar(require("fs"));
|
|
40
41
|
const path = __importStar(require("path"));
|
|
41
42
|
const utils_1 = require("../utils");
|
|
@@ -105,3 +106,16 @@ function generateEntryPointFile() {
|
|
|
105
106
|
content: readTemplateFile('cli-entry.ts', 'CLI entry point'),
|
|
106
107
|
};
|
|
107
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Generate an embedder.ts file with pluggable text-to-vector embedding.
|
|
111
|
+
*
|
|
112
|
+
* Provides a runtime embedder registry using @agentic-kit/ollama so that
|
|
113
|
+
* CLI search and list commands can convert text queries into vector arrays
|
|
114
|
+
* for pgvector similarity search when --auto-embed is passed.
|
|
115
|
+
*/
|
|
116
|
+
function generateEmbedderFile() {
|
|
117
|
+
return {
|
|
118
|
+
fileName: 'embedder.ts',
|
|
119
|
+
content: readTemplateFile('embedder.ts', 'CLI embedder — pluggable text-to-vector embedding for search commands'),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
@@ -65,6 +65,23 @@ export declare function buildSpecialFieldsMarkdown(groups: SpecialFieldGroup[]):
|
|
|
65
65
|
* Returns empty array when there are no special fields.
|
|
66
66
|
*/
|
|
67
67
|
export declare function buildSpecialFieldsPlain(groups: SpecialFieldGroup[]): string[];
|
|
68
|
+
export interface SearchExample {
|
|
69
|
+
description: string;
|
|
70
|
+
code: string[];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build concrete, field-specific CLI examples for tables with search fields.
|
|
74
|
+
* Uses the same field-name derivation logic as buildSearchHandler in
|
|
75
|
+
* table-command-generator.ts so the examples match the actual generated code.
|
|
76
|
+
*
|
|
77
|
+
* Returns an empty array when the table has no search/embedding fields.
|
|
78
|
+
*/
|
|
79
|
+
export declare function buildSearchExamples(specialGroups: SpecialFieldGroup[], toolName: string, cmd: string): SearchExample[];
|
|
80
|
+
/**
|
|
81
|
+
* Build markdown lines for search-specific examples in README-style docs.
|
|
82
|
+
* Returns empty array when there are no search examples.
|
|
83
|
+
*/
|
|
84
|
+
export declare function buildSearchExamplesMarkdown(specialGroups: SpecialFieldGroup[], toolName: string, cmd: string): string[];
|
|
68
85
|
/**
|
|
69
86
|
* Represents a flattened argument for docs/skills generation.
|
|
70
87
|
* INPUT_OBJECT args are expanded to dot-notation fields.
|
|
@@ -10,6 +10,8 @@ exports.getSearchFields = getSearchFields;
|
|
|
10
10
|
exports.categorizeSpecialFields = categorizeSpecialFields;
|
|
11
11
|
exports.buildSpecialFieldsMarkdown = buildSpecialFieldsMarkdown;
|
|
12
12
|
exports.buildSpecialFieldsPlain = buildSpecialFieldsPlain;
|
|
13
|
+
exports.buildSearchExamples = buildSearchExamples;
|
|
14
|
+
exports.buildSearchExamplesMarkdown = buildSearchExamplesMarkdown;
|
|
13
15
|
exports.cleanTypeName = cleanTypeName;
|
|
14
16
|
exports.flattenArgs = flattenArgs;
|
|
15
17
|
exports.flattenedArgsToFlags = flattenedArgsToFlags;
|
|
@@ -255,6 +257,131 @@ function buildSpecialFieldsPlain(groups) {
|
|
|
255
257
|
}
|
|
256
258
|
return lines;
|
|
257
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* Build concrete, field-specific CLI examples for tables with search fields.
|
|
262
|
+
* Uses the same field-name derivation logic as buildSearchHandler in
|
|
263
|
+
* table-command-generator.ts so the examples match the actual generated code.
|
|
264
|
+
*
|
|
265
|
+
* Returns an empty array when the table has no search/embedding fields.
|
|
266
|
+
*/
|
|
267
|
+
function buildSearchExamples(specialGroups, toolName, cmd) {
|
|
268
|
+
const examples = [];
|
|
269
|
+
const scoreFields = [];
|
|
270
|
+
for (const group of specialGroups) {
|
|
271
|
+
for (const field of group.fields) {
|
|
272
|
+
// tsvector (FullText scalar) — where input uses the column name directly
|
|
273
|
+
if (field.type.gqlType === 'FullText' && !field.type.isArray) {
|
|
274
|
+
examples.push({
|
|
275
|
+
description: `Full-text search via tsvector (\`${field.name}\`)`,
|
|
276
|
+
code: [
|
|
277
|
+
`${toolName} ${cmd} list --where.${field.name} "search query" --select title,tsvRank`,
|
|
278
|
+
],
|
|
279
|
+
});
|
|
280
|
+
scoreFields.push('tsvRank');
|
|
281
|
+
}
|
|
282
|
+
// BM25 computed score — bodyBm25Score → bm25Body
|
|
283
|
+
if (/Bm25Score$/.test(field.name)) {
|
|
284
|
+
const baseName = field.name.replace(/Bm25Score$/, '');
|
|
285
|
+
const inputName = `bm25${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}`;
|
|
286
|
+
examples.push({
|
|
287
|
+
description: `BM25 keyword search via \`${inputName}\``,
|
|
288
|
+
code: [
|
|
289
|
+
`${toolName} ${cmd} list --where.${inputName}.query "search query" --select title,${field.name}`,
|
|
290
|
+
],
|
|
291
|
+
});
|
|
292
|
+
scoreFields.push(field.name);
|
|
293
|
+
}
|
|
294
|
+
// Trigram similarity — titleTrgmSimilarity → trgmTitle
|
|
295
|
+
if (/TrgmSimilarity$/.test(field.name)) {
|
|
296
|
+
const baseName = field.name.replace(/TrgmSimilarity$/, '');
|
|
297
|
+
const inputName = `trgm${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}`;
|
|
298
|
+
examples.push({
|
|
299
|
+
description: `Fuzzy search via trigram similarity (\`${inputName}\`)`,
|
|
300
|
+
code: [
|
|
301
|
+
`${toolName} ${cmd} list --where.${inputName}.value "approximate query" --where.${inputName}.threshold 0.3 --select title,${field.name}`,
|
|
302
|
+
],
|
|
303
|
+
});
|
|
304
|
+
scoreFields.push(field.name);
|
|
305
|
+
}
|
|
306
|
+
// pgvector embedding — uses column name, with --auto-embed for text-to-vector
|
|
307
|
+
if (group.category === 'embedding') {
|
|
308
|
+
examples.push({
|
|
309
|
+
description: `Vector similarity search via \`${field.name}\` (manual vector)`,
|
|
310
|
+
code: [
|
|
311
|
+
`# Pass a pre-computed vector array via dot-notation`,
|
|
312
|
+
`${toolName} ${cmd} list --where.${field.name}.vector '[0.1,0.2,0.3]' --where.${field.name}.distance 1.0 --select title,${field.name}VectorDistance`,
|
|
313
|
+
],
|
|
314
|
+
});
|
|
315
|
+
examples.push({
|
|
316
|
+
description: `Vector semantic search via \`${field.name}\` with --auto-embed`,
|
|
317
|
+
code: [
|
|
318
|
+
`# --auto-embed converts text to vectors using the configured embedder (e.g. Ollama nomic-embed-text)`,
|
|
319
|
+
`EMBEDDER_PROVIDER=ollama ${toolName} ${cmd} search "semantic query" --auto-embed --select title,${field.name}VectorDistance`,
|
|
320
|
+
`EMBEDDER_PROVIDER=ollama ${toolName} ${cmd} list --where.${field.name}.vector "semantic query" --auto-embed --select title,${field.name}VectorDistance`,
|
|
321
|
+
],
|
|
322
|
+
});
|
|
323
|
+
examples.push({
|
|
324
|
+
description: `Create/update with auto-embedded \`${field.name}\` via --auto-embed`,
|
|
325
|
+
code: [
|
|
326
|
+
`# --auto-embed on create/update converts text strings in vector fields to embeddings before saving`,
|
|
327
|
+
`EMBEDDER_PROVIDER=ollama ${toolName} ${cmd} create --${field.name} "text to embed" --auto-embed`,
|
|
328
|
+
`EMBEDDER_PROVIDER=ollama ${toolName} ${cmd} update --${field.name} "new text to embed" --auto-embed`,
|
|
329
|
+
],
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
// searchScore — composite blend field, useful for ordering
|
|
333
|
+
if (field.name === 'searchScore') {
|
|
334
|
+
scoreFields.push('searchScore');
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
// Composite fullTextSearch example (dispatches to all text adapters)
|
|
339
|
+
const hasTextSearch = specialGroups.some((g) => g.category === 'search' && g.fields.some((f) => f.type.gqlType === 'FullText' || /TrgmSimilarity$/.test(f.name) || /Bm25Score$/.test(f.name)));
|
|
340
|
+
if (hasTextSearch) {
|
|
341
|
+
const fieldsArg = scoreFields.length > 0
|
|
342
|
+
? `title,${[...new Set(scoreFields)].join(',')}`
|
|
343
|
+
: 'title';
|
|
344
|
+
examples.push({
|
|
345
|
+
description: 'Composite search (fullTextSearch dispatches to all text adapters)',
|
|
346
|
+
code: [
|
|
347
|
+
`${toolName} ${cmd} list --where.fullTextSearch "search query" --select ${fieldsArg}`,
|
|
348
|
+
],
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
// Combined search + pagination + ordering example
|
|
352
|
+
if (examples.length > 0) {
|
|
353
|
+
examples.push({
|
|
354
|
+
description: 'Search with pagination and field projection',
|
|
355
|
+
code: [
|
|
356
|
+
`${toolName} ${cmd} list --where.fullTextSearch "query" --limit 10 --select id,title,searchScore`,
|
|
357
|
+
`${toolName} ${cmd} search "query" --limit 10 --select id,title,searchScore`,
|
|
358
|
+
],
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
return examples;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Build markdown lines for search-specific examples in README-style docs.
|
|
365
|
+
* Returns empty array when there are no search examples.
|
|
366
|
+
*/
|
|
367
|
+
function buildSearchExamplesMarkdown(specialGroups, toolName, cmd) {
|
|
368
|
+
const examples = buildSearchExamples(specialGroups, toolName, cmd);
|
|
369
|
+
if (examples.length === 0)
|
|
370
|
+
return [];
|
|
371
|
+
const lines = [];
|
|
372
|
+
lines.push('**Search Examples:**');
|
|
373
|
+
lines.push('');
|
|
374
|
+
for (const ex of examples) {
|
|
375
|
+
lines.push(`*${ex.description}:*`);
|
|
376
|
+
lines.push('```bash');
|
|
377
|
+
for (const c of ex.code) {
|
|
378
|
+
lines.push(c);
|
|
379
|
+
}
|
|
380
|
+
lines.push('```');
|
|
381
|
+
lines.push('');
|
|
382
|
+
}
|
|
383
|
+
return lines;
|
|
384
|
+
}
|
|
258
385
|
function unwrapNonNull(typeRef) {
|
|
259
386
|
if (typeRef.kind === 'NON_NULL' && typeRef.ofType) {
|
|
260
387
|
return { inner: typeRef.ofType, required: true };
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateHooksReadme = generateHooksReadme;
|
|
4
4
|
exports.generateHooksAgentsDocs = generateHooksAgentsDocs;
|
|
5
5
|
exports.generateHooksSkills = generateHooksSkills;
|
|
6
|
-
const
|
|
6
|
+
const inflekt_1 = require("inflekt");
|
|
7
7
|
const docs_utils_1 = require("./docs-utils");
|
|
8
8
|
const utils_1 = require("./utils");
|
|
9
9
|
function getCustomHookName(op) {
|
|
@@ -178,7 +178,7 @@ function generateHooksSkills(tables, customOperations, targetName, registry) {
|
|
|
178
178
|
const selectFields = scalarFields
|
|
179
179
|
.map((f) => `${f.name}: true`)
|
|
180
180
|
.join(', ');
|
|
181
|
-
const refName = (0,
|
|
181
|
+
const refName = (0, inflekt_1.toKebabCase)(singularName);
|
|
182
182
|
referenceNames.push(refName);
|
|
183
183
|
files.push({
|
|
184
184
|
fileName: `${skillName}/references/${refName}.md`,
|
|
@@ -229,7 +229,7 @@ function generateHooksSkills(tables, customOperations, targetName, registry) {
|
|
|
229
229
|
const callArgs = op.args.length > 0
|
|
230
230
|
? `{ ${op.args.map((a) => `${a.name}: ${(0, docs_utils_1.argPlaceholder)(a, registry)}`).join(', ')} }`
|
|
231
231
|
: '';
|
|
232
|
-
const refName = (0,
|
|
232
|
+
const refName = (0, inflekt_1.toKebabCase)(op.name);
|
|
233
233
|
referenceNames.push(refName);
|
|
234
234
|
files.push({
|
|
235
235
|
fileName: `${skillName}/references/${refName}.md`,
|