openapi-typesafe 1.0.0-rc.0 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) hide show
  1. package/dist/adapters/redocly-loader/redocly-config-source.cjs +21 -2
  2. package/dist/adapters/redocly-loader/redocly-config-source.cjs.map +1 -1
  3. package/dist/adapters/redocly-loader/redocly-config-source.mjs +22 -3
  4. package/dist/adapters/redocly-loader/redocly-config-source.mjs.map +1 -1
  5. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +15 -5
  6. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
  7. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +15 -5
  8. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
  9. package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs +3 -0
  10. package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs.map +1 -1
  11. package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs +3 -0
  12. package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs.map +1 -1
  13. package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs +15 -9
  14. package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs.map +1 -1
  15. package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs +15 -9
  16. package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs.map +1 -1
  17. package/dist/api/discriminator-conflict-warnings.cjs +25 -0
  18. package/dist/api/discriminator-conflict-warnings.cjs.map +1 -0
  19. package/dist/api/discriminator-conflict-warnings.mjs +23 -0
  20. package/dist/api/discriminator-conflict-warnings.mjs.map +1 -0
  21. package/dist/api/discriminator-enum-names.cjs +19 -0
  22. package/dist/api/discriminator-enum-names.cjs.map +1 -0
  23. package/dist/api/discriminator-enum-names.mjs +17 -0
  24. package/dist/api/discriminator-enum-names.mjs.map +1 -0
  25. package/dist/api/discriminator-enum-parent.cjs +59 -0
  26. package/dist/api/discriminator-enum-parent.cjs.map +1 -0
  27. package/dist/api/discriminator-enum-parent.mjs +57 -0
  28. package/dist/api/discriminator-enum-parent.mjs.map +1 -0
  29. package/dist/api/discriminator-enum.cjs +25 -0
  30. package/dist/api/discriminator-enum.cjs.map +1 -1
  31. package/dist/api/discriminator-enum.mjs +25 -1
  32. package/dist/api/discriminator-enum.mjs.map +1 -1
  33. package/dist/api/discriminator-other-owners.cjs +67 -0
  34. package/dist/api/discriminator-other-owners.cjs.map +1 -0
  35. package/dist/api/discriminator-other-owners.mjs +64 -0
  36. package/dist/api/discriminator-other-owners.mjs.map +1 -0
  37. package/dist/api/discriminator-patch.cjs +88 -0
  38. package/dist/api/discriminator-patch.cjs.map +1 -0
  39. package/dist/api/discriminator-patch.mjs +82 -0
  40. package/dist/api/discriminator-patch.mjs.map +1 -0
  41. package/dist/api/discriminator-scan.cjs +50 -65
  42. package/dist/api/discriminator-scan.cjs.map +1 -1
  43. package/dist/api/discriminator-scan.mjs +44 -59
  44. package/dist/api/discriminator-scan.mjs.map +1 -1
  45. package/dist/api/document-run.cjs +18 -3
  46. package/dist/api/document-run.cjs.map +1 -1
  47. package/dist/api/document-run.mjs +19 -4
  48. package/dist/api/document-run.mjs.map +1 -1
  49. package/dist/api/enum-values-warnings.cjs +16 -0
  50. package/dist/api/enum-values-warnings.cjs.map +1 -0
  51. package/dist/api/enum-values-warnings.mjs +14 -0
  52. package/dist/api/enum-values-warnings.mjs.map +1 -0
  53. package/dist/api/path-template-warnings.cjs +21 -0
  54. package/dist/api/path-template-warnings.cjs.map +1 -0
  55. package/dist/api/path-template-warnings.mjs +19 -0
  56. package/dist/api/path-template-warnings.mjs.map +1 -0
  57. package/dist/api/transform-context.cjs +3 -1
  58. package/dist/api/transform-context.cjs.map +1 -1
  59. package/dist/api/transform-context.mjs +3 -1
  60. package/dist/api/transform-context.mjs.map +1 -1
  61. package/dist/api/transform-schema.cjs +52 -3
  62. package/dist/api/transform-schema.cjs.map +1 -1
  63. package/dist/api/transform-schema.mjs +53 -4
  64. package/dist/api/transform-schema.mjs.map +1 -1
  65. package/dist/api/unsupported-feature-warnings.cjs +6 -1
  66. package/dist/api/unsupported-feature-warnings.cjs.map +1 -1
  67. package/dist/api/unsupported-feature-warnings.mjs +6 -1
  68. package/dist/api/unsupported-feature-warnings.mjs.map +1 -1
  69. package/dist/application/print/type-printer.cjs +5 -0
  70. package/dist/application/print/type-printer.cjs.map +1 -1
  71. package/dist/application/print/type-printer.mjs +5 -0
  72. package/dist/application/print/type-printer.mjs.map +1 -1
  73. package/dist/application/transform/document/assignability.cjs +144 -0
  74. package/dist/application/transform/document/assignability.cjs.map +1 -0
  75. package/dist/application/transform/document/assignability.mjs +138 -0
  76. package/dist/application/transform/document/assignability.mjs.map +1 -0
  77. package/dist/application/transform/document/components.cjs +2 -2
  78. package/dist/application/transform/document/components.cjs.map +1 -1
  79. package/dist/application/transform/document/components.mjs +4 -4
  80. package/dist/application/transform/document/components.mjs.map +1 -1
  81. package/dist/application/transform/document/declared-types.cjs +66 -0
  82. package/dist/application/transform/document/declared-types.cjs.map +1 -0
  83. package/dist/application/transform/document/declared-types.mjs +63 -0
  84. package/dist/application/transform/document/declared-types.mjs.map +1 -0
  85. package/dist/application/transform/document/document.cjs +32 -9
  86. package/dist/application/transform/document/document.cjs.map +1 -1
  87. package/dist/application/transform/document/document.mjs +34 -11
  88. package/dist/application/transform/document/document.mjs.map +1 -1
  89. package/dist/application/transform/document/exploded-query.cjs +46 -0
  90. package/dist/application/transform/document/exploded-query.cjs.map +1 -0
  91. package/dist/application/transform/document/exploded-query.mjs +43 -0
  92. package/dist/application/transform/document/exploded-query.mjs.map +1 -0
  93. package/dist/application/transform/document/global-type-references.cjs +63 -0
  94. package/dist/application/transform/document/global-type-references.cjs.map +1 -0
  95. package/dist/application/transform/document/global-type-references.mjs +61 -0
  96. package/dist/application/transform/document/global-type-references.mjs.map +1 -0
  97. package/dist/application/transform/document/list-assignability.cjs +54 -0
  98. package/dist/application/transform/document/list-assignability.cjs.map +1 -0
  99. package/dist/application/transform/document/list-assignability.mjs +52 -0
  100. package/dist/application/transform/document/list-assignability.mjs.map +1 -0
  101. package/dist/application/transform/document/parameters.cjs +40 -8
  102. package/dist/application/transform/document/parameters.cjs.map +1 -1
  103. package/dist/application/transform/document/parameters.mjs +41 -9
  104. package/dist/application/transform/document/parameters.mjs.map +1 -1
  105. package/dist/application/transform/document/path-key-overlaps.cjs +83 -33
  106. package/dist/application/transform/document/path-key-overlaps.cjs.map +1 -1
  107. package/dist/application/transform/document/path-key-overlaps.mjs +83 -33
  108. package/dist/application/transform/document/path-key-overlaps.mjs.map +1 -1
  109. package/dist/application/transform/document/path-template-replace.cjs +48 -0
  110. package/dist/application/transform/document/path-template-replace.cjs.map +1 -0
  111. package/dist/application/transform/document/path-template-replace.mjs +45 -0
  112. package/dist/application/transform/document/path-template-replace.mjs.map +1 -0
  113. package/dist/application/transform/document/paths.cjs +54 -28
  114. package/dist/application/transform/document/paths.cjs.map +1 -1
  115. package/dist/application/transform/document/paths.mjs +53 -29
  116. package/dist/application/transform/document/paths.mjs.map +1 -1
  117. package/dist/application/transform/document/root-type-aliases.cjs +15 -14
  118. package/dist/application/transform/document/root-type-aliases.cjs.map +1 -1
  119. package/dist/application/transform/document/root-type-aliases.mjs +15 -13
  120. package/dist/application/transform/document/root-type-aliases.mjs.map +1 -1
  121. package/dist/application/transform/document/template-key-match.cjs +128 -0
  122. package/dist/application/transform/document/template-key-match.cjs.map +1 -0
  123. package/dist/application/transform/document/template-key-match.mjs +125 -0
  124. package/dist/application/transform/document/template-key-match.mjs.map +1 -0
  125. package/dist/application/transform/document/type-assignability.cjs +192 -0
  126. package/dist/application/transform/document/type-assignability.cjs.map +1 -0
  127. package/dist/application/transform/document/type-assignability.mjs +190 -0
  128. package/dist/application/transform/document/type-assignability.mjs.map +1 -0
  129. package/dist/application/transform/document/type-key.cjs +70 -0
  130. package/dist/application/transform/document/type-key.cjs.map +1 -0
  131. package/dist/application/transform/document/type-key.mjs +68 -0
  132. package/dist/application/transform/document/type-key.mjs.map +1 -0
  133. package/dist/application/transform/document/type-resolution.cjs +131 -0
  134. package/dist/application/transform/document/type-resolution.cjs.map +1 -0
  135. package/dist/application/transform/document/type-resolution.mjs +125 -0
  136. package/dist/application/transform/document/type-resolution.mjs.map +1 -0
  137. package/dist/application/transform/footer/document-footer.cjs +66 -4
  138. package/dist/application/transform/footer/document-footer.cjs.map +1 -1
  139. package/dist/application/transform/footer/document-footer.mjs +67 -5
  140. package/dist/application/transform/footer/document-footer.mjs.map +1 -1
  141. package/dist/application/transform/footer/enum-naming.cjs +17 -0
  142. package/dist/application/transform/footer/enum-naming.cjs.map +1 -1
  143. package/dist/application/transform/footer/enum-naming.mjs +17 -1
  144. package/dist/application/transform/footer/enum-naming.mjs.map +1 -1
  145. package/dist/application/transform/footer/enum-values-check.cjs +129 -0
  146. package/dist/application/transform/footer/enum-values-check.cjs.map +1 -0
  147. package/dist/application/transform/footer/enum-values-check.mjs +127 -0
  148. package/dist/application/transform/footer/enum-values-check.mjs.map +1 -0
  149. package/dist/application/transform/footer/evaluation.cjs +33 -0
  150. package/dist/application/transform/footer/evaluation.cjs.map +1 -0
  151. package/dist/application/transform/footer/evaluation.mjs +26 -0
  152. package/dist/application/transform/footer/evaluation.mjs.map +1 -0
  153. package/dist/application/transform/footer/shared-enum-names.cjs +60 -0
  154. package/dist/application/transform/footer/shared-enum-names.cjs.map +1 -0
  155. package/dist/application/transform/footer/shared-enum-names.mjs +57 -0
  156. package/dist/application/transform/footer/shared-enum-names.mjs.map +1 -0
  157. package/dist/application/transform/footer/type-evaluation.cjs +246 -0
  158. package/dist/application/transform/footer/type-evaluation.cjs.map +1 -0
  159. package/dist/application/transform/footer/type-evaluation.mjs +244 -0
  160. package/dist/application/transform/footer/type-evaluation.mjs.map +1 -0
  161. package/dist/application/transform/footer/type-rules.cjs +172 -0
  162. package/dist/application/transform/footer/type-rules.cjs.map +1 -0
  163. package/dist/application/transform/footer/type-rules.mjs +166 -0
  164. package/dist/application/transform/footer/type-rules.mjs.map +1 -0
  165. package/dist/application/transform/ref-pointer/generated-location.cjs +138 -0
  166. package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -0
  167. package/dist/application/transform/ref-pointer/generated-location.mjs +136 -0
  168. package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -0
  169. package/dist/application/transform/ref-pointer/generated-shape.cjs +171 -0
  170. package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -0
  171. package/dist/application/transform/ref-pointer/generated-shape.mjs +162 -0
  172. package/dist/application/transform/ref-pointer/generated-shape.mjs.map +1 -0
  173. package/dist/application/transform/ref-pointer/inline-cycles.cjs +44 -0
  174. package/dist/application/transform/ref-pointer/inline-cycles.cjs.map +1 -0
  175. package/dist/application/transform/ref-pointer/inline-cycles.mjs +42 -0
  176. package/dist/application/transform/ref-pointer/inline-cycles.mjs.map +1 -0
  177. package/dist/application/transform/ref-pointer/original-index.cjs +62 -0
  178. package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -0
  179. package/dist/application/transform/ref-pointer/original-index.mjs +60 -0
  180. package/dist/application/transform/ref-pointer/original-index.mjs.map +1 -0
  181. package/dist/application/transform/ref-pointer/pointer-type.cjs +60 -0
  182. package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -0
  183. package/dist/application/transform/ref-pointer/pointer-type.mjs +57 -0
  184. package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -0
  185. package/dist/application/transform/ref-pointer/pointer-walk.cjs +66 -0
  186. package/dist/application/transform/ref-pointer/pointer-walk.cjs.map +1 -0
  187. package/dist/application/transform/ref-pointer/pointer-walk.mjs +56 -0
  188. package/dist/application/transform/ref-pointer/pointer-walk.mjs.map +1 -0
  189. package/dist/application/transform/ref-pointer/typed-walk.cjs +124 -0
  190. package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -0
  191. package/dist/application/transform/ref-pointer/typed-walk.mjs +122 -0
  192. package/dist/application/transform/ref-pointer/typed-walk.mjs.map +1 -0
  193. package/dist/application/transform/ref-type.cjs +7 -2
  194. package/dist/application/transform/ref-type.cjs.map +1 -1
  195. package/dist/application/transform/ref-type.mjs +3 -2
  196. package/dist/application/transform/ref-type.mjs.map +1 -1
  197. package/dist/application/transform/schema/access-flags.cjs +38 -0
  198. package/dist/application/transform/schema/access-flags.cjs.map +1 -0
  199. package/dist/application/transform/schema/access-flags.mjs +36 -0
  200. package/dist/application/transform/schema/access-flags.mjs.map +1 -0
  201. package/dist/application/transform/schema/array-type.cjs +32 -1
  202. package/dist/application/transform/schema/array-type.cjs.map +1 -1
  203. package/dist/application/transform/schema/array-type.mjs +33 -2
  204. package/dist/application/transform/schema/array-type.mjs.map +1 -1
  205. package/dist/application/transform/schema/composition-type.cjs +50 -15
  206. package/dist/application/transform/schema/composition-type.cjs.map +1 -1
  207. package/dist/application/transform/schema/composition-type.mjs +50 -15
  208. package/dist/application/transform/schema/composition-type.mjs.map +1 -1
  209. package/dist/application/transform/schema/core-type.cjs +3 -1
  210. package/dist/application/transform/schema/core-type.cjs.map +1 -1
  211. package/dist/application/transform/schema/core-type.mjs +3 -1
  212. package/dist/application/transform/schema/core-type.mjs.map +1 -1
  213. package/dist/application/transform/schema/discriminated-union.cjs +30 -0
  214. package/dist/application/transform/schema/discriminated-union.cjs.map +1 -0
  215. package/dist/application/transform/schema/discriminated-union.mjs +27 -0
  216. package/dist/application/transform/schema/discriminated-union.mjs.map +1 -0
  217. package/dist/application/transform/schema/discriminator-property.cjs +3 -2
  218. package/dist/application/transform/schema/discriminator-property.cjs.map +1 -1
  219. package/dist/application/transform/schema/discriminator-property.mjs +3 -2
  220. package/dist/application/transform/schema/discriminator-property.mjs.map +1 -1
  221. package/dist/application/transform/schema/enum-rule.cjs +66 -10
  222. package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
  223. package/dist/application/transform/schema/enum-rule.mjs +67 -12
  224. package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
  225. package/dist/application/transform/schema/inherited-discriminator.cjs +29 -0
  226. package/dist/application/transform/schema/inherited-discriminator.cjs.map +1 -0
  227. package/dist/application/transform/schema/inherited-discriminator.mjs +26 -0
  228. package/dist/application/transform/schema/inherited-discriminator.mjs.map +1 -0
  229. package/dist/application/transform/schema/object-type.cjs +38 -25
  230. package/dist/application/transform/schema/object-type.cjs.map +1 -1
  231. package/dist/application/transform/schema/object-type.mjs +39 -27
  232. package/dist/application/transform/schema/object-type.mjs.map +1 -1
  233. package/dist/application/transform/schema/required-variants.cjs +45 -0
  234. package/dist/application/transform/schema/required-variants.cjs.map +1 -0
  235. package/dist/application/transform/schema/required-variants.mjs +42 -0
  236. package/dist/application/transform/schema/required-variants.mjs.map +1 -0
  237. package/dist/application/transform/schema/schema-transform.cjs +2 -2
  238. package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
  239. package/dist/application/transform/schema/schema-transform.mjs +2 -2
  240. package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
  241. package/dist/application/transform/schema-comment.cjs +51 -5
  242. package/dist/application/transform/schema-comment.cjs.map +1 -1
  243. package/dist/application/transform/schema-comment.mjs +50 -6
  244. package/dist/application/transform/schema-comment.mjs.map +1 -1
  245. package/dist/application/transform/type-combinators.mjs +1 -1
  246. package/dist/cli/cli-arguments.cjs +11 -3
  247. package/dist/cli/cli-arguments.cjs.map +1 -1
  248. package/dist/cli/cli-arguments.mjs +11 -3
  249. package/dist/cli/cli-arguments.mjs.map +1 -1
  250. package/dist/cli/cli-errors.cjs +3 -2
  251. package/dist/cli/cli-errors.cjs.map +1 -1
  252. package/dist/cli/cli-errors.mjs +3 -2
  253. package/dist/cli/cli-errors.mjs.map +1 -1
  254. package/dist/cli/cli-output.cjs +8 -3
  255. package/dist/cli/cli-output.cjs.map +1 -1
  256. package/dist/cli/cli-output.mjs +9 -4
  257. package/dist/cli/cli-output.mjs.map +1 -1
  258. package/dist/cli/main.cjs +5 -0
  259. package/dist/cli/main.cjs.map +1 -1
  260. package/dist/cli/main.mjs +5 -0
  261. package/dist/cli/main.mjs.map +1 -1
  262. package/dist/cli/redocly-apis.cjs +7 -3
  263. package/dist/cli/redocly-apis.cjs.map +1 -1
  264. package/dist/cli/redocly-apis.mjs +8 -4
  265. package/dist/cli/redocly-apis.mjs.map +1 -1
  266. package/dist/cli/ref-limits.cjs +1 -1
  267. package/dist/cli/ref-limits.cjs.map +1 -1
  268. package/dist/cli/ref-limits.mjs +2 -2
  269. package/dist/cli/ref-limits.mjs.map +1 -1
  270. package/dist/cli/run-cli.cjs +15 -2
  271. package/dist/cli/run-cli.cjs.map +1 -1
  272. package/dist/cli/run-cli.mjs +16 -3
  273. package/dist/cli/run-cli.mjs.map +1 -1
  274. package/dist/domain/errors.cjs +2 -0
  275. package/dist/domain/errors.cjs.map +1 -1
  276. package/dist/domain/errors.mjs +2 -0
  277. package/dist/domain/errors.mjs.map +1 -1
  278. package/dist/domain/ir/constructors.cjs +5 -1
  279. package/dist/domain/ir/constructors.cjs.map +1 -1
  280. package/dist/domain/ir/constructors.mjs +5 -2
  281. package/dist/domain/ir/constructors.mjs.map +1 -1
  282. package/dist/domain/openapi/admitted-values.cjs +75 -0
  283. package/dist/domain/openapi/admitted-values.cjs.map +1 -0
  284. package/dist/domain/openapi/admitted-values.mjs +72 -0
  285. package/dist/domain/openapi/admitted-values.mjs.map +1 -0
  286. package/dist/domain/openapi/discriminated-union.cjs +68 -0
  287. package/dist/domain/openapi/discriminated-union.cjs.map +1 -0
  288. package/dist/domain/openapi/discriminated-union.mjs +62 -0
  289. package/dist/domain/openapi/discriminated-union.mjs.map +1 -0
  290. package/dist/domain/openapi/discriminator-conflicts.cjs +143 -0
  291. package/dist/domain/openapi/discriminator-conflicts.cjs.map +1 -0
  292. package/dist/domain/openapi/discriminator-conflicts.mjs +141 -0
  293. package/dist/domain/openapi/discriminator-conflicts.mjs.map +1 -0
  294. package/dist/domain/openapi/parameter-object.cjs.map +1 -1
  295. package/dist/domain/openapi/parameter-object.mjs.map +1 -1
  296. package/dist/domain/openapi/path-templates.cjs +23 -0
  297. package/dist/domain/openapi/path-templates.cjs.map +1 -0
  298. package/dist/domain/openapi/path-templates.mjs +21 -0
  299. package/dist/domain/openapi/path-templates.mjs.map +1 -0
  300. package/dist/domain/output-fixes.cjs +36 -1
  301. package/dist/domain/output-fixes.cjs.map +1 -1
  302. package/dist/domain/output-fixes.mjs +36 -1
  303. package/dist/domain/output-fixes.mjs.map +1 -1
  304. package/dist/domain/warnings.cjs +15 -0
  305. package/dist/domain/warnings.cjs.map +1 -0
  306. package/dist/domain/warnings.mjs +12 -0
  307. package/dist/domain/warnings.mjs.map +1 -0
  308. package/dist/index.d.cts +29 -0
  309. package/dist/index.d.mts +29 -0
  310. package/dist/index.d.ts +29 -0
  311. package/dist/transform/components-object.cjs +2 -1
  312. package/dist/transform/components-object.cjs.map +1 -1
  313. package/dist/transform/components-object.mjs +2 -1
  314. package/dist/transform/components-object.mjs.map +1 -1
  315. package/package.json +1 -1
  316. package/src/adapters/redocly-loader/redocly-config-source.ts +41 -6
  317. package/src/adapters/redocly-loader/redocly-schema-loader.ts +22 -6
  318. package/src/adapters/type-ast-bridge/ir-to-typescript.ts +3 -0
  319. package/src/adapters/type-ast-bridge/typescript-to-ir.ts +26 -12
  320. package/src/api/discriminator-conflict-warnings.ts +43 -0
  321. package/src/api/discriminator-enum-names.ts +26 -0
  322. package/src/api/discriminator-enum-parent.ts +129 -0
  323. package/src/api/discriminator-enum.ts +39 -0
  324. package/src/api/discriminator-other-owners.ts +97 -0
  325. package/src/api/discriminator-patch.ts +147 -0
  326. package/src/api/discriminator-scan.ts +78 -90
  327. package/src/api/document-run.ts +24 -6
  328. package/src/api/enum-values-warnings.ts +21 -0
  329. package/src/api/path-template-warnings.ts +27 -0
  330. package/src/api/transform-context.ts +7 -1
  331. package/src/api/transform-schema.ts +88 -4
  332. package/src/api/unsupported-feature-warnings.ts +8 -1
  333. package/src/application/ports/redocly-config-source.ts +5 -1
  334. package/src/application/print/type-printer.ts +6 -0
  335. package/src/application/transform/document/assignability.ts +203 -0
  336. package/src/application/transform/document/components.ts +6 -6
  337. package/src/application/transform/document/declared-types.ts +93 -0
  338. package/src/application/transform/document/document.ts +71 -13
  339. package/src/application/transform/document/exploded-query.ts +91 -0
  340. package/src/application/transform/document/global-type-references.ts +78 -0
  341. package/src/application/transform/document/list-assignability.ts +87 -0
  342. package/src/application/transform/document/parameters.ts +76 -11
  343. package/src/application/transform/document/path-key-overlaps.ts +148 -59
  344. package/src/application/transform/document/path-template-replace.ts +90 -0
  345. package/src/application/transform/document/paths.ts +99 -37
  346. package/src/application/transform/document/root-type-aliases.ts +29 -28
  347. package/src/application/transform/document/template-key-match.ts +183 -0
  348. package/src/application/transform/document/type-assignability.ts +268 -0
  349. package/src/application/transform/document/type-key.ts +80 -0
  350. package/src/application/transform/document/type-resolution.ts +163 -0
  351. package/src/application/transform/footer/document-footer.ts +91 -6
  352. package/src/application/transform/footer/enum-naming.ts +29 -0
  353. package/src/application/transform/footer/enum-values-check.ts +171 -0
  354. package/src/application/transform/footer/evaluation.ts +47 -0
  355. package/src/application/transform/footer/shared-enum-names.ts +86 -0
  356. package/src/application/transform/footer/type-evaluation.ts +294 -0
  357. package/src/application/transform/footer/type-rules.ts +269 -0
  358. package/src/application/transform/ref-pointer/generated-location.ts +211 -0
  359. package/src/application/transform/ref-pointer/generated-shape.ts +275 -0
  360. package/src/application/transform/ref-pointer/inline-cycles.ts +56 -0
  361. package/src/application/transform/ref-pointer/original-index.ts +95 -0
  362. package/src/application/transform/ref-pointer/pointer-type.ts +92 -0
  363. package/src/application/transform/ref-pointer/pointer-walk.ts +96 -0
  364. package/src/application/transform/ref-pointer/typed-walk.ts +192 -0
  365. package/src/application/transform/ref-type.ts +11 -6
  366. package/src/application/transform/schema/access-flags.ts +63 -0
  367. package/src/application/transform/schema/array-type.ts +66 -5
  368. package/src/application/transform/schema/composition-type.ts +96 -24
  369. package/src/application/transform/schema/core-type.ts +8 -4
  370. package/src/application/transform/schema/discriminated-union.ts +58 -0
  371. package/src/application/transform/schema/discriminator-property.ts +8 -3
  372. package/src/application/transform/schema/enum-rule.ts +136 -13
  373. package/src/application/transform/schema/inherited-discriminator.ts +54 -0
  374. package/src/application/transform/schema/object-type.ts +51 -33
  375. package/src/application/transform/schema/required-variants.ts +88 -0
  376. package/src/application/transform/schema/schema-context.ts +26 -0
  377. package/src/application/transform/schema/schema-transform.ts +2 -2
  378. package/src/application/transform/schema-comment.ts +84 -4
  379. package/src/cli/cli-arguments.ts +13 -3
  380. package/src/cli/cli-dependencies.ts +5 -0
  381. package/src/cli/cli-errors.ts +4 -2
  382. package/src/cli/cli-output.ts +18 -4
  383. package/src/cli/main.ts +6 -0
  384. package/src/cli/redocly-apis.ts +8 -4
  385. package/src/cli/ref-limits.ts +2 -2
  386. package/src/cli/run-cli.ts +20 -3
  387. package/src/domain/errors.ts +2 -0
  388. package/src/domain/ir/constructors.ts +6 -1
  389. package/src/domain/ir/nodes.ts +2 -1
  390. package/src/domain/openapi/admitted-values.ts +113 -0
  391. package/src/domain/openapi/discriminated-union.ts +109 -0
  392. package/src/domain/openapi/discriminator-conflicts.ts +251 -0
  393. package/src/domain/openapi/parameter-object.ts +4 -0
  394. package/src/domain/openapi/path-templates.ts +31 -0
  395. package/src/domain/openapi/schema-object.ts +2 -0
  396. package/src/domain/output-fixes.ts +43 -2
  397. package/src/domain/warnings.ts +20 -0
  398. package/src/transform/components-object.ts +3 -1
  399. package/src/types/generator-options.ts +11 -0
  400. package/dist/application/transform/document/path-item-conflicts.cjs +0 -51
  401. package/dist/application/transform/document/path-item-conflicts.cjs.map +0 -1
  402. package/dist/application/transform/document/path-item-conflicts.mjs +0 -49
  403. package/dist/application/transform/document/path-item-conflicts.mjs.map +0 -1
  404. package/src/application/transform/document/path-item-conflicts.ts +0 -79
