ts-procedures 6.0.2 → 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 (199) hide show
  1. package/agent_config/bin/setup.mjs +2 -2
  2. package/agent_config/claude-code/skills/ts-procedures/SKILL.md +2 -0
  3. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +2 -0
  4. package/agent_config/claude-code/skills/ts-procedures-kotlin/SKILL.md +106 -0
  5. package/agent_config/claude-code/skills/ts-procedures-swift/SKILL.md +119 -0
  6. package/agent_config/copilot/copilot-instructions.md +3 -0
  7. package/agent_config/cursor/cursorrules +3 -0
  8. package/agent_config/lib/install-claude.mjs +1 -1
  9. package/build/codegen/bin/cli.d.ts +39 -0
  10. package/build/codegen/bin/cli.js +164 -0
  11. package/build/codegen/bin/cli.js.map +1 -1
  12. package/build/codegen/bin/cli.test.js +180 -1
  13. package/build/codegen/bin/cli.test.js.map +1 -1
  14. package/build/codegen/index.d.ts +36 -0
  15. package/build/codegen/index.js +8 -0
  16. package/build/codegen/index.js.map +1 -1
  17. package/build/codegen/pipeline.d.ts +22 -4
  18. package/build/codegen/pipeline.js +44 -86
  19. package/build/codegen/pipeline.js.map +1 -1
  20. package/build/codegen/pipeline.test.js +162 -0
  21. package/build/codegen/pipeline.test.js.map +1 -1
  22. package/build/codegen/targets/_shared/error-schemas.d.ts +10 -0
  23. package/build/codegen/targets/_shared/error-schemas.js +17 -0
  24. package/build/codegen/targets/_shared/error-schemas.js.map +1 -0
  25. package/build/codegen/targets/_shared/error-schemas.test.d.ts +1 -0
  26. package/build/codegen/targets/_shared/error-schemas.test.js +38 -0
  27. package/build/codegen/targets/_shared/error-schemas.test.js.map +1 -0
  28. package/build/codegen/targets/_shared/indent.d.ts +6 -0
  29. package/build/codegen/targets/_shared/indent.js +13 -0
  30. package/build/codegen/targets/_shared/indent.js.map +1 -0
  31. package/build/codegen/targets/_shared/indent.test.d.ts +1 -0
  32. package/build/codegen/targets/_shared/indent.test.js +21 -0
  33. package/build/codegen/targets/_shared/indent.test.js.map +1 -0
  34. package/build/codegen/targets/_shared/pascal-case.d.ts +6 -0
  35. package/build/codegen/targets/_shared/pascal-case.js +13 -0
  36. package/build/codegen/targets/_shared/pascal-case.js.map +1 -0
  37. package/build/codegen/targets/_shared/pascal-case.test.d.ts +1 -0
  38. package/build/codegen/targets/_shared/pascal-case.test.js +25 -0
  39. package/build/codegen/targets/_shared/pascal-case.test.js.map +1 -0
  40. package/build/codegen/targets/_shared/path-utils.d.ts +12 -0
  41. package/build/codegen/targets/_shared/path-utils.js +20 -0
  42. package/build/codegen/targets/_shared/path-utils.js.map +1 -0
  43. package/build/codegen/targets/_shared/path-utils.test.d.ts +1 -0
  44. package/build/codegen/targets/_shared/path-utils.test.js +42 -0
  45. package/build/codegen/targets/_shared/path-utils.test.js.map +1 -0
  46. package/build/codegen/targets/_shared/pick-defined.d.ts +11 -0
  47. package/build/codegen/targets/_shared/pick-defined.js +21 -0
  48. package/build/codegen/targets/_shared/pick-defined.js.map +1 -0
  49. package/build/codegen/targets/_shared/pick-defined.test.d.ts +1 -0
  50. package/build/codegen/targets/_shared/pick-defined.test.js +25 -0
  51. package/build/codegen/targets/_shared/pick-defined.test.js.map +1 -0
  52. package/build/codegen/targets/_shared/route-slots.d.ts +17 -0
  53. package/build/codegen/targets/_shared/route-slots.js +17 -0
  54. package/build/codegen/targets/_shared/route-slots.js.map +1 -0
  55. package/build/codegen/targets/_shared/route-slots.test.d.ts +1 -0
  56. package/build/codegen/targets/_shared/route-slots.test.js +43 -0
  57. package/build/codegen/targets/_shared/route-slots.test.js.map +1 -0
  58. package/build/codegen/targets/_shared/target-run.d.ts +27 -0
  59. package/build/codegen/targets/_shared/target-run.js +2 -0
  60. package/build/codegen/targets/_shared/target-run.js.map +1 -0
  61. package/build/codegen/targets/_shared/write-files.d.ts +24 -0
  62. package/build/codegen/targets/_shared/write-files.js +35 -0
  63. package/build/codegen/targets/_shared/write-files.js.map +1 -0
  64. package/build/codegen/targets/_shared/write-files.test.d.ts +1 -0
  65. package/build/codegen/targets/_shared/write-files.test.js +79 -0
  66. package/build/codegen/targets/_shared/write-files.test.js.map +1 -0
  67. package/build/codegen/targets/kotlin/ajsc-adapter.d.ts +6 -4
  68. package/build/codegen/targets/kotlin/ajsc-adapter.js +12 -7
  69. package/build/codegen/targets/kotlin/ajsc-adapter.js.map +1 -1
  70. package/build/codegen/targets/kotlin/ajsc-adapter.test.js +20 -2
  71. package/build/codegen/targets/kotlin/ajsc-adapter.test.js.map +1 -1
  72. package/build/codegen/targets/kotlin/e2e-compile.test.js +41 -9
  73. package/build/codegen/targets/kotlin/e2e-compile.test.js.map +1 -1
  74. package/build/codegen/targets/kotlin/emit-route-kotlin.d.ts +6 -2
  75. package/build/codegen/targets/kotlin/emit-route-kotlin.js +18 -28
  76. package/build/codegen/targets/kotlin/emit-route-kotlin.js.map +1 -1
  77. package/build/codegen/targets/kotlin/emit-route-kotlin.test.js +120 -1
  78. package/build/codegen/targets/kotlin/emit-route-kotlin.test.js.map +1 -1
  79. package/build/codegen/targets/kotlin/emit-scope-kotlin.d.ts +4 -1
  80. package/build/codegen/targets/kotlin/emit-scope-kotlin.js +12 -11
  81. package/build/codegen/targets/kotlin/emit-scope-kotlin.js.map +1 -1
  82. package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js +39 -0
  83. package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js.map +1 -1
  84. package/build/codegen/targets/kotlin/format-kotlin.d.ts +0 -1
  85. package/build/codegen/targets/kotlin/format-kotlin.js +0 -7
  86. package/build/codegen/targets/kotlin/format-kotlin.js.map +1 -1
  87. package/build/codegen/targets/kotlin/format-kotlin.test.js +1 -8
  88. package/build/codegen/targets/kotlin/format-kotlin.test.js.map +1 -1
  89. package/build/codegen/targets/kotlin/integration.test.js +27 -10
  90. package/build/codegen/targets/kotlin/integration.test.js.map +1 -1
  91. package/build/codegen/targets/kotlin/probe-unsupported-unions.test.d.ts +1 -0
  92. package/build/codegen/targets/kotlin/probe-unsupported-unions.test.js +50 -0
  93. package/build/codegen/targets/kotlin/probe-unsupported-unions.test.js.map +1 -0
  94. package/build/codegen/targets/kotlin/run.d.ts +11 -0
  95. package/build/codegen/targets/kotlin/run.js +51 -0
  96. package/build/codegen/targets/kotlin/run.js.map +1 -0
  97. package/build/codegen/targets/swift/access-level.test.d.ts +1 -0
  98. package/build/codegen/targets/swift/access-level.test.js +98 -0
  99. package/build/codegen/targets/swift/access-level.test.js.map +1 -0
  100. package/build/codegen/targets/swift/ajsc-adapter.d.ts +27 -0
  101. package/build/codegen/targets/swift/ajsc-adapter.js +38 -0
  102. package/build/codegen/targets/swift/ajsc-adapter.js.map +1 -0
  103. package/build/codegen/targets/swift/ajsc-adapter.test.d.ts +1 -0
  104. package/build/codegen/targets/swift/ajsc-adapter.test.js +37 -0
  105. package/build/codegen/targets/swift/ajsc-adapter.test.js.map +1 -0
  106. package/build/codegen/targets/swift/e2e-compile.test.d.ts +1 -0
  107. package/build/codegen/targets/swift/e2e-compile.test.js +57 -0
  108. package/build/codegen/targets/swift/e2e-compile.test.js.map +1 -0
  109. package/build/codegen/targets/swift/emit-route-swift.d.ts +15 -0
  110. package/build/codegen/targets/swift/emit-route-swift.js +64 -0
  111. package/build/codegen/targets/swift/emit-route-swift.js.map +1 -0
  112. package/build/codegen/targets/swift/emit-route-swift.test.d.ts +1 -0
  113. package/build/codegen/targets/swift/emit-route-swift.test.js +258 -0
  114. package/build/codegen/targets/swift/emit-route-swift.test.js.map +1 -0
  115. package/build/codegen/targets/swift/emit-scope-swift.d.ts +13 -0
  116. package/build/codegen/targets/swift/emit-scope-swift.js +36 -0
  117. package/build/codegen/targets/swift/emit-scope-swift.js.map +1 -0
  118. package/build/codegen/targets/swift/emit-scope-swift.test.d.ts +1 -0
  119. package/build/codegen/targets/swift/emit-scope-swift.test.js +136 -0
  120. package/build/codegen/targets/swift/emit-scope-swift.test.js.map +1 -0
  121. package/build/codegen/targets/swift/format-swift.d.ts +2 -0
  122. package/build/codegen/targets/swift/format-swift.js +10 -0
  123. package/build/codegen/targets/swift/format-swift.js.map +1 -0
  124. package/build/codegen/targets/swift/format-swift.test.d.ts +1 -0
  125. package/build/codegen/targets/swift/format-swift.test.js +14 -0
  126. package/build/codegen/targets/swift/format-swift.test.js.map +1 -0
  127. package/build/codegen/targets/swift/integration.test.d.ts +1 -0
  128. package/build/codegen/targets/swift/integration.test.js +53 -0
  129. package/build/codegen/targets/swift/integration.test.js.map +1 -0
  130. package/build/codegen/targets/swift/run.d.ts +11 -0
  131. package/build/codegen/targets/swift/run.js +47 -0
  132. package/build/codegen/targets/swift/run.js.map +1 -0
  133. package/build/codegen/targets/ts/run.d.ts +4 -0
  134. package/build/codegen/targets/ts/run.js +86 -0
  135. package/build/codegen/targets/ts/run.js.map +1 -0
  136. package/build/codegen/test-helpers/golden.d.ts +15 -0
  137. package/build/codegen/test-helpers/golden.js +30 -0
  138. package/build/codegen/test-helpers/golden.js.map +1 -0
  139. package/build/codegen/test-helpers/golden.test.d.ts +1 -0
  140. package/build/codegen/test-helpers/golden.test.js +76 -0
  141. package/build/codegen/test-helpers/golden.test.js.map +1 -0
  142. package/docs/codegen-kotlin.md +176 -0
  143. package/docs/codegen-swift.md +314 -0
  144. package/docs/superpowers/plans/2026-04-25-ajsc-v7-kotlin-polish.md +1993 -0
  145. package/docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md +1 -1
  146. package/docs/superpowers/specs/2026-04-25-ajsc-v7-kotlin-polish-design.md +314 -0
  147. package/docs/superpowers/specs/2026-04-25-swift-codegen-design.md +264 -0
  148. package/package.json +2 -2
  149. package/src/codegen/__fixtures__/users-envelope.json +144 -0
  150. package/src/codegen/bin/cli.test.ts +200 -1
  151. package/src/codegen/bin/cli.ts +187 -0
  152. package/src/codegen/index.ts +50 -0
  153. package/src/codegen/pipeline.test.ts +175 -0
  154. package/src/codegen/pipeline.ts +58 -101
  155. package/src/codegen/targets/_shared/error-schemas.test.ts +42 -0
  156. package/src/codegen/targets/_shared/error-schemas.ts +17 -0
  157. package/src/codegen/targets/_shared/indent.test.ts +25 -0
  158. package/src/codegen/targets/_shared/indent.ts +12 -0
  159. package/src/codegen/targets/_shared/pascal-case.test.ts +30 -0
  160. package/src/codegen/targets/_shared/pascal-case.ts +12 -0
  161. package/src/codegen/targets/_shared/path-utils.test.ts +51 -0
  162. package/src/codegen/targets/_shared/path-utils.ts +21 -0
  163. package/src/codegen/targets/_shared/pick-defined.test.ts +48 -0
  164. package/src/codegen/targets/_shared/pick-defined.ts +23 -0
  165. package/src/codegen/targets/_shared/route-slots.test.ts +55 -0
  166. package/src/codegen/targets/_shared/route-slots.ts +32 -0
  167. package/src/codegen/targets/_shared/target-run.ts +28 -0
  168. package/src/codegen/targets/_shared/write-files.test.ts +110 -0
  169. package/src/codegen/targets/_shared/write-files.ts +53 -0
  170. package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +121 -0
  171. package/src/codegen/targets/kotlin/__snapshots__/probe-unsupported-unions.test.ts.snap +27 -0
  172. package/src/codegen/targets/kotlin/ajsc-adapter.test.ts +47 -0
  173. package/src/codegen/targets/kotlin/ajsc-adapter.ts +66 -0
  174. package/src/codegen/targets/kotlin/e2e-compile.test.ts +86 -0
  175. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +239 -0
  176. package/src/codegen/targets/kotlin/emit-route-kotlin.ts +89 -0
  177. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +112 -0
  178. package/src/codegen/targets/kotlin/emit-scope-kotlin.ts +60 -0
  179. package/src/codegen/targets/kotlin/format-kotlin.test.ts +26 -0
  180. package/src/codegen/targets/kotlin/format-kotlin.ts +13 -0
  181. package/src/codegen/targets/kotlin/integration.test.ts +77 -0
  182. package/src/codegen/targets/kotlin/probe-unsupported-unions.test.ts +64 -0
  183. package/src/codegen/targets/kotlin/run.ts +78 -0
  184. package/src/codegen/targets/swift/__fixtures__/users-golden.swift +123 -0
  185. package/src/codegen/targets/swift/access-level.test.ts +108 -0
  186. package/src/codegen/targets/swift/ajsc-adapter.test.ts +47 -0
  187. package/src/codegen/targets/swift/ajsc-adapter.ts +67 -0
  188. package/src/codegen/targets/swift/e2e-compile.test.ts +66 -0
  189. package/src/codegen/targets/swift/emit-route-swift.test.ts +300 -0
  190. package/src/codegen/targets/swift/emit-route-swift.ts +90 -0
  191. package/src/codegen/targets/swift/emit-scope-swift.test.ts +164 -0
  192. package/src/codegen/targets/swift/emit-scope-swift.ts +59 -0
  193. package/src/codegen/targets/swift/format-swift.test.ts +23 -0
  194. package/src/codegen/targets/swift/format-swift.ts +9 -0
  195. package/src/codegen/targets/swift/integration.test.ts +80 -0
  196. package/src/codegen/targets/swift/run.ts +74 -0
  197. package/src/codegen/targets/ts/run.ts +117 -0
  198. package/src/codegen/test-helpers/golden.test.ts +80 -0
  199. package/src/codegen/test-helpers/golden.ts +34 -0
