@scalar/blocks 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +13 -29
  3. package/dist/code-example/components/AsyncApiCodeExample.vue.d.ts +19 -0
  4. package/dist/code-example/components/AsyncApiCodeExample.vue.d.ts.map +1 -0
  5. package/dist/code-example/components/AsyncApiCodeExample.vue.js +9 -0
  6. package/dist/code-example/components/AsyncApiCodeExample.vue.js.map +1 -0
  7. package/dist/code-example/components/AsyncApiCodeExample.vue_vue_type_script_setup_true_lang.js +114 -0
  8. package/dist/code-example/components/AsyncApiCodeExample.vue_vue_type_script_setup_true_lang.js.map +1 -0
  9. package/dist/code-example/components/CodeExample.vue.js +4 -4
  10. package/dist/code-example/components/CodeExample.vue.js.map +1 -1
  11. package/dist/code-example/components/CodeExample.vue_vue_type_script_setup_true_lang.js +258 -0
  12. package/dist/code-example/components/CodeExample.vue_vue_type_script_setup_true_lang.js.map +1 -0
  13. package/dist/code-example/components/ExamplePicker.vue.js +1 -1
  14. package/dist/code-example/components/ExamplePicker.vue.js.map +1 -1
  15. package/dist/code-example/components/{ExamplePicker.vue.script.js → ExamplePicker.vue_vue_type_script_setup_true_lang.js} +5 -5
  16. package/dist/code-example/components/ExamplePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  17. package/dist/code-example/components/HttpMethod.vue.js +1 -1
  18. package/dist/code-example/components/HttpMethod.vue.js.map +1 -1
  19. package/dist/code-example/components/{HttpMethod.vue.script.js → HttpMethod.vue_vue_type_script_setup_true_lang.js} +1 -1
  20. package/dist/code-example/components/HttpMethod.vue_vue_type_script_setup_true_lang.js.map +1 -0
  21. package/dist/code-example/helpers/filter-clients-by-query.js.map +1 -1
  22. package/dist/code-example/helpers/find-client.js.map +1 -1
  23. package/dist/code-example/helpers/format-language.js.map +1 -1
  24. package/dist/code-example/helpers/generate-client-options.js.map +1 -1
  25. package/dist/code-example/helpers/generate-code-snippet.js.map +1 -1
  26. package/dist/code-example/helpers/get-asyncapi-example-context.d.ts +12 -0
  27. package/dist/code-example/helpers/get-asyncapi-example-context.d.ts.map +1 -0
  28. package/dist/code-example/helpers/get-asyncapi-example-context.js +33 -0
  29. package/dist/code-example/helpers/get-asyncapi-example-context.js.map +1 -0
  30. package/dist/code-example/helpers/get-clients.js.map +1 -1
  31. package/dist/code-example/helpers/get-custom-code-samples.js.map +1 -1
  32. package/dist/code-example/helpers/get-generated-payload-example.d.ts +4 -0
  33. package/dist/code-example/helpers/get-generated-payload-example.d.ts.map +1 -0
  34. package/dist/code-example/helpers/get-generated-payload-example.js +25 -0
  35. package/dist/code-example/helpers/get-generated-payload-example.js.map +1 -0
  36. package/dist/code-example/helpers/get-message-example-content.d.ts +10 -0
  37. package/dist/code-example/helpers/get-message-example-content.d.ts.map +1 -0
  38. package/dist/code-example/helpers/get-message-example-content.js +29 -0
  39. package/dist/code-example/helpers/get-message-example-content.js.map +1 -0
  40. package/dist/code-example/helpers/get-secrets.js.map +1 -1
  41. package/dist/code-example/helpers/get-snippet.js.map +1 -1
  42. package/dist/code-example/helpers/operation-to-har/operation-to-har.js +32 -32
  43. package/dist/code-example/helpers/operation-to-har/operation-to-har.js.map +1 -1
  44. package/dist/code-example/helpers/operation-to-har/process-body.js +41 -47
  45. package/dist/code-example/helpers/operation-to-har/process-body.js.map +1 -1
  46. package/dist/code-example/helpers/operation-to-har/process-parameters.js +51 -55
  47. package/dist/code-example/helpers/operation-to-har/process-parameters.js.map +1 -1
  48. package/dist/code-example/helpers/operation-to-har/process-security-schemes.js +30 -38
  49. package/dist/code-example/helpers/operation-to-har/process-security-schemes.js.map +1 -1
  50. package/dist/code-example/helpers/operation-to-har/process-server-url.js +5 -1
  51. package/dist/code-example/helpers/operation-to-har/process-server-url.js.map +1 -1
  52. package/dist/code-example/index.d.ts +4 -0
  53. package/dist/code-example/index.d.ts.map +1 -1
  54. package/dist/code-example/index.js +17 -14
  55. package/dist/code-example/mount-asyncapi.d.ts +14 -0
  56. package/dist/code-example/mount-asyncapi.d.ts.map +1 -0
  57. package/dist/code-example/mount-asyncapi.js +27 -0
  58. package/dist/code-example/mount-asyncapi.js.map +1 -0
  59. package/dist/code-example/mount.d.ts +4 -2
  60. package/dist/code-example/mount.d.ts.map +1 -1
  61. package/dist/code-example/mount.js +39 -37
  62. package/dist/code-example/mount.js.map +1 -1
  63. package/dist/constants.js +1 -1
  64. package/dist/constants.js.map +1 -1
  65. package/dist/schema/LinkButton.vue.js.map +1 -1
  66. package/dist/schema/RenderString.vue.js +1 -1
  67. package/dist/schema/RenderString.vue.js.map +1 -1
  68. package/dist/schema/{RenderString.vue.script.js → RenderString.vue_vue_type_script_setup_true_lang.js} +1 -1
  69. package/dist/schema/RenderString.vue_vue_type_script_setup_true_lang.js.map +1 -0
  70. package/dist/schema/Schema.vue.js +2 -2
  71. package/dist/schema/Schema.vue.js.map +1 -1
  72. package/dist/schema/{Schema.vue.script.js → Schema.vue_vue_type_script_setup_true_lang.js} +1 -1
  73. package/dist/schema/Schema.vue_vue_type_script_setup_true_lang.js.map +1 -0
  74. package/dist/schema/SchemaCollapsedPreview.vue.js +1 -1
  75. package/dist/schema/SchemaCollapsedPreview.vue.js.map +1 -1
  76. package/dist/schema/{SchemaCollapsedPreview.vue.script.js → SchemaCollapsedPreview.vue_vue_type_script_setup_true_lang.js} +1 -1
  77. package/dist/schema/SchemaCollapsedPreview.vue_vue_type_script_setup_true_lang.js.map +1 -0
  78. package/dist/schema/SchemaComposition.vue.js +2 -2
  79. package/dist/schema/SchemaComposition.vue.js.map +1 -1
  80. package/dist/schema/{SchemaComposition.vue.script.js → SchemaComposition.vue_vue_type_script_setup_true_lang.js} +5 -5
  81. package/dist/schema/SchemaComposition.vue_vue_type_script_setup_true_lang.js.map +1 -0
  82. package/dist/schema/SchemaEnumPropertyItem.vue.js +1 -1
  83. package/dist/schema/SchemaEnumPropertyItem.vue.js.map +1 -1
  84. package/dist/schema/{SchemaEnumPropertyItem.vue.script.js → SchemaEnumPropertyItem.vue_vue_type_script_setup_true_lang.js} +1 -1
  85. package/dist/schema/SchemaEnumPropertyItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
  86. package/dist/schema/SchemaEnums.vue.js +2 -2
  87. package/dist/schema/SchemaEnums.vue.js.map +1 -1
  88. package/dist/schema/{SchemaEnums.vue.script.js → SchemaEnums.vue_vue_type_script_setup_true_lang.js} +1 -1
  89. package/dist/schema/SchemaEnums.vue_vue_type_script_setup_true_lang.js.map +1 -0
  90. package/dist/schema/SchemaGlyphPuck.vue.js +1 -1
  91. package/dist/schema/SchemaGlyphPuck.vue.js.map +1 -1
  92. package/dist/schema/{SchemaGlyphPuck.vue.script.js → SchemaGlyphPuck.vue_vue_type_script_setup_true_lang.js} +1 -1
  93. package/dist/schema/SchemaGlyphPuck.vue_vue_type_script_setup_true_lang.js.map +1 -0
  94. package/dist/schema/SchemaGutterToggle.vue.js +1 -1
  95. package/dist/schema/SchemaGutterToggle.vue.js.map +1 -1
  96. package/dist/schema/{SchemaGutterToggle.vue.script.js → SchemaGutterToggle.vue_vue_type_script_setup_true_lang.js} +1 -1
  97. package/dist/schema/SchemaGutterToggle.vue_vue_type_script_setup_true_lang.js.map +1 -0
  98. package/dist/schema/SchemaHeading.vue.js +2 -2
  99. package/dist/schema/SchemaHeading.vue.js.map +1 -1
  100. package/dist/schema/{SchemaHeading.vue.script.js → SchemaHeading.vue_vue_type_script_setup_true_lang.js} +1 -1
  101. package/dist/schema/SchemaHeading.vue_vue_type_script_setup_true_lang.js.map +1 -0
  102. package/dist/schema/SchemaObjectExampleCodeBlock.vue.js +1 -1
  103. package/dist/schema/SchemaObjectExampleCodeBlock.vue.js.map +1 -1
  104. package/dist/schema/{SchemaObjectExampleCodeBlock.vue.script.js → SchemaObjectExampleCodeBlock.vue_vue_type_script_setup_true_lang.js} +1 -1
  105. package/dist/schema/SchemaObjectExampleCodeBlock.vue_vue_type_script_setup_true_lang.js.map +1 -0
  106. package/dist/schema/SchemaObjectProperties.vue.js +1 -1
  107. package/dist/schema/SchemaObjectProperties.vue.js.map +1 -1
  108. package/dist/schema/{SchemaObjectProperties.vue.script.js → SchemaObjectProperties.vue_vue_type_script_setup_true_lang.js} +3 -3
  109. package/dist/schema/{SchemaObjectProperties.vue.script.js.map → SchemaObjectProperties.vue_vue_type_script_setup_true_lang.js.map} +1 -1
  110. package/dist/schema/SchemaProperty.vue.js +2 -2
  111. package/dist/schema/SchemaProperty.vue.js.map +1 -1
  112. package/dist/schema/{SchemaProperty.vue.script.js → SchemaProperty.vue_vue_type_script_setup_true_lang.js} +3 -7
  113. package/dist/schema/SchemaProperty.vue_vue_type_script_setup_true_lang.js.map +1 -0
  114. package/dist/schema/SchemaPropertyDefault.vue.js +2 -2
  115. package/dist/schema/SchemaPropertyDefault.vue.js.map +1 -1
  116. package/dist/schema/{SchemaPropertyDefault.vue.script.js → SchemaPropertyDefault.vue_vue_type_script_setup_true_lang.js} +1 -1
  117. package/dist/schema/SchemaPropertyDefault.vue_vue_type_script_setup_true_lang.js.map +1 -0
  118. package/dist/schema/SchemaPropertyDetail.vue.js +2 -2
  119. package/dist/schema/SchemaPropertyDetail.vue.js.map +1 -1
  120. package/dist/schema/{SchemaPropertyDetail.vue.script.js → SchemaPropertyDetail.vue_vue_type_script_setup_true_lang.js} +1 -1
  121. package/dist/schema/SchemaPropertyDetail.vue_vue_type_script_setup_true_lang.js.map +1 -0
  122. package/dist/schema/SchemaPropertyExamples.vue.d.ts +2 -0
  123. package/dist/schema/SchemaPropertyExamples.vue.d.ts.map +1 -1
  124. package/dist/schema/SchemaPropertyExamples.vue.js +3 -3
  125. package/dist/schema/SchemaPropertyExamples.vue.js.map +1 -1
  126. package/dist/schema/{SchemaPropertyExamples.vue.script.js → SchemaPropertyExamples.vue_vue_type_script_setup_true_lang.js} +10 -3
  127. package/dist/schema/SchemaPropertyExamples.vue_vue_type_script_setup_true_lang.js.map +1 -0
  128. package/dist/schema/SchemaPropertyHeading.vue.js +2 -2
  129. package/dist/schema/SchemaPropertyHeading.vue.js.map +1 -1
  130. package/dist/schema/{SchemaPropertyHeading.vue.script.js → SchemaPropertyHeading.vue_vue_type_script_setup_true_lang.js} +1 -1
  131. package/dist/schema/SchemaPropertyHeading.vue_vue_type_script_setup_true_lang.js.map +1 -0
  132. package/dist/schema/SchemaPropertyPattern.vue.js +2 -2
  133. package/dist/schema/SchemaPropertyPattern.vue.js.map +1 -1
  134. package/dist/schema/{SchemaPropertyPattern.vue.script.js → SchemaPropertyPattern.vue_vue_type_script_setup_true_lang.js} +1 -1
  135. package/dist/schema/SchemaPropertyPattern.vue_vue_type_script_setup_true_lang.js.map +1 -0
  136. package/dist/schema/SchemaRailPanel.vue.js +1 -1
  137. package/dist/schema/SchemaRailPanel.vue.js.map +1 -1
  138. package/dist/schema/{SchemaRailPanel.vue.script.js → SchemaRailPanel.vue_vue_type_script_setup_true_lang.js} +1 -1
  139. package/dist/schema/SchemaRailPanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  140. package/dist/schema/components/CopyLinkButton.vue.js +1 -1
  141. package/dist/schema/components/CopyLinkButton.vue.js.map +1 -1
  142. package/dist/schema/components/{CopyLinkButton.vue.script.js → CopyLinkButton.vue_vue_type_script_setup_true_lang.js} +1 -1
  143. package/dist/schema/components/CopyLinkButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  144. package/dist/schema/components/WithBreadcrumb.vue.js +1 -1
  145. package/dist/schema/components/WithBreadcrumb.vue.js.map +1 -1
  146. package/dist/schema/components/{WithBreadcrumb.vue.script.js → WithBreadcrumb.vue_vue_type_script_setup_true_lang.js} +1 -1
  147. package/dist/schema/components/WithBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -0
  148. package/dist/schema/discriminator-metadata.js.map +1 -1
  149. package/dist/schema/expansion/index.js +1 -2
  150. package/dist/schema/helpers/dynamic-scope.js.map +1 -1
  151. package/dist/schema/helpers/format-example.js.map +1 -1
  152. package/dist/schema/helpers/format-value.js.map +1 -1
  153. package/dist/schema/helpers/get-compositions-to-render.js.map +1 -1
  154. package/dist/schema/helpers/get-discriminator-values.js.map +1 -1
  155. package/dist/schema/helpers/get-enum-values.js.map +1 -1
  156. package/dist/schema/helpers/get-property-description.js.map +1 -1
  157. package/dist/schema/helpers/get-ref-name.js.map +1 -1
  158. package/dist/schema/helpers/get-schema-type.js.map +1 -1
  159. package/dist/schema/helpers/get-type-signature-tokens.js.map +1 -1
  160. package/dist/schema/helpers/has-complex-array-items.js.map +1 -1
  161. package/dist/schema/helpers/is-empty-schema-object.js.map +1 -1
  162. package/dist/schema/helpers/is-model-linkable.js.map +1 -1
  163. package/dist/schema/helpers/is-on-schema-target-path.js.map +1 -1
  164. package/dist/schema/helpers/is-type-object.js.map +1 -1
  165. package/dist/schema/helpers/merge-all-of-schemas.js +24 -25
  166. package/dist/schema/helpers/merge-all-of-schemas.js.map +1 -1
  167. package/dist/schema/helpers/normalize-object-composition.js.map +1 -1
  168. package/dist/schema/helpers/optimize-value-for-display.js +5 -12
  169. package/dist/schema/helpers/optimize-value-for-display.js.map +1 -1
  170. package/dist/schema/helpers/partition-all-of-compositions.js.map +1 -1
  171. package/dist/schema/helpers/schema-composition.js.map +1 -1
  172. package/dist/schema/helpers/schema-cycle.js.map +1 -1
  173. package/dist/schema/helpers/schema-expansion.js +4 -5
  174. package/dist/schema/helpers/schema-expansion.js.map +1 -1
  175. package/dist/schema/helpers/schema-keyboard-nav.js.map +1 -1
  176. package/dist/schema/helpers/schema-name.js.map +1 -1
  177. package/dist/schema/helpers/should-display-description.js.map +1 -1
  178. package/dist/schema/helpers/should-display-heading.js.map +1 -1
  179. package/dist/schema/helpers/should-render-array-item-composition.js.map +1 -1
  180. package/dist/schema/helpers/sort-property-names.js.map +1 -1
  181. package/dist/schema/helpers/unwrap-for-read.js.map +1 -1
  182. package/dist/schema/index.d.ts +1 -0
  183. package/dist/schema/index.d.ts.map +1 -1
  184. package/dist/schema/index.js +6 -5
  185. package/dist/schema/localization/index.d.ts +1 -1
  186. package/dist/schema/localization/index.js.map +1 -1
  187. package/dist/schema/localization/locales/ar.js.map +1 -1
  188. package/dist/schema/localization/locales/de.js.map +1 -1
  189. package/dist/schema/localization/locales/en.js.map +1 -1
  190. package/dist/schema/localization/locales/es.js.map +1 -1
  191. package/dist/schema/localization/locales/fr.js.map +1 -1
  192. package/dist/schema/localization/locales/pt.js.map +1 -1
  193. package/dist/schema/localization/locales/ru.js.map +1 -1
  194. package/dist/schema/localization/locales/zh-cn.js.map +1 -1
  195. package/dist/schema/localization/locales/zh-tw.js.map +1 -1
  196. package/dist/schema/localization/translations.js.map +1 -1
  197. package/dist/schema/request-body-composition-index.js.map +1 -1
  198. package/dist/shared/Badge.vue.js +2 -2
  199. package/dist/shared/Badge.vue.js.map +1 -1
  200. package/dist/shared/{Badge.vue.script.js → Badge.vue_vue_type_script_setup_true_lang.js} +1 -1
  201. package/dist/shared/Badge.vue_vue_type_script_setup_true_lang.js.map +1 -0
  202. package/dist/shared/ExternalDocs.vue.js +1 -1
  203. package/dist/shared/ExternalDocs.vue.js.map +1 -1
  204. package/dist/shared/{ExternalDocs.vue.script.js → ExternalDocs.vue_vue_type_script_setup_true_lang.js} +1 -1
  205. package/dist/shared/ExternalDocs.vue_vue_type_script_setup_true_lang.js.map +1 -0
  206. package/dist/shared/ScreenReader.vue.js +1 -1
  207. package/dist/shared/ScreenReader.vue.js.map +1 -1
  208. package/dist/shared/{ScreenReader.vue.script.js → ScreenReader.vue_vue_type_script_setup_true_lang.js} +1 -1
  209. package/dist/shared/ScreenReader.vue_vue_type_script_setup_true_lang.js.map +1 -0
  210. package/dist/specification-extensions/ExtensionValue.vue.js +1 -1
  211. package/dist/specification-extensions/ExtensionValue.vue.js.map +1 -1
  212. package/dist/specification-extensions/{ExtensionValue.vue.script.js → ExtensionValue.vue_vue_type_script_setup_true_lang.js} +1 -1
  213. package/dist/specification-extensions/ExtensionValue.vue_vue_type_script_setup_true_lang.js.map +1 -0
  214. package/dist/specification-extensions/SpecificationExtensions.vue.js +1 -1
  215. package/dist/specification-extensions/SpecificationExtensions.vue.js.map +1 -1
  216. package/dist/specification-extensions/{SpecificationExtensions.vue.script.js → SpecificationExtensions.vue_vue_type_script_setup_true_lang.js} +1 -1
  217. package/dist/specification-extensions/SpecificationExtensions.vue_vue_type_script_setup_true_lang.js.map +1 -0
  218. package/dist/specification-extensions/index.js +1 -2
  219. package/dist/style.css +68 -31
  220. package/dist/vue-styles.css +1 -1
  221. package/package.json +23 -23
  222. package/dist/code-example/components/CodeExample.vue.script.js +0 -258
  223. package/dist/code-example/components/CodeExample.vue.script.js.map +0 -1
  224. package/dist/code-example/components/ExamplePicker.vue.script.js.map +0 -1
  225. package/dist/code-example/components/HttpMethod.vue.script.js.map +0 -1
  226. package/dist/schema/RenderString.vue.script.js.map +0 -1
  227. package/dist/schema/Schema.vue.script.js.map +0 -1
  228. package/dist/schema/SchemaCollapsedPreview.vue.script.js.map +0 -1
  229. package/dist/schema/SchemaComposition.vue.script.js.map +0 -1
  230. package/dist/schema/SchemaEnumPropertyItem.vue.script.js.map +0 -1
  231. package/dist/schema/SchemaEnums.vue.script.js.map +0 -1
  232. package/dist/schema/SchemaGlyphPuck.vue.script.js.map +0 -1
  233. package/dist/schema/SchemaGutterToggle.vue.script.js.map +0 -1
  234. package/dist/schema/SchemaHeading.vue.script.js.map +0 -1
  235. package/dist/schema/SchemaObjectExampleCodeBlock.vue.script.js.map +0 -1
  236. package/dist/schema/SchemaProperty.vue.script.js.map +0 -1
  237. package/dist/schema/SchemaPropertyDefault.vue.script.js.map +0 -1
  238. package/dist/schema/SchemaPropertyDetail.vue.script.js.map +0 -1
  239. package/dist/schema/SchemaPropertyExamples.vue.script.js.map +0 -1
  240. package/dist/schema/SchemaPropertyHeading.vue.script.js.map +0 -1
  241. package/dist/schema/SchemaPropertyPattern.vue.script.js.map +0 -1
  242. package/dist/schema/SchemaRailPanel.vue.script.js.map +0 -1
  243. package/dist/schema/components/CopyLinkButton.vue.script.js.map +0 -1
  244. package/dist/schema/components/WithBreadcrumb.vue.script.js.map +0 -1
  245. package/dist/shared/Badge.vue.script.js.map +0 -1
  246. package/dist/shared/ExternalDocs.vue.script.js.map +0 -1
  247. package/dist/shared/ScreenReader.vue.script.js.map +0 -1
  248. package/dist/specification-extensions/ExtensionValue.vue.script.js.map +0 -1
  249. package/dist/specification-extensions/SpecificationExtensions.vue.script.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"is-model-linkable.js","names":[],"sources":["../../../src/schema/helpers/is-model-linkable.ts"],"sourcesContent":["import { getResolvedRef, mergeSiblingReferences } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { isHidden } from '@scalar/workspace-store/helpers/is-hidden'\n\nimport type { SchemaOptions } from '../types'\nimport { unwrapForRead } from './unwrap-for-read'\n\n/** The slice of schema options needed to decide whether a model name renders as a link. */\nexport type ModelLinkOptions = Pick<SchemaOptions, 'hideModels' | 'document'>\n\n/**\n * A model name normally links to its entry in the models section. It should render as plain\n * text when there is nothing to scroll to:\n *\n * - the whole models section is hidden via `hideModels`, or\n * - the referenced schema itself is hidden via `x-internal` / `x-scalar-ignore`.\n *\n * The hidden check mirrors how the sidebar decides which schemas to drop (see `traverseSchemas`),\n * so the link only shows when the model actually exists in the models section.\n */\nexport const isModelLinkable = (\n schemaKey: string | null | undefined,\n { hideModels, document }: ModelLinkOptions,\n): boolean => {\n if (!schemaKey || hideModels) {\n return false\n }\n\n // Walking down to a single component schema costs three proxied reads per row, so the\n // document is taken off the reactive and detect-changes layers first. See `unwrapForRead`.\n const schema = unwrapForRead(document)?.components?.schemas?.[schemaKey]\n\n return !isHidden(getResolvedRef(schema, mergeSiblingReferences))\n}\n"],"mappings":";;;;AAmBA,IAAa,KACX,GACA,EAAE,eAAY,kBACF;CACZ,IAAI,CAAC,KAAa,GAChB,OAAO;CAKT,IAAM,IAAS,EAAc,CAAQ,CAAC,EAAE,YAAY,UAAU;CAE9D,OAAO,CAAC,EAAS,EAAe,GAAQ,CAAsB,CAAC;AACjE"}