@@ -14,18 +14,26 @@ import {
14
14
  pathItemOperations,
15
15
  } from "../../../domain/openapi/path-item-object.js";
16
16
  import type { ReferenceSchema, SchemaObject } from "../../../domain/openapi/schema-object.js";
17
+ import { OutputFix } from "../../../domain/output-fixes.js";
17
18
  import { documentEntries } from "../document-entries.js";
18
19
  import { refType } from "../ref-type.js";
19
20
  import type { TransformContext } from "../transform-context.js";
21
+ import { type DeclaredTypeLookup, NO_DECLARED_TYPES } from "./declared-types.js";
20
22
  import { documentMember } from "./document-member.js";
21
23
  import { pathItemType } from "./path-item.js";
22
- import { isCoveredPathItemRejected } from "./path-item-conflicts.js";
23
24
  import {
25
+ type CoverRejection,
24
26
  coveringTemplateKeys,
25
27
  type PathKey,
26
28
  type PathKeyPart,
27
29
  type PathPlaceholder,
28
30
  } from "./path-key-overlaps.js";
31
+ import {
32
+ type PathParameterMatch,
33
+ placeholderText,
34
+ replacedTemplateParts,
35
+ } from "./path-template-replace.js";
36
+ import { assignabilityProof } from "./type-assignability.js";
29
37
 
