@thymian/plugin-sampler 0.3.0-canary.20261007-e6cb8dc → 0.3.0-canary.20261007-cdbe1d3

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 (264) hide show
  1. package/dist/cli/check-result.d.ts +88 -0
  2. package/dist/cli/check-result.d.ts.map +1 -0
  3. package/dist/cli/check-result.js +160 -0
  4. package/dist/cli/check-result.js.map +1 -0
  5. package/dist/cli/commands/sampler/check.d.ts +32 -4
  6. package/dist/cli/commands/sampler/check.d.ts.map +1 -1
  7. package/dist/cli/commands/sampler/check.js +126 -88
  8. package/dist/cli/commands/sampler/check.js.map +1 -1
  9. package/dist/cli/commands/sampler/init.d.ts +4 -6
  10. package/dist/cli/commands/sampler/init.d.ts.map +1 -1
  11. package/dist/cli/commands/sampler/init.js +33 -49
  12. package/dist/cli/commands/sampler/init.js.map +1 -1
  13. package/dist/cli/commands/sampler/show.d.ts +11 -0
  14. package/dist/cli/commands/sampler/show.d.ts.map +1 -0
  15. package/dist/cli/commands/sampler/show.js +36 -0
  16. package/dist/cli/commands/sampler/show.js.map +1 -0
  17. package/dist/cli/commands/sampler/sync.d.ts +11 -0
  18. package/dist/cli/commands/sampler/sync.d.ts.map +1 -0
  19. package/dist/cli/commands/sampler/sync.js +65 -0
  20. package/dist/cli/commands/sampler/sync.js.map +1 -0
  21. package/dist/cli/commands/sampler/validate.d.ts +3 -10
  22. package/dist/cli/commands/sampler/validate.d.ts.map +1 -1
  23. package/dist/cli/commands/sampler/validate.js +57 -126
  24. package/dist/cli/commands/sampler/validate.js.map +1 -1
  25. package/dist/generation/closed-schema.d.ts +22 -0
  26. package/dist/generation/closed-schema.d.ts.map +1 -0
  27. package/dist/generation/closed-schema.js +45 -0
  28. package/dist/generation/closed-schema.js.map +1 -0
  29. package/dist/generation/content-type-strategies/json.content-type-strategy.d.ts.map +1 -1
  30. package/dist/generation/content-type-strategies/json.content-type-strategy.js +3 -1
  31. package/dist/generation/content-type-strategies/json.content-type-strategy.js.map +1 -1
  32. package/dist/generation/content-type-strategies/xml.content-type-strategy.d.ts.map +1 -1
  33. package/dist/generation/content-type-strategies/xml.content-type-strategy.js +3 -1
  34. package/dist/generation/content-type-strategies/xml.content-type-strategy.js.map +1 -1
  35. package/dist/generation/generate-request-sample.d.ts +12 -0
  36. package/dist/generation/generate-request-sample.d.ts.map +1 -0
  37. package/dist/generation/{generate-samples.js → generate-request-sample.js} +11 -4
  38. package/dist/generation/generate-request-sample.js.map +1 -0
  39. package/dist/generation/request-generators/default-request-generator.d.ts +14 -0
  40. package/dist/generation/request-generators/default-request-generator.d.ts.map +1 -1
  41. package/dist/generation/request-generators/default-request-generator.js +18 -1
  42. package/dist/generation/request-generators/default-request-generator.js.map +1 -1
  43. package/dist/generation/types/declaration-set.d.ts +124 -0
  44. package/dist/generation/types/declaration-set.d.ts.map +1 -0
  45. package/dist/generation/types/declaration-set.js +389 -0
  46. package/dist/generation/types/declaration-set.js.map +1 -0
  47. package/dist/generation/types/example-reflection.d.ts +21 -0
  48. package/dist/generation/types/example-reflection.d.ts.map +1 -0
  49. package/dist/generation/types/example-reflection.js +135 -0
  50. package/dist/generation/types/example-reflection.js.map +1 -0
  51. package/dist/generation/types/generate-type-surface.d.ts +23 -0
  52. package/dist/generation/types/generate-type-surface.d.ts.map +1 -0
  53. package/dist/generation/types/generate-type-surface.js +671 -0
  54. package/dist/generation/types/generate-type-surface.js.map +1 -0
  55. package/dist/generation/types/schema-type.d.ts +20 -0
  56. package/dist/generation/types/schema-type.d.ts.map +1 -0
  57. package/dist/generation/types/schema-type.js +203 -0
  58. package/dist/generation/types/schema-type.js.map +1 -0
  59. package/dist/generation/types/self-check-surface.d.ts +32 -0
  60. package/dist/generation/types/self-check-surface.d.ts.map +1 -0
  61. package/dist/generation/types/self-check-surface.js +92 -0
  62. package/dist/generation/types/self-check-surface.js.map +1 -0
  63. package/dist/generation/types/type-names.d.ts +135 -0
  64. package/dist/generation/types/type-names.d.ts.map +1 -0
  65. package/dist/generation/types/type-names.js +213 -0
  66. package/dist/generation/types/type-names.js.map +1 -0
  67. package/dist/generation/types/write-type-surface.d.ts +58 -0
  68. package/dist/generation/types/write-type-surface.d.ts.map +1 -0
  69. package/dist/generation/types/write-type-surface.js +119 -0
  70. package/dist/generation/types/write-type-surface.js.map +1 -0
  71. package/dist/hooks/create-hook-utils.d.ts +22 -6
  72. package/dist/hooks/create-hook-utils.d.ts.map +1 -1
  73. package/dist/hooks/create-hook-utils.js +74 -96
  74. package/dist/hooks/create-hook-utils.js.map +1 -1
  75. package/dist/hooks/hook-api.d.ts +49 -0
  76. package/dist/hooks/hook-api.d.ts.map +1 -0
  77. package/dist/hooks/hook-api.js +105 -0
  78. package/dist/hooks/hook-api.js.map +1 -0
  79. package/dist/hooks/hook-diagnostics.d.ts +45 -0
  80. package/dist/hooks/hook-diagnostics.d.ts.map +1 -0
  81. package/dist/hooks/hook-diagnostics.js +80 -0
  82. package/dist/hooks/hook-diagnostics.js.map +1 -0
  83. package/dist/hooks/hook-errors.d.ts +33 -0
  84. package/dist/hooks/hook-errors.d.ts.map +1 -1
  85. package/dist/hooks/hook-errors.js +46 -0
  86. package/dist/hooks/hook-errors.js.map +1 -1
  87. package/dist/hooks/hook-registration.d.ts +108 -0
  88. package/dist/hooks/hook-registration.d.ts.map +1 -0
  89. package/dist/hooks/hook-registration.js +69 -0
  90. package/dist/hooks/hook-registration.js.map +1 -0
  91. package/dist/hooks/hook-runner.d.ts +111 -11
  92. package/dist/hooks/hook-runner.d.ts.map +1 -1
  93. package/dist/hooks/hook-runner.js +309 -142
  94. package/dist/hooks/hook-runner.js.map +1 -1
  95. package/dist/hooks/hook-utils-factory.d.ts +19 -0
  96. package/dist/hooks/hook-utils-factory.d.ts.map +1 -0
  97. package/dist/hooks/hook-utils-factory.js +2 -0
  98. package/dist/hooks/hook-utils-factory.js.map +1 -0
  99. package/dist/hooks/hook-utils.d.ts +80 -12
  100. package/dist/hooks/hook-utils.d.ts.map +1 -1
  101. package/dist/hooks/invoke-hook.d.ts +71 -0
  102. package/dist/hooks/invoke-hook.d.ts.map +1 -0
  103. package/dist/hooks/invoke-hook.js +161 -0
  104. package/dist/hooks/invoke-hook.js.map +1 -0
  105. package/dist/hooks/load-user-hooks.d.ts +96 -0
  106. package/dist/hooks/load-user-hooks.d.ts.map +1 -0
  107. package/dist/hooks/load-user-hooks.js +432 -0
  108. package/dist/hooks/load-user-hooks.js.map +1 -0
  109. package/dist/hooks/nested-request.d.ts +21 -0
  110. package/dist/hooks/nested-request.d.ts.map +1 -0
  111. package/dist/hooks/nested-request.js +24 -0
  112. package/dist/hooks/nested-request.js.map +1 -0
  113. package/dist/hooks/overlay-args.d.ts +40 -0
  114. package/dist/hooks/overlay-args.d.ts.map +1 -0
  115. package/dist/hooks/overlay-args.js +84 -0
  116. package/dist/hooks/overlay-args.js.map +1 -0
  117. package/dist/hooks/resolve-targeting.d.ts +16 -0
  118. package/dist/hooks/resolve-targeting.d.ts.map +1 -0
  119. package/dist/hooks/resolve-targeting.js +168 -0
  120. package/dist/hooks/resolve-targeting.js.map +1 -0
  121. package/dist/hooks/run-scoped-hooks.d.ts +83 -0
  122. package/dist/hooks/run-scoped-hooks.d.ts.map +1 -0
  123. package/dist/hooks/run-scoped-hooks.js +153 -0
  124. package/dist/hooks/run-scoped-hooks.js.map +1 -0
  125. package/dist/index.d.ts +42 -19
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +152 -165
  128. package/dist/index.js.map +1 -1
  129. package/dist/request-sampler.d.ts +40 -11
  130. package/dist/request-sampler.d.ts.map +1 -1
  131. package/dist/request-sampler.js +51 -76
  132. package/dist/request-sampler.js.map +1 -1
  133. package/dist/sampler-paths.d.ts +19 -0
  134. package/dist/sampler-paths.d.ts.map +1 -0
  135. package/dist/sampler-paths.js +22 -0
  136. package/dist/sampler-paths.js.map +1 -0
  137. package/dist/selectors/nearest-paths.d.ts +14 -0
  138. package/dist/selectors/nearest-paths.d.ts.map +1 -0
  139. package/dist/selectors/nearest-paths.js +32 -0
  140. package/dist/selectors/nearest-paths.js.map +1 -0
  141. package/dist/selectors/path-glob.d.ts +94 -0
  142. package/dist/selectors/path-glob.d.ts.map +1 -0
  143. package/dist/selectors/path-glob.js +136 -0
  144. package/dist/selectors/path-glob.js.map +1 -0
  145. package/dist/selectors/selector-errors.d.ts +17 -0
  146. package/dist/selectors/selector-errors.d.ts.map +1 -0
  147. package/dist/selectors/selector-errors.js +139 -0
  148. package/dist/selectors/selector-errors.js.map +1 -0
  149. package/dist/selectors/selector.d.ts +55 -0
  150. package/dist/selectors/selector.d.ts.map +1 -0
  151. package/dist/selectors/selector.js +305 -0
  152. package/dist/selectors/selector.js.map +1 -0
  153. package/dist/selectors/transaction-catalog.d.ts +96 -0
  154. package/dist/selectors/transaction-catalog.d.ts.map +1 -0
  155. package/dist/selectors/transaction-catalog.js +193 -0
  156. package/dist/selectors/transaction-catalog.js.map +1 -0
  157. package/dist/selectors/transaction-filter.d.ts +119 -0
  158. package/dist/selectors/transaction-filter.d.ts.map +1 -0
  159. package/dist/selectors/transaction-filter.js +191 -0
  160. package/dist/selectors/transaction-filter.js.map +1 -0
  161. package/dist/ts-path.d.ts +36 -0
  162. package/dist/ts-path.d.ts.map +1 -0
  163. package/dist/ts-path.js +46 -0
  164. package/dist/ts-path.js.map +1 -0
  165. package/dist/utils.d.ts +1 -2
  166. package/dist/utils.d.ts.map +1 -1
  167. package/dist/utils.js +2 -20
  168. package/dist/utils.js.map +1 -1
  169. package/dist/validation/canonicalize.d.ts +17 -0
  170. package/dist/validation/canonicalize.d.ts.map +1 -0
  171. package/dist/validation/canonicalize.js +29 -0
  172. package/dist/validation/canonicalize.js.map +1 -0
  173. package/dist/validation/shared-compiler-host.d.ts +17 -0
  174. package/dist/validation/shared-compiler-host.d.ts.map +1 -0
  175. package/dist/validation/shared-compiler-host.js +58 -0
  176. package/dist/validation/shared-compiler-host.js.map +1 -0
  177. package/dist/validation/typecheck-hooks.d.ts +37 -0
  178. package/dist/validation/typecheck-hooks.d.ts.map +1 -0
  179. package/dist/validation/typecheck-hooks.js +169 -0
  180. package/dist/validation/typecheck-hooks.js.map +1 -0
  181. package/dist/validation/validate-sampler.d.ts +79 -0
  182. package/dist/validation/validate-sampler.d.ts.map +1 -0
  183. package/dist/validation/validate-sampler.js +89 -0
  184. package/dist/validation/validate-sampler.js.map +1 -0
  185. package/package.json +7 -11
  186. package/dist/cli/commands/sampler/generate/hook.d.ts +0 -10
  187. package/dist/cli/commands/sampler/generate/hook.d.ts.map +0 -1
  188. package/dist/cli/commands/sampler/generate/hook.js +0 -19
  189. package/dist/cli/commands/sampler/generate/hook.js.map +0 -1
  190. package/dist/cli/generate-hook.d.ts +0 -4
  191. package/dist/cli/generate-hook.d.ts.map +0 -1
  192. package/dist/cli/generate-hook.js +0 -96
  193. package/dist/cli/generate-hook.js.map +0 -1
  194. package/dist/cli/templates.d.ts +0 -4
  195. package/dist/cli/templates.d.ts.map +0 -1
  196. package/dist/cli/templates.js +0 -28
  197. package/dist/cli/templates.js.map +0 -1
  198. package/dist/constants.d.ts +0 -12
  199. package/dist/constants.d.ts.map +0 -1
  200. package/dist/constants.js +0 -16
  201. package/dist/constants.js.map +0 -1
  202. package/dist/generation/generate-samples-for-thymian-format.d.ts +0 -4
  203. package/dist/generation/generate-samples-for-thymian-format.d.ts.map +0 -1
  204. package/dist/generation/generate-samples-for-thymian-format.js +0 -18
  205. package/dist/generation/generate-samples-for-thymian-format.js.map +0 -1
  206. package/dist/generation/generate-samples.d.ts +0 -4
  207. package/dist/generation/generate-samples.d.ts.map +0 -1
  208. package/dist/generation/generate-samples.js.map +0 -1
  209. package/dist/hooks/generate-request-types.d.ts +0 -34
  210. package/dist/hooks/generate-request-types.d.ts.map +0 -1
  211. package/dist/hooks/generate-request-types.js +0 -458
  212. package/dist/hooks/generate-request-types.js.map +0 -1
  213. package/dist/hooks/hook-types.d.ts +0 -7
  214. package/dist/hooks/hook-types.d.ts.map +0 -1
  215. package/dist/hooks/hook-types.js +0 -2
  216. package/dist/hooks/hook-types.js.map +0 -1
  217. package/dist/hooks/load-hooks-from-samples.d.ts +0 -3
  218. package/dist/hooks/load-hooks-from-samples.d.ts.map +0 -1
  219. package/dist/hooks/load-hooks-from-samples.js +0 -22
  220. package/dist/hooks/load-hooks-from-samples.js.map +0 -1
  221. package/dist/hooks/ts-config.d.ts +0 -10
  222. package/dist/hooks/ts-config.d.ts.map +0 -1
  223. package/dist/hooks/ts-config.js +0 -10
  224. package/dist/hooks/ts-config.js.map +0 -1
  225. package/dist/samples-structure/file-request-sample.d.ts +0 -20
  226. package/dist/samples-structure/file-request-sample.d.ts.map +0 -1
  227. package/dist/samples-structure/file-request-sample.js +0 -5
  228. package/dist/samples-structure/file-request-sample.js.map +0 -1
  229. package/dist/samples-structure/get-path-transaction-id.d.ts +0 -3
  230. package/dist/samples-structure/get-path-transaction-id.d.ts.map +0 -1
  231. package/dist/samples-structure/get-path-transaction-id.js +0 -22
  232. package/dist/samples-structure/get-path-transaction-id.js.map +0 -1
  233. package/dist/samples-structure/merge-tree.d.ts +0 -5
  234. package/dist/samples-structure/merge-tree.d.ts.map +0 -1
  235. package/dist/samples-structure/merge-tree.js +0 -118
  236. package/dist/samples-structure/merge-tree.js.map +0 -1
  237. package/dist/samples-structure/read-samples-from-dir.d.ts +0 -13
  238. package/dist/samples-structure/read-samples-from-dir.d.ts.map +0 -1
  239. package/dist/samples-structure/read-samples-from-dir.js +0 -205
  240. package/dist/samples-structure/read-samples-from-dir.js.map +0 -1
  241. package/dist/samples-structure/samples-from-transactions.d.ts +0 -5
  242. package/dist/samples-structure/samples-from-transactions.d.ts.map +0 -1
  243. package/dist/samples-structure/samples-from-transactions.js +0 -120
  244. package/dist/samples-structure/samples-from-transactions.js.map +0 -1
  245. package/dist/samples-structure/samples-tree-structure.d.ts +0 -106
  246. package/dist/samples-structure/samples-tree-structure.d.ts.map +0 -1
  247. package/dist/samples-structure/samples-tree-structure.js +0 -26
  248. package/dist/samples-structure/samples-tree-structure.js.map +0 -1
  249. package/dist/samples-structure/structure-meta-on-disc.d.ts +0 -11
  250. package/dist/samples-structure/structure-meta-on-disc.d.ts.map +0 -1
  251. package/dist/samples-structure/structure-meta-on-disc.js +0 -2
  252. package/dist/samples-structure/structure-meta-on-disc.js.map +0 -1
  253. package/dist/samples-structure/traverse.d.ts +0 -4
  254. package/dist/samples-structure/traverse.d.ts.map +0 -1
  255. package/dist/samples-structure/traverse.js +0 -13
  256. package/dist/samples-structure/traverse.js.map +0 -1
  257. package/dist/samples-structure/write-samples-to-dir.d.ts +0 -37
  258. package/dist/samples-structure/write-samples-to-dir.d.ts.map +0 -1
  259. package/dist/samples-structure/write-samples-to-dir.js +0 -183
  260. package/dist/samples-structure/write-samples-to-dir.js.map +0 -1
  261. package/dist/validation/validate-sampler-output.d.ts +0 -38
  262. package/dist/validation/validate-sampler-output.d.ts.map +0 -1
  263. package/dist/validation/validate-sampler-output.js +0 -288
  264. package/dist/validation/validate-sampler-output.js.map +0 -1
