@constructive-io/graphql-codegen 4.27.5 → 4.28.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.
@@ -315,6 +315,60 @@ function generateSkills(tables, customOperations, toolName, targetName, registry
315
315
  ],
316
316
  }),
317
317
  });
318
+ // Embedder reference (generated once when any table has Vector fields)
319
+ const hasEmbeddings = tables.some((t) => (0, docs_utils_1.categorizeSpecialFields)(t, registry).some((g) => g.category === 'embedding'));
320
+ if (hasEmbeddings) {
321
+ referenceNames.push('embedder');
322
+ files.push({
323
+ fileName: `${skillName}/references/embedder.md`,
324
+ content: (0, docs_utils_1.buildSkillReference)({
325
+ title: 'Embedder Configuration',
326
+ description: `Configure text-to-vector embedding for \`--auto-embed\` support in ${toolName}.\n\n` +
327
+ 'When an embedder is configured, you can pass plain text to vector fields and ' +
328
+ 'the CLI will automatically convert it to an embedding vector.\n\n' +
329
+ '**Supported providers:** ollama, openai\n\n' +
330
+ '**Configuration methods:** appstash config (persisted per-context) or environment variables',
331
+ usage: [
332
+ `# Configure via appstash config (persisted per-context)`,
333
+ `${toolName} config set embedder.provider <provider>`,
334
+ `${toolName} config set embedder.model <model>`,
335
+ `${toolName} config set embedder.baseUrl <url>`,
336
+ '',
337
+ `# Or configure via environment variables`,
338
+ `EMBEDDER_PROVIDER=<provider> EMBEDDER_MODEL=<model> EMBEDDER_BASE_URL=<url> ${toolName} <command>`,
339
+ ],
340
+ examples: [
341
+ {
342
+ description: 'Ollama with nomic-embed-text (open-source, local)',
343
+ code: [
344
+ `# Start Ollama locally and pull the model`,
345
+ `ollama pull nomic-embed-text`,
346
+ '',
347
+ `# Register the embedder`,
348
+ `${toolName} config set embedder.provider ollama`,
349
+ `${toolName} config set embedder.model nomic-embed-text`,
350
+ `${toolName} config set embedder.baseUrl http://localhost:11434`,
351
+ '',
352
+ `# Now use --auto-embed with any vector field`,
353
+ `${toolName} ${(0, inflekt_1.toKebabCase)((0, utils_1.getTableNames)(tables[0]).singularName)} search "my query" --auto-embed`,
354
+ ],
355
+ },
356
+ {
357
+ description: 'OpenAI with an API key',
358
+ code: [
359
+ `# Register the embedder`,
360
+ `${toolName} config set embedder.provider openai`,
361
+ `${toolName} config set embedder.model text-embedding-3-small`,
362
+ `${toolName} config set embedder.apiKey sk-proj-...your-api-key`,
363
+ '',
364
+ `# Or use environment variables`,
365
+ `EMBEDDER_PROVIDER=openai EMBEDDER_MODEL=text-embedding-3-small EMBEDDER_API_KEY=sk-proj-...your-api-key ${toolName} ${(0, inflekt_1.toKebabCase)((0, utils_1.getTableNames)(tables[0]).singularName)} search "my query" --auto-embed`,
366
+ ],
367
+ },
368
+ ],
369
+ }),
370
+ });
371
+ }
318
372
  // Table references
319
373
  for (const table of tables) {
320
374
  const { singularName } = (0, utils_1.getTableNames)(table);
@@ -867,6 +921,64 @@ function generateMultiTargetSkills(input) {
867
921
  ],
868
922
  }),
869
923
  });
