@constructive-io/graphql-codegen 4.12.2 → 4.13.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.
Files changed (37) hide show
  1. package/core/codegen/cli/command-map-generator.d.ts +1 -0
  2. package/core/codegen/cli/command-map-generator.js +4 -0
  3. package/core/codegen/cli/config-command-generator.d.ts +11 -0
  4. package/core/codegen/cli/config-command-generator.js +458 -0
  5. package/core/codegen/cli/docs-generator.d.ts +1 -0
  6. package/core/codegen/cli/docs-generator.js +267 -1
  7. package/core/codegen/cli/helpers-generator.d.ts +15 -0
  8. package/core/codegen/cli/helpers-generator.js +119 -0
  9. package/core/codegen/cli/index.d.ts +4 -0
  10. package/core/codegen/cli/index.js +21 -3
  11. package/core/codegen/orm/index.js +3 -2
  12. package/core/codegen/orm/input-types-generator.d.ts +3 -1
  13. package/core/codegen/orm/input-types-generator.js +14 -6
  14. package/core/codegen/orm/model-generator.d.ts +6 -2
  15. package/core/codegen/orm/model-generator.js +59 -37
  16. package/core/codegen/templates/query-builder.ts +2 -2
  17. package/core/codegen/templates/select-types.ts +2 -2
  18. package/esm/core/codegen/cli/command-map-generator.d.ts +1 -0
  19. package/esm/core/codegen/cli/command-map-generator.js +4 -0
  20. package/esm/core/codegen/cli/config-command-generator.d.ts +11 -0
  21. package/esm/core/codegen/cli/config-command-generator.js +422 -0
  22. package/esm/core/codegen/cli/docs-generator.d.ts +1 -0
  23. package/esm/core/codegen/cli/docs-generator.js +267 -1
  24. package/esm/core/codegen/cli/helpers-generator.d.ts +15 -0
  25. package/esm/core/codegen/cli/helpers-generator.js +83 -0
  26. package/esm/core/codegen/cli/index.d.ts +4 -0
  27. package/esm/core/codegen/cli/index.js +18 -2
  28. package/esm/core/codegen/orm/index.js +3 -2
  29. package/esm/core/codegen/orm/input-types-generator.d.ts +3 -1
  30. package/esm/core/codegen/orm/input-types-generator.js +14 -6
  31. package/esm/core/codegen/orm/model-generator.d.ts +6 -2
  32. package/esm/core/codegen/orm/model-generator.js +59 -37
  33. package/esm/types/config.d.ts +9 -0
  34. package/esm/types/config.js +1 -0
  35. package/package.json +4 -4
  36. package/types/config.d.ts +9 -0
  37. package/types/config.js +1 -0