@@ -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[];
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Returns the deterministic ordered slot list for a route, filtered to slots
3
+ * with non-null sources. Order is fixed at the module level for stable output.
4
+ */
5
+ export function extractRouteSlots(route) {
6
+ const schema = route.schema ?? {};
7
+ const input = (schema.input ?? {});
8
+ // Order is load-bearing: targets emit slots in this sequence.
9
+ const slots = [
10
+ { rootName: 'PathParams', source: input.pathParams },
11
+ { rootName: 'Query', source: input.query },
12
+ { rootName: 'Body', source: input.body },
13
+ { rootName: 'Response', source: schema.returnType },
14
+ ];
15
+ return slots.filter((s) => s.source != null);
16
+ }
17
+ //# sourceMappingURL=route-slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-slots.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/route-slots.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAsB;IACtD,MAAM,MAAM,GAAI,KAA8C,CAAC,MAAM,IAAI,EAAE,CAAA;IAC3E,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAA4B,CAAA;IAE7D,8DAA8D;IAC9D,MAAM,KAAK,GAAgB;QACzB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE;QACpD,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE;QAC1C,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE;QACxC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE;KACpD,CAAA;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,CAAA;AAC9C,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { extractRouteSlots } from './route-slots.js';
3
+ const r = (schema) => ({ name: 'X', kind: 'api', method: 'GET', fullPath: '/x', schema });
4
+ describe('extractRouteSlots', () => {
5
+ it('returns no slots when schema is undefined', () => {
6
+ expect(extractRouteSlots(r(undefined))).toEqual([]);
7
+ });
8
+ it('returns no slots when schema is empty', () => {
9
+ expect(extractRouteSlots(r({}))).toEqual([]);
10
+ });
11
+ it('returns the deterministic slot order: PathParams, Query, Body, Response', () => {
12
+ const slots = extractRouteSlots(r({
13
+ input: {
14
+ body: { type: 'object', x: 'body' },
15
+ query: { type: 'object', x: 'query' },
16
+ pathParams: { type: 'object', x: 'path' },
17
+ },
18
+ returnType: { type: 'object', x: 'response' },
19
+ }));
20
+ expect(slots.map((s) => s.rootName)).toEqual(['PathParams', 'Query', 'Body', 'Response']);
21
+ });
22
+ it('omits slots whose source is null or undefined', () => {
23
+ const slots = extractRouteSlots(r({
24
+ input: { pathParams: { type: 'object' }, query: null, body: undefined },
25
+ // returnType missing
26
+ }));
27
+ expect(slots.map((s) => s.rootName)).toEqual(['PathParams']);
28
+ });
29
+ it('attaches the source schema verbatim to each slot', () => {
30
+ const path = { type: 'object', tag: 'p' };
31
+ const ret = { type: 'object', tag: 'r' };
32
+ const slots = extractRouteSlots(r({ input: { pathParams: path }, returnType: ret }));
33
+ expect(slots).toEqual([
34
+ { rootName: 'PathParams', source: path },
35
+ { rootName: 'Response', source: ret },
36
+ ]);
37
+ });
38
+ it('returns no slots for stream/no-schema routes', () => {
39
+ const stream = { name: 'S', kind: 'stream', method: 'GET', path: '/s' };
40
+ expect(extractRouteSlots(stream)).toEqual([]);
41
+ });
42
+ });
43
+ //# sourceMappingURL=route-slots.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-slots.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/route-slots.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAGpD,MAAM,CAAC,GAAG,CAAC,MAA2C,EAAmB,EAAE,CACzE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAiC,CAAA,CAAA;AAEnG,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,KAAK,GAAG,iBAAiB,CAC7B,CAAC,CAAC;YACA,KAAK,EAAE;gBACL,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE;gBACnC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE;gBACrC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE;aAC1C;YACD,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE;SAC9C,CAAC,CACH,CAAA;QACD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAA;IAC3F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,KAAK,GAAG,iBAAiB,CAC7B,CAAC,CAAC;YACA,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;YACvE,qBAAqB;SACtB,CAAC,CACH,CAAA;QACD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QACzC,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;QACpF,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC;YACpB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE;YACxC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE;SACtC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAgC,CAAA;QACrG,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,27 @@
1
+ import type { DocEnvelope } from '../../../implementations/types.js';
2
+ import type { ScopeGroup } from '../../group-routes.js';
3
+ import type { AjscOptions } from '../../emit-types.js';
4
+ /**
5
+ * Inputs the dispatcher prepares once and forwards to every per-target
6
+ * `run*Pipeline` module. Each target module reads only the fields it needs.
7
+ *
8
+ * The fields here are deliberately narrow: target-specific knobs (e.g.
9
+ * `kotlinPackage`, `swiftSerializer`) are passed as additional options on
10
+ * each per-target input shape, not on this base.
11
+ */
12
+ export interface TargetRunInput {
13
+ envelope: DocEnvelope;
14
+ outDir: string;
15
+ /** MD5 hash of the envelope JSON, prefix-stamped into every emitted file. */
16
+ hash: string;
17
+ /** Pre-grouped routes (one entry per scope key). */
18
+ groups: ScopeGroup[];
19
+ /** Validated service name (defaults to `Api` upstream). */
20
+ serviceName: string;
21
+ ajsc?: AjscOptions;
22
+ clientImportPath?: string;
23
+ dryRun?: boolean;
24
+ namespaceTypes?: boolean;
25
+ selfContained?: boolean;
26
+ cleanOutDir?: boolean;
27
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=target-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-run.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/target-run.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ export interface GeneratedFile {
2
+ path: string;
3
+ code: string;
4
+ }
5
+ export interface WriteOptions {
6
+ /** When true, log what would happen instead of touching the filesystem. */
7
+ dryRun?: boolean;
8
+ /** When true, recursively delete `outDir` before writing. */
9
+ cleanOutDir?: boolean;
10
+ }
11
+ /**
12
+ * Persists the generated files to disk (or simulates the writes under
13
+ * `dryRun`). Centralises the dryRun / cleanOutDir / mkdir / writeFile
14
+ * sequence shared by every codegen target so per-target run modules don't
15
+ * duplicate it.
16
+ *
17
+ * Behaviour:
18
+ * - `dryRun: true` — logs `[dry-run] Would write: <path> (<bytes> bytes)` per
19
+ * file, plus a leading `[dry-run] Would clean outDir: <outDir>` when
20
+ * `cleanOutDir: true`. No filesystem mutation.
21
+ * - `dryRun: false` (default) — when `cleanOutDir`, recursively removes
22
+ * `outDir`; then ensures it exists; then writes each file as utf-8.
23
+ */
24
+ export declare function writeGeneratedFiles(files: readonly GeneratedFile[], outDir: string, opts?: WriteOptions): Promise<void>;
@@ -0,0 +1,35 @@
1
+ import { mkdir, rm, writeFile } from 'node:fs/promises';
2
+ /**
3
+ * Persists the generated files to disk (or simulates the writes under
4
+ * `dryRun`). Centralises the dryRun / cleanOutDir / mkdir / writeFile
5
+ * sequence shared by every codegen target so per-target run modules don't
6
+ * duplicate it.
7
+ *
8
+ * Behaviour:
9
+ * - `dryRun: true` — logs `[dry-run] Would write: <path> (<bytes> bytes)` per
10
+ * file, plus a leading `[dry-run] Would clean outDir: <outDir>` when
11
+ * `cleanOutDir: true`. No filesystem mutation.
12
+ * - `dryRun: false` (default) — when `cleanOutDir`, recursively removes
13
+ * `outDir`; then ensures it exists; then writes each file as utf-8.
14
+ */
15
+ export async function writeGeneratedFiles(files, outDir, opts = {}) {
16
+ const { dryRun = false, cleanOutDir = false } = opts;
17
+ if (dryRun) {
18
+ if (cleanOutDir) {
19
+ console.log(`[dry-run] Would clean outDir: ${outDir}`);
20
+ }
21
+ for (const f of files) {
22
+ const bytes = Buffer.byteLength(f.code, 'utf-8');
23
+ console.log(`[dry-run] Would write: ${f.path} (${bytes} bytes)`);
24
+ }
25
+ return;
26
+ }
27
+ if (cleanOutDir) {
28
+ await rm(outDir, { recursive: true, force: true });
29
+ }
30
+ await mkdir(outDir, { recursive: true });
31
+ for (const f of files) {
32
+ await writeFile(f.path, f.code, 'utf-8');
33
+ }
34
+ }
35
+ //# sourceMappingURL=write-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-files.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/write-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAcvD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAA+B,EAC/B,MAAc,EACd,OAAqB,EAAE;IAEvB,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,WAAW,GAAG,KAAK,EAAE,GAAG,IAAI,CAAA;IAEpD,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,iCAAiC,MAAM,EAAE,CAAC,CAAA;QACxD,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAChD,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,IAAI,KAAK,KAAK,SAAS,CAAC,CAAA;QAClE,CAAC;QACD,OAAM;IACR,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;AACH,CAAC"}
@@ -0,0 +1,79 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { mkdir, readFile, rm, writeFile, stat, mkdtemp } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { writeGeneratedFiles } from './write-files.js';
6
+ describe('writeGeneratedFiles', () => {
7
+ describe('dryRun mode', () => {
8
+ let logSpy;
9
+ beforeEach(() => {
10
+ logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
11
+ });
12
+ afterEach(() => {
13
+ logSpy.mockRestore();
14
+ });
15
+ it('logs each file with its byte length and does not touch the filesystem', async () => {
16
+ const dir = '/nonexistent/should-not-be-created';
17
+ await writeGeneratedFiles([
18
+ { path: `${dir}/a.txt`, code: 'hello' },
19
+ { path: `${dir}/b.txt`, code: 'hi' },
20
+ ], dir, { dryRun: true });
21
+ expect(logSpy).toHaveBeenCalledWith(`[dry-run] Would write: ${dir}/a.txt (5 bytes)`);
22
+ expect(logSpy).toHaveBeenCalledWith(`[dry-run] Would write: ${dir}/b.txt (2 bytes)`);
23
+ // Sanity: the dir was not created.
24
+ await expect(stat(dir)).rejects.toBeInstanceOf(Error);
25
+ });
26
+ it('logs a clean-outDir notice when cleanOutDir is true', async () => {
27
+ await writeGeneratedFiles([], '/out', { dryRun: true, cleanOutDir: true });
28
+ expect(logSpy).toHaveBeenCalledWith('[dry-run] Would clean outDir: /out');
29
+ });
30
+ it('does not log clean-outDir when cleanOutDir is false', async () => {
31
+ await writeGeneratedFiles([{ path: '/out/x', code: 'x' }], '/out', { dryRun: true });
32
+ const messages = logSpy.mock.calls.map((c) => c[0]);
33
+ expect(messages.find((m) => String(m).includes('Would clean'))).toBeUndefined();
34
+ });
35
+ it('counts bytes as utf-8', async () => {
36
+ // "é" is 2 bytes in utf-8.
37
+ await writeGeneratedFiles([{ path: '/x/e.txt', code: 'é' }], '/x', { dryRun: true });
38
+ expect(logSpy).toHaveBeenCalledWith('[dry-run] Would write: /x/e.txt (2 bytes)');
39
+ });
40
+ });
41
+ describe('real write mode', () => {
42
+ let outDir;
43
+ beforeEach(async () => {
44
+ outDir = await mkdtemp(join(tmpdir(), 'write-files-test-'));
45
+ });
46
+ afterEach(async () => {
47
+ await rm(outDir, { recursive: true, force: true });
48
+ });
49
+ it('writes each file with utf-8 contents', async () => {
50
+ await writeGeneratedFiles([
51
+ { path: join(outDir, 'a.txt'), code: 'alpha' },
52
+ { path: join(outDir, 'b.txt'), code: 'beta' },
53
+ ], outDir);
54
+ expect(await readFile(join(outDir, 'a.txt'), 'utf-8')).toBe('alpha');
55
+ expect(await readFile(join(outDir, 'b.txt'), 'utf-8')).toBe('beta');
56
+ });
57
+ it('creates outDir recursively if missing', async () => {
58
+ const nested = join(outDir, 'a', 'b', 'c');
59
+ await writeGeneratedFiles([{ path: join(nested, 'x.txt'), code: 'x' }], nested);
60
+ expect(await readFile(join(nested, 'x.txt'), 'utf-8')).toBe('x');
61
+ });
62
+ it('removes outDir when cleanOutDir is true before writing', async () => {
63
+ // Pre-populate a stale file.
64
+ await mkdir(outDir, { recursive: true });
65
+ await writeFile(join(outDir, 'stale.txt'), 'stale', 'utf-8');
66
+ await writeGeneratedFiles([{ path: join(outDir, 'fresh.txt'), code: 'fresh' }], outDir, { cleanOutDir: true });
67
+ await expect(readFile(join(outDir, 'stale.txt'), 'utf-8')).rejects.toBeInstanceOf(Error);
68
+ expect(await readFile(join(outDir, 'fresh.txt'), 'utf-8')).toBe('fresh');
69
+ });
70
+ it('does not remove outDir when cleanOutDir is false', async () => {
71
+ await mkdir(outDir, { recursive: true });
72
+ await writeFile(join(outDir, 'keep.txt'), 'keep', 'utf-8');
73
+ await writeGeneratedFiles([{ path: join(outDir, 'new.txt'), code: 'new' }], outDir);
74
+ expect(await readFile(join(outDir, 'keep.txt'), 'utf-8')).toBe('keep');
75
+ expect(await readFile(join(outDir, 'new.txt'), 'utf-8')).toBe('new');
76
+ });
77
+ });
78
+ });
79
+ //# sourceMappingURL=write-files.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-files.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/_shared/write-files.test.ts"],"names":[],"mappings":"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"}
@@ -6,11 +6,12 @@ export interface KotlinEmitResult {
6
6
  }
7
7
  export interface KotlinEmitOptions {
8
8
  rootTypeName: string;
9
+ /** Always set true at our call sites; v7.2 default is false. */
9
10
  inlineTypes?: boolean;
10
- serializer?: 'kotlinx';
11
- enumStyle?: string;
11
+ serializer?: 'kotlinx' | 'none';
12
+ unsupportedUnions?: 'throw' | 'fallback';
13
+ arrayItemNaming?: string | false;
12
14
  depluralize?: boolean;
13
- arrayItemNaming?: string;
14
15
  uncountableWords?: string[];
15
16
  }
16
17
  export interface KotlinEmitter {
@@ -19,6 +20,7 @@ export interface KotlinEmitter {
19
20
  export declare function createStubKotlinEmitter(results: Record<string, KotlinEmitResult>): KotlinEmitter;
20
21
  /**
21
22
  * Resolves the production Kotlin emitter from `ajsc`. Throws a clear error
22
- * if the ajsc package does not yet expose `emitKotlin` (Phase A pending).
23
+ * if ajsc is not installed or does not expose `emitKotlin` (e.g. consumer
24
+ * ran `npm install --omit=optional` since ajsc is in optionalDependencies).
23
25
  */
24
26
  export declare function resolveProductionKotlinEmitter(): Promise<KotlinEmitter>;
@@ -12,21 +12,26 @@ export function createStubKotlinEmitter(results) {
12
12
  }
13
13
  /**
14
14
  * Resolves the production Kotlin emitter from `ajsc`. Throws a clear error
15
- * if the ajsc package does not yet expose `emitKotlin` (Phase A pending).
15
+ * if ajsc is not installed or does not expose `emitKotlin` (e.g. consumer
16
+ * ran `npm install --omit=optional` since ajsc is in optionalDependencies).
16
17
  */
17
18
  export async function resolveProductionKotlinEmitter() {
18
- // TODO(ajsc-phase-a): replace dynamic import with a static import once ajsc ships emitKotlin.
19
- const ajsc = await import('ajsc').catch(() => null);
19
+ let ajsc = null;
20
+ let importError;
21
+ try {
22
+ ajsc = (await import('ajsc'));
23
+ }
24
+ catch (err) {
25
+ importError = err;
26
+ }
20
27
  const emitKotlin = ajsc?.emitKotlin;
21
28
  if (typeof emitKotlin !== 'function') {
22
29
  throw new Error('[ts-procedures-codegen] ajsc.emitKotlin is not available. ' +
23
- 'Kotlin codegen requires ajsc Phase A. See docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md.');
30
+ 'Install ajsc (`npm install ajsc`) it is an optional dependency.', importError !== undefined ? { cause: importError } : undefined);
24
31
  }
25
32
  return {
26
33
  emit(schema, opts) {
27
- // ajsc's return shape is normalized to KotlinEmitResult here.
28
- const r = emitKotlin(schema, opts);
29
- return r;
34
+ return emitKotlin(schema, opts);
30
35
  },
31
36
  };
32
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ajsc-adapter.js","sourceRoot":"","sources":["../../../../src/codegen/targets/kotlin/ajsc-adapter.ts"],"names":[],"mappings":"AAqBA,MAAM,UAAU,uBAAuB,CACrC,OAAyC;IAEzC,OAAO;QACL,IAAI,CAAC,OAAO,EAAE,IAAI;YAChB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YACzC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CACb,6DAA6D,IAAI,CAAC,YAAY,KAAK;oBACjF,iCAAiC,CACpC,CAAA;YACH,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B;IAClD,8FAA8F;IAC9F,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IACnD,MAAM,UAAU,GAAI,IAAwC,EAAE,UAAU,CAAA;IACxE,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CACb,4DAA4D;YAC5D,6GAA6G,CAC9G,CAAA;IACH,CAAC;IACD,OAAO;QACL,IAAI,CAAC,MAAM,EAAE,IAAI;YACf,8DAA8D;YAC9D,MAAM,CAAC,GAAI,UAA2D,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YACpF,OAAO,CAAC,CAAA;QACV,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"ajsc-adapter.js","sourceRoot":"","sources":["../../../../src/codegen/targets/kotlin/ajsc-adapter.ts"],"names":[],"mappings":"AAsBA,MAAM,UAAU,uBAAuB,CACrC,OAAyC;IAEzC,OAAO;QACL,IAAI,CAAC,OAAO,EAAE,IAAI;YAChB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YACzC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CACb,6DAA6D,IAAI,CAAC,YAAY,KAAK;oBACjF,iCAAiC,CACpC,CAAA;YACH,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B;IAClD,IAAI,IAAI,GAAoC,IAAI,CAAA;IAChD,IAAI,WAAoB,CAAA;IACxB,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,CAA6B,CAAA;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,GAAG,GAAG,CAAA;IACnB,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,CAAA;IACnC,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CACb,4DAA4D;YAC5D,mEAAmE,EACnE,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAC/D,CAAA;IACH,CAAC;IACD,OAAO;QACL,IAAI,CAAC,MAAM,EAAE,IAAI;YACf,OAAQ,UAA2D,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QACnF,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { createStubKotlinEmitter } from './ajsc-adapter.js';
2
+ import { createStubKotlinEmitter, resolveProductionKotlinEmitter } from './ajsc-adapter.js';
3
3
  describe('createStubKotlinEmitter', () => {
4
4
  it('returns the configured EmitResult for the matching root name', () => {
5
5
  const expected = {
@@ -9,11 +9,29 @@ describe('createStubKotlinEmitter', () => {
9
9
  imports: ['kotlinx.serialization.Serializable'],
10
10
  };
11
11
  const emitter = createStubKotlinEmitter({ User: expected });
12
- expect(emitter.emit({ type: 'object' }, { rootTypeName: 'User' })).toEqual(expected);
12
+ expect(emitter.emit({ type: 'object' }, {
13
+ rootTypeName: 'User',
14
+ inlineTypes: true,
15
+ serializer: 'kotlinx',
16
+ unsupportedUnions: 'throw',
17
+ })).toEqual(expected);
13
18
  });
14
19
  it('throws when asked to emit a name not in the stub map', () => {
15
20
  const emitter = createStubKotlinEmitter({});
16
21
  expect(() => emitter.emit({}, { rootTypeName: 'Missing' })).toThrow(/Missing/);
17
22
  });
18
23
  });
24
+ describe('resolveProductionKotlinEmitter', () => {
25
+ it('returns a working emitter that invokes ajsc.emitKotlin when ajsc is installed', async () => {
26
+ const emitter = await resolveProductionKotlinEmitter();
27
+ const result = emitter.emit({ type: 'object', properties: { id: { type: 'string' } }, required: ['id'] }, { rootTypeName: 'Probe' });
28
+ expect(typeof result.code).toBe('string');
29
+ expect(result.code.length).toBeGreaterThan(0);
30
+ expect(result.rootTypeName).toBe('Probe');
31
+ expect(Array.isArray(result.imports)).toBe(true);
32
+ });
33
+ // Note: testing the failure path (ajsc unavailable) requires module mocking;
34
+ // we leave that as a manual-verification path. The error message is pinned
35
+ // by the message text below so any change requires updating both call sites.
36
+ });
19
37
  //# sourceMappingURL=ajsc-adapter.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ajsc-adapter.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/kotlin/ajsc-adapter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,uBAAuB,EAAyB,MAAM,mBAAmB,CAAA;AAElF,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,QAAQ,GAAqB;YACjC,IAAI,EAAE,+CAA+C;YACrD,YAAY,EAAE,MAAM;YACpB,kBAAkB,EAAE,EAAE;YACtB,OAAO,EAAE,CAAC,oCAAoC,CAAC;SAChD,CAAA;QACD,MAAM,OAAO,GAAG,uBAAuB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC3D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACtF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,OAAO,GAAG,uBAAuB,CAAC,EAAE,CAAC,CAAA;QAC3C,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"ajsc-adapter.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/kotlin/ajsc-adapter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAyB,MAAM,mBAAmB,CAAA;AAElH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,QAAQ,GAAqB;YACjC,IAAI,EAAE,+CAA+C;YACrD,YAAY,EAAE,MAAM;YACpB,kBAAkB,EAAE,EAAE;YACtB,OAAO,EAAE,CAAC,oCAAoC,CAAC;SAChD,CAAA;QACD,MAAM,OAAO,GAAG,uBAAuB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC3D,MAAM,CACJ,OAAO,CAAC,IAAI,CACV,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB;YACE,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,SAAS;YACrB,iBAAiB,EAAE,OAAO;SAC3B,CACF,CACF,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACrB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,OAAO,GAAG,uBAAuB,CAAC,EAAE,CAAC,CAAA;QAC3C,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,OAAO,GAAG,MAAM,8BAA8B,EAAE,CAAA;QACtD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CACzB,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,EAC5E,EAAE,YAAY,EAAE,OAAO,EAAE,CAC1B,CAAA;QACD,MAAM,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACzC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IACF,6EAA6E;IAC7E,2EAA2E;IAC3E,6EAA6E;AAC/E,CAAC,CAAC,CAAA"}
@@ -1,7 +1,6 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { execSync } from 'node:child_process';
3
- import { mkdtempSync, writeFileSync } from 'node:fs';
4
- import { readFile } from 'node:fs/promises';
2
+ import { execFileSync, execSync } from 'node:child_process';
3
+ import { mkdtempSync, writeFileSync, readFileSync, readdirSync, existsSync } from 'node:fs';
5
4
  import { tmpdir } from 'node:os';
6
5
  import { dirname, join } from 'node:path';
7
6
  import { fileURLToPath } from 'node:url';
@@ -18,10 +17,31 @@ function kotlincAvailable() {
18
17
  return false;
19
18
  }
20
19
  }
20
+ const RUN = process.env.TS_PROCEDURES_KOTLIN_E2E === '1';
21
+ /**
22
+ * E2E: real ajsc → real .kt output → real kotlinc compile.
23
+ *
24
+ * Gated on (a) `kotlinc` on PATH and (b) opt-in via env var so default
25
+ * `npm test` runs stay green for contributors without the toolchain.
26
+ *
27
+ * **Classpath setup (one-time, local):**
28
+ *
29
+ * Download kotlinx-serialization jars (matching versions, e.g. 1.6.3) from
30
+ * Maven Central or a local Gradle/Maven cache. The classpath value is a
31
+ * `:`-separated list (`;` on Windows). Concrete example:
32
+ *
33
+ * export TS_PROCEDURES_KOTLIN_E2E_CLASSPATH="\
34
+ * $HOME/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-serialization-json-jvm/1.6.3/<hash>/kotlinx-serialization-json-jvm-1.6.3.jar:\
35
+ * $HOME/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-serialization-core-jvm/1.6.3/<hash>/kotlinx-serialization-core-jvm-1.6.3.jar"
36
+ *
37
+ * If the env var is unset the compile uses kotlinc's default classpath which
38
+ * lacks the kotlinx jars and fails — that's the expected mode when checking
39
+ * gating works.
40
+ */
21
41
  describe('kotlin codegen — kotlinc compile (gated)', () => {
22
- it.skipIf(!kotlincAvailable() || process.env.TS_PROCEDURES_KOTLIN_E2E !== '1')('compiles generated output without errors', async () => {
42
+ it.skipIf(!kotlincAvailable() || !RUN)('compiles generated output without errors', async () => {
23
43
  const emitter = await resolveProductionKotlinEmitter();
24
- const envelope = JSON.parse(await readFile(join(__dirname, '__fixtures__/users-envelope.json'), 'utf8'));
44
+ const envelope = JSON.parse(readFileSync(join(__dirname, '../../__fixtures__/users-envelope.json'), 'utf8'));
25
45
  const files = await runPipeline({
26
46
  envelope,
27
47
  outDir: 'out',
@@ -34,10 +54,22 @@ describe('kotlin codegen — kotlinc compile (gated)', () => {
34
54
  for (const f of files) {
35
55
  writeFileSync(join(dir, f.path.split('/').pop()), f.code);
36
56
  }
37
- // Compile against the kotlinx-serialization runtime jar present in the test env.
38
- // If the jar isn't on the classpath, this fails; CI must provide it.
39
- execSync(`kotlinc ${dir}/*.kt -d ${dir}/out.jar`, { stdio: 'inherit' });
40
- expect(true).toBe(true); // reaching here means compile succeeded
57
+ // Expand the source glob in Node and pass kotlinc args as an array so
58
+ // the shell never sees user-controlled input. The classpath env var is
59
+ // only forwarded as a single -classpath argument; even a value with
60
+ // shell metachars cannot escape into command parsing.
61
+ const ktFiles = readdirSync(dir)
62
+ .filter((name) => name.endsWith('.kt'))
63
+ .map((name) => join(dir, name));
64
+ const outJar = join(dir, 'out.jar');
65
+ const cp = process.env.TS_PROCEDURES_KOTLIN_E2E_CLASSPATH;
66
+ const args = [];
67
+ if (cp != null && cp.length > 0) {
68
+ args.push('-classpath', cp);
69
+ }
70
+ args.push(...ktFiles, '-d', outJar);
71
+ execFileSync('kotlinc', args, { stdio: 'inherit' });
72
+ expect(existsSync(outJar)).toBe(true);
41
73
  });
42
74
  });
43
75
  //# sourceMappingURL=e2e-compile.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"e2e-compile.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/kotlin/e2e-compile.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAA;AAElE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;AAErC,SAAS,gBAAgB;IACvB,IAAI,CAAC;QACH,QAAQ,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;QACjD,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACxD,EAAE,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,GAAG,CAAC,CAC5E,0CAA0C,EAC1C,KAAK,IAAI,EAAE;QACT,MAAM,OAAO,GAAG,MAAM,8BAA8B,EAAE,CAAA;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,kCAAkC,CAAC,EAAE,MAAM,CAAC,CAC5E,CAAA;QACD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC;YAC9B,QAAQ;YACR,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,QAAQ;YAChB,aAAa,EAAE,iBAAiB;YAChC,aAAa,EAAE,OAAO;SACvB,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAA;QAC1D,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;QAC5D,CAAC;QACD,iFAAiF;QACjF,qEAAqE;QACrE,QAAQ,CAAC,WAAW,GAAG,YAAY,GAAG,UAAU,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;QACvE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAC,wCAAwC;IAClE,CAAC,CACF,CAAA;AACH,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"e2e-compile.test.js","sourceRoot":"","sources":["../../../../src/codegen/targets/kotlin/e2e-compile.test.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { AnyHttpRouteDoc } from '../../../implementations/types.js';
2
- import type { KotlinEmitter } from './ajsc-adapter.js';
2
+ import type { KotlinEmitter, KotlinEmitOptions } from './ajsc-adapter.js';
3
3
  export interface EmitRouteResult {
4
4
  /** Inner body of the `object RouteName { ... }` block — already indented one level. */
5
5
  code: string;
@@ -7,5 +7,9 @@ export interface EmitRouteResult {
7
7
  imports: string[];
8
8
  /** Outer route name used as the `object RouteName` identifier. */
9
9
  routeName: string;
10
+ /** True when the route was a stream (out-of-scope). Caller logs once. */
11
+ skipped?: boolean;
10
12
  }
11
- export declare function emitKotlinRoute(route: AnyHttpRouteDoc, emitter: KotlinEmitter, errorSchemas: Map<string, unknown>): EmitRouteResult;
13
+ /** Subset of KotlinEmitOptions threaded by the pipeline; per-call rootTypeName is set inside. */
14
+ export type EmitRouteOpts = Omit<KotlinEmitOptions, 'rootTypeName' | 'inlineTypes'>;
15
+ export declare function emitKotlinRoute(route: AnyHttpRouteDoc, emitter: KotlinEmitter, errorSchemas: Map<string, unknown>, routeOpts?: EmitRouteOpts): EmitRouteResult;
@@ -1,14 +1,7 @@
1
- import { indent } from './format-kotlin.js';
2
- const COLON_PARAM_RE = /:([A-Za-z_][A-Za-z0-9_]*)/g;
3
- function toBracePath(template) {
4
- return template.replace(COLON_PARAM_RE, '{$1}');
5
- }
6
- function pathParamNames(template) {
7
- const names = [];
8
- for (const match of template.matchAll(COLON_PARAM_RE))
9
- names.push(match[1]);
10
- return names;
11
- }
1
+ import { indent } from '../_shared/indent.js';
2
+ import { pickDefined } from '../_shared/pick-defined.js';
3
+ import { toBracePath, pathParamNames } from '../_shared/path-utils.js';
4
+ import { extractRouteSlots } from '../_shared/route-slots.js';
12
5
  function buildPathFn(bracePath, params) {
13
6
  if (params.length === 0)
14
7
  return `const val path = "${bracePath}"`;
@@ -17,11 +10,18 @@ function buildPathFn(bracePath, params) {
17
10
  body = body.replace(`{${name}}`, `\${p.${name}}`);
18
11
  return `fun path(p: PathParams): String = "${body}"`;
19
12
  }
20
- export function emitKotlinRoute(route, emitter, errorSchemas) {
13
+ function emitOptsFor(rootTypeName, routeOpts) {
14
+ const PASSTHROUGH_KEYS = ['serializer', 'unsupportedUnions', 'arrayItemNaming', 'depluralize', 'uncountableWords'];
15
+ return {
16
+ rootTypeName,
17
+ inlineTypes: true,
18
+ ...pickDefined(routeOpts, PASSTHROUGH_KEYS),
19
+ };
20
+ }
21
+ export function emitKotlinRoute(route, emitter, errorSchemas, routeOpts = {}) {
21
22
  const kind = route.kind;
22
23
  if (kind === 'stream') {
23
- console.warn(`[ts-procedures-codegen] Skipping stream route "${route.name}" streams are out of scope for kotlin target.`);
24
- return { code: '', imports: [], routeName: route.name };
24
+ return { code: '', imports: [], routeName: route.name, skipped: true };
25
25
  }
26
26
  const isApi = kind === 'api' || 'fullPath' in route;
27
27
  const rawPath = isApi ? route.fullPath : route.path;
@@ -34,19 +34,9 @@ export function emitKotlinRoute(route, emitter, errorSchemas) {
34
34
  buildPathFn(bracePath, params),
35
35
  ];
36
36
  const imports = [];
37
- const schema = route.schema ?? {};
38
- const input = (schema.input ?? {});
39
37
  // Per-slot emission. Order is fixed for deterministic output.
40
- const slots = [
41
- { key: 'pathParams', rootName: 'PathParams', source: input.pathParams },
42
- { key: 'query', rootName: 'Query', source: input.query },
43
- { key: 'body', rootName: 'Body', source: input.body },
44
- { key: 'response', rootName: 'Response', source: schema.returnType },
45
- ];
46
- for (const slot of slots) {
47
- if (slot.source == null)
48
- continue;
49
- const result = emitter.emit(slot.source, { rootTypeName: slot.rootName });
38
+ for (const slot of extractRouteSlots(route)) {
39
+ const result = emitter.emit(slot.source, emitOptsFor(slot.rootName, routeOpts));
50
40
  lines.push('');
51
41
  lines.push(result.code);
52
42
  imports.push(...result.imports);
@@ -59,7 +49,7 @@ export function emitKotlinRoute(route, emitter, errorSchemas) {
59
49
  if (routeErrorKeys.length > 0) {
60
50
  const inner = [];
61
51
  for (const key of routeErrorKeys) {
62
- const r = emitter.emit(errorSchemas.get(key), { rootTypeName: key });
52
+ const r = emitter.emit(errorSchemas.get(key), emitOptsFor(key, routeOpts));
63
53
  inner.push(r.code);
64
54
  imports.push(...r.imports);
65
55
  }
@@ -68,6 +58,6 @@ export function emitKotlinRoute(route, emitter, errorSchemas) {
68
58
  lines.push(indent(inner.join('\n\n'), 1));
69
59
  lines.push('}');
70
60
  }
71
- return { code: lines.join('\n'), imports, routeName: route.name };
61
+ return { code: lines.join('\n'), imports, routeName: route.name, skipped: false };
72
62
  }
73
63
  //# sourceMappingURL=emit-route-kotlin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"emit-route-kotlin.js","sourceRoot":"","sources":["../../../../src/codegen/targets/kotlin/emit-route-kotlin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"emit-route-kotlin.js","sourceRoot":"","sources":["../../../../src/codegen/targets/kotlin/emit-route-kotlin.ts"],"names":[],"mappings":"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"}