924
+ // Embedder reference (generated once when any target has tables with Vector fields)
925
+ const allTargetTables = targets.flatMap((t) => t.tables);
926
+ const hasEmbeddings = allTargetTables.some((t) => (0, docs_utils_1.categorizeSpecialFields)(t, registry).some((g) => g.category === 'embedding'));
927
+ if (hasEmbeddings) {
928
+ const firstTableName = allTargetTables.length > 0
929
+ ? (0, inflekt_1.toKebabCase)((0, utils_1.getTableNames)(allTargetTables[0]).singularName)
930
+ : 'model';
931
+ commonReferenceNames.push('embedder');
932
+ files.push({
933
+ fileName: `${commonSkillName}/references/embedder.md`,
934
+ content: (0, docs_utils_1.buildSkillReference)({
935
+ title: 'Embedder Configuration',
936
+ description: `Configure text-to-vector embedding for \`--auto-embed\` support in ${toolName}.\n\n` +
937
+ 'When an embedder is configured, you can pass plain text to vector fields and ' +
938
+ 'the CLI will automatically convert it to an embedding vector.\n\n' +
939
+ '**Supported providers:** ollama, openai\n\n' +
940
+ '**Configuration methods:** appstash config (persisted per-context) or environment variables',
941
+ usage: [
942
+ `# Configure via appstash config (persisted per-context)`,
943
+ `${toolName} ${builtinNames.config} set embedder.provider <provider>`,
944
+ `${toolName} ${builtinNames.config} set embedder.model <model>`,
945
+ `${toolName} ${builtinNames.config} set embedder.baseUrl <url>`,
946
+ '',
947
+ `# Or configure via environment variables`,
948
+ `EMBEDDER_PROVIDER=<provider> EMBEDDER_MODEL=<model> EMBEDDER_BASE_URL=<url> ${toolName} <command>`,
949
+ ],
950
+ examples: [
951
+ {
952
+ description: 'Ollama with nomic-embed-text (open-source, local)',
953
+ code: [
954
+ `# Start Ollama locally and pull the model`,
955
+ `ollama pull nomic-embed-text`,
956
+ '',
957
+ `# Register the embedder`,
958
+ `${toolName} ${builtinNames.config} set embedder.provider ollama`,
959
+ `${toolName} ${builtinNames.config} set embedder.model nomic-embed-text`,
960
+ `${toolName} ${builtinNames.config} set embedder.baseUrl http://localhost:11434`,
961
+ '',
962
+ `# Now use --auto-embed with any vector field`,
963
+ `${toolName} ${targets[0]?.name ? `${targets[0].name}:` : ''}${firstTableName} search "my query" --auto-embed`,
964
+ ],
965
+ },
966
+ {
967
+ description: 'OpenAI with an API key',
968
+ code: [
969
+ `# Register the embedder`,
970
+ `${toolName} ${builtinNames.config} set embedder.provider openai`,
971
+ `${toolName} ${builtinNames.config} set embedder.model text-embedding-3-small`,
972
+ `${toolName} ${builtinNames.config} set embedder.apiKey sk-proj-...your-api-key`,
973
+ '',
974
+ `# Or use environment variables`,
975
+ `EMBEDDER_PROVIDER=openai EMBEDDER_MODEL=text-embedding-3-small EMBEDDER_API_KEY=sk-proj-...your-api-key ${toolName} ${targets[0]?.name ? `${targets[0].name}:` : ''}${firstTableName} search "my query" --auto-embed`,
976
+ ],
977
+ },
978
+ ],
979
+ }),
980
+ });
981
+ }
870
982
  // Common SKILL.md