@@ -25,6 +25,7 @@ export function generateReadme(tables, customOperations, toolName, registry) {
25
25
  lines.push('|---------|-------------|');
26
26
  lines.push('| `context` | Manage API contexts (endpoints) |');
27
27
  lines.push('| `auth` | Manage authentication tokens |');
28
+ lines.push('| `config` | Manage config key-value store (per-context) |');
28
29
  for (const table of tables) {
29
30
  const { singularName } = getTableNames(table);
30
31
  const kebab = toKebabCase(singularName);
@@ -61,6 +62,19 @@ export function generateReadme(tables, customOperations, toolName, registry) {
61
62
  lines.push('| `status` | Show auth status across all contexts |');
62
63
  lines.push('| `logout` | Remove credentials for current context |');
63
64
  lines.push('');
65
+ lines.push('### `config`');
66
+ lines.push('');
67
+ lines.push('Manage per-context key-value configuration variables.');
68
+ lines.push('');
69
+ lines.push('| Subcommand | Description |');
70
+ lines.push('|------------|-------------|');
71
+ lines.push('| `get <key>` | Get a config value |');
72
+ lines.push('| `set <key> <value>` | Set a config value |');
73
+ lines.push('| `list` | List all config values |');
74
+ lines.push('| `delete <key>` | Delete a config value |');
75
+ lines.push('');
76
+ lines.push(`Variables are scoped to the active context and stored at \`~/.${toolName}/config/\`.`);
77
+ lines.push('');
64
78
  if (tables.length > 0) {
65
79
  lines.push('## Table Commands');
66
80
  lines.push('');
@@ -221,6 +235,28 @@ export function generateAgentsDocs(tables, customOperations, toolName, registry)
221
235
  lines.push(' logout: { context, status: "logged out" }');
222
236
  lines.push('```');
223
237
  lines.push('');
238
+ lines.push('### TOOL: config');
239
+ lines.push('');
240
+ lines.push('Manage per-context key-value configuration variables.');
241
+ lines.push('');
242
+ lines.push('```');
243
+ lines.push('SUBCOMMANDS:');
244
+ lines.push(` ${toolName} config get <key> Get a config value`);
245
+ lines.push(` ${toolName} config set <key> <value> Set a config value`);
246
+ lines.push(` ${toolName} config list List all config values`);
247
+ lines.push(` ${toolName} config delete <key> Delete a config value`);
248
+ lines.push('');
249
+ lines.push('INPUT:');
250
+ lines.push(' key: string (required for get/set/delete) - Variable name');
251
+ lines.push(' value: string (required for set) - Variable value');
252
+ lines.push('');
253
+ lines.push('OUTPUT: JSON');
254
+ lines.push(' get: { key, value }');
255
+ lines.push(' set: { key, value }');
256
+ lines.push(' list: { vars: { key: value, ... } }');
257
+ lines.push(' delete: { deleted: key }');
258
+ lines.push('```');
259
+ lines.push('');
224
260
  for (const table of tables) {
225
261
  const { singularName } = getTableNames(table);
226
262
  const kebab = toKebabCase(singularName);
@@ -428,6 +464,45 @@ export function getCliMcpTools(tables, customOperations, toolName, registry) {
428
464
  description: 'Remove credentials for the current context',
429
465
  inputSchema: { type: 'object', properties: {} },
430
466
  });
467
+ tools.push({
468
+ name: `${toolName}_config_get`,
469
+ description: 'Get a config variable value for the current context',
470
+ inputSchema: {
471
+ type: 'object',
472
+ properties: {
473
+ key: { type: 'string', description: 'Variable name' },
474
+ },
475
+ required: ['key'],
476
+ },
477
+ });
478
+ tools.push({
479
+ name: `${toolName}_config_set`,
480
+ description: 'Set a config variable value for the current context',
481
+ inputSchema: {
482
+ type: 'object',
483
+ properties: {
484
+ key: { type: 'string', description: 'Variable name' },
485
+ value: { type: 'string', description: 'Variable value' },
486
+ },
487
+ required: ['key', 'value'],
488
+ },
489
+ });
490
+ tools.push({
491
+ name: `${toolName}_config_list`,
492
+ description: 'List all config variables for the current context',
493
+ inputSchema: { type: 'object', properties: {} },
494
+ });
495
+ tools.push({
496
+ name: `${toolName}_config_delete`,
497
+ description: 'Delete a config variable for the current context',
498
+ inputSchema: {
499
+ type: 'object',
500
+ properties: {
501
+ key: { type: 'string', description: 'Variable name to delete' },
502
+ },
503
+ required: ['key'],
504
+ },
505
+ });
431
506
  for (const table of tables) {
432
507
  const { singularName } = getTableNames(table);
433
508
  const kebab = toKebabCase(singularName);
@@ -605,6 +680,34 @@ export function generateSkills(tables, customOperations, toolName, targetName, r
605
680
  ],
606
681
  }),
607
682
  });
683
+ // Config reference
684
+ referenceNames.push('config');
685
+ files.push({
686
+ fileName: `${skillName}/references/config.md`,
687
+ content: buildSkillReference({
688
+ title: 'Config Variables',
689
+ description: `Manage per-context key-value configuration variables for ${toolName}`,
690
+ usage: [
691
+ `${toolName} config get <key>`,
692
+ `${toolName} config set <key> <value>`,
693
+ `${toolName} config list`,
694
+ `${toolName} config delete <key>`,
695
+ ],
696
+ examples: [
697
+ {
698
+ description: 'Store and retrieve a config variable',
699
+ code: [
700
+ `${toolName} config set orgId abc-123`,
701
+ `${toolName} config get orgId`,
702
+ ],
703
+ },
704
+ {
705
+ description: 'List all config variables',
706
+ code: [`${toolName} config list`],
707
+ },
708
+ ],
709
+ }),
710
+ });
608
711
  // Table references
609
712
  for (const table of tables) {
610
713
  const { singularName } = getTableNames(table);
@@ -686,6 +789,10 @@ export function generateSkills(tables, customOperations, toolName, targetName, r
686
789
  `# Authentication`,
687
790
  `${toolName} auth set-token <token>`,
688
791
  '',
792
+ `# Config variables`,
793
+ `${toolName} config set <key> <value>`,
794
+ `${toolName} config get <key>`,
795
+ '',
689
796
  `# CRUD for any table (e.g. ${tableKebabs[0] || 'model'})`,
690
797
  `${toolName} ${tableKebabs[0] || 'model'} list`,
691
798
  `${toolName} ${tableKebabs[0] || 'model'} get --id <value>`,
@@ -781,6 +888,7 @@ export function generateMultiTargetReadme(input) {
781
888
  lines.push('|---------|-------------|');
782
889
  lines.push(`| \`${builtinNames.context}\` | Manage API contexts (per-target endpoints) |`);
783
890
  lines.push(`| \`${builtinNames.auth}\` | Manage authentication tokens |`);
891
+ lines.push(`| \`${builtinNames.config}\` | Manage config key-value store (per-context) |`);
784
892
  lines.push('');
785
893
  for (const tgt of targets) {
786
894
  lines.push(`### ${tgt.name}`);
@@ -830,6 +938,40 @@ export function generateMultiTargetReadme(input) {
830
938
  lines.push('| `status` | Show auth status across all contexts |');
831
939
  lines.push('| `logout` | Remove credentials for current context |');
832
940
  lines.push('');
941
+ lines.push(`### \`${builtinNames.config}\``);
942
+ lines.push('');
943
+ lines.push('Manage per-context key-value configuration variables.');
944
+ lines.push('');
945
+ lines.push('| Subcommand | Description |');
946
+ lines.push('|------------|-------------|');
947
+ lines.push('| `get <key>` | Get a config value |');
948
+ lines.push('| `set <key> <value>` | Set a config value |');
949
+ lines.push('| `list` | List all config values |');
950
+ lines.push('| `delete <key>` | Delete a config value |');
951
+ lines.push('');
952
+ lines.push(`Variables are scoped to the active context and stored at \`~/.${toolName}/config/\`.`);
953
+ lines.push('');
954
+ lines.push('## SDK Helpers');
955
+ lines.push('');
956
+ lines.push('The generated `helpers.ts` provides typed client factories for use in scripts and services:');
957
+ lines.push('');
958
+ lines.push('```typescript');
959
+ for (const tgt of targets) {
960
+ const pascalName = tgt.name.charAt(0).toUpperCase() + tgt.name.slice(1);
961
+ lines.push(`import { create${pascalName}Client } from './helpers';`);
962
+ }
963
+ lines.push('');
964
+ for (const tgt of targets) {
965
+ const pascalName = tgt.name.charAt(0).toUpperCase() + tgt.name.slice(1);
966
+ lines.push(`const ${tgt.name} = create${pascalName}Client();`);
967
+ }
968
+ lines.push('```');
969
+ lines.push('');
970
+ lines.push('Credential resolution order:');
971
+ lines.push(`1. appstash store (\`~/.${toolName}/config/\`)`);
972
+ lines.push(`2. Environment variables (\`${toolName.toUpperCase().replace(/-/g, '_')}_TOKEN\`, \`${toolName.toUpperCase().replace(/-/g, '_')}_<TARGET>_ENDPOINT\`)`);
973
+ lines.push('3. Throws with actionable error message');
974
+ lines.push('');
833
975
  for (const tgt of targets) {
834
976
  if (tgt.tables.length === 0 && tgt.customOperations.length === 0)
835
977
  continue;
@@ -956,6 +1098,7 @@ export function generateMultiTargetAgentsDocs(input) {
956
1098
  lines.push(` ${toolName} <target>:<command> <subcommand> [flags] Target-specific commands`);
957
1099
  lines.push(` ${toolName} ${builtinNames.context} <subcommand> [flags] Context management`);
958
1100
  lines.push(` ${toolName} ${builtinNames.auth} <subcommand> [flags] Authentication`);
1101
+ lines.push(` ${toolName} ${builtinNames.config} <subcommand> [flags] Config key-value store`);
959
1102
  lines.push('');
960
1103
  lines.push('## PREREQUISITES');
961
1104
  lines.push('');
@@ -1020,6 +1163,51 @@ export function generateMultiTargetAgentsDocs(input) {
1020
1163
  lines.push(' logout: { context, status: "logged out" }');
1021
1164
  lines.push('```');
1022
1165
  lines.push('');
1166
+ lines.push(`### TOOL: ${builtinNames.config}`);
1167
+ lines.push('');
1168
+ lines.push('Manage per-context key-value configuration variables.');
1169
+ lines.push('');
1170
+ lines.push('```');
1171
+ lines.push('SUBCOMMANDS:');
1172
+ lines.push(` ${toolName} ${builtinNames.config} get <key> Get a config value`);
1173
+ lines.push(` ${toolName} ${builtinNames.config} set <key> <value> Set a config value`);
1174
+ lines.push(` ${toolName} ${builtinNames.config} list List all config values`);
1175
+ lines.push(` ${toolName} ${builtinNames.config} delete <key> Delete a config value`);
1176
+ lines.push('');
1177
+ lines.push('INPUT:');
1178
+ lines.push(' key: string (required for get/set/delete) - Variable name');
1179
+ lines.push(' value: string (required for set) - Variable value');
1180
+ lines.push('');
1181
+ lines.push('OUTPUT: JSON');
1182
+ lines.push(' get: { key, value }');
1183
+ lines.push(' set: { key, value }');
1184
+ lines.push(' list: { vars: { key: value, ... } }');
1185
+ lines.push(' delete: { deleted: key }');
1186
+ lines.push('```');
1187
+ lines.push('');
1188
+ lines.push('### TOOL: helpers (SDK)');
1189
+ lines.push('');
1190
+ lines.push('Typed client factories for use in scripts and services (generated helpers.ts).');
1191
+ lines.push('Resolves credentials via: appstash store -> env vars -> throw.');
1192
+ lines.push('');
1193
+ lines.push('```');
1194
+ lines.push('FACTORIES:');
1195
+ for (const tgt of targets) {
1196
+ const pascalName = tgt.name.charAt(0).toUpperCase() + tgt.name.slice(1);
1197
+ lines.push(` create${pascalName}Client(contextName?) Create a configured ${tgt.name} ORM client`);
1198
+ }
1199
+ lines.push('');
1200
+ lines.push('USAGE:');
1201
+ lines.push(` import { create${targets[0] ? targets[0].name.charAt(0).toUpperCase() + targets[0].name.slice(1) : 'Target'}Client } from './helpers';`);
1202
+ lines.push(` const client = create${targets[0] ? targets[0].name.charAt(0).toUpperCase() + targets[0].name.slice(1) : 'Target'}Client();`);
1203
+ lines.push('');
1204
+ lines.push('CREDENTIAL RESOLUTION:');
1205
+ lines.push(` 1. appstash store (~/.${toolName}/config/)`);
1206
+ const envPrefix = toolName.toUpperCase().replace(/-/g, '_');
1207
+ lines.push(` 2. env vars (${envPrefix}_TOKEN, ${envPrefix}_<TARGET>_ENDPOINT)`);
1208
+ lines.push(' 3. throws with actionable error message');
1209
+ lines.push('```');
1210
+ lines.push('');
1023
1211
  for (const tgt of targets) {
1024
1212
  for (const table of tgt.tables) {
1025
1213
  const { singularName } = getTableNames(table);
@@ -1245,6 +1433,45 @@ export function getMultiTargetCliMcpTools(input) {
1245
1433
  description: 'Remove credentials for the current context',
1246
1434
  inputSchema: { type: 'object', properties: {} },
1247
1435
  });
1436
+ tools.push({
1437
+ name: `${toolName}_${builtinNames.config}_get`,
1438
+ description: 'Get a config variable value for the current context',
1439
+ inputSchema: {
1440
+ type: 'object',
1441
+ properties: {
1442
+ key: { type: 'string', description: 'Variable name' },
1443
+ },
1444
+ required: ['key'],
1445
+ },
1446
+ });
1447
+ tools.push({
1448
+ name: `${toolName}_${builtinNames.config}_set`,
1449
+ description: 'Set a config variable value for the current context',
1450
+ inputSchema: {
1451
+ type: 'object',
1452
+ properties: {
1453
+ key: { type: 'string', description: 'Variable name' },
1454
+ value: { type: 'string', description: 'Variable value' },
1455
+ },
1456
+ required: ['key', 'value'],
1457
+ },
1458
+ });
1459
+ tools.push({
1460
+ name: `${toolName}_${builtinNames.config}_list`,
1461
+ description: 'List all config variables for the current context',
1462
+ inputSchema: { type: 'object', properties: {} },
1463
+ });
1464
+ tools.push({
1465
+ name: `${toolName}_${builtinNames.config}_delete`,
1466
+ description: 'Delete a config variable for the current context',
1467
+ inputSchema: {
1468
+ type: 'object',
1469
+ properties: {
1470
+ key: { type: 'string', description: 'Variable name to delete' },
1471
+ },
1472
+ required: ['key'],
1473
+ },
1474
+ });
1248
1475
  for (const tgt of targets) {
1249
1476
  for (const table of tgt.tables) {
1250
1477
  const { singularName } = getTableNames(table);
@@ -1439,12 +1666,40 @@ export function generateMultiTargetSkills(input) {
1439
1666
  ],
1440
1667
  }),
1441
1668
  });
1669
+ // Config reference
1670
+ commonReferenceNames.push('config');
1671
+ files.push({
1672
+ fileName: `${commonSkillName}/references/config.md`,
1673
+ content: buildSkillReference({
1674
+ title: 'Config Variables',
1675
+ description: `Manage per-context key-value configuration variables for ${toolName}`,
1676
+ usage: [
1677
+ `${toolName} ${builtinNames.config} get <key>`,
1678
+ `${toolName} ${builtinNames.config} set <key> <value>`,
1679
+ `${toolName} ${builtinNames.config} list`,
1680
+ `${toolName} ${builtinNames.config} delete <key>`,
1681
+ ],
1682
+ examples: [
1683
+ {
1684
+ description: 'Store and retrieve a config variable',
1685
+ code: [
1686
+ `${toolName} ${builtinNames.config} set orgId abc-123`,
1687
+ `${toolName} ${builtinNames.config} get orgId`,
1688
+ ],
1689
+ },
1690
+ {
1691
+ description: 'List all config variables',
1692
+ code: [`${toolName} ${builtinNames.config} list`],
1693
+ },
1694
+ ],
1695
+ }),
1696
+ });
1442
1697
  // Common SKILL.md
1443
1698
  files.push({
1444
1699
  fileName: `${commonSkillName}/SKILL.md`,
1445
1700
  content: buildSkillFile({
1446
1701
  name: commonSkillName,
1447
- description: `Shared CLI utilities for ${toolName} — context management and authentication across targets: ${targets.map((t) => t.name).join(', ')}`,
1702
+ description: `Shared CLI utilities for ${toolName} — context management, authentication, and config across targets: ${targets.map((t) => t.name).join(', ')}`,
1448
1703
  usage: [
1449
1704
  `# Context management`,
1450
1705
  `${toolName} ${builtinNames.context} create <name>`,
@@ -1453,6 +1708,11 @@ export function generateMultiTargetSkills(input) {
1453
1708
  `# Authentication`,
1454
1709
  `${toolName} ${builtinNames.auth} set-token <token>`,
1455
1710
  `${toolName} ${builtinNames.auth} status`,
1711
+ '',
1712
+ `# Config variables`,
1713
+ `${toolName} ${builtinNames.config} set <key> <value>`,
1714
+ `${toolName} ${builtinNames.config} get <key>`,
1715
+ `${toolName} ${builtinNames.config} list`,
1456
1716
  ],
1457
1717
  examples: [
1458
1718
  {
@@ -1463,6 +1723,12 @@ export function generateMultiTargetSkills(input) {
1463
1723
  `${toolName} ${builtinNames.auth} set-token <token>`,
1464
1724
  ],
1465
1725
  },
1726
+ {
1727
+ description: 'Store a config variable',
1728
+ code: [
1729
+ `${toolName} ${builtinNames.config} set orgId abc-123`,
1730
+ ],
1731
+ },
1466
1732
  ],
1467
1733
  }, commonReferenceNames),
1468
1734
  });
@@ -0,0 +1,15 @@
1
+ import type { GeneratedFile } from './executor-generator';
2
+ export interface HelpersGeneratorInput {
3
+ name: string;
4
+ ormImportPath: string;
5
+ }
6
+ /**
7
+ * Generate helpers.ts with typed per-target client factories.
8
+ *
9
+ * Each target gets a `createXxxClient(contextName?)` function that uses
10
+ * `store.getClientConfig(targetName, contextName)` under the hood with
11
+ * 3-tier resolution: appstash store -> env vars -> throw.
12
+ *
13
+ * Also re-exports the store for direct config/var access.
14
+ */
15
+ export declare function generateHelpersFile(toolName: string, targets: HelpersGeneratorInput[]): GeneratedFile;
@@ -0,0 +1,83 @@
1
+ import * as t from '@babel/types';
2
+ import { generateCode } from '../babel-ast';
3
+ import { getGeneratedFileHeader } from '../utils';
4
+ function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false) {
5
+ const specifiers = namedImports.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
6
+ const decl = t.importDeclaration(specifiers, t.stringLiteral(moduleSpecifier));
7
+ decl.importKind = typeOnly ? 'type' : 'value';
8
+ return decl;
9
+ }
10
+ /**
11
+ * Generate helpers.ts with typed per-target client factories.
12
+ *
13
+ * Each target gets a `createXxxClient(contextName?)` function that uses
14
+ * `store.getClientConfig(targetName, contextName)` under the hood with
15
+ * 3-tier resolution: appstash store -> env vars -> throw.
16
+ *
17
+ * Also re-exports the store for direct config/var access.
18
+ */
19
+ export function generateHelpersFile(toolName, targets) {
20
+ const statements = [];
21
+ // import { createConfigStore } from 'appstash';
22
+ statements.push(createImportDeclaration('appstash', ['createConfigStore']));
23
+ // import type { ClientConfig } from 'appstash';
24
+ statements.push(createImportDeclaration('appstash', ['ClientConfig'], true));
25
+ // Import createClient from each target's ORM
26
+ for (const target of targets) {
27
+ const aliasName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}OrmClient`;
28
+ const specifier = t.importSpecifier(t.identifier(aliasName), t.identifier('createClient'));
29
+ statements.push(t.importDeclaration([specifier], t.stringLiteral(target.ormImportPath)));
30
+ }
31
+ // const store = createConfigStore('toolName');
32
+ statements.push(t.variableDeclaration('const', [
33
+ t.variableDeclarator(t.identifier('store'), t.callExpression(t.identifier('createConfigStore'), [
34
+ t.stringLiteral(toolName),
35
+ ])),
36
+ ]));
37
+ // export const getStore = () => store;
38
+ const getStoreExport = t.variableDeclaration('const', [
39
+ t.variableDeclarator(t.identifier('getStore'), t.arrowFunctionExpression([], t.identifier('store'))),
40
+ ]);
41
+ statements.push(t.exportNamedDeclaration(getStoreExport));
42
+ // export function getClientConfig(targetName: string, contextName?: string): ClientConfig
43
+ const targetNameParam = t.identifier('targetName');
44
+ targetNameParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword());
45
+ const contextNameParam = t.identifier('contextName');
46
+ contextNameParam.optional = true;
47
+ contextNameParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword());
48
+ const getClientConfigBody = t.blockStatement([
49
+ t.returnStatement(t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('getClientConfig')), [t.identifier('targetName'), t.identifier('contextName')])),
50
+ ]);
51
+ const getClientConfigFunc = t.functionDeclaration(t.identifier('getClientConfig'), [targetNameParam, contextNameParam], getClientConfigBody);
52
+ // Add return type annotation
53
+ const returnTypeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('ClientConfig')));
54
+ getClientConfigFunc.returnType = returnTypeAnnotation;
55
+ statements.push(t.exportNamedDeclaration(getClientConfigFunc));
56
+ // Generate typed factory for each target
57
+ for (const target of targets) {
58
+ const factoryName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}Client`;
59
+ const ormAliasName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}OrmClient`;
60
+ const ctxParam = t.identifier('contextName');
61
+ ctxParam.optional = true;
62
+ ctxParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword());
63
+ const factoryBody = t.blockStatement([
64
+ t.variableDeclaration('const', [
65
+ t.variableDeclarator(t.identifier('config'), t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('getClientConfig')), [t.stringLiteral(target.name), t.identifier('contextName')])),
66
+ ]),
67
+ t.returnStatement(t.callExpression(t.identifier(ormAliasName), [
68
+ t.objectExpression([
69
+ t.objectProperty(t.identifier('endpoint'), t.memberExpression(t.identifier('config'), t.identifier('endpoint'))),
70
+ t.objectProperty(t.identifier('headers'), t.memberExpression(t.identifier('config'), t.identifier('headers'))),
71
+ ]),
72
+ ])),
73
+ ]);
74
+ const factoryFunc = t.functionDeclaration(t.identifier(factoryName), [ctxParam], factoryBody);
75
+ statements.push(t.exportNamedDeclaration(factoryFunc));
76
+ }
77
+ const header = getGeneratedFileHeader('SDK helpers — typed per-target client factories with 3-tier credential resolution');
78
+ const code = generateCode(statements);
79
+ return {
80
+ fileName: 'helpers.ts',
81
+ content: header + '\n' + code,
82
+ };
83
+ }
@@ -47,12 +47,16 @@ export interface GenerateMultiTargetCliOptions {
47
47
  export declare function resolveBuiltinNames(targetNames: string[], userOverrides?: BuiltinNames): {
48
48
  auth: string;
49
49
  context: string;
50
+ config: string;
50
51
  };
51
52
  export declare function generateMultiTargetCli(options: GenerateMultiTargetCliOptions): GenerateCliResult;
52
53
  export { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator';
53
54
  export { generateTableCommand } from './table-command-generator';
54
55
  export { generateCustomCommand } from './custom-command-generator';
55
56
  export { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator';
57
+ export { generateConfigCommand } from './config-command-generator';
58
+ export { generateHelpersFile } from './helpers-generator';
59
+ export type { HelpersGeneratorInput } from './helpers-generator';
56
60
  export { generateContextCommand, generateAuthCommand, generateMultiTargetContextCommand, generateAuthCommandWithName, } from './infra-generator';
57
61
  export { generateReadme, generateAgentsDocs, getCliMcpTools, generateSkills, generateMultiTargetReadme, generateMultiTargetAgentsDocs, getMultiTargetCliMcpTools, generateMultiTargetSkills, } from './docs-generator';
58
62
  export type { MultiTargetDocsInput } from './docs-generator';
@@ -1,6 +1,8 @@
1
1
  import { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator';
2
+ import { generateConfigCommand } from './config-command-generator';
2
3
  import { generateCustomCommand } from './custom-command-generator';
3
4
  import { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator';
5
+ import { generateHelpersFile } from './helpers-generator';
4
6
  import { generateAuthCommand, generateAuthCommandWithName, generateContextCommand, generateMultiTargetContextCommand, } from './infra-generator';
5
7
  import { generateTableCommand } from './table-command-generator';
6
8
  import { generateUtilsFile, generateNodeFetchFile, generateEntryPointFile } from './utils-generator';
@@ -62,13 +64,17 @@ export function generateCli(options) {
62
64
  export function resolveBuiltinNames(targetNames, userOverrides) {
63
65
  let authName = userOverrides?.auth ?? 'auth';
64
66
  let contextName = userOverrides?.context ?? 'context';
67
+ let configName = userOverrides?.config ?? 'config';
65
68
  if (targetNames.includes(authName) && !userOverrides?.auth) {
66
69
  authName = 'credentials';
67
70
  }
68
71
  if (targetNames.includes(contextName) && !userOverrides?.context) {
69
72
  contextName = 'env';
70
73
  }
71
- return { auth: authName, context: contextName };
74
+ if (targetNames.includes(configName) && !userOverrides?.config) {
75
+ configName = 'vars';
76
+ }
77
+ return { auth: authName, context: contextName, config: configName };
72
78
  }
73
79
  export function generateMultiTargetCli(options) {
74
80
  const { toolName, targets } = options;
@@ -94,6 +100,14 @@ export function generateMultiTargetCli(options) {
94
100
  files.push(contextFile);
95
101
  const authFile = generateAuthCommandWithName(toolName, builtinNames.auth);
96
102
  files.push(authFile);
103
+ const configFile = generateConfigCommand(toolName, builtinNames.config);
104
+ files.push(configFile);
105
+ const helpersInputs = targets.map((t) => ({
106
+ name: t.name,
107
+ ormImportPath: t.ormImportPath,
108
+ }));
109
+ const helpersFile = generateHelpersFile(toolName, helpersInputs);
110
+ files.push(helpersFile);
97
111
  let totalTables = 0;
98
112
  let totalQueries = 0;
99
113
  let totalMutations = 0;
@@ -145,7 +159,7 @@ export function generateMultiTargetCli(options) {
145
159
  tables: totalTables,
146
160
  customQueries: totalQueries,
147
161
  customMutations: totalMutations,
148
- infraFiles: 4,
162
+ infraFiles: 6,
149
163
  totalFiles: files.length,
150
164
  },
151
165
  };
@@ -154,6 +168,8 @@ export { generateExecutorFile, generateMultiTargetExecutorFile } from './executo
154
168
  export { generateTableCommand } from './table-command-generator';
155
169
  export { generateCustomCommand } from './custom-command-generator';
156
170
  export { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator';
171
+ export { generateConfigCommand } from './config-command-generator';
172
+ export { generateHelpersFile } from './helpers-generator';
157
173
  export { generateContextCommand, generateAuthCommand, generateMultiTargetContextCommand, generateAuthCommandWithName, } from './infra-generator';
158
174
  export { generateReadme, generateAgentsDocs, getCliMcpTools, generateSkills, generateMultiTargetReadme, generateMultiTargetAgentsDocs, getMultiTargetCliMcpTools, generateMultiTargetSkills, } from './docs-generator';
159
175
  export { resolveDocsConfig } from '../docs-utils';
@@ -9,6 +9,7 @@ import { generateAllModelFiles } from './model-generator';
9
9
  export function generateOrm(options) {
10
10
  const { tables, customOperations, sharedTypesPath } = options;
11
11
  const commentsEnabled = options.config.codegen?.comments !== false;
12
+ const conditionEnabled = options.config.codegen?.condition !== false;
12
13
  const files = [];
13
14
  // Use shared types when a sharedTypesPath is provided (unified output mode)
14
15
  const useSharedTypes = !!sharedTypesPath;
@@ -29,7 +30,7 @@ export function generateOrm(options) {
29
30
  content: selectTypesFile.content,
30
31
  });
31
32
  // 2. Generate model files
32
- const modelFiles = generateAllModelFiles(tables, useSharedTypes);
33
+ const modelFiles = generateAllModelFiles(tables, useSharedTypes, { condition: conditionEnabled });
33
34
  for (const modelFile of modelFiles) {
34
35
  files.push({
35
36
  path: `models/${modelFile.fileName}`,
@@ -66,7 +67,7 @@ export function generateOrm(options) {
66
67
  }
67
68
  }
68
69
  }
69
- const inputTypesFile = generateInputTypesFile(typeRegistry ?? new Map(), usedInputTypes, tables, usedPayloadTypes, commentsEnabled);
70
+ const inputTypesFile = generateInputTypesFile(typeRegistry ?? new Map(), usedInputTypes, tables, usedPayloadTypes, commentsEnabled, { condition: conditionEnabled });
70
71
  files.push({
71
72
  path: inputTypesFile.fileName,
72
73
  content: inputTypesFile.content,
@@ -18,4 +18,6 @@ export declare function collectPayloadTypeNames(operations: Array<{
18
18
  /**
19
19
  * Generate comprehensive input-types.ts file using Babel AST
20
20
  */
21
- export declare function generateInputTypesFile(typeRegistry: TypeRegistry, usedInputTypes: Set<string>, tables?: CleanTable[], usedPayloadTypes?: Set<string>, comments?: boolean): GeneratedInputTypesFile;
21
+ export declare function generateInputTypesFile(typeRegistry: TypeRegistry, usedInputTypes: Set<string>, tables?: CleanTable[], usedPayloadTypes?: Set<string>, comments?: boolean, options?: {
22
+ condition?: boolean;
23
+ }): GeneratedInputTypesFile;
@@ -1024,9 +1024,9 @@ function buildTableCrudTypeNames(tables) {
1024
1024
  /**
1025
1025
  * Generate custom input type statements from TypeRegistry
1026
1026
  */
1027
- function generateCustomInputTypes(typeRegistry, usedInputTypes, tableCrudTypes, comments = true) {
1027
+ function generateCustomInputTypes(typeRegistry, usedInputTypes, tableCrudTypes, comments = true, alreadyGeneratedTypes) {
1028
1028
  const statements = [];
1029
- const generatedTypes = new Set();
1029
+ const generatedTypes = new Set(alreadyGeneratedTypes ?? []);
1030
1030
  const typesToGenerate = new Set(Array.from(usedInputTypes));
1031
1031
  // Filter out types we've already generated (exact matches for table CRUD types only)
1032
1032
  if (tableCrudTypes) {
@@ -1296,7 +1296,8 @@ function collectConditionExtraInputTypes(tables, typeRegistry) {
1296
1296
  /**
1297
1297
  * Generate comprehensive input-types.ts file using Babel AST
1298
1298
  */
1299
- export function generateInputTypesFile(typeRegistry, usedInputTypes, tables, usedPayloadTypes, comments = true) {
1299
+ export function generateInputTypesFile(typeRegistry, usedInputTypes, tables, usedPayloadTypes, comments = true, options) {
1300
+ const conditionEnabled = options?.condition !== false;
1300
1301
  const statements = [];
1301
1302
  const tablesList = tables ?? [];
1302
1303
  const hasTables = tablesList.length > 0;
@@ -1323,7 +1324,9 @@ export function generateInputTypesFile(typeRegistry, usedInputTypes, tables, use
1323
1324
  // 4b. Table condition types (simple equality filter)
1324
1325
  // Pass typeRegistry to merge plugin-injected condition fields
1325
1326
  // (e.g., vectorEmbedding from VectorSearchPlugin)
1326
- statements.push(...generateTableConditionTypes(tablesList, typeRegistry));
1327
+ if (conditionEnabled) {
1328
+ statements.push(...generateTableConditionTypes(tablesList, typeRegistry));
1329
+ }
1327
1330
  // 5. OrderBy types
1328
1331
  // Pass typeRegistry to merge plugin-injected orderBy values
1329
1332
  // (e.g., EMBEDDING_DISTANCE_ASC/DESC from VectorSearchPlugin)
@@ -1337,14 +1340,19 @@ export function generateInputTypesFile(typeRegistry, usedInputTypes, tables, use
1337
1340
  // 7. Custom input types from TypeRegistry
1338
1341
  // Also include any extra types referenced by plugin-injected condition fields
1339
1342
  const mergedUsedInputTypes = new Set(usedInputTypes);
1340
- if (hasTables) {
1343
+ if (hasTables && conditionEnabled) {
1341
1344
  const conditionExtraTypes = collectConditionExtraInputTypes(tablesList, typeRegistry);
1342
1345
  for (const typeName of conditionExtraTypes) {
1343
1346
  mergedUsedInputTypes.add(typeName);
1344
1347
  }
1345
1348
  }
1346
1349
  const tableCrudTypes = tables ? buildTableCrudTypeNames(tables) : undefined;
1347
- statements.push(...generateCustomInputTypes(typeRegistry, mergedUsedInputTypes, tableCrudTypes, comments));
1350
+ // Pass customScalarTypes + enumTypes as already-generated to avoid duplicate declarations
1351
+ const alreadyGenerated = new Set([
1352
+ ...customScalarTypes,
1353
+ ...enumTypes,
1354
+ ]);
1355
+ statements.push(...generateCustomInputTypes(typeRegistry, mergedUsedInputTypes, tableCrudTypes, comments, alreadyGenerated));
1348
1356
  // 8. Payload/return types for custom operations
1349
1357
  if (usedPayloadTypes && usedPayloadTypes.size > 0) {
1350
1358
  const alreadyGeneratedTypes = new Set();
@@ -5,5 +5,9 @@ export interface GeneratedModelFile {
5
5
  modelName: string;
6
6
  tableName: string;
7
7
  }
8
- export declare function generateModelFile(table: CleanTable, _useSharedTypes: boolean): GeneratedModelFile;
9
- export declare function generateAllModelFiles(tables: CleanTable[], useSharedTypes: boolean): GeneratedModelFile[];
8
+ export declare function generateModelFile(table: CleanTable, _useSharedTypes: boolean, options?: {
9
+ condition?: boolean;
10
+ }): GeneratedModelFile;
11
+ export declare function generateAllModelFiles(tables: CleanTable[], useSharedTypes: boolean, options?: {
12
+ condition?: boolean;
13
+ }): GeneratedModelFile[];