1
+ {"version":3,"file":"is-model-linkable.js","names":["isModelLinkable","schemaKey","hideModels","schema","unwrapForRead","document","isHidden","getResolvedRef","mergeSiblingReferences"],"sources":["../../../src/schema/helpers/is-model-linkable.ts"],"sourcesContent":["import { getResolvedRef, mergeSiblingReferences } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { isHidden } from '@scalar/workspace-store/helpers/is-hidden'\n\nimport type { SchemaOptions } from '../types'\nimport { unwrapForRead } from './unwrap-for-read'\n\n/** The slice of schema options needed to decide whether a model name renders as a link. */\nexport type ModelLinkOptions = Pick<SchemaOptions, 'hideModels' | 'document'>\n\n/**\n * A model name normally links to its entry in the models section. It should render as plain\n * text when there is nothing to scroll to:\n *\n * - the whole models section is hidden via `hideModels`, or\n * - the referenced schema itself is hidden via `x-internal` / `x-scalar-ignore`.\n *\n * The hidden check mirrors how the sidebar decides which schemas to drop (see `traverseSchemas`),\n * so the link only shows when the model actually exists in the models section.\n */\nexport const isModelLinkable = (\n schemaKey: string | null | undefined,\n { hideModels, document }: ModelLinkOptions,\n): boolean => {\n if (!schemaKey || hideModels) {\n return false\n }\n\n // Walking down to a single component schema costs three proxied reads per row, so the\n // document is taken off the reactive and detect-changes layers first. See `unwrapForRead`.\n const schema = unwrapForRead(document)?.components?.schemas?.[schemaKey]\n\n return !isHidden(getResolvedRef(schema, mergeSiblingReferences))\n}\n"],"mappings":";;;;AAmBA,IAAaA,KACX,GACA,EAAE,eAAY,kBACF;CACZ,IAAI,CAACC,KAAaC,GAChB,OAAO;CAKT,IAAMC,IAASC,EAAcC,CAAQ,CAAC,EAAE,YAAY,UAAUJ;CAE9D,OAAO,CAACK,EAASC,EAAeJ,GAAQK,CAAsB,CAAC;AACjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"is-on-schema-target-path.js","names":[],"sources":["../../../src/schema/helpers/is-on-schema-target-path.ts"],"sourcesContent":["/** Match complete breadcrumb segments so `user` does not match `username`. */\nexport const isOnSchemaTargetPath = (path: string | undefined, target: string): boolean =>\n Boolean(path && target && (target === path || target.startsWith(`${path}.`)))\n"],"mappings":";AACA,IAAa,KAAwB,GAA0B,MAC7D,GAAQ,KAAQ,MAAW,MAAW,KAAQ,EAAO,WAAW,GAAG,EAAK,EAAE"}
1
+ {"version":3,"file":"is-on-schema-target-path.js","names":["isOnSchemaTargetPath","path","target"],"sources":["../../../src/schema/helpers/is-on-schema-target-path.ts"],"sourcesContent":["/** Match complete breadcrumb segments so `user` does not match `username`. */\nexport const isOnSchemaTargetPath = (path: string | undefined, target: string): boolean =>\n Boolean(path && target && (target === path || target.startsWith(`${path}.`)))\n"],"mappings":";AACA,IAAaA,KAAwB,GAA0B,MAC7D,GAAQC,KAAQC,MAAWA,MAAWD,KAAQC,EAAO,WAAW,GAAGD,EAAK,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"is-type-object.js","names":[],"sources":["../../../src/schema/helpers/is-type-object.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\n/*\n * Checks whether a JSON schema is of type object\n */\nexport const isTypeObject = (schema: unknown): schema is Extract<SchemaObject, { type: 'object' }> => {\n // null, primitive types, arrays\n if (schema === null || typeof schema !== 'object' || Array.isArray(schema)) {\n return false\n }\n\n // Check for composition keywords - if present, this should be handled by composition logic\n const hasComposition = 'oneOf' in schema || 'anyOf' in schema || 'allOf' in schema || 'not' in schema\n\n // If it has composition keywords, it should not be treated as a simple object schema\n if (hasComposition) {\n return false\n }\n\n const hasType = 'type' in schema\n\n // Handle union types (type: ['object', 'null'])\n if (hasType && Array.isArray(schema.type)) {\n return schema.type.includes('object')\n }\n\n const hasTypeObject = hasType && schema.type === 'object'\n\n // type: object\n if (hasTypeObject) {\n return true\n }\n\n // type: string, number, boolean, array, etc.\n if (hasType && !hasTypeObject) {\n return false\n }\n\n const hasProperties = 'properties' in schema\n const hasAdditionalProperties = 'additionalProperties' in schema\n const hasPatternProperties = 'patternProperties' in schema\n\n return hasProperties || hasAdditionalProperties || hasPatternProperties\n}\n"],"mappings":";AAKA,IAAa,KAAgB,MAAyE;CAUpG,IARuB,OAAO,KAAW,aAArC,KAAiD,MAAM,QAAQ,CAAM,KAKlD,WAAW,KAAU,WAAW,KAAU,WAAW,KAAU,SAAS,GAI7F,OAAO;CAGT,IAAM,IAAU,UAAU;CAG1B,IAAI,KAAW,MAAM,QAAQ,EAAO,IAAI,GACtC,OAAO,EAAO,KAAK,SAAS,QAAQ;CAGtC,IAAM,IAAgB,KAAW,EAAO,SAAS;CAGjD,IAAI,GACF,OAAO;CAIT,IAAI,KAAW,CAAC,GACd,OAAO;CAGT,IAAM,IAAgB,gBAAgB,GAChC,IAA0B,0BAA0B,GACpD,IAAuB,uBAAuB;CAEpD,OAAO,KAAiB,KAA2B;AACrD"}
1
+ {"version":3,"file":"is-type-object.js","names":["isTypeObject","schema","hasType","hasTypeObject","hasProperties","hasAdditionalProperties","hasPatternProperties"],"sources":["../../../src/schema/helpers/is-type-object.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\n/*\n * Checks whether a JSON schema is of type object\n */\nexport const isTypeObject = (schema: unknown): schema is Extract<SchemaObject, { type: 'object' }> => {\n // null, primitive types, arrays\n if (schema === null || typeof schema !== 'object' || Array.isArray(schema)) {\n return false\n }\n\n // Check for composition keywords - if present, this should be handled by composition logic\n const hasComposition = 'oneOf' in schema || 'anyOf' in schema || 'allOf' in schema || 'not' in schema\n\n // If it has composition keywords, it should not be treated as a simple object schema\n if (hasComposition) {\n return false\n }\n\n const hasType = 'type' in schema\n\n // Handle union types (type: ['object', 'null'])\n if (hasType && Array.isArray(schema.type)) {\n return schema.type.includes('object')\n }\n\n const hasTypeObject = hasType && schema.type === 'object'\n\n // type: object\n if (hasTypeObject) {\n return true\n }\n\n // type: string, number, boolean, array, etc.\n if (hasType && !hasTypeObject) {\n return false\n }\n\n const hasProperties = 'properties' in schema\n const hasAdditionalProperties = 'additionalProperties' in schema\n const hasPatternProperties = 'patternProperties' in schema\n\n return hasProperties || hasAdditionalProperties || hasPatternProperties\n}\n"],"mappings":";AAKA,IAAaA,KAAgB,MAAyE;CAUpG,IARuB,OAAOC,KAAW,aAArCA,KAAiD,MAAM,QAAQA,CAAM,KAKlD,WAAWA,KAAU,WAAWA,KAAU,WAAWA,KAAU,SAASA,GAI7F,OAAO;CAGT,IAAMC,IAAU,UAAUD;CAG1B,IAAIC,KAAW,MAAM,QAAQD,EAAO,IAAI,GACtC,OAAOA,EAAO,KAAK,SAAS,QAAQ;CAGtC,IAAME,IAAgBD,KAAWD,EAAO,SAAS;CAGjD,IAAIE,GACF,OAAO;CAIT,IAAID,KAAW,CAACC,GACd,OAAO;CAGT,IAAMC,IAAgB,gBAAgBH,GAChCI,IAA0B,0BAA0BJ,GACpDK,IAAuB,uBAAuBL;CAEpD,OAAOG,KAAiBC,KAA2BC;AACrD"}
@@ -24,11 +24,7 @@ var a = /* @__PURE__ */ new Set(["description", "title"]), o = [
24
24
  for (let n of e.allOf) {
25
25
  if (typeof n != "boolean" && (!n || typeof n != "object")) continue;
26
26
  let e = t.schema(n);
27
- if (e.allOf) {
28
- l(i, c(e, void 0, r), !1, r);
29
- continue;
30
- }
31
- l(i, e, !1, r);
27
+ e.allOf ? l(i, c(e, void 0, r), !1, r) : l(i, e, !1, r);
32
28
  }
33
29
  Object.keys(o).length > 0 && l(i, o, !0, r), n && typeof n == "object" && (n.allOf ? l(i, c(n, void 0, r), !0, r) : l(i, n, !0, r));
34
30
  let s = "discriminator" in o || !!(n && typeof n == "object" && "discriminator" in n);
@@ -39,27 +35,32 @@ var a = /* @__PURE__ */ new Set(["description", "title"]), o = [
39
35
  let m = s(r, o, l);
40
36
  for (let i of p) {
41
37
  let s = i, p = e(o[i]);
42
- if (p !== void 0) if (s === "required") Array.isArray(p) && p.length > 0 && (r.required?.length ? r.required = [.../* @__PURE__ */ new Set([...r.required, ...p])] : r.required = p.slice());
43
- else if (s === "properties") p && typeof p == "object" && (r.properties ||= {}, u(r.properties, p, f));
44
- else if (s === "items") {
45
- let i = t.schema(p);
46
- if (i) if (n(o)) if (r.items ||= {}, i.allOf) {
47
- let e = c(i, void 0, f);
48
- Object.assign(r.items, e);
49
- } else d(e(r.items), i, f);
50
- else if (i.allOf) {
51
- let e = c(i, void 0, f);
52
- "properties" in e && ("properties" in r || (r.properties = {}), "properties" in r && u(r.properties, e.properties, f));
53
- } else "items" in r || (r.items = i);
54
- } else if (i === "enum") continue;
55
- else if (i === "oneOf" || i === "anyOf") Array.isArray(p) && p.length > 0 && (l || r[i] === void 0) && (r[i] = p);
56
- else if (i === "allOf") continue;
57
- else (l || a.has(s) || r[i] === void 0) && (r[i] = p);
38
+ if (p !== void 0) {
39
+ if (s === "required") Array.isArray(p) && p.length > 0 && (r.required = r.required?.length ? [.../* @__PURE__ */ new Set([...r.required, ...p])] : p.slice());
40
+ else if (s === "properties") p && typeof p == "object" && (r.properties ||= {}, u(r.properties, p, f));
41
+ else if (s === "items") {
42
+ let i = t.schema(p);
43
+ if (i) {
44
+ if (n(o)) {
45
+ if (r.items ||= {}, i.allOf) {
46
+ let e = c(i, void 0, f);
47
+ Object.assign(r.items, e);
48
+ } else d(e(r.items), i, f);
49
+ } else if (i.allOf) {
50
+ let e = c(i, void 0, f);
51
+ "properties" in e && ("properties" in r || (r.properties = {}), "properties" in r && u(r.properties, e.properties, f));
52
+ } else "items" in r || (r.items = i);
53
+ }
54
+ } else if (i === "enum") continue;
55
+ else if (i === "oneOf" || i === "anyOf") Array.isArray(p) && p.length > 0 && (l || r[i] === void 0) && (r[i] = p);
56
+ else if (i === "allOf") continue;
57
+ else (l || a.has(s) || r[i] === void 0) && (r[i] = p);
58
+ }
58
59
  }
59
60
  Object.assign(r, m);
60
61
  }, u = (e, r, i = /* @__PURE__ */ new Set()) => {
61
62
  let a = Object.keys(r ?? {});
62
- if (!(!r || !e || a.length === 0)) for (let o of a) {
63
+ if (r && e && a.length !== 0) for (let o of a) {
63
64
  let a = t.schema(r[o]);
64
65
  if (!a) {
65
66
  delete e[o];
@@ -117,9 +118,7 @@ var a = /* @__PURE__ */ new Set(["description", "title"]), o = [
117
118
  else i.push(n);
118
119
  let a = c({ allOf: i }, void 0, r);
119
120
  Object.assign(e, a);
120
- return;
121
- }
122
- Object.assign(e, n), "properties" in e && "properties" in n && u(e.properties, n.properties, r);
121
+ } else Object.assign(e, n), "properties" in e && "properties" in n && u(e.properties, n.properties, r);
123
122
  }, f = (e, t, n = /* @__PURE__ */ new Set()) => {
124
123
  let r = t.$ref;
125
124
  return typeof r == "string" ? n.has(r) ? e : p(e, t, new Set(n).add(r)) : p(e, t, n);
@@ -1 +1 @@
1
- {"version":3,"file":"merge-all-of-schemas.js","names":[],"sources":["../../../src/schema/helpers/merge-all-of-schemas.ts"],"sourcesContent":["import { isObjectEqual } from '@scalar/helpers/object/is-object-equal'\nimport { objectKeys } from '@scalar/helpers/object/object-keys'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards'\n\n/**\n * Schema keywords whose value should reflect the *last* occurrence when merging\n * `allOf` members. Most keywords keep the first occurrence, but for human-facing\n * annotations a later subschema is expected to override an earlier one — matching\n * OpenAPI/JSON Schema tooling like Swagger UI.\n */\nconst LAST_WINS_KEYS = new Set<string>(['description', 'title'])\n\nconst ENUM_ANNOTATIONS = ['x-enum-varnames', 'x-enumNames', 'x-enum-descriptions', 'x-enumDescriptions'] as const\n\n/** Keep positional annotations attached to their values when intersecting enum constraints. */\nconst mergeEnums = (\n existing: SchemaObject,\n incoming: SchemaObject,\n override: boolean = false,\n): Partial<SchemaObject> => {\n const values =\n existing.enum?.filter(\n (value) => incoming.enum === undefined || incoming.enum.some((candidate) => isObjectEqual(value, candidate)),\n ) ?? incoming.enum?.slice()\n\n if (values === undefined) {\n return {}\n }\n\n const merged: Partial<SchemaObject> = { enum: values }\n for (const key of ENUM_ANNOTATIONS) {\n const source = incoming[key] !== undefined && (override || existing[key] === undefined) ? incoming : existing\n const annotation = source[key]\n const sourceValues = source.enum\n if (Array.isArray(annotation)) {\n merged[key] =\n sourceValues === undefined\n ? annotation\n : values.map(\n (value) => annotation[sourceValues.findIndex((candidate) => isObjectEqual(value, candidate))] ?? '',\n )\n } else if (annotation !== undefined && (key === 'x-enum-descriptions' || key === 'x-enumDescriptions')) {\n merged[key] = annotation\n }\n }\n return merged\n}\n\n/**\n * Merges multiple OpenAPI schema objects into a single schema object.\n * Handles nested allOf compositions and merges properties recursively.\n *\n * @param schemas - Array of OpenAPI schema objects to merge\n * @param rootSchema - Optional root schema to merge with the result\n * @param seenRefs - `$ref` strings already being merged higher in the call stack\n * @returns Merged schema object\n */\nexport const mergeAllOfSchemas = (\n schemas: SchemaObject | undefined,\n rootSchema?: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n // Handle max depth, empty or invalid input\n if (!schemas?.allOf?.length || !Array.isArray(schemas.allOf)) {\n return rootSchema || ({} as SchemaObject)\n }\n\n // Initialize result object once\n const result = {} as SchemaObject\n\n // Extract base schema properties (everything except allOf)\n const { allOf: _, ...baseSchema } = schemas\n\n // Process allOf schemas first\n for (const _schema of schemas.allOf) {\n if (typeof _schema !== 'boolean' && (!_schema || typeof _schema !== 'object')) {\n continue\n }\n\n // Resolve ref if present\n const schema = resolve.schema(_schema)\n\n // Handle nested allOf recursively\n if (schema.allOf) {\n const nestedMerged = mergeAllOfSchemas(schema, undefined, seenRefs)\n mergeSchemaIntoResult(result, nestedMerged, false, seenRefs)\n continue\n }\n\n mergeSchemaIntoResult(result, schema, false, seenRefs)\n }\n\n // Apply base schema properties with precedence over allOf properties\n if (Object.keys(baseSchema).length > 0) {\n mergeSchemaIntoResult(result, baseSchema, true, seenRefs)\n }\n\n // Process root schema last if provided\n if (rootSchema && typeof rootSchema === 'object') {\n if (rootSchema.allOf) {\n const nestedMerged = mergeAllOfSchemas(rootSchema, undefined, seenRefs)\n mergeSchemaIntoResult(result, nestedMerged, true, seenRefs)\n } else {\n mergeSchemaIntoResult(result, rootSchema, true, seenRefs)\n }\n }\n\n // Drop a `discriminator` inherited from an `allOf` member: a merged subtype is\n // one concrete branch, not a choice-point, and keeping the base's mapping makes\n // it look like the base again, recursing the selector inference (issue #9674).\n // A discriminator the schema declares itself is kept.\n const declaresOwnDiscriminator =\n 'discriminator' in baseSchema ||\n Boolean(rootSchema && typeof rootSchema === 'object' && 'discriminator' in rootSchema)\n\n if ('discriminator' in result && !declaresOwnDiscriminator) {\n delete (result as Record<string, unknown>).discriminator\n }\n\n return result\n}\n\n/**\n * Efficiently merges a source schema into a target result object.\n * Handles all schema merging logic in a single optimized function.\n *\n * @param result - The target schema object to merge into\n * @param schema - The source schema object to merge from\n * @param override - Whether to override existing properties (default: false)\n */\nconst mergeSchemaIntoResult = (\n result: SchemaObject,\n schema: SchemaObject,\n override: boolean = false,\n seenRefs: Set<string> = new Set(),\n): void => {\n // Early return if schema is empty\n const schemaKeys = objectKeys(schema)\n if (schemaKeys.length === 0) {\n return\n }\n\n const mergedEnums = mergeEnums(result, schema, override)\n\n // Loop through all schema properties and handle them appropriately\n for (const key of schemaKeys) {\n const propertyName: string = key\n const value = getResolvedRef(schema[key]) as any\n\n if (value === undefined) {\n continue\n }\n\n // Required\n if (propertyName === 'required') {\n // Merge required fields with deduplication\n if (Array.isArray(value) && value.length > 0) {\n // @ts-expect-error\n if (result.required?.length) {\n // @ts-expect-error\n result.required = [...new Set([...result.required, ...value])]\n } else {\n // @ts-expect-error\n result.required = value.slice()\n }\n }\n }\n // Properties\n else if (propertyName === 'properties') {\n // Merge properties recursively\n if (value && typeof value === 'object') {\n // @ts-expect-error\n if (!result.properties) {\n // @ts-expect-error\n result.properties = {}\n }\n\n // @ts-expect-error\n mergePropertiesIntoResult(result.properties, value, seenRefs)\n }\n }\n // Items\n else if (propertyName === 'items') {\n // Handle items (for both arrays and objects with items)\n const items = resolve.schema(value)\n if (items) {\n if (isArraySchema(schema)) {\n // @ts-expect-error\n if (!result.items) {\n // @ts-expect-error\n result.items = {}\n }\n\n // Handle allOf within array items\n if (items.allOf) {\n const mergedItems = mergeAllOfSchemas(items, undefined, seenRefs)\n // @ts-expect-error\n Object.assign(result.items, mergedItems)\n } else {\n // @ts-expect-error\n mergeItemsIntoResult(getResolvedRef(result.items), items, seenRefs)\n }\n }\n // For non-array types with items.allOf, merge into properties\n else if (items.allOf) {\n const mergedItems = mergeAllOfSchemas(items, undefined, seenRefs)\n if ('properties' in mergedItems) {\n if (!('properties' in result)) {\n // @ts-expect-error\n result.properties = {}\n }\n\n 'properties' in result && mergePropertiesIntoResult(result.properties, mergedItems.properties, seenRefs)\n }\n }\n // For non-array types without allOf, still set items if not already set\n else if (!('items' in result)) {\n // @ts-expect-error\n result.items = items\n }\n }\n }\n // Enum values and their annotations are applied together after the other keywords.\n else if (key === 'enum') {\n continue\n }\n // OneOf/AnyOf\n else if (key === 'oneOf' || key === 'anyOf') {\n // Preserve the composition itself so its variants keep rendering as a\n // selector. Flattening the option properties into the parent would drop\n // the variant structure entirely and silently lose branches that have no\n // top-level `properties` (for example branches that are themselves an\n // `allOf`). The sibling `allOf` members stay on `result` as base\n // properties, which the Schema component renders above the selector.\n if (Array.isArray(value) && value.length > 0 && (override || result[key] === undefined)) {\n result[key] = value\n }\n }\n // Skip allOf as it's handled at a higher level\n else if (key === 'allOf') {\n continue\n }\n // For all other properties, preserve the first occurrence or override if specified.\n // Annotation keywords (see LAST_WINS_KEYS) always take the latest value so a later\n // allOf member can override an earlier one.\n else {\n if (override || LAST_WINS_KEYS.has(propertyName) || result[key] === undefined) {\n result[key] = value\n }\n }\n }\n Object.assign(result, mergedEnums)\n}\n\n/**\n * Efficiently merges properties into a result object without creating new objects.\n */\nconst mergePropertiesIntoResult = (\n result: Extract<SchemaObject, { type: 'object' }>['properties'],\n properties: Extract<SchemaObject, { type: 'object' }>['properties'],\n seenRefs: Set<string> = new Set(),\n): void => {\n const propertyKeys = Object.keys(properties ?? {})\n if (!properties || !result || propertyKeys.length === 0) {\n return\n }\n\n for (const key of propertyKeys) {\n const schema = resolve.schema(properties[key])\n if (!schema) {\n delete result[key]\n continue\n }\n\n if (typeof schema !== 'object') {\n result[key] = schema\n continue\n }\n\n if (!result[key]) {\n // Break self-referential cycles reached through `allOf`. When a brand-new\n // property's `$ref` is already being merged higher in the call stack,\n // keep the raw reference instead of recursing into its `allOf` forever.\n // This mirrors the guard in the \"merge existing property\" branch below and\n // covers schemas that point back at themselves through an `allOf` member\n // (e.g. a node whose `self` property $refs the node, which is an allOf).\n const rawProperty = properties[key]\n const newSchemaRef = (rawProperty as { $ref?: string })?.$ref\n if (rawProperty && typeof newSchemaRef === 'string' && seenRefs.has(newSchemaRef)) {\n result[key] = rawProperty\n continue\n }\n const nextNewSeenRefs = typeof newSchemaRef === 'string' ? new Set(seenRefs).add(newSchemaRef) : seenRefs\n\n // Handle new property with allOf\n if (schema.allOf) {\n result[key] = mergeAllOfSchemas(schema, undefined, nextNewSeenRefs)\n } else if (isArraySchema(schema) && resolve.schema(schema.items)?.allOf) {\n result[key] = {\n ...schema,\n items: mergeAllOfSchemas(resolve.schema(schema.items), undefined, seenRefs),\n }\n } else if (properties[key]) {\n result[key] = properties[key]\n }\n continue\n }\n\n // Merge existing property\n const existing = resolve.schema(result[key])\n\n // Break self-referential cycles: when this property's `$ref` is already\n // being merged higher in the call stack, keep the partially merged existing\n // schema instead of recursing into it again. This mirrors the guard in\n // `mergeItems` and covers schemas that point back at themselves through a\n // plain object property (e.g. a tree node whose `parent` $refs the node).\n const schemaRef = schema.$ref\n if (typeof schemaRef === 'string' && seenRefs.has(schemaRef)) {\n result[key] = existing\n continue\n }\n const nextSeenRefs = typeof schemaRef === 'string' ? new Set(seenRefs).add(schemaRef) : seenRefs\n\n if (schema.allOf) {\n result[key] = mergeAllOfSchemas({ allOf: [existing, schema] } as SchemaObject, undefined, nextSeenRefs)\n } else if (isArraySchema(schema) && isArraySchema(existing) && schema.items) {\n const existingItems = resolve.schema(existing.items)\n result[key] = {\n ...existing,\n type: 'array',\n items: existingItems\n ? mergeItems(existingItems, resolve.schema(schema.items), nextSeenRefs)\n : resolve.schema(schema.items),\n }\n } else {\n // Create merged object with properties handled separately\n if ('properties' in existing && 'properties' in schema) {\n const merged = { ...existing, ...schema }\n merged.properties = { ...existing.properties }\n mergePropertiesIntoResult(merged.properties, schema.properties, nextSeenRefs)\n result[key] = merged\n }\n // Simple merge without property recursion\n else {\n result[key] = {\n ...schema,\n ...existing,\n ...mergeEnums(existing, schema),\n }\n }\n }\n }\n}\n\n/**\n * Efficiently merges array items into a result object.\n */\nconst mergeItemsIntoResult = (result: SchemaObject, items: SchemaObject, seenRefs: Set<string> = new Set()): void => {\n // Handle allOf in items\n if (items.allOf || result.allOf) {\n // Build array without spreads for better performance\n const allOfSchemas: SchemaObject[] = []\n\n if (result.allOf) {\n for (const schema of result.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(result)\n }\n\n if (items.allOf) {\n for (const schema of items.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(items)\n }\n\n const merged = mergeAllOfSchemas({ allOf: allOfSchemas } as SchemaObject, undefined, seenRefs)\n Object.assign(result, merged)\n return\n }\n\n // Regular merge\n Object.assign(result, items)\n\n // Merge properties if both have them\n if ('properties' in result && 'properties' in items) {\n mergePropertiesIntoResult(result.properties, items.properties, seenRefs)\n }\n}\n\n/**\n * Helper function for merging items that returns a new object.\n */\nconst mergeItems = (\n existing: SchemaObject,\n incoming: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n const incomingRef = (incoming as { $ref?: string }).$ref\n\n if (typeof incomingRef === 'string') {\n if (seenRefs.has(incomingRef)) {\n return existing\n }\n return mergeItemsInner(existing, incoming, new Set(seenRefs).add(incomingRef))\n }\n\n return mergeItemsInner(existing, incoming, seenRefs)\n}\n\nconst mergeItemsInner = (\n existing: SchemaObject,\n incoming: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n // Handle allOf in either schema\n if (existing.allOf || incoming.allOf) {\n // Build array without spreads for better performance\n const allOfSchemas: SchemaObject[] = []\n\n if (existing.allOf) {\n for (const schema of existing.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(existing)\n }\n\n if (incoming.allOf) {\n for (const schema of incoming.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(incoming)\n }\n\n return mergeAllOfSchemas({ allOf: allOfSchemas } as SchemaObject, undefined, seenRefs)\n }\n\n // Construct the merged object after narrowing both schemas so their property types survive.\n if ('properties' in existing && 'properties' in incoming) {\n const merged = { ...existing, ...incoming, properties: { ...existing.properties } }\n mergePropertiesIntoResult(merged.properties, incoming.properties, seenRefs)\n return merged\n }\n\n return { ...existing, ...incoming }\n}\n"],"mappings":";;;;;;AAaA,IAAM,oBAAiB,IAAI,IAAY,CAAC,eAAe,OAAO,CAAC,GAEzD,IAAmB;CAAC;CAAmB;CAAe;CAAuB;AAAoB,GAGjG,KACJ,GACA,GACA,IAAoB,OACM;CAC1B,IAAM,IACJ,EAAS,MAAM,QACZ,MAAU,EAAS,SAAS,KAAA,KAAa,EAAS,KAAK,MAAM,MAAc,EAAc,GAAO,CAAS,CAAC,CAC7G,KAAK,EAAS,MAAM,MAAM;CAE5B,IAAI,MAAW,KAAA,GACb,OAAO,CAAC;CAGV,IAAM,IAAgC,EAAE,MAAM,EAAO;CACrD,KAAK,IAAM,KAAO,GAAkB;EAClC,IAAM,IAAS,EAAS,OAAS,KAAA,MAAc,KAAY,EAAS,OAAS,KAAA,KAAa,IAAW,GAC/F,IAAa,EAAO,IACpB,IAAe,EAAO;EAC5B,AAAI,MAAM,QAAQ,CAAU,IAC1B,EAAO,KACL,MAAiB,KAAA,IACb,IACA,EAAO,KACJ,MAAU,EAAW,EAAa,WAAW,MAAc,EAAc,GAAO,CAAS,CAAC,MAAM,EACnG,IACG,MAAe,KAAA,MAAc,MAAQ,yBAAyB,MAAQ,0BAC/E,EAAO,KAAO;CAElB;CACA,OAAO;AACT,GAWa,KACX,GACA,GACA,oBAAwB,IAAI,IAAI,MACf;CAEjB,IAAI,CAAC,GAAS,OAAO,UAAU,CAAC,MAAM,QAAQ,EAAQ,KAAK,GACzD,OAAO,KAAe,CAAC;CAIzB,IAAM,IAAS,CAAC,GAGV,EAAE,OAAO,GAAG,GAAG,MAAe;CAGpC,KAAK,IAAM,KAAW,EAAQ,OAAO;EACnC,IAAI,OAAO,KAAY,cAAc,CAAC,KAAW,OAAO,KAAY,WAClE;EAIF,IAAM,IAAS,EAAQ,OAAO,CAAO;EAGrC,IAAI,EAAO,OAAO;GAEhB,EAAsB,GADD,EAAkB,GAAQ,KAAA,GAAW,CAC5B,GAAc,IAAO,CAAQ;GAC3D;EACF;EAEA,EAAsB,GAAQ,GAAQ,IAAO,CAAQ;CACvD;CAQA,AALI,OAAO,KAAK,CAAU,CAAC,CAAC,SAAS,KACnC,EAAsB,GAAQ,GAAY,IAAM,CAAQ,GAItD,KAAc,OAAO,KAAe,aAClC,EAAW,QAEb,EAAsB,GADD,EAAkB,GAAY,KAAA,GAAW,CAChC,GAAc,IAAM,CAAQ,IAE1D,EAAsB,GAAQ,GAAY,IAAM,CAAQ;CAQ5D,IAAM,IACJ,mBAAmB,KACnB,GAAQ,KAAc,OAAO,KAAe,YAAY,mBAAmB;CAM7E,OAJI,mBAAmB,KAAU,CAAC,KAChC,OAAQ,EAAmC,eAGtC;AACT,GAUM,KACJ,GACA,GACA,IAAoB,IACpB,oBAAwB,IAAI,IAAI,MACvB;CAET,IAAM,IAAa,EAAW,CAAM;CACpC,IAAI,EAAW,WAAW,GACxB;CAGF,IAAM,IAAc,EAAW,GAAQ,GAAQ,CAAQ;CAGvD,KAAK,IAAM,KAAO,GAAY;EAC5B,IAAM,IAAuB,GACvB,IAAQ,EAAe,EAAO,EAAI;EAEpC,UAAU,KAAA,GAKd,IAAI,MAAiB,YAEf,MAAM,QAAQ,CAAK,KAAK,EAAM,SAAS,MAErC,EAAO,UAAU,SAEnB,EAAO,WAAW,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,EAAO,UAAU,GAAG,CAAK,CAAC,CAAC,IAG7D,EAAO,WAAW,EAAM,MAAM;OAK/B,IAAI,MAAiB,cAEpB,KAAS,OAAO,KAAU,aAE5B,AAEE,EAAO,eAAa,CAAC,GAIvB,EAA0B,EAAO,YAAY,GAAO,CAAQ;OAI3D,IAAI,MAAiB,SAAS;GAEjC,IAAM,IAAQ,EAAQ,OAAO,CAAK;GAClC,IAAI,OACE,EAAc,CAAM,GAQtB,IANA,AAEE,EAAO,UAAQ,CAAC,GAId,EAAM,OAAO;IACf,IAAM,IAAc,EAAkB,GAAO,KAAA,GAAW,CAAQ;IAEhE,OAAO,OAAO,EAAO,OAAO,CAAW;GACzC,OAEE,EAAqB,EAAe,EAAO,KAAK,GAAG,GAAO,CAAQ;QAIjE,IAAI,EAAM,OAAO;IACpB,IAAM,IAAc,EAAkB,GAAO,KAAA,GAAW,CAAQ;IAChE,AAAI,gBAAgB,MACZ,gBAAgB,MAEpB,EAAO,aAAa,CAAC,IAGvB,gBAAgB,KAAU,EAA0B,EAAO,YAAY,EAAY,YAAY,CAAQ;GAE3G,OAEK,AAAM,WAAW,MAEpB,EAAO,QAAQ;EAGrB,OAEK,IAAI,MAAQ,QACf;OAGG,IAAI,MAAQ,WAAW,MAAQ,SAO9B,MAAM,QAAQ,CAAK,KAAK,EAAM,SAAS,MAAM,KAAY,EAAO,OAAS,KAAA,OAC3E,EAAO,KAAO;OAIb,IAAI,MAAQ,SACf;OAMA,CAAI,KAAY,EAAe,IAAI,CAAY,KAAK,EAAO,OAAS,KAAA,OAClE,EAAO,KAAO;CAGpB;CACA,OAAO,OAAO,GAAQ,CAAW;AACnC,GAKM,KACJ,GACA,GACA,oBAAwB,IAAI,IAAI,MACvB;CACT,IAAM,IAAe,OAAO,KAAK,KAAc,CAAC,CAAC;CAC7C,OAAC,KAAc,CAAC,KAAU,EAAa,WAAW,IAItD,KAAK,IAAM,KAAO,GAAc;EAC9B,IAAM,IAAS,EAAQ,OAAO,EAAW,EAAI;EAC7C,IAAI,CAAC,GAAQ;GACX,OAAO,EAAO;GACd;EACF;EAEA,IAAI,OAAO,KAAW,UAAU;GAC9B,EAAO,KAAO;GACd;EACF;EAEA,IAAI,CAAC,EAAO,IAAM;GAOhB,IAAM,IAAc,EAAW,IACzB,IAAgB,GAAmC;GACzD,IAAI,KAAe,OAAO,KAAiB,YAAY,EAAS,IAAI,CAAY,GAAG;IACjF,EAAO,KAAO;IACd;GACF;GACA,IAAM,IAAkB,OAAO,KAAiB,WAAW,IAAI,IAAI,CAAQ,CAAC,CAAC,IAAI,CAAY,IAAI;GAGjG,AAAI,EAAO,QACT,EAAO,KAAO,EAAkB,GAAQ,KAAA,GAAW,CAAe,IACzD,EAAc,CAAM,KAAK,EAAQ,OAAO,EAAO,KAAK,CAAC,EAAE,QAChE,EAAO,KAAO;IACZ,GAAG;IACH,OAAO,EAAkB,EAAQ,OAAO,EAAO,KAAK,GAAG,KAAA,GAAW,CAAQ;GAC5E,IACS,EAAW,OACpB,EAAO,KAAO,EAAW;GAE3B;EACF;EAGA,IAAM,IAAW,EAAQ,OAAO,EAAO,EAAI,GAOrC,IAAY,EAAO;EACzB,IAAI,OAAO,KAAc,YAAY,EAAS,IAAI,CAAS,GAAG;GAC5D,EAAO,KAAO;GACd;EACF;EACA,IAAM,IAAe,OAAO,KAAc,WAAW,IAAI,IAAI,CAAQ,CAAC,CAAC,IAAI,CAAS,IAAI;EAExF,IAAI,EAAO,OACT,EAAO,KAAO,EAAkB,EAAE,OAAO,CAAC,GAAU,CAAM,EAAE,GAAmB,KAAA,GAAW,CAAY;OACjG,IAAI,EAAc,CAAM,KAAK,EAAc,CAAQ,KAAK,EAAO,OAAO;GAC3E,IAAM,IAAgB,EAAQ,OAAO,EAAS,KAAK;GACnD,EAAO,KAAO;IACZ,GAAG;IACH,MAAM;IACN,OAAO,IACH,EAAW,GAAe,EAAQ,OAAO,EAAO,KAAK,GAAG,CAAY,IACpE,EAAQ,OAAO,EAAO,KAAK;GACjC;EACF,OAEE,IAAI,gBAAgB,KAAY,gBAAgB,GAAQ;GACtD,IAAM,IAAS;IAAE,GAAG;IAAU,GAAG;GAAO;GAGxC,AAFA,EAAO,aAAa,EAAE,GAAG,EAAS,WAAW,GAC7C,EAA0B,EAAO,YAAY,EAAO,YAAY,CAAY,GAC5E,EAAO,KAAO;EAChB,OAGE,EAAO,KAAO;GACZ,GAAG;GACH,GAAG;GACH,GAAG,EAAW,GAAU,CAAM;EAChC;CAGN;AACF,GAKM,KAAwB,GAAsB,GAAqB,oBAAwB,IAAI,IAAI,MAAY;CAEnH,IAAI,EAAM,SAAS,EAAO,OAAO;EAE/B,IAAM,IAA+B,CAAC;EAEtC,IAAI,EAAO,OACT,KAAK,IAAM,KAAU,EAAO,OAC1B,EAAa,KAAK,EAAQ,OAAO,CAAM,CAAC;OAG1C,EAAa,KAAK,CAAM;EAG1B,IAAI,EAAM,OACR,KAAK,IAAM,KAAU,EAAM,OACzB,EAAa,KAAK,EAAQ,OAAO,CAAM,CAAC;OAG1C,EAAa,KAAK,CAAK;EAGzB,IAAM,IAAS,EAAkB,EAAE,OAAO,EAAa,GAAmB,KAAA,GAAW,CAAQ;EAC7F,OAAO,OAAO,GAAQ,CAAM;EAC5B;CACF;CAMA,AAHA,OAAO,OAAO,GAAQ,CAAK,GAGvB,gBAAgB,KAAU,gBAAgB,KAC5C,EAA0B,EAAO,YAAY,EAAM,YAAY,CAAQ;AAE3E,GAKM,KACJ,GACA,GACA,oBAAwB,IAAI,IAAI,MACf;CACjB,IAAM,IAAe,EAA+B;CASpD,OAPI,OAAO,KAAgB,WACrB,EAAS,IAAI,CAAW,IACnB,IAEF,EAAgB,GAAU,GAAU,IAAI,IAAI,CAAQ,CAAC,CAAC,IAAI,CAAW,CAAC,IAGxE,EAAgB,GAAU,GAAU,CAAQ;AACrD,GAEM,KACJ,GACA,GACA,oBAAwB,IAAI,IAAI,MACf;CAEjB,IAAI,EAAS,SAAS,EAAS,OAAO;EAEpC,IAAM,IAA+B,CAAC;EAEtC,IAAI,EAAS,OACX,KAAK,IAAM,KAAU,EAAS,OAC5B,EAAa,KAAK,EAAQ,OAAO,CAAM,CAAC;OAG1C,EAAa,KAAK,CAAQ;EAG5B,IAAI,EAAS,OACX,KAAK,IAAM,KAAU,EAAS,OAC5B,EAAa,KAAK,EAAQ,OAAO,CAAM,CAAC;OAG1C,EAAa,KAAK,CAAQ;EAG5B,OAAO,EAAkB,EAAE,OAAO,EAAa,GAAmB,KAAA,GAAW,CAAQ;CACvF;CAGA,IAAI,gBAAgB,KAAY,gBAAgB,GAAU;EACxD,IAAM,IAAS;GAAE,GAAG;GAAU,GAAG;GAAU,YAAY,EAAE,GAAG,EAAS,WAAW;EAAE;EAElF,OADA,EAA0B,EAAO,YAAY,EAAS,YAAY,CAAQ,GACnE;CACT;CAEA,OAAO;EAAE,GAAG;EAAU,GAAG;CAAS;AACpC"}
1
+ {"version":3,"file":"merge-all-of-schemas.js","names":["LAST_WINS_KEYS","ENUM_ANNOTATIONS","mergeEnums","values","existing","incoming","isObjectEqual","value","candidate","merged","key","source","override","annotation","sourceValues","mergeAllOfSchemas","schemas","rootSchema","result","_","baseSchema","_schema","schema","resolve","mergeSchemaIntoResult","seenRefs","declaresOwnDiscriminator","schemaKeys","objectKeys","mergedEnums","propertyName","getResolvedRef","mergePropertiesIntoResult","items","isArraySchema","mergedItems","propertyKeys","properties","rawProperty","newSchemaRef","nextNewSeenRefs","schemaRef","nextSeenRefs","existingItems","mergeItems","mergeItemsIntoResult","allOfSchemas","incomingRef","mergeItemsInner"],"sources":["../../../src/schema/helpers/merge-all-of-schemas.ts"],"sourcesContent":["import { isObjectEqual } from '@scalar/helpers/object/is-object-equal'\nimport { objectKeys } from '@scalar/helpers/object/object-keys'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards'\n\n/**\n * Schema keywords whose value should reflect the *last* occurrence when merging\n * `allOf` members. Most keywords keep the first occurrence, but for human-facing\n * annotations a later subschema is expected to override an earlier one — matching\n * OpenAPI/JSON Schema tooling like Swagger UI.\n */\nconst LAST_WINS_KEYS = new Set<string>(['description', 'title'])\n\nconst ENUM_ANNOTATIONS = ['x-enum-varnames', 'x-enumNames', 'x-enum-descriptions', 'x-enumDescriptions'] as const\n\n/** Keep positional annotations attached to their values when intersecting enum constraints. */\nconst mergeEnums = (\n existing: SchemaObject,\n incoming: SchemaObject,\n override: boolean = false,\n): Partial<SchemaObject> => {\n const values =\n existing.enum?.filter(\n (value) => incoming.enum === undefined || incoming.enum.some((candidate) => isObjectEqual(value, candidate)),\n ) ?? incoming.enum?.slice()\n\n if (values === undefined) {\n return {}\n }\n\n const merged: Partial<SchemaObject> = { enum: values }\n for (const key of ENUM_ANNOTATIONS) {\n const source = incoming[key] !== undefined && (override || existing[key] === undefined) ? incoming : existing\n const annotation = source[key]\n const sourceValues = source.enum\n if (Array.isArray(annotation)) {\n merged[key] =\n sourceValues === undefined\n ? annotation\n : values.map(\n (value) => annotation[sourceValues.findIndex((candidate) => isObjectEqual(value, candidate))] ?? '',\n )\n } else if (annotation !== undefined && (key === 'x-enum-descriptions' || key === 'x-enumDescriptions')) {\n merged[key] = annotation\n }\n }\n return merged\n}\n\n/**\n * Merges multiple OpenAPI schema objects into a single schema object.\n * Handles nested allOf compositions and merges properties recursively.\n *\n * @param schemas - Array of OpenAPI schema objects to merge\n * @param rootSchema - Optional root schema to merge with the result\n * @param seenRefs - `$ref` strings already being merged higher in the call stack\n * @returns Merged schema object\n */\nexport const mergeAllOfSchemas = (\n schemas: SchemaObject | undefined,\n rootSchema?: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n // Handle max depth, empty or invalid input\n if (!schemas?.allOf?.length || !Array.isArray(schemas.allOf)) {\n return rootSchema || ({} as SchemaObject)\n }\n\n // Initialize result object once\n const result = {} as SchemaObject\n\n // Extract base schema properties (everything except allOf)\n const { allOf: _, ...baseSchema } = schemas\n\n // Process allOf schemas first\n for (const _schema of schemas.allOf) {\n if (typeof _schema !== 'boolean' && (!_schema || typeof _schema !== 'object')) {\n continue\n }\n\n // Resolve ref if present\n const schema = resolve.schema(_schema)\n\n // Handle nested allOf recursively\n if (schema.allOf) {\n const nestedMerged = mergeAllOfSchemas(schema, undefined, seenRefs)\n mergeSchemaIntoResult(result, nestedMerged, false, seenRefs)\n continue\n }\n\n mergeSchemaIntoResult(result, schema, false, seenRefs)\n }\n\n // Apply base schema properties with precedence over allOf properties\n if (Object.keys(baseSchema).length > 0) {\n mergeSchemaIntoResult(result, baseSchema, true, seenRefs)\n }\n\n // Process root schema last if provided\n if (rootSchema && typeof rootSchema === 'object') {\n if (rootSchema.allOf) {\n const nestedMerged = mergeAllOfSchemas(rootSchema, undefined, seenRefs)\n mergeSchemaIntoResult(result, nestedMerged, true, seenRefs)\n } else {\n mergeSchemaIntoResult(result, rootSchema, true, seenRefs)\n }\n }\n\n // Drop a `discriminator` inherited from an `allOf` member: a merged subtype is\n // one concrete branch, not a choice-point, and keeping the base's mapping makes\n // it look like the base again, recursing the selector inference (issue #9674).\n // A discriminator the schema declares itself is kept.\n const declaresOwnDiscriminator =\n 'discriminator' in baseSchema ||\n Boolean(rootSchema && typeof rootSchema === 'object' && 'discriminator' in rootSchema)\n\n if ('discriminator' in result && !declaresOwnDiscriminator) {\n delete (result as Record<string, unknown>).discriminator\n }\n\n return result\n}\n\n/**\n * Efficiently merges a source schema into a target result object.\n * Handles all schema merging logic in a single optimized function.\n *\n * @param result - The target schema object to merge into\n * @param schema - The source schema object to merge from\n * @param override - Whether to override existing properties (default: false)\n */\nconst mergeSchemaIntoResult = (\n result: SchemaObject,\n schema: SchemaObject,\n override: boolean = false,\n seenRefs: Set<string> = new Set(),\n): void => {\n // Early return if schema is empty\n const schemaKeys = objectKeys(schema)\n if (schemaKeys.length === 0) {\n return\n }\n\n const mergedEnums = mergeEnums(result, schema, override)\n\n // Loop through all schema properties and handle them appropriately\n for (const key of schemaKeys) {\n const propertyName: string = key\n const value = getResolvedRef(schema[key]) as any\n\n if (value === undefined) {\n continue\n }\n\n // Required\n if (propertyName === 'required') {\n // Merge required fields with deduplication\n if (Array.isArray(value) && value.length > 0) {\n // @ts-expect-error\n if (result.required?.length) {\n // @ts-expect-error\n result.required = [...new Set([...result.required, ...value])]\n } else {\n // @ts-expect-error\n result.required = value.slice()\n }\n }\n }\n // Properties\n else if (propertyName === 'properties') {\n // Merge properties recursively\n if (value && typeof value === 'object') {\n // @ts-expect-error\n if (!result.properties) {\n // @ts-expect-error\n result.properties = {}\n }\n\n // @ts-expect-error\n mergePropertiesIntoResult(result.properties, value, seenRefs)\n }\n }\n // Items\n else if (propertyName === 'items') {\n // Handle items (for both arrays and objects with items)\n const items = resolve.schema(value)\n if (items) {\n if (isArraySchema(schema)) {\n // @ts-expect-error\n if (!result.items) {\n // @ts-expect-error\n result.items = {}\n }\n\n // Handle allOf within array items\n if (items.allOf) {\n const mergedItems = mergeAllOfSchemas(items, undefined, seenRefs)\n // @ts-expect-error\n Object.assign(result.items, mergedItems)\n } else {\n // @ts-expect-error\n mergeItemsIntoResult(getResolvedRef(result.items), items, seenRefs)\n }\n }\n // For non-array types with items.allOf, merge into properties\n else if (items.allOf) {\n const mergedItems = mergeAllOfSchemas(items, undefined, seenRefs)\n if ('properties' in mergedItems) {\n if (!('properties' in result)) {\n // @ts-expect-error\n result.properties = {}\n }\n\n 'properties' in result && mergePropertiesIntoResult(result.properties, mergedItems.properties, seenRefs)\n }\n }\n // For non-array types without allOf, still set items if not already set\n else if (!('items' in result)) {\n // @ts-expect-error\n result.items = items\n }\n }\n }\n // Enum values and their annotations are applied together after the other keywords.\n else if (key === 'enum') {\n continue\n }\n // OneOf/AnyOf\n else if (key === 'oneOf' || key === 'anyOf') {\n // Preserve the composition itself so its variants keep rendering as a\n // selector. Flattening the option properties into the parent would drop\n // the variant structure entirely and silently lose branches that have no\n // top-level `properties` (for example branches that are themselves an\n // `allOf`). The sibling `allOf` members stay on `result` as base\n // properties, which the Schema component renders above the selector.\n if (Array.isArray(value) && value.length > 0 && (override || result[key] === undefined)) {\n result[key] = value\n }\n }\n // Skip allOf as it's handled at a higher level\n else if (key === 'allOf') {\n continue\n }\n // For all other properties, preserve the first occurrence or override if specified.\n // Annotation keywords (see LAST_WINS_KEYS) always take the latest value so a later\n // allOf member can override an earlier one.\n else {\n if (override || LAST_WINS_KEYS.has(propertyName) || result[key] === undefined) {\n result[key] = value\n }\n }\n }\n Object.assign(result, mergedEnums)\n}\n\n/**\n * Efficiently merges properties into a result object without creating new objects.\n */\nconst mergePropertiesIntoResult = (\n result: Extract<SchemaObject, { type: 'object' }>['properties'],\n properties: Extract<SchemaObject, { type: 'object' }>['properties'],\n seenRefs: Set<string> = new Set(),\n): void => {\n const propertyKeys = Object.keys(properties ?? {})\n if (!properties || !result || propertyKeys.length === 0) {\n return\n }\n\n for (const key of propertyKeys) {\n const schema = resolve.schema(properties[key])\n if (!schema) {\n delete result[key]\n continue\n }\n\n if (typeof schema !== 'object') {\n result[key] = schema\n continue\n }\n\n if (!result[key]) {\n // Break self-referential cycles reached through `allOf`. When a brand-new\n // property's `$ref` is already being merged higher in the call stack,\n // keep the raw reference instead of recursing into its `allOf` forever.\n // This mirrors the guard in the \"merge existing property\" branch below and\n // covers schemas that point back at themselves through an `allOf` member\n // (e.g. a node whose `self` property $refs the node, which is an allOf).\n const rawProperty = properties[key]\n const newSchemaRef = (rawProperty as { $ref?: string })?.$ref\n if (rawProperty && typeof newSchemaRef === 'string' && seenRefs.has(newSchemaRef)) {\n result[key] = rawProperty\n continue\n }\n const nextNewSeenRefs = typeof newSchemaRef === 'string' ? new Set(seenRefs).add(newSchemaRef) : seenRefs\n\n // Handle new property with allOf\n if (schema.allOf) {\n result[key] = mergeAllOfSchemas(schema, undefined, nextNewSeenRefs)\n } else if (isArraySchema(schema) && resolve.schema(schema.items)?.allOf) {\n result[key] = {\n ...schema,\n items: mergeAllOfSchemas(resolve.schema(schema.items), undefined, seenRefs),\n }\n } else if (properties[key]) {\n result[key] = properties[key]\n }\n continue\n }\n\n // Merge existing property\n const existing = resolve.schema(result[key])\n\n // Break self-referential cycles: when this property's `$ref` is already\n // being merged higher in the call stack, keep the partially merged existing\n // schema instead of recursing into it again. This mirrors the guard in\n // `mergeItems` and covers schemas that point back at themselves through a\n // plain object property (e.g. a tree node whose `parent` $refs the node).\n const schemaRef = schema.$ref\n if (typeof schemaRef === 'string' && seenRefs.has(schemaRef)) {\n result[key] = existing\n continue\n }\n const nextSeenRefs = typeof schemaRef === 'string' ? new Set(seenRefs).add(schemaRef) : seenRefs\n\n if (schema.allOf) {\n result[key] = mergeAllOfSchemas({ allOf: [existing, schema] } as SchemaObject, undefined, nextSeenRefs)\n } else if (isArraySchema(schema) && isArraySchema(existing) && schema.items) {\n const existingItems = resolve.schema(existing.items)\n result[key] = {\n ...existing,\n type: 'array',\n items: existingItems\n ? mergeItems(existingItems, resolve.schema(schema.items), nextSeenRefs)\n : resolve.schema(schema.items),\n }\n } else {\n // Create merged object with properties handled separately\n if ('properties' in existing && 'properties' in schema) {\n const merged = { ...existing, ...schema }\n merged.properties = { ...existing.properties }\n mergePropertiesIntoResult(merged.properties, schema.properties, nextSeenRefs)\n result[key] = merged\n }\n // Simple merge without property recursion\n else {\n result[key] = {\n ...schema,\n ...existing,\n ...mergeEnums(existing, schema),\n }\n }\n }\n }\n}\n\n/**\n * Efficiently merges array items into a result object.\n */\nconst mergeItemsIntoResult = (result: SchemaObject, items: SchemaObject, seenRefs: Set<string> = new Set()): void => {\n // Handle allOf in items\n if (items.allOf || result.allOf) {\n // Build array without spreads for better performance\n const allOfSchemas: SchemaObject[] = []\n\n if (result.allOf) {\n for (const schema of result.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(result)\n }\n\n if (items.allOf) {\n for (const schema of items.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(items)\n }\n\n const merged = mergeAllOfSchemas({ allOf: allOfSchemas } as SchemaObject, undefined, seenRefs)\n Object.assign(result, merged)\n return\n }\n\n // Regular merge\n Object.assign(result, items)\n\n // Merge properties if both have them\n if ('properties' in result && 'properties' in items) {\n mergePropertiesIntoResult(result.properties, items.properties, seenRefs)\n }\n}\n\n/**\n * Helper function for merging items that returns a new object.\n */\nconst mergeItems = (\n existing: SchemaObject,\n incoming: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n const incomingRef = (incoming as { $ref?: string }).$ref\n\n if (typeof incomingRef === 'string') {\n if (seenRefs.has(incomingRef)) {\n return existing\n }\n return mergeItemsInner(existing, incoming, new Set(seenRefs).add(incomingRef))\n }\n\n return mergeItemsInner(existing, incoming, seenRefs)\n}\n\nconst mergeItemsInner = (\n existing: SchemaObject,\n incoming: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n // Handle allOf in either schema\n if (existing.allOf || incoming.allOf) {\n // Build array without spreads for better performance\n const allOfSchemas: SchemaObject[] = []\n\n if (existing.allOf) {\n for (const schema of existing.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(existing)\n }\n\n if (incoming.allOf) {\n for (const schema of incoming.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(incoming)\n }\n\n return mergeAllOfSchemas({ allOf: allOfSchemas } as SchemaObject, undefined, seenRefs)\n }\n\n // Construct the merged object after narrowing both schemas so their property types survive.\n if ('properties' in existing && 'properties' in incoming) {\n const merged = { ...existing, ...incoming, properties: { ...existing.properties } }\n mergePropertiesIntoResult(merged.properties, incoming.properties, seenRefs)\n return merged\n }\n\n return { ...existing, ...incoming }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"normalize-object-composition.js","names":[],"sources":["../../../src/schema/helpers/normalize-object-composition.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { isTypeObject } from './is-type-object'\nimport { partitionAllOfCompositions } from './partition-all-of-compositions'\n\n/** Display schemas may carry the nullable annotation produced by composition optimization. */\ntype DisplaySchema = SchemaObject & { nullable?: boolean }\n\n/** Preserve a named property's object boundary when all of its composition members form one object. */\nexport const normalizeObjectComposition = (\n value: DisplaySchema | undefined,\n name: string | undefined,\n): DisplaySchema | undefined => {\n // Choice groups and unnamed composition containers keep their existing rendering.\n if (!name || !value?.allOf || value.oneOf || value.anyOf || value.not) {\n return value\n }\n\n const { segments } = partitionAllOfCompositions(value)\n const segment = segments[0]\n if (segments.length !== 1 || segment?.kind !== 'object' || !isTypeObject(segment.schema)) {\n return value\n }\n\n // A member reference identifies only part of this object, not the combined property.\n // Keep the property's own reference, if it has one.\n const objectSchema = { ...segment.schema }\n if ('$ref' in objectSchema) {\n delete objectSchema.$ref\n }\n // Member annotations describe only one part of the combined property. Keep the\n // property's annotations authoritative without changing merged validation rules.\n const annotations = {\n title: value.title,\n description: value.description,\n deprecated: value.deprecated,\n readOnly: value.readOnly,\n writeOnly: value.writeOnly,\n example: value.example,\n examples: value.examples,\n nullable: value.nullable,\n }\n return {\n ...objectSchema,\n ...annotations,\n ...('$ref' in value && typeof value.$ref === 'string' ? { $ref: value.$ref } : {}),\n }\n}\n"],"mappings":";;;AASA,IAAa,KACX,GACA,MAC8B;CAE9B,IAAI,CAAC,KAAQ,CAAC,GAAO,SAAS,EAAM,SAAS,EAAM,SAAS,EAAM,KAChE,OAAO;CAGT,IAAM,EAAE,gBAAa,EAA2B,CAAK,GAC/C,IAAU,EAAS;CACzB,IAAI,EAAS,WAAW,KAAK,GAAS,SAAS,YAAY,CAAC,EAAa,EAAQ,MAAM,GACrF,OAAO;CAKT,IAAM,IAAe,EAAE,GAAG,EAAQ,OAAO;CACzC,AAAI,UAAU,KACZ,OAAO,EAAa;CAItB,IAAM,IAAc;EAClB,OAAO,EAAM;EACb,aAAa,EAAM;EACnB,YAAY,EAAM;EAClB,UAAU,EAAM;EAChB,WAAW,EAAM;EACjB,SAAS,EAAM;EACf,UAAU,EAAM;EAChB,UAAU,EAAM;CAClB;CACA,OAAO;EACL,GAAG;EACH,GAAG;EACH,GAAI,UAAU,KAAS,OAAO,EAAM,QAAS,WAAW,EAAE,MAAM,EAAM,KAAK,IAAI,CAAC;CAClF;AACF"}
1
+ {"version":3,"file":"normalize-object-composition.js","names":["normalizeObjectComposition","name","value","partitionAllOfCompositions","segment","segments","isTypeObject","objectSchema","annotations"],"sources":["../../../src/schema/helpers/normalize-object-composition.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { isTypeObject } from './is-type-object'\nimport { partitionAllOfCompositions } from './partition-all-of-compositions'\n\n/** Display schemas may carry the nullable annotation produced by composition optimization. */\ntype DisplaySchema = SchemaObject & { nullable?: boolean }\n\n/** Preserve a named property's object boundary when all of its composition members form one object. */\nexport const normalizeObjectComposition = (\n value: DisplaySchema | undefined,\n name: string | undefined,\n): DisplaySchema | undefined => {\n // Choice groups and unnamed composition containers keep their existing rendering.\n if (!name || !value?.allOf || value.oneOf || value.anyOf || value.not) {\n return value\n }\n\n const { segments } = partitionAllOfCompositions(value)\n const segment = segments[0]\n if (segments.length !== 1 || segment?.kind !== 'object' || !isTypeObject(segment.schema)) {\n return value\n }\n\n // A member reference identifies only part of this object, not the combined property.\n // Keep the property's own reference, if it has one.\n const objectSchema = { ...segment.schema }\n if ('$ref' in objectSchema) {\n delete objectSchema.$ref\n }\n // Member annotations describe only one part of the combined property. Keep the\n // property's annotations authoritative without changing merged validation rules.\n const annotations = {\n title: value.title,\n description: value.description,\n deprecated: value.deprecated,\n readOnly: value.readOnly,\n writeOnly: value.writeOnly,\n example: value.example,\n examples: value.examples,\n nullable: value.nullable,\n }\n return {\n ...objectSchema,\n ...annotations,\n ...('$ref' in value && typeof value.$ref === 'string' ? { $ref: value.$ref } : {}),\n }\n}\n"],"mappings":";;;AASA,IAAaA,KACX,GACA,MAC8B;CAE9B,IAAI,CAACC,KAAQ,CAACC,GAAO,SAASA,EAAM,SAASA,EAAM,SAASA,EAAM,KAChE,OAAOA;CAGT,IAAM,EAAE,gBAAaC,EAA2BD,CAAK,GAC/CE,IAAUC,EAAS;CACzB,IAAIA,EAAS,WAAW,KAAKD,GAAS,SAAS,YAAY,CAACE,EAAaF,EAAQ,MAAM,GACrF,OAAOF;CAKT,IAAMK,IAAe,EAAE,GAAGH,EAAQ,OAAO;CACzC,AAAI,UAAUG,KACZ,OAAOA,EAAa;CAItB,IAAMC,IAAc;EAClB,OAAON,EAAM;EACb,aAAaA,EAAM;EACnB,YAAYA,EAAM;EAClB,UAAUA,EAAM;EAChB,WAAWA,EAAM;EACjB,SAASA,EAAM;EACf,UAAUA,EAAM;EAChB,UAAUA,EAAM;CAClB;CACA,OAAO;EACL,GAAGK;EACH,GAAGC;EACH,GAAI,UAAUN,KAAS,OAAOA,EAAM,QAAS,WAAW,EAAE,MAAMA,EAAM,KAAK,IAAI,CAAC;CAClF;AACF"}
@@ -4,18 +4,11 @@ import { resolve as n } from "@scalar/workspace-store/resolve";
4
4
  //#region src/schema/helpers/optimize-value-for-display.ts
5
5
  function r(...e) {
6
6
  let t = {}, n = {}, r = /* @__PURE__ */ new Set(), i = !1, a = !1;
7
- for (let o of e) if (o) for (let [e, s] of Object.entries(o)) {
8
- if (e === "properties" && s && typeof s == "object") {
9
- Object.assign(n, s), i = !0;
10
- continue;
11
- }
12
- if (e === "required" && Array.isArray(s)) {
13
- for (let e of s) r.add(e);
14
- a = !0;
15
- continue;
16
- }
17
- t[e] = s;
18
- }
7
+ for (let o of e) if (o) for (let [e, s] of Object.entries(o)) if (e === "properties" && s && typeof s == "object") Object.assign(n, s), i = !0;
8
+ else if (e === "required" && Array.isArray(s)) {
9
+ for (let e of s) r.add(e);
10
+ a = !0;
11
+ } else t[e] = s;
19
12
  return i && (t.properties = n), a && (t.required = [...r]), t;
20
13
  }
21
14
  function i(i) {
@@ -1 +1 @@
1
- {"version":3,"file":"optimize-value-for-display.js","names":[],"sources":["../../../src/schema/helpers/optimize-value-for-display.ts"],"sourcesContent":["import { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { type DiscriminatorSchema, schemaDiscriminator } from '../discriminator-metadata'\nimport { compositions } from './schema-composition'\n\n/** Display normalization tracks null branches without changing the stored OpenAPI schema. */\ntype DisplaySchema = SchemaObject & { nullable?: boolean }\n\n/**\n * Shallow-merges schema-like objects, but unions `properties` and `required`\n * instead of letting a later object's `properties`/`required` completely\n * overwrite an earlier one's. Without this, a variant schema (e.g. a `oneOf`\n * branch) that declares its own `properties`/`required` would wipe out the\n * shared base fields factored out at the root (or via a sibling `allOf`)\n * instead of being combined with them (#9657).\n */\nfunction mergeSchemaProperties(...objects: (Record<string, unknown> | undefined)[]): Record<string, unknown> {\n const merged: Record<string, unknown> = {}\n const properties: Record<string, unknown> = {}\n const required = new Set<string>()\n let hasProperties = false\n let hasRequired = false\n\n for (const object of objects) {\n if (!object) {\n continue\n }\n\n for (const [key, val] of Object.entries(object)) {\n if (key === 'properties' && val && typeof val === 'object') {\n Object.assign(properties, val)\n hasProperties = true\n continue\n }\n\n if (key === 'required' && Array.isArray(val)) {\n for (const name of val) {\n required.add(name)\n }\n hasRequired = true\n continue\n }\n\n merged[key] = val\n }\n }\n\n if (hasProperties) {\n merged.properties = properties\n }\n if (hasRequired) {\n merged.required = [...required]\n }\n\n return merged\n}\n\n/**\n * Normalize compositions for display without changing the source schema. Null branches\n * become nullable state, single branches are flattened, and shared properties and\n * required fields are merged into variants so the renderer keeps their full context.\n */\nexport function optimizeValueForDisplay(value: DisplaySchema | undefined): DisplaySchema | undefined {\n if (!value || typeof value !== 'object') {\n return value\n }\n\n // Inferred AsyncAPI variants already carry complete concrete schemas. Flattening\n // them would lose reference identities and merge the base identity into descendants.\n if ((value as DiscriminatorSchema)[schemaDiscriminator]?.inheritedVariants) {\n return value\n }\n\n // Find the composition keyword early to avoid unnecessary work\n const composition = compositions.find((keyword) => keyword in value && keyword !== 'not')\n\n // If there's no relevant composition keyword, return a shallow copy\n if (!composition) {\n return { ...value }\n }\n\n const schemas = value[composition]\n if (!Array.isArray(schemas)) {\n return { ...value }\n }\n\n // Extract root properties efficiently (excluding composition and nullable)\n const { [composition]: _, nullable: originalNullable, ...rootProperties } = value\n const hasRootProperties = Object.keys(rootProperties).length > 0\n\n // Check for null schemas and filter them out in one pass\n const { filteredSchemas, hasNullSchema } = schemas.reduce<{\n filteredSchemas: SchemaObject[]\n hasNullSchema: boolean\n }>(\n (acc, _schema) => {\n const schema = resolve.schema(_schema)\n\n if ('type' in schema && schema.type === 'null') {\n acc.hasNullSchema = true\n } else {\n acc.filteredSchemas.push(schema)\n }\n return acc\n },\n { filteredSchemas: [], hasNullSchema: false },\n )\n\n // Determine if nullable should be set\n const shouldBeNullable = hasNullSchema || originalNullable === true\n\n // If only one schema remains after filtering, merge with root properties.\n // `properties`/`required` are unioned so sibling properties declared next to\n // the composition (e.g. `properties` alongside a single-`$ref` `allOf`) are\n // kept instead of being overwritten by the member schema's own `properties`.\n // Root-level annotations (title, description, …) win over the member's: they\n // describe the combined schema, not the base it extends.\n if (filteredSchemas.length === 1) {\n const mergedSchema = mergeSchemaProperties(filteredSchemas[0], rootProperties) as DisplaySchema\n if (shouldBeNullable) {\n mergedSchema.nullable = true\n }\n return mergedSchema\n }\n\n // Check if root properties should be merged into schemas\n const shouldMergeRootProperties =\n (composition === 'oneOf' || composition === 'anyOf') &&\n (hasRootProperties || filteredSchemas.some((schema) => schema.allOf))\n\n if (shouldMergeRootProperties) {\n // The discriminator belongs to the union, not to its variants. Copied into a variant, it\n // makes the variant look like a bare `discriminator.mapping` base, which then infers a\n // second selector inside the variant.\n const { discriminator: _discriminator, ...variantRootProperties } = rootProperties\n\n const mergedSchemas = filteredSchemas.map((_schema) => {\n const schema = resolve.schema(_schema)\n\n // Flatten single-item allOf and merge with root properties. If the\n // variant has its own properties/required/$ref, the allOf member's own\n // identity (`$ref`, `title`, `name`) is dropped before merging so it\n // cannot overwrite the variant's, which would otherwise mislabel the\n // flattened schema as the base it extends instead of the variant itself\n // (#9964). `getModelNameFromSchema` labels a variant by title → name →\n // $ref, so any of those leaking from the base is enough to mislabel it.\n // A variant that is a bare wrapper around the allOf member has no\n // identity of its own to protect, so the base's identity is kept as a\n // fallback label.\n if (schema.allOf?.length === 1) {\n const { allOf, ...otherProps } = schema\n const allOfMember = resolve.schema(allOf[0])!\n const variantHasOwnIdentity = 'properties' in otherProps || 'required' in otherProps || '$ref' in otherProps\n if (variantHasOwnIdentity) {\n const { $ref: _ref, title: _title, name: _name, ...allOfMemberWithoutIdentity } = allOfMember\n return mergeSchemaProperties(variantRootProperties, otherProps, allOfMemberWithoutIdentity)\n }\n return mergeSchemaProperties(variantRootProperties, otherProps, allOfMember)\n }\n return mergeSchemaProperties(variantRootProperties, schema)\n })\n\n // @ts-expect-error - We avoid using coerceValue here as it may be dangerous, so we type cast\n const result = { [composition]: mergedSchemas } as DisplaySchema\n if (typeof value.description === 'string') {\n result.description = value.description\n }\n if (shouldBeNullable) {\n result.nullable = true\n }\n return result\n }\n\n // Return with filtered schemas if any nulls were removed\n if (filteredSchemas.length !== schemas.length) {\n const result: DisplaySchema = { ...value, [composition]: filteredSchemas }\n if (shouldBeNullable) {\n result.nullable = true\n }\n return result\n }\n\n return { ...value }\n}\n"],"mappings":";;;;AAiBA,SAAS,EAAsB,GAAG,GAA2E;CAC3G,IAAM,IAAkC,CAAC,GACnC,IAAsC,CAAC,GACvC,oBAAW,IAAI,IAAY,GAC7B,IAAgB,IAChB,IAAc;CAElB,KAAK,IAAM,KAAU,GACd,OAIL,KAAK,IAAM,CAAC,GAAK,MAAQ,OAAO,QAAQ,CAAM,GAAG;EAC/C,IAAI,MAAQ,gBAAgB,KAAO,OAAO,KAAQ,UAAU;GAE1D,AADA,OAAO,OAAO,GAAY,CAAG,GAC7B,IAAgB;GAChB;EACF;EAEA,IAAI,MAAQ,cAAc,MAAM,QAAQ,CAAG,GAAG;GAC5C,KAAK,IAAM,KAAQ,GACjB,EAAS,IAAI,CAAI;GAEnB,IAAc;GACd;EACF;EAEA,EAAO,KAAO;CAChB;CAUF,OAPI,MACF,EAAO,aAAa,IAElB,MACF,EAAO,WAAW,CAAC,GAAG,CAAQ,IAGzB;AACT;AAOA,SAAgB,EAAwB,GAA6D;CAOnG,IANI,CAAC,KAAS,OAAO,KAAU,YAM1B,EAA8B,EAAoB,EAAE,mBACvD,OAAO;CAIT,IAAM,IAAc,EAAa,MAAM,MAAY,KAAW,KAAS,MAAY,KAAK;CAGxF,IAAI,CAAC,GACH,OAAO,EAAE,GAAG,EAAM;CAGpB,IAAM,IAAU,EAAM;CACtB,IAAI,CAAC,MAAM,QAAQ,CAAO,GACxB,OAAO,EAAE,GAAG,EAAM;CAIpB,IAAM,GAAG,IAAc,GAAG,UAAU,GAAkB,GAAG,MAAmB,GACtE,IAAoB,OAAO,KAAK,CAAc,CAAC,CAAC,SAAS,GAGzD,EAAE,oBAAiB,qBAAkB,EAAQ,QAIhD,GAAK,MAAY;EAChB,IAAM,IAAS,EAAQ,OAAO,CAAO;EAOrC,OALI,UAAU,KAAU,EAAO,SAAS,SACtC,EAAI,gBAAgB,KAEpB,EAAI,gBAAgB,KAAK,CAAM,GAE1B;CACT,GACA;EAAE,iBAAiB,CAAC;EAAG,eAAe;CAAM,CAC9C,GAGM,IAAmB,KAAiB,MAAqB;CAQ/D,IAAI,EAAgB,WAAW,GAAG;EAChC,IAAM,IAAe,EAAsB,EAAgB,IAAI,CAAc;EAI7E,OAHI,MACF,EAAa,WAAW,KAEnB;CACT;CAOA,KAHG,MAAgB,WAAW,MAAgB,aAC3C,KAAqB,EAAgB,MAAM,MAAW,EAAO,KAAK,IAEtC;EAI7B,IAAM,EAAE,eAAe,GAAgB,GAAG,MAA0B,GAE9D,IAAgB,EAAgB,KAAK,MAAY;GACrD,IAAM,IAAS,EAAQ,OAAO,CAAO;GAYrC,IAAI,EAAO,OAAO,WAAW,GAAG;IAC9B,IAAM,EAAE,UAAO,GAAG,MAAe,GAC3B,IAAc,EAAQ,OAAO,EAAM,EAAE;IAE3C,IAD8B,gBAAgB,KAAc,cAAc,KAAc,UAAU,GACvE;KACzB,IAAM,EAAE,MAAM,GAAM,OAAO,GAAQ,MAAM,GAAO,GAAG,MAA+B;KAClF,OAAO,EAAsB,GAAuB,GAAY,CAA0B;IAC5F;IACA,OAAO,EAAsB,GAAuB,GAAY,CAAW;GAC7E;GACA,OAAO,EAAsB,GAAuB,CAAM;EAC5D,CAAC,GAGK,IAAS,GAAG,IAAc,EAAc;EAO9C,OANI,OAAO,EAAM,eAAgB,aAC/B,EAAO,cAAc,EAAM,cAEzB,MACF,EAAO,WAAW,KAEb;CACT;CAGA,IAAI,EAAgB,WAAW,EAAQ,QAAQ;EAC7C,IAAM,IAAwB;GAAE,GAAG;IAAQ,IAAc;EAAgB;EAIzE,OAHI,MACF,EAAO,WAAW,KAEb;CACT;CAEA,OAAO,EAAE,GAAG,EAAM;AACpB"}
1
+ {"version":3,"file":"optimize-value-for-display.js","names":["mergeSchemaProperties","objects","merged","properties","required","hasProperties","hasRequired","object","key","val","name","optimizeValueForDisplay","value","schemaDiscriminator","composition","compositions","keyword","schemas","_","originalNullable","rootProperties","hasRootProperties","schema","resolve","_schema","acc","shouldBeNullable","hasNullSchema","filteredSchemas","mergedSchema","_discriminator","variantRootProperties","mergedSchemas","otherProps","allOfMember","allOf","_ref","_title","_name","allOfMemberWithoutIdentity","result"],"sources":["../../../src/schema/helpers/optimize-value-for-display.ts"],"sourcesContent":["import { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { type DiscriminatorSchema, schemaDiscriminator } from '../discriminator-metadata'\nimport { compositions } from './schema-composition'\n\n/** Display normalization tracks null branches without changing the stored OpenAPI schema. */\ntype DisplaySchema = SchemaObject & { nullable?: boolean }\n\n/**\n * Shallow-merges schema-like objects, but unions `properties` and `required`\n * instead of letting a later object's `properties`/`required` completely\n * overwrite an earlier one's. Without this, a variant schema (e.g. a `oneOf`\n * branch) that declares its own `properties`/`required` would wipe out the\n * shared base fields factored out at the root (or via a sibling `allOf`)\n * instead of being combined with them (#9657).\n */\nfunction mergeSchemaProperties(...objects: (Record<string, unknown> | undefined)[]): Record<string, unknown> {\n const merged: Record<string, unknown> = {}\n const properties: Record<string, unknown> = {}\n const required = new Set<string>()\n let hasProperties = false\n let hasRequired = false\n\n for (const object of objects) {\n if (!object) {\n continue\n }\n\n for (const [key, val] of Object.entries(object)) {\n if (key === 'properties' && val && typeof val === 'object') {\n Object.assign(properties, val)\n hasProperties = true\n continue\n }\n\n if (key === 'required' && Array.isArray(val)) {\n for (const name of val) {\n required.add(name)\n }\n hasRequired = true\n continue\n }\n\n merged[key] = val\n }\n }\n\n if (hasProperties) {\n merged.properties = properties\n }\n if (hasRequired) {\n merged.required = [...required]\n }\n\n return merged\n}\n\n/**\n * Normalize compositions for display without changing the source schema. Null branches\n * become nullable state, single branches are flattened, and shared properties and\n * required fields are merged into variants so the renderer keeps their full context.\n */\nexport function optimizeValueForDisplay(value: DisplaySchema | undefined): DisplaySchema | undefined {\n if (!value || typeof value !== 'object') {\n return value\n }\n\n // Inferred AsyncAPI variants already carry complete concrete schemas. Flattening\n // them would lose reference identities and merge the base identity into descendants.\n if ((value as DiscriminatorSchema)[schemaDiscriminator]?.inheritedVariants) {\n return value\n }\n\n // Find the composition keyword early to avoid unnecessary work\n const composition = compositions.find((keyword) => keyword in value && keyword !== 'not')\n\n // If there's no relevant composition keyword, return a shallow copy\n if (!composition) {\n return { ...value }\n }\n\n const schemas = value[composition]\n if (!Array.isArray(schemas)) {\n return { ...value }\n }\n\n // Extract root properties efficiently (excluding composition and nullable)\n const { [composition]: _, nullable: originalNullable, ...rootProperties } = value\n const hasRootProperties = Object.keys(rootProperties).length > 0\n\n // Check for null schemas and filter them out in one pass\n const { filteredSchemas, hasNullSchema } = schemas.reduce<{\n filteredSchemas: SchemaObject[]\n hasNullSchema: boolean\n }>(\n (acc, _schema) => {\n const schema = resolve.schema(_schema)\n\n if ('type' in schema && schema.type === 'null') {\n acc.hasNullSchema = true\n } else {\n acc.filteredSchemas.push(schema)\n }\n return acc\n },\n { filteredSchemas: [], hasNullSchema: false },\n )\n\n // Determine if nullable should be set\n const shouldBeNullable = hasNullSchema || originalNullable === true\n\n // If only one schema remains after filtering, merge with root properties.\n // `properties`/`required` are unioned so sibling properties declared next to\n // the composition (e.g. `properties` alongside a single-`$ref` `allOf`) are\n // kept instead of being overwritten by the member schema's own `properties`.\n // Root-level annotations (title, description, …) win over the member's: they\n // describe the combined schema, not the base it extends.\n if (filteredSchemas.length === 1) {\n const mergedSchema = mergeSchemaProperties(filteredSchemas[0], rootProperties) as DisplaySchema\n if (shouldBeNullable) {\n mergedSchema.nullable = true\n }\n return mergedSchema\n }\n\n // Check if root properties should be merged into schemas\n const shouldMergeRootProperties =\n (composition === 'oneOf' || composition === 'anyOf') &&\n (hasRootProperties || filteredSchemas.some((schema) => schema.allOf))\n\n if (shouldMergeRootProperties) {\n // The discriminator belongs to the union, not to its variants. Copied into a variant, it\n // makes the variant look like a bare `discriminator.mapping` base, which then infers a\n // second selector inside the variant.\n const { discriminator: _discriminator, ...variantRootProperties } = rootProperties\n\n const mergedSchemas = filteredSchemas.map((_schema) => {\n const schema = resolve.schema(_schema)\n\n // Flatten single-item allOf and merge with root properties. If the\n // variant has its own properties/required/$ref, the allOf member's own\n // identity (`$ref`, `title`, `name`) is dropped before merging so it\n // cannot overwrite the variant's, which would otherwise mislabel the\n // flattened schema as the base it extends instead of the variant itself\n // (#9964). `getModelNameFromSchema` labels a variant by title → name →\n // $ref, so any of those leaking from the base is enough to mislabel it.\n // A variant that is a bare wrapper around the allOf member has no\n // identity of its own to protect, so the base's identity is kept as a\n // fallback label.\n if (schema.allOf?.length === 1) {\n const { allOf, ...otherProps } = schema\n const allOfMember = resolve.schema(allOf[0])!\n const variantHasOwnIdentity = 'properties' in otherProps || 'required' in otherProps || '$ref' in otherProps\n if (variantHasOwnIdentity) {\n const { $ref: _ref, title: _title, name: _name, ...allOfMemberWithoutIdentity } = allOfMember\n return mergeSchemaProperties(variantRootProperties, otherProps, allOfMemberWithoutIdentity)\n }\n return mergeSchemaProperties(variantRootProperties, otherProps, allOfMember)\n }\n return mergeSchemaProperties(variantRootProperties, schema)\n })\n\n // @ts-expect-error - We avoid using coerceValue here as it may be dangerous, so we type cast\n const result = { [composition]: mergedSchemas } as DisplaySchema\n if (typeof value.description === 'string') {\n result.description = value.description\n }\n if (shouldBeNullable) {\n result.nullable = true\n }\n return result\n }\n\n // Return with filtered schemas if any nulls were removed\n if (filteredSchemas.length !== schemas.length) {\n const result: DisplaySchema = { ...value, [composition]: filteredSchemas }\n if (shouldBeNullable) {\n result.nullable = true\n }\n return result\n }\n\n return { ...value }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"partition-all-of-compositions.js","names":[],"sources":["../../../src/schema/helpers/partition-all-of-compositions.ts"],"sourcesContent":["import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject, SchemaReferenceType } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { mergeAllOfSchemas } from './merge-all-of-schemas'\nimport type { CompositionKeyword } from './schema-composition'\n\ntype ChoiceKeyword = Extract<CompositionKeyword, 'oneOf' | 'anyOf'>\n\n/** An ordered piece of an `allOf`: either a merged object or a choice picker. */\ntype AllOfSegment =\n | { kind: 'object'; schema: SchemaObject }\n | {\n kind: 'choice'\n composition: ChoiceKeyword\n /** A minimal schema carrying only this group's composition, for SchemaComposition */\n value: SchemaObject\n /** Ordinal among choice members, matching the request-example composition key */\n choiceIndex: number\n }\n\nconst CHOICE_KEYWORDS: ChoiceKeyword[] = ['oneOf', 'anyOf']\n\ntype Member =\n | { kind: 'object'; schema: SchemaObject }\n | { kind: 'boolean'; schema: SchemaObject }\n | { kind: 'choice'; composition: ChoiceKeyword; value: SchemaObject; inheritedSelection: boolean }\n\n/**\n * Flattens a member's own (non-composition) properties and every `oneOf`/`anyOf`\n * group it declares — recursing into nested `allOf` — into a flat, ordered list,\n * preserving source order so choice groups stay where they were authored.\n *\n * Pure-constraint keywords (`not`, `if/then/else`) are dropped: they carry no\n * visual variant and Scalar would otherwise render `not` as a bogus picker. The\n * rule still lives in the schema (validation) and in field descriptions.\n */\nconst collectMembers = (\n input: SchemaReferenceType<SchemaObject> | boolean,\n out: Member[],\n seenRefs: Set<string>,\n): void => {\n const target = getResolvedRef(input)\n if (typeof target === 'boolean') {\n // Keep the explanation separate: merging it with an object's description would hide it.\n out.push({ kind: 'boolean', schema: resolve.schema(target) })\n return\n }\n const schema = resolve.schema(input)\n const {\n allOf,\n oneOf,\n anyOf,\n not: _not,\n if: _if,\n then: _then,\n else: _else,\n ...rest\n }: SchemaObject & {\n allOf?: unknown[]\n oneOf?: unknown[]\n anyOf?: unknown[]\n not?: unknown\n if?: unknown\n then?: unknown\n else?: unknown\n } = schema\n\n if (Object.keys(rest).length > 0) {\n out.push({ kind: 'object', schema: rest })\n }\n\n for (const keyword of CHOICE_KEYWORDS) {\n const value = keyword === 'oneOf' ? oneOf : anyOf\n // A variant inherits its base fields through allOf, but the base's choice\n // containing that variant has already been selected. Rendering it again\n // would re-enter the variant and expose fields from the other branches.\n const selectsAncestor =\n Array.isArray(value) &&\n value.some((branch) => {\n const ref = branch && typeof branch === 'object' && '$ref' in branch ? branch.$ref : undefined\n return typeof ref === 'string' && seenRefs.has(ref)\n })\n if (Array.isArray(value) && value.length > 0) {\n out.push({\n kind: 'choice',\n composition: keyword,\n value: { [keyword]: value } as unknown as SchemaObject,\n inheritedSelection: selectsAncestor,\n })\n }\n }\n\n if (Array.isArray(allOf)) {\n for (const rawMember of allOf) {\n if (typeof rawMember === 'boolean' || (rawMember && typeof rawMember === 'object')) {\n const resolved: SchemaObject & { $ref?: string } = resolve.schema(rawMember)\n // Break `$ref` cycles reached through `allOf` (e.g. a member that\n // references an ancestor). Without this guard a recursive `allOf`\n // schema would recurse forever. `mergeAllOfSchemas` guards the same way.\n const ref = resolved.$ref\n if (typeof ref === 'string') {\n if (seenRefs.has(ref)) {\n continue\n }\n collectMembers(rawMember, out, new Set(seenRefs).add(ref))\n } else {\n collectMembers(rawMember, out, seenRefs)\n }\n }\n }\n }\n}\n\n/**\n * Splits an `allOf` schema into an ordered list of segments so the renderer can\n * show each `oneOf`/`anyOf` group as its own picker **in the position it was\n * declared**, with the surrounding plain fields around it.\n *\n * `mergeAllOfSchemas` alone keeps only the FIRST `oneOf`/`anyOf` (dropping the\n * 2nd+ groups of an object with several independent mutually-exclusive\n * selections) and, being a merge, also loses the ordering between fields and\n * choices. Walking the members in order fixes both: runs of consecutive object\n * members are merged into one object segment, and each choice member becomes its\n * own picker segment in place.\n */\nexport const partitionAllOfCompositions = (schema: SchemaObject | undefined): { segments: AllOfSegment[] } => {\n if (!schema) {\n return { segments: [] }\n }\n\n // The schema's own (non-composition) keys, minus its top-level `oneOf`/`anyOf`\n // — those are rendered as their own composition by the caller, not here.\n const {\n allOf,\n oneOf: _oneOf,\n anyOf: _anyOf,\n not: _not,\n if: _if,\n then: _then,\n else: _else,\n ...rest\n }: SchemaObject & {\n allOf?: unknown[]\n oneOf?: unknown[]\n anyOf?: unknown[]\n not?: unknown\n if?: unknown\n then?: unknown\n else?: unknown\n } = schema\n\n if (!Array.isArray(allOf)) {\n return { segments: [{ kind: 'object', schema: schema }] }\n }\n\n const members: Member[] = []\n if (Object.keys(rest).length > 0) {\n members.push({ kind: 'object', schema: rest })\n }\n const schemaRef = '$ref' in schema ? schema.$ref : undefined\n const seenRefs = new Set<string>(typeof schemaRef === 'string' ? [schemaRef] : [])\n for (const rawMember of allOf) {\n if (typeof rawMember === 'boolean' || (rawMember && typeof rawMember === 'object')) {\n const resolved: SchemaObject & { $ref?: string } = resolve.schema(rawMember)\n const ref = resolved.$ref\n collectMembers(rawMember, members, typeof ref === 'string' ? new Set(seenRefs).add(ref) : seenRefs)\n }\n }\n\n // Coalesce consecutive object members into a single merged object segment,\n // keeping choice members as their own segments between them.\n const segments: AllOfSegment[] = []\n let objectRun: SchemaObject[] = []\n let choiceIndex = 0\n\n const flushObjectRun = () => {\n if (objectRun.length === 0) {\n return\n }\n const merged = objectRun.length === 1 ? objectRun[0]! : mergeAllOfSchemas({ allOf: objectRun } as SchemaObject)\n segments.push({ kind: 'object', schema: merged })\n objectRun = []\n }\n\n for (const member of members) {\n if (member.kind === 'object') {\n objectRun.push(member.schema)\n } else if (member.kind === 'boolean') {\n flushObjectRun()\n segments.push({ kind: 'object', schema: member.schema })\n } else if (member.inheritedSelection) {\n // Hidden inherited choices still occupy an ordinal in the request example.\n choiceIndex++\n } else {\n flushObjectRun()\n // `choiceIndex` is the ordinal used to build the composition-selection key\n // that syncs each picker with the request example. It MUST stay aligned\n // with the ordinal computed while walking `allOf` in\n // `get-example-from-schema.ts` (`@scalar/workspace-store`), or a picker and\n // its generated example fall out of sync.\n segments.push({\n kind: 'choice',\n composition: member.composition,\n value: member.value,\n choiceIndex: choiceIndex++,\n })\n }\n }\n flushObjectRun()\n\n return { segments }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"partition-all-of-compositions.js","names":["CHOICE_KEYWORDS","collectMembers","target","getResolvedRef","input","resolve","_not","_if","_then","_else","rest","out","keyword","value","oneOf","anyOf","selectsAncestor","ref","branch","seenRefs","allOf","rawMember","partitionAllOfCompositions","schema","_oneOf","_anyOf","members","schemaRef","segments","objectRun","choiceIndex","flushObjectRun","merged","mergeAllOfSchemas","member"],"sources":["../../../src/schema/helpers/partition-all-of-compositions.ts"],"sourcesContent":["import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject, SchemaReferenceType } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { mergeAllOfSchemas } from './merge-all-of-schemas'\nimport type { CompositionKeyword } from './schema-composition'\n\ntype ChoiceKeyword = Extract<CompositionKeyword, 'oneOf' | 'anyOf'>\n\n/** An ordered piece of an `allOf`: either a merged object or a choice picker. */\ntype AllOfSegment =\n | { kind: 'object'; schema: SchemaObject }\n | {\n kind: 'choice'\n composition: ChoiceKeyword\n /** A minimal schema carrying only this group's composition, for SchemaComposition */\n value: SchemaObject\n /** Ordinal among choice members, matching the request-example composition key */\n choiceIndex: number\n }\n\nconst CHOICE_KEYWORDS: ChoiceKeyword[] = ['oneOf', 'anyOf']\n\ntype Member =\n | { kind: 'object'; schema: SchemaObject }\n | { kind: 'boolean'; schema: SchemaObject }\n | { kind: 'choice'; composition: ChoiceKeyword; value: SchemaObject; inheritedSelection: boolean }\n\n/**\n * Flattens a member's own (non-composition) properties and every `oneOf`/`anyOf`\n * group it declares — recursing into nested `allOf` — into a flat, ordered list,\n * preserving source order so choice groups stay where they were authored.\n *\n * Pure-constraint keywords (`not`, `if/then/else`) are dropped: they carry no\n * visual variant and Scalar would otherwise render `not` as a bogus picker. The\n * rule still lives in the schema (validation) and in field descriptions.\n */\nconst collectMembers = (\n input: SchemaReferenceType<SchemaObject> | boolean,\n out: Member[],\n seenRefs: Set<string>,\n): void => {\n const target = getResolvedRef(input)\n if (typeof target === 'boolean') {\n // Keep the explanation separate: merging it with an object's description would hide it.\n out.push({ kind: 'boolean', schema: resolve.schema(target) })\n return\n }\n const schema = resolve.schema(input)\n const {\n allOf,\n oneOf,\n anyOf,\n not: _not,\n if: _if,\n then: _then,\n else: _else,\n ...rest\n }: SchemaObject & {\n allOf?: unknown[]\n oneOf?: unknown[]\n anyOf?: unknown[]\n not?: unknown\n if?: unknown\n then?: unknown\n else?: unknown\n } = schema\n\n if (Object.keys(rest).length > 0) {\n out.push({ kind: 'object', schema: rest })\n }\n\n for (const keyword of CHOICE_KEYWORDS) {\n const value = keyword === 'oneOf' ? oneOf : anyOf\n // A variant inherits its base fields through allOf, but the base's choice\n // containing that variant has already been selected. Rendering it again\n // would re-enter the variant and expose fields from the other branches.\n const selectsAncestor =\n Array.isArray(value) &&\n value.some((branch) => {\n const ref = branch && typeof branch === 'object' && '$ref' in branch ? branch.$ref : undefined\n return typeof ref === 'string' && seenRefs.has(ref)\n })\n if (Array.isArray(value) && value.length > 0) {\n out.push({\n kind: 'choice',\n composition: keyword,\n value: { [keyword]: value } as unknown as SchemaObject,\n inheritedSelection: selectsAncestor,\n })\n }\n }\n\n if (Array.isArray(allOf)) {\n for (const rawMember of allOf) {\n if (typeof rawMember === 'boolean' || (rawMember && typeof rawMember === 'object')) {\n const resolved: SchemaObject & { $ref?: string } = resolve.schema(rawMember)\n // Break `$ref` cycles reached through `allOf` (e.g. a member that\n // references an ancestor). Without this guard a recursive `allOf`\n // schema would recurse forever. `mergeAllOfSchemas` guards the same way.\n const ref = resolved.$ref\n if (typeof ref === 'string') {\n if (seenRefs.has(ref)) {\n continue\n }\n collectMembers(rawMember, out, new Set(seenRefs).add(ref))\n } else {\n collectMembers(rawMember, out, seenRefs)\n }\n }\n }\n }\n}\n\n/**\n * Splits an `allOf` schema into an ordered list of segments so the renderer can\n * show each `oneOf`/`anyOf` group as its own picker **in the position it was\n * declared**, with the surrounding plain fields around it.\n *\n * `mergeAllOfSchemas` alone keeps only the FIRST `oneOf`/`anyOf` (dropping the\n * 2nd+ groups of an object with several independent mutually-exclusive\n * selections) and, being a merge, also loses the ordering between fields and\n * choices. Walking the members in order fixes both: runs of consecutive object\n * members are merged into one object segment, and each choice member becomes its\n * own picker segment in place.\n */\nexport const partitionAllOfCompositions = (schema: SchemaObject | undefined): { segments: AllOfSegment[] } => {\n if (!schema) {\n return { segments: [] }\n }\n\n // The schema's own (non-composition) keys, minus its top-level `oneOf`/`anyOf`\n // — those are rendered as their own composition by the caller, not here.\n const {\n allOf,\n oneOf: _oneOf,\n anyOf: _anyOf,\n not: _not,\n if: _if,\n then: _then,\n else: _else,\n ...rest\n }: SchemaObject & {\n allOf?: unknown[]\n oneOf?: unknown[]\n anyOf?: unknown[]\n not?: unknown\n if?: unknown\n then?: unknown\n else?: unknown\n } = schema\n\n if (!Array.isArray(allOf)) {\n return { segments: [{ kind: 'object', schema: schema }] }\n }\n\n const members: Member[] = []\n if (Object.keys(rest).length > 0) {\n members.push({ kind: 'object', schema: rest })\n }\n const schemaRef = '$ref' in schema ? schema.$ref : undefined\n const seenRefs = new Set<string>(typeof schemaRef === 'string' ? [schemaRef] : [])\n for (const rawMember of allOf) {\n if (typeof rawMember === 'boolean' || (rawMember && typeof rawMember === 'object')) {\n const resolved: SchemaObject & { $ref?: string } = resolve.schema(rawMember)\n const ref = resolved.$ref\n collectMembers(rawMember, members, typeof ref === 'string' ? new Set(seenRefs).add(ref) : seenRefs)\n }\n }\n\n // Coalesce consecutive object members into a single merged object segment,\n // keeping choice members as their own segments between them.\n const segments: AllOfSegment[] = []\n let objectRun: SchemaObject[] = []\n let choiceIndex = 0\n\n const flushObjectRun = () => {\n if (objectRun.length === 0) {\n return\n }\n const merged = objectRun.length === 1 ? objectRun[0]! : mergeAllOfSchemas({ allOf: objectRun } as SchemaObject)\n segments.push({ kind: 'object', schema: merged })\n objectRun = []\n }\n\n for (const member of members) {\n if (member.kind === 'object') {\n objectRun.push(member.schema)\n } else if (member.kind === 'boolean') {\n flushObjectRun()\n segments.push({ kind: 'object', schema: member.schema })\n } else if (member.inheritedSelection) {\n // Hidden inherited choices still occupy an ordinal in the request example.\n choiceIndex++\n } else {\n flushObjectRun()\n // `choiceIndex` is the ordinal used to build the composition-selection key\n // that syncs each picker with the request example. It MUST stay aligned\n // with the ordinal computed while walking `allOf` in\n // `get-example-from-schema.ts` (`@scalar/workspace-store`), or a picker and\n // its generated example fall out of sync.\n segments.push({\n kind: 'choice',\n composition: member.composition,\n value: member.value,\n choiceIndex: choiceIndex++,\n })\n }\n }\n flushObjectRun()\n\n return { segments }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-composition.js","names":[],"sources":["../../../src/schema/helpers/schema-composition.ts"],"sourcesContent":["/** Composition */\nexport type CompositionKeyword = 'oneOf' | 'anyOf' | 'allOf' | 'not'\n\nexport const compositions: CompositionKeyword[] = ['oneOf', 'anyOf', 'allOf', 'not']\n"],"mappings":";AAGA,IAAa,IAAqC;CAAC;CAAS;CAAS;CAAS;AAAK"}
1
+ {"version":3,"file":"schema-composition.js","names":["compositions"],"sources":["../../../src/schema/helpers/schema-composition.ts"],"sourcesContent":["/** Composition */\nexport type CompositionKeyword = 'oneOf' | 'anyOf' | 'allOf' | 'not'\n\nexport const compositions: CompositionKeyword[] = ['oneOf', 'anyOf', 'allOf', 'not']\n"],"mappings":";AAGA,IAAaA,IAAqC;CAAC;CAAS;CAAS;CAAS;AAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-cycle.js","names":[],"sources":["../../../src/schema/helpers/schema-cycle.ts"],"sourcesContent":["import type { InjectionKey } from 'vue'\n\n/**\n * The set of schema \"cycle keys\" for every ancestor on the current render path.\n *\n * Each `Schema` component injects this set, adds its own key, and re-provides\n * it to its descendants. When a node's key is already present in the ancestor\n * set we've hit a cycle (a self-referential schema) and must stop force\n * expanding to avoid rendering forever.\n *\n * See {@link getCycleKey} for how a node's key is derived.\n */\nexport const SCHEMA_ANCESTORS_SYMBOL: InjectionKey<ReadonlySet<unknown>> = Symbol('schema-ancestors')\n\n/**\n * Derive a stable identity for a schema node from its *raw* (unresolved) value.\n *\n * Cycle detection needs a key that is identical every time the same schema is\n * reached along a path, and that survives the shallow copies/merges performed\n * while rendering (which break object identity of the resolved schema).\n *\n * - For `$ref` nodes we use the ref string. Two branches that reference the\n * same component share the string, so a schema that (transitively) references\n * itself is detected as a cycle, while sibling references are not.\n * - For inline schemas there is no ref, so we fall back to the raw object\n * reference. A self-referential inline schema reuses the same object, so\n * object identity catches the cycle.\n *\n * Returns `undefined` for primitives/booleans (e.g. `additionalProperties: true`)\n * which can never form a cycle.\n */\nexport const getCycleKey = (raw: unknown): unknown => {\n if (raw && typeof raw === 'object') {\n if ('$ref' in raw && typeof raw.$ref === 'string') {\n return (raw as { $ref: string }).$ref\n }\n return raw\n }\n\n return undefined\n}\n"],"mappings":";AAYA,IAAa,IAA8D,OAAO,kBAAkB,GAmBvF,KAAe,MAA0B;CACpD,IAAI,KAAO,OAAO,KAAQ,UAIxB,OAHI,UAAU,KAAO,OAAO,EAAI,QAAS,WAC/B,EAAyB,OAE5B;AAIX"}
1
+ {"version":3,"file":"schema-cycle.js","names":["SCHEMA_ANCESTORS_SYMBOL","getCycleKey","raw"],"sources":["../../../src/schema/helpers/schema-cycle.ts"],"sourcesContent":["import type { InjectionKey } from 'vue'\n\n/**\n * The set of schema \"cycle keys\" for every ancestor on the current render path.\n *\n * Each `Schema` component injects this set, adds its own key, and re-provides\n * it to its descendants. When a node's key is already present in the ancestor\n * set we've hit a cycle (a self-referential schema) and must stop force\n * expanding to avoid rendering forever.\n *\n * See {@link getCycleKey} for how a node's key is derived.\n */\nexport const SCHEMA_ANCESTORS_SYMBOL: InjectionKey<ReadonlySet<unknown>> = Symbol('schema-ancestors')\n\n/**\n * Derive a stable identity for a schema node from its *raw* (unresolved) value.\n *\n * Cycle detection needs a key that is identical every time the same schema is\n * reached along a path, and that survives the shallow copies/merges performed\n * while rendering (which break object identity of the resolved schema).\n *\n * - For `$ref` nodes we use the ref string. Two branches that reference the\n * same component share the string, so a schema that (transitively) references\n * itself is detected as a cycle, while sibling references are not.\n * - For inline schemas there is no ref, so we fall back to the raw object\n * reference. A self-referential inline schema reuses the same object, so\n * object identity catches the cycle.\n *\n * Returns `undefined` for primitives/booleans (e.g. `additionalProperties: true`)\n * which can never form a cycle.\n */\nexport const getCycleKey = (raw: unknown): unknown => {\n if (raw && typeof raw === 'object') {\n if ('$ref' in raw && typeof raw.$ref === 'string') {\n return (raw as { $ref: string }).$ref\n }\n return raw\n }\n\n return undefined\n}\n"],"mappings":";AAYA,IAAaA,IAA8D,OAAO,kBAAkB,GAmBvFC,KAAe,MAA0B;CACpD,IAAIC,KAAO,OAAOA,KAAQ,UAIxB,OAHI,UAAUA,KAAO,OAAOA,EAAI,QAAS,WAC/BA,EAAyB,OAE5BA;AAIX"}
@@ -19,12 +19,11 @@ var s = (e, t) => t === "" || e === t || e.startsWith(`${t}.`), c = (e) => e?.jo
19
19
  f = !1;
20
20
  });
21
21
  }, m = (e, t) => {
22
- if (d(e), e === "") {
23
- o.clear(), c.value = t ? "expanded" : "collapsed";
24
- return;
22
+ if (d(e), e === "") o.clear(), c.value = t ? "expanded" : "collapsed";
23
+ else {
24
+ for (let t of [...o.keys()]) s(t, e) && o.delete(t);
25
+ o.set(e, t);
25
26
  }
26
- for (let t of [...o.keys()]) s(t, e) && o.delete(t);
27
- o.set(e, t);
28
27
  }, h = (t, i = {}) => {
29
28
  let a = r.get(t);
30
29
  if (a !== void 0) return a;
@@ -1 +1 @@
1
- {"version":3,"file":"schema-expansion.js","names":[],"sources":["../../../src/schema/helpers/schema-expansion.ts"],"sourcesContent":["import {\n type InjectionKey,\n type Ref,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowReactive,\n shallowRef,\n watch,\n} from 'vue'\n\nimport { isOnSchemaTargetPath } from './is-on-schema-target-path'\n\n/**\n * What a node does when nobody has expressed an opinion about it: its own\n * `defaultOpen`, or whatever expand-all / collapse-all last set.\n */\ntype ExpansionBaseline = 'default' | 'expanded' | 'collapsed'\n\n/** What the store cannot work out about a node on its own. */\ntype ExpansionContext = {\n /**\n * Whether this node sits on a `$ref` cycle. Bulk expansion and the baseline\n * skip cyclic nodes; without that, `expandAll()` on a self-referential schema\n * never terminates, because the cycle guard only suppresses auto-expansion.\n */\n cyclic?: boolean\n /** What the node would do with no store at all (its `defaultOpen`). */\n defaultOpen?: boolean\n /**\n * The public anchor path this node covers, when it differs from its key. A\n * key carrying a structural marker (`~headers`) must still open for a deep\n * link written against the anchor path (`…headers.X-Rate`).\n */\n anchorPath?: string\n}\n\n/** Shared expansion controls for a host and its schema trees. */\nexport type SchemaExpansionStore = {\n /** Resolve whether a node is open. See the resolution order below. */\n isExpanded: (key: string, ctx?: ExpansionContext) => boolean\n /** Record an explicit user decision about one node. */\n setExpanded: (key: string, value: boolean) => void\n /** Flip one node, resolving its current state first. */\n toggle: (key: string, ctx?: ExpansionContext) => void\n /** Expand everything, or everything beneath `root`. */\n expandAll: (root?: string) => void\n /** Collapse everything, or everything beneath `root`. */\n collapseAll: (root?: string) => void\n /** Make a deep link's expansion permanent by opening every ancestor of `path`. */\n commitPath: (path: string) => void\n /** The standing baseline, exposed so a print hook can flip it and put it back. */\n baseline: Ref<ExpansionBaseline>\n /**\n * The budget for closed panels kept in the DOM as `hidden=\"until-found\"`. It\n * lives on the store, so it is shared by every schema tree under one reference.\n * Kept panels stay searchable with find-in-page but grow the DOM, so a closing\n * row asks `acquire()` first and simply unmounts past the cap. Deliberately\n * not reactive: it only matters at the moment a panel closes.\n */\n untilFound: {\n acquire: () => boolean\n release: () => void\n }\n /**\n * Run a bulk transition with slot retention paused. A collapse-all or the\n * afterprint restore closes many rows in one flush; letting each one\n * `acquire()` would drain the budget in a single gesture and pin hundreds of\n * hidden subtrees. Releases still run, so reopened rows hand slots back.\n */\n pauseRetentionFor: (mutate: () => void) => void\n}\n\n/**\n * Whether `key` is `root` or sits beneath it. A literal `.` is the separator\n * even though property names may contain one (`a.b` + `c` collides with `a` +\n * `b.c`); the key is deliberately the same string as the public anchor used by\n * the sidebar, `scrollTargetId` and shared URLs, so it cannot be re-encoded alone.\n */\nconst isUnder = (key: string, root: string): boolean => root === '' || key === root || key.startsWith(`${root}.`)\n\n/**\n * Build the node key for a breadcrumb: the dot-joined anchor path, so store keys\n * and public anchors are the same string. Callers append `~`-marked structural\n * segments (`~headers`, `~anonymous-…`) for nodes the anchor cannot name.\n */\nexport const toNodeKey = (breadcrumb: readonly string[] | undefined): string => breadcrumb?.join('.') ?? ''\n\n/**\n * How many closed panels one store keeps mounted as `hidden=\"until-found\"` —\n * one `<ApiReference>`, not one tree, since every tree under it shares a store.\n */\nconst UNTIL_FOUND_CAP = 300\n\n/**\n * A per-reference store of which schema properties are open. Sparse by\n * construction: only what somebody touched, typically under twenty keys, where\n * a dense map over a large document would be tens of thousands. The maps are\n * `shallowReactive` because a Map inside a `shallowRef` does not track `.set()`\n * (clicks would do nothing) and replacing the Map wholesale would invalidate\n * every mounted row on every toggle.\n */\nexport const createSchemaExpansionStore = (scrollTargetId: Ref<string> = shallowRef('')): SchemaExpansionStore => {\n /** Only what the user explicitly opened or closed. */\n const overrides = shallowReactive(new Map<string, boolean>())\n /** Per-subtree expand-all / collapse-all roots. */\n const bulkRoots = shallowReactive(new Map<string, boolean>())\n const baseline = shallowRef<ExpansionBaseline>('default')\n\n /** The nearest bulk root at or above `key`, if any. */\n const nearestBulkRoot = (key: string): boolean | undefined => {\n if (bulkRoots.size === 0) {\n return undefined\n }\n\n let candidate = key\n\n while (true) {\n const value = bulkRoots.get(candidate)\n\n if (value !== undefined) {\n return value\n }\n\n const cut = candidate.lastIndexOf('.')\n\n if (cut === -1) {\n return bulkRoots.get('')\n }\n\n candidate = candidate.slice(0, cut)\n }\n }\n\n /**\n * Newest intent wins: a bulk write drops the overrides beneath its root, so\n * \"an explicit override always wins\" never becomes \"Expand all silently skips\n * every node the user has ever touched\". O(overrides), which stays small.\n */\n const clearOverridesUnder = (root: string): void => {\n for (const key of [...overrides.keys()]) {\n if (isUnder(key, root)) {\n overrides.delete(key)\n }\n }\n }\n\n /** While true, closing rows must not take until-found slots. */\n let retentionPaused = false\n\n const pauseRetentionFor = (mutate: () => void): void => {\n retentionPaused = true\n mutate()\n\n // The closes land in the same pre-render flush as the write, so the pause can lift after it.\n void nextTick(() => {\n retentionPaused = false\n })\n }\n\n const setBulk = (root: string, value: boolean): void => {\n clearOverridesUnder(root)\n\n if (root === '') {\n // A document-wide bulk action supersedes every narrower one.\n bulkRoots.clear()\n baseline.value = value ? 'expanded' : 'collapsed'\n return\n }\n\n for (const existing of [...bulkRoots.keys()]) {\n if (isUnder(existing, root)) {\n bulkRoots.delete(existing)\n }\n }\n\n bulkRoots.set(root, value)\n }\n\n const isExpanded = (key: string, ctx: ExpansionContext = {}): boolean => {\n // 1. An explicit decision by the user, O(1).\n const override = overrides.get(key)\n\n if (override !== undefined) {\n return override\n }\n\n // 2 and 3 are skipped for cyclic nodes, so bulk expansion terminates.\n if (!ctx.cyclic) {\n // 2. The nearest enclosing bulk action.\n const bulk = nearestBulkRoot(key)\n\n if (bulk !== undefined) {\n return bulk\n }\n\n // 3. The standing baseline.\n if (baseline.value === 'expanded') {\n return true\n }\n\n if (baseline.value === 'collapsed') {\n return false\n }\n }\n\n // 4. A live deep link, read here rather than at mount so a second deep link\n // into an already-rendered operation still works.\n if (isOnSchemaTargetPath(ctx.anchorPath ?? key, scrollTargetId.value)) {\n return true\n }\n\n // 5. Whatever the node would have done on its own.\n return ctx.defaultOpen ?? false\n }\n\n const setExpanded = (key: string, value: boolean): void => {\n overrides.set(key, value)\n }\n\n return {\n isExpanded,\n setExpanded,\n toggle: (key, ctx) => setExpanded(key, !isExpanded(key, ctx)),\n expandAll: (root = '') => setBulk(root, true),\n collapseAll: (root = '') => pauseRetentionFor(() => setBulk(root, false)),\n commitPath: (path: string): void => {\n if (!path) {\n return\n }\n\n // Open every ancestor and the target itself as overrides, so the expansion\n // outlives `clearScrollTarget` and stays user-collapsible.\n const segments = path.split('.')\n\n for (let index = 1; index <= segments.length; index++) {\n const prefix = segments.slice(0, index).join('.')\n overrides.set(prefix, true)\n\n /*\n * Also commit the marked form (`~headers`) of this segment: it is not a\n * literal prefix of the anchor, so it would re-collapse, and unmount the\n * landed-on row, once the scroll target cleared. Derived rather than\n * registered, because operations mount lazily and would register too\n * late. An override for a key nothing uses is inert.\n */\n const cut = prefix.lastIndexOf('.')\n\n if (cut !== -1) {\n overrides.set(`${prefix.slice(0, cut)}.~${prefix.slice(cut + 1)}`, true)\n }\n }\n },\n baseline,\n pauseRetentionFor,\n untilFound: (() => {\n let used = 0\n\n return {\n acquire: (): boolean => {\n if (retentionPaused || used >= UNTIL_FOUND_CAP) {\n return false\n }\n\n used += 1\n return true\n },\n release: (): void => {\n used = Math.max(0, used - 1)\n },\n }\n })(),\n }\n}\n\n/**\n * Marks that an enclosing Schema already owns the tree root. Nesting depth\n * cannot identify the outermost tree, because a nested Schema may mount at depth\n * 0 (an `allOf` member, or a caller that omits `depth`), and the root-only\n * features (sticky ancestor strip, keyboard navigation) must not install twice.\n */\nexport const SCHEMA_TREE_ROOT_SYMBOL: InjectionKey<boolean> = Symbol('schema-tree-root')\n\n/**\n * Create the expansion store for one `<ApiReference>` and wire up deep links.\n * The scroll target is read only after mount: it comes from a URL fragment the\n * server never sees, so committing it during SSR would make every ancestor\n * panel on a deep-linked path a hydration mismatch.\n */\nexport const useSchemaExpansion = (scrollTargetId: Ref<string> = shallowRef('')): SchemaExpansionStore => {\n const store = createSchemaExpansionStore(scrollTargetId)\n\n onMounted(() => {\n watch(\n scrollTargetId,\n (target) => {\n if (target) {\n store.commitPath(target)\n }\n },\n { immediate: true },\n )\n\n /** Print with everything expanded, then put the reader's state back. */\n let baselineBeforePrint: ExpansionBaseline | null = null\n\n const handleBeforePrint = (): void => {\n baselineBeforePrint = store.baseline.value\n store.baseline.value = 'expanded'\n }\n\n const handleAfterPrint = (): void => {\n if (baselineBeforePrint !== null) {\n // Restoring the baseline closes every row the print flip opened; none may claim a slot.\n const previous = baselineBeforePrint\n store.pauseRetentionFor(() => {\n store.baseline.value = previous\n })\n baselineBeforePrint = null\n }\n }\n\n window.addEventListener('beforeprint', handleBeforePrint)\n window.addEventListener('afterprint', handleAfterPrint)\n\n onBeforeUnmount(() => {\n window.removeEventListener('beforeprint', handleBeforePrint)\n window.removeEventListener('afterprint', handleAfterPrint)\n })\n })\n\n return store\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"schema-expansion.js","names":["isUnder","root","key","toNodeKey","breadcrumb","UNTIL_FOUND_CAP","createSchemaExpansionStore","shallowRef","overrides","shallowReactive","bulkRoots","baseline","nearestBulkRoot","candidate","value","cut","clearOverridesUnder","retentionPaused","pauseRetentionFor","mutate","nextTick","setBulk","existing","isExpanded","override","ctx","bulk","isOnSchemaTargetPath","scrollTargetId","setExpanded","path","segments","index","prefix","used","SCHEMA_TREE_ROOT_SYMBOL","useSchemaExpansion","store","onMounted","target","baselineBeforePrint","handleBeforePrint","handleAfterPrint","previous","onBeforeUnmount"],"sources":["../../../src/schema/helpers/schema-expansion.ts"],"sourcesContent":["import {\n type InjectionKey,\n type Ref,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowReactive,\n shallowRef,\n watch,\n} from 'vue'\n\nimport { isOnSchemaTargetPath } from './is-on-schema-target-path'\n\n/**\n * What a node does when nobody has expressed an opinion about it: its own\n * `defaultOpen`, or whatever expand-all / collapse-all last set.\n */\ntype ExpansionBaseline = 'default' | 'expanded' | 'collapsed'\n\n/** What the store cannot work out about a node on its own. */\ntype ExpansionContext = {\n /**\n * Whether this node sits on a `$ref` cycle. Bulk expansion and the baseline\n * skip cyclic nodes; without that, `expandAll()` on a self-referential schema\n * never terminates, because the cycle guard only suppresses auto-expansion.\n */\n cyclic?: boolean\n /** What the node would do with no store at all (its `defaultOpen`). */\n defaultOpen?: boolean\n /**\n * The public anchor path this node covers, when it differs from its key. A\n * key carrying a structural marker (`~headers`) must still open for a deep\n * link written against the anchor path (`…headers.X-Rate`).\n */\n anchorPath?: string\n}\n\n/** Shared expansion controls for a host and its schema trees. */\nexport type SchemaExpansionStore = {\n /** Resolve whether a node is open. See the resolution order below. */\n isExpanded: (key: string, ctx?: ExpansionContext) => boolean\n /** Record an explicit user decision about one node. */\n setExpanded: (key: string, value: boolean) => void\n /** Flip one node, resolving its current state first. */\n toggle: (key: string, ctx?: ExpansionContext) => void\n /** Expand everything, or everything beneath `root`. */\n expandAll: (root?: string) => void\n /** Collapse everything, or everything beneath `root`. */\n collapseAll: (root?: string) => void\n /** Make a deep link's expansion permanent by opening every ancestor of `path`. */\n commitPath: (path: string) => void\n /** The standing baseline, exposed so a print hook can flip it and put it back. */\n baseline: Ref<ExpansionBaseline>\n /**\n * The budget for closed panels kept in the DOM as `hidden=\"until-found\"`. It\n * lives on the store, so it is shared by every schema tree under one reference.\n * Kept panels stay searchable with find-in-page but grow the DOM, so a closing\n * row asks `acquire()` first and simply unmounts past the cap. Deliberately\n * not reactive: it only matters at the moment a panel closes.\n */\n untilFound: {\n acquire: () => boolean\n release: () => void\n }\n /**\n * Run a bulk transition with slot retention paused. A collapse-all or the\n * afterprint restore closes many rows in one flush; letting each one\n * `acquire()` would drain the budget in a single gesture and pin hundreds of\n * hidden subtrees. Releases still run, so reopened rows hand slots back.\n */\n pauseRetentionFor: (mutate: () => void) => void\n}\n\n/**\n * Whether `key` is `root` or sits beneath it. A literal `.` is the separator\n * even though property names may contain one (`a.b` + `c` collides with `a` +\n * `b.c`); the key is deliberately the same string as the public anchor used by\n * the sidebar, `scrollTargetId` and shared URLs, so it cannot be re-encoded alone.\n */\nconst isUnder = (key: string, root: string): boolean => root === '' || key === root || key.startsWith(`${root}.`)\n\n/**\n * Build the node key for a breadcrumb: the dot-joined anchor path, so store keys\n * and public anchors are the same string. Callers append `~`-marked structural\n * segments (`~headers`, `~anonymous-…`) for nodes the anchor cannot name.\n */\nexport const toNodeKey = (breadcrumb: readonly string[] | undefined): string => breadcrumb?.join('.') ?? ''\n\n/**\n * How many closed panels one store keeps mounted as `hidden=\"until-found\"` —\n * one `<ApiReference>`, not one tree, since every tree under it shares a store.\n */\nconst UNTIL_FOUND_CAP = 300\n\n/**\n * A per-reference store of which schema properties are open. Sparse by\n * construction: only what somebody touched, typically under twenty keys, where\n * a dense map over a large document would be tens of thousands. The maps are\n * `shallowReactive` because a Map inside a `shallowRef` does not track `.set()`\n * (clicks would do nothing) and replacing the Map wholesale would invalidate\n * every mounted row on every toggle.\n */\nexport const createSchemaExpansionStore = (scrollTargetId: Ref<string> = shallowRef('')): SchemaExpansionStore => {\n /** Only what the user explicitly opened or closed. */\n const overrides = shallowReactive(new Map<string, boolean>())\n /** Per-subtree expand-all / collapse-all roots. */\n const bulkRoots = shallowReactive(new Map<string, boolean>())\n const baseline = shallowRef<ExpansionBaseline>('default')\n\n /** The nearest bulk root at or above `key`, if any. */\n const nearestBulkRoot = (key: string): boolean | undefined => {\n if (bulkRoots.size === 0) {\n return undefined\n }\n\n let candidate = key\n\n while (true) {\n const value = bulkRoots.get(candidate)\n\n if (value !== undefined) {\n return value\n }\n\n const cut = candidate.lastIndexOf('.')\n\n if (cut === -1) {\n return bulkRoots.get('')\n }\n\n candidate = candidate.slice(0, cut)\n }\n }\n\n /**\n * Newest intent wins: a bulk write drops the overrides beneath its root, so\n * \"an explicit override always wins\" never becomes \"Expand all silently skips\n * every node the user has ever touched\". O(overrides), which stays small.\n */\n const clearOverridesUnder = (root: string): void => {\n for (const key of [...overrides.keys()]) {\n if (isUnder(key, root)) {\n overrides.delete(key)\n }\n }\n }\n\n /** While true, closing rows must not take until-found slots. */\n let retentionPaused = false\n\n const pauseRetentionFor = (mutate: () => void): void => {\n retentionPaused = true\n mutate()\n\n // The closes land in the same pre-render flush as the write, so the pause can lift after it.\n void nextTick(() => {\n retentionPaused = false\n })\n }\n\n const setBulk = (root: string, value: boolean): void => {\n clearOverridesUnder(root)\n\n if (root === '') {\n // A document-wide bulk action supersedes every narrower one.\n bulkRoots.clear()\n baseline.value = value ? 'expanded' : 'collapsed'\n return\n }\n\n for (const existing of [...bulkRoots.keys()]) {\n if (isUnder(existing, root)) {\n bulkRoots.delete(existing)\n }\n }\n\n bulkRoots.set(root, value)\n }\n\n const isExpanded = (key: string, ctx: ExpansionContext = {}): boolean => {\n // 1. An explicit decision by the user, O(1).\n const override = overrides.get(key)\n\n if (override !== undefined) {\n return override\n }\n\n // 2 and 3 are skipped for cyclic nodes, so bulk expansion terminates.\n if (!ctx.cyclic) {\n // 2. The nearest enclosing bulk action.\n const bulk = nearestBulkRoot(key)\n\n if (bulk !== undefined) {\n return bulk\n }\n\n // 3. The standing baseline.\n if (baseline.value === 'expanded') {\n return true\n }\n\n if (baseline.value === 'collapsed') {\n return false\n }\n }\n\n // 4. A live deep link, read here rather than at mount so a second deep link\n // into an already-rendered operation still works.\n if (isOnSchemaTargetPath(ctx.anchorPath ?? key, scrollTargetId.value)) {\n return true\n }\n\n // 5. Whatever the node would have done on its own.\n return ctx.defaultOpen ?? false\n }\n\n const setExpanded = (key: string, value: boolean): void => {\n overrides.set(key, value)\n }\n\n return {\n isExpanded,\n setExpanded,\n toggle: (key, ctx) => setExpanded(key, !isExpanded(key, ctx)),\n expandAll: (root = '') => setBulk(root, true),\n collapseAll: (root = '') => pauseRetentionFor(() => setBulk(root, false)),\n commitPath: (path: string): void => {\n if (!path) {\n return\n }\n\n // Open every ancestor and the target itself as overrides, so the expansion\n // outlives `clearScrollTarget` and stays user-collapsible.\n const segments = path.split('.')\n\n for (let index = 1; index <= segments.length; index++) {\n const prefix = segments.slice(0, index).join('.')\n overrides.set(prefix, true)\n\n /*\n * Also commit the marked form (`~headers`) of this segment: it is not a\n * literal prefix of the anchor, so it would re-collapse, and unmount the\n * landed-on row, once the scroll target cleared. Derived rather than\n * registered, because operations mount lazily and would register too\n * late. An override for a key nothing uses is inert.\n */\n const cut = prefix.lastIndexOf('.')\n\n if (cut !== -1) {\n overrides.set(`${prefix.slice(0, cut)}.~${prefix.slice(cut + 1)}`, true)\n }\n }\n },\n baseline,\n pauseRetentionFor,\n untilFound: (() => {\n let used = 0\n\n return {\n acquire: (): boolean => {\n if (retentionPaused || used >= UNTIL_FOUND_CAP) {\n return false\n }\n\n used += 1\n return true\n },\n release: (): void => {\n used = Math.max(0, used - 1)\n },\n }\n })(),\n }\n}\n\n/**\n * Marks that an enclosing Schema already owns the tree root. Nesting depth\n * cannot identify the outermost tree, because a nested Schema may mount at depth\n * 0 (an `allOf` member, or a caller that omits `depth`), and the root-only\n * features (sticky ancestor strip, keyboard navigation) must not install twice.\n */\nexport const SCHEMA_TREE_ROOT_SYMBOL: InjectionKey<boolean> = Symbol('schema-tree-root')\n\n/**\n * Create the expansion store for one `<ApiReference>` and wire up deep links.\n * The scroll target is read only after mount: it comes from a URL fragment the\n * server never sees, so committing it during SSR would make every ancestor\n * panel on a deep-linked path a hydration mismatch.\n */\nexport const useSchemaExpansion = (scrollTargetId: Ref<string> = shallowRef('')): SchemaExpansionStore => {\n const store = createSchemaExpansionStore(scrollTargetId)\n\n onMounted(() => {\n watch(\n scrollTargetId,\n (target) => {\n if (target) {\n store.commitPath(target)\n }\n },\n { immediate: true },\n )\n\n /** Print with everything expanded, then put the reader's state back. */\n let baselineBeforePrint: ExpansionBaseline | null = null\n\n const handleBeforePrint = (): void => {\n baselineBeforePrint = store.baseline.value\n store.baseline.value = 'expanded'\n }\n\n const handleAfterPrint = (): void => {\n if (baselineBeforePrint !== null) {\n // Restoring the baseline closes every row the print flip opened; none may claim a slot.\n const previous = baselineBeforePrint\n store.pauseRetentionFor(() => {\n store.baseline.value = previous\n })\n baselineBeforePrint = null\n }\n }\n\n window.addEventListener('beforeprint', handleBeforePrint)\n window.addEventListener('afterprint', handleAfterPrint)\n\n onBeforeUnmount(() => {\n window.removeEventListener('beforeprint', handleBeforePrint)\n window.removeEventListener('afterprint', handleAfterPrint)\n })\n })\n\n return store\n}\n"],"mappings":";;;AA+EA,IAAMA,KAAW,GAAa,MAA0BC,MAAS,MAAMC,MAAQD,KAAQC,EAAI,WAAW,GAAGD,EAAK,EAAE,GAOnGE,KAAa,MAAsDC,GAAY,KAAK,GAAG,KAAK,IAMnGC,IAAkB,KAUXC,KAA8B,IAA8BC,EAAW,EAAE,MAA4B;CAEhH,IAAMC,IAAYC,kBAAgB,IAAI,IAAqB,CAAC,GAEtDC,IAAYD,kBAAgB,IAAI,IAAqB,CAAC,GACtDE,IAAWJ,EAA8B,SAAS,GAGlDK,KAAmB,MAAqC;EAC5D,IAAIF,EAAU,SAAS,GACrB;EAGF,IAAIG,IAAYX;EAEhB,SAAa;GACX,IAAMY,IAAQJ,EAAU,IAAIG,CAAS;GAErC,IAAIC,MAAU,KAAA,GACZ,OAAOA;GAGT,IAAMC,IAAMF,EAAU,YAAY,GAAG;GAErC,IAAIE,MAAQ,IACV,OAAOL,EAAU,IAAI,EAAE;GAGzB,IAAYG,EAAU,MAAM,GAAGE,CAAG;EACpC;CACF,GAOMC,KAAuB,MAAuB;EAClD,KAAK,IAAMd,KAAO,CAAC,GAAGM,EAAU,KAAK,CAAC,GACpC,AAAIR,EAAQE,GAAKD,CAAI,KACnBO,EAAU,OAAON,CAAG;CAG1B,GAGIe,IAAkB,IAEhBC,KAAqB,MAA6B;EAKtD,AAJA,IAAkB,IAClBC,EAAO,GAGPC,QAAoB;GAClB,IAAkB;EACpB,CAAC;CACH,GAEMC,KAAW,GAAc,MAAyB;EAGtD,IAFAL,EAAoBf,CAAI,GAEpBA,MAAS,IAGX,AADAS,EAAU,MAAM,GAChB,EAAS,QAAQI,IAAQ,aAAa;OAIxC;QAAK,IAAMQ,KAAY,CAAC,GAAGZ,EAAU,KAAK,CAAC,GACzC,AAAIV,EAAQsB,GAAUrB,CAAI,KACxBS,EAAU,OAAOY,CAAQ;GAI7B,EAAU,IAAIrB,GAAMa,CAAK;EAJI;CAK/B,GAEMS,KAAc,GAAa,IAAwB,CAAC,MAAe;EAEvE,IAAMC,IAAWhB,EAAU,IAAIN,CAAG;EAElC,IAAIsB,MAAa,KAAA,GACf,OAAOA;EAIT,IAAI,CAACC,EAAI,QAAQ;GAEf,IAAMC,IAAOd,EAAgBV,CAAG;GAEhC,IAAIwB,MAAS,KAAA,GACX,OAAOA;GAIT,IAAIf,EAAS,UAAU,YACrB,OAAO;GAGT,IAAIA,EAAS,UAAU,aACrB,OAAO;EAEX;EASA,OALIgB,EAAqBF,EAAI,cAAcvB,GAAK0B,EAAe,KAAK,IAC3D,KAIFH,EAAI,eAAe;CAC5B,GAEMI,KAAe,GAAa,MAAyB;EACzD,EAAU,IAAI3B,GAAKY,CAAK;CAC1B;CAEA,OAAO;EACL;EACA;EACA,SAAS,GAAK,MAAQe,EAAY3B,GAAK,CAACqB,EAAWrB,GAAKuB,CAAG,CAAC;EAC5D,YAAY,IAAO,OAAOJ,EAAQpB,GAAM,EAAI;EAC5C,cAAc,IAAO,OAAOiB,QAAwBG,EAAQpB,GAAM,EAAK,CAAC;EACxE,aAAa,MAAuB;GAClC,IAAI,CAAC6B,GACH;GAKF,IAAMC,IAAWD,EAAK,MAAM,GAAG;GAE/B,KAAK,IAAIE,IAAQ,GAAGA,KAASD,EAAS,QAAQ,KAAS;IACrD,IAAME,IAASF,EAAS,MAAM,GAAGC,CAAK,CAAC,CAAC,KAAK,GAAG;IAChD,EAAU,IAAIC,GAAQ,EAAI;IAS1B,IAAMlB,IAAMkB,EAAO,YAAY,GAAG;IAElC,AAAIlB,MAAQ,MACVP,EAAU,IAAI,GAAGyB,EAAO,MAAM,GAAGlB,CAAG,EAAE,IAAIkB,EAAO,MAAMlB,IAAM,CAAC,KAAK,EAAI;GAE3E;EACF;EACA;EACA;EACA,mBAAmB;GACjB,IAAImB,IAAO;GAEX,OAAO;IACL,eACMjB,KAAmBiB,KAAQ7B,IACtB,MAGT,KAAQ,GACD;IAET,eAAqB;KACnB,IAAO,KAAK,IAAI,GAAG6B,IAAO,CAAC;IAC7B;GACF;EACF,EAAA,CAAG;CACL;AACF,GAQaC,IAAiD,OAAO,kBAAkB,GAQ1EC,KAAsB,IAA8B7B,EAAW,EAAE,MAA4B;CACxG,IAAM8B,IAAQ/B,EAA2BsB,CAAc;CAyCvD,OAvCAU,QAAgB;EACd,EACEV,IACC,MAAW;GACV,AAAIW,KACFF,EAAM,WAAWE,CAAM;EAE3B,GACA,EAAE,WAAW,GAAK,CACpB;EAGA,IAAIC,IAAgD,MAE9CC,UAAgC;GAEpC,AADA,IAAsBJ,EAAM,SAAS,OACrC,EAAM,SAAS,QAAQ;EACzB,GAEMK,UAA+B;GACnC,IAAIF,MAAwB,MAAM;IAEhC,IAAMG,IAAWH;IAIjB,AAHAH,EAAM,wBAAwB;KAC5B,EAAM,SAAS,QAAQM;IACzB,CAAC,GACD,IAAsB;GACxB;EACF;EAKA,AAHA,OAAO,iBAAiB,eAAeF,CAAiB,GACxD,OAAO,iBAAiB,cAAcC,CAAgB,GAEtDE,QAAsB;GAEpB,AADA,OAAO,oBAAoB,eAAeH,CAAiB,GAC3D,OAAO,oBAAoB,cAAcC,CAAgB;EAC3D,CAAC;CACH,CAAC,GAEML;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-keyboard-nav.js","names":[],"sources":["../../../src/schema/helpers/schema-keyboard-nav.ts"],"sourcesContent":["/**\n * Arrow-key navigation over the schema tree's disclosure toggles, behind\n * `schemaKeyboardNav`. One delegated keydown per tree root, only for a\n * `[data-schema-toggle]` target with no modifier held. The bindings follow the\n * APG tree pattern, but nothing announces them, so Tab order must stand alone.\n */\n\n/**\n * All toggles under the root that are visible right now. `offsetParent` alone\n * is not enough: a panel kept as `hidden=\"until-found\"` retains its descendants'\n * layout boxes, so their toggles pass that test while `focus()` does nothing.\n */\nconst visibleToggles = (root: HTMLElement): HTMLElement[] =>\n [...root.querySelectorAll<HTMLElement>('[data-schema-toggle]')].filter(\n (toggle) => toggle.offsetParent !== null && !toggle.closest('[hidden]'),\n )\n\n/** The toggle of the row that owns the panel this toggle's row sits inside. */\nconst parentToggle = (toggle: HTMLElement): HTMLElement | null =>\n toggle\n .closest('.property-children')\n ?.closest('.property--tree')\n ?.querySelector<HTMLElement>(':scope > [data-schema-toggle]') ?? null\n\n/** The first toggle inside this row's own panel, when one is open. */\nconst firstChildToggle = (toggle: HTMLElement): HTMLElement | null =>\n toggle.closest('.property--tree')?.querySelector<HTMLElement>(':scope > .property-children [data-schema-toggle]') ??\n null\n\n/**\n * Move focus between tree toggles in response to one keydown.\n *\n * Bind this as a keydown listener on any element that owns tree rows — the\n * schema tree itself, or the response headers group that sits beside one. The\n * listener is delegated, so the element it is bound to defines the set of rows\n * it navigates: `event.currentTarget` is the root, and only the toggles under\n * that root are reachable.\n *\n * It acts only when the event target is a `[data-schema-toggle]` element and no\n * modifier key is held, so typing and browser shortcuts pass through untouched.\n * When it does handle a key it calls `preventDefault`, which doubles as the\n * handoff between nested roots: an inner root marks the event, and any outer\n * delegate the event bubbles to leaves focus where the inner one put it.\n */\nexport const handleTreeKeydown = (event: KeyboardEvent): void => {\n const target = event.target\n\n if (\n // A nested tree root already moved focus for this key; the event keeps\n // bubbling to any outer delegate, which must not move it a second time.\n event.defaultPrevented ||\n !(target instanceof HTMLElement) ||\n !target.hasAttribute('data-schema-toggle') ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.shiftKey\n ) {\n return\n }\n\n /*\n * The root is whatever element the listener was bound to, so any surface that\n * owns tree rows can delegate here — the schema tree itself, and the response\n * headers group, which sits beside a tree rather than inside one.\n */\n const root = event.currentTarget instanceof HTMLElement ? event.currentTarget : null\n\n if (!root) {\n return\n }\n\n const toggles = visibleToggles(root)\n const index = toggles.indexOf(target)\n\n if (index === -1) {\n return\n }\n\n const isExpanded = target.getAttribute('aria-expanded') === 'true'\n\n switch (event.key) {\n case 'ArrowDown':\n toggles[index + 1]?.focus()\n break\n case 'ArrowUp':\n toggles[index - 1]?.focus()\n break\n case 'ArrowRight':\n if (!isExpanded) {\n target.click()\n } else {\n // Expanded with only leaf children — the majority case — is a no-op.\n firstChildToggle(target)?.focus()\n }\n break\n case 'ArrowLeft':\n if (isExpanded) {\n target.click()\n } else {\n parentToggle(target)?.focus()\n }\n break\n case 'Home':\n toggles[0]?.focus()\n break\n case 'End':\n toggles[toggles.length - 1]?.focus()\n break\n default:\n return\n }\n\n event.preventDefault()\n}\n"],"mappings":";AAYA,IAAM,KAAkB,MACtB,CAAC,GAAG,EAAK,iBAA8B,sBAAsB,CAAC,CAAC,CAAC,QAC7D,MAAW,EAAO,iBAAiB,QAAQ,CAAC,EAAO,QAAQ,UAAU,CACxE,GAGI,KAAgB,MACpB,EACG,QAAQ,oBAAoB,CAAC,EAC5B,QAAQ,iBAAiB,CAAC,EAC1B,cAA2B,+BAA+B,KAAK,MAG/D,KAAoB,MACxB,EAAO,QAAQ,iBAAiB,CAAC,EAAE,cAA2B,kDAAkD,KAChH,MAiBW,KAAqB,MAA+B;CAC/D,IAAM,IAAS,EAAM;CAErB,IAGE,EAAM,oBACN,EAAE,aAAkB,gBACpB,CAAC,EAAO,aAAa,oBAAoB,KACzC,EAAM,UACN,EAAM,WACN,EAAM,WACN,EAAM,UAEN;CAQF,IAAM,IAAO,EAAM,yBAAyB,cAAc,EAAM,gBAAgB;CAEhF,IAAI,CAAC,GACH;CAGF,IAAM,IAAU,EAAe,CAAI,GAC7B,IAAQ,EAAQ,QAAQ,CAAM;CAEpC,IAAI,MAAU,IACZ;CAGF,IAAM,IAAa,EAAO,aAAa,eAAe,MAAM;CAE5D,QAAQ,EAAM,KAAd;EACE,KAAK;GACH,EAAQ,IAAQ,EAAE,EAAE,MAAM;GAC1B;EACF,KAAK;GACH,EAAQ,IAAQ,EAAE,EAAE,MAAM;GAC1B;EACF,KAAK;GACH,AAAK,IAIH,EAAiB,CAAM,CAAC,EAAE,MAAM,IAHhC,EAAO,MAAM;GAKf;EACF,KAAK;GACH,AAAI,IACF,EAAO,MAAM,IAEb,EAAa,CAAM,CAAC,EAAE,MAAM;GAE9B;EACF,KAAK;GACH,EAAQ,EAAE,EAAE,MAAM;GAClB;EACF,KAAK;GACH,EAAQ,EAAQ,SAAS,EAAE,EAAE,MAAM;GACnC;EACF,SACE;CACJ;CAEA,EAAM,eAAe;AACvB"}
1
+ {"version":3,"file":"schema-keyboard-nav.js","names":["visibleToggles","root","toggle","parentToggle","firstChildToggle","handleTreeKeydown","target","event","toggles","index","isExpanded"],"sources":["../../../src/schema/helpers/schema-keyboard-nav.ts"],"sourcesContent":["/**\n * Arrow-key navigation over the schema tree's disclosure toggles, behind\n * `schemaKeyboardNav`. One delegated keydown per tree root, only for a\n * `[data-schema-toggle]` target with no modifier held. The bindings follow the\n * APG tree pattern, but nothing announces them, so Tab order must stand alone.\n */\n\n/**\n * All toggles under the root that are visible right now. `offsetParent` alone\n * is not enough: a panel kept as `hidden=\"until-found\"` retains its descendants'\n * layout boxes, so their toggles pass that test while `focus()` does nothing.\n */\nconst visibleToggles = (root: HTMLElement): HTMLElement[] =>\n [...root.querySelectorAll<HTMLElement>('[data-schema-toggle]')].filter(\n (toggle) => toggle.offsetParent !== null && !toggle.closest('[hidden]'),\n )\n\n/** The toggle of the row that owns the panel this toggle's row sits inside. */\nconst parentToggle = (toggle: HTMLElement): HTMLElement | null =>\n toggle\n .closest('.property-children')\n ?.closest('.property--tree')\n ?.querySelector<HTMLElement>(':scope > [data-schema-toggle]') ?? null\n\n/** The first toggle inside this row's own panel, when one is open. */\nconst firstChildToggle = (toggle: HTMLElement): HTMLElement | null =>\n toggle.closest('.property--tree')?.querySelector<HTMLElement>(':scope > .property-children [data-schema-toggle]') ??\n null\n\n/**\n * Move focus between tree toggles in response to one keydown.\n *\n * Bind this as a keydown listener on any element that owns tree rows — the\n * schema tree itself, or the response headers group that sits beside one. The\n * listener is delegated, so the element it is bound to defines the set of rows\n * it navigates: `event.currentTarget` is the root, and only the toggles under\n * that root are reachable.\n *\n * It acts only when the event target is a `[data-schema-toggle]` element and no\n * modifier key is held, so typing and browser shortcuts pass through untouched.\n * When it does handle a key it calls `preventDefault`, which doubles as the\n * handoff between nested roots: an inner root marks the event, and any outer\n * delegate the event bubbles to leaves focus where the inner one put it.\n */\nexport const handleTreeKeydown = (event: KeyboardEvent): void => {\n const target = event.target\n\n if (\n // A nested tree root already moved focus for this key; the event keeps\n // bubbling to any outer delegate, which must not move it a second time.\n event.defaultPrevented ||\n !(target instanceof HTMLElement) ||\n !target.hasAttribute('data-schema-toggle') ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.shiftKey\n ) {\n return\n }\n\n /*\n * The root is whatever element the listener was bound to, so any surface that\n * owns tree rows can delegate here — the schema tree itself, and the response\n * headers group, which sits beside a tree rather than inside one.\n */\n const root = event.currentTarget instanceof HTMLElement ? event.currentTarget : null\n\n if (!root) {\n return\n }\n\n const toggles = visibleToggles(root)\n const index = toggles.indexOf(target)\n\n if (index === -1) {\n return\n }\n\n const isExpanded = target.getAttribute('aria-expanded') === 'true'\n\n switch (event.key) {\n case 'ArrowDown':\n toggles[index + 1]?.focus()\n break\n case 'ArrowUp':\n toggles[index - 1]?.focus()\n break\n case 'ArrowRight':\n if (!isExpanded) {\n target.click()\n } else {\n // Expanded with only leaf children — the majority case — is a no-op.\n firstChildToggle(target)?.focus()\n }\n break\n case 'ArrowLeft':\n if (isExpanded) {\n target.click()\n } else {\n parentToggle(target)?.focus()\n }\n break\n case 'Home':\n toggles[0]?.focus()\n break\n case 'End':\n toggles[toggles.length - 1]?.focus()\n break\n default:\n return\n }\n\n event.preventDefault()\n}\n"],"mappings":";AAYA,IAAMA,KAAkB,MACtB,CAAC,GAAGC,EAAK,iBAA8B,sBAAsB,CAAC,CAAC,CAAC,QAC7D,MAAWC,EAAO,iBAAiB,QAAQ,CAACA,EAAO,QAAQ,UAAU,CACxE,GAGIC,KAAgB,MACpBD,EACG,QAAQ,oBAAoB,CAAC,EAC5B,QAAQ,iBAAiB,CAAC,EAC1B,cAA2B,+BAA+B,KAAK,MAG/DE,KAAoB,MACxBF,EAAO,QAAQ,iBAAiB,CAAC,EAAE,cAA2B,kDAAkD,KAChH,MAiBWG,KAAqB,MAA+B;CAC/D,IAAMC,IAASC,EAAM;CAErB,IAGEA,EAAM,oBACN,EAAED,aAAkB,gBACpB,CAACA,EAAO,aAAa,oBAAoB,KACzCC,EAAM,UACNA,EAAM,WACNA,EAAM,WACNA,EAAM,UAEN;CAQF,IAAMN,IAAOM,EAAM,yBAAyB,cAAcA,EAAM,gBAAgB;CAEhF,IAAI,CAACN,GACH;CAGF,IAAMO,IAAUR,EAAeC,CAAI,GAC7BQ,IAAQD,EAAQ,QAAQF,CAAM;CAEpC,IAAIG,MAAU,IACZ;CAGF,IAAMC,IAAaJ,EAAO,aAAa,eAAe,MAAM;CAE5D,QAAQC,EAAM,KAAd;EACE,KAAK;GACH,EAAQE,IAAQ,EAAE,EAAE,MAAM;GAC1B;EACF,KAAK;GACH,EAAQA,IAAQ,EAAE,EAAE,MAAM;GAC1B;EACF,KAAK;GACH,AAAKC,IAIHN,EAAiBE,CAAM,CAAC,EAAE,MAAM,IAHhCA,EAAO,MAAM;GAKf;EACF,KAAK;GACH,AAAII,IACFJ,EAAO,MAAM,IAEbH,EAAaG,CAAM,CAAC,EAAE,MAAM;GAE9B;EACF,KAAK;GACH,EAAQ,EAAE,EAAE,MAAM;GAClB;EACF,KAAK;GACH,EAAQE,EAAQ,SAAS,EAAE,EAAE,MAAM;GACnC;EACF,SACE;CACJ;CAEA,EAAM,eAAe;AACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-name.js","names":[],"sources":["../../../src/schema/helpers/schema-name.ts"],"sourcesContent":["import { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject, SchemaReferenceType } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards'\n\nimport { getRefName, getSchemaRefName } from './get-ref-name'\n\ntype SchemaModelName = {\n /**\n * The key in `components.schemas` (extracted from `$ref`), used for sidebar\n * navigation. Only set when the `$ref` actually targets\n * `#/components/schemas/`; `null` for refs into other component buckets or\n * external files, so those never render a dead link.\n */\n schemaKey: string | null\n /** The human-readable name to display (schema.title, schema.name, or ref key). */\n label: string\n}\n\n/**\n * Extract schema name from various schema formats\n *\n * Handles $ref, title, name, type, and schema dictionary lookup\n */\nexport const getModelNameFromSchema = (\n schemaOrRef: SchemaObject | SchemaReferenceType<SchemaObject>,\n): SchemaModelName | null => {\n if (!schemaOrRef || typeof schemaOrRef !== 'object') {\n return null\n }\n\n const schema = resolve.schema(schemaOrRef)\n\n // Only refs into `#/components/schemas/` are navigable in the models section.\n const schemaKey = '$ref' in schemaOrRef ? getSchemaRefName(schemaOrRef.$ref) : null\n\n if (schema.title) {\n return { schemaKey, label: schema.title }\n }\n\n if (schema.name) {\n return { schemaKey, label: schema.name }\n }\n\n if ('$ref' in schemaOrRef) {\n // Fall back to the last ref segment as a display label, even for\n // non-schema refs. The name still shows, it just is not a link.\n const label = getRefName(schemaOrRef.$ref)\n if (label) {\n return { schemaKey, label }\n }\n }\n\n return null\n}\n\n/**\n * Model name for a schema, resolving array branches too: an inline\n * `{ type: 'array', items: { $ref: Model } }` becomes `Model[]` instead of the\n * structural `array object[]`. Returns `null` when no model name applies (for\n * example an array of primitives), so callers can fall back to `getSchemaType`.\n */\nexport const getModelNameWithArray = (\n schemaOrRef: SchemaObject | SchemaReferenceType<SchemaObject>,\n): SchemaModelName | null => {\n const direct = getModelNameFromSchema(schemaOrRef)\n if (direct) {\n return direct\n }\n\n const schema = resolve.schema(schemaOrRef)\n if (isArraySchema(schema) && schema.items) {\n const itemName = getModelNameFromSchema(schema.items)\n if (itemName) {\n return { schemaKey: itemName.schemaKey, label: `${itemName.label}[]` }\n }\n }\n\n return null\n}\n"],"mappings":";;;;AAuBA,IAAa,KACX,MAC2B;CAC3B,IAAI,CAAC,KAAe,OAAO,KAAgB,UACzC,OAAO;CAGT,IAAM,IAAS,EAAQ,OAAO,CAAW,GAGnC,IAAY,UAAU,IAAc,EAAiB,EAAY,IAAI,IAAI;CAE/E,IAAI,EAAO,OACT,OAAO;EAAE;EAAW,OAAO,EAAO;CAAM;CAG1C,IAAI,EAAO,MACT,OAAO;EAAE;EAAW,OAAO,EAAO;CAAK;CAGzC,IAAI,UAAU,GAAa;EAGzB,IAAM,IAAQ,EAAW,EAAY,IAAI;EACzC,IAAI,GACF,OAAO;GAAE;GAAW;EAAM;CAE9B;CAEA,OAAO;AACT,GAQa,KACX,MAC2B;CAC3B,IAAM,IAAS,EAAuB,CAAW;CACjD,IAAI,GACF,OAAO;CAGT,IAAM,IAAS,EAAQ,OAAO,CAAW;CACzC,IAAI,EAAc,CAAM,KAAK,EAAO,OAAO;EACzC,IAAM,IAAW,EAAuB,EAAO,KAAK;EACpD,IAAI,GACF,OAAO;GAAE,WAAW,EAAS;GAAW,OAAO,GAAG,EAAS,MAAM;EAAI;CAEzE;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"schema-name.js","names":["getModelNameFromSchema","schemaOrRef","schema","resolve","schemaKey","getSchemaRefName","label","getRefName","getModelNameWithArray","direct","isArraySchema","itemName"],"sources":["../../../src/schema/helpers/schema-name.ts"],"sourcesContent":["import { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject, SchemaReferenceType } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards'\n\nimport { getRefName, getSchemaRefName } from './get-ref-name'\n\ntype SchemaModelName = {\n /**\n * The key in `components.schemas` (extracted from `$ref`), used for sidebar\n * navigation. Only set when the `$ref` actually targets\n * `#/components/schemas/`; `null` for refs into other component buckets or\n * external files, so those never render a dead link.\n */\n schemaKey: string | null\n /** The human-readable name to display (schema.title, schema.name, or ref key). */\n label: string\n}\n\n/**\n * Extract schema name from various schema formats\n *\n * Handles $ref, title, name, type, and schema dictionary lookup\n */\nexport const getModelNameFromSchema = (\n schemaOrRef: SchemaObject | SchemaReferenceType<SchemaObject>,\n): SchemaModelName | null => {\n if (!schemaOrRef || typeof schemaOrRef !== 'object') {\n return null\n }\n\n const schema = resolve.schema(schemaOrRef)\n\n // Only refs into `#/components/schemas/` are navigable in the models section.\n const schemaKey = '$ref' in schemaOrRef ? getSchemaRefName(schemaOrRef.$ref) : null\n\n if (schema.title) {\n return { schemaKey, label: schema.title }\n }\n\n if (schema.name) {\n return { schemaKey, label: schema.name }\n }\n\n if ('$ref' in schemaOrRef) {\n // Fall back to the last ref segment as a display label, even for\n // non-schema refs. The name still shows, it just is not a link.\n const label = getRefName(schemaOrRef.$ref)\n if (label) {\n return { schemaKey, label }\n }\n }\n\n return null\n}\n\n/**\n * Model name for a schema, resolving array branches too: an inline\n * `{ type: 'array', items: { $ref: Model } }` becomes `Model[]` instead of the\n * structural `array object[]`. Returns `null` when no model name applies (for\n * example an array of primitives), so callers can fall back to `getSchemaType`.\n */\nexport const getModelNameWithArray = (\n schemaOrRef: SchemaObject | SchemaReferenceType<SchemaObject>,\n): SchemaModelName | null => {\n const direct = getModelNameFromSchema(schemaOrRef)\n if (direct) {\n return direct\n }\n\n const schema = resolve.schema(schemaOrRef)\n if (isArraySchema(schema) && schema.items) {\n const itemName = getModelNameFromSchema(schema.items)\n if (itemName) {\n return { schemaKey: itemName.schemaKey, label: `${itemName.label}[]` }\n }\n }\n\n return null\n}\n"],"mappings":";;;;AAuBA,IAAaA,KACX,MAC2B;CAC3B,IAAI,CAACC,KAAe,OAAOA,KAAgB,UACzC,OAAO;CAGT,IAAMC,IAASC,EAAQ,OAAOF,CAAW,GAGnCG,IAAY,UAAUH,IAAcI,EAAiBJ,EAAY,IAAI,IAAI;CAE/E,IAAIC,EAAO,OACT,OAAO;EAAE;EAAW,OAAOA,EAAO;CAAM;CAG1C,IAAIA,EAAO,MACT,OAAO;EAAE;EAAW,OAAOA,EAAO;CAAK;CAGzC,IAAI,UAAUD,GAAa;EAGzB,IAAMK,IAAQC,EAAWN,EAAY,IAAI;EACzC,IAAIK,GACF,OAAO;GAAE;GAAW;EAAM;CAE9B;CAEA,OAAO;AACT,GAQaE,KACX,MAC2B;CAC3B,IAAMC,IAAST,EAAuBC,CAAW;CACjD,IAAIQ,GACF,OAAOA;CAGT,IAAMP,IAASC,EAAQ,OAAOF,CAAW;CACzC,IAAIS,EAAcR,CAAM,KAAKA,EAAO,OAAO;EACzC,IAAMS,IAAWX,EAAuBE,EAAO,KAAK;EACpD,IAAIS,GACF,OAAO;GAAE,WAAWA,EAAS;GAAW,OAAO,GAAGA,EAAS,MAAM;EAAI;CAEzE;CAEA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"should-display-description.js","names":[],"sources":["../../../src/schema/helpers/should-display-description.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\n/**\n * Determine if description should be displayed\n *\n * @param schema - The schema object to check\n * @param propDescription - Optional description from props\n * @returns Description string to display, or null if should not be displayed\n */\nexport const shouldDisplayDescription = (schema: SchemaObject | undefined, propDescription?: string): string | null => {\n if (!schema) {\n return null\n }\n\n // Don't show description for schemas with compositions to avoid duplicate descriptions\n if (schema.allOf) {\n return null\n }\n\n // When both an external description (e.g. a response or parameter description) and the\n // schema's own description are present, show both so neither is lost. This matters for\n // responses with multiple content types where each media type schema carries its own\n // description (see expandAllResponses). Identical descriptions are shown only once.\n if (propDescription && schema.description) {\n return propDescription === schema.description ? propDescription : `${propDescription}\\n\\n${schema.description}`\n }\n\n return propDescription || schema.description || null\n}\n"],"mappings":";AASA,IAAa,KAA4B,GAAkC,MACrE,CAAC,KAKD,EAAO,QACF,OAOL,KAAmB,EAAO,cACrB,MAAoB,EAAO,cAAc,IAAkB,GAAG,EAAgB,MAAM,EAAO,gBAG7F,KAAmB,EAAO,eAAe"}
1
+ {"version":3,"file":"should-display-description.js","names":["shouldDisplayDescription","schema","propDescription"],"sources":["../../../src/schema/helpers/should-display-description.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\n/**\n * Determine if description should be displayed\n *\n * @param schema - The schema object to check\n * @param propDescription - Optional description from props\n * @returns Description string to display, or null if should not be displayed\n */\nexport const shouldDisplayDescription = (schema: SchemaObject | undefined, propDescription?: string): string | null => {\n if (!schema) {\n return null\n }\n\n // Don't show description for schemas with compositions to avoid duplicate descriptions\n if (schema.allOf) {\n return null\n }\n\n // When both an external description (e.g. a response or parameter description) and the\n // schema's own description are present, show both so neither is lost. This matters for\n // responses with multiple content types where each media type schema carries its own\n // description (see expandAllResponses). Identical descriptions are shown only once.\n if (propDescription && schema.description) {\n return propDescription === schema.description ? propDescription : `${propDescription}\\n\\n${schema.description}`\n }\n\n return propDescription || schema.description || null\n}\n"],"mappings":";AASA,IAAaA,KAA4B,GAAkC,MACrE,CAACC,KAKDA,EAAO,QACF,OAOLC,KAAmBD,EAAO,cACrBC,MAAoBD,EAAO,cAAcC,IAAkB,GAAGA,EAAgB,MAAMD,EAAO,gBAG7FC,KAAmBD,EAAO,eAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"should-display-heading.js","names":[],"sources":["../../../src/schema/helpers/should-display-heading.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\n/**\n * Determine if property heading should be displayed\n *\n * @param schema - The schema object to check\n * @param name - Optional property name\n * @param required - Whether the property is required\n * @returns true if heading should be displayed, false otherwise\n */\nexport const shouldDisplayHeading = (schema: SchemaObject | undefined, name?: string, required = false): boolean => {\n // Early return for simple cases\n if (name || required) {\n return true\n }\n\n // If schema is undefined, return false\n if (!schema) {\n return false\n }\n\n // Check schema properties that warrant a heading\n return (\n schema.deprecated === true ||\n schema.const !== undefined ||\n schema.enum?.length === 1 ||\n ('type' in schema && schema.type !== undefined) ||\n ('nullable' in schema && schema.nullable === true) ||\n schema.writeOnly === true ||\n schema.readOnly === true\n )\n}\n"],"mappings":";AAUA,IAAa,KAAwB,GAAkC,GAAe,IAAW,OAE3F,KAAQ,IACH,KAIJ,IAMH,EAAO,eAAe,MACtB,EAAO,UAAU,KAAA,KACjB,EAAO,MAAM,WAAW,KACvB,UAAU,KAAU,EAAO,SAAS,KAAA,KACpC,cAAc,KAAU,EAAO,aAAa,MAC7C,EAAO,cAAc,MACrB,EAAO,aAAa,KAXb"}
1
+ {"version":3,"file":"should-display-heading.js","names":["shouldDisplayHeading","name","required","schema"],"sources":["../../../src/schema/helpers/should-display-heading.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\n/**\n * Determine if property heading should be displayed\n *\n * @param schema - The schema object to check\n * @param name - Optional property name\n * @param required - Whether the property is required\n * @returns true if heading should be displayed, false otherwise\n */\nexport const shouldDisplayHeading = (schema: SchemaObject | undefined, name?: string, required = false): boolean => {\n // Early return for simple cases\n if (name || required) {\n return true\n }\n\n // If schema is undefined, return false\n if (!schema) {\n return false\n }\n\n // Check schema properties that warrant a heading\n return (\n schema.deprecated === true ||\n schema.const !== undefined ||\n schema.enum?.length === 1 ||\n ('type' in schema && schema.type !== undefined) ||\n ('nullable' in schema && schema.nullable === true) ||\n schema.writeOnly === true ||\n schema.readOnly === true\n )\n}\n"],"mappings":";AAUA,IAAaA,KAAwB,GAAkC,GAAe,IAAW,OAE3FC,KAAQC,IACH,KAIJC,IAMHA,EAAO,eAAe,MACtBA,EAAO,UAAU,KAAA,KACjBA,EAAO,MAAM,WAAW,KACvB,UAAUA,KAAUA,EAAO,SAAS,KAAA,KACpC,cAAcA,KAAUA,EAAO,aAAa,MAC7CA,EAAO,cAAc,MACrBA,EAAO,aAAa,KAXb"}
@@ -1 +1 @@
1
- {"version":3,"file":"should-render-array-item-composition.js","names":[],"sources":["../../../src/schema/helpers/should-render-array-item-composition.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards'\n\nimport { hasComplexArrayItems } from './has-complex-array-items'\n\n/**\n * Check if array item composition should be rendered\n *\n * @param schema - The schema object to check\n * @param composition - The composition keyword to check for\n * @returns true if array item composition should be rendered, false otherwise\n */\nexport const shouldRenderArrayItemComposition = (schema: SchemaObject | undefined, composition: string): boolean => {\n // Early return if schema is invalid or not an array\n if (!schema || !isArraySchema(schema)) {\n return false\n }\n\n // Check if items exist and have the composition keyword\n const items = schema.items\n if (!items || typeof items !== 'object' || !(composition in items)) {\n return false\n }\n\n // Only render if items are not complex (complex items are handled differently)\n return !hasComplexArrayItems(schema)\n}\n"],"mappings":";;;AAYA,IAAa,KAAoC,GAAkC,MAAiC;CAElH,IAAI,CAAC,KAAU,CAAC,EAAc,CAAM,GAClC,OAAO;CAIT,IAAM,IAAQ,EAAO;CAMrB,OALI,CAAC,KAAS,OAAO,KAAU,YAAY,EAAE,KAAe,KACnD,KAIF,CAAC,EAAqB,CAAM;AACrC"}
1
+ {"version":3,"file":"should-render-array-item-composition.js","names":["shouldRenderArrayItemComposition","schema","isArraySchema","items","composition","hasComplexArrayItems"],"sources":["../../../src/schema/helpers/should-render-array-item-composition.ts"],"sourcesContent":["import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards'\n\nimport { hasComplexArrayItems } from './has-complex-array-items'\n\n/**\n * Check if array item composition should be rendered\n *\n * @param schema - The schema object to check\n * @param composition - The composition keyword to check for\n * @returns true if array item composition should be rendered, false otherwise\n */\nexport const shouldRenderArrayItemComposition = (schema: SchemaObject | undefined, composition: string): boolean => {\n // Early return if schema is invalid or not an array\n if (!schema || !isArraySchema(schema)) {\n return false\n }\n\n // Check if items exist and have the composition keyword\n const items = schema.items\n if (!items || typeof items !== 'object' || !(composition in items)) {\n return false\n }\n\n // Only render if items are not complex (complex items are handled differently)\n return !hasComplexArrayItems(schema)\n}\n"],"mappings":";;;AAYA,IAAaA,KAAoC,GAAkC,MAAiC;CAElH,IAAI,CAACC,KAAU,CAACC,EAAcD,CAAM,GAClC,OAAO;CAIT,IAAME,IAAQF,EAAO;CAMrB,OALI,CAACE,KAAS,OAAOA,KAAU,YAAY,EAAEC,KAAeD,KACnD,KAIF,CAACE,EAAqBJ,CAAM;AACrC"}