871
983
  files.push({
872
984
  fileName: `${commonSkillName}/SKILL.md`,
@@ -124,7 +124,7 @@ function generateOrmAgentsDocs(tables, customOperations) {
124
124
  lines.push('');
125
125
  lines.push('- Prisma-like ORM client for a GraphQL API (TypeScript)');
126
126
  lines.push(`- ${tableCount} model${tableCount !== 1 ? 's' : ''}${customOpCount > 0 ? `, ${customOpCount} custom operation${customOpCount !== 1 ? 's' : ''}` : ''}`);
127
- lines.push('- All methods return a query builder; call `.execute()` to run');
127
+ lines.push('- All methods return a QueryBuilder; call `.execute()` to run, or `.unwrap()` to throw on error');
128
128
  lines.push('');
129
129
  lines.push('## Quick Start');
130
130
  lines.push('');
@@ -137,6 +137,29 @@ function generateOrmAgentsDocs(tables, customOperations) {
137
137
  lines.push('});');
138
138
  lines.push('```');
139
139
  lines.push('');
140
+ lines.push('## Error Handling');
141
+ lines.push('');
142
+ lines.push('> **CRITICAL:** `.execute()` returns `{ ok, data, errors }` — it does **NOT** throw.');
143
+ lines.push('> A bare `try/catch` around `.execute()` will silently swallow errors.');
144
+ lines.push('');
145
+ lines.push('```typescript');
146
+ lines.push('// WRONG — errors are silently lost:');
147
+ lines.push('try { const r = await db.model.findMany({...}).execute(); } catch (e) { /* never runs */ }');
148
+ lines.push('');
149
+ lines.push('// RIGHT — .execute().unwrap() throws GraphQLRequestError on failure:');
150
+ lines.push('const data = await db.model.findMany({...}).execute().unwrap();');
151
+ lines.push('');
152
+ lines.push('// RIGHT — check .ok for control flow:');
153
+ lines.push('const result = await db.model.findMany({...}).execute();');
154
+ lines.push('if (!result.ok) { console.error(result.errors); return; }');
155
+ lines.push('return result.data;');
156
+ lines.push('```');
157
+ lines.push('');
158
+ lines.push('Available helpers (chain after `.execute()`):');
159
+ lines.push('- `.execute().unwrap()` — throws on error, returns typed data');
160
+ lines.push('- `.execute().unwrapOr(default)` — returns default value on error');
161
+ lines.push('- `.execute().unwrapOrElse(fn)` — calls callback with errors on failure');
162
+ lines.push('');
140
163
  lines.push('## Resources');
141
164
  lines.push('');
142
165
  lines.push(`- **Full API reference:** [README.md](./README.md) — model docs for all ${tableCount} tables`);
@@ -147,7 +170,7 @@ function generateOrmAgentsDocs(tables, customOperations) {
147
170
  lines.push('');
148
171
  lines.push('- Access models via `db.<ModelName>` (e.g. `db.User`)');
149
172
  lines.push('- CRUD methods: `findMany`, `findOne`, `create`, `update`, `delete`');
150
- lines.push('- Always call `.execute()` to run the query');
173
+ lines.push('- Chain `.execute().unwrap()` to run and throw on error, or `.execute()` alone for discriminated union result');
151
174
  lines.push('- Custom operations via `db.query.<name>` or `db.mutation.<name>`');
152
175
  lines.push('');
153
176
  lines.push('## Boundaries');
@@ -305,6 +305,60 @@ export function generateSkills(tables, customOperations, toolName, targetName, r
305
305
  ],
306
306
  }),
307
307
  });
308
+ // Embedder reference (generated once when any table has Vector fields)
309
+ const hasEmbeddings = tables.some((t) => categorizeSpecialFields(t, registry).some((g) => g.category === 'embedding'));
310
+ if (hasEmbeddings) {
311
+ referenceNames.push('embedder');
312
+ files.push({
313
+ fileName: `${skillName}/references/embedder.md`,
314
+ content: buildSkillReference({
315
+ title: 'Embedder Configuration',
316
+ description: `Configure text-to-vector embedding for \`--auto-embed\` support in ${toolName}.\n\n` +
317
+ 'When an embedder is configured, you can pass plain text to vector fields and ' +
318
+ 'the CLI will automatically convert it to an embedding vector.\n\n' +
319
+ '**Supported providers:** ollama, openai\n\n' +
320
+ '**Configuration methods:** appstash config (persisted per-context) or environment variables',
321
+ usage: [
322
+ `# Configure via appstash config (persisted per-context)`,
323
+ `${toolName} config set embedder.provider <provider>`,
324
+ `${toolName} config set embedder.model <model>`,
325
+ `${toolName} config set embedder.baseUrl <url>`,
326
+ '',
327
+ `# Or configure via environment variables`,
328
+ `EMBEDDER_PROVIDER=<provider> EMBEDDER_MODEL=<model> EMBEDDER_BASE_URL=<url> ${toolName} <command>`,
329
+ ],
330
+ examples: [
331
+ {
332
+ description: 'Ollama with nomic-embed-text (open-source, local)',
333
+ code: [
334
+ `# Start Ollama locally and pull the model`,
335
+ `ollama pull nomic-embed-text`,
336
+ '',
337
+ `# Register the embedder`,
338
+ `${toolName} config set embedder.provider ollama`,
339
+ `${toolName} config set embedder.model nomic-embed-text`,
340
+ `${toolName} config set embedder.baseUrl http://localhost:11434`,
341
+ '',
342
+ `# Now use --auto-embed with any vector field`,
343
+ `${toolName} ${toKebabCase(getTableNames(tables[0]).singularName)} search "my query" --auto-embed`,
344
+ ],
345
+ },
346
+ {
347
+ description: 'OpenAI with an API key',
348
+ code: [
349
+ `# Register the embedder`,
350
+ `${toolName} config set embedder.provider openai`,
351
+ `${toolName} config set embedder.model text-embedding-3-small`,
352
+ `${toolName} config set embedder.apiKey sk-proj-...your-api-key`,
353
+ '',
354
+ `# Or use environment variables`,
355
+ `EMBEDDER_PROVIDER=openai EMBEDDER_MODEL=text-embedding-3-small EMBEDDER_API_KEY=sk-proj-...your-api-key ${toolName} ${toKebabCase(getTableNames(tables[0]).singularName)} search "my query" --auto-embed`,
356
+ ],
357
+ },
358
+ ],
359
+ }),
360
+ });
361
+ }
308
362
  // Table references
309
363
  for (const table of tables) {
310
364
  const { singularName } = getTableNames(table);
@@ -857,6 +911,64 @@ export function generateMultiTargetSkills(input) {
857
911
  ],
858
912
  }),
