@scalar/api-client 3.19.3 → 3.21.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 (433) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/dist/components/HttpMethod/HttpMethod.vue.d.ts +2 -2
  3. package/dist/components/HttpMethod/HttpMethod.vue.d.ts.map +1 -1
  4. package/dist/components/HttpMethod/HttpMethod.vue.js +1 -1
  5. package/dist/components/HttpMethod/HttpMethod.vue.js.map +1 -1
  6. package/dist/components/HttpMethod/HttpMethod.vue.script.js +15 -7
  7. package/dist/components/HttpMethod/HttpMethod.vue.script.js.map +1 -1
  8. package/dist/components/SectionFilter.vue.d.ts +2 -0
  9. package/dist/components/SectionFilter.vue.d.ts.map +1 -1
  10. package/dist/components/SectionFilter.vue.js +1 -1
  11. package/dist/components/SectionFilter.vue.js.map +1 -1
  12. package/dist/components/SectionFilter.vue.script.js +11 -8
  13. package/dist/components/SectionFilter.vue.script.js.map +1 -1
  14. package/dist/components/Server/ServerVariablesSelect.vue.d.ts.map +1 -1
  15. package/dist/components/Server/ServerVariablesSelect.vue.js.map +1 -1
  16. package/dist/components/Server/ServerVariablesSelect.vue.script.js +5 -3
  17. package/dist/components/Server/ServerVariablesSelect.vue.script.js.map +1 -1
  18. package/dist/components/Server/ServerVariablesTextbox.vue.d.ts.map +1 -1
  19. package/dist/components/Server/ServerVariablesTextbox.vue.js.map +1 -1
  20. package/dist/components/Server/ServerVariablesTextbox.vue.script.js +6 -3
  21. package/dist/components/Server/ServerVariablesTextbox.vue.script.js.map +1 -1
  22. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.d.ts.map +1 -1
  23. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.js.map +1 -1
  24. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.script.js +4 -2
  25. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.script.js.map +1 -1
  26. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.d.ts.map +1 -1
  27. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.js.map +1 -1
  28. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.script.js +3 -1
  29. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.script.js.map +1 -1
  30. package/dist/style.css +164 -141
  31. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +3 -2
  32. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
  33. package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
  34. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +16 -3
  35. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
  36. package/dist/v2/blocks/operation-block/components/Header.vue.d.ts +1 -2
  37. package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
  38. package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
  39. package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
  40. package/dist/v2/blocks/operation-block/components/Header.vue.script.js +10 -6
  41. package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
  42. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.d.ts.map +1 -1
  43. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.js +1 -1
  44. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.js.map +1 -1
  45. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.script.js +6 -3
  46. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.script.js.map +1 -1
  47. package/dist/v2/blocks/operation-block/helpers/har-to-fetch-response.d.ts +1 -2
  48. package/dist/v2/blocks/operation-block/helpers/har-to-fetch-response.d.ts.map +1 -1
  49. package/dist/v2/blocks/operation-block/helpers/har-to-fetch-response.js.map +1 -1
  50. package/dist/v2/blocks/operation-block/helpers/send-request.d.ts +1 -2
  51. package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
  52. package/dist/v2/blocks/operation-block/helpers/send-request.js +4 -3
  53. package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
  54. package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts +3 -2
  55. package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts.map +1 -1
  56. package/dist/v2/blocks/request-block/RequestBlock.vue.js +1 -1
  57. package/dist/v2/blocks/request-block/RequestBlock.vue.js.map +1 -1
  58. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +59 -26
  59. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
  60. package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
  61. package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
  62. package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
  63. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +28 -8
  64. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
  65. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.d.ts.map +1 -1
  66. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.js.map +1 -1
  67. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js +9 -3
  68. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js.map +1 -1
  69. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.d.ts.map +1 -1
  70. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.js.map +1 -1
  71. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.script.js +6 -4
  72. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.script.js.map +1 -1
  73. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
  74. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
  75. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +13 -4
  76. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
  77. package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts +2 -0
  78. package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts.map +1 -1
  79. package/dist/v2/blocks/request-block/components/RequestParams.vue.js.map +1 -1
  80. package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js +14 -7
  81. package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js.map +1 -1
  82. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +6 -6
  83. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
  84. package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
  85. package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
  86. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js +40 -7
  87. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
  88. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +16 -16
  89. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
  90. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
  91. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +24 -20
  92. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
  93. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.d.ts.map +1 -1
  94. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.js.map +1 -1
  95. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js +6 -4
  96. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js.map +1 -1
  97. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.d.ts.map +1 -1
  98. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js +14 -6
  99. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js.map +1 -1
  100. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.d.ts.map +1 -1
  101. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +5 -4
  102. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js.map +1 -1
  103. package/dist/v2/blocks/response-block/ResponseBlock.vue.d.ts.map +1 -1
  104. package/dist/v2/blocks/response-block/ResponseBlock.vue.js +1 -1
  105. package/dist/v2/blocks/response-block/ResponseBlock.vue.js.map +1 -1
  106. package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js +34 -13
  107. package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js.map +1 -1
  108. package/dist/v2/blocks/response-block/components/Headers.vue.d.ts +3 -3
  109. package/dist/v2/blocks/response-block/components/Headers.vue.d.ts.map +1 -1
  110. package/dist/v2/blocks/response-block/components/Headers.vue.js.map +1 -1
  111. package/dist/v2/blocks/response-block/components/Headers.vue.script.js +5 -3
  112. package/dist/v2/blocks/response-block/components/Headers.vue.script.js.map +1 -1
  113. package/dist/v2/blocks/response-block/components/ResponseBody.vue.d.ts.map +1 -1
  114. package/dist/v2/blocks/response-block/components/ResponseBody.vue.js +1 -1
  115. package/dist/v2/blocks/response-block/components/ResponseBody.vue.js.map +1 -1
  116. package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js +3 -1
  117. package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js.map +1 -1
  118. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.d.ts.map +1 -1
  119. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.js.map +1 -1
  120. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.script.js +11 -3
  121. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.script.js.map +1 -1
  122. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.d.ts.map +1 -1
  123. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.js +1 -1
  124. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.js.map +1 -1
  125. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.script.js +8 -6
  126. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.script.js.map +1 -1
  127. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.d.ts +1 -0
  128. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.d.ts.map +1 -1
  129. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.js.map +1 -1
  130. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.script.js +109 -56
  131. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.script.js.map +1 -1
  132. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.d.ts.map +1 -1
  133. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.js.map +1 -1
  134. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.script.js +5 -3
  135. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.script.js.map +1 -1
  136. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.d.ts.map +1 -1
  137. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.js.map +1 -1
  138. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.script.js +6 -3
  139. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.script.js.map +1 -1
  140. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.d.ts.map +1 -1
  141. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.js.map +1 -1
  142. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js +7 -5
  143. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js.map +1 -1
  144. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.d.ts +2 -2
  145. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.d.ts.map +1 -1
  146. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.js +1 -1
  147. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.js.map +1 -1
  148. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.script.js +20 -15
  149. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.script.js.map +1 -1
  150. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.d.ts.map +1 -1
  151. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.js +1 -1
  152. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.js.map +1 -1
  153. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.script.js +4 -2
  154. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.script.js.map +1 -1
  155. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.d.ts.map +1 -1
  156. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.js.map +1 -1
  157. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.script.js +11 -6
  158. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.script.js.map +1 -1
  159. package/dist/v2/blocks/response-block/helpers/response-stream-multipart.d.ts +4 -0
  160. package/dist/v2/blocks/response-block/helpers/response-stream-multipart.d.ts.map +1 -0
  161. package/dist/v2/blocks/response-block/helpers/response-stream-multipart.js +100 -0
  162. package/dist/v2/blocks/response-block/helpers/response-stream-multipart.js.map +1 -0
  163. package/dist/v2/blocks/response-block/helpers/response-stream.d.ts +13 -0
  164. package/dist/v2/blocks/response-block/helpers/response-stream.d.ts.map +1 -0
  165. package/dist/v2/blocks/response-block/helpers/response-stream.js +97 -0
  166. package/dist/v2/blocks/response-block/helpers/response-stream.js.map +1 -0
  167. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts +2 -3
  168. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
  169. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
  170. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
  171. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +41 -29
  172. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
  173. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.d.ts +6 -7
  174. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.d.ts.map +1 -1
  175. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js +1 -1
  176. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js.map +1 -1
  177. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js +7 -4
  178. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js.map +1 -1
  179. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.d.ts.map +1 -1
  180. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.js.map +1 -1
  181. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js +21 -16
  182. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js.map +1 -1
  183. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.d.ts.map +1 -1
  184. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.js.map +1 -1
  185. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js +7 -5
  186. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
  187. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.d.ts.map +1 -1
  188. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.js.map +1 -1
  189. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.script.js +7 -5
  190. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.script.js.map +1 -1
  191. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
  192. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
  193. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +105 -40
  194. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
  195. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.d.ts.map +1 -1
  196. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.js.map +1 -1
  197. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.script.js +10 -8
  198. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.script.js.map +1 -1
  199. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.d.ts.map +1 -1
  200. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.js.map +1 -1
  201. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js +20 -14
  202. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js.map +1 -1
  203. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.d.ts.map +1 -1
  204. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.js.map +1 -1
  205. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js +6 -4
  206. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js.map +1 -1
  207. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.d.ts.map +1 -1
  208. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.js.map +1 -1
  209. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.script.js +3 -1
  210. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.script.js.map +1 -1
  211. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
  212. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
  213. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js +40 -40
  214. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
  215. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.d.ts +108 -7
  216. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.d.ts.map +1 -1
  217. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.js +12 -0
  218. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.js.map +1 -1
  219. package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts.map +1 -1
  220. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.d.ts.map +1 -1
  221. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js +8 -5
  222. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js.map +1 -1
  223. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts +2 -0
  224. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts.map +1 -1
  225. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js +2 -0
  226. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js.map +1 -1
  227. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.d.ts +3 -0
  228. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.d.ts.map +1 -0
  229. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.js +8 -0
  230. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.js.map +1 -0
  231. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.d.ts +3 -0
  232. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.d.ts.map +1 -0
  233. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.js +11 -0
  234. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.js.map +1 -0
  235. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.d.ts +19 -0
  236. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.d.ts.map +1 -0
  237. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js +117 -0
  238. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js.map +1 -0
  239. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts +2 -1
  240. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts.map +1 -1
  241. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +15 -11
  242. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
  243. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts +1 -1
  244. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts.map +1 -1
  245. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js +8 -1
  246. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js.map +1 -1
  247. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.d.ts.map +1 -1
  248. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js +6 -0
  249. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js.map +1 -1
  250. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts +2 -1
  251. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts.map +1 -1
  252. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js +8 -6
  253. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js.map +1 -1
  254. package/dist/v2/components/code-input/CodeInput.vue.d.ts +4 -4
  255. package/dist/v2/components/code-input/CodeInput.vue.d.ts.map +1 -1
  256. package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
  257. package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
  258. package/dist/v2/components/code-input/CodeInput.vue.script.js +10 -10
  259. package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
  260. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts +4 -4
  261. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -1
  262. package/dist/v2/components/code-input/CodeInputLite.vue.js +1 -1
  263. package/dist/v2/components/code-input/CodeInputLite.vue.js.map +1 -1
  264. package/dist/v2/components/code-input/CodeInputLite.vue.script.js +8 -5
  265. package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -1
  266. package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts +4 -0
  267. package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts.map +1 -1
  268. package/dist/v2/components/code-input/PillTooltipHost.vue.js.map +1 -1
  269. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js +7 -3
  270. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js.map +1 -1
  271. package/dist/v2/components/code-input/code-variable-widget.d.ts +3 -0
  272. package/dist/v2/components/code-input/code-variable-widget.d.ts.map +1 -1
  273. package/dist/v2/components/code-input/code-variable-widget.js +6 -3
  274. package/dist/v2/components/code-input/code-variable-widget.js.map +1 -1
  275. package/dist/v2/components/data-table/DataTable.vue.d.ts.map +1 -1
  276. package/dist/v2/components/data-table/DataTable.vue.js.map +1 -1
  277. package/dist/v2/components/data-table/DataTable.vue.script.js +2 -1
  278. package/dist/v2/components/data-table/DataTable.vue.script.js.map +1 -1
  279. package/dist/v2/components/data-table/DataTableCheckbox.vue.d.ts +0 -1
  280. package/dist/v2/components/data-table/DataTableCheckbox.vue.d.ts.map +1 -1
  281. package/dist/v2/components/data-table/DataTableCheckbox.vue.js.map +1 -1
  282. package/dist/v2/components/data-table/DataTableCheckbox.vue.script.js +4 -2
  283. package/dist/v2/components/data-table/DataTableCheckbox.vue.script.js.map +1 -1
  284. package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
  285. package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
  286. package/dist/v2/components/data-table/DataTableInput.vue.js.map +1 -1
  287. package/dist/v2/components/data-table/DataTableInput.vue.script.js +5 -3
  288. package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
  289. package/dist/v2/components/data-table/DataTableInputSelect.vue.d.ts.map +1 -1
  290. package/dist/v2/components/data-table/DataTableInputSelect.vue.js.map +1 -1
  291. package/dist/v2/components/data-table/DataTableInputSelect.vue.script.js +12 -9
  292. package/dist/v2/components/data-table/DataTableInputSelect.vue.script.js.map +1 -1
  293. package/dist/v2/components/forms/ConfirmationForm.vue.d.ts.map +1 -1
  294. package/dist/v2/components/forms/ConfirmationForm.vue.js.map +1 -1
  295. package/dist/v2/components/forms/ConfirmationForm.vue.script.js +5 -3
  296. package/dist/v2/components/forms/ConfirmationForm.vue.script.js.map +1 -1
  297. package/dist/v2/components/layout/CollapsibleSection.vue.d.ts.map +1 -1
  298. package/dist/v2/components/layout/CollapsibleSection.vue.js.map +1 -1
  299. package/dist/v2/components/layout/CollapsibleSection.vue.script.js +3 -1
  300. package/dist/v2/components/layout/CollapsibleSection.vue.script.js.map +1 -1
  301. package/dist/v2/components/modals/DeleteModal.vue.d.ts.map +1 -1
  302. package/dist/v2/components/modals/DeleteModal.vue.js.map +1 -1
  303. package/dist/v2/components/modals/DeleteModal.vue.script.js +3 -1
  304. package/dist/v2/components/modals/DeleteModal.vue.script.js.map +1 -1
  305. package/dist/v2/components/modals/ModalClientContainer.vue.d.ts.map +1 -1
  306. package/dist/v2/components/modals/ModalClientContainer.vue.js +1 -1
  307. package/dist/v2/components/modals/ModalClientContainer.vue.js.map +1 -1
  308. package/dist/v2/components/modals/ModalClientContainer.vue.script.js +5 -2
  309. package/dist/v2/components/modals/ModalClientContainer.vue.script.js.map +1 -1
  310. package/dist/v2/components/server/ServerDropdown.vue.d.ts.map +1 -1
  311. package/dist/v2/components/server/ServerDropdown.vue.js.map +1 -1
  312. package/dist/v2/components/server/ServerDropdown.vue.script.js +9 -5
  313. package/dist/v2/components/server/ServerDropdown.vue.script.js.map +1 -1
  314. package/dist/v2/components/sidebar/Sidebar.vue.d.ts.map +1 -1
  315. package/dist/v2/components/sidebar/Sidebar.vue.js.map +1 -1
  316. package/dist/v2/components/sidebar/Sidebar.vue.script.js +4 -2
  317. package/dist/v2/components/sidebar/Sidebar.vue.script.js.map +1 -1
  318. package/dist/v2/components/sidebar/SidebarMenu.vue.d.ts.map +1 -1
  319. package/dist/v2/components/sidebar/SidebarMenu.vue.js.map +1 -1
  320. package/dist/v2/components/sidebar/SidebarMenu.vue.script.js +4 -2
  321. package/dist/v2/components/sidebar/SidebarMenu.vue.script.js.map +1 -1
  322. package/dist/v2/components/sidebar/SidebarToggle.vue.d.ts.map +1 -1
  323. package/dist/v2/components/sidebar/SidebarToggle.vue.js.map +1 -1
  324. package/dist/v2/components/sidebar/SidebarToggle.vue.script.js +4 -2
  325. package/dist/v2/components/sidebar/SidebarToggle.vue.script.js.map +1 -1
  326. package/dist/v2/constants.js +1 -1
  327. package/dist/v2/features/command-palette/components/CommandActionForm.vue.d.ts.map +1 -1
  328. package/dist/v2/features/command-palette/components/CommandActionForm.vue.js.map +1 -1
  329. package/dist/v2/features/command-palette/components/CommandActionForm.vue.script.js +4 -2
  330. package/dist/v2/features/command-palette/components/CommandActionForm.vue.script.js.map +1 -1
  331. package/dist/v2/features/command-palette/components/CommandActionInput.vue.d.ts +2 -2
  332. package/dist/v2/features/environments/EnvironmentsList.vue.d.ts.map +1 -1
  333. package/dist/v2/features/environments/EnvironmentsList.vue.js.map +1 -1
  334. package/dist/v2/features/environments/EnvironmentsList.vue.script.js +4 -2
  335. package/dist/v2/features/environments/EnvironmentsList.vue.script.js.map +1 -1
  336. package/dist/v2/features/environments/components/Environment.vue.d.ts.map +1 -1
  337. package/dist/v2/features/environments/components/Environment.vue.js.map +1 -1
  338. package/dist/v2/features/environments/components/Environment.vue.script.js +12 -10
  339. package/dist/v2/features/environments/components/Environment.vue.script.js.map +1 -1
  340. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.d.ts.map +1 -1
  341. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.js.map +1 -1
  342. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.script.js +5 -3
  343. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.script.js.map +1 -1
  344. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.d.ts.map +1 -1
  345. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.js.map +1 -1
  346. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.script.js +9 -6
  347. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.script.js.map +1 -1
  348. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.d.ts.map +1 -1
  349. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.js.map +1 -1
  350. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js +6 -4
  351. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js.map +1 -1
  352. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.d.ts.map +1 -1
  353. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js +1 -1
  354. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js.map +1 -1
  355. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js +22 -10
  356. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js.map +1 -1
  357. package/dist/v2/features/localization/index.d.ts +18 -0
  358. package/dist/v2/features/localization/index.d.ts.map +1 -0
  359. package/dist/v2/features/localization/index.js +35 -0
  360. package/dist/v2/features/localization/index.js.map +1 -0
  361. package/dist/v2/features/localization/locales/ar.d.ts +389 -0
  362. package/dist/v2/features/localization/locales/ar.d.ts.map +1 -0
  363. package/dist/v2/features/localization/locales/ar.js +351 -0
  364. package/dist/v2/features/localization/locales/ar.js.map +1 -0
  365. package/dist/v2/features/localization/locales/de.d.ts +389 -0
  366. package/dist/v2/features/localization/locales/de.d.ts.map +1 -0
  367. package/dist/v2/features/localization/locales/de.js +351 -0
  368. package/dist/v2/features/localization/locales/de.js.map +1 -0
  369. package/dist/v2/features/localization/locales/es.d.ts +389 -0
  370. package/dist/v2/features/localization/locales/es.d.ts.map +1 -0
  371. package/dist/v2/features/localization/locales/es.js +351 -0
  372. package/dist/v2/features/localization/locales/es.js.map +1 -0
  373. package/dist/v2/features/localization/locales/fr.d.ts +389 -0
  374. package/dist/v2/features/localization/locales/fr.d.ts.map +1 -0
  375. package/dist/v2/features/localization/locales/fr.js +351 -0
  376. package/dist/v2/features/localization/locales/fr.js.map +1 -0
  377. package/dist/v2/features/localization/locales/pt.d.ts +389 -0
  378. package/dist/v2/features/localization/locales/pt.d.ts.map +1 -0
  379. package/dist/v2/features/localization/locales/pt.js +351 -0
  380. package/dist/v2/features/localization/locales/pt.js.map +1 -0
  381. package/dist/v2/features/localization/locales/ru.d.ts +389 -0
  382. package/dist/v2/features/localization/locales/ru.d.ts.map +1 -0
  383. package/dist/v2/features/localization/locales/ru.js +351 -0
  384. package/dist/v2/features/localization/locales/ru.js.map +1 -0
  385. package/dist/v2/features/localization/locales/zh-cn.d.ts +389 -0
  386. package/dist/v2/features/localization/locales/zh-cn.d.ts.map +1 -0
  387. package/dist/v2/features/localization/locales/zh-cn.js +351 -0
  388. package/dist/v2/features/localization/locales/zh-cn.js.map +1 -0
  389. package/dist/v2/features/localization/translations.d.ts +389 -0
  390. package/dist/v2/features/localization/translations.d.ts.map +1 -0
  391. package/dist/v2/features/localization/translations.js +351 -0
  392. package/dist/v2/features/localization/translations.js.map +1 -0
  393. package/dist/v2/features/modal/Modal.vue.d.ts +1 -2
  394. package/dist/v2/features/modal/Modal.vue.d.ts.map +1 -1
  395. package/dist/v2/features/modal/Modal.vue.js.map +1 -1
  396. package/dist/v2/features/modal/Modal.vue.script.js +15 -4
  397. package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
  398. package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts +2 -3
  399. package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts.map +1 -1
  400. package/dist/v2/features/modal/helpers/resolve-route-parameters.js +8 -7
  401. package/dist/v2/features/modal/helpers/resolve-route-parameters.js.map +1 -1
  402. package/dist/v2/features/modal/hooks/use-modal-sidebar.d.ts +2 -3
  403. package/dist/v2/features/modal/hooks/use-modal-sidebar.d.ts.map +1 -1
  404. package/dist/v2/features/modal/hooks/use-modal-sidebar.js.map +1 -1
  405. package/dist/v2/features/modal/use-lazy-api-client.d.ts +11 -0
  406. package/dist/v2/features/modal/use-lazy-api-client.d.ts.map +1 -0
  407. package/dist/v2/features/modal/use-lazy-api-client.js +48 -0
  408. package/dist/v2/features/modal/use-lazy-api-client.js.map +1 -0
  409. package/dist/v2/features/operation/Operation.vue.d.ts +1 -2
  410. package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
  411. package/dist/v2/features/operation/Operation.vue.js.map +1 -1
  412. package/dist/v2/features/operation/Operation.vue.script.js +22 -6
  413. package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
  414. package/dist/v2/features/search/components/DocumentSearchModal.vue.d.ts.map +1 -1
  415. package/dist/v2/features/search/components/DocumentSearchModal.vue.js +1 -1
  416. package/dist/v2/features/search/components/DocumentSearchModal.vue.js.map +1 -1
  417. package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js +12 -8
  418. package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js.map +1 -1
  419. package/dist/v2/features/search/components/SearchResult.vue.d.ts.map +1 -1
  420. package/dist/v2/features/search/components/SearchResult.vue.js.map +1 -1
  421. package/dist/v2/features/search/components/SearchResult.vue.script.js +14 -10
  422. package/dist/v2/features/search/components/SearchResult.vue.script.js.map +1 -1
  423. package/dist/v2/helpers/generate-location-id.d.ts +1 -2
  424. package/dist/v2/helpers/generate-location-id.d.ts.map +1 -1
  425. package/dist/v2/helpers/generate-location-id.js.map +1 -1
  426. package/dist/v2/types/options.d.ts +1 -1
  427. package/dist/v2/types/options.d.ts.map +1 -1
  428. package/dist/v2/workspace-events.d.ts +2 -2
  429. package/dist/v2/workspace-events.d.ts.map +1 -1
  430. package/dist/v2/workspace-events.js +8 -1
  431. package/dist/v2/workspace-events.js.map +1 -1
  432. package/dist/vue-styles.css +128 -129
  433. package/package.json +22 -11