30
38
  const PATH_PARAMETER_RE = /\{[^}]+\}/g;
31
39
 
@@ -37,11 +45,6 @@ const PLACEHOLDERS: ReadonlyMap<unknown, PathPlaceholder> = new Map([
37
45
  ]);
38
46
  const STRING_PLACEHOLDER: PathPlaceholder = "string";
39
47
 
40
- /** `${type}`: the text of a template literal type placeholder. */
41
- function placeholderText(type: PathPlaceholder): string {
42
- return `\${${type}}`;
43
- }
44
-
45
48
  function resolvedParameter(
46
49
  parameter: ParameterOrReference,
47
50
  context: TransformContext,
@@ -80,29 +83,37 @@ function pathParameters(
80
83
  return byName;
81
84
  }
82
85
 
86
+ /** Each `{name}` of the URL and its own placeholder, from the URL split at the matches. */
87
+ function splitTemplateParts(url: string, matches: readonly PathParameterMatch[]): PathKeyPart[] {
88
+ return url.split(PATH_PARAMETER_RE).flatMap((text, index): PathKeyPart[] => {
89
+ const type = matches[index]?.type;
90
+ const textPart: PathKeyPart = { kind: "text", text };
91
+ return type === undefined ? [textPart] : [textPart, { kind: "placeholder", type }];
92
+ });
93
+ }
94
+
83
95
  /**
84
96
  * `--path-params-as-types`: the URL as template parts, each `{name}` replaced by a placeholder for
85
- * its parameter's type. Null when the URL has no complete `{…}` placeholder.
97
+ * its parameter's type, the way the original replaces them unless the `path-param-type-names` fix
98
+ * is on (see `replacedTemplateParts`). Null when the URL has no complete `{…}` placeholder.
86
99
  */
87
100
  function pathTemplateParts(
88
101
  url: string,
89
102
  pathItem: PathItemObject,
90
103
  context: TransformContext,
91
104
  ): PathKeyPart[] | null {
92
- const matches = url.match(PATH_PARAMETER_RE);
93
- if (!matches) {
105
+ const found = url.match(PATH_PARAMETER_RE);
106
+ if (!found) {
94
107
  return null;
95
108
  }
96
109
  const parameters = pathParameters(pathItem, context);
97
- const placeholders = matches.map((match) => {
110
+ const matches = found.map((match): PathParameterMatch => {
98
111
  const schema = parameters.get(match.slice(1, -1))?.schema as SchemaObject | undefined;
99
- return PLACEHOLDERS.get(schema?.type) ?? STRING_PLACEHOLDER;
100
- });
101
- return url.split(PATH_PARAMETER_RE).flatMap((text, index): PathKeyPart[] => {
102
- const type = placeholders[index];
103
- const textPart: PathKeyPart = { kind: "text", text };
104
- return type === undefined ? [textPart] : [textPart, { kind: "placeholder", type }];
112
+ return { match, type: PLACEHOLDERS.get(schema?.type) ?? STRING_PLACEHOLDER };
105
113
  });
114
+ return context.options.fixes.has(OutputFix.PATH_PARAM_TYPE_NAMES)
115
+ ? splitTemplateParts(url, matches)
116
+ : replacedTemplateParts(url, matches);
106
117
  }
107
118
 
108
119
  /**
@@ -120,7 +131,8 @@ function templateText(parts: readonly PathKeyPart[]): string {
120
131
  }
121
132
 
122
133
  /** A path's member, its key and its path item type for the overlap check. */
123
- interface PathMember {
134
+ export interface PathMember {
135
+ readonly url: string;
124
136
  readonly member: IrMember;
125
137
  readonly key: PathKey;
126
138
  readonly type: IrType;
@@ -139,7 +151,7 @@ function pathItemMember(
139
151
  : null;
140
152
  if (parts === null) {
141
153
  const member = irProperty(toPropertyName(url), type, { isReadonly });
142
- return { member, key: literalKey(url), type };
154
+ return { url, member, key: literalKey(url), type };
143
155
  }
144
156
  const member: IrMember = {
145
157
  kind: "indexSignature",
@@ -149,33 +161,75 @@ function pathItemMember(
149
161
  isReadonly,
150
162
  comments: [],
151
163
  };
152
- return { member, key: { kind: "template", parts }, type };
164
+ return { url, member, key: { kind: "template", parts }, type };
153
165
  }
154
166
 
155
167
  function literalKey(url: string): PathKey {
156
168
  return { kind: "literal", url };
157
169
  }
158
170
 
171
+ const PATHS_TYPE_NAME = "paths";
172
+
173
+ /** The URL of `paths["/apps/{id}"]`, or null for any other type. */
174
+ function pathsIndexOf(type: IrType): string | null {
175
+ if (type.kind !== "indexedAccess" || type.index.kind !== "stringLiteral") {
176
+ return null;
177
+ }
178
+ const { object } = type;
179
+ const isPaths =
180
+ object.kind === "reference" &&
181
+ object.name === PATHS_TYPE_NAME &&
182
+ object.typeArguments.length === 0;
183
+ return isPaths ? type.index.value : null;
184
+ }
185
+
186
+ /**
187
+ * The lookup, and `paths["/apps/{id}"]` as that path's item. The declarations cannot read it: a
188
+ * templated path is no property of `paths`, and TypeScript finds it through the signature.
189
+ */
190
+ function withPathItems(
191
+ paths: readonly PathMember[],
192
+ lookup: DeclaredTypeLookup,
193
+ ): DeclaredTypeLookup {
194
+ const byUrl = new Map(paths.map((path) => [path.url, path.type]));
195
+ return (type) => {
196
+ const url = pathsIndexOf(type);
197
+ return (url === null ? undefined : byUrl.get(url)) ?? lookup(type);
198
+ };
199
+ }
200
+
201
+ /**
202
+ * The rejection of a covered path item: only one proven not assignable to the signature's type
203
+ * counts (ADR-028). A pair the proof cannot decide keeps the original output, which may well
204
+ * compile (`Record<string, never>` fits `{ [key: string]: unknown }`).
205
+ */
206
+ function rejectionOf(paths: readonly PathMember[], lookup: DeclaredTypeLookup): CoverRejection {
207
+ const relate = assignabilityProof(withPathItems(paths, lookup));
208
+ return (coveringIndex, coveredIndex) => {
209
+ const coveringPath = paths[coveringIndex];
210
+ const coveredPath = paths[coveredIndex];
211
+ return (
212
+ coveringPath !== undefined &&
213
+ coveredPath !== undefined &&
214
+ relate(coveredPath.type, coveringPath.type) === "rejected"
215
+ );
216
+ };
217
+ }
218
+
159
219
  /**
160
220
  * The members as one object type. When an index signature covers another key, TypeScript checks
161
221
  * the covered key's type against it. Where that check surely fails (TS2411, TS2413), each such
162
222
  * signature gets an object of its own in an intersection: an intersection does not check its parts
163
223
  * against each other, and every key has the type it had in the one object. Output that compiles
164
- * keeps the one object.
224
+ * keeps the one object. The lookup reads the types that path items reference; without it, a
225
+ * reference decides nothing.
165
226
  */
166
- function pathsObjectType(paths: readonly PathMember[]): IrType {
167
- const covering = coveringTemplateKeys(
168
- paths.map(({ key }) => key),
169
- (coveringIndex, coveredIndex) => {
170
- const coveringPath = paths[coveringIndex];
171
- const coveredPath = paths[coveredIndex];
172
- return (
173
- coveringPath !== undefined &&
174
- coveredPath !== undefined &&
175
- isCoveredPathItemRejected(coveredPath.type, coveringPath.type)
176
- );
177
- },
178
- );
227
+ export function pathsObjectType(
228
+ paths: readonly PathMember[],
229
+ lookup: DeclaredTypeLookup = NO_DECLARED_TYPES,
230
+ ): IrType {
231
+ const keys = paths.map(({ key }) => key);
232
+ const covering = coveringTemplateKeys(keys, rejectionOf(paths, lookup));
179
233
  if (covering.size === 0) {
180
234
  return irObject(paths.map(({ member }) => member));
181
235
  }
@@ -186,8 +240,8 @@ function pathsObjectType(paths: readonly PathMember[]): IrType {
186
240
  return irIntersection([irObject(rest), ...own]);
187
241
  }
188
242
 
189
- /** The `paths` interface body (OpenAPI 3.1 §4.8.8): one member per path, by URL. */
190
- export function pathsType(paths: PathsObject, context: TransformContext): IrType {
243
+ /** The members of the `paths` interface (OpenAPI 3.1 §4.8.8): one per path, by URL. */
244
+ export function pathMembers(paths: PathsObject, context: TransformContext): PathMember[] {
191
245
  const members: PathMember[] = [];
192
246
  for (const [url, pathItem] of documentEntries(paths, context.options)) {
193
247
  if (!pathItem || typeof pathItem !== "object") {
@@ -196,7 +250,7 @@ export function pathsType(paths: PathsObject, context: TransformContext): IrType
196
250
  if ("$ref" in pathItem) {
197
251
  const options = { isReadonly: context.options.immutable };
198
252
  const member = documentMember(url, refType(pathItem.$ref), pathItem, options);
199
- members.push({ member, key: literalKey(url), type: member.type });
253
+ members.push({ url, member, key: literalKey(url), type: member.type });
200
254
  continue;
201
255
  }
202
256
  const startedAt = context.diagnostics.now();
@@ -207,5 +261,13 @@ export function pathsType(paths: PathsObject, context: TransformContext): IrType
207
261
  context.diagnostics.debug(`Transformed path "${url}"`, context.diagnostics.now() - startedAt);
208
262
  }
209
263
  }
210
- return pathsObjectType(members);
264
+ return members;
265
+ }
266
+
267
+ /**
268
+ * The `paths` interface body, with only the path items' own types for the overlap check. The
269
+ * document transform checks the overlaps again once the referenced types are declared.
270
+ */
271
+ export function pathsType(paths: PathsObject, context: TransformContext): IrType {
272
+ return pathsObjectType(pathMembers(paths, context));
211
273
  }
@@ -2,6 +2,7 @@ import { irRaw } from "../../../domain/ir/constructors.js";
2
2
  import type { IrDeclaration, IrTypeAliasDeclaration } from "../../../domain/ir/nodes.js";
3
3
  import { escapeSingleQuotedText } from "../../../domain/ir/raw-text-escapes.js";
4
4
  import type { ComponentKind } from "../../../domain/openapi/components-object.js";
5
+ import { globalTypeReferences } from "./global-type-references.js";
5
6
 
6
7
  /** The `--root-types` aliases: `export type Pet = components['schemas']['Pet'];`. */
7
8
 
@@ -66,37 +67,37 @@ function freeName(name: string, taken: ReadonlySet<string>): string {
66
67
  }
67
68
 
68
69
  /**
69
- * With the `root-type-numbering` fix (ADR-021, roadmap R13, backlog 30): the aliases that a later
70
- * schema of one exported name took the name from, numbered `Name_2`, `Name_3`, … in document order
71
- * with the next free number. The later schema keeps the name, so the fix only adds exports.
70
+ * Rename each root alias whose name an enum or a helper type of the footer also declares, or that
71
+ * shadows a TypeScript global type the output refers to (`Record` in `Record<string, never>`), to
72
+ * the next free `Name_2`, `Name_3`, … (the suffix `--root-types` uses for its own conflicts). The
73
+ * footer and the globals keep their names, because the generated types refer to them. Before, the
74
+ * output did not compile (enums: upstream #2099, #2341, #2206; helpers: a schema named
75
+ * `WithRequired`, roadmap R11; globals: TS2315). Other declarations are returned unchanged.
76
+ *
77
+ * With the `root-type-numbering` fix (ADR-021, roadmap R13, backlog 30) the body also holds the
78
+ * aliases a later schema of one exported name took the name from, after the other aliases and
79
+ * under that same name. Each gets the next free number in body order, after the alias that kept
80
+ * the name got its own: so the fix only adds exports, and every other alias keeps the name it has
81
+ * without the fix.
72
82
  */
73
- export function numberDisplacedAliases(
74
- displaced: readonly IrTypeAliasDeclaration[],
75
- kept: readonly IrTypeAliasDeclaration[],
76
- ): IrTypeAliasDeclaration[] {
77
- const taken = new Set(kept.map((alias) => alias.name));
78
- return displaced.map((alias) => {
79
- const name = freeName(alias.name, taken);
80
- taken.add(name);
81
- return { ...alias, name };
82
- });
83
- }
84
-
85
- /**
86
- * Rename each root alias whose name an enum or a helper type of the footer also declares, to the
87
- * next free `Name_2`, `Name_3`, … (the suffix `--root-types` uses for its own conflicts). The
88
- * footer keeps its names, because the generated types refer to them. Before, both were declared
89
- * under one name, which does not compile (enums: upstream #2099, #2341, #2206; helpers: a schema
90
- * named `WithRequired`, roadmap R11). Other declarations are returned unchanged.
91
- */
92
- export function renameAliasesTakenByFooter(
93
- body: readonly IrDeclaration[],
83
+ export function renameTakenAliases<T extends IrDeclaration>(
84
+ body: readonly T[],
94
85
  footer: readonly IrDeclaration[],
95
- ): IrDeclaration[] {
96
- const footerNames = footerTypeNames(footer);
97
- const taken = declaredNames([...body, ...footer]);
86
+ closing: readonly IrDeclaration[] = [],
87
+ ): T[] {
88
+ const reserved = footerTypeNames(footer);
89
+ for (const name of globalTypeReferences([...body, ...footer, ...closing])) {
90
+ reserved.add(name);
91
+ }
92
+ const taken = declaredNames([...body, ...footer, ...closing]);
93
+ const aliasNames = new Set<string>();
98
94
  return body.map((declaration) => {
99
- if (!isRootTypeAlias(declaration) || !footerNames.has(declaration.name)) {
95
+ if (!isRootTypeAlias(declaration)) {
96
+ return declaration;
97
+ }
98
+ const isRepeated = aliasNames.has(declaration.name);
99
+ aliasNames.add(declaration.name);
100
+ if (!isRepeated && !reserved.has(declaration.name)) {
100
101
  return declaration;
101
102
  }
102
103
  const name = freeName(declaration.name, taken);
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Whether a key type is assignable to a template literal key type, decided the way TypeScript's
3
+ * checker decides it (`inferFromLiteralPartsToTemplateLiteral` and
4
+ * `isValidTypeForTemplateLiteralPlaceholder` in TypeScript 5 and 6). An index signature checks
5
+ * exactly the keys that are assignable to its key type, so the overlap check must match the
6
+ * checker, not the strings a template stands for: the checker matches each text of the target at
7
+ * its first occurrence, so it misses some keys a regular expression would match, and a key it
8
+ * misses is never checked against the signature.
9
+ */
10
+
11
+ /** A placeholder type of a template, after `${boolean}` became the texts `true` and `false`. */
12
+ export type TemplatePlaceholder = "string" | "number";
13
+
14
+ /**
15
+ * A key type as TypeScript stores a template literal: texts around placeholders, one more text
16
+ * than placeholders. A string literal is one text and no placeholder.
17
+ */
18
+ export interface TemplateShape {
19
+ readonly texts: readonly string[];
20
+ readonly types: readonly TemplatePlaceholder[];
21
+ }
22
+
23
+ /** The text at an index of the shape; every caller passes one of `0 .. types.length`. */
24
+ function textAt(shape: TemplateShape, index: number): string {
25
+ return shape.texts[index] as string;
26
+ }
27
+
28
+ /** The type the checker infers for one target placeholder: a text, or a slice of the source. */
29
+ type InferredMatch =
30
+ | { readonly kind: "text"; readonly text: string }
31
+ | { readonly kind: "template"; readonly shape: TemplateShape };
32
+
33
+ /** TypeScript's `isValidNumberString(text, false)`: a text that converts to a finite number. */
34
+ export function isNumberText(text: string): boolean {
35
+ return text !== "" && Number.isFinite(Number(text));
36
+ }
37
+
38
+ /** Whether the inferred type fits a placeholder: any string for `string`, a number for `number`. */
39
+ function isValidMatch(match: InferredMatch, placeholder: TemplatePlaceholder): boolean {
40
+ if (placeholder === "string") {
41
+ return true;
42
+ }
43
+ if (match.kind === "text") {
44
+ return isNumberText(match.text);
45
+ }
46
+ const { texts, types } = match.shape;
47
+ return texts.length === 2 && texts[0] === "" && texts[1] === "" && types[0] === "number";
48
+ }
49
+
50
+ /** The state of the scan through the source: the current text and the position in it. */
51
+ interface Cursor {
52
+ readonly segment: number;
53
+ readonly position: number;
54
+ }
55
+
56
+ /** The scan of `inferFromLiteralPartsToTemplateLiteral`, over one source and one target. */
57
+ class LiteralPartsScan {
58
+ private readonly matches: InferredMatch[] = [];
59
+ private cursor: Cursor;
60
+ private readonly source: TemplateShape;
61
+ private readonly lastSourceIndex: number;
62
+ private readonly remainingEndText: string;
63
+
64
+ constructor(source: TemplateShape, startPosition: number, endTextLength: number) {
65
+ this.source = source;
66
+ this.lastSourceIndex = source.texts.length - 1;
67
+ const endText = textAt(source, this.lastSourceIndex);
68
+ this.remainingEndText = endText.slice(0, endText.length - endTextLength);
69
+ this.cursor = { segment: 0, position: startPosition };
70
+ }
71
+
72
+ /** The matches for the target's texts between its first and last; null when one is missing. */
73
+ run(delimiters: readonly string[]): readonly InferredMatch[] | null {
74
+ for (const delimiter of delimiters) {
75
+ if (!this.matchDelimiter(delimiter)) {
76
+ return null;
77
+ }
78
+ }
79
+ this.addMatch(this.lastSourceIndex, this.sourceText(this.lastSourceIndex).length);
80
+ return this.matches;
81
+ }
82
+
83
+ private matchDelimiter(delimiter: string): boolean {
84
+ const { segment, position } = this.cursor;
85
+ if (delimiter.length > 0) {
86
+ const found = this.find(delimiter);
87
+ if (found === null) {
88
+ return false;
89
+ }
90
+ this.addMatch(found.segment, found.position);
91
+ this.cursor = { ...this.cursor, position: this.cursor.position + delimiter.length };
92
+ return true;
93
+ }
94
+ if (position < this.sourceText(segment).length) {
95
+ this.addMatch(segment, position + 1);
96
+ return true;
97
+ }
98
+ if (segment < this.lastSourceIndex) {
99
+ this.addMatch(segment + 1, 0);
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+
105
+ /** The first occurrence of the delimiter at or after the cursor, in this or a later text. */
106
+ private find(delimiter: string): Cursor | null {
107
+ let { segment, position } = this.cursor;
108
+ while (segment < this.source.texts.length) {
109
+ const index = this.sourceText(segment).indexOf(delimiter, position);
110
+ if (index >= 0) {
111
+ return { segment, position: index };
112
+ }
113
+ segment += 1;
114
+ position = 0;
115
+ }
116
+ return null;
117
+ }
118
+
119
+ private sourceText(index: number): string {
120
+ return index < this.lastSourceIndex ? textAt(this.source, index) : this.remainingEndText;
121
+ }
122
+
123
+ private addMatch(segment: number, position: number): void {
124
+ const start = this.cursor;
125
+ if (segment === start.segment) {
126
+ const text = this.sourceText(segment).slice(start.position, position);
127
+ this.matches.push({ kind: "text", text });
128
+ } else {
129
+ const texts = [
130
+ textAt(this.source, start.segment).slice(start.position),
131
+ ...this.source.texts.slice(start.segment + 1, segment),
132
+ this.sourceText(segment).slice(0, position),
133
+ ];
134
+ const types = this.source.types.slice(start.segment, segment);
135
+ this.matches.push({ kind: "template", shape: { texts, types } });
136
+ }
137
+ this.cursor = { segment, position };
138
+ }
139
+ }
140
+
141
+ /** The checker's inferences for the target's placeholders; null when the texts do not fit. */
142
+ function inferMatches(
143
+ source: TemplateShape,
144
+ target: TemplateShape,
145
+ ): readonly InferredMatch[] | null {
146
+ const sourceStart = textAt(source, 0);
147
+ const sourceEnd = textAt(source, source.texts.length - 1);
148
+ const targetStart = textAt(target, 0);
149
+ const targetEnd = textAt(target, target.texts.length - 1);
150
+ const isTooShort =
151
+ source.texts.length === 1 && sourceStart.length < targetStart.length + targetEnd.length;
152
+ if (isTooShort || !sourceStart.startsWith(targetStart) || !sourceEnd.endsWith(targetEnd)) {
153
+ return null;
154
+ }
155
+ const scan = new LiteralPartsScan(source, targetStart.length, targetEnd.length);
156
+ return scan.run(target.texts.slice(1, -1));
157
+ }
158
+
159
+ function haveSameTexts(source: TemplateShape, target: TemplateShape): boolean {
160
+ return (
161
+ source.texts.length === target.texts.length &&
162
+ source.texts.every((text, index) => text === target.texts[index])
163
+ );
164
+ }
165
+
166
+ /**
167
+ * Whether the source key type is assignable to the target template. Templates with the same texts
168
+ * compare placeholder by placeholder (`inferTypesFromTemplateLiteralType`).
169
+ */
170
+ export function isAssignableToTemplate(source: TemplateShape, target: TemplateShape): boolean {
171
+ if (source.types.length > 0 && haveSameTexts(source, target)) {
172
+ return source.types.every((type, index) => {
173
+ const placeholder = target.types[index];
174
+ return placeholder === "string" || type === placeholder;
175
+ });
176
+ }
177
+ const matches = inferMatches(source, target);
178
+ const isEveryMatchValid = matches?.every((match, index) => {
179
+ const placeholder = target.types[index];
180
+ return placeholder !== undefined && isValidMatch(match, placeholder);
181
+ });
182
+ return isEveryMatchValid === true;
183
+ }