ts-procedures 6.1.0 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/agent_config/bin/setup.mjs +2 -2
  2. package/agent_config/claude-code/skills/ts-procedures/SKILL.md +1 -0
  3. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +1 -1
  4. package/agent_config/claude-code/skills/ts-procedures-kotlin/SKILL.md +1 -1
  5. package/agent_config/claude-code/skills/ts-procedures-swift/SKILL.md +119 -0
  6. package/agent_config/copilot/copilot-instructions.md +1 -0
  7. package/agent_config/cursor/cursorrules +1 -0
  8. package/agent_config/lib/install-claude.mjs +1 -1
  9. package/build/codegen/bin/cli.d.ts +17 -3
  10. package/build/codegen/bin/cli.js +79 -3
  11. package/build/codegen/bin/cli.js.map +1 -1
  12. package/build/codegen/index.d.ts +18 -1
  13. package/build/codegen/index.js +3 -0
  14. package/build/codegen/index.js.map +1 -1
  15. package/build/codegen/pipeline.d.ts +16 -5
  16. package/build/codegen/pipeline.js +44 -143
  17. package/build/codegen/pipeline.js.map +1 -1
  18. package/build/codegen/targets/_shared/error-schemas.d.ts +10 -0
  19. package/build/codegen/targets/_shared/error-schemas.js +17 -0
  20. package/build/codegen/targets/_shared/error-schemas.js.map +1 -0
  21. package/build/codegen/targets/_shared/error-schemas.test.d.ts +1 -0
  22. package/build/codegen/targets/_shared/error-schemas.test.js +38 -0
  23. package/build/codegen/targets/_shared/error-schemas.test.js.map +1 -0
  24. package/build/codegen/targets/_shared/indent.d.ts +6 -0
  25. package/build/codegen/targets/_shared/indent.js +13 -0
  26. package/build/codegen/targets/_shared/indent.js.map +1 -0
  27. package/build/codegen/targets/_shared/indent.test.d.ts +1 -0
  28. package/build/codegen/targets/_shared/indent.test.js +21 -0
  29. package/build/codegen/targets/_shared/indent.test.js.map +1 -0
  30. package/build/codegen/targets/_shared/pascal-case.d.ts +6 -0
  31. package/build/codegen/targets/_shared/pascal-case.js +13 -0
  32. package/build/codegen/targets/_shared/pascal-case.js.map +1 -0
  33. package/build/codegen/targets/_shared/pascal-case.test.d.ts +1 -0
  34. package/build/codegen/targets/_shared/pascal-case.test.js +25 -0
  35. package/build/codegen/targets/_shared/pascal-case.test.js.map +1 -0
  36. package/build/codegen/targets/_shared/path-utils.d.ts +12 -0
  37. package/build/codegen/targets/_shared/path-utils.js +20 -0
  38. package/build/codegen/targets/_shared/path-utils.js.map +1 -0
  39. package/build/codegen/targets/_shared/path-utils.test.d.ts +1 -0
  40. package/build/codegen/targets/_shared/path-utils.test.js +42 -0
  41. package/build/codegen/targets/_shared/path-utils.test.js.map +1 -0
  42. package/build/codegen/targets/_shared/pick-defined.d.ts +11 -0
  43. package/build/codegen/targets/_shared/pick-defined.js +21 -0
  44. package/build/codegen/targets/_shared/pick-defined.js.map +1 -0
  45. package/build/codegen/targets/_shared/pick-defined.test.d.ts +1 -0
  46. package/build/codegen/targets/_shared/pick-defined.test.js +25 -0
  47. package/build/codegen/targets/_shared/pick-defined.test.js.map +1 -0
  48. package/build/codegen/targets/_shared/route-slots.d.ts +17 -0
  49. package/build/codegen/targets/_shared/route-slots.js +17 -0
  50. package/build/codegen/targets/_shared/route-slots.js.map +1 -0
  51. package/build/codegen/targets/_shared/route-slots.test.d.ts +1 -0
  52. package/build/codegen/targets/_shared/route-slots.test.js +43 -0
  53. package/build/codegen/targets/_shared/route-slots.test.js.map +1 -0
  54. package/build/codegen/targets/_shared/target-run.d.ts +27 -0
  55. package/build/codegen/targets/_shared/target-run.js +2 -0
  56. package/build/codegen/targets/_shared/target-run.js.map +1 -0
  57. package/build/codegen/targets/_shared/write-files.d.ts +24 -0
  58. package/build/codegen/targets/_shared/write-files.js +35 -0
  59. package/build/codegen/targets/_shared/write-files.js.map +1 -0
  60. package/build/codegen/targets/_shared/write-files.test.d.ts +1 -0
  61. package/build/codegen/targets/_shared/write-files.test.js +79 -0
  62. package/build/codegen/targets/_shared/write-files.test.js.map +1 -0
  63. package/build/codegen/targets/kotlin/e2e-compile.test.js +1 -1
  64. package/build/codegen/targets/kotlin/e2e-compile.test.js.map +1 -1
  65. package/build/codegen/targets/kotlin/emit-route-kotlin.js +5 -22
  66. package/build/codegen/targets/kotlin/emit-route-kotlin.js.map +1 -1
  67. package/build/codegen/targets/kotlin/emit-scope-kotlin.js +4 -8
  68. package/build/codegen/targets/kotlin/emit-scope-kotlin.js.map +1 -1
  69. package/build/codegen/targets/kotlin/format-kotlin.d.ts +0 -12
  70. package/build/codegen/targets/kotlin/format-kotlin.js +0 -27
  71. package/build/codegen/targets/kotlin/format-kotlin.js.map +1 -1
  72. package/build/codegen/targets/kotlin/format-kotlin.test.js +1 -34
  73. package/build/codegen/targets/kotlin/format-kotlin.test.js.map +1 -1
  74. package/build/codegen/targets/kotlin/integration.test.js +1 -1
  75. package/build/codegen/targets/kotlin/integration.test.js.map +1 -1
  76. package/build/codegen/targets/kotlin/run.d.ts +11 -0
  77. package/build/codegen/targets/kotlin/run.js +51 -0
  78. package/build/codegen/targets/kotlin/run.js.map +1 -0
  79. package/build/codegen/targets/swift/access-level.test.d.ts +1 -0
  80. package/build/codegen/targets/swift/access-level.test.js +98 -0
  81. package/build/codegen/targets/swift/access-level.test.js.map +1 -0
  82. package/build/codegen/targets/swift/ajsc-adapter.d.ts +27 -0
  83. package/build/codegen/targets/swift/ajsc-adapter.js +38 -0
  84. package/build/codegen/targets/swift/ajsc-adapter.js.map +1 -0
  85. package/build/codegen/targets/swift/ajsc-adapter.test.d.ts +1 -0
  86. package/build/codegen/targets/swift/ajsc-adapter.test.js +37 -0
  87. package/build/codegen/targets/swift/ajsc-adapter.test.js.map +1 -0
  88. package/build/codegen/targets/swift/e2e-compile.test.d.ts +1 -0
  89. package/build/codegen/targets/swift/e2e-compile.test.js +57 -0
  90. package/build/codegen/targets/swift/e2e-compile.test.js.map +1 -0
  91. package/build/codegen/targets/swift/emit-route-swift.d.ts +15 -0
  92. package/build/codegen/targets/swift/emit-route-swift.js +64 -0
  93. package/build/codegen/targets/swift/emit-route-swift.js.map +1 -0
  94. package/build/codegen/targets/swift/emit-route-swift.test.d.ts +1 -0
  95. package/build/codegen/targets/swift/emit-route-swift.test.js +258 -0
  96. package/build/codegen/targets/swift/emit-route-swift.test.js.map +1 -0
  97. package/build/codegen/targets/swift/emit-scope-swift.d.ts +13 -0
  98. package/build/codegen/targets/swift/emit-scope-swift.js +36 -0
  99. package/build/codegen/targets/swift/emit-scope-swift.js.map +1 -0
  100. package/build/codegen/targets/swift/emit-scope-swift.test.d.ts +1 -0
  101. package/build/codegen/targets/swift/emit-scope-swift.test.js +136 -0
  102. package/build/codegen/targets/swift/emit-scope-swift.test.js.map +1 -0
  103. package/build/codegen/targets/swift/format-swift.d.ts +2 -0
  104. package/build/codegen/targets/swift/format-swift.js +10 -0
  105. package/build/codegen/targets/swift/format-swift.js.map +1 -0
  106. package/build/codegen/targets/swift/format-swift.test.d.ts +1 -0
  107. package/build/codegen/targets/swift/format-swift.test.js +14 -0
  108. package/build/codegen/targets/swift/format-swift.test.js.map +1 -0
  109. package/build/codegen/targets/swift/integration.test.d.ts +1 -0
  110. package/build/codegen/targets/swift/integration.test.js +53 -0
  111. package/build/codegen/targets/swift/integration.test.js.map +1 -0
  112. package/build/codegen/targets/swift/run.d.ts +11 -0
  113. package/build/codegen/targets/swift/run.js +47 -0
  114. package/build/codegen/targets/swift/run.js.map +1 -0
  115. package/build/codegen/targets/ts/run.d.ts +4 -0
  116. package/build/codegen/targets/ts/run.js +86 -0
  117. package/build/codegen/targets/ts/run.js.map +1 -0
  118. package/docs/codegen-kotlin.md +1 -0
  119. package/docs/codegen-swift.md +314 -0
  120. package/docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md +1 -1
  121. package/docs/superpowers/specs/2026-04-25-ajsc-v7-kotlin-polish-design.md +1 -1
  122. package/docs/superpowers/specs/2026-04-25-swift-codegen-design.md +264 -0
  123. package/package.json +2 -2
  124. package/src/codegen/bin/cli.ts +91 -7
  125. package/src/codegen/index.ts +24 -1
  126. package/src/codegen/pipeline.ts +52 -174
  127. package/src/codegen/targets/_shared/error-schemas.test.ts +42 -0
  128. package/src/codegen/targets/_shared/error-schemas.ts +17 -0
  129. package/src/codegen/targets/_shared/indent.test.ts +25 -0
  130. package/src/codegen/targets/_shared/indent.ts +12 -0
  131. package/src/codegen/targets/_shared/pascal-case.test.ts +30 -0
  132. package/src/codegen/targets/_shared/pascal-case.ts +12 -0
  133. package/src/codegen/targets/_shared/path-utils.test.ts +51 -0
  134. package/src/codegen/targets/_shared/path-utils.ts +21 -0
  135. package/src/codegen/targets/_shared/pick-defined.test.ts +48 -0
  136. package/src/codegen/targets/_shared/pick-defined.ts +23 -0
  137. package/src/codegen/targets/_shared/route-slots.test.ts +55 -0
  138. package/src/codegen/targets/_shared/route-slots.ts +32 -0
  139. package/src/codegen/targets/_shared/target-run.ts +28 -0
  140. package/src/codegen/targets/_shared/write-files.test.ts +110 -0
  141. package/src/codegen/targets/_shared/write-files.ts +53 -0
  142. package/src/codegen/targets/kotlin/e2e-compile.test.ts +1 -1
  143. package/src/codegen/targets/kotlin/emit-route-kotlin.ts +5 -25
  144. package/src/codegen/targets/kotlin/emit-scope-kotlin.ts +4 -9
  145. package/src/codegen/targets/kotlin/format-kotlin.test.ts +0 -44
  146. package/src/codegen/targets/kotlin/format-kotlin.ts +0 -32
  147. package/src/codegen/targets/kotlin/integration.test.ts +1 -1
  148. package/src/codegen/targets/kotlin/run.ts +78 -0
  149. package/src/codegen/targets/swift/__fixtures__/users-golden.swift +123 -0
  150. package/src/codegen/targets/swift/access-level.test.ts +108 -0
  151. package/src/codegen/targets/swift/ajsc-adapter.test.ts +47 -0
  152. package/src/codegen/targets/swift/ajsc-adapter.ts +67 -0
  153. package/src/codegen/targets/swift/e2e-compile.test.ts +66 -0
  154. package/src/codegen/targets/swift/emit-route-swift.test.ts +300 -0
  155. package/src/codegen/targets/swift/emit-route-swift.ts +90 -0
  156. package/src/codegen/targets/swift/emit-scope-swift.test.ts +164 -0
  157. package/src/codegen/targets/swift/emit-scope-swift.ts +59 -0
  158. package/src/codegen/targets/swift/format-swift.test.ts +23 -0
  159. package/src/codegen/targets/swift/format-swift.ts +9 -0
  160. package/src/codegen/targets/swift/integration.test.ts +80 -0
  161. package/src/codegen/targets/swift/run.ts +74 -0
  162. package/src/codegen/targets/ts/run.ts +117 -0
  163. /package/src/codegen/{targets/kotlin/__fixtures__ → __fixtures__}/users-envelope.json +0 -0