@@ -1 +1 @@
1
- {"version":3,"file":"Header.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/components/Header.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n Operation block header: address bar, environment selector, and modal controls.\n\n Renders the top bar for the API client operation view: URL/method (AddressBar),\n optional environment selector, optional \"Open API Client\" button in modal layout,\n and close button for modal. Layout and visibility depend on `layout` and `source` props.\n */\nexport type HeaderProps = {\n /** An external example must finish loading before sending. */\n executionDisabled?: boolean\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethod\n /** Whether this request comes from an OpenAPI webhook. */\n isWebhook?: boolean\n /** Client layout */\n layout: ClientLayout\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document slug */\n documentSlug: string\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Currently selected server */\n server: ServerObject | null\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** List of request history */\n history: History[]\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** Environment variables */\n environment: XScalarEnvironment\n /** Meta information for the server */\n serverMeta: ServerMeta\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconGearSix } from '@scalar/icons'\nimport type {\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { AddressBar, type History } from '@/v2/blocks/scalar-address-bar-block'\nimport EnvironmentSelector from '@/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport OpenApiClientButton from './OpenApiClientButton.vue'\n\nconst {\n hideClientButton = false,\n eventBus,\n exampleKey,\n documentSlug,\n} = defineProps<HeaderProps>()\n\nconst emit = defineEmits<{\n /** Execute the current operation example */\n (e: 'execute'): void\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n /** Add a new environment */\n (e: 'add:environment'): void\n /** Navigate to the settings page for the current entity */\n (e: 'navigate:settings'): void\n /** Update the full destination URL used to deliver a webhook. */\n (e: 'update:webhook-url', url: string): void\n}>()\n\nconst handleSelectEnvironment = (environmentName: string) => {\n eventBus.emit('workspace:update:active-environment', environmentName)\n}\n\nconst handleAddEnvironment = () => {\n eventBus.emit('ui:navigate', { page: 'document', path: 'environment' })\n}\n</script>\n\n<template>\n <!--\n `@container` declares an unnamed container so the AddressBar can\n adapt to the right column's actual width (which shrinks when the\n sidebar opens) instead of the viewport. The query is declared here\n on the parent rather than on the AddressBar itself so the bar's\n `w-full` mobile state cannot feed back into its own breakpoint.\n -->\n <div\n class=\"lg:min-h-header t-app__top-container @container flex w-full flex-wrap items-center justify-center p-2\">\n <!-- Left spacer to center bar -->\n <div class=\"flex flex-1\"></div>\n <AddressBar\n :activeEnvironment\n :documentSlug\n :environment\n :environments\n :eventBus\n :exampleKey\n :executionDisabled\n :history\n :isWebhook\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n @add:environment=\"emit('add:environment')\"\n @execute=\"emit('execute')\"\n @select:history:item=\"(payload) => emit('select:history:item', payload)\"\n @update:webhook-url=\"(value) => emit('update:webhook-url', value)\" />\n\n <div class=\"mb-2 flex flex-1 items-center justify-end gap-2 @3xl:mb-0\">\n <!--\n Environment Selector\n Hidden for `modal` layout\n -->\n <EnvironmentSelector\n v-if=\"layout !== 'modal'\"\n :activeEnvironment=\"activeEnvironment\"\n :environments=\"environments\"\n @add:environment=\"handleAddEnvironment\"\n @select:environment=\"handleSelectEnvironment\" />\n <!-- Operation settings -->\n <ScalarIconButton\n v-if=\"layout !== 'modal' && !isWebhook\"\n :icon=\"ScalarIconGearSix\"\n label=\"Operation settings\"\n size=\"sm\"\n weight=\"bold\"\n @click=\"emit('navigate:settings')\" />\n <!--\n Open API Client Button\n\n Only shown in `modal` layout\n -->\n <OpenApiClientButton\n v-if=\"layout === 'modal' && documentUrl && !hideClientButton\"\n buttonSource=\"modal\"\n class=\"!w-fit lg:-mr-1\"\n :integration=\"integration ?? null\"\n :operationMethod=\"method\"\n :operationPath=\"path\"\n :source=\"source ?? 'api-reference'\"\n :url=\"documentUrl\" />\n\n <!--\n Close Button\n\n Only shown in `modal` layout and hidden for GitBook Integration\n -->\n <button\n v-if=\"layout === 'modal' && source !== 'gitbook'\"\n class=\"app-exit-button zoomed:static zoomed:p-1 fixed top-2 right-2 rounded-full p-2\"\n type=\"button\"\n @click=\"eventBus.emit('ui:close:client-modal')\">\n <ScalarIcon\n icon=\"Close\"\n size=\"lg\"\n thickness=\"2\" />\n <span class=\"sr-only\">Close Client</span>\n </button>\n\n <!--\n Close Button for GitBook Integration\n\n Hidden by default and visible for GitBook Integration in `modal` layout\n -->\n <button\n v-if=\"layout === 'modal' && source === 'gitbook'\"\n class=\"text-c-1 hover:bg-b-2 active:text-c-1 -mr-1.5 rounded p-2\"\n type=\"button\"\n @click=\"eventBus.emit('ui:close:client-modal')\">\n <ScalarIcon\n icon=\"Close\"\n size=\"md\"\n thickness=\"1.75\" />\n <span class=\"sr-only\">Close Client</span>\n </button>\n </div>\n </div>\n</template>\n<style scoped>\n.app-exit-button {\n color: white;\n background: rgba(0, 0, 0, 0.1);\n}\n.app-exit-button:hover {\n background: rgba(255, 255, 255, 0.1);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2EA,MAAM,OAAO;EAab,MAAM,2BAA2B,oBAA4B;GAC3D,QAAA,SAAS,KAAK,uCAAuC,eAAe;EACtE;EAEA,MAAM,6BAA6B;GACjC,QAAA,SAAS,KAAK,eAAe;IAAE,MAAM;IAAY,MAAM;GAAc,CAAC;EACxE;;uBAWE,mBA6FM,OA7FN,YA6FM;8BA1FJ,mBAA+B,OAAA,EAA1B,OAAM,cAAa,GAAA,MAAA,EAAA;IACxB,YAmBuE,MAAA,kBAAA,GAAA;KAlBpE,mBAAA,QAAA;KACA,cAAA,QAAA;KACA,aAAA,QAAA;KACA,cAAA,QAAA;KACA,UAAA,QAAA;KACA,YAAA,QAAA;KACA,mBAAA,QAAA;KACA,SAAA,QAAA;KACA,WAAA,QAAA;KACA,QAAA,QAAA;KACA,QAAA,QAAA;KACA,MAAA,QAAA;KACA,QAAA,QAAA;KACA,YAAA,QAAA;KACA,SAAA,QAAA;KACA,qBAAe,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,iBAAA;KACrB,WAAO,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,SAAA;KACb,yBAAmB,OAAA,OAAA,OAAA,MAAG,YAAY,KAAI,uBAAwB,OAAO;KACrE,uBAAkB,OAAA,OAAA,OAAA,MAAG,UAAU,KAAI,sBAAuB,KAAK;;;;;;;;;;;;;;;;;;IAElE,mBAmEM,OAnEN,YAmEM;KA7DI,QAAA,WAAM,WAAA,UAAA,GADd,YAKkD,6BAAA;;MAH/C,mBAAmB,QAAA;MACnB,cAAc,QAAA;MACd,qBAAiB;MACjB,wBAAoB;;KAGf,QAAA,WAAM,WAAA,CAAiB,QAAA,aAAA,UAAA,GAD/B,YAMuC,MAAA,gBAAA,GAAA;;MAJpC,MAAM,MAAA,iBAAA;MACP,OAAM;MACN,MAAK;MACL,QAAO;MACN,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,mBAAA;;KAON,QAAA,WAAM,WAAgB,QAAA,eAAW,CAAK,QAAA,oBAAA,UAAA,GAD9C,YAQuB,6BAAA;;MANrB,cAAa;MACb,OAAM;MACL,aAAa,QAAA,eAAW;MACxB,iBAAiB,QAAA;MACjB,eAAe,QAAA;MACf,QAAQ,QAAA,UAAM;MACd,KAAK,QAAA;;;;;;;;KAQA,QAAA,WAAM,WAAgB,QAAA,WAAM,aAAA,UAAA,GADpC,mBAUS,UAAA;;MARP,OAAM;MACN,MAAK;MACJ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,SAAS,KAAI,uBAAA;SACrB,YAGkB,MAAA,UAAA,GAAA;MAFhB,MAAK;MACL,MAAK;MACL,WAAU;mCACZ,mBAAyC,QAAA,EAAnC,OAAM,UAAS,GAAC,gBAAY,EAAA,EAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;KAS5B,QAAA,WAAM,WAAgB,QAAA,WAAM,aAAA,UAAA,GADpC,mBAUS,UAAA;;MARP,OAAM;MACN,MAAK;MACJ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,SAAS,KAAI,uBAAA;SACrB,YAGqB,MAAA,UAAA,GAAA;MAFnB,MAAK;MACL,MAAK;MACL,WAAU;mCACZ,mBAAyC,QAAA,EAAnC,OAAM,UAAS,GAAC,gBAAY,EAAA,EAAA,CAAA,KAAA,mBAAA,IAAA,IAAA"}
1
+ {"version":3,"file":"Header.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/components/Header.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n Operation block header: address bar, environment selector, and modal controls.\n\n Renders the top bar for the API client operation view: URL/method (AddressBar),\n optional environment selector, optional \"Open API Client\" button in modal layout,\n and close button for modal. Layout and visibility depend on `layout` and `source` props.\n */\nexport type HeaderProps = {\n /** An external example must finish loading before sending. */\n executionDisabled?: boolean\n /** Current request path */\n path: string\n /** Current request method */\n method: string\n /** Whether this request comes from an OpenAPI webhook. */\n isWebhook?: boolean\n /** Client layout */\n layout: ClientLayout\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document slug */\n documentSlug: string\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Currently selected server */\n server: ServerObject | null\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** List of request history */\n history: History[]\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** Environment variables */\n environment: XScalarEnvironment\n /** Meta information for the server */\n serverMeta: ServerMeta\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { ScalarIconGearSix } from '@scalar/icons'\nimport type {\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { AddressBar, type History } from '@/v2/blocks/scalar-address-bar-block'\nimport EnvironmentSelector from '@/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue'\nimport { useLocalization } from '@/v2/features/localization'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport OpenApiClientButton from './OpenApiClientButton.vue'\n\nconst {\n hideClientButton = false,\n eventBus,\n exampleKey,\n documentSlug,\n} = defineProps<HeaderProps>()\n\nconst emit = defineEmits<{\n /** Execute the current operation example */\n (e: 'execute'): void\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n /** Add a new environment */\n (e: 'add:environment'): void\n /** Navigate to the settings page for the current entity */\n (e: 'navigate:settings'): void\n /** Update the full destination URL used to deliver a webhook. */\n (e: 'update:webhook-url', url: string): void\n}>()\n\nconst { translate } = useLocalization()\n\nconst handleSelectEnvironment = (environmentName: string) => {\n eventBus.emit('workspace:update:active-environment', environmentName)\n}\n\nconst handleAddEnvironment = () => {\n eventBus.emit('ui:navigate', { page: 'document', path: 'environment' })\n}\n</script>\n\n<template>\n <!--\n `@container` declares an unnamed container so the AddressBar can\n adapt to the right column's actual width (which shrinks when the\n sidebar opens) instead of the viewport. The query is declared here\n on the parent rather than on the AddressBar itself so the bar's\n `w-full` mobile state cannot feed back into its own breakpoint.\n -->\n <div\n class=\"lg:min-h-header t-app__top-container @container flex w-full flex-wrap items-center justify-center p-2\">\n <!-- Left spacer to center bar -->\n <div class=\"flex flex-1\"></div>\n <AddressBar\n :activeEnvironment\n :documentSlug\n :environment\n :environments\n :eventBus\n :exampleKey\n :executionDisabled\n :history\n :isWebhook\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n @add:environment=\"emit('add:environment')\"\n @execute=\"emit('execute')\"\n @select:history:item=\"(payload) => emit('select:history:item', payload)\"\n @update:webhook-url=\"(value) => emit('update:webhook-url', value)\" />\n\n <div class=\"mb-2 flex flex-1 items-center justify-end gap-2 @3xl:mb-0\">\n <!--\n Environment Selector\n Hidden for `modal` layout\n -->\n <EnvironmentSelector\n v-if=\"layout !== 'modal'\"\n :activeEnvironment=\"activeEnvironment\"\n :environments=\"environments\"\n @add:environment=\"handleAddEnvironment\"\n @select:environment=\"handleSelectEnvironment\" />\n <!-- Operation settings -->\n <ScalarIconButton\n v-if=\"layout !== 'modal' && !isWebhook\"\n :icon=\"ScalarIconGearSix\"\n :label=\"translate('apiClient.header.operationSettings')\"\n size=\"sm\"\n weight=\"bold\"\n @click=\"emit('navigate:settings')\" />\n <!--\n Open API Client Button\n\n Only shown in `modal` layout\n -->\n <OpenApiClientButton\n v-if=\"layout === 'modal' && documentUrl && !hideClientButton\"\n buttonSource=\"modal\"\n class=\"!w-fit lg:-mr-1\"\n :integration=\"integration ?? null\"\n :operationMethod=\"method\"\n :operationPath=\"path\"\n :source=\"source ?? 'api-reference'\"\n :url=\"documentUrl\" />\n\n <!--\n Close Button\n\n Only shown in `modal` layout and hidden for GitBook Integration\n -->\n <button\n v-if=\"layout === 'modal' && source !== 'gitbook'\"\n class=\"app-exit-button zoomed:static zoomed:p-1 fixed top-2 right-2 rounded-full p-2\"\n type=\"button\"\n @click=\"eventBus.emit('ui:close:client-modal')\">\n <ScalarIcon\n icon=\"Close\"\n size=\"lg\"\n thickness=\"2\" />\n <span class=\"sr-only\">{{\n translate('apiClient.header.closeClient')\n }}</span>\n </button>\n\n <!--\n Close Button for GitBook Integration\n\n Hidden by default and visible for GitBook Integration in `modal` layout\n -->\n <button\n v-if=\"layout === 'modal' && source === 'gitbook'\"\n class=\"text-c-1 hover:bg-b-2 active:text-c-1 -mr-1.5 rounded p-2\"\n type=\"button\"\n @click=\"eventBus.emit('ui:close:client-modal')\">\n <ScalarIcon\n icon=\"Close\"\n size=\"md\"\n thickness=\"1.75\" />\n <span class=\"sr-only\">{{\n translate('apiClient.header.closeClient')\n }}</span>\n </button>\n </div>\n </div>\n</template>\n<style scoped>\n.app-exit-button {\n color: white;\n background: rgba(0, 0, 0, 0.1);\n}\n.app-exit-button:hover {\n background: rgba(255, 255, 255, 0.1);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2EA,MAAM,OAAO;EAab,MAAM,EAAE,cAAc,gBAAgB;EAEtC,MAAM,2BAA2B,oBAA4B;GAC3D,QAAA,SAAS,KAAK,uCAAuC,eAAe;EACtE;EAEA,MAAM,6BAA6B;GACjC,QAAA,SAAS,KAAK,eAAe;IAAE,MAAM;IAAY,MAAM;GAAc,CAAC;EACxE;;uBAWE,mBAiGM,OAjGN,YAiGM;8BA9FJ,mBAA+B,OAAA,EAA1B,OAAM,cAAa,GAAA,MAAA,EAAA;IACxB,YAmBuE,MAAA,kBAAA,GAAA;KAlBpE,mBAAA,QAAA;KACA,cAAA,QAAA;KACA,aAAA,QAAA;KACA,cAAA,QAAA;KACA,UAAA,QAAA;KACA,YAAA,QAAA;KACA,mBAAA,QAAA;KACA,SAAA,QAAA;KACA,WAAA,QAAA;KACA,QAAA,QAAA;KACA,QAAA,QAAA;KACA,MAAA,QAAA;KACA,QAAA,QAAA;KACA,YAAA,QAAA;KACA,SAAA,QAAA;KACA,qBAAe,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,iBAAA;KACrB,WAAO,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,SAAA;KACb,yBAAmB,OAAA,OAAA,OAAA,MAAG,YAAY,KAAI,uBAAwB,OAAO;KACrE,uBAAkB,OAAA,OAAA,OAAA,MAAG,UAAU,KAAI,sBAAuB,KAAK;;;;;;;;;;;;;;;;;;IAElE,mBAuEM,OAvEN,YAuEM;KAjEI,QAAA,WAAM,WAAA,UAAA,GADd,YAKkD,6BAAA;;MAH/C,mBAAmB,QAAA;MACnB,cAAc,QAAA;MACd,qBAAiB;MACjB,wBAAoB;;KAGf,QAAA,WAAM,WAAA,CAAiB,QAAA,aAAA,UAAA,GAD/B,YAMuC,MAAA,gBAAA,GAAA;;MAJpC,MAAM,MAAA,iBAAA;MACN,OAAO,MAAA,SAAA,CAAS,CAAA,oCAAA;MACjB,MAAK;MACL,QAAO;MACN,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,mBAAA;;KAON,QAAA,WAAM,WAAgB,QAAA,eAAW,CAAK,QAAA,oBAAA,UAAA,GAD9C,YAQuB,6BAAA;;MANrB,cAAa;MACb,OAAM;MACL,aAAa,QAAA,eAAW;MACxB,iBAAiB,QAAA;MACjB,eAAe,QAAA;MACf,QAAQ,QAAA,UAAM;MACd,KAAK,QAAA;;;;;;;;KAQA,QAAA,WAAM,WAAgB,QAAA,WAAM,aAAA,UAAA,GADpC,mBAYS,UAAA;;MAVP,OAAM;MACN,MAAK;MACJ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,SAAS,KAAI,uBAAA;SACrB,YAGkB,MAAA,UAAA,GAAA;MAFhB,MAAK;MACL,MAAK;MACL,WAAU;SACZ,mBAES,QAFT,YAES,gBADP,MAAA,SAAA,CAAS,CAAA,8BAAA,CAAA,GAAA,CAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;KAUL,QAAA,WAAM,WAAgB,QAAA,WAAM,aAAA,UAAA,GADpC,mBAYS,UAAA;;MAVP,OAAM;MACN,MAAK;MACJ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,SAAS,KAAI,uBAAA;SACrB,YAGqB,MAAA,UAAA,GAAA;MAFnB,MAAK;MACL,MAAK;MACL,WAAU;SACZ,mBAES,QAFT,YAES,gBADP,MAAA,SAAA,CAAS,CAAA,8BAAA,CAAA,GAAA,CAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"OpenApiClientButton.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/components/OpenApiClientButton.vue"],"names":[],"mappings":"AAsIA,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,SAAS,GAAG,OAAO,CAAA;IACjC,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACpC,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAC;AAsHF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"OpenApiClientButton.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/components/OpenApiClientButton.vue"],"names":[],"mappings":"AAqJA,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,SAAS,GAAG,OAAO,CAAA;IACjC,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACpC,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAC;AAkIF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_
2
2
  import OpenApiClientButton_vue_vue_type_script_setup_true_lang_default from "./OpenApiClientButton.vue.script.js";