859
913
  });
914
+ // Embedder reference (generated once when any target has tables with Vector fields)
915
+ const allTargetTables = targets.flatMap((t) => t.tables);
916
+ const hasEmbeddings = allTargetTables.some((t) => categorizeSpecialFields(t, registry).some((g) => g.category === 'embedding'));
917
+ if (hasEmbeddings) {
918
+ const firstTableName = allTargetTables.length > 0
919
+ ? toKebabCase(getTableNames(allTargetTables[0]).singularName)
920
+ : 'model';
921
+ commonReferenceNames.push('embedder');
922
+ files.push({
923
+ fileName: `${commonSkillName}/references/embedder.md`,
924
+ content: buildSkillReference({
925
+ title: 'Embedder Configuration',
926
+ description: `Configure text-to-vector embedding for \`--auto-embed\` support in ${toolName}.\n\n` +
927
+ 'When an embedder is configured, you can pass plain text to vector fields and ' +
928
+ 'the CLI will automatically convert it to an embedding vector.\n\n' +
929
+ '**Supported providers:** ollama, openai\n\n' +
930
+ '**Configuration methods:** appstash config (persisted per-context) or environment variables',
931
+ usage: [
932
+ `# Configure via appstash config (persisted per-context)`,
933
+ `${toolName} ${builtinNames.config} set embedder.provider <provider>`,
934
+ `${toolName} ${builtinNames.config} set embedder.model <model>`,
935
+ `${toolName} ${builtinNames.config} set embedder.baseUrl <url>`,
936
+ '',
937
+ `# Or configure via environment variables`,
938
+ `EMBEDDER_PROVIDER=<provider> EMBEDDER_MODEL=<model> EMBEDDER_BASE_URL=<url> ${toolName} <command>`,
939
+ ],
940
+ examples: [
941
+ {
942
+ description: 'Ollama with nomic-embed-text (open-source, local)',
943
+ code: [
944
+ `# Start Ollama locally and pull the model`,
945
+ `ollama pull nomic-embed-text`,
946
+ '',
947
+ `# Register the embedder`,
948
+ `${toolName} ${builtinNames.config} set embedder.provider ollama`,
949
+ `${toolName} ${builtinNames.config} set embedder.model nomic-embed-text`,
950
+ `${toolName} ${builtinNames.config} set embedder.baseUrl http://localhost:11434`,
951
+ '',
952
+ `# Now use --auto-embed with any vector field`,
953
+ `${toolName} ${targets[0]?.name ? `${targets[0].name}:` : ''}${firstTableName} search "my query" --auto-embed`,
954
+ ],
955
+ },
956
+ {
957
+ description: 'OpenAI with an API key',
958
+ code: [
959
+ `# Register the embedder`,
960
+ `${toolName} ${builtinNames.config} set embedder.provider openai`,
961
+ `${toolName} ${builtinNames.config} set embedder.model text-embedding-3-small`,
962
+ `${toolName} ${builtinNames.config} set embedder.apiKey sk-proj-...your-api-key`,
963
+ '',
964
+ `# Or use environment variables`,
965
+ `EMBEDDER_PROVIDER=openai EMBEDDER_MODEL=text-embedding-3-small EMBEDDER_API_KEY=sk-proj-...your-api-key ${toolName} ${targets[0]?.name ? `${targets[0].name}:` : ''}${firstTableName} search "my query" --auto-embed`,
966
+ ],
967
+ },
968
+ ],
969
+ }),
970
+ });
971
+ }
860
972
  // Common SKILL.md