@@ -0,0 +1,20 @@
1
+ import { type Declaration } from './declaration-set.js';
2
+ export type GeneratedType = {
3
+ /** The declarations this type is made of: its own, plus every named
4
+ * component it references. */
5
+ declarations: Declaration[];
6
+ /** The name of the root declaration, usable wherever a type is expected. */
7
+ type: string;
8
+ };
9
+ /** Whether a media type is one whose body has a JSON shape worth typing. */
10
+ export declare function isJsonMediaType(mediaType: string): boolean;
11
+ /**
12
+ * The TypeScript type for one schema, with its `examples` reflected into
13
+ * property types.
14
+ *
15
+ * A non-JSON media type is `unknown`: the sampler can generate a body for it,
16
+ * but a schema is not what describes it, so pretending to type it would be
17
+ * worse than admitting we do not.
18
+ */
19
+ export declare function generateSchemaType(schema: unknown, mediaType: string, typeName: string): Promise<GeneratedType>;
20
+ //# sourceMappingURL=schema-type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-type.d.ts","sourceRoot":"","sources":["../../../src/generation/types/schema-type.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,sBAAsB,CAAC;AAG3E,MAAM,MAAM,aAAa,GAAG;IAC1B;kCAC8B;IAC9B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAmMF,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAI1D;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CA+BxB"}
@@ -0,0 +1,203 @@
1
+ import { isRecord } from '@thymian/core';
2
+ import { compile } from 'json-schema-to-typescript';
3
+ import { closedObjectsToBoolean } from '../closed-schema.js';
4
+ import { splitDeclarations } from './declaration-set.js';
5
+ import { reflectExamples } from './example-reflection.js';
6
+ const UNKNOWN = { declarations: [], type: 'unknown' };
7
+ /**
8
+ * `$defs` is the 2020-12 spelling of the keyword `definitions` names in
9
+ * draft-07, and `json-schema-to-typescript` only resolves the older one. So
10
+ * both the key **and** every `$ref` pointing into it are rewritten — renaming
11
+ * the key alone leaves the pointers aimed at a token that no longer exists,
12
+ * which fails the whole generation with `Missing $ref pointer`.
13
+ */
14
+ function defsToDefinitions(input) {
15
+ if (Array.isArray(input)) {
16
+ return input.map(defsToDefinitions);
17
+ }
18
+ if (!isRecord(input)) {
19
+ return input;
20
+ }
21
+ const out = {};
22
+ for (const [key, value] of Object.entries(input)) {
23
+ if (key === '$ref' && typeof value === 'string') {
24
+ out[key] = value.replace(/\/\$defs\//g, '/definitions/');
25
+ continue;
26
+ }
27
+ out[key === '$defs' ? 'definitions' : key] = defsToDefinitions(value);
28
+ }
29
+ // A top-level `$ref` beside `definitions` is what a description produces when
30
+ // a body is exactly one named schema, and the emitter cannot compile that
31
+ // shape: wrapping the reference in an `allOf` says the same thing in a shape
32
+ // it can.
33
+ if ('$ref' in out && 'definitions' in out) {
34
+ const ref = out['$ref'];
35
+ delete out['$ref'];
36
+ out['allOf'] = [{ $ref: ref }];
37
+ }
38
+ return out;
39
+ }
40
+ /**
41
+ * The keywords a schema names ITSELF with, in the library's own precedence
42
+ * order. All three outrank the name `compile()` is handed, so all three have to
43
+ * be gone before the schema is compiled.
44
+ *
45
+ * The library resolves a declaration name as
46
+ * `options.customName?.(…) || schema.title || schema.$id || keyNameFromDefinition`
47
+ * (`json-schema-to-typescript@15/dist/src/parser.js`), and its normalizer only
48
+ * synthesises the `$id` we rely on `if (!schema.$id && !schema.title …)`. So a
49
+ * schema-level `title` — which any hand-written OpenAPI document is likely to
50
+ * carry — makes the library declare `export interface Astronaut` while the
51
+ * surface still references the name we asked for, and the committed file no
52
+ * longer compiles. `id` is not covered by removing `$id`: the normalizer runs a
53
+ * `Transform id to $id` rule AFTER this pass, so the draft-04 spelling walks
54
+ * back in through the very keyword `$id` was removed to protect.
55
+ *
56
+ * None of the three carries type information. `description` is the keyword the
57
+ * library turns into a JSDoc comment and is deliberately KEPT.
58
+ *
59
+ * Enumerating keywords is not a proof, which is why {@link assertDeclares}
60
+ * turns a keyword this list forgets into a loud failure rather than a surface
61
+ * that silently does not compile.
62
+ */
63
+ const NAME_KEYWORDS = ['title', '$id', 'id'];
64
+ /**
65
+ * The emitter's own extensions, which let a schema write TypeScript directly.
66
+ *
67
+ * `tsType` is printed VERBATIM in place of whatever the node would have
68
+ * compiled to, and `tsEnumNames` mints a `const enum` declaration of its own.
69
+ * An API description is input — it can be fetched over the network, and it is
70
+ * not reviewed the way source is — so leaving these through means a description
71
+ * decides the contents of a file the project commits and compiles against.
72
+ * `tsType: 'any'` alone silently switches off type checking for that property
73
+ * everywhere a hook touches it, and a `tsEnumNames` declaration is named after
74
+ * the property rather than by {@link NameRegistry}, so it can shadow anything.
75
+ *
76
+ * The sampler uses `tsType` itself, for example reflection. That is why this
77
+ * strip runs BEFORE `reflectExamples`: what a description asked for is gone,
78
+ * and what the generator adds afterwards is its own.
79
+ */
80
+ const TYPE_DIRECTIVES = ['tsType', 'tsEnumNames'];
81
+ /**
82
+ * Where a schema nests another schema, by the shape of the position.
83
+ *
84
+ * The walk below has to be keyword-aware rather than a blind key filter: `id`
85
+ * is a name keyword in a SCHEMA position and an ordinary property NAME inside
86
+ * `properties`, so filtering every key called `id` deletes the `id` property
87
+ * from every body that has one. That is not hypothetical — it is what the first
88
+ * version of this strip did, and the type surface it produced was clean
89
+ * TypeScript describing the wrong object.
90
+ */
91
+ const NESTED_SCHEMA = {
92
+ /** Positions holding exactly one schema. */
93
+ single: [
94
+ 'additionalItems',
95
+ 'additionalProperties',
96
+ 'contains',
97
+ 'else',
98
+ 'if',
99
+ 'items',
100
+ 'not',
101
+ 'propertyNames',
102
+ 'then',
103
+ 'unevaluatedItems',
104
+ 'unevaluatedProperties',
105
+ ],
106
+ /** Positions holding an array of schemas. */
107
+ list: ['allOf', 'anyOf', 'oneOf', 'prefixItems'],
108
+ /** Positions holding a name-to-schema map, where the KEY is not a keyword. */
109
+ map: [
110
+ '$defs',
111
+ 'definitions',
112
+ 'dependentSchemas',
113
+ 'patternProperties',
114
+ 'properties',
115
+ ],
116
+ };
117
+ /**
118
+ * Strips the given keywords at every schema position — the root, a nested
119
+ * property, an array's element, a composition branch and a named component
120
+ * alike, because the emitter reads them the same way at each of them.
121
+ */
122
+ function stripKeywords(schema, keywords) {
123
+ if (!isRecord(schema)) {
124
+ return schema;
125
+ }
126
+ const node = { ...schema };
127
+ for (const keyword of keywords) {
128
+ delete node[keyword];
129
+ }
130
+ for (const keyword of NESTED_SCHEMA.single) {
131
+ if (keyword in node) {
132
+ node[keyword] = stripKeywords(node[keyword], keywords);
133
+ }
134
+ }
135
+ for (const keyword of NESTED_SCHEMA.list) {
136
+ const branches = node[keyword];
137
+ if (Array.isArray(branches)) {
138
+ node[keyword] = branches.map((branch) => stripKeywords(branch, keywords));
139
+ }
140
+ }
141
+ for (const keyword of NESTED_SCHEMA.map) {
142
+ const members = node[keyword];
143
+ if (isRecord(members)) {
144
+ node[keyword] = Object.fromEntries(Object.entries(members).map(([name, member]) => [
145
+ name,
146
+ stripKeywords(member, keywords),
147
+ ]));
148
+ }
149
+ }
150
+ return node;
151
+ }
152
+ /**
153
+ * Fails if the library did not declare under the name it was handed.
154
+ *
155
+ * The surface references `typeName`, so a declaration under any other name is a
156
+ * dangling reference in a committed file — a `tsc` error for the user, in
157
+ * generated code they are told not to edit. Catching it here costs one regex
158
+ * and names the schema that caused it.
159
+ */
160
+ function assertDeclares(declaration, typeName) {
161
+ const declared = new RegExp(`^export (?:interface|type) ${typeName}\\b`, 'm').test(declaration);
162
+ if (!declared) {
163
+ throw new Error(`The type generator asked for a declaration named ${typeName} and did ` +
164
+ `not get one. A schema keyword is overriding the name; see ` +
165
+ `NAME_KEYWORDS in schema-type.ts.`);
166
+ }
167
+ }
168
+ /** Whether a media type is one whose body has a JSON shape worth typing. */
169
+ export function isJsonMediaType(mediaType) {
170
+ const essence = mediaType.split(';', 1)[0]?.trim().toLowerCase() ?? '';
171
+ return essence === 'application/json' || /\+json$/.test(essence);
172
+ }
173
+ /**
174
+ * The TypeScript type for one schema, with its `examples` reflected into
175
+ * property types.
176
+ *
177
+ * A non-JSON media type is `unknown`: the sampler can generate a body for it,
178
+ * but a schema is not what describes it, so pretending to type it would be
179
+ * worse than admitting we do not.
180
+ */
181
+ export async function generateSchemaType(schema, mediaType, typeName) {
182
+ if (!isJsonMediaType(mediaType)) {
183
+ return UNKNOWN;
184
+ }
185
+ if (schema === undefined) {
186
+ return UNKNOWN;
187
+ }
188
+ // The strip comes first so that the only `tsType` the emitter sees is the one
189
+ // example reflection adds next.
190
+ const stripped = stripKeywords(structuredClone(schema), [
191
+ ...NAME_KEYWORDS,
192
+ ...TYPE_DIRECTIVES,
193
+ ]);
194
+ const declaration = await compile(defsToDefinitions(closedObjectsToBoolean(reflectExamples(stripped))), typeName, {
195
+ bannerComment: '',
196
+ additionalProperties: true,
197
+ style: { semi: false },
198
+ $refOptions: { mutateInputSchema: true },
199
+ });
200
+ assertDeclares(declaration, typeName);
201
+ return { declarations: splitDeclarations(declaration), type: typeName };
202
+ }
203
+ //# sourceMappingURL=schema-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-type.js","sourceRoot":"","sources":["../../../src/generation/types/schema-type.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type TypeSurface } from './generate-type-surface.js';
2
+ /**
3
+ * Compile the emitted declaration files **alone**, with `skipLibCheck: false`,
4
+ * and report what `tsc` says about them.
5
+ *
6
+ * Every path that consumes the surface afterwards — the scaffolded tsconfig,
7
+ * `typecheckHooks`, the hook-authoring compile probe — sets `skipLibCheck:
8
+ * true`, because a user's own `@types` tree is not the sampler's business to
9
+ * police. That is exactly the flag that stops TypeScript from reporting an
10
+ * error *inside* a `.d.ts`, so the file the sampler commits — and whose diff
11
+ * is the drift signal every other gate trusts — is the one file none of those
12
+ * paths actually check. This is the check that does.
13
+ *
14
+ * Both files are given as program roots, not just one: `hooksApi` imports
15
+ * `requestTypes`, so a root of `requestTypes` alone never pulls `hooksApi`
16
+ * into the program, and a defect confined to the (mostly static) hooks
17
+ * surface would go unreported.
18
+ */
19
+ export declare function surfaceDiagnostics(surface: TypeSurface): Promise<string[]>;
20
+ /**
21
+ * The self-check gate: refuse to hand back a surface that does not compile.
22
+ *
23
+ * Called wherever a fresh surface is produced — `init`, `sync`, and
24
+ * `validate`'s scratch surface — so no emitter defect, present or future, can
25
+ * hide behind a user's own compiler settings (`skipLibCheck` among them) and
26
+ * surface later as a confusing error in their hooks. The message and the
27
+ * `GeneratedSurfaceError` name deliberately attribute the fault to the
28
+ * generator: whatever a diagnostic here says, it is never something a user's
29
+ * API description or hooks could have caused.
30
+ */
31
+ export declare function selfCheckSurface(surface: TypeSurface): Promise<void>;
32
+ //# sourceMappingURL=self-check-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-check-surface.d.ts","sourceRoot":"","sources":["../../../src/generation/types/self-check-surface.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AAEpC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CA2DnB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB1E"}
@@ -0,0 +1,92 @@
1
+ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { ThymianBaseError } from '@thymian/core';
5
+ import ts from 'typescript';
6
+ import { tsPathRelativeTo } from '../../ts-path.js';
7
+ import { sharedCompilerHost } from '../../validation/shared-compiler-host.js';
8
+ import { HOOKS_API_FILE, REQUEST_TYPES_FILE, } from './generate-type-surface.js';
9
+ /**
10
+ * Compile the emitted declaration files **alone**, with `skipLibCheck: false`,
11
+ * and report what `tsc` says about them.
12
+ *
13
+ * Every path that consumes the surface afterwards — the scaffolded tsconfig,
14
+ * `typecheckHooks`, the hook-authoring compile probe — sets `skipLibCheck:
15
+ * true`, because a user's own `@types` tree is not the sampler's business to
16
+ * police. That is exactly the flag that stops TypeScript from reporting an
17
+ * error *inside* a `.d.ts`, so the file the sampler commits — and whose diff
18
+ * is the drift signal every other gate trusts — is the one file none of those
19
+ * paths actually check. This is the check that does.
20
+ *
21
+ * Both files are given as program roots, not just one: `hooksApi` imports
22
+ * `requestTypes`, so a root of `requestTypes` alone never pulls `hooksApi`
23
+ * into the program, and a defect confined to the (mostly static) hooks
24
+ * surface would go unreported.
25
+ */
26
+ export async function surfaceDiagnostics(surface) {
27
+ const root = await mkdtemp(join(tmpdir(), 'thymian-surface-check-'));
28
+ try {
29
+ const generated = join(root, 'generated');
30
+ const requestTypes = join(generated, REQUEST_TYPES_FILE);
31
+ const hooksApi = join(generated, HOOKS_API_FILE);
32
+ await mkdir(generated, { recursive: true });
33
+ await writeFile(requestTypes, surface.requestTypes, 'utf-8');
34
+ await writeFile(hooksApi, surface.hooksApi, 'utf-8');
35
+ const options = {
36
+ strict: true,
37
+ noEmit: true,
38
+ module: ts.ModuleKind.NodeNext,
39
+ moduleResolution: ts.ModuleResolutionKind.NodeNext,
40
+ target: ts.ScriptTarget.ES2023,
41
+ // The whole point of this probe: do not skip the files under test.
42
+ skipLibCheck: false,
43
+ baseUrl: root,
44
+ paths: { '@thymian/hooks': [`./generated/${HOOKS_API_FILE}`] },
45
+ lib: ['lib.es2023.d.ts'],
46
+ types: [],
47
+ };
48
+ const program = ts.createProgram([hooksApi, requestTypes], options, sharedCompilerHost(options));
49
+ return ts.getPreEmitDiagnostics(program).flatMap((diagnostic) => {
50
+ const file = diagnostic.file;
51
+ // `generated` is a `node:path` value; TypeScript's own `fileName`s are
52
+ // forward-slashed. `tsPathRelativeTo` normalizes both, which keeps this
53
+ // correct on Windows.
54
+ const relativeFile = file
55
+ ? tsPathRelativeTo(file.fileName, generated)
56
+ : undefined;
57
+ if (!file || relativeFile === undefined) {
58
+ return [];
59
+ }
60
+ const { line } = file.getLineAndCharacterOfPosition(diagnostic.start ?? 0);
61
+ const where = `${relativeFile}:${line + 1}`;
62
+ const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, ' ');
63
+ return [`${where} TS${diagnostic.code}: ${message}`];
64
+ });
65
+ }
66
+ finally {
67
+ await rm(root, { recursive: true, force: true });
68
+ }
69
+ }
70
+ /**
71
+ * The self-check gate: refuse to hand back a surface that does not compile.
72
+ *
73
+ * Called wherever a fresh surface is produced — `init`, `sync`, and
74
+ * `validate`'s scratch surface — so no emitter defect, present or future, can
75
+ * hide behind a user's own compiler settings (`skipLibCheck` among them) and
76
+ * surface later as a confusing error in their hooks. The message and the
77
+ * `GeneratedSurfaceError` name deliberately attribute the fault to the
78
+ * generator: whatever a diagnostic here says, it is never something a user's
79
+ * API description or hooks could have caused.
80
+ */
81
+ export async function selfCheckSurface(surface) {
82
+ const diagnostics = await surfaceDiagnostics(surface);
83
+ if (diagnostics.length === 0) {
84
+ return;
85
+ }
86
+ throw new ThymianBaseError(`The sampler generated a type surface that does not compile (${diagnostics.length} ${diagnostics.length === 1 ? 'diagnostic' : 'diagnostics'}). This is a defect in the sampler's own generator — not your API description or your hooks — please report it.`, {
87
+ name: 'GeneratedSurfaceError',
88
+ ref: 'https://thymian.dev/references/errors/generated-surface-error/',
89
+ suggestions: diagnostics,
90
+ });
91
+ }
92
+ //# sourceMappingURL=self-check-surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-check-surface.js","sourceRoot":"","sources":["../../../src/generation/types/self-check-surface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Deterministic TypeScript identifiers for the declarations the type surface
3
+ * emits.
4
+ *
5
+ * Every name is a pure function of the transaction's selector plus the schema's
6
+ * role within that transaction. Naming by catalog position instead
7
+ * (`Transaction4Type2`) is stable under a document reorder but not under an
8
+ * *insertion*: a new endpoint that sorts first renumbers every declaration
9
+ * after it. The surface is committed and the diff against it **is** the
10
+ * staleness signal, so a positional name turns adding one endpoint into a
11
+ * whole-file diff — 282 changed lines on the demo description, for one added
12
+ * operation.
13
+ *
14
+ * SANITISATION IS NOT COSMETIC AND THE COLLISION SUFFIX IS NOT DEFENSIVE. A
15
+ * selector legitimately carries characters no identifier can: a method is an
16
+ * RFC 9110 section 5.6.2 token, paths carry `/`, `{`, `}` and percent-encoding,
17
+ * and media types carry `/`, `+`, `;` and `=`. Two distinct selectors therefore
18
+ * collapse onto one stem — methods `A-B` and `A.B` on the same path both
19
+ * sanitise to `AB` — so the suffix is reached by real input.
20
+ *
21
+ * THE NAME WE REFERENCE AND THE NAME THE LIBRARY DECLARES ARE ONE STRING.
22
+ * `json-schema-to-typescript` does not declare under the name it is handed: it
23
+ * declares under `toSafeString(name)`, which re-cases a lowercase letter that
24
+ * follows a digit (`V1beta` becomes `V1Beta`), collapses `_x` into `X` and
25
+ * upper-cases the first letter. A positional name is already a fixed point of
26
+ * that transform; a selector-derived one is not, and a name that changes on the
27
+ * way in is a dangling reference on the way out. {@link safeIdentifier} is the
28
+ * single boundary, and {@link NameRegistry} uniquifies AFTER it — so two
29
+ * candidates that sanitise onto one identifier get a suffix rather than one
30
+ * declaration emitted twice under two names.
31
+ */
32
+ /**
33
+ * The fixed declarations `generate-type-surface.ts` emits around the
34
+ * generated ones. Shared by {@link NameRegistry} (so a generated declaration
35
+ * never shadows one of these) and by `DeclarationSet` (so a description
36
+ * component named after one of these — `Status`, say — is reserved out from
37
+ * under it rather than silently merged into it, which is what let a
38
+ * description declaring a `Status` component reach the committed surface as
39
+ * two conflicting `export type Status` and `export interface Status`
40
+ * declarations, `skipLibCheck` hiding the fault until a user's own hook
41
+ * compile — or, once the self-check gate is on, at generation time with an
42
+ * unattributed `TS2300`).
43
+ */
44
+ export declare const FIXED_ROOT_NAMES: readonly ["Endpoints", "Method", "Path", "RequestMediaType", "ResponseMediaType", "Responses", "Selector", "Status", "StatusClass", "TransactionResponse", "WireMediaType"];
45
+ /** Which schema of a transaction a declaration was generated for. */
46
+ export type SchemaRole = {
47
+ readonly kind: 'request-body';
48
+ } | {
49
+ readonly kind: 'response-body';
50
+ } | {
51
+ readonly kind: 'query-parameter';
52
+ readonly parameter: string;
53
+ } | {
54
+ readonly kind: 'path-parameter';
55
+ readonly parameter: string;
56
+ } | {
57
+ readonly kind: 'request-header';
58
+ readonly parameter: string;
59
+ } | {
60
+ readonly kind: 'cookie';
61
+ readonly parameter: string;
62
+ } | {
63
+ readonly kind: 'response-header';
64
+ readonly parameter: string;
65
+ };
66
+ /**
67
+ * Splits on every run of non-alphanumeric characters and upper-cases each
68
+ * remaining segment's first character, so `GET`, `astronauts`, `{id}` and
69
+ * `application/vnd.Example+JSON` become `Get`, `Astronauts`, `Id` and
70
+ * `ApplicationVndExampleJson`.
71
+ *
72
+ * The tail is lower-cased deliberately: a declaration NAME is not required to
73
+ * be byte-exact — only the emitted selector keys and union members are — and
74
+ * folding it keeps `JSON` and `json` from producing two visually
75
+ * indistinguishable identifiers.
76
+ */
77
+ export declare function pascalSegments(value: string): string;
78
+ /** The role's contribution to a declaration name. */
79
+ export declare function roleSuffix(role: SchemaRole): string;
80
+ /**
81
+ * The identifier a selector plus a role WANTS. Several sites may want the same
82
+ * one; {@link NameRegistry} is what turns wants into names.
83
+ *
84
+ * A method is an RFC 9110 token, so it may be all digits (`123 /x` is a legal
85
+ * selector), and a parameter name may start with one (`2fa`). Neither an
86
+ * identifier nor the library's own transform tolerates a leading digit, so the
87
+ * candidate leaves through {@link safeIdentifier} rather than through a local
88
+ * guard.
89
+ */
90
+ export declare function candidateName(selector: string, role: SchemaRole): string;
91
+ /**
92
+ * An identifier `json-schema-to-typescript`'s `toSafeString` leaves alone, for
93
+ * any input string.
94
+ *
95
+ * The contract is deliberately weaker than "reproduce `toSafeString`": the
96
+ * library never sees the original, only this function's output, so all that has
97
+ * to hold is that the output is a FIXED POINT of the library's transform. That
98
+ * is four conditions, and each is enforced by one branch below:
99
+ *
100
+ * - every character is in `[A-Za-z0-9_$]`, so nothing is replaced by whitespace;
101
+ * - the first character is never a digit, hence the `_` prefix;
102
+ * - no lowercase letter follows a digit, a `$` or an `_`;
103
+ * - the first character is never lowercase, so `upperFirst` is a no-op.
104
+ *
105
+ * A run of unusable characters is a word boundary rather than a deletion, so
106
+ * `foo bar` and `foo-bar` both become `FooBar` — the same convention
107
+ * {@link pascalSegments} uses, which is why applying both is harmless.
108
+ */
109
+ export declare function safeIdentifier(value: string): string;
110
+ /**
111
+ * Hands out unique identifiers, remembering what each site was given.
112
+ *
113
+ * The suffix order is a function of the description rather than of traversal
114
+ * order, because the catalog is sorted by selector and each transaction's
115
+ * schemas are visited in a fixed role order. Adding a transaction that collides
116
+ * with an existing stem can renumber the colliding group, and only that group;
117
+ * adding a non-colliding one — the overwhelmingly common case — renames
118
+ * nothing.
119
+ */
120
+ export declare class NameRegistry {
121
+ private readonly used;
122
+ private readonly byKey;
123
+ /**
124
+ * @param reserved names nothing may be assigned, such as the fixed
125
+ * declarations the surface emits around the generated ones.
126
+ */
127
+ constructor(reserved?: Iterable<string>);
128
+ /**
129
+ * The name for `selector` in `role`, minted the first time it is asked for
130
+ * and returned unchanged thereafter — so two references to one site cannot
131
+ * drift apart.
132
+ */
133
+ nameFor(selector: string, role: SchemaRole): string;
134
+ }
135
+ //# sourceMappingURL=type-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-names.d.ts","sourceRoot":"","sources":["../../../src/generation/types/type-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,6KAYnB,CAAC;AAEX,qEAAqE;AACrE,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACjC;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAClC;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASpD;AAcD,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAiBnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAMxE;AAYD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiCpD;AAED;;;;;;;;;GASG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IAEnD;;;OAGG;gBACS,QAAQ,GAAE,QAAQ,CAAC,MAAM,CAAM;IAI3C;;;;OAIG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM;CAsBpD"}