3
3
  /* empty css */
4
4
  //#region src/v2/blocks/operation-block/components/OpenApiClientButton.vue
5
- var OpenApiClientButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default(OpenApiClientButton_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-cd067f84"]]);
5
+ var OpenApiClientButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default(OpenApiClientButton_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-746e7aef"]]);
6
6
  //#endregion
7
7
  export { OpenApiClientButton_default as default };
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"OpenApiClientButton.vue.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/components/OpenApiClientButton.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { ScalarIconArrowUpRight } from '@scalar/icons'\nimport { computed } from 'vue'\n\nconst {\n integration,\n isDevelopment,\n url,\n operationPath,\n operationMethod,\n buttonSource,\n source = 'api-reference',\n} = defineProps<{\n buttonSource: 'sidebar' | 'modal'\n source?: 'api-reference' | 'gitbook'\n isDevelopment?: boolean\n integration?: string | null\n url?: string\n /** Operation path to open in the client after import */\n operationPath?: string\n /** HTTP method for the operation to open in the client after import */\n operationMethod?: string\n}>()\n\n/** Link to import an OpenAPI document */\nconst href = computed((): string | undefined => {\n /**\n * The URL we want to pass to client.scalar.com for the import.\n * Might be an OpenAPI document URL, but could also just be the URL of the API reference.\n */\n const urlToImportFrom =\n url ?? (typeof window !== 'undefined' ? window.location.href : undefined)\n\n if (!urlToImportFrom) {\n return undefined\n }\n\n const absoluteUrl = makeUrlAbsolute(urlToImportFrom)\n\n if (!absoluteUrl?.length) {\n return undefined\n }\n\n // Base URL\n const link = new URL(\n isDevelopment ? 'http://localhost:5065' : 'https://client.scalar.com',\n )\n\n // URL that we'd like to import\n link.searchParams.set('url', absoluteUrl)\n\n if (operationPath?.length && operationMethod?.length) {\n link.searchParams.set('operation_path', operationPath)\n link.searchParams.set('operation_method', operationMethod.toLowerCase())\n }\n\n // Integration identifier\n if (integration !== null) {\n link.searchParams.set('integration', integration ?? 'vue')\n }\n\n // UTM Source\n link.searchParams.set('utm_source', 'api-reference')\n link.searchParams.set('utm_medium', 'button')\n link.searchParams.set('utm_campaign', buttonSource)\n\n // Special for gitbook, set the source and grab the logos (hacky)\n if (source === 'gitbook') {\n link.searchParams.set('utm_source', 'gitbook')\n\n const darkLogo = document.querySelector(\"img.dark\\\\:block[alt='Logo']\")\n const lightLogo = document.querySelector(\"img.dark\\\\:hidden[alt='Logo']\")\n\n if (darkLogo && darkLogo instanceof HTMLImageElement) {\n link.searchParams.set('dark_logo', encodeURIComponent(darkLogo.src))\n }\n if (lightLogo && lightLogo instanceof HTMLImageElement) {\n link.searchParams.set('light_logo', encodeURIComponent(lightLogo.src))\n }\n }\n\n return link.toString()\n})\n</script>\n\n<template>\n <a\n v-if=\"href\"\n class=\"open-api-client-button\"\n :href=\"href\"\n target=\"_blank\">\n <ScalarIconArrowUpRight\n class=\"size-3\"\n weight=\"regular\" />\n Open API Client\n </a>\n</template>\n\n<style scoped>\n.open-api-client-button {\n cursor: pointer;\n width: 100%;\n padding: 9px 12px;\n height: 31px;\n display: block;\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n white-space: nowrap;\n font-size: var(--scalar-small);\n line-height: 1.385;\n text-decoration: none;\n border-radius: var(--scalar-radius);\n box-shadow: 0 0 0 0.5px var(--scalar-border-color);\n gap: 6px;\n color: var(--scalar-sidebar-color-1);\n}\n\n.open-api-client-button:hover {\n background: var(\n --scalar-sidebar-item-hover-background,\n var(--scalar-background-2)\n );\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"OpenApiClientButton.vue.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/components/OpenApiClientButton.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { ScalarIconArrowUpRight } from '@scalar/icons'\nimport { computed } from 'vue'\n\nimport { useLocalization } from '@/v2/features/localization'\n\nconst {\n integration,\n isDevelopment,\n url,\n operationPath,\n operationMethod,\n buttonSource,\n source = 'api-reference',\n} = defineProps<{\n buttonSource: 'sidebar' | 'modal'\n source?: 'api-reference' | 'gitbook'\n isDevelopment?: boolean\n integration?: string | null\n url?: string\n /** Operation path to open in the client after import */\n operationPath?: string\n /** HTTP method for the operation to open in the client after import */\n operationMethod?: string\n}>()\n\nconst { translate } = useLocalization()\n\n/** Link to import an OpenAPI document */\nconst href = computed((): string | undefined => {\n /**\n * The URL we want to pass to client.scalar.com for the import.\n * Might be an OpenAPI document URL, but could also just be the URL of the API reference.\n */\n const urlToImportFrom =\n url ?? (typeof window !== 'undefined' ? window.location.href : undefined)\n\n if (!urlToImportFrom) {\n return undefined\n }\n\n const absoluteUrl = makeUrlAbsolute(urlToImportFrom)\n\n if (!absoluteUrl?.length) {\n return undefined\n }\n\n // Base URL\n const link = new URL(\n isDevelopment ? 'http://localhost:5065' : 'https://client.scalar.com',\n )\n\n // URL that we'd like to import\n link.searchParams.set('url', absoluteUrl)\n\n if (operationPath?.length && operationMethod?.length) {\n link.searchParams.set('operation_path', operationPath)\n link.searchParams.set(\n 'operation_method',\n operationMethod === operationMethod.toUpperCase() &&\n isHttpMethod(operationMethod)\n ? operationMethod.toLowerCase()\n : operationMethod,\n )\n }\n\n // Integration identifier\n if (integration !== null) {\n link.searchParams.set('integration', integration ?? 'vue')\n }\n\n // UTM Source\n link.searchParams.set('utm_source', 'api-reference')\n link.searchParams.set('utm_medium', 'button')\n link.searchParams.set('utm_campaign', buttonSource)\n\n // Special for gitbook, set the source and grab the logos (hacky)\n if (source === 'gitbook') {\n link.searchParams.set('utm_source', 'gitbook')\n\n const darkLogo = document.querySelector(\"img.dark\\\\:block[alt='Logo']\")\n const lightLogo = document.querySelector(\"img.dark\\\\:hidden[alt='Logo']\")\n\n if (darkLogo && darkLogo instanceof HTMLImageElement) {\n link.searchParams.set('dark_logo', encodeURIComponent(darkLogo.src))\n }\n if (lightLogo && lightLogo instanceof HTMLImageElement) {\n link.searchParams.set('light_logo', encodeURIComponent(lightLogo.src))\n }\n }\n\n return link.toString()\n})\n</script>\n\n<template>\n <a\n v-if=\"href\"\n class=\"open-api-client-button\"\n :href=\"href\"\n target=\"_blank\">\n <ScalarIconArrowUpRight\n class=\"size-3\"\n weight=\"regular\" />{{\n translate('apiClient.openApiClientButton.openAPIClient')\n }}</a\n >\n</template>\n\n<style scoped>\n.open-api-client-button {\n cursor: pointer;\n width: 100%;\n padding: 9px 12px;\n height: 31px;\n display: block;\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n white-space: nowrap;\n font-size: var(--scalar-small);\n line-height: 1.385;\n text-decoration: none;\n border-radius: var(--scalar-radius);\n box-shadow: 0 0 0 0.5px var(--scalar-border-color);\n gap: 6px;\n color: var(--scalar-sidebar-color-1);\n}\n\n.open-api-client-button:hover {\n background: var(\n --scalar-sidebar-item-hover-background,\n var(--scalar-background-2)\n );\n}\n</style>\n"],"mappings":""}
@@ -1,5 +1,7 @@
1
- import { computed, createCommentVNode, createElementBlock, createTextVNode, createVNode, defineComponent, openBlock, unref } from "vue";
1
+ import { useLocalization } from "../../../features/localization/index.js";
2
+ import { computed, createCommentVNode, createElementBlock, createTextVNode, createVNode, defineComponent, openBlock, toDisplayString, unref } from "vue";
2
3
  import { ScalarIconArrowUpRight } from "@scalar/icons";
4
+ import { isHttpMethod } from "@scalar/helpers/http/is-http-method";
3
5
  import { makeUrlAbsolute } from "@scalar/helpers/url/make-url-absolute";
4
6
  //#region src/v2/blocks/operation-block/components/OpenApiClientButton.vue?vue&type=script&setup=true&lang.ts
5
7
  var _hoisted_1 = ["href"];
@@ -15,6 +17,7 @@ var OpenApiClientButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
15
17
  operationMethod: {}
16
18
  },
17
19
  setup(__props) {
20
+ const { translate } = useLocalization();
18
21
  /** Link to import an OpenAPI document */
19
22
  const href = computed(() => {
20
23
  /**
@@ -29,7 +32,7 @@ var OpenApiClientButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
29
32
  link.searchParams.set("url", absoluteUrl);
30
33
  if (__props.operationPath?.length && __props.operationMethod?.length) {
31
34
  link.searchParams.set("operation_path", __props.operationPath);
32
- link.searchParams.set("operation_method", __props.operationMethod.toLowerCase());
35
+ link.searchParams.set("operation_method", __props.operationMethod === __props.operationMethod.toUpperCase() && isHttpMethod(__props.operationMethod) ? __props.operationMethod.toLowerCase() : __props.operationMethod);
33
36
  }
34
37
  if (__props.integration !== null) link.searchParams.set("integration", __props.integration ?? "vue");
35
38
  link.searchParams.set("utm_source", "api-reference");
@@ -53,7 +56,7 @@ var OpenApiClientButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
53
56
  }, [createVNode(unref(ScalarIconArrowUpRight), {
54
57
  class: "size-3",
55
58
  weight: "regular"
56
- }), _cache[0] || (_cache[0] = createTextVNode(" Open API Client ", -1))], 8, _hoisted_1)) : createCommentVNode("", true);
59
+ }), createTextVNode(toDisplayString(unref(translate)("apiClient.openApiClientButton.openAPIClient")), 1)], 8, _hoisted_1)) : createCommentVNode("", true);
57
60
  };
58
61
  }
59
62
  });
@@ -1 +1 @@
1
- {"version":3,"file":"OpenApiClientButton.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/components/OpenApiClientButton.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { ScalarIconArrowUpRight } from '@scalar/icons'\nimport { computed } from 'vue'\n\nconst {\n integration,\n isDevelopment,\n url,\n operationPath,\n operationMethod,\n buttonSource,\n source = 'api-reference',\n} = defineProps<{\n buttonSource: 'sidebar' | 'modal'\n source?: 'api-reference' | 'gitbook'\n isDevelopment?: boolean\n integration?: string | null\n url?: string\n /** Operation path to open in the client after import */\n operationPath?: string\n /** HTTP method for the operation to open in the client after import */\n operationMethod?: string\n}>()\n\n/** Link to import an OpenAPI document */\nconst href = computed((): string | undefined => {\n /**\n * The URL we want to pass to client.scalar.com for the import.\n * Might be an OpenAPI document URL, but could also just be the URL of the API reference.\n */\n const urlToImportFrom =\n url ?? (typeof window !== 'undefined' ? window.location.href : undefined)\n\n if (!urlToImportFrom) {\n return undefined\n }\n\n const absoluteUrl = makeUrlAbsolute(urlToImportFrom)\n\n if (!absoluteUrl?.length) {\n return undefined\n }\n\n // Base URL\n const link = new URL(\n isDevelopment ? 'http://localhost:5065' : 'https://client.scalar.com',\n )\n\n // URL that we'd like to import\n link.searchParams.set('url', absoluteUrl)\n\n if (operationPath?.length && operationMethod?.length) {\n link.searchParams.set('operation_path', operationPath)\n link.searchParams.set('operation_method', operationMethod.toLowerCase())\n }\n\n // Integration identifier\n if (integration !== null) {\n link.searchParams.set('integration', integration ?? 'vue')\n }\n\n // UTM Source\n link.searchParams.set('utm_source', 'api-reference')\n link.searchParams.set('utm_medium', 'button')\n link.searchParams.set('utm_campaign', buttonSource)\n\n // Special for gitbook, set the source and grab the logos (hacky)\n if (source === 'gitbook') {\n link.searchParams.set('utm_source', 'gitbook')\n\n const darkLogo = document.querySelector(\"img.dark\\\\:block[alt='Logo']\")\n const lightLogo = document.querySelector(\"img.dark\\\\:hidden[alt='Logo']\")\n\n if (darkLogo && darkLogo instanceof HTMLImageElement) {\n link.searchParams.set('dark_logo', encodeURIComponent(darkLogo.src))\n }\n if (lightLogo && lightLogo instanceof HTMLImageElement) {\n link.searchParams.set('light_logo', encodeURIComponent(lightLogo.src))\n }\n }\n\n return link.toString()\n})\n</script>\n\n<template>\n <a\n v-if=\"href\"\n class=\"open-api-client-button\"\n :href=\"href\"\n target=\"_blank\">\n <ScalarIconArrowUpRight\n class=\"size-3\"\n weight=\"regular\" />\n Open API Client\n </a>\n</template>\n\n<style scoped>\n.open-api-client-button {\n cursor: pointer;\n width: 100%;\n padding: 9px 12px;\n height: 31px;\n display: block;\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n white-space: nowrap;\n font-size: var(--scalar-small);\n line-height: 1.385;\n text-decoration: none;\n border-radius: var(--scalar-radius);\n box-shadow: 0 0 0 0.5px var(--scalar-border-color);\n gap: 6px;\n color: var(--scalar-sidebar-color-1);\n}\n\n.open-api-client-button:hover {\n background: var(\n --scalar-sidebar-item-hover-background,\n var(--scalar-background-2)\n );\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EA0BA,MAAM,OAAO,eAAmC;;;;;GAK9C,MAAM,kBACJ,QAAA,QAAQ,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO,KAAA;GAEjE,IAAI,CAAC,iBACH;GAGF,MAAM,cAAc,gBAAgB,eAAe;GAEnD,IAAI,CAAC,aAAa,QAChB;GAIF,MAAM,OAAO,IAAI,IACf,QAAA,gBAAgB,0BAA0B,2BAC5C;GAGA,KAAK,aAAa,IAAI,OAAO,WAAW;GAExC,IAAI,QAAA,eAAe,UAAU,QAAA,iBAAiB,QAAQ;IACpD,KAAK,aAAa,IAAI,kBAAkB,QAAA,aAAa;IACrD,KAAK,aAAa,IAAI,oBAAoB,QAAA,gBAAgB,YAAY,CAAC;GACzE;GAGA,IAAI,QAAA,gBAAgB,MAClB,KAAK,aAAa,IAAI,eAAe,QAAA,eAAe,KAAK;GAI3D,KAAK,aAAa,IAAI,cAAc,eAAe;GACnD,KAAK,aAAa,IAAI,cAAc,QAAQ;GAC5C,KAAK,aAAa,IAAI,gBAAgB,QAAA,YAAY;GAGlD,IAAI,QAAA,WAAW,WAAW;IACxB,KAAK,aAAa,IAAI,cAAc,SAAS;IAE7C,MAAM,WAAW,SAAS,cAAc,8BAA8B;IACtE,MAAM,YAAY,SAAS,cAAc,+BAA+B;IAExE,IAAI,YAAY,oBAAoB,kBAClC,KAAK,aAAa,IAAI,aAAa,mBAAmB,SAAS,GAAG,CAAC;IAErE,IAAI,aAAa,qBAAqB,kBACpC,KAAK,aAAa,IAAI,cAAc,mBAAmB,UAAU,GAAG,CAAC;GAEzE;GAEA,OAAO,KAAK,SAAS;EACvB,CAAC;;UAKS,KAAA,SAAA,UAAA,GADR,mBASI,KAAA;;IAPF,OAAM;IACL,MAAM,KAAA;IACP,QAAO;OACP,YAEqB,MAAA,sBAAA,GAAA;IADnB,OAAM;IACN,QAAO;iDAAY,qBAEvB,EAAA,EAAA,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA"}
1
+ {"version":3,"file":"OpenApiClientButton.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/components/OpenApiClientButton.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { ScalarIconArrowUpRight } from '@scalar/icons'\nimport { computed } from 'vue'\n\nimport { useLocalization } from '@/v2/features/localization'\n\nconst {\n integration,\n isDevelopment,\n url,\n operationPath,\n operationMethod,\n buttonSource,\n source = 'api-reference',\n} = defineProps<{\n buttonSource: 'sidebar' | 'modal'\n source?: 'api-reference' | 'gitbook'\n isDevelopment?: boolean\n integration?: string | null\n url?: string\n /** Operation path to open in the client after import */\n operationPath?: string\n /** HTTP method for the operation to open in the client after import */\n operationMethod?: string\n}>()\n\nconst { translate } = useLocalization()\n\n/** Link to import an OpenAPI document */\nconst href = computed((): string | undefined => {\n /**\n * The URL we want to pass to client.scalar.com for the import.\n * Might be an OpenAPI document URL, but could also just be the URL of the API reference.\n */\n const urlToImportFrom =\n url ?? (typeof window !== 'undefined' ? window.location.href : undefined)\n\n if (!urlToImportFrom) {\n return undefined\n }\n\n const absoluteUrl = makeUrlAbsolute(urlToImportFrom)\n\n if (!absoluteUrl?.length) {\n return undefined\n }\n\n // Base URL\n const link = new URL(\n isDevelopment ? 'http://localhost:5065' : 'https://client.scalar.com',\n )\n\n // URL that we'd like to import\n link.searchParams.set('url', absoluteUrl)\n\n if (operationPath?.length && operationMethod?.length) {\n link.searchParams.set('operation_path', operationPath)\n link.searchParams.set(\n 'operation_method',\n operationMethod === operationMethod.toUpperCase() &&\n isHttpMethod(operationMethod)\n ? operationMethod.toLowerCase()\n : operationMethod,\n )\n }\n\n // Integration identifier\n if (integration !== null) {\n link.searchParams.set('integration', integration ?? 'vue')\n }\n\n // UTM Source\n link.searchParams.set('utm_source', 'api-reference')\n link.searchParams.set('utm_medium', 'button')\n link.searchParams.set('utm_campaign', buttonSource)\n\n // Special for gitbook, set the source and grab the logos (hacky)\n if (source === 'gitbook') {\n link.searchParams.set('utm_source', 'gitbook')\n\n const darkLogo = document.querySelector(\"img.dark\\\\:block[alt='Logo']\")\n const lightLogo = document.querySelector(\"img.dark\\\\:hidden[alt='Logo']\")\n\n if (darkLogo && darkLogo instanceof HTMLImageElement) {\n link.searchParams.set('dark_logo', encodeURIComponent(darkLogo.src))\n }\n if (lightLogo && lightLogo instanceof HTMLImageElement) {\n link.searchParams.set('light_logo', encodeURIComponent(lightLogo.src))\n }\n }\n\n return link.toString()\n})\n</script>\n\n<template>\n <a\n v-if=\"href\"\n class=\"open-api-client-button\"\n :href=\"href\"\n target=\"_blank\">\n <ScalarIconArrowUpRight\n class=\"size-3\"\n weight=\"regular\" />{{\n translate('apiClient.openApiClientButton.openAPIClient')\n }}</a\n >\n</template>\n\n<style scoped>\n.open-api-client-button {\n cursor: pointer;\n width: 100%;\n padding: 9px 12px;\n height: 31px;\n display: block;\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n white-space: nowrap;\n font-size: var(--scalar-small);\n line-height: 1.385;\n text-decoration: none;\n border-radius: var(--scalar-radius);\n box-shadow: 0 0 0 0.5px var(--scalar-border-color);\n gap: 6px;\n color: var(--scalar-sidebar-color-1);\n}\n\n.open-api-client-button:hover {\n background: var(\n --scalar-sidebar-item-hover-background,\n var(--scalar-background-2)\n );\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;EA4BA,MAAM,EAAE,cAAc,gBAAgB;;EAGtC,MAAM,OAAO,eAAmC;;;;;GAK9C,MAAM,kBACJ,QAAA,QAAQ,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO,KAAA;GAEjE,IAAI,CAAC,iBACH;GAGF,MAAM,cAAc,gBAAgB,eAAe;GAEnD,IAAI,CAAC,aAAa,QAChB;GAIF,MAAM,OAAO,IAAI,IACf,QAAA,gBAAgB,0BAA0B,2BAC5C;GAGA,KAAK,aAAa,IAAI,OAAO,WAAW;GAExC,IAAI,QAAA,eAAe,UAAU,QAAA,iBAAiB,QAAQ;IACpD,KAAK,aAAa,IAAI,kBAAkB,QAAA,aAAa;IACrD,KAAK,aAAa,IAChB,oBACA,QAAA,oBAAoB,QAAA,gBAAgB,YAAY,KAC9C,aAAa,QAAA,eAAe,IAC1B,QAAA,gBAAgB,YAAY,IAC5B,QAAA,eACN;GACF;GAGA,IAAI,QAAA,gBAAgB,MAClB,KAAK,aAAa,IAAI,eAAe,QAAA,eAAe,KAAK;GAI3D,KAAK,aAAa,IAAI,cAAc,eAAe;GACnD,KAAK,aAAa,IAAI,cAAc,QAAQ;GAC5C,KAAK,aAAa,IAAI,gBAAgB,QAAA,YAAY;GAGlD,IAAI,QAAA,WAAW,WAAW;IACxB,KAAK,aAAa,IAAI,cAAc,SAAS;IAE7C,MAAM,WAAW,SAAS,cAAc,8BAA8B;IACtE,MAAM,YAAY,SAAS,cAAc,+BAA+B;IAExE,IAAI,YAAY,oBAAoB,kBAClC,KAAK,aAAa,IAAI,aAAa,mBAAmB,SAAS,GAAG,CAAC;IAErE,IAAI,aAAa,qBAAqB,kBACpC,KAAK,aAAa,IAAI,cAAc,mBAAmB,UAAU,GAAG,CAAC;GAEzE;GAEA,OAAO,KAAK,SAAS;EACvB,CAAC;;UAKS,KAAA,SAAA,UAAA,GADR,mBAUC,KAAA;;IARC,OAAM;IACL,MAAM,KAAA;IACP,QAAO;OACP,YAEqB,MAAA,sBAAA,GAAA;IADnB,OAAM;IACN,QAAO;uCACP,MAAA,SAAA,CAAS,CAAA,6CAAA,CAAA,GAAA,CAAA,CAAA,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA"}
@@ -1,4 +1,3 @@
1
- import type { HttpMethod } from '@scalar/helpers/http/http-methods';
2
1
  import type { HarResponse } from '@scalar/snippetz';
3
2
  import type { ResponseInstance } from '../../../../v2/blocks/operation-block/helpers/send-request.js';
4
3
  type HarToFetchResponseProps = {
@@ -7,7 +6,7 @@ type HarToFetchResponseProps = {
7
6
  /** Optional URL to set on the Response object */
8
7
  url?: string;
9
8
  /** The HTTP method used for the request */
10
- method: HttpMethod;
9
+ method: string;
11
10
  /** The request path */
12
11
  path: string;
13
12
  /** Time in ms the request took */
@@ -1 +1 @@
1
- {"version":3,"file":"har-to-fetch-response.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/har-to-fetch-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAA;AAExF,KAAK,uBAAuB,GAAG;IAC7B,yCAAyC;IACzC,WAAW,EAAE,WAAW,CAAA;IACxB,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,MAAM,EAAE,UAAU,CAAA;IAClB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,kBAAkB,GAAI,+CAMhC,uBAAuB,KAAG,gBAwB5B,CAAA"}
1
+ {"version":3,"file":"har-to-fetch-response.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/har-to-fetch-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAA;AAExF,KAAK,uBAAuB,GAAG;IAC7B,yCAAyC;IACzC,WAAW,EAAE,WAAW,CAAA;IACxB,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,kBAAkB,GAAI,+CAMhC,uBAAuB,KAAG,gBAwB5B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"har-to-fetch-response.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/har-to-fetch-response.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { HarResponse } from '@scalar/snippetz'\n\nimport { getCookieHeaderKeys } from '@/v2/blocks/operation-block/helpers/get-cookie-header-keys'\nimport type { ResponseInstance } from '@/v2/blocks/operation-block/helpers/send-request'\n\ntype HarToFetchResponseProps = {\n /** The HAR Response object to convert */\n harResponse: HarResponse\n /** Optional URL to set on the Response object */\n url?: string\n /** The HTTP method used for the request */\n method: HttpMethod\n /** The request path */\n path: string\n /** Time in ms the request took */\n duration?: number\n}\n\ntype ProcessedBody = {\n /** ArrayBuffer for Response body */\n body: ArrayBuffer | null\n /** Data for ResponseInstance (string or Blob) */\n data: string | Blob\n /** Size in bytes */\n size: number\n}\n\n/**\n * Converts a HAR (HTTP Archive) Response back to a ResponseInstance object.\n *\n * This function is the reverse of fetchResponseToHar - it takes a HAR response\n * and converts it back into a ResponseInstance object that includes both the\n * standard Fetch API Response properties and additional metadata.\n *\n * The conversion handles:\n * - Status code and status text restoration\n * - Headers reconstruction from HAR headers array\n * - Body decoding\n * - Content-Type and other header restoration\n * - URL property setting (if provided)\n * - Cookie header detection\n * - Duration tracking\n * - Response size calculation in bytes\n *\n * Body Handling:\n * - Plain text (no encoding): Text-based responses under 1MB from fetchResponseToHar\n * - Base64 encoded: Binary or legacy data (note: new HAR files won't contain binary data)\n * - Empty: Streaming responses, large responses (>1MB), or responses without bodies\n *\n * Use cases:\n * - Replaying recorded HTTP responses\n * - Creating mock responses from HAR files\n * - Testing with fixtures\n * - Response caching and restoration\n *\n * Note: The Fetch API Response object does not support setting the HTTP version,\n * so that information from the HAR is not preserved in the returned Response.\n * The URL property is set using Object.defineProperty since it is read-only\n * in the standard Response constructor.\n *\n * @see https://w3c.github.io/web-performance/specs/HAR/Overview.html\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Response\n *\n * @example\n * const harResponse = { status: 200, statusText: 'OK', ... }\n * const response = harToFetchResponse({\n * harResponse,\n * url: 'https://api.example.com',\n * method: 'GET',\n * path: '/users',\n * duration: 250\n * })\n * console.log(response.url) // 'https://api.example.com'\n * console.log(response.duration) // 250\n */\nexport const harToFetchResponse = ({\n harResponse,\n url = '',\n method,\n path,\n duration = 0,\n}: HarToFetchResponseProps): ResponseInstance => {\n const headers = buildHeaders(harResponse)\n const { body, data, size } = processBody(harResponse)\n const cookieHeaderKeys = getCookieHeaderKeys(headers)\n\n const response = new Response(body, {\n status: harResponse.status,\n statusText: harResponse.statusText,\n headers,\n })\n\n return {\n ...response,\n headers: Object.fromEntries(headers.entries()),\n cookieHeaderKeys,\n duration,\n status: harResponse.status,\n statusText: harResponse.statusText,\n method,\n path,\n data,\n size,\n url,\n }\n}\n\n/**\n * Builds Headers object and record from HAR response headers.\n */\nconst buildHeaders = (harResponse: HarResponse) => {\n const headers = new Headers()\n\n harResponse.headers.forEach(({ name, value }) => {\n headers.append(name, value)\n })\n\n return headers\n}\n\n/**\n * Processes HAR response body content.\n * Returns body, data and size for ResponseInstance.\n */\nconst processBody = (harResponse: HarResponse): ProcessedBody => {\n if (!harResponse.content.text) {\n return { body: null, data: '', size: 0 }\n }\n\n const { text, encoding } = harResponse.content\n\n if (encoding) {\n return { body: null, data: text, size: text.length }\n }\n\n const body = new TextEncoder().encode(text).buffer\n\n return { body, data: text, size: body.byteLength }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4EA,IAAa,sBAAsB,EACjC,aACA,MAAM,IACN,QACA,MACA,WAAW,QACoC;CAC/C,MAAM,UAAU,aAAa,WAAW;CACxC,MAAM,EAAE,MAAM,MAAM,SAAS,YAAY,WAAW;CACpD,MAAM,mBAAmB,oBAAoB,OAAO;CAQpD,OAAO;EACL,GAAG,IAPgB,SAAS,MAAM;GAClC,QAAQ,YAAY;GACpB,YAAY,YAAY;GACxB;EACF,CAGK;EACH,SAAS,OAAO,YAAY,QAAQ,QAAQ,CAAC;EAC7C;EACA;EACA,QAAQ,YAAY;EACpB,YAAY,YAAY;EACxB;EACA;EACA;EACA;EACA;CACF;AACF;;;;AAKA,IAAM,gBAAgB,gBAA6B;CACjD,MAAM,UAAU,IAAI,QAAQ;CAE5B,YAAY,QAAQ,SAAS,EAAE,MAAM,YAAY;EAC/C,QAAQ,OAAO,MAAM,KAAK;CAC5B,CAAC;CAED,OAAO;AACT;;;;;AAMA,IAAM,eAAe,gBAA4C;CAC/D,IAAI,CAAC,YAAY,QAAQ,MACvB,OAAO;EAAE,MAAM;EAAM,MAAM;EAAI,MAAM;CAAE;CAGzC,MAAM,EAAE,MAAM,aAAa,YAAY;CAEvC,IAAI,UACF,OAAO;EAAE,MAAM;EAAM,MAAM;EAAM,MAAM,KAAK;CAAO;CAGrD,MAAM,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;CAE5C,OAAO;EAAE;EAAM,MAAM;EAAM,MAAM,KAAK;CAAW;AACnD"}
1
+ {"version":3,"file":"har-to-fetch-response.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/har-to-fetch-response.ts"],"sourcesContent":["import type { HarResponse } from '@scalar/snippetz'\n\nimport { getCookieHeaderKeys } from '@/v2/blocks/operation-block/helpers/get-cookie-header-keys'\nimport type { ResponseInstance } from '@/v2/blocks/operation-block/helpers/send-request'\n\ntype HarToFetchResponseProps = {\n /** The HAR Response object to convert */\n harResponse: HarResponse\n /** Optional URL to set on the Response object */\n url?: string\n /** The HTTP method used for the request */\n method: string\n /** The request path */\n path: string\n /** Time in ms the request took */\n duration?: number\n}\n\ntype ProcessedBody = {\n /** ArrayBuffer for Response body */\n body: ArrayBuffer | null\n /** Data for ResponseInstance (string or Blob) */\n data: string | Blob\n /** Size in bytes */\n size: number\n}\n\n/**\n * Converts a HAR (HTTP Archive) Response back to a ResponseInstance object.\n *\n * This function is the reverse of fetchResponseToHar - it takes a HAR response\n * and converts it back into a ResponseInstance object that includes both the\n * standard Fetch API Response properties and additional metadata.\n *\n * The conversion handles:\n * - Status code and status text restoration\n * - Headers reconstruction from HAR headers array\n * - Body decoding\n * - Content-Type and other header restoration\n * - URL property setting (if provided)\n * - Cookie header detection\n * - Duration tracking\n * - Response size calculation in bytes\n *\n * Body Handling:\n * - Plain text (no encoding): Text-based responses under 1MB from fetchResponseToHar\n * - Base64 encoded: Binary or legacy data (note: new HAR files won't contain binary data)\n * - Empty: Streaming responses, large responses (>1MB), or responses without bodies\n *\n * Use cases:\n * - Replaying recorded HTTP responses\n * - Creating mock responses from HAR files\n * - Testing with fixtures\n * - Response caching and restoration\n *\n * Note: The Fetch API Response object does not support setting the HTTP version,\n * so that information from the HAR is not preserved in the returned Response.\n * The URL property is set using Object.defineProperty since it is read-only\n * in the standard Response constructor.\n *\n * @see https://w3c.github.io/web-performance/specs/HAR/Overview.html\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Response\n *\n * @example\n * const harResponse = { status: 200, statusText: 'OK', ... }\n * const response = harToFetchResponse({\n * harResponse,\n * url: 'https://api.example.com',\n * method: 'GET',\n * path: '/users',\n * duration: 250\n * })\n * console.log(response.url) // 'https://api.example.com'\n * console.log(response.duration) // 250\n */\nexport const harToFetchResponse = ({\n harResponse,\n url = '',\n method,\n path,\n duration = 0,\n}: HarToFetchResponseProps): ResponseInstance => {\n const headers = buildHeaders(harResponse)\n const { body, data, size } = processBody(harResponse)\n const cookieHeaderKeys = getCookieHeaderKeys(headers)\n\n const response = new Response(body, {\n status: harResponse.status,\n statusText: harResponse.statusText,\n headers,\n })\n\n return {\n ...response,\n headers: Object.fromEntries(headers.entries()),\n cookieHeaderKeys,\n duration,\n status: harResponse.status,\n statusText: harResponse.statusText,\n method,\n path,\n data,\n size,\n url,\n }\n}\n\n/**\n * Builds Headers object and record from HAR response headers.\n */\nconst buildHeaders = (harResponse: HarResponse) => {\n const headers = new Headers()\n\n harResponse.headers.forEach(({ name, value }) => {\n headers.append(name, value)\n })\n\n return headers\n}\n\n/**\n * Processes HAR response body content.\n * Returns body, data and size for ResponseInstance.\n */\nconst processBody = (harResponse: HarResponse): ProcessedBody => {\n if (!harResponse.content.text) {\n return { body: null, data: '', size: 0 }\n }\n\n const { text, encoding } = harResponse.content\n\n if (encoding) {\n return { body: null, data: text, size: text.length }\n }\n\n const body = new TextEncoder().encode(text).buffer\n\n return { body, data: text, size: body.byteLength }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2EA,IAAa,sBAAsB,EACjC,aACA,MAAM,IACN,QACA,MACA,WAAW,QACoC;CAC/C,MAAM,UAAU,aAAa,WAAW;CACxC,MAAM,EAAE,MAAM,MAAM,SAAS,YAAY,WAAW;CACpD,MAAM,mBAAmB,oBAAoB,OAAO;CAQpD,OAAO;EACL,GAAG,IAPgB,SAAS,MAAM;GAClC,QAAQ,YAAY;GACpB,YAAY,YAAY;GACxB;EACF,CAGK;EACH,SAAS,OAAO,YAAY,QAAQ,QAAQ,CAAC;EAC7C;EACA;EACA,QAAQ,YAAY;EACpB,YAAY,YAAY;EACxB;EACA;EACA;EACA;EACA;CACF;AACF;;;;AAKA,IAAM,gBAAgB,gBAA6B;CACjD,MAAM,UAAU,IAAI,QAAQ;CAE5B,YAAY,QAAQ,SAAS,EAAE,MAAM,YAAY;EAC/C,QAAQ,OAAO,MAAM,KAAK;CAC5B,CAAC;CAED,OAAO;AACT;;;;;AAMA,IAAM,eAAe,gBAA4C;CAC/D,IAAI,CAAC,YAAY,QAAQ,MACvB,OAAO;EAAE,MAAM;EAAM,MAAM;EAAI,MAAM;CAAE;CAGzC,MAAM,EAAE,MAAM,aAAa,YAAY;CAEvC,IAAI,UACF,OAAO;EAAE,MAAM;EAAM,MAAM;EAAM,MAAM,KAAK;CAAO;CAGrD,MAAM,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;CAE5C,OAAO;EAAE;EAAM,MAAM;EAAM,MAAM,KAAK;CAAW;AACnD"}
@@ -1,5 +1,4 @@
1
1
  import { type ErrorResponse } from '@scalar/helpers/errors/normalize-error';
2
- import type { HttpMethod } from '@scalar/helpers/http/http-methods';
3
2
  import type { ClientPlugin } from '@scalar/oas-utils/helpers';
4
3
  import type { RequestPayload } from '@scalar/workspace-store/request-example';
5
4
  /** A single set of populated values for a sent request */
@@ -15,7 +14,7 @@ export type ResponseInstance = Omit<Response, 'headers'> & {
15
14
  /** The response status text */
16
15
  statusText: string;
17
16
  /** The response method */
18
- method: HttpMethod;
17
+ method: string;
19
18
  /** The request path */
20
19
  path: string;
21
20
  } & ({
@@ -1 +1 @@
1
- {"version":3,"file":"send-request.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAkB,MAAM,wCAAwC,CAAA;AAGnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAKnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAA;AAY7E,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IACzD,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,CACE;IACE,wBAAwB;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,qDAAqD;IACrD,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAA;CAChD,CACJ,CAAA;AAKH,2EAA2E;AAC3E,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAA;AAEtC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,sFAO/B;IACD,YAAY,EAAE,OAAO,CAAA;IACrB,cAAc,EAAE,cAAc,CAAA;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iEAAiE;IACjE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,uEAAuE;IACvE,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACzF,KAAG,OAAO,CACT,aAAa,CAAC;IACZ,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,QAAQ,CAAA;CAC3B,CAAC,CA8DH,CAAA"}
1
+ {"version":3,"file":"send-request.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAkB,MAAM,wCAAwC,CAAA;AAOnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAA;AAa7E,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IACzD,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,CACE;IACE,wBAAwB;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,qDAAqD;IACrD,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAA;CAChD,CACJ,CAAA;AAKH,2EAA2E;AAC3E,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAA;AAEtC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,sFAO/B;IACD,YAAY,EAAE,OAAO,CAAA;IACrB,cAAc,EAAE,cAAc,CAAA;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iEAAiE;IACjE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,uEAAuE;IACvE,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACzF,KAAG,OAAO,CACT,aAAa,CAAC;IACZ,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,QAAQ,CAAA;CAC3B,CAAC,CA8DH,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { getCookieHeaderKeys } from "./get-cookie-header-keys.js";
2
2
  import { resolveResponseBodyHandler } from "../../response-block/helpers/resolve-response-body-handler.js";
3
3
  import { resolveResponseContentType, resolveResponseMimeType } from "../../response-block/helpers/resolve-response-content-type.js";
4
+ import { getResponseStreamFormat } from "../../response-block/helpers/response-stream.js";
4
5
  import { decodeBuffer } from "./decode-buffer.js";
5
6
  import { ERRORS, normalizeError } from "@scalar/helpers/errors/normalize-error";
6
7
  import { isElectron } from "@scalar/helpers/general/is-electron";
@@ -46,11 +47,11 @@ var sendRequest = async ({ isUsingProxy, requestPayload, request, plugins = [],
46
47
  const method = requestPayload[1].method ?? "GET";
47
48
  const shouldSkipBody = NO_BODY_STATUS_CODES.includes(response.status);
48
49
  /**
49
- * Handle server-sent event streams separately.
50
+ * Handle sequential response formats without buffering the complete body.
50
51
  * These responses need a reader instead of buffered data.
51
52
  * We check this early to avoid unnecessary body reading.
52
53
  */
53
- if (contentType?.startsWith("text/event-stream") && response.body) return buildStreamingResponse({
54
+ if (!shouldSkipBody && contentType && getResponseStreamFormat(contentType) && response.body) return buildStreamingResponse({
54
55
  response,
55
56
  requestPayload,
56
57
  timestamp,
@@ -93,7 +94,7 @@ var getCustomCookie = (response) => {
93
94
  return null;
94
95
  };
95
96
  /**
96
- * Build a streaming response for server-sent events.
97
+ * Build a streaming response for sequential media types.
97
98
  * Streaming responses use a reader instead of buffering the entire body.
98
99
  */
99
100
  var buildStreamingResponse = ({ response, requestPayload, timestamp, duration, responseHeaders, statusText, method, fullPath }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"send-request.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"sourcesContent":["import { ERRORS, type ErrorResponse, normalizeError } from '@scalar/helpers/errors/normalize-error'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { httpStatusCodes } from '@scalar/helpers/http/http-status-codes'\nimport { normalizeHeaders } from '@scalar/helpers/http/normalize-headers'\nimport { X_SCALAR_SET_COOKIE } from '@scalar/helpers/http/scalar-headers'\nimport { serializeCookie } from '@scalar/helpers/http/serialize-cookie'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { RequestPayload } from '@scalar/workspace-store/request-example'\nimport { parseSetCookie } from 'set-cookie-parser'\n\nimport { getCookieHeaderKeys } from '@/v2/blocks/operation-block/helpers/get-cookie-header-keys'\nimport { resolveResponseBodyHandler } from '@/v2/blocks/response-block/helpers/resolve-response-body-handler'\nimport {\n resolveResponseContentType,\n resolveResponseMimeType,\n} from '@/v2/blocks/response-block/helpers/resolve-response-content-type'\n\nimport { decodeBuffer } from './decode-buffer'\n\n/** A single set of populated values for a sent request */\nexport type ResponseInstance = Omit<Response, 'headers'> & {\n /** Store headers as an object to match what we had with axios */\n headers: Record<string, string>\n /** Keys of headers which set cookies */\n cookieHeaderKeys: string[]\n /** Time in ms the request took */\n duration: number\n /** The response status */\n status: number\n /** The response status text */\n statusText: string\n /** The response method */\n method: HttpMethod\n /** The request path */\n path: string\n} & (\n | {\n /** The response data */\n data: string | Blob\n /** The response size in bytes */\n size: number\n }\n | {\n /** A stream reader for a streamable response body */\n reader: ReadableStreamDefaultReader<Uint8Array>\n }\n )\n\n/** HTTP status codes that should not include a response body */\nconst NO_BODY_STATUS_CODES = [204, 205, 304]\n\n/** Custom fetch function signature compatible with the global fetch API */\nexport type CustomFetch = typeof fetch\n\n/**\n * Execute the built fetch request and return a structured response.\n *\n * This function handles the complete request lifecycle including plugin hooks,\n * response processing, streaming detection, and error handling. It supports both\n * standard responses and server-sent event streams.\n *\n * @param request - The request built by the buildRequest helper\n * @param operation - The OpenAPI operation being executed\n * @param plugins - Array of client plugins to execute hooks\n * @param isUsingProxy - Whether the request is being proxied for header handling\n * @returns A tuple with either an error or the response data\n */\nexport const sendRequest = async ({\n isUsingProxy,\n requestPayload,\n request,\n plugins = [],\n customFetch = fetch,\n onResponseReceived,\n}: {\n isUsingProxy: boolean\n requestPayload: RequestPayload\n /**\n * Pre-built fetch Request to send as-is. When provided, it is used instead of rebuilding\n * from the request payload so plugin hooks observe the exact bytes that go over the wire\n * (rebuilding a multipart body generates a different boundary).\n */\n request?: Request\n /** Registered client plugins for custom content type handling */\n plugins?: ClientPlugin[]\n /** Optional custom fetch implementation, overrides the global fetch */\n customFetch?: CustomFetch\n /** Runs before response processing and returns the response to use. */\n onResponseReceived?: (response: Response, responseDuration: number) => Promise<Response>\n}): Promise<\n ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n }>\n> => {\n try {\n // Execute the request and measure duration\n const startTime = performance.now()\n\n // In electron we allow GET requests to have a body\n const fetchedResponse = isElectron()\n ? await customFetch(...requestPayload)\n : await customFetch(request ?? buildSafeBodyRequest(...requestPayload))\n\n const endTime = performance.now()\n const timestamp = Date.now()\n const duration = endTime - startTime\n\n const response = onResponseReceived ? await onResponseReceived(fetchedResponse, duration) : fetchedResponse\n\n // Extract response metadata early for reuse\n const contentType = response.headers.get('content-type')\n const responseHeaders = normalizeHeaders(response.headers, isUsingProxy)\n // A Response built with the Response constructor has an empty url. For intercepted responses,\n // fall back to the original network response destination, and finally to the requested URL.\n const responseUrl = new URL(response.url || fetchedResponse.url || requestPayload[0])\n const fullPath = responseUrl.pathname + responseUrl.search\n const statusText = response.statusText || httpStatusCodes[response.status]?.name || ''\n const method = (requestPayload[1].method ?? 'GET') as HttpMethod\n const shouldSkipBody = NO_BODY_STATUS_CODES.includes(response.status)\n\n /**\n * Handle server-sent event streams separately.\n * These responses need a reader instead of buffered data.\n * We check this early to avoid unnecessary body reading.\n */\n if (contentType?.startsWith('text/event-stream') && response.body) {\n return buildStreamingResponse({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n })\n }\n\n return await buildStandardResponse({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n contentType,\n shouldSkipBody,\n plugins,\n })\n } catch (error) {\n return [normalizeError(error, ERRORS.REQUEST_FAILED), null]\n }\n}\n\n/**\n * Extracts and serializes custom cookies from the response using the custom cookie header.\n *\n * This function parses the custom cookie header (if present), serializes each cookie using our\n * in-repo `serializeCookie` helper, and then deletes the custom cookie header from the response.\n * Returns an array of serialized cookie strings, or null if no cookies were found.\n */\nconst getCustomCookie = (response: Response): string[] | null => {\n const result = parseSetCookie(response.headers.get(X_SCALAR_SET_COOKIE) ?? '').map((c) =>\n serializeCookie(c.name, c.value, {\n ...c,\n sameSite: c.sameSite as boolean | 'lax' | 'strict' | 'none' | undefined,\n }),\n )\n\n if (result.length) {\n return result\n }\n\n return null\n}\n\n/**\n * Build a streaming response for server-sent events.\n * Streaming responses use a reader instead of buffering the entire body.\n */\nconst buildStreamingResponse = ({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n}: {\n response: Response\n requestPayload: RequestPayload\n timestamp: number\n duration: number\n responseHeaders: Record<string, string>\n statusText: string\n method: HttpMethod\n fullPath: string\n}): ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n}> => {\n const normalizedResponse = new Response(null, {\n status: response.status,\n statusText,\n headers: response.headers,\n })\n\n const customCookie = getCustomCookie(normalizedResponse)\n const cookieHeaderKeys = customCookie ?? getCookieHeaderKeys(normalizedResponse.headers)\n\n return [\n null,\n {\n timestamp,\n requestPayload,\n response: {\n ...normalizedResponse,\n status: response.status,\n statusText,\n headers: responseHeaders,\n cookieHeaderKeys,\n reader: response.body!.getReader(),\n duration,\n method,\n path: fullPath,\n },\n originalResponse: normalizedResponse.clone(),\n },\n ]\n}\n\n/**\n * Build a standard response with buffered body data.\n * This handles all non-streaming responses including JSON, text, and binary data.\n */\nconst buildStandardResponse = async ({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n contentType,\n shouldSkipBody,\n plugins,\n}: {\n response: Response\n requestPayload: RequestPayload\n timestamp: number\n duration: number\n responseHeaders: Record<string, string>\n statusText: string\n method: HttpMethod\n fullPath: string\n contentType: string | null\n shouldSkipBody: boolean\n plugins: ClientPlugin[]\n}): Promise<\n ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n }>\n> => {\n /**\n * Clone the response to preserve the original for body reading.\n * Read the body once and reuse the buffer for both decoding and creating a new Response.\n */\n const clonedResponse = response.clone()\n const arrayBuffer = await clonedResponse.arrayBuffer()\n const responseType = resolveResponseContentType(contentType)\n const mimeEssence = resolveResponseMimeType(contentType).essence\n const pluginHandler = resolveResponseBodyHandler(mimeEssence, plugins)\n const responseData = await decodeBuffer(arrayBuffer, responseType, pluginHandler)\n\n /**\n * Create a new Response using the arrayBuffer we already read.\n * ArrayBuffers can be reused to create new Response objects without additional memory.\n */\n const normalizedResponse = new Response(shouldSkipBody ? null : arrayBuffer, {\n status: response.status,\n statusText,\n headers: response.headers,\n })\n\n const customCookie = getCustomCookie(normalizedResponse)\n const cookieHeaderKeys = customCookie ?? getCookieHeaderKeys(normalizedResponse.headers)\n\n return [\n null,\n {\n timestamp,\n requestPayload,\n response: {\n ...normalizedResponse,\n status: response.status,\n statusText,\n headers: responseHeaders,\n cookieHeaderKeys,\n data: responseData,\n size: arrayBuffer.byteLength,\n duration,\n method,\n path: fullPath,\n },\n originalResponse: response.clone(),\n },\n ]\n}\n"],"mappings":";;;;;;;;;;;;;;AAmDA,IAAM,uBAAuB;CAAC;CAAK;CAAK;AAAG;;;;;;;;;;;;;;AAkB3C,IAAa,cAAc,OAAO,EAChC,cACA,gBACA,SACA,UAAU,CAAC,GACX,cAAc,OACd,yBAuBG;CACH,IAAI;EAEF,MAAM,YAAY,YAAY,IAAI;EAGlC,MAAM,kBAAkB,WAAW,IAC/B,MAAM,YAAY,GAAG,cAAc,IACnC,MAAM,YAAY,WAAW,qBAAqB,GAAG,cAAc,CAAC;EAExE,MAAM,UAAU,YAAY,IAAI;EAChC,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,WAAW,UAAU;EAE3B,MAAM,WAAW,qBAAqB,MAAM,mBAAmB,iBAAiB,QAAQ,IAAI;EAG5F,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;EACvD,MAAM,kBAAkB,iBAAiB,SAAS,SAAS,YAAY;EAGvE,MAAM,cAAc,IAAI,IAAI,SAAS,OAAO,gBAAgB,OAAO,eAAe,EAAE;EACpF,MAAM,WAAW,YAAY,WAAW,YAAY;EACpD,MAAM,aAAa,SAAS,cAAc,gBAAgB,SAAS,OAAO,EAAE,QAAQ;EACpF,MAAM,SAAU,eAAe,EAAE,CAAC,UAAU;EAC5C,MAAM,iBAAiB,qBAAqB,SAAS,SAAS,MAAM;;;;;;EAOpE,IAAI,aAAa,WAAW,mBAAmB,KAAK,SAAS,MAC3D,OAAO,uBAAuB;GAC5B;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;EAGH,OAAO,MAAM,sBAAsB;GACjC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;CACH,SAAS,OAAO;EACd,OAAO,CAAC,eAAe,OAAO,OAAO,cAAc,GAAG,IAAI;CAC5D;AACF;;;;;;;;AASA,IAAM,mBAAmB,aAAwC;CAC/D,MAAM,SAAS,eAAe,SAAS,QAAQ,IAAI,mBAAmB,KAAK,EAAE,CAAC,CAAC,KAAK,MAClF,gBAAgB,EAAE,MAAM,EAAE,OAAO;EAC/B,GAAG;EACH,UAAU,EAAE;CACd,CAAC,CACH;CAEA,IAAI,OAAO,QACT,OAAO;CAGT,OAAO;AACT;;;;;AAMA,IAAM,0BAA0B,EAC9B,UACA,gBACA,WACA,UACA,iBACA,YACA,QACA,eAeI;CACJ,MAAM,qBAAqB,IAAI,SAAS,MAAM;EAC5C,QAAQ,SAAS;EACjB;EACA,SAAS,SAAS;CACpB,CAAC;CAGD,MAAM,mBADe,gBAAgB,kBACZ,KAAgB,oBAAoB,mBAAmB,OAAO;CAEvF,OAAO,CACL,MACA;EACE;EACA;EACA,UAAU;GACR,GAAG;GACH,QAAQ,SAAS;GACjB;GACA,SAAS;GACT;GACA,QAAQ,SAAS,KAAM,UAAU;GACjC;GACA;GACA,MAAM;EACR;EACA,kBAAkB,mBAAmB,MAAM;CAC7C,CACF;AACF;;;;;AAMA,IAAM,wBAAwB,OAAO,EACnC,UACA,gBACA,WACA,UACA,iBACA,YACA,QACA,UACA,aACA,gBACA,cAoBG;CAMH,MAAM,cAAc,MADG,SAAS,MACN,CAAA,CAAe,YAAY;CACrD,MAAM,eAAe,2BAA2B,WAAW;CAC3D,MAAM,cAAc,wBAAwB,WAAW,CAAC,CAAC;CAEzD,MAAM,eAAe,MAAM,aAAa,aAAa,cAD/B,2BAA2B,aAAa,OACK,CAAa;;;;;CAMhF,MAAM,qBAAqB,IAAI,SAAS,iBAAiB,OAAO,aAAa;EAC3E,QAAQ,SAAS;EACjB;EACA,SAAS,SAAS;CACpB,CAAC;CAGD,MAAM,mBADe,gBAAgB,kBACZ,KAAgB,oBAAoB,mBAAmB,OAAO;CAEvF,OAAO,CACL,MACA;EACE;EACA;EACA,UAAU;GACR,GAAG;GACH,QAAQ,SAAS;GACjB;GACA,SAAS;GACT;GACA,MAAM;GACN,MAAM,YAAY;GAClB;GACA;GACA,MAAM;EACR;EACA,kBAAkB,SAAS,MAAM;CACnC,CACF;AACF"}
1
+ {"version":3,"file":"send-request.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"sourcesContent":["import { ERRORS, type ErrorResponse, normalizeError } from '@scalar/helpers/errors/normalize-error'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport { httpStatusCodes } from '@scalar/helpers/http/http-status-codes'\nimport { normalizeHeaders } from '@scalar/helpers/http/normalize-headers'\nimport { X_SCALAR_SET_COOKIE } from '@scalar/helpers/http/scalar-headers'\nimport { serializeCookie } from '@scalar/helpers/http/serialize-cookie'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { RequestPayload } from '@scalar/workspace-store/request-example'\nimport { parseSetCookie } from 'set-cookie-parser'\n\nimport { getCookieHeaderKeys } from '@/v2/blocks/operation-block/helpers/get-cookie-header-keys'\nimport { resolveResponseBodyHandler } from '@/v2/blocks/response-block/helpers/resolve-response-body-handler'\nimport {\n resolveResponseContentType,\n resolveResponseMimeType,\n} from '@/v2/blocks/response-block/helpers/resolve-response-content-type'\nimport { getResponseStreamFormat } from '@/v2/blocks/response-block/helpers/response-stream'\n\nimport { decodeBuffer } from './decode-buffer'\n\n/** A single set of populated values for a sent request */\nexport type ResponseInstance = Omit<Response, 'headers'> & {\n /** Store headers as an object to match what we had with axios */\n headers: Record<string, string>\n /** Keys of headers which set cookies */\n cookieHeaderKeys: string[]\n /** Time in ms the request took */\n duration: number\n /** The response status */\n status: number\n /** The response status text */\n statusText: string\n /** The response method */\n method: string\n /** The request path */\n path: string\n} & (\n | {\n /** The response data */\n data: string | Blob\n /** The response size in bytes */\n size: number\n }\n | {\n /** A stream reader for a streamable response body */\n reader: ReadableStreamDefaultReader<Uint8Array>\n }\n )\n\n/** HTTP status codes that should not include a response body */\nconst NO_BODY_STATUS_CODES = [204, 205, 304]\n\n/** Custom fetch function signature compatible with the global fetch API */\nexport type CustomFetch = typeof fetch\n\n/**\n * Execute the built fetch request and return a structured response.\n *\n * This function handles the complete request lifecycle including plugin hooks,\n * response processing, streaming detection, and error handling. It supports both\n * standard responses and server-sent event streams.\n *\n * @param request - The request built by the buildRequest helper\n * @param operation - The OpenAPI operation being executed\n * @param plugins - Array of client plugins to execute hooks\n * @param isUsingProxy - Whether the request is being proxied for header handling\n * @returns A tuple with either an error or the response data\n */\nexport const sendRequest = async ({\n isUsingProxy,\n requestPayload,\n request,\n plugins = [],\n customFetch = fetch,\n onResponseReceived,\n}: {\n isUsingProxy: boolean\n requestPayload: RequestPayload\n /**\n * Pre-built fetch Request to send as-is. When provided, it is used instead of rebuilding\n * from the request payload so plugin hooks observe the exact bytes that go over the wire\n * (rebuilding a multipart body generates a different boundary).\n */\n request?: Request\n /** Registered client plugins for custom content type handling */\n plugins?: ClientPlugin[]\n /** Optional custom fetch implementation, overrides the global fetch */\n customFetch?: CustomFetch\n /** Runs before response processing and returns the response to use. */\n onResponseReceived?: (response: Response, responseDuration: number) => Promise<Response>\n}): Promise<\n ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n }>\n> => {\n try {\n // Execute the request and measure duration\n const startTime = performance.now()\n\n // In electron we allow GET requests to have a body\n const fetchedResponse = isElectron()\n ? await customFetch(...requestPayload)\n : await customFetch(request ?? buildSafeBodyRequest(...requestPayload))\n\n const endTime = performance.now()\n const timestamp = Date.now()\n const duration = endTime - startTime\n\n const response = onResponseReceived ? await onResponseReceived(fetchedResponse, duration) : fetchedResponse\n\n // Extract response metadata early for reuse\n const contentType = response.headers.get('content-type')\n const responseHeaders = normalizeHeaders(response.headers, isUsingProxy)\n // A Response built with the Response constructor has an empty url. For intercepted responses,\n // fall back to the original network response destination, and finally to the requested URL.\n const responseUrl = new URL(response.url || fetchedResponse.url || requestPayload[0])\n const fullPath = responseUrl.pathname + responseUrl.search\n const statusText = response.statusText || httpStatusCodes[response.status]?.name || ''\n const method = (requestPayload[1].method ?? 'GET') as string\n const shouldSkipBody = NO_BODY_STATUS_CODES.includes(response.status)\n\n /**\n * Handle sequential response formats without buffering the complete body.\n * These responses need a reader instead of buffered data.\n * We check this early to avoid unnecessary body reading.\n */\n if (!shouldSkipBody && contentType && getResponseStreamFormat(contentType) && response.body) {\n return buildStreamingResponse({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n })\n }\n\n return await buildStandardResponse({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n contentType,\n shouldSkipBody,\n plugins,\n })\n } catch (error) {\n return [normalizeError(error, ERRORS.REQUEST_FAILED), null]\n }\n}\n\n/**\n * Extracts and serializes custom cookies from the response using the custom cookie header.\n *\n * This function parses the custom cookie header (if present), serializes each cookie using our\n * in-repo `serializeCookie` helper, and then deletes the custom cookie header from the response.\n * Returns an array of serialized cookie strings, or null if no cookies were found.\n */\nconst getCustomCookie = (response: Response): string[] | null => {\n const result = parseSetCookie(response.headers.get(X_SCALAR_SET_COOKIE) ?? '').map((c) =>\n serializeCookie(c.name, c.value, {\n ...c,\n sameSite: c.sameSite as boolean | 'lax' | 'strict' | 'none' | undefined,\n }),\n )\n\n if (result.length) {\n return result\n }\n\n return null\n}\n\n/**\n * Build a streaming response for sequential media types.\n * Streaming responses use a reader instead of buffering the entire body.\n */\nconst buildStreamingResponse = ({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n}: {\n response: Response\n requestPayload: RequestPayload\n timestamp: number\n duration: number\n responseHeaders: Record<string, string>\n statusText: string\n method: string\n fullPath: string\n}): ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n}> => {\n const normalizedResponse = new Response(null, {\n status: response.status,\n statusText,\n headers: response.headers,\n })\n\n const customCookie = getCustomCookie(normalizedResponse)\n const cookieHeaderKeys = customCookie ?? getCookieHeaderKeys(normalizedResponse.headers)\n\n return [\n null,\n {\n timestamp,\n requestPayload,\n response: {\n ...normalizedResponse,\n status: response.status,\n statusText,\n headers: responseHeaders,\n cookieHeaderKeys,\n reader: response.body!.getReader(),\n duration,\n method,\n path: fullPath,\n },\n originalResponse: normalizedResponse.clone(),\n },\n ]\n}\n\n/**\n * Build a standard response with buffered body data.\n * This handles all non-streaming responses including JSON, text, and binary data.\n */\nconst buildStandardResponse = async ({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n contentType,\n shouldSkipBody,\n plugins,\n}: {\n response: Response\n requestPayload: RequestPayload\n timestamp: number\n duration: number\n responseHeaders: Record<string, string>\n statusText: string\n method: string\n fullPath: string\n contentType: string | null\n shouldSkipBody: boolean\n plugins: ClientPlugin[]\n}): Promise<\n ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n }>\n> => {\n /**\n * Clone the response to preserve the original for body reading.\n * Read the body once and reuse the buffer for both decoding and creating a new Response.\n */\n const clonedResponse = response.clone()\n const arrayBuffer = await clonedResponse.arrayBuffer()\n const responseType = resolveResponseContentType(contentType)\n const mimeEssence = resolveResponseMimeType(contentType).essence\n const pluginHandler = resolveResponseBodyHandler(mimeEssence, plugins)\n const responseData = await decodeBuffer(arrayBuffer, responseType, pluginHandler)\n\n /**\n * Create a new Response using the arrayBuffer we already read.\n * ArrayBuffers can be reused to create new Response objects without additional memory.\n */\n const normalizedResponse = new Response(shouldSkipBody ? null : arrayBuffer, {\n status: response.status,\n statusText,\n headers: response.headers,\n })\n\n const customCookie = getCustomCookie(normalizedResponse)\n const cookieHeaderKeys = customCookie ?? getCookieHeaderKeys(normalizedResponse.headers)\n\n return [\n null,\n {\n timestamp,\n requestPayload,\n response: {\n ...normalizedResponse,\n status: response.status,\n statusText,\n headers: responseHeaders,\n cookieHeaderKeys,\n data: responseData,\n size: arrayBuffer.byteLength,\n duration,\n method,\n path: fullPath,\n },\n originalResponse: response.clone(),\n },\n ]\n}\n"],"mappings":";;;;;;;;;;;;;;;AAmDA,IAAM,uBAAuB;CAAC;CAAK;CAAK;AAAG;;;;;;;;;;;;;;AAkB3C,IAAa,cAAc,OAAO,EAChC,cACA,gBACA,SACA,UAAU,CAAC,GACX,cAAc,OACd,yBAuBG;CACH,IAAI;EAEF,MAAM,YAAY,YAAY,IAAI;EAGlC,MAAM,kBAAkB,WAAW,IAC/B,MAAM,YAAY,GAAG,cAAc,IACnC,MAAM,YAAY,WAAW,qBAAqB,GAAG,cAAc,CAAC;EAExE,MAAM,UAAU,YAAY,IAAI;EAChC,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,WAAW,UAAU;EAE3B,MAAM,WAAW,qBAAqB,MAAM,mBAAmB,iBAAiB,QAAQ,IAAI;EAG5F,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;EACvD,MAAM,kBAAkB,iBAAiB,SAAS,SAAS,YAAY;EAGvE,MAAM,cAAc,IAAI,IAAI,SAAS,OAAO,gBAAgB,OAAO,eAAe,EAAE;EACpF,MAAM,WAAW,YAAY,WAAW,YAAY;EACpD,MAAM,aAAa,SAAS,cAAc,gBAAgB,SAAS,OAAO,EAAE,QAAQ;EACpF,MAAM,SAAU,eAAe,EAAE,CAAC,UAAU;EAC5C,MAAM,iBAAiB,qBAAqB,SAAS,SAAS,MAAM;;;;;;EAOpE,IAAI,CAAC,kBAAkB,eAAe,wBAAwB,WAAW,KAAK,SAAS,MACrF,OAAO,uBAAuB;GAC5B;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;EAGH,OAAO,MAAM,sBAAsB;GACjC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;CACH,SAAS,OAAO;EACd,OAAO,CAAC,eAAe,OAAO,OAAO,cAAc,GAAG,IAAI;CAC5D;AACF;;;;;;;;AASA,IAAM,mBAAmB,aAAwC;CAC/D,MAAM,SAAS,eAAe,SAAS,QAAQ,IAAI,mBAAmB,KAAK,EAAE,CAAC,CAAC,KAAK,MAClF,gBAAgB,EAAE,MAAM,EAAE,OAAO;EAC/B,GAAG;EACH,UAAU,EAAE;CACd,CAAC,CACH;CAEA,IAAI,OAAO,QACT,OAAO;CAGT,OAAO;AACT;;;;;AAMA,IAAM,0BAA0B,EAC9B,UACA,gBACA,WACA,UACA,iBACA,YACA,QACA,eAeI;CACJ,MAAM,qBAAqB,IAAI,SAAS,MAAM;EAC5C,QAAQ,SAAS;EACjB;EACA,SAAS,SAAS;CACpB,CAAC;CAGD,MAAM,mBADe,gBAAgB,kBACZ,KAAgB,oBAAoB,mBAAmB,OAAO;CAEvF,OAAO,CACL,MACA;EACE;EACA;EACA,UAAU;GACR,GAAG;GACH,QAAQ,SAAS;GACjB;GACA,SAAS;GACT;GACA,QAAQ,SAAS,KAAM,UAAU;GACjC;GACA;GACA,MAAM;EACR;EACA,kBAAkB,mBAAmB,MAAM;CAC7C,CACF;AACF;;;;;AAMA,IAAM,wBAAwB,OAAO,EACnC,UACA,gBACA,WACA,UACA,iBACA,YACA,QACA,UACA,aACA,gBACA,cAoBG;CAMH,MAAM,cAAc,MADG,SAAS,MACN,CAAA,CAAe,YAAY;CACrD,MAAM,eAAe,2BAA2B,WAAW;CAC3D,MAAM,cAAc,wBAAwB,WAAW,CAAC,CAAC;CAEzD,MAAM,eAAe,MAAM,aAAa,aAAa,cAD/B,2BAA2B,aAAa,OACK,CAAa;;;;;CAMhF,MAAM,qBAAqB,IAAI,SAAS,iBAAiB,OAAO,aAAa;EAC3E,QAAQ,SAAS;EACjB;EACA,SAAS,SAAS;CACpB,CAAC;CAGD,MAAM,mBADe,gBAAgB,kBACZ,KAAgB,oBAAoB,mBAAmB,OAAO;CAEvF,OAAO,CACL,MACA;EACE;EACA;EACA,UAAU;GACR,GAAG;GACH,QAAQ,SAAS;GACjB;GACA,SAAS;GACT;GACA,MAAM;GACN,MAAM,YAAY;GAClB;GACA;GACA,MAAM;EACR;EACA,kBAAkB,SAAS,MAAM;CACnC,CACF;AACF"}
@@ -1,5 +1,4 @@
1
1
  import type { ClientOptionGroup } from '@scalar/blocks/code-example';
2
- import type { HttpMethod } from '@scalar/helpers/http/http-methods';
3
2
  import type { ClientPlugin } from '@scalar/oas-utils/helpers';
4
3
  import type { WorkspaceStore } from '@scalar/workspace-store/client';
5
4
  import type { SelectedSecurity } from '@scalar/workspace-store/entities/auth';
@@ -21,8 +20,10 @@ export type RequestBlockProps = {
21
20
  /** Slug of the document the operation belongs to */
22
21
  documentSlug: string;
23
22
  layout: ClientLayout;
24
- method: HttpMethod;
23
+ method: string;
25
24
  operation: OperationObject;
25
+ /** Operation before downloaded examples are overlaid, for parameter edit targets. */
26
+ sourceOperation?: OperationObject;
26
27
  path: string;
27
28
  plugins: ClientPlugin[];
28
29
  proxyUrl: string;
@@ -1 +1 @@
1
- {"version":3,"file":"RequestBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/request-block/RequestBlock.vue"],"names":[],"mappings":"AA6xBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAGpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAGnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AAC7E,OAAO,KAAK,EAEV,QAAQ,EACR,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AAIvC,OAAO,EAKL,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAChC,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAerE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAA;AACjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAcrD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,QAAQ,CAAA;IAClB,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC,WAAW,EAAE,kBAAkB,CAAA;IAC/B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,aAAa,EAAE,CAAA;IACjC,eAAe,EAAE,aAAa,EAAE,CAAA;IAChC,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,UAAU,CAAA;IAClB,SAAS,EAAE,eAAe,CAAA;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,oBAAoB,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;IACjD,eAAe,EAAE,qBAAqB,CAAA;IACtC,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxD,cAAc,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC,yBAAyB,CAAC,CAAA;IACtE,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,uBAAuB,EAAE,0BAA0B,EAAE,CAAA;IACrD,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,mHAAmH;IACnH,sBAAsB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IACvC,uDAAuD;IACvD,OAAO,CAAC,EAAE,aAAa,CAAA;CACxB,CAAA;AAm6BD,QAAA,MAAM,YAAY,8SAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"RequestBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/request-block/RequestBlock.vue"],"names":[],"mappings":"AAu0BA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAKpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AAC7E,OAAO,KAAK,EAEV,QAAQ,EACR,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AAIvC,OAAO,EAKL,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAChC,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAerE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAA;AAEjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAWrD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,QAAQ,CAAA;IAClB,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC,WAAW,EAAE,kBAAkB,CAAA;IAC/B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,aAAa,EAAE,CAAA;IACjC,eAAe,EAAE,aAAa,EAAE,CAAA;IAChC,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,eAAe,CAAA;IAC1B,qFAAqF;IACrF,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,oBAAoB,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;IACjD,eAAe,EAAE,qBAAqB,CAAA;IACtC,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxD,cAAc,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC,yBAAyB,CAAC,CAAA;IACtE,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,uBAAuB,EAAE,0BAA0B,EAAE,CAAA;IACrD,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,mHAAmH;IACnH,sBAAsB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IACvC,uDAAuD;IACvD,OAAO,CAAC,EAAE,aAAa,CAAA;CACxB,CAAA;AAg+BD,QAAA,MAAM,YAAY,8SAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
2
2
  import RequestBlock_vue_vue_type_script_setup_true_lang_default from "./RequestBlock.vue.script.js";
3
3
  /* empty css */
4
4
  //#region src/v2/blocks/request-block/RequestBlock.vue
5
- var RequestBlock_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RequestBlock_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-5d6c8262"]]);
5
+ var RequestBlock_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RequestBlock_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-ec56362c"]]);
6
6
  //#endregion
7
7
  export { RequestBlock_default as default };
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"RequestBlock.vue.js","names":[],"sources":["../../../../src/v2/blocks/request-block/RequestBlock.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ClientOptionGroup } from '@scalar/blocks/code-example'\nimport { ScalarErrorBoundary } from '@scalar/components/error-boundary'\nimport { canMethodHaveBody } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { REGEX } from '@scalar/helpers/regex/regex-helpers'\nimport { replaceEnvVariables } from '@scalar/helpers/regex/replace-variables'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n AuthMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport { getUniqueExampleName } from '@scalar/workspace-store/navigation'\nimport {\n filterGlobalCookie,\n getEnvironmentVariables,\n getResolvedUrl,\n getSchemaExampleFromBody,\n type MergedSecuritySchemes,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OpenApiDocument,\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { computed, ref, useId, watch } from 'vue'\n\nimport SectionFilter from '@/components/SectionFilter.vue'\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport RequestBody from '@/v2/blocks/request-block/components/RequestBody.vue'\nimport RequestCodeSnippet from '@/v2/blocks/request-block/components/RequestCodeSnippet.vue'\nimport RequestParams from '@/v2/blocks/request-block/components/RequestParams.vue'\nimport type { TableRow } from '@/v2/blocks/request-block/components/RequestTableRow.vue'\nimport { createParameterHandlers } from '@/v2/blocks/request-block/helpers/create-parameter-handlers'\nimport { createParameterRows } from '@/v2/blocks/request-block/helpers/create-parameter-rows'\nimport { groupBy } from '@/v2/blocks/request-block/helpers/group-by'\nimport { groupGlobalCookies } from '@/v2/blocks/request-block/helpers/group-global-cookies'\nimport { getStructuredBodyCodec } from '@/v2/blocks/request-block/helpers/structured-body-codec'\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\n/** Base name for examples created by the \"generate example from schema\" button */\nconst GENERATED_EXAMPLE_NAME = 'Generated from schema'\n\ntype Filter =\n | 'All'\n | 'Auth'\n | 'Variables'\n | 'Cookies'\n | 'Headers'\n | 'Query'\n | 'Body'\n\nexport type RequestBlockProps = {\n authMeta: AuthMeta\n clientOptions: ClientOptionGroup[]\n environment: XScalarEnvironment\n eventBus: WorkspaceEventBus\n exampleKey: string\n workspaceCookies: XScalarCookie[]\n documentCookies: XScalarCookie[]\n /** Slug of the document the operation belongs to */\n documentSlug: string\n layout: ClientLayout\n method: HttpMethod\n operation: OperationObject\n path: string\n plugins: ClientPlugin[]\n proxyUrl: string\n securityRequirements: OpenApiDocument['security']\n securitySchemes: MergedSecuritySchemes\n requestBodyCompositionSelection?: Record<string, number>\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n selectedSecurity: SelectedSecurity\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n server: ServerObject | null\n defaultHeaders: Record<string, string>\n /** Initial view for structured request bodies, from the `x-scalar-default-request-body-view` document extension */\n defaultRequestBodyView?: 'form' | 'raw'\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}\n\nconst {\n authMeta = { type: 'document' },\n clientOptions,\n environment,\n eventBus,\n exampleKey,\n workspaceCookies,\n documentCookies,\n documentSlug,\n layout,\n method,\n operation,\n path,\n plugins,\n proxyUrl,\n requestBodyCompositionSelection,\n securityRequirements,\n securitySchemes,\n selectedClient,\n selectedSecurity,\n selectedSecuritySchemes,\n server,\n defaultHeaders: autoGeneratedHeaders,\n defaultRequestBodyView = 'raw',\n} = defineProps<RequestBlockProps>()\n\n/** Operation metadata used across event emissions */\nconst meta = computed(() => ({\n method,\n path,\n exampleKey,\n}))\n\nconst deletedExpandedParameterPaths = ref<Record<string, string[][]>>({})\n\n/** Renamed expanded rows, tracked as old-schema-path -> typed-value-path per parameter. */\nconst renamedExpandedParameterPaths = ref<\n Record<string, { from: string[]; to: string[] }[]>\n>({})\n\nconst getExpandedParameterKey = (parameter: {\n in: string\n name: string\n}): string => `${parameter.in}:${parameter.name}`\n\nconst getHiddenValuePaths = (parameter: {\n in: string\n name: string\n}): string[][] =>\n deletedExpandedParameterPaths.value[getExpandedParameterKey(parameter)] ?? []\n\nconst getRenamedValuePaths = (parameter: {\n in: string\n name: string\n}): { from: string[]; to: string[] }[] =>\n renamedExpandedParameterPaths.value[getExpandedParameterKey(parameter)] ?? []\n\nconst pathsEqual = (a: string[], b: string[]): boolean =>\n a.length === b.length && a.every((segment, index) => segment === b[index])\n\n/**\n * Hides the schema path of an expanded row so it does not reappear as an empty suggestion. Used\n * both when a row is deleted and when its key is renamed (the old key should not pop back up).\n */\nconst hideExpandedRowPath = (row: TableRow): void => {\n if (!row.originalParameter || !row.sourceParameterValuePath) {\n return\n }\n\n const key = getExpandedParameterKey(row.originalParameter)\n deletedExpandedParameterPaths.value = {\n ...deletedExpandedParameterPaths.value,\n [key]: [\n ...(deletedExpandedParameterPaths.value[key] ?? []),\n row.sourceParameterValuePath,\n ],\n }\n}\n\n/**\n * Records that an expanded row was renamed from its current value path to the typed one, so the\n * read side can render the renamed key in the original property's slot instead of appending it to\n * the end of the table. Repeated renames of the same row stay anchored to the original schema path.\n */\nconst recordExpandedRowRename = (\n row: TableRow,\n newValuePath: string[],\n): void => {\n if (!row.originalParameter || !row.sourceParameterValuePath) {\n return\n }\n\n const from = row.sourceParameterValuePath\n const key = getExpandedParameterKey(row.originalParameter)\n const existing = renamedExpandedParameterPaths.value[key] ?? []\n\n // If this row was already renamed, the row's current path is the previous target. Re-anchor that\n // entry to the new target so a second rename does not create an orphaned mapping.\n const chained = existing.find((entry) => pathsEqual(entry.to, from))\n const next = chained\n ? existing.map((entry) =>\n entry === chained ? { from: entry.from, to: newValuePath } : entry,\n )\n : [...existing, { from, to: newValuePath }]\n\n renamedExpandedParameterPaths.value = {\n ...renamedExpandedParameterPaths.value,\n [key]: next,\n }\n}\n\n/** Parameters grouped by type (path, query, header, cookie) */\nconst sections = computed(() =>\n groupBy(\n operation.parameters\n ?.map((param) => getResolvedRef(param))\n .filter((param) => param !== undefined)\n .flatMap((param) =>\n createParameterRows(param, exampleKey, {\n hiddenValuePaths:\n param.in === 'query' ? getHiddenValuePaths(param) : [],\n renamedValuePaths:\n param.in === 'query' ? getRenamedValuePaths(param) : [],\n }).map((row) => ({\n ...row,\n in: param.in,\n })),\n ) ?? [],\n 'in',\n ({ in: _in, ...row }) => {\n return row\n },\n ),\n)\n\n// Generate a reverse map for fast lookup of headers by the name\nconst headersMap = computed(() =>\n groupBy(\n sections.value.header?.map((it) => ({\n ...it,\n name: it.name.toLowerCase(),\n })) ?? [],\n 'name',\n ),\n)\n\nconst defaultHeaders = computed(() => {\n const disableParameters =\n operation['x-scalar-disable-parameters']?.['default-headers']?.[\n exampleKey\n ] ?? {}\n\n const isOverridden = (name: string) => {\n const header = headersMap.value[name.toLowerCase()]?.[0]\n\n if (!header) {\n return false\n }\n\n return !header.isDisabled\n }\n\n return Object.entries(autoGeneratedHeaders).map(([name, value]) => {\n return {\n name,\n value,\n schema: undefined,\n isOverridden: isOverridden(name),\n isReadonly: true,\n isDisabled: disableParameters[name.toLowerCase()] ?? false,\n } satisfies TableRow\n })\n})\n\nconst headers = computed(() => [\n ...defaultHeaders.value,\n ...(sections.value.header ?? []),\n])\n\n/** Resolved request URL, used to filter global cookies by their domain and path. */\nconst requestCookieUrl = computed(() => {\n const environmentVariables = getEnvironmentVariables(environment)\n const resolvedUrl = getResolvedUrl({ server, path })\n return replaceEnvVariables(resolvedUrl, environmentVariables)\n})\n\n/**\n * Global cookies grouped by name. Same-named cookies collapse into a single logical cookie so\n * duplicate names no longer share one disabled state (which made toggling one toggle them all).\n * A name with multiple values becomes a preset the user can switch between.\n */\nconst globalCookieGroups = computed(() =>\n groupGlobalCookies({\n sources: [\n { location: 'workspace', cookies: workspaceCookies },\n { location: 'document', cookies: documentCookies },\n ],\n // Keep domain/path filtering but ignore the disabled flag, so a disabled preset value stays\n // selectable in the switcher (it is only hidden from the request, not from the dropdown).\n shouldInclude: (cookie) =>\n filterGlobalCookie({\n cookie: { ...cookie, isDisabled: false },\n url: requestCookieUrl.value,\n disabledGlobalCookies: {},\n }),\n }),\n)\n\nconst defaultCookies = computed<TableRow[]>(() => {\n const disabledGlobalCookies =\n operation['x-scalar-disable-parameters']?.['global-cookies']?.[\n exampleKey\n ] ?? {}\n\n return globalCookieGroups.value.map((group) => ({\n name: group.name,\n value: group.selectedValue,\n globalRoute: { page: group.location, path: 'cookies' } as const,\n isReadonly: true,\n isDisabled: disabledGlobalCookies[group.name.toLowerCase()] ?? false,\n presetOptions: group.isPreset ? group.options : undefined,\n }))\n})\n\n/**\n * Switch a grouped global cookie preset to the chosen value by enabling the matching sibling and\n * disabling the rest. Selection is written back to the source `x-scalar-cookies` list so it\n * persists, and the send path drops disabled cookies, so only the selected value is sent.\n */\nconst handleSelectCookiePreset = (index: number, value: string): void => {\n const group = globalCookieGroups.value[index]\n if (!group) {\n return\n }\n\n for (const sibling of group.siblings) {\n eventBus.emit('cookie:upsert:cookie', {\n collectionType: sibling.location,\n index: sibling.index,\n payload: { isDisabled: sibling.value !== value },\n })\n }\n}\n\nconst cookies = computed(() => [\n ...(defaultCookies.value ?? []),\n ...(sections.value.cookie ?? []),\n])\n\n/** Currently selected filter for the request sections */\nconst selectedFilter = ref<Filter>('All')\n\n/** Available operation sections */\nconst OPERATION_SECTIONS: readonly Filter[] = [\n 'Auth',\n 'Variables',\n 'Cookies',\n 'Headers',\n 'Query',\n 'Body',\n] as const\n\n/**\n * Pre-generated stable IDs for all possible filter sections.\n * These are created once at setup time to avoid regenerating IDs on re-render.\n */\nconst sectionIds: Record<Filter, string> = {\n All: useId(),\n Auth: useId(),\n Variables: useId(),\n Cookies: useId(),\n Headers: useId(),\n Query: useId(),\n Body: useId(),\n}\n\n/** Filters available based on operation state */\nconst filters = computed<Filter[]>(() => {\n const availableFilters = new Set<Filter>(['All', ...OPERATION_SECTIONS])\n\n if (!sections.value.path?.length) {\n availableFilters.delete('Variables')\n }\n if (!canMethodHaveBody(method)) {\n availableFilters.delete('Body')\n }\n if (isAuthHidden.value) {\n availableFilters.delete('Auth')\n }\n\n return [...availableFilters]\n})\n\n/**\n * Map available filters to their pre-generated stable IDs.\n * Only includes IDs for filters that are currently available.\n */\nconst filterIds = computed(() =>\n filters.value.reduce<Partial<Record<Filter, string>>>((ids, section) => {\n ids[section] = sectionIds[section]\n return ids\n }, {}),\n)\n\n/**\n * Hide auth selector in readonly mode when no security schemes are defined.\n * This keeps the UI clean when there are no authentication options available.\n */\nconst isAuthHidden = computed(\n () => layout === 'modal' && !Object.keys(securitySchemes ?? {}).length,\n)\n\n/**\n * Keep auth available for unauthenticated operations, but collapse it by default\n * in readonly modal layouts unless a requirement or manual selection exists.\n */\nconst isAuthDefaultOpen = computed(\n () =>\n layout !== 'modal' ||\n Boolean(\n securityRequirements?.length || selectedSecurity.selectedSchemes.length,\n ),\n)\n\n/** Get a sensible placeholder for the request name input */\nconst requestNamePlaceholder = computed(() => {\n if (operation.summary) {\n return operation.summary\n }\n const cleanPath = path.replace(REGEX.PROTOCOL, '')\n return cleanPath || 'Request Name'\n})\n\n/** Check if the section should be shown based on the selected filter */\nconst isSectionVisible = (section: Filter): boolean => {\n return selectedFilter.value === 'All' || selectedFilter.value === section\n}\n\n/**\n * Reset filter to 'All' if Body filter is selected but method changes to one that cannot have a body.\n * This prevents showing an empty Body section when switching methods.\n */\nwatch(\n () => method,\n (newMethod) => {\n if (selectedFilter.value === 'Body' && !canMethodHaveBody(newMethod)) {\n selectedFilter.value = 'All'\n }\n },\n)\n\n// Expanded-row bookkeeping is keyed by `in:name`, which is not unique across operations or\n// examples. Reset both maps when the operation or example changes so stale delete/rename mappings\n// do not leak onto another request that happens to share a query parameter name.\nwatch(\n () => [method, path, exampleKey],\n () => {\n deletedExpandedParameterPaths.value = {}\n renamedExpandedParameterPaths.value = {}\n },\n)\n\n/** Handle operation summary updates */\nconst handleSummaryUpdate = (event: Event): void => {\n if (!(event.target instanceof HTMLInputElement)) {\n return\n }\n const summary = event.target.value\n eventBus.emit('operation:update:meta', {\n meta: meta.value,\n payload: { summary: summary.trim() },\n })\n}\n\n/** Parameter handlers */\nconst parameterHandlers = computed(() => ({\n path: createParameterHandlers('path', eventBus, meta.value, {\n context: sections.value.path ?? [],\n }),\n cookie: {\n ...createParameterHandlers('cookie', eventBus, meta.value, {\n context: cookies.value ?? [],\n globalParameters: defaultCookies.value.length,\n }),\n selectPreset: handleSelectCookiePreset,\n },\n header: createParameterHandlers('header', eventBus, meta.value, {\n context: headers.value,\n defaultParameters: defaultHeaders.value.length,\n }),\n query: createParameterHandlers('query', eventBus, meta.value, {\n context: sections.value.query ?? [],\n onDeleteExpandedRow: hideExpandedRowPath,\n onRenameExpandedRow: recordExpandedRowRename,\n }),\n}))\n\n/** Handle request body content type update */\nconst handleUpdateContentType = (payload: { value: string }): void =>\n eventBus.emit('operation:update:requestBody:contentType', {\n payload: { contentType: payload.value },\n meta: meta.value,\n })\n\n/** Handle request body value update */\nconst handleUpdateBodyValue = ({\n payload,\n contentType,\n}: Pick<\n ApiReferenceEvents['operation:update:requestBody:value'],\n 'payload' | 'contentType'\n>): void => {\n const debounceKey =\n typeof payload === 'string'\n ? `update:requestBody:value-${contentType}`\n : undefined\n\n eventBus.emit(\n 'operation:update:requestBody:value',\n {\n payload,\n contentType,\n meta: meta.value,\n },\n {\n debounceKey,\n },\n )\n}\n\n/** Handle request body value update */\nconst handleUpdateBodyFormValue = ({\n payload,\n contentType,\n}: Pick<\n ApiReferenceEvents['operation:update:requestBody:formValue'],\n 'payload' | 'contentType'\n>): void => {\n const debounceKey = `update:requestBody:${contentType}-form-value`\n\n eventBus.emit(\n 'operation:update:requestBody:formValue',\n {\n payload: payload.map((row) => unpackProxyObject(row, { depth: 1 })),\n contentType,\n meta: meta.value,\n },\n {\n debounceKey,\n },\n )\n}\n\n/**\n * Create a new example seeded with values generated from the request body schema.\n *\n * Custom examples in the document otherwise hide the auto-generated fields entirely. Rather than\n * only rendering the generated body, we write it into a fresh example so the user can edit it and\n * so it survives an export of the document.\n */\nconst handleGenerateExample = ({\n contentType,\n}: {\n contentType: string\n}): void => {\n const requestBody = getResolvedRef(operation.requestBody)\n const codec = getStructuredBodyCodec(contentType)\n if (!requestBody || !codec) {\n return\n }\n\n const value = getSchemaExampleFromBody(\n requestBody,\n contentType,\n requestBodyCompositionSelection,\n )\n\n // A schema that generates nothing writable would leave the user on an empty new example.\n if (value === undefined || value === null) {\n return\n }\n\n const exampleName = getUniqueExampleName(operation, GENERATED_EXAMPLE_NAME)\n const exampleMeta = { path, method, exampleKey: exampleName }\n\n eventBus.emit('operation:create:draft-example', {\n documentName: documentSlug,\n meta: { path, method },\n exampleName,\n })\n\n // Carry over the content type the user was looking at, otherwise the new example opens on\n // whichever content type happens to come first on the request body.\n eventBus.emit('operation:update:requestBody:contentType', {\n payload: { contentType },\n meta: exampleMeta,\n })\n\n eventBus.emit('operation:update:requestBody:value', {\n payload: codec.stringify(value),\n contentType,\n meta: exampleMeta,\n })\n\n // The modal selects the example after its creation hook rebuilds the sidebar.\n if (layout === 'modal') {\n return\n }\n\n eventBus.emit('ui:navigate', {\n page: 'example',\n documentSlug,\n path,\n method,\n exampleName,\n })\n}\n\nconst labelRequestNameId = useId()\n\nconst globalCookies = computed(() => [...workspaceCookies, ...documentCookies])\n\n/** Allow updating the operation extensions for the plugins */\nconst updateOperationExtension = (\n payload: ApiReferenceEvents['operation:update:extension']['payload'],\n): void =>\n eventBus.emit('operation:update:extension', { payload, meta: meta.value })\n</script>\n<template>\n <ViewLayoutSection :aria-label=\"`Request: ${operation.summary}`\">\n <template #title>\n <div\n class=\"group pointer-events-none flex flex-1 items-center gap-1 lg:pr-24\">\n <label\n v-if=\"layout !== 'modal'\"\n class=\"pointer-events-auto absolute top-0 left-0 h-full w-full cursor-text opacity-0\"\n :for=\"labelRequestNameId\" />\n <input\n v-if=\"layout !== 'modal'\"\n :id=\"labelRequestNameId\"\n class=\"text-c-1 group-hover-input pointer-events-auto relative z-10 -ml-0.5 h-8 w-full rounded pl-1.25 has-[:focus-visible]:outline md:-ml-1.25\"\n :placeholder=\"requestNamePlaceholder\"\n :value=\"operation.summary\"\n @blur=\"handleSummaryUpdate\" />\n <span\n v-else\n class=\"text-c-1 flex h-8 items-center\">\n {{ operation.summary }}\n </span>\n </div>\n <SectionFilter\n v-model=\"selectedFilter\"\n :filterIds=\"filterIds\"\n :filters=\"filters\" />\n </template>\n\n <div\n :id=\"filterIds.All\"\n class=\"request-section-content custom-scroll relative flex flex-1 flex-col\"\n :role=\"selectedFilter === 'All' ? 'tabpanel' : 'none'\">\n <!-- Auth Selector -->\n <AuthSelector\n v-show=\"isSectionVisible('Auth') && !isAuthHidden\"\n :id=\"filterIds.Auth\"\n :createAnySecurityScheme=\"layout !== 'modal'\"\n :defaultOpen=\"isAuthDefaultOpen\"\n :environment\n :eventBus\n :meta=\"authMeta\"\n :options\n :proxyUrl\n :securityRequirements\n :securitySchemes\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n title=\"Authentication\" />\n\n <!-- Variables (Path Parameters) -->\n <RequestParams\n v-show=\"isSectionVisible('Variables') && sections.path?.length\"\n :id=\"filterIds.Variables\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"sections.path ?? []\"\n :showAddRowPlaceholder=\"false\"\n title=\"Variables\"\n v-on=\"parameterHandlers.path\" />\n\n <!-- Cookies -->\n <RequestParams\n v-show=\"isSectionVisible('Cookies')\"\n :id=\"filterIds.Cookies\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"cookies ?? []\"\n :showAddRowPlaceholder=\"true\"\n title=\"Cookies\"\n v-on=\"parameterHandlers.cookie\" />\n\n <!-- Headers -->\n <RequestParams\n v-show=\"isSectionVisible('Headers')\"\n :id=\"filterIds.Headers\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"headers ?? []\"\n title=\"Headers\"\n v-on=\"parameterHandlers.header\" />\n\n <!-- Query Parameters -->\n <RequestParams\n v-show=\"isSectionVisible('Query')\"\n :id=\"filterIds.Query\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"sections.query ?? []\"\n title=\"Query Parameters\"\n v-on=\"parameterHandlers.query\" />\n\n <!-- Request Body -->\n <RequestBody\n v-show=\"isSectionVisible('Body') && canMethodHaveBody(method)\"\n :id=\"filterIds.Body\"\n :defaultView=\"defaultRequestBodyView\"\n :environment\n :exampleKey\n :requestBody=\"getResolvedRef(operation.requestBody)\"\n :requestBodyCompositionSelection\n title=\"Request Body\"\n @generate:example=\"handleGenerateExample\"\n @update:contentType=\"handleUpdateContentType\"\n @update:formValue=\"handleUpdateBodyFormValue\"\n @update:value=\"handleUpdateBodyValue\" />\n\n <!-- Inject request section plugin components -->\n <ScalarErrorBoundary\n v-for=\"(plugin, index) in plugins\"\n :key=\"index\">\n <component\n :is=\"plugin.components.request.component\"\n v-if=\"plugin?.components?.request\"\n v-show=\"selectedFilter === 'All'\"\n :operation\n v-bind=\"plugin.components.request.additionalProps\"\n @operation:update:extension=\"updateOperationExtension\" />\n </ScalarErrorBoundary>\n\n <!-- Spacer -->\n <div class=\"flex grow\" />\n <!-- Code Snippet -->\n <RequestCodeSnippet\n v-show=\"selectedFilter === 'All'\"\n :clientOptions\n :eventBus\n :globalCookies\n integration=\"client\"\n :method\n :operation\n :path\n :securitySchemes=\"selectedSecuritySchemes\"\n :selectedClient\n :selectedContentType=\"\n getResolvedRef(operation.requestBody)?.[\n 'x-scalar-selected-content-type'\n ]?.[exampleKey]\n \"\n :selectedServer=\"server ?? undefined\" />\n </div>\n </ViewLayoutSection>\n</template>\n<style scoped>\n.request-section-content {\n --scalar-border-width: 0.5px;\n}\n.request-section-content-filter {\n box-shadow: 0 -10px 0 10px var(--scalar-background-1);\n}\n.request-item:focus-within .request-meta-buttons {\n opacity: 1;\n}\n.group-hover-input {\n border-width: var(--scalar-border-width);\n border-color: transparent;\n}\n.group:hover .group-hover-input {\n background: color-mix(\n in srgb,\n var(--scalar-background-1),\n var(--scalar-background-2)\n );\n border-color: var(--scalar-border-color);\n}\n.group-hover-input:focus {\n background: transparent !important;\n border-color: var(--scalar-border-color) !important;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"RequestBlock.vue.js","names":[],"sources":["../../../../src/v2/blocks/request-block/RequestBlock.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ClientOptionGroup } from '@scalar/blocks/code-example'\nimport { ScalarErrorBoundary } from '@scalar/components/error-boundary'\nimport { canMethodHaveBody } from '@scalar/helpers/http/can-method-have-body'\nimport { REGEX } from '@scalar/helpers/regex/regex-helpers'\nimport { replaceEnvVariables } from '@scalar/helpers/regex/replace-variables'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n AuthMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport { getUniqueExampleName } from '@scalar/workspace-store/navigation'\nimport {\n filterGlobalCookie,\n getEnvironmentVariables,\n getResolvedUrl,\n getSchemaExampleFromBody,\n type MergedSecuritySchemes,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OpenApiDocument,\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { computed, ref, useId, watch } from 'vue'\n\nimport SectionFilter from '@/components/SectionFilter.vue'\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport RequestBody from '@/v2/blocks/request-block/components/RequestBody.vue'\nimport RequestCodeSnippet from '@/v2/blocks/request-block/components/RequestCodeSnippet.vue'\nimport RequestParams from '@/v2/blocks/request-block/components/RequestParams.vue'\nimport type { TableRow } from '@/v2/blocks/request-block/components/RequestTableRow.vue'\nimport { createParameterHandlers } from '@/v2/blocks/request-block/helpers/create-parameter-handlers'\nimport { createParameterRows } from '@/v2/blocks/request-block/helpers/create-parameter-rows'\nimport { groupBy } from '@/v2/blocks/request-block/helpers/group-by'\nimport { groupGlobalCookies } from '@/v2/blocks/request-block/helpers/group-global-cookies'\nimport { getStructuredBodyCodec } from '@/v2/blocks/request-block/helpers/structured-body-codec'\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport { useLocalization } from '@/v2/features/localization'\nimport type { ClientLayout } from '@/v2/types/layout'\n\ntype Filter =\n | 'All'\n | 'Auth'\n | 'Variables'\n | 'Cookies'\n | 'Headers'\n | 'Query'\n | 'Body'\n\nexport type RequestBlockProps = {\n authMeta: AuthMeta\n clientOptions: ClientOptionGroup[]\n environment: XScalarEnvironment\n eventBus: WorkspaceEventBus\n exampleKey: string\n workspaceCookies: XScalarCookie[]\n documentCookies: XScalarCookie[]\n /** Slug of the document the operation belongs to */\n documentSlug: string\n layout: ClientLayout\n method: string\n operation: OperationObject\n /** Operation before downloaded examples are overlaid, for parameter edit targets. */\n sourceOperation?: OperationObject\n path: string\n plugins: ClientPlugin[]\n proxyUrl: string\n securityRequirements: OpenApiDocument['security']\n securitySchemes: MergedSecuritySchemes\n requestBodyCompositionSelection?: Record<string, number>\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n selectedSecurity: SelectedSecurity\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n server: ServerObject | null\n defaultHeaders: Record<string, string>\n /** Initial view for structured request bodies, from the `x-scalar-default-request-body-view` document extension */\n defaultRequestBodyView?: 'form' | 'raw'\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}\n\nconst {\n authMeta = { type: 'document' },\n clientOptions,\n environment,\n eventBus,\n exampleKey,\n workspaceCookies,\n documentCookies,\n documentSlug,\n layout,\n method,\n operation,\n sourceOperation,\n path,\n plugins,\n proxyUrl,\n requestBodyCompositionSelection,\n securityRequirements,\n securitySchemes,\n selectedClient,\n selectedSecurity,\n selectedSecuritySchemes,\n server,\n defaultHeaders: autoGeneratedHeaders,\n defaultRequestBodyView = 'raw',\n} = defineProps<RequestBlockProps>()\n\nconst { translate } = useLocalization()\n\n/** Base name for examples created by the \"generate example from schema\" button */\nconst GENERATED_EXAMPLE_NAME = 'Generated from schema'\n\n/** Operation metadata used across event emissions */\nconst meta = computed(() => ({\n method,\n path,\n exampleKey,\n}))\n\nconst deletedExpandedParameterPaths = ref<Record<string, string[][]>>({})\n\n/** Renamed expanded rows, tracked as old-schema-path -> typed-value-path per parameter. */\nconst renamedExpandedParameterPaths = ref<\n Record<string, { from: string[]; to: string[] }[]>\n>({})\n\nconst getExpandedParameterKey = (parameter: {\n in: string\n name: string\n}): string => `${parameter.in}:${parameter.name}`\n\nconst getHiddenValuePaths = (parameter: {\n in: string\n name: string\n}): string[][] =>\n deletedExpandedParameterPaths.value[getExpandedParameterKey(parameter)] ?? []\n\nconst getRenamedValuePaths = (parameter: {\n in: string\n name: string\n}): { from: string[]; to: string[] }[] =>\n renamedExpandedParameterPaths.value[getExpandedParameterKey(parameter)] ?? []\n\nconst pathsEqual = (a: string[], b: string[]): boolean =>\n a.length === b.length && a.every((segment, index) => segment === b[index])\n\n/**\n * Hides the schema path of an expanded row so it does not reappear as an empty suggestion. Used\n * both when a row is deleted and when its key is renamed (the old key should not pop back up).\n */\nconst hideExpandedRowPath = (row: TableRow): void => {\n if (!row.originalParameter || !row.sourceParameterValuePath) {\n return\n }\n\n const key = getExpandedParameterKey(row.originalParameter)\n deletedExpandedParameterPaths.value = {\n ...deletedExpandedParameterPaths.value,\n [key]: [\n ...(deletedExpandedParameterPaths.value[key] ?? []),\n row.sourceParameterValuePath,\n ],\n }\n}\n\n/**\n * Records that an expanded row was renamed from its current value path to the typed one, so the\n * read side can render the renamed key in the original property's slot instead of appending it to\n * the end of the table. Repeated renames of the same row stay anchored to the original schema path.\n */\nconst recordExpandedRowRename = (\n row: TableRow,\n newValuePath: string[],\n): void => {\n if (!row.originalParameter || !row.sourceParameterValuePath) {\n return\n }\n\n const from = row.sourceParameterValuePath\n const key = getExpandedParameterKey(row.originalParameter)\n const existing = renamedExpandedParameterPaths.value[key] ?? []\n\n // If this row was already renamed, the row's current path is the previous target. Re-anchor that\n // entry to the new target so a second rename does not create an orphaned mapping.\n const chained = existing.find((entry) => pathsEqual(entry.to, from))\n const next = chained\n ? existing.map((entry) =>\n entry === chained ? { from: entry.from, to: newValuePath } : entry,\n )\n : [...existing, { from, to: newValuePath }]\n\n renamedExpandedParameterPaths.value = {\n ...renamedExpandedParameterPaths.value,\n [key]: next,\n }\n}\n\n/** Whole-query parameters share the Query section but retain their original identity. */\nconst hasQuerystringParameter = computed(\n () =>\n operation.parameters?.some(\n (parameter) => getResolvedRef(parameter)?.in === 'querystring',\n ) ?? false,\n)\n\n/** Parameters grouped by type (path, query, header, cookie) */\nconst sections = computed(() =>\n groupBy(\n operation.parameters?.flatMap((reference, index) => {\n const param = getResolvedRef(reference)\n if (!param) return []\n return createParameterRows(param, exampleKey, {\n hiddenValuePaths:\n param.in === 'query' ? getHiddenValuePaths(param) : [],\n renamedValuePaths:\n param.in === 'query' ? getRenamedValuePaths(param) : [],\n }).map((row) => ({\n ...row,\n // Overlays retain parameter order, but their downloaded values are read-only.\n originalParameter:\n getResolvedRef(sourceOperation?.parameters?.[index]) ?? param,\n in: param.in === 'querystring' ? 'query' : param.in,\n }))\n }) ?? [],\n 'in',\n ({ in: _in, ...row }) => {\n return row\n },\n ),\n)\n\n// Generate a reverse map for fast lookup of headers by the name\nconst headersMap = computed(() =>\n groupBy(\n sections.value.header?.map((it) => ({\n ...it,\n name: it.name.toLowerCase(),\n })) ?? [],\n 'name',\n ),\n)\n\nconst defaultHeaders = computed(() => {\n const disableParameters =\n operation['x-scalar-disable-parameters']?.['default-headers']?.[\n exampleKey\n ] ?? {}\n\n const isOverridden = (name: string) => {\n const header = headersMap.value[name.toLowerCase()]?.[0]\n\n if (!header) {\n return false\n }\n\n return !header.isDisabled\n }\n\n return Object.entries(autoGeneratedHeaders).map(([name, value]) => {\n return {\n name,\n value,\n schema: undefined,\n isOverridden: isOverridden(name),\n isReadonly: true,\n isDisabled: disableParameters[name.toLowerCase()] ?? false,\n } satisfies TableRow\n })\n})\n\nconst headers = computed(() => [\n ...defaultHeaders.value,\n ...(sections.value.header ?? []),\n])\n\n/** Resolved request URL, used to filter global cookies by their domain and path. */\nconst requestCookieUrl = computed(() => {\n const environmentVariables = getEnvironmentVariables(environment)\n const resolvedUrl = getResolvedUrl({ server, path })\n return replaceEnvVariables(resolvedUrl, environmentVariables)\n})\n\n/**\n * Global cookies grouped by name. Same-named cookies collapse into a single logical cookie so\n * duplicate names no longer share one disabled state (which made toggling one toggle them all).\n * A name with multiple values becomes a preset the user can switch between.\n */\nconst globalCookieGroups = computed(() =>\n groupGlobalCookies({\n sources: [\n { location: 'workspace', cookies: workspaceCookies },\n { location: 'document', cookies: documentCookies },\n ],\n // Keep domain/path filtering but ignore the disabled flag, so a disabled preset value stays\n // selectable in the switcher (it is only hidden from the request, not from the dropdown).\n shouldInclude: (cookie) =>\n filterGlobalCookie({\n cookie: { ...cookie, isDisabled: false },\n url: requestCookieUrl.value,\n disabledGlobalCookies: {},\n }),\n }),\n)\n\nconst defaultCookies = computed<TableRow[]>(() => {\n const disabledGlobalCookies =\n operation['x-scalar-disable-parameters']?.['global-cookies']?.[\n exampleKey\n ] ?? {}\n\n return globalCookieGroups.value.map((group) => ({\n name: group.name,\n value: group.selectedValue,\n globalRoute: { page: group.location, path: 'cookies' } as const,\n isReadonly: true,\n isDisabled: disabledGlobalCookies[group.name.toLowerCase()] ?? false,\n presetOptions: group.isPreset ? group.options : undefined,\n }))\n})\n\n/**\n * Switch a grouped global cookie preset to the chosen value by enabling the matching sibling and\n * disabling the rest. Selection is written back to the source `x-scalar-cookies` list so it\n * persists, and the send path drops disabled cookies, so only the selected value is sent.\n */\nconst handleSelectCookiePreset = (index: number, value: string): void => {\n const group = globalCookieGroups.value[index]\n if (!group) {\n return\n }\n\n for (const sibling of group.siblings) {\n eventBus.emit('cookie:upsert:cookie', {\n collectionType: sibling.location,\n index: sibling.index,\n payload: { isDisabled: sibling.value !== value },\n })\n }\n}\n\nconst cookies = computed(() => [\n ...(defaultCookies.value ?? []),\n ...(sections.value.cookie ?? []),\n])\n\n/** Currently selected filter for the request sections */\nconst selectedFilter = ref<Filter>('All')\n\n/** Available operation sections */\nconst OPERATION_SECTIONS: readonly Filter[] = [\n 'Auth',\n 'Variables',\n 'Cookies',\n 'Headers',\n 'Query',\n 'Body',\n] as const\n\n/**\n * Pre-generated stable IDs for all possible filter sections.\n * These are created once at setup time to avoid regenerating IDs on re-render.\n */\nconst sectionIds: Record<Filter, string> = {\n All: useId(),\n Auth: useId(),\n Variables: useId(),\n Cookies: useId(),\n Headers: useId(),\n Query: useId(),\n Body: useId(),\n}\n\n/** Filters available based on operation state */\nconst filters = computed<Filter[]>(() => {\n const availableFilters = new Set<Filter>(['All', ...OPERATION_SECTIONS])\n\n if (!sections.value.path?.length) {\n availableFilters.delete('Variables')\n }\n if (!canMethodHaveBody(method)) {\n availableFilters.delete('Body')\n }\n if (isAuthHidden.value) {\n availableFilters.delete('Auth')\n }\n\n return [...availableFilters]\n})\n\n/**\n * Map available filters to their pre-generated stable IDs.\n * Only includes IDs for filters that are currently available.\n */\nconst filterIds = computed(() =>\n filters.value.reduce<Partial<Record<Filter, string>>>((ids, section) => {\n ids[section] = sectionIds[section]\n return ids\n }, {}),\n)\n\n/**\n * Hide auth selector in readonly mode when no security schemes are defined.\n * This keeps the UI clean when there are no authentication options available.\n */\nconst isAuthHidden = computed(\n () => layout === 'modal' && !Object.keys(securitySchemes ?? {}).length,\n)\n\n/**\n * Keep auth available for unauthenticated operations, but collapse it by default\n * in readonly modal layouts unless a requirement or manual selection exists.\n */\nconst isAuthDefaultOpen = computed(\n () =>\n layout !== 'modal' ||\n Boolean(\n securityRequirements?.length || selectedSecurity.selectedSchemes.length,\n ),\n)\n\n/** Get a sensible placeholder for the request name input */\nconst requestNamePlaceholder = computed(() => {\n if (operation.summary) {\n return operation.summary\n }\n const cleanPath = path.replace(REGEX.PROTOCOL, '')\n return cleanPath || translate('apiClient.requestBlock.requestName')\n})\n\n/** Check if the section should be shown based on the selected filter */\nconst isSectionVisible = (section: Filter): boolean => {\n return selectedFilter.value === 'All' || selectedFilter.value === section\n}\n\n/**\n * Reset filter to 'All' if Body filter is selected but method changes to one that cannot have a body.\n * This prevents showing an empty Body section when switching methods.\n */\nwatch(\n () => method,\n (newMethod) => {\n if (selectedFilter.value === 'Body' && !canMethodHaveBody(newMethod)) {\n selectedFilter.value = 'All'\n }\n },\n)\n\n// Expanded-row bookkeeping is keyed by `in:name`, which is not unique across operations or\n// examples. Reset both maps when the operation or example changes so stale delete/rename mappings\n// do not leak onto another request that happens to share a query parameter name.\nwatch(\n () => [method, path, exampleKey],\n () => {\n deletedExpandedParameterPaths.value = {}\n renamedExpandedParameterPaths.value = {}\n },\n)\n\n/** Handle operation summary updates */\nconst handleSummaryUpdate = (event: Event): void => {\n if (!(event.target instanceof HTMLInputElement)) {\n return\n }\n const summary = event.target.value\n eventBus.emit('operation:update:meta', {\n meta: meta.value,\n payload: { summary: summary.trim() },\n })\n}\n\n/** Parameter handlers */\nconst parameterHandlers = computed(() => ({\n path: createParameterHandlers('path', eventBus, meta.value, {\n context: sections.value.path ?? [],\n }),\n cookie: {\n ...createParameterHandlers('cookie', eventBus, meta.value, {\n context: cookies.value ?? [],\n globalParameters: defaultCookies.value.length,\n }),\n selectPreset: handleSelectCookiePreset,\n },\n header: createParameterHandlers('header', eventBus, meta.value, {\n context: headers.value,\n defaultParameters: defaultHeaders.value.length,\n }),\n query: createParameterHandlers('query', eventBus, meta.value, {\n context: sections.value.query ?? [],\n onDeleteExpandedRow: hideExpandedRowPath,\n onRenameExpandedRow: recordExpandedRowRename,\n }),\n}))\n\n/** Handle request body content type update */\nconst handleUpdateContentType = (payload: { value: string }): void =>\n eventBus.emit('operation:update:requestBody:contentType', {\n payload: { contentType: payload.value },\n meta: meta.value,\n })\n\n/** Handle request body value update */\nconst handleUpdateBodyValue = ({\n payload,\n contentType,\n}: Pick<\n ApiReferenceEvents['operation:update:requestBody:value'],\n 'payload' | 'contentType'\n>): void => {\n const debounceKey =\n typeof payload === 'string'\n ? `update:requestBody:value-${contentType}`\n : undefined\n\n eventBus.emit(\n 'operation:update:requestBody:value',\n {\n payload,\n contentType,\n meta: meta.value,\n },\n {\n debounceKey,\n },\n )\n}\n\n/** Handle request body value update */\nconst handleUpdateBodyFormValue = ({\n payload,\n contentType,\n}: Pick<\n ApiReferenceEvents['operation:update:requestBody:formValue'],\n 'payload' | 'contentType'\n>): void => {\n const debounceKey = `update:requestBody:${contentType}-form-value`\n\n eventBus.emit(\n 'operation:update:requestBody:formValue',\n {\n payload: payload.map((row) => unpackProxyObject(row, { depth: 1 })),\n contentType,\n meta: meta.value,\n },\n {\n debounceKey,\n },\n )\n}\n\n/**\n * Create a new example seeded with values generated from the request body schema.\n *\n * Custom examples in the document otherwise hide the auto-generated fields entirely. Rather than\n * only rendering the generated body, we write it into a fresh example so the user can edit it and\n * so it survives an export of the document.\n */\nconst handleGenerateExample = ({\n contentType,\n}: {\n contentType: string\n}): void => {\n const requestBody = getResolvedRef(operation.requestBody)\n const codec = getStructuredBodyCodec(contentType)\n if (!requestBody || !codec) {\n return\n }\n\n const value = getSchemaExampleFromBody(\n requestBody,\n contentType,\n requestBodyCompositionSelection,\n )\n\n // A schema that generates nothing writable would leave the user on an empty new example.\n if (value === undefined || value === null) {\n return\n }\n\n const exampleName = getUniqueExampleName(operation, GENERATED_EXAMPLE_NAME)\n const exampleMeta = { path, method, exampleKey: exampleName }\n\n eventBus.emit('operation:create:draft-example', {\n documentName: documentSlug,\n meta: { path, method },\n exampleName,\n })\n\n // Carry over the content type the user was looking at, otherwise the new example opens on\n // whichever content type happens to come first on the request body.\n eventBus.emit('operation:update:requestBody:contentType', {\n payload: { contentType },\n meta: exampleMeta,\n })\n\n eventBus.emit('operation:update:requestBody:value', {\n payload: codec.stringify(value),\n contentType,\n meta: exampleMeta,\n })\n\n // The modal selects the example after its creation hook rebuilds the sidebar.\n if (layout === 'modal') {\n return\n }\n\n eventBus.emit('ui:navigate', {\n page: 'example',\n documentSlug,\n path,\n method,\n exampleName,\n })\n}\n\nconst labelRequestNameId = useId()\n\nconst globalCookies = computed(() => [...workspaceCookies, ...documentCookies])\n\n/** Allow updating the operation extensions for the plugins */\nconst updateOperationExtension = (\n payload: ApiReferenceEvents['operation:update:extension']['payload'],\n): void =>\n eventBus.emit('operation:update:extension', { payload, meta: meta.value })\n\nconst filterLabels = computed(() => ({\n All: translate('apiClient.sectionFilter.all'),\n Auth: translate('apiClient.sectionFilter.auth'),\n Variables: translate('apiClient.sectionFilter.variables'),\n Cookies: translate('apiClient.sectionFilter.cookies'),\n Headers: translate('apiClient.sectionFilter.headers'),\n Query: translate('apiClient.sectionFilter.query'),\n Body: translate('apiClient.sectionFilter.body'),\n}))\n</script>\n<template>\n <ViewLayoutSection\n :aria-label=\"\n translate('apiClient.requestBlock.label', {\n name: operation.summary ?? '',\n })\n \">\n <template #title>\n <div\n class=\"group pointer-events-none flex flex-1 items-center gap-1 lg:pe-24\">\n <label\n v-if=\"layout !== 'modal'\"\n class=\"pointer-events-auto absolute top-0 left-0 h-full w-full cursor-text opacity-0\"\n :for=\"labelRequestNameId\" />\n <input\n v-if=\"layout !== 'modal'\"\n :id=\"labelRequestNameId\"\n class=\"text-c-1 group-hover-input pointer-events-auto relative z-10 -ml-0.5 h-8 w-full rounded pl-1.25 has-[:focus-visible]:outline md:-ml-1.25\"\n :placeholder=\"requestNamePlaceholder\"\n :value=\"operation.summary\"\n @blur=\"handleSummaryUpdate\" />\n <span\n v-else\n class=\"text-c-1 flex h-8 items-center\">\n {{ operation.summary }}\n </span>\n </div>\n <SectionFilter\n v-model=\"selectedFilter\"\n :filterIds=\"filterIds\"\n :filters=\"filters\"\n :labels=\"filterLabels\" />\n </template>\n\n <div\n :id=\"filterIds.All\"\n class=\"request-section-content custom-scroll relative flex flex-1 flex-col\"\n :role=\"selectedFilter === 'All' ? 'tabpanel' : 'none'\">\n <!-- Auth Selector -->\n <AuthSelector\n v-show=\"isSectionVisible('Auth') && !isAuthHidden\"\n :id=\"filterIds.Auth\"\n :createAnySecurityScheme=\"layout !== 'modal'\"\n :defaultOpen=\"isAuthDefaultOpen\"\n :environment\n :eventBus\n :meta=\"authMeta\"\n :options\n :proxyUrl\n :securityRequirements\n :securitySchemes\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :title=\"translate('apiClient.requestBlock.authentication')\" />\n\n <!-- Variables (Path Parameters) -->\n <RequestParams\n v-show=\"isSectionVisible('Variables') && sections.path?.length\"\n :id=\"filterIds.Variables\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"sections.path ?? []\"\n :showAddRowPlaceholder=\"false\"\n :title=\"translate('apiClient.requestBlock.variables')\"\n v-on=\"parameterHandlers.path\" />\n\n <!-- Cookies -->\n <RequestParams\n v-show=\"isSectionVisible('Cookies')\"\n :id=\"filterIds.Cookies\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"cookies ?? []\"\n :showAddRowPlaceholder=\"true\"\n :title=\"translate('apiClient.requestBlock.cookies')\"\n v-on=\"parameterHandlers.cookie\" />\n\n <!-- Headers -->\n <RequestParams\n v-show=\"isSectionVisible('Headers')\"\n :id=\"filterIds.Headers\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"headers ?? []\"\n :title=\"translate('apiClient.requestBlock.headers')\"\n v-on=\"parameterHandlers.header\" />\n\n <!-- Query Parameters -->\n <RequestParams\n v-show=\"isSectionVisible('Query')\"\n :id=\"filterIds.Query\"\n :description=\"\n hasQuerystringParameter\n ? translate('apiClient.requestBlock.queryStringDescription')\n : undefined\n \"\n :environment\n :eventBus\n :exampleKey\n :rows=\"sections.query ?? []\"\n :showAddRowPlaceholder=\"!hasQuerystringParameter\"\n :title=\"\n hasQuerystringParameter\n ? translate('apiClient.requestBlock.queryString')\n : translate('apiClient.requestBlock.queryParameters')\n \"\n v-on=\"parameterHandlers.query\" />\n\n <!-- Request Body -->\n <RequestBody\n v-show=\"isSectionVisible('Body') && canMethodHaveBody(method)\"\n :id=\"filterIds.Body\"\n :defaultView=\"defaultRequestBodyView\"\n :environment\n :exampleKey\n :requestBody=\"getResolvedRef(operation.requestBody)\"\n :requestBodyCompositionSelection\n :title=\"translate('apiClient.requestBlock.requestBody')\"\n @generate:example=\"handleGenerateExample\"\n @update:contentType=\"handleUpdateContentType\"\n @update:formValue=\"handleUpdateBodyFormValue\"\n @update:value=\"handleUpdateBodyValue\" />\n\n <!-- Inject request section plugin components -->\n <ScalarErrorBoundary\n v-for=\"(plugin, index) in plugins\"\n :key=\"index\">\n <component\n :is=\"plugin.components.request.component\"\n v-if=\"plugin?.components?.request\"\n v-show=\"selectedFilter === 'All'\"\n :operation\n v-bind=\"plugin.components.request.additionalProps\"\n @operation:update:extension=\"updateOperationExtension\" />\n </ScalarErrorBoundary>\n\n <!-- Spacer -->\n <div class=\"flex grow\" />\n <!-- Code Snippet -->\n <RequestCodeSnippet\n v-show=\"selectedFilter === 'All'\"\n :clientOptions\n :eventBus\n :globalCookies\n integration=\"client\"\n :method\n :operation\n :path\n :securitySchemes=\"selectedSecuritySchemes\"\n :selectedClient\n :selectedContentType=\"\n getResolvedRef(operation.requestBody)?.[\n 'x-scalar-selected-content-type'\n ]?.[exampleKey]\n \"\n :selectedExample=\"exampleKey\"\n :selectedServer=\"server ?? undefined\" />\n </div>\n </ViewLayoutSection>\n</template>\n<style scoped>\n.request-section-content {\n --scalar-border-width: 0.5px;\n}\n.request-section-content-filter {\n box-shadow: 0 -10px 0 10px var(--scalar-background-1);\n}\n.request-item:focus-within .request-meta-buttons {\n opacity: 1;\n}\n.group-hover-input {\n border-width: var(--scalar-border-width);\n border-color: transparent;\n}\n.group:hover .group-hover-input {\n background: color-mix(\n in srgb,\n var(--scalar-background-1),\n var(--scalar-background-2)\n );\n border-color: var(--scalar-border-color);\n}\n.group-hover-input:focus {\n background: transparent !important;\n border-color: var(--scalar-border-color) !important;\n}\n</style>\n"],"mappings":""}