@@ -1,15 +1,17 @@
1
- import { mkdir, rm, writeFile } from 'node:fs/promises';
2
- import { join } from 'node:path';
3
1
  import { createHash } from 'node:crypto';
4
2
  import { groupRoutesByScope } from './group-routes.js';
5
- import { emitScopeFile } from './emit-scope.js';
6
- import { emitIndexFile } from './emit-index.js';
7
- import { emitErrorsFile } from './emit-errors.js';
8
- import { emitClientTypesFile } from './emit-client-types.js';
9
- import { emitClientRuntimeFile } from './emit-client-runtime.js';
10
3
  import { validateServiceName } from './naming.js';
11
- import { emitKotlinScope } from './targets/kotlin/emit-scope-kotlin.js';
12
- import { pickDefined } from './targets/kotlin/format-kotlin.js';
4
+ import { runKotlinPipeline } from './targets/kotlin/run.js';
5
+ import { runSwiftPipeline } from './targets/swift/run.js';
6
+ import { runTsPipeline } from './targets/ts/run.js';
7
+ /**
8
+ * Top-level codegen entry. Validates the service name, computes the source
9
+ * hash, groups routes by scope, then dispatches to the per-target run module.
10
+ *
11
+ * Per-target modules own their language-specific emission and the file-write
12
+ * tail (dryRun / cleanOutDir / mkdir / writeFile via
13
+ * `_shared/write-files.ts`).
14
+ */
13
15
  export async function runPipeline(options) {
14
16
  const { envelope, outDir, ajsc: ajscOpts, dryRun = false, namespaceTypes = false, selfContained = false, cleanOutDir = false } = options;
15
17
  const serviceName = options.serviceName ?? 'Api';
@@ -19,142 +21,41 @@ export async function runPipeline(options) {
19
21
  console.warn('[ts-procedures-codegen] --self-contained overrides --client-import-path; using ./_types');
20
22
  }
21
23
  const hash = createHash('md5').update(JSON.stringify(envelope)).digest('hex');
22
- const hashComment = `// Source hash: ${hash}`;
23
- const groups = groupRoutesByScope(envelope.routes);
24
- const groupArray = Array.from(groups.values());
25
- if (options.target === 'kotlin') {
26
- if (options.kotlinPackage == null) {
27
- throw new Error('[ts-procedures-codegen] target=kotlin requires kotlinPackage');
28
- }
29
- if (options.kotlinEmitter == null) {
30
- throw new Error('[ts-procedures-codegen] target=kotlin requires a kotlinEmitter (CLI resolves via resolveProductionKotlinEmitter)');
31
- }
32
- // Route errors are taxonomy keys (string[]); look up actual schemas from the
33
- // envelope's top-level errors array. Mirrors the existing TS scope emitter.
34
- const errorSchemas = new Map();
35
- for (const e of envelope.errors) {
36
- if (e.schema != null)
37
- errorSchemas.set(e.name, e.schema);
38
- }
39
- // Spec §"CLI flags" — `--array-item-naming`, `--depluralize`, `--uncountable-words`
40
- // also apply to the Kotlin target. The CLI parks them on `options.ajsc` (a TS-target
41
- // structure historically); copy the Kotlin-relevant subset onto the scope opts here.
42
- const ajscPassthrough = options.ajsc ?? {};
43
- const AJSC_PASSTHROUGH_KEYS = ['arrayItemNaming', 'depluralize', 'uncountableWords'];
44
- const kotlinFiles = [];
45
- const allSkipped = [];
46
- for (const group of groupArray) {
47
- const emitted = emitKotlinScope(group, {
48
- kotlinPackage: options.kotlinPackage,
49
- sourceHash: hash,
50
- ...(options.kotlinSerializer !== undefined ? { serializer: options.kotlinSerializer } : {}),
51
- ...(options.unsupportedUnions !== undefined ? { unsupportedUnions: options.unsupportedUnions } : {}),
52
- ...pickDefined(ajscPassthrough, AJSC_PASSTHROUGH_KEYS),
53
- }, options.kotlinEmitter, errorSchemas);
54
- kotlinFiles.push({ path: join(outDir, emitted.filename), code: emitted.code });
55
- allSkipped.push(...emitted.skippedStreams);
56
- }
57
- if (allSkipped.length > 0) {
58
- console.log(`[ts-procedures-codegen] Skipped ${allSkipped.length} stream route${allSkipped.length === 1 ? '' : 's'} (kotlin target): ${allSkipped.join(', ')}`);
59
- }
60
- if (dryRun) {
61
- if (cleanOutDir) {
62
- console.log(`[dry-run] Would clean outDir: ${outDir}`);
63
- }
64
- for (const f of kotlinFiles) {
65
- const bytes = Buffer.byteLength(f.code, 'utf-8');
66
- console.log(`[dry-run] Would write: ${f.path} (${bytes} bytes)`);
67
- }
68
- }
69
- else {
70
- if (cleanOutDir) {
71
- await rm(outDir, { recursive: true, force: true });
72
- }
73
- await mkdir(outDir, { recursive: true });
74
- for (const f of kotlinFiles) {
75
- await writeFile(f.path, f.code, 'utf-8');
76
- }
77
- }
78
- return kotlinFiles;
79
- }
80
- // Error keys that will be emitted in `_errors.ts` — only those with a schema.
81
- // Scope emit uses this to filter `route.errors` so generated code never
82
- // references an undefined error type.
83
- const errorKeys = new Set(envelope.errors.filter((e) => e.schema != null).map((e) => e.name));
84
- if (selfContained) {
85
- for (const group of groupArray) {
86
- if (group.scopeKey === '_types' || group.scopeKey === '_client') {
87
- throw new Error(`[ts-procedures-codegen] Scope "${group.scopeKey}" conflicts with self-contained mode reserved filename "${group.scopeKey}.ts". Rename the scope to avoid collision.`);
88
- }
89
- }
90
- }
91
- const files = [];
92
- for (const group of groupArray) {
93
- const rawCode = await emitScopeFile(group, {
94
- ajsc: ajscOpts,
95
- clientImportPath,
96
- namespaceTypes,
97
- serviceName,
98
- errorKeys: errorKeys.size > 0 ? errorKeys : undefined,
99
- });
100
- const lines = rawCode.split('\n');
101
- lines.splice(1, 0, hashComment);
102
- const code = lines.join('\n');
103
- files.push({ path: join(outDir, `${group.scopeKey}.ts`), code });
104
- }
105
- const errorsCode = await emitErrorsFile(envelope.errors, { ajsc: ajscOpts, clientImportPath, namespaceTypes, serviceName });
106
- const hasErrors = errorsCode != null;
107
- if (errorsCode != null) {
108
- const errorsLines = errorsCode.split('\n');
109
- errorsLines.splice(1, 0, hashComment);
110
- const errorsWithHash = errorsLines.join('\n');
111
- files.push({ path: join(outDir, '_errors.ts'), code: errorsWithHash });
112
- }
113
- // In self-contained mode types come from `./_types` but the runtime
114
- // (`createClient`) lives in `./_client`. In regular mode both share the
115
- // single `clientImportPath` (e.g. `ts-procedures/client`).
116
- const clientRuntimeImportPath = selfContained ? './_client' : clientImportPath;
117
- const rawIndexCode = emitIndexFile(groupArray, {
24
+ const groups = Array.from(groupRoutesByScope(envelope.routes).values());
25
+ const base = {
26
+ envelope,
27
+ outDir,
28
+ hash,
29
+ groups,
30
+ serviceName,
31
+ ajsc: ajscOpts,
118
32
  clientImportPath,
119
- clientRuntimeImportPath,
120
- hasErrors,
33
+ dryRun,
121
34
  namespaceTypes,
122
- serviceName,
123
- });
124
- const indexLines = rawIndexCode.split('\n');
125
- indexLines.splice(1, 0, hashComment);
126
- const indexCode = indexLines.join('\n');
127
- files.push({ path: join(outDir, 'index.ts'), code: indexCode });
128
- if (selfContained) {
129
- const rawTypesCode = await emitClientTypesFile();
130
- const typesLines = rawTypesCode.split('\n');
131
- typesLines.splice(1, 0, hashComment);
132
- const typesCode = typesLines.join('\n');
133
- files.push({ path: join(outDir, '_types.ts'), code: typesCode });
134
- const rawClientCode = await emitClientRuntimeFile();
135
- const clientLines = rawClientCode.split('\n');
136
- clientLines.splice(1, 0, hashComment);
137
- const clientCode = clientLines.join('\n');
138
- files.push({ path: join(outDir, '_client.ts'), code: clientCode });
139
- }
140
- if (dryRun) {
141
- if (cleanOutDir) {
142
- console.log(`[dry-run] Would clean outDir: ${outDir}`);
143
- }
144
- for (const file of files) {
145
- const bytes = Buffer.byteLength(file.code, 'utf-8');
146
- console.log(`[dry-run] Would write: ${file.path} (${bytes} bytes)`);
147
- }
148
- }
149
- else {
150
- if (cleanOutDir) {
151
- await rm(outDir, { recursive: true, force: true });
152
- }
153
- await mkdir(outDir, { recursive: true });
154
- for (const file of files) {
155
- await writeFile(file.path, file.code, 'utf-8');
156
- }
35
+ selfContained,
36
+ cleanOutDir,
37
+ };
38
+ switch (options.target) {
39
+ case 'kotlin':
40
+ return runKotlinPipeline({
41
+ ...base,
42
+ kotlinPackage: options.kotlinPackage,
43
+ kotlinSerializer: options.kotlinSerializer,
44
+ unsupportedUnions: options.unsupportedUnions,
45
+ kotlinEmitter: options.kotlinEmitter,
46
+ });
47
+ case 'swift':
48
+ return runSwiftPipeline({
49
+ ...base,
50
+ swiftSerializer: options.swiftSerializer,
51
+ swiftAccessLevel: options.swiftAccessLevel,
52
+ unsupportedUnions: options.unsupportedUnions,
53
+ swiftEmitter: options.swiftEmitter,
54
+ });
55
+ case 'ts':
56
+ case undefined:
57
+ default:
58
+ return runTsPipeline(base);
157
59
  }
158
- return files;
159
60
  }
160
61
  //# sourceMappingURL=pipeline.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/codegen/pipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/codegen/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AA0BnD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAwB;IACxD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,EAAE,cAAc,GAAG,KAAK,EAAE,aAAa,GAAG,KAAK,EAAE,WAAW,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IACxI,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,KAAK,CAAA;IAChD,mBAAmB,CAAC,WAAW,CAAC,CAAA;IAEhC,MAAM,gBAAgB,GAAG,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAA;IAC9E,IAAI,aAAa,IAAI,OAAO,CAAC,gBAAgB,IAAI,IAAI,EAAE,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,yFAAyF,CAAC,CAAA;IACzG,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC7E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;IAEvE,MAAM,IAAI,GAAG;QACX,QAAQ;QACR,MAAM;QACN,IAAI;QACJ,MAAM;QACN,WAAW;QACX,IAAI,EAAE,QAAQ;QACd,gBAAgB;QAChB,MAAM;QACN,cAAc;QACd,aAAa;QACb,WAAW;KACZ,CAAA;IAED,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,QAAQ;YACX,OAAO,iBAAiB,CAAC;gBACvB,GAAG,IAAI;gBACP,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;gBAC1C,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;gBAC5C,aAAa,EAAE,OAAO,CAAC,aAAa;aACrC,CAAC,CAAA;QACJ,KAAK,OAAO;YACV,OAAO,gBAAgB,CAAC;gBACtB,GAAG,IAAI;gBACP,eAAe,EAAE,OAAO,CAAC,eAAe;gBACxC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;gBAC1C,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;gBAC5C,YAAY,EAAE,OAAO,CAAC,YAAY;aACnC,CAAC,CAAA;QACJ,KAAK,IAAI,CAAC;QACV,KAAK,SAAS,CAAC;QACf;YACE,OAAO,aAAa,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ErrorDoc } from '../../../implementations/types.js';
2
+ /**
3
+ * Builds a lookup map from a {@link DocEnvelope}'s top-level `errors` array
4
+ * keyed by `name`. Only entries with a `schema` are included — errors
5
+ * documented without a schema cannot have a corresponding generated type.
6
+ *
7
+ * Targets pass this map to per-route emission so taxonomy keys on
8
+ * `route.errors` (a `string[]`) can be resolved to actual JSON Schemas.
9
+ */
10
+ export declare function buildErrorSchemasMap(errors: readonly ErrorDoc[]): Map<string, unknown>;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Builds a lookup map from a {@link DocEnvelope}'s top-level `errors` array
3
+ * keyed by `name`. Only entries with a `schema` are included — errors
4
+ * documented without a schema cannot have a corresponding generated type.
5
+ *
6
+ * Targets pass this map to per-route emission so taxonomy keys on
7
+ * `route.errors` (a `string[]`) can be resolved to actual JSON Schemas.
8
+ */
9
+ export function buildErrorSchemasMap(errors) {
10
+ const errorSchemas = new Map();
11
+ for (const e of errors) {
12
+ if (e.schema != null)
13
+ errorSchemas.set(e.name, e.schema);
14
+ }
15
+ return errorSchemas;
16
+ }
17
+ //# sourceMappingURL=error-schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-schemas.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/error-schemas.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA2B;IAC9D,MAAM,YAAY,GAAG,IAAI,GAAG,EAAmB,CAAA;IAC/C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI;YAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;IAC1D,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { buildErrorSchemasMap } from './error-schemas.js';
3
+ describe('buildErrorSchemasMap', () => {
4
+ it('returns an empty map when there are no errors', () => {
5
+ expect(buildErrorSchemasMap([])).toEqual(new Map());
6
+ });
7
+ it('includes errors with schemas', () => {
8
+ const schemaA = { type: 'object', tag: 'a' };
9
+ const schemaB = { type: 'object', tag: 'b' };
10
+ const errors = [
11
+ { name: 'A', statusCode: 400, description: '', schema: schemaA },
12
+ { name: 'B', statusCode: 500, description: '', schema: schemaB },
13
+ ];
14
+ const map = buildErrorSchemasMap(errors);
15
+ expect(map.size).toBe(2);
16
+ expect(map.get('A')).toBe(schemaA);
17
+ expect(map.get('B')).toBe(schemaB);
18
+ });
19
+ it('skips errors without a schema', () => {
20
+ const schemaA = { type: 'object' };
21
+ const errors = [
22
+ { name: 'A', statusCode: 400, description: '', schema: schemaA },
23
+ { name: 'NoSchema', statusCode: 500, description: '' },
24
+ ];
25
+ const map = buildErrorSchemasMap(errors);
26
+ expect(map.size).toBe(1);
27
+ expect(map.has('A')).toBe(true);
28
+ expect(map.has('NoSchema')).toBe(false);
29
+ });
30
+ it('keys the map by error name', () => {
31
+ const schema = { type: 'object' };
32
+ const map = buildErrorSchemasMap([
33
+ { name: 'NotFound', statusCode: 404, description: '', schema },
34
+ ]);
35
+ expect(Array.from(map.keys())).toEqual(['NotFound']);
36
+ });
37
+ });
38
+ //# sourceMappingURL=error-schemas.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-schemas.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/error-schemas.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAGzD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QAC5C,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QAC5C,MAAM,MAAM,GAAe;YACzB,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;YAChE,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;SACjE,CAAA;QACD,MAAM,GAAG,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;QACxC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAClC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;QAClC,MAAM,MAAM,GAAe;YACzB,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;YAChE,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE;SACvD,CAAA;QACD,MAAM,GAAG,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;QACxC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;QACjC,MAAM,GAAG,GAAG,oBAAoB,CAAC;YAC/B,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE;SAC/D,CAAC,CAAA;QACF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Indents every non-blank line of `text` by `level * 4` spaces. Blank lines
3
+ * are preserved as empty (no trailing whitespace). Suitable for languages
4
+ * that use 4-space indentation (Kotlin, Swift).
5
+ */
6
+ export declare function indent(text: string, level: number): string;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Indents every non-blank line of `text` by `level * 4` spaces. Blank lines
3
+ * are preserved as empty (no trailing whitespace). Suitable for languages
4
+ * that use 4-space indentation (Kotlin, Swift).
5
+ */
6
+ export function indent(text, level) {
7
+ const prefix = ' '.repeat(level);
8
+ return text
9
+ .split('\n')
10
+ .map((line) => (line.length === 0 ? line : `${prefix}${line}`))
11
+ .join('\n');
12
+ }
13
+ //# sourceMappingURL=indent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/indent.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,KAAa;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACnC,OAAO,IAAI;SACR,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC;SAC9D,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { indent } from './indent.js';
3
+ describe('indent', () => {
4
+ it('indents every line by 4 spaces per level', () => {
5
+ expect(indent('a\nb', 1)).toBe(' a\n b');
6
+ expect(indent('a', 2)).toBe(' a');
7
+ });
8
+ it('preserves blank lines without trailing whitespace when indenting', () => {
9
+ expect(indent('a\n\nb', 1)).toBe(' a\n\n b');
10
+ });
11
+ it('returns the input unchanged at level 0', () => {
12
+ expect(indent('a\n\nb', 0)).toBe('a\n\nb');
13
+ });
14
+ it('indents a single line', () => {
15
+ expect(indent('hello', 1)).toBe(' hello');
16
+ });
17
+ it('returns empty string for empty input', () => {
18
+ expect(indent('', 1)).toBe('');
19
+ });
20
+ });
21
+ //# sourceMappingURL=indent.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/indent.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAC9C,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Converts a kebab-case (or single-word) scope key to PascalCase. Used by
3
+ * codegen targets to derive top-level type/namespace identifiers from scope
4
+ * names (e.g. `user-management` → `UserManagement`).
5
+ */
6
+ export declare function pascalCase(scope: string): string;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Converts a kebab-case (or single-word) scope key to PascalCase. Used by
3
+ * codegen targets to derive top-level type/namespace identifiers from scope
4
+ * names (e.g. `user-management` → `UserManagement`).
5
+ */
6
+ export function pascalCase(scope) {
7
+ return scope
8
+ .split('-')
9
+ .filter((p) => p.length > 0)
10
+ .map((p) => p.charAt(0).toUpperCase() + p.slice(1))
11
+ .join('');
12
+ }
13
+ //# sourceMappingURL=pascal-case.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pascal-case.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/pascal-case.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,EAAE,CAAC,CAAA;AACb,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { pascalCase } from './pascal-case.js';
3
+ describe('pascalCase', () => {
4
+ it('converts a single-word scope', () => {
5
+ expect(pascalCase('users')).toBe('Users');
6
+ });
7
+ it('converts a kebab-case scope', () => {
8
+ expect(pascalCase('user-management')).toBe('UserManagement');
9
+ });
10
+ it('handles multi-segment kebab-case', () => {
11
+ expect(pascalCase('a-b-c')).toBe('ABC');
12
+ });
13
+ it('drops empty segments from leading/trailing/double dashes', () => {
14
+ expect(pascalCase('-users')).toBe('Users');
15
+ expect(pascalCase('users-')).toBe('Users');
16
+ expect(pascalCase('user--mgmt')).toBe('UserMgmt');
17
+ });
18
+ it('returns empty string for empty input', () => {
19
+ expect(pascalCase('')).toBe('');
20
+ });
21
+ it('preserves casing of letters after the leading character', () => {
22
+ expect(pascalCase('user-API')).toBe('UserAPI');
23
+ });
24
+ });
25
+ //# sourceMappingURL=pascal-case.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pascal-case.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/pascal-case.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC1C,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC1C,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Language-agnostic path-template utilities used by every codegen target that
3
+ * emits HTTP routes. Routes carry colon-prefixed path templates (e.g.
4
+ * `/users/:id`); targets typically need both the brace form (`/users/{id}`)
5
+ * for documentation/template constants and the parameter-name list for
6
+ * generating typed path-builder functions.
7
+ */
8
+ export declare const COLON_PARAM_RE: RegExp;
9
+ /** Converts colon-prefixed path params (`:foo`) to brace form (`{foo}`). */
10
+ export declare function toBracePath(template: string): string;
11
+ /** Extracts the parameter names from a colon-prefixed path template. */
12
+ export declare function pathParamNames(template: string): string[];
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Language-agnostic path-template utilities used by every codegen target that
3
+ * emits HTTP routes. Routes carry colon-prefixed path templates (e.g.
4
+ * `/users/:id`); targets typically need both the brace form (`/users/{id}`)
5
+ * for documentation/template constants and the parameter-name list for
6
+ * generating typed path-builder functions.
7
+ */
8
+ export const COLON_PARAM_RE = /:([A-Za-z_][A-Za-z0-9_]*)/g;
9
+ /** Converts colon-prefixed path params (`:foo`) to brace form (`{foo}`). */
10
+ export function toBracePath(template) {
11
+ return template.replace(COLON_PARAM_RE, '{$1}');
12
+ }
13
+ /** Extracts the parameter names from a colon-prefixed path template. */
14
+ export function pathParamNames(template) {
15
+ const names = [];
16
+ for (const match of template.matchAll(COLON_PARAM_RE))
17
+ names.push(match[1]);
18
+ return names;
19
+ }
20
+ //# sourceMappingURL=path-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/path-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,4BAA4B,CAAA;AAE1D,4EAA4E;AAC5E,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;AACjD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAA;IAC5E,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { COLON_PARAM_RE, toBracePath, pathParamNames } from './path-utils.js';
3
+ describe('path-utils', () => {
4
+ describe('toBracePath', () => {
5
+ it('converts colon params to brace form', () => {
6
+ expect(toBracePath('/users/:id')).toBe('/users/{id}');
7
+ });
8
+ it('converts multiple params', () => {
9
+ expect(toBracePath('/orgs/:orgId/users/:userId')).toBe('/orgs/{orgId}/users/{userId}');
10
+ });
11
+ it('returns the template unchanged when there are no params', () => {
12
+ expect(toBracePath('/users')).toBe('/users');
13
+ });
14
+ it('supports underscore-prefixed param names', () => {
15
+ expect(toBracePath('/x/:_id')).toBe('/x/{_id}');
16
+ });
17
+ it('does not match leading-digit identifiers', () => {
18
+ // ":1abc" is not a valid identifier; should not be rewritten.
19
+ expect(toBracePath('/x/:1abc')).toBe('/x/:1abc');
20
+ });
21
+ });
22
+ describe('pathParamNames', () => {
23
+ it('returns an empty list for templates without params', () => {
24
+ expect(pathParamNames('/users')).toEqual([]);
25
+ });
26
+ it('returns the single param name', () => {
27
+ expect(pathParamNames('/users/:id')).toEqual(['id']);
28
+ });
29
+ it('preserves the order of multiple params', () => {
30
+ expect(pathParamNames('/orgs/:orgId/users/:userId')).toEqual(['orgId', 'userId']);
31
+ });
32
+ it('matches identifiers with digits and underscores', () => {
33
+ expect(pathParamNames('/x/:user_id1')).toEqual(['user_id1']);
34
+ });
35
+ });
36
+ describe('COLON_PARAM_RE', () => {
37
+ it('is a global regex (so matchAll works)', () => {
38
+ expect(COLON_PARAM_RE.global).toBe(true);
39
+ });
40
+ });
41
+ });
42
+ //# sourceMappingURL=path-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/path-utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAE7E,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACvD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,MAAM,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAA;QACxF,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACjD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,8DAA8D;YAC9D,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;QACtD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAA;QACnF,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;QAC9D,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Returns a new object containing only the keys of `src` whose values are
3
+ * not `undefined`. Useful for building option objects where unset keys must
4
+ * be ABSENT (not `undefined`-valued), so they don't shadow downstream
5
+ * defaults — e.g., when forwarding into a target's `Emit*Options`.
6
+ *
7
+ * @example
8
+ * pickDefined({ a: 1, b: undefined, c: false }, ['a', 'b', 'c'])
9
+ * // → { a: 1, c: false }
10
+ */
11
+ export declare function pickDefined<T extends object, K extends keyof T>(src: T, keys: readonly K[]): Partial<Pick<T, K>>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Returns a new object containing only the keys of `src` whose values are
3
+ * not `undefined`. Useful for building option objects where unset keys must
4
+ * be ABSENT (not `undefined`-valued), so they don't shadow downstream
5
+ * defaults — e.g., when forwarding into a target's `Emit*Options`.
6
+ *
7
+ * @example
8
+ * pickDefined({ a: 1, b: undefined, c: false }, ['a', 'b', 'c'])
9
+ * // → { a: 1, c: false }
10
+ */
11
+ export function pickDefined(src, keys) {
12
+ const out = {};
13
+ for (const key of keys) {
14
+ const value = src[key];
15
+ if (value !== undefined) {
16
+ out[key] = value;
17
+ }
18
+ }
19
+ return out;
20
+ }
21
+ //# sourceMappingURL=pick-defined.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pick-defined.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/pick-defined.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,GAAM,EACN,IAAkB;IAElB,MAAM,GAAG,GAAwB,EAAE,CAAA;IACnC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;QACtB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QAClB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { pickDefined } from './pick-defined.js';
3
+ describe('pickDefined', () => {
4
+ it('returns only the keys whose values are not undefined', () => {
5
+ expect(pickDefined({ a: 1, b: undefined, c: 3 }, ['a', 'b', 'c'])).toEqual({ a: 1, c: 3 });
6
+ });
7
+ it('preserves the literal `false` value for boolean opts', () => {
8
+ expect(pickDefined({ depluralize: false, x: undefined }, ['depluralize', 'x'])).toEqual({ depluralize: false });
9
+ });
10
+ it('preserves the literal `false` for `string | false` opts (e.g. arrayItemNaming)', () => {
11
+ const result = pickDefined({ arrayItemNaming: false }, ['arrayItemNaming']);
12
+ expect(result).toEqual({ arrayItemNaming: false });
13
+ expect('arrayItemNaming' in result).toBe(true);
14
+ });
15
+ it('omits keys not in the keys list even if they are defined on src', () => {
16
+ expect(pickDefined({ a: 1, b: 2 }, ['a'])).toEqual({ a: 1 });
17
+ });
18
+ it('returns an empty object when all keys are undefined', () => {
19
+ expect(pickDefined({ a: undefined, b: undefined }, ['a', 'b'])).toEqual({});
20
+ });
21
+ it('returns an empty object when keys is empty', () => {
22
+ expect(pickDefined({ a: 1 }, [])).toEqual({});
23
+ });
24
+ });
25
+ //# sourceMappingURL=pick-defined.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pick-defined.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/pick-defined.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CACJ,WAAW,CACT,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAA4C,EACtE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAChB,CACF,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CACJ,WAAW,CACT,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAA2C,EAC7E,CAAC,aAAa,EAAE,GAAG,CAAC,CACrB,CACF,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QAExF,MAAM,MAAM,GAAG,WAAW,CAAmB,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAA;QAC7F,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAA;QAClD,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CACJ,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAgC,EAAE,CAAC,GAAG,CAAC,CAAC,CACjE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IACrB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,CACJ,WAAW,CACT,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAgC,EAC5D,CAAC,GAAG,EAAE,GAAG,CAAC,CACX,CACF,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACf,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAa,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,17 @@
1
+ import type { AnyHttpRouteDoc } from '../../../implementations/types.js';
2
+ /**
3
+ * A "slot" is one of the deterministic schema sources a route exposes:
4
+ * `pathParams`, `query`, `body` (under `schema.input`) and the response
5
+ * (`schema.returnType`). Targets emit one type per non-null slot.
6
+ */
7
+ export interface RouteSlot {
8
+ /** Stable identifier used as the emitted type's `rootTypeName`. */
9
+ rootName: string;
10
+ /** The raw JSON Schema source for this slot, or `null`/`undefined` when absent. */
11
+ source: unknown;
12
+ }
13
+ /**
14
+ * Returns the deterministic ordered slot list for a route, filtered to slots
15
+ * with non-null sources. Order is fixed at the module level for stable output.
16
+ */
17
+ export declare function extractRouteSlots(route: AnyHttpRouteDoc): RouteSlot[];