@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
package/core/codegen/index.js
CHANGED
|
@@ -97,7 +97,7 @@ function generate(options) {
|
|
|
97
97
|
hasInvalidation = true;
|
|
98
98
|
}
|
|
99
99
|
// Condition types (PostGraphile simple equality filters)
|
|
100
|
-
const conditionEnabled = config.codegen?.condition
|
|
100
|
+
const conditionEnabled = config.codegen?.condition === true;
|
|
101
101
|
// 4. Generate table-based query hooks (queries/*.ts)
|
|
102
102
|
const queryHooks = (0, queries_1.generateAllQueryHooks)(tables, {
|
|
103
103
|
reactQueryEnabled,
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateOrmReadme = generateOrmReadme;
|
|
4
4
|
exports.generateOrmAgentsDocs = generateOrmAgentsDocs;
|
|
5
5
|
exports.generateOrmSkills = generateOrmSkills;
|
|
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 generateOrmReadme(tables, customOperations, registry) {
|
|
@@ -169,7 +169,7 @@ function generateOrmSkills(tables, customOperations, targetName, registry) {
|
|
|
169
169
|
const pk = (0, utils_1.getPrimaryKeyInfo)(table)[0];
|
|
170
170
|
const editableFields = (0, docs_utils_1.getEditableFields)(table);
|
|
171
171
|
const modelName = (0, utils_1.lcFirst)(singularName);
|
|
172
|
-
const refName = (0,
|
|
172
|
+
const refName = (0, inflekt_1.toKebabCase)(singularName);
|
|
173
173
|
referenceNames.push(refName);
|
|
174
174
|
const ormSkillSpecialGroups = (0, docs_utils_1.categorizeSpecialFields)(table);
|
|
175
175
|
const ormSkillBaseDesc = table.description || `ORM operations for ${table.name} records`;
|
|
@@ -218,7 +218,7 @@ function generateOrmSkills(tables, customOperations, targetName, registry) {
|
|
|
218
218
|
const callArgs = op.args.length > 0
|
|
219
219
|
? `{ ${op.args.map((a) => `${a.name}: ${(0, docs_utils_1.argPlaceholder)(a, registry)}`).join(', ')} }`
|
|
220
220
|
: '';
|
|
221
|
-
const refName = (0,
|
|
221
|
+
const refName = (0, inflekt_1.toKebabCase)(op.name);
|
|
222
222
|
referenceNames.push(refName);
|
|
223
223
|
files.push({
|
|
224
224
|
fileName: `${skillName}/references/${refName}.md`,
|
|
@@ -13,7 +13,7 @@ const model_generator_1 = require("./model-generator");
|
|
|
13
13
|
function generateOrm(options) {
|
|
14
14
|
const { tables, customOperations, sharedTypesPath } = options;
|
|
15
15
|
const commentsEnabled = options.config.codegen?.comments !== false;
|
|
16
|
-
const conditionEnabled = options.config.codegen?.condition
|
|
16
|
+
const conditionEnabled = options.config.codegen?.condition === true;
|
|
17
17
|
const files = [];
|
|
18
18
|
// Use shared types when a sharedTypesPath is provided (unified output mode)
|
|
19
19
|
const useSharedTypes = !!sharedTypesPath;
|
|
@@ -1420,7 +1420,7 @@ function collectConditionExtraInputTypes(tables, typeRegistry) {
|
|
|
1420
1420
|
* Generate comprehensive input-types.ts file using Babel AST
|
|
1421
1421
|
*/
|
|
1422
1422
|
function generateInputTypesFile(typeRegistry, usedInputTypes, tables, usedPayloadTypes, comments = true, options) {
|
|
1423
|
-
const conditionEnabled = options?.condition
|
|
1423
|
+
const conditionEnabled = options?.condition === true;
|
|
1424
1424
|
const statements = [];
|
|
1425
1425
|
const tablesList = tables ?? [];
|
|
1426
1426
|
const hasTables = tablesList.length > 0;
|
|
@@ -104,7 +104,7 @@ function strictSelectGuard(selectTypeName) {
|
|
|
104
104
|
]));
|
|
105
105
|
}
|
|
106
106
|
function generateModelFile(table, _useSharedTypes, options, allTables) {
|
|
107
|
-
const conditionEnabled = options?.condition
|
|
107
|
+
const conditionEnabled = options?.condition === true;
|
|
108
108
|
const { typeName, singularName, pluralName } = (0, utils_1.getTableNames)(table);
|
|
109
109
|
const modelName = `${typeName}Model`;
|
|
110
110
|
const baseFileName = (0, utils_1.lcFirst)(typeName);
|
package/core/codegen/queries.js
CHANGED
|
@@ -49,7 +49,7 @@ const babel_ast_1 = require("./babel-ast");
|
|
|
49
49
|
const hooks_ast_1 = require("./hooks-ast");
|
|
50
50
|
const utils_1 = require("./utils");
|
|
51
51
|
function generateListQueryHook(table, options = {}) {
|
|
52
|
-
const { reactQueryEnabled = true, useCentralizedKeys = true, hasRelationships = false, condition: conditionEnabled =
|
|
52
|
+
const { reactQueryEnabled = true, useCentralizedKeys = true, hasRelationships = false, condition: conditionEnabled = false, } = options;
|
|
53
53
|
const { typeName, pluralName, singularName } = (0, utils_1.getTableNames)(table);
|
|
54
54
|
const hookName = (0, utils_1.getListQueryHookName)(table);
|
|
55
55
|
const queryName = (0, utils_1.getAllRowsQueryName)(table);
|
|
@@ -229,16 +229,16 @@ export function parseOrderByFlag(
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
/**
|
|
232
|
-
* Parse --
|
|
233
|
-
* e.g. --
|
|
232
|
+
* Parse --select flag into a select object, falling back to a default.
|
|
233
|
+
* e.g. --select id,name → { id: true, name: true }
|
|
234
234
|
*/
|
|
235
235
|
export function parseSelectFlag(
|
|
236
236
|
argv: Record<string, unknown>,
|
|
237
237
|
defaultSelect: Record<string, unknown>,
|
|
238
238
|
): Record<string, unknown> {
|
|
239
|
-
const
|
|
240
|
-
return typeof
|
|
241
|
-
? buildSelectFromPaths(
|
|
239
|
+
const raw = argv.select;
|
|
240
|
+
return typeof raw === 'string'
|
|
241
|
+
? buildSelectFromPaths(raw)
|
|
242
242
|
: defaultSelect;
|
|
243
243
|
}
|
|
244
244
|
|
|
@@ -252,11 +252,11 @@ export function parseSelectFlag(
|
|
|
252
252
|
* const findManyArgs = parseFindManyArgs(argv, { id: true, name: true });
|
|
253
253
|
* const result = await client.user.findMany(findManyArgs).execute();
|
|
254
254
|
*/
|
|
255
|
-
export function parseFindManyArgs(
|
|
255
|
+
export function parseFindManyArgs<T = Record<string, unknown>>(
|
|
256
256
|
argv: Record<string, unknown>,
|
|
257
257
|
defaultSelect: Record<string, unknown>,
|
|
258
258
|
extraWhere?: Record<string, unknown>,
|
|
259
|
-
):
|
|
259
|
+
): T {
|
|
260
260
|
const limit = parseIntFlag(argv, 'limit');
|
|
261
261
|
const last = parseIntFlag(argv, 'last');
|
|
262
262
|
const offset = parseIntFlag(argv, 'offset');
|
|
@@ -280,7 +280,7 @@ export function parseFindManyArgs(
|
|
|
280
280
|
...(where !== undefined ? { where } : {}),
|
|
281
281
|
...(condition !== undefined ? { condition } : {}),
|
|
282
282
|
...(orderBy !== undefined ? { orderBy } : {}),
|
|
283
|
-
};
|
|
283
|
+
} as unknown as T;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
/**
|
|
@@ -288,10 +288,10 @@ export function parseFindManyArgs(
|
|
|
288
288
|
* Like parseFindManyArgs but only includes select, where, and condition
|
|
289
289
|
* (no pagination flags — findFirst returns the first matching record).
|
|
290
290
|
*/
|
|
291
|
-
export function parseFindFirstArgs(
|
|
291
|
+
export function parseFindFirstArgs<T = Record<string, unknown>>(
|
|
292
292
|
argv: Record<string, unknown>,
|
|
293
293
|
defaultSelect: Record<string, unknown>,
|
|
294
|
-
):
|
|
294
|
+
): T {
|
|
295
295
|
const select = parseSelectFlag(argv, defaultSelect);
|
|
296
296
|
const parsed = unflattenDotNotation(argv);
|
|
297
297
|
const where = parsed.where;
|
|
@@ -301,7 +301,7 @@ export function parseFindFirstArgs(
|
|
|
301
301
|
select,
|
|
302
302
|
...(where !== undefined ? { where } : {}),
|
|
303
303
|
...(condition !== undefined ? { condition } : {}),
|
|
304
|
-
};
|
|
304
|
+
} as unknown as T;
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
export function buildSelectFromPaths(
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Embedder — pluggable text-to-vector embedding for CLI commands
|
|
3
|
+
*
|
|
4
|
+
* This is RUNTIME code that gets copied to generated output.
|
|
5
|
+
* Provides a pluggable system for registering embedding functions so that
|
|
6
|
+
* CLI commands can convert text queries into vector arrays for pgvector
|
|
7
|
+
* similarity search (list/search) and create/update vector fields inline.
|
|
8
|
+
*
|
|
9
|
+
* Configuration via appstash config or environment variables:
|
|
10
|
+
* embedder.provider = 'ollama' | 'custom'
|
|
11
|
+
* embedder.model = 'nomic-embed-text' (default)
|
|
12
|
+
* embedder.baseUrl = 'http://localhost:11434' (Ollama endpoint)
|
|
13
|
+
*
|
|
14
|
+
* Uses @agentic-kit/ollama for the built-in Ollama provider.
|
|
15
|
+
*
|
|
16
|
+
* NOTE: This file is read at codegen time and written to output.
|
|
17
|
+
* Any changes here will affect all generated CLI embedder modules.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import OllamaClient from '@agentic-kit/ollama';
|
|
21
|
+
|
|
22
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
export type EmbedderFunction = (text: string) => Promise<number[]>;
|
|
25
|
+
|
|
26
|
+
export interface EmbedderConfig {
|
|
27
|
+
/** Provider name: 'ollama' or 'custom' */
|
|
28
|
+
provider: string;
|
|
29
|
+
/** Model identifier (e.g. 'nomic-embed-text') */
|
|
30
|
+
model?: string;
|
|
31
|
+
/** Base URL for the provider (e.g. 'http://localhost:11434' for Ollama) */
|
|
32
|
+
baseUrl?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ─── Built-in Ollama Provider ────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
function createOllamaEmbedder(
|
|
38
|
+
baseUrl: string = 'http://localhost:11434',
|
|
39
|
+
model: string = 'nomic-embed-text',
|
|
40
|
+
): EmbedderFunction {
|
|
41
|
+
const client = new OllamaClient(baseUrl);
|
|
42
|
+
return async (text: string): Promise<number[]> => {
|
|
43
|
+
return client.generateEmbedding(text, model);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ─── Embedder Resolution ─────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Resolve an embedder function from environment variables or appstash config.
|
|
51
|
+
*
|
|
52
|
+
* Resolution order:
|
|
53
|
+
* 1. EMBEDDER_PROVIDER env var (+ EMBEDDER_MODEL, EMBEDDER_BASE_URL)
|
|
54
|
+
* 2. appstash config keys: embedder.provider, embedder.model, embedder.baseUrl
|
|
55
|
+
* 3. null (no embedder configured)
|
|
56
|
+
*
|
|
57
|
+
* @param store - Optional appstash config store for reading persisted config
|
|
58
|
+
* @returns An EmbedderFunction or null if no embedder is configured
|
|
59
|
+
*/
|
|
60
|
+
export function resolveEmbedder(
|
|
61
|
+
store?: { getVar: (key: string) => string | undefined },
|
|
62
|
+
): EmbedderFunction | null {
|
|
63
|
+
// 1. Check environment variables first
|
|
64
|
+
const envProvider = process.env.EMBEDDER_PROVIDER;
|
|
65
|
+
if (envProvider) {
|
|
66
|
+
return buildEmbedder({
|
|
67
|
+
provider: envProvider,
|
|
68
|
+
model: process.env.EMBEDDER_MODEL,
|
|
69
|
+
baseUrl: process.env.EMBEDDER_BASE_URL,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 2. Check appstash config
|
|
74
|
+
if (store) {
|
|
75
|
+
const configProvider = store.getVar('embedder.provider');
|
|
76
|
+
if (configProvider) {
|
|
77
|
+
return buildEmbedder({
|
|
78
|
+
provider: configProvider,
|
|
79
|
+
model: store.getVar('embedder.model'),
|
|
80
|
+
baseUrl: store.getVar('embedder.baseUrl'),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 3. No embedder configured
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Build an embedder function from a config object.
|
|
91
|
+
*/
|
|
92
|
+
function buildEmbedder(config: EmbedderConfig): EmbedderFunction | null {
|
|
93
|
+
switch (config.provider) {
|
|
94
|
+
case 'ollama':
|
|
95
|
+
return createOllamaEmbedder(config.baseUrl, config.model);
|
|
96
|
+
default:
|
|
97
|
+
console.error(
|
|
98
|
+
`Unknown embedder provider: '${config.provider}'. Supported: ollama`,
|
|
99
|
+
);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Auto-embed text values in vector where-clause fields.
|
|
106
|
+
*
|
|
107
|
+
* When --auto-embed is passed, any vector field in the where clause that
|
|
108
|
+
* contains a text string (instead of a float array) will be converted to
|
|
109
|
+
* an embedding vector using the configured embedder.
|
|
110
|
+
*
|
|
111
|
+
* @param where - The where clause object (mutated in place)
|
|
112
|
+
* @param vectorFieldNames - Names of vector embedding fields (e.g. ['vectorEmbedding'])
|
|
113
|
+
* @param embedder - The resolved embedder function
|
|
114
|
+
* @returns The modified where clause
|
|
115
|
+
*/
|
|
116
|
+
export async function autoEmbedWhere(
|
|
117
|
+
where: Record<string, unknown>,
|
|
118
|
+
vectorFieldNames: string[],
|
|
119
|
+
embedder: EmbedderFunction,
|
|
120
|
+
): Promise<Record<string, unknown>> {
|
|
121
|
+
for (const fieldName of vectorFieldNames) {
|
|
122
|
+
const fieldValue = where[fieldName];
|
|
123
|
+
if (fieldValue && typeof fieldValue === 'object') {
|
|
124
|
+
const input = fieldValue as Record<string, unknown>;
|
|
125
|
+
// If 'vector' is a string, embed it
|
|
126
|
+
if (typeof input.vector === 'string') {
|
|
127
|
+
const text = input.vector;
|
|
128
|
+
const embedding = await embedder(text);
|
|
129
|
+
input.vector = embedding;
|
|
130
|
+
}
|
|
131
|
+
} else if (typeof fieldValue === 'string') {
|
|
132
|
+
// Shorthand: --where.vectorEmbedding "text" with --auto-embed
|
|
133
|
+
// becomes { vector: [embedded], metric: 'COSINE' }
|
|
134
|
+
const embedding = await embedder(fieldValue);
|
|
135
|
+
where[fieldName] = { vector: embedding };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return where;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Auto-embed text values in mutation input data (create/update).
|
|
143
|
+
*
|
|
144
|
+
* When --auto-embed is passed on create or update, any vector field in
|
|
145
|
+
* the input data that contains a text string will be converted to an
|
|
146
|
+
* embedding vector using the configured embedder.
|
|
147
|
+
*
|
|
148
|
+
* Usage:
|
|
149
|
+
* csdk article create --input.embedding "Machine learning concepts" --auto-embed
|
|
150
|
+
* csdk article update --id xxx --input.embedding "Updated description" --auto-embed
|
|
151
|
+
*
|
|
152
|
+
* This is a CLI-only convenience — in production, database triggers or
|
|
153
|
+
* a job queue should handle embedding generation.
|
|
154
|
+
*
|
|
155
|
+
* @param data - The mutation input data object (mutated in place)
|
|
156
|
+
* @param vectorFieldNames - Names of vector embedding fields (e.g. ['embedding'])
|
|
157
|
+
* @param embedder - The resolved embedder function
|
|
158
|
+
* @returns The modified data object with text values replaced by vectors
|
|
159
|
+
*/
|
|
160
|
+
export async function autoEmbedInput(
|
|
161
|
+
data: Record<string, unknown>,
|
|
162
|
+
vectorFieldNames: string[],
|
|
163
|
+
embedder: EmbedderFunction,
|
|
164
|
+
): Promise<Record<string, unknown>> {
|
|
165
|
+
for (const fieldName of vectorFieldNames) {
|
|
166
|
+
const fieldValue = data[fieldName];
|
|
167
|
+
if (typeof fieldValue === 'string') {
|
|
168
|
+
// Text string → embed to vector array
|
|
169
|
+
const embedding = await embedder(fieldValue);
|
|
170
|
+
data[fieldName] = embedding;
|
|
171
|
+
}
|
|
172
|
+
// If it's already an array (pre-computed vector), leave it as-is
|
|
173
|
+
}
|
|
174
|
+
return data;
|
|
175
|
+
}
|
package/core/generate.js
CHANGED
|
@@ -587,12 +587,14 @@ async function generateMulti(options) {
|
|
|
587
587
|
const firstTargetConfig = configs[names[0]];
|
|
588
588
|
const multiNodeHttpAdapter = firstTargetConfig?.nodeHttpAdapter === true ||
|
|
589
589
|
(firstTargetConfig?.nodeHttpAdapter !== false);
|
|
590
|
+
const multiConditionEnabled = firstTargetConfig?.codegen?.condition === true;
|
|
590
591
|
const { files } = (0, cli_1.generateMultiTargetCli)({
|
|
591
592
|
toolName,
|
|
592
593
|
builtinNames: cliConfig.builtinNames,
|
|
593
594
|
targets: cliTargets,
|
|
594
595
|
nodeHttpAdapter: multiNodeHttpAdapter,
|
|
595
596
|
entryPoint: cliConfig.entryPoint,
|
|
597
|
+
condition: multiConditionEnabled,
|
|
596
598
|
});
|
|
597
599
|
const cliFilesToWrite = files.map((file) => ({
|
|
598
600
|
path: node_path_1.default.posix.join('cli', file.fileName),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as t from '@babel/types';
|
|
2
|
-
import { toKebabCase } from '
|
|
2
|
+
import { toKebabCase } from 'inflekt';
|
|
3
3
|
import { generateCode } from '../babel-ast';
|
|
4
4
|
import { getGeneratedFileHeader, getTableNames } from '../utils';
|
|
5
5
|
function createImportDeclaration(moduleSpecifier, defaultImportName) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as t from '@babel/types';
|
|
2
|
-
import { toKebabCase } from '
|
|
2
|
+
import { toKebabCase } from 'inflekt';
|
|
3
3
|
import { generateCode } from '../babel-ast';
|
|
4
4
|
import { getGeneratedFileHeader, ucFirst } from '../utils';
|
|
5
5
|
import { buildQuestionsArray } from './arg-mapper';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { toKebabCase } from '
|
|
2
|
-
import { flattenArgs, flattenedArgsToFlags, cleanTypeName, getEditableFields, categorizeSpecialFields, buildSpecialFieldsMarkdown, getReadmeHeader, getReadmeFooter, buildSkillFile, buildSkillReference, } from '../docs-utils';
|
|
1
|
+
import { toKebabCase } from 'inflekt';
|
|
2
|
+
import { flattenArgs, flattenedArgsToFlags, cleanTypeName, getEditableFields, categorizeSpecialFields, buildSpecialFieldsMarkdown, buildSearchExamples, buildSearchExamplesMarkdown, getReadmeHeader, getReadmeFooter, buildSkillFile, buildSkillReference, } from '../docs-utils';
|
|
3
3
|
import { getScalarFields, getTableNames, getPrimaryKeyInfo, } from '../utils';
|
|
4
4
|
import { getFieldsWithDefaults } from './table-command-generator';
|
|
5
5
|
export { resolveDocsConfig } from '../docs-utils';
|
|
@@ -124,6 +124,7 @@ export function generateReadme(tables, customOperations, toolName, registry) {
|
|
|
124
124
|
}
|
|
125
125
|
const specialGroups = categorizeSpecialFields(table, registry);
|
|
126
126
|
lines.push(...buildSpecialFieldsMarkdown(specialGroups));
|
|
127
|
+
lines.push(...buildSearchExamplesMarkdown(specialGroups, toolName, kebab));
|
|
127
128
|
lines.push('');
|
|
128
129
|
}
|
|
129
130
|
}
|
|
@@ -358,18 +359,13 @@ export function generateSkills(tables, customOperations, toolName, targetName, r
|
|
|
358
359
|
},
|
|
359
360
|
{
|
|
360
361
|
description: `List ${singularName} records with field selection`,
|
|
361
|
-
code: [`${toolName} ${kebab} list --
|
|
362
|
+
code: [`${toolName} ${kebab} list --select id,${pk.name}`],
|
|
362
363
|
},
|
|
363
364
|
{
|
|
364
365
|
description: `List ${singularName} records with filtering and ordering`,
|
|
365
366
|
code: [`${toolName} ${kebab} list --where.${pk.name}.equalTo <value> --orderBy ${pk.name.replace(/([A-Z])/g, '_$1').toUpperCase()}_ASC`],
|
|
366
367
|
},
|
|
367
|
-
...(skillSpecialGroups
|
|
368
|
-
? [{
|
|
369
|
-
description: `Search ${singularName} records`,
|
|
370
|
-
code: [`${toolName} ${kebab} search "query text" --limit 10 --fields id,searchScore`],
|
|
371
|
-
}]
|
|
372
|
-
: []),
|
|
368
|
+
...buildSearchExamples(skillSpecialGroups, toolName, kebab),
|
|
373
369
|
{
|
|
374
370
|
description: `Create a ${singularName}`,
|
|
375
371
|
code: [
|
|
@@ -656,6 +652,7 @@ export function generateMultiTargetReadme(input) {
|
|
|
656
652
|
}
|
|
657
653
|
const mtSpecialGroups = categorizeSpecialFields(table, registry);
|
|
658
654
|
lines.push(...buildSpecialFieldsMarkdown(mtSpecialGroups));
|
|
655
|
+
lines.push(...buildSearchExamplesMarkdown(mtSpecialGroups, toolName, `${tgt.name}:${kebab}`));
|
|
659
656
|
lines.push('');
|
|
660
657
|
}
|
|
661
658
|
for (const op of tgt.customOperations) {
|
|
@@ -958,12 +955,7 @@ export function generateMultiTargetSkills(input) {
|
|
|
958
955
|
description: `List ${singularName} records with filtering and ordering`,
|
|
959
956
|
code: [`${toolName} ${cmd} list --where.${pk.name}.equalTo <value> --orderBy ${pk.name.replace(/([A-Z])/g, '_$1').toUpperCase()}_ASC`],
|
|
960
957
|
},
|
|
961
|
-
...(mtSkillSpecialGroups
|
|
962
|
-
? [{
|
|
963
|
-
description: `Search ${singularName} records`,
|
|
964
|
-
code: [`${toolName} ${cmd} search "query text" --limit 10 --fields id,searchScore`],
|
|
965
|
-
}]
|
|
966
|
-
: []),
|
|
958
|
+
...buildSearchExamples(mtSkillSpecialGroups, toolName, cmd),
|
|
967
959
|
{
|
|
968
960
|
description: `Create a ${singularName}`,
|
|
969
961
|
code: [
|
|
@@ -43,6 +43,8 @@ export interface GenerateMultiTargetCliOptions {
|
|
|
43
43
|
nodeHttpAdapter?: boolean;
|
|
44
44
|
/** Generate a runnable index.ts entry point */
|
|
45
45
|
entryPoint?: boolean;
|
|
46
|
+
/** Whether PostGraphile condition types are enabled (default: true) */
|
|
47
|
+
condition?: boolean;
|
|
46
48
|
}
|
|
47
49
|
export declare function resolveBuiltinNames(targetNames: string[], userOverrides?: BuiltinNames): {
|
|
48
50
|
auth: string;
|
|
@@ -62,5 +64,5 @@ export { generateReadme, generateAgentsDocs, generateSkills, generateMultiTarget
|
|
|
62
64
|
export type { MultiTargetDocsInput } from './docs-generator';
|
|
63
65
|
export { resolveDocsConfig } from '../docs-utils';
|
|
64
66
|
export type { GeneratedDocFile } from '../docs-utils';
|
|
65
|
-
export { generateUtilsFile, generateEntryPointFile } from './utils-generator';
|
|
67
|
+
export { generateUtilsFile, generateEntryPointFile, generateEmbedderFile } from './utils-generator';
|
|
66
68
|
export type { GeneratedFile, MultiTargetExecutorInput } from './executor-generator';
|
|
@@ -5,7 +5,7 @@ import { generateExecutorFile, generateMultiTargetExecutorFile } from './executo
|
|
|
5
5
|
import { generateHelpersFile } from './helpers-generator';
|
|
6
6
|
import { generateAuthCommand, generateAuthCommandWithName, generateContextCommand, generateMultiTargetContextCommand, } from './infra-generator';
|
|
7
7
|
import { generateTableCommand } from './table-command-generator';
|
|
8
|
-
import { generateUtilsFile, generateNodeFetchFile, generateEntryPointFile } from './utils-generator';
|
|
8
|
+
import { generateUtilsFile, generateNodeFetchFile, generateEntryPointFile, generateEmbedderFile } from './utils-generator';
|
|
9
9
|
export function generateCli(options) {
|
|
10
10
|
const { tables, customOperations, config } = options;
|
|
11
11
|
const files = [];
|
|
@@ -21,6 +21,11 @@ export function generateCli(options) {
|
|
|
21
21
|
files.push(executorFile);
|
|
22
22
|
const utilsFile = generateUtilsFile();
|
|
23
23
|
files.push(utilsFile);
|
|
24
|
+
// Generate embedder module if any table has vector embedding fields
|
|
25
|
+
const hasAnyEmbeddings = tables.some((t) => t.fields.some((f) => f.type.gqlType === 'Vector' || f.type.gqlType === '[Float]'));
|
|
26
|
+
if (hasAnyEmbeddings) {
|
|
27
|
+
files.push(generateEmbedderFile());
|
|
28
|
+
}
|
|
24
29
|
// Generate node HTTP adapter if configured (for *.localhost subdomain routing)
|
|
25
30
|
if (useNodeHttpAdapter) {
|
|
26
31
|
files.push(generateNodeFetchFile());
|
|
@@ -29,9 +34,11 @@ export function generateCli(options) {
|
|
|
29
34
|
files.push(contextFile);
|
|
30
35
|
const authFile = generateAuthCommand(toolName);
|
|
31
36
|
files.push(authFile);
|
|
37
|
+
const conditionEnabled = config.codegen?.condition === true;
|
|
32
38
|
for (const table of tables) {
|
|
33
39
|
const tableFile = generateTableCommand(table, {
|
|
34
40
|
typeRegistry: options.typeRegistry,
|
|
41
|
+
condition: conditionEnabled,
|
|
35
42
|
});
|
|
36
43
|
files.push(tableFile);
|
|
37
44
|
}
|
|
@@ -78,6 +85,7 @@ export function resolveBuiltinNames(targetNames, userOverrides) {
|
|
|
78
85
|
}
|
|
79
86
|
export function generateMultiTargetCli(options) {
|
|
80
87
|
const { toolName, targets } = options;
|
|
88
|
+
const conditionEnabled = options.condition === true;
|
|
81
89
|
const files = [];
|
|
82
90
|
const targetNames = targets.map((t) => t.name);
|
|
83
91
|
const builtinNames = resolveBuiltinNames(targetNames, options.builtinNames);
|
|
@@ -92,6 +100,11 @@ export function generateMultiTargetCli(options) {
|
|
|
92
100
|
files.push(executorFile);
|
|
93
101
|
const utilsFile = generateUtilsFile();
|
|
94
102
|
files.push(utilsFile);
|
|
103
|
+
// Generate embedder module if any target has tables with vector embedding fields
|
|
104
|
+
const hasAnyMtEmbeddings = targets.some((tgt) => tgt.tables.some((t) => t.fields.some((f) => f.type.gqlType === 'Vector' || f.type.gqlType === '[Float]')));
|
|
105
|
+
if (hasAnyMtEmbeddings) {
|
|
106
|
+
files.push(generateEmbedderFile());
|
|
107
|
+
}
|
|
95
108
|
// Generate node HTTP adapter if configured (for *.localhost subdomain routing)
|
|
96
109
|
if (options.nodeHttpAdapter) {
|
|
97
110
|
files.push(generateNodeFetchFile());
|
|
@@ -122,6 +135,7 @@ export function generateMultiTargetCli(options) {
|
|
|
122
135
|
targetName: target.name,
|
|
123
136
|
executorImportPath: '../../executor',
|
|
124
137
|
typeRegistry: target.typeRegistry,
|
|
138
|
+
condition: conditionEnabled,
|
|
125
139
|
});
|
|
126
140
|
files.push(tableFile);
|
|
127
141
|
}
|
|
@@ -173,4 +187,4 @@ export { generateHelpersFile } from './helpers-generator';
|
|
|
173
187
|
export { generateContextCommand, generateAuthCommand, generateMultiTargetContextCommand, generateAuthCommandWithName, } from './infra-generator';
|
|
174
188
|
export { generateReadme, generateAgentsDocs, generateSkills, generateMultiTargetReadme, generateMultiTargetAgentsDocs, generateMultiTargetSkills, } from './docs-generator';
|
|
175
189
|
export { resolveDocsConfig } from '../docs-utils';
|
|
176
|
-
export { generateUtilsFile, generateEntryPointFile } from './utils-generator';
|
|
190
|
+
export { generateUtilsFile, generateEntryPointFile, generateEmbedderFile } from './utils-generator';
|
|
@@ -6,5 +6,7 @@ export interface TableCommandOptions {
|
|
|
6
6
|
executorImportPath?: string;
|
|
7
7
|
/** TypeRegistry from introspection, used to check field defaults */
|
|
8
8
|
typeRegistry?: TypeRegistry;
|
|
9
|
+
/** Whether PostGraphile condition types are enabled (default: true) */
|
|
10
|
+
condition?: boolean;
|
|
9
11
|
}
|
|
10
12
|
export declare function generateTableCommand(table: Table, options?: TableCommandOptions): GeneratedFile;
|