861
973
  files.push({
862
974
  fileName: `${commonSkillName}/SKILL.md`,
@@ -119,7 +119,7 @@ export function generateOrmAgentsDocs(tables, customOperations) {
119
119
  lines.push('');
120
120
  lines.push('- Prisma-like ORM client for a GraphQL API (TypeScript)');
121
121
  lines.push(`- ${tableCount} model${tableCount !== 1 ? 's' : ''}${customOpCount > 0 ? `, ${customOpCount} custom operation${customOpCount !== 1 ? 's' : ''}` : ''}`);
122
- lines.push('- All methods return a query builder; call `.execute()` to run');
122
+ lines.push('- All methods return a QueryBuilder; call `.execute()` to run, or `.unwrap()` to throw on error');
123
123
  lines.push('');
124
124
  lines.push('## Quick Start');
125
125
  lines.push('');
@@ -132,6 +132,29 @@ export function generateOrmAgentsDocs(tables, customOperations) {
132
132
  lines.push('});');
133
133
  lines.push('```');
134
134
  lines.push('');
135
+ lines.push('## Error Handling');
136
+ lines.push('');
137
+ lines.push('> **CRITICAL:** `.execute()` returns `{ ok, data, errors }` — it does **NOT** throw.');
138
+ lines.push('> A bare `try/catch` around `.execute()` will silently swallow errors.');
139
+ lines.push('');
140
+ lines.push('```typescript');
141
+ lines.push('// WRONG — errors are silently lost:');
142
+ lines.push('try { const r = await db.model.findMany({...}).execute(); } catch (e) { /* never runs */ }');
143
+ lines.push('');
144
+ lines.push('// RIGHT — .execute().unwrap() throws GraphQLRequestError on failure:');
145
+ lines.push('const data = await db.model.findMany({...}).execute().unwrap();');
146
+ lines.push('');
147
+ lines.push('// RIGHT — check .ok for control flow:');
148
+ lines.push('const result = await db.model.findMany({...}).execute();');
149
+ lines.push('if (!result.ok) { console.error(result.errors); return; }');
150
+ lines.push('return result.data;');
151
+ lines.push('```');
152
+ lines.push('');
153
+ lines.push('Available helpers (chain after `.execute()`):');
154
+ lines.push('- `.execute().unwrap()` — throws on error, returns typed data');
155
+ lines.push('- `.execute().unwrapOr(default)` — returns default value on error');
156
+ lines.push('- `.execute().unwrapOrElse(fn)` — calls callback with errors on failure');
157
+ lines.push('');
135
158
  lines.push('## Resources');
136
159
  lines.push('');
137
160
  lines.push(`- **Full API reference:** [README.md](./README.md) — model docs for all ${tableCount} tables`);
@@ -142,7 +165,7 @@ export function generateOrmAgentsDocs(tables, customOperations) {
142
165
  lines.push('');
143
166
  lines.push('- Access models via `db.<ModelName>` (e.g. `db.User`)');
144
167
  lines.push('- CRUD methods: `findMany`, `findOne`, `create`, `update`, `delete`');
145
- lines.push('- Always call `.execute()` to run the query');
168
+ lines.push('- Chain `.execute().unwrap()` to run and throw on error, or `.execute()` alone for discriminated union result');
146
169
  lines.push('- Custom operations via `db.query.<name>` or `db.mutation.<name>`');
147
170
  lines.push('');
148
171
  lines.push('## Boundaries');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/graphql-codegen",
3
- "version": "4.27.5",
3
+ "version": "4.28.1",
4
4
  "description": "GraphQL SDK generator for Constructive databases with React Query hooks",
5
5
  "keywords": [
6
6
  "graphql",
@@ -56,7 +56,7 @@
56
56
  "@0no-co/graphql.web": "^1.1.2",
57
57
  "@babel/generator": "^7.29.1",
58
58
  "@babel/types": "^7.29.0",
59
- "@constructive-io/graphql-query": "^3.12.11",
59
+ "@constructive-io/graphql-query": "^3.12.12",
60
60
  "@constructive-io/graphql-types": "^3.4.3",
61
61
  "@inquirerer/utils": "^3.3.5",
62
62
  "@pgpmjs/core": "^6.10.6",
@@ -64,7 +64,7 @@
64
64
  "deepmerge": "^4.3.1",
65
65
  "find-and-require-package-json": "^0.9.1",
66
66
  "gql-ast": "^3.4.2",
67
- "graphile-schema": "^1.11.7",
67
+ "graphile-schema": "^1.11.8",
68
68
  "graphql": "16.13.0",
69
69
  "inflekt": "^0.7.1",
70
70
  "inquirerer": "^4.7.0",
@@ -100,5 +100,5 @@
100
100
  "tsx": "^4.21.0",
101
101
  "typescript": "^5.9.3"
102
102
  },
103
- "gitHead": "0b7edbd088ca9661503c5038134ee15311eac027"
103
+ "gitHead": "fc23b83307d007a14e54b1d0fc36614b9650a5dc"
104
104
  }