@scalar/api-client 3.14.0 → 3.16.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 (369) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/assets/computer.ascii.virtual.js.map +1 -1
  3. package/dist/components/HelpfulLink.vue.script.js +1 -1
  4. package/dist/components/HelpfulLink.vue.script.js.map +1 -1
  5. package/dist/components/HttpMethod/HttpMethod.vue.js +1 -1
  6. package/dist/components/HttpMethod/HttpMethod.vue.script.js +1 -1
  7. package/dist/components/HttpMethod/HttpMethod.vue.script.js.map +1 -1
  8. package/dist/components/ScalarAsciiArt/ScalarAsciiArt.vue.js +1 -1
  9. package/dist/components/ScalarAsciiArt/ScalarAsciiArt.vue.script.js +1 -1
  10. package/dist/components/ScalarAsciiArt/ScalarAsciiArt.vue.script.js.map +1 -1
  11. package/dist/components/SectionFilter.vue.d.ts +1 -1
  12. package/dist/components/SectionFilter.vue.d.ts.map +1 -1
  13. package/dist/components/SectionFilter.vue.js +1 -1
  14. package/dist/components/SectionFilter.vue.script.js +2 -2
  15. package/dist/components/SectionFilter.vue.script.js.map +1 -1
  16. package/dist/components/SectionFilterButton.vue.script.js +1 -1
  17. package/dist/components/SectionFilterButton.vue.script.js.map +1 -1
  18. package/dist/components/Server/ServerVariablesForm.vue.d.ts.map +1 -1
  19. package/dist/components/Server/ServerVariablesForm.vue.script.js +1 -1
  20. package/dist/components/Server/ServerVariablesForm.vue.script.js.map +1 -1
  21. package/dist/components/Server/ServerVariablesSelect.vue.script.js +1 -1
  22. package/dist/components/Server/ServerVariablesSelect.vue.script.js.map +1 -1
  23. package/dist/components/Server/ServerVariablesTextbox.vue.script.js +1 -1
  24. package/dist/components/Server/ServerVariablesTextbox.vue.script.js.map +1 -1
  25. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.d.ts.map +1 -1
  26. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.script.js +1 -1
  27. package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.script.js.map +1 -1
  28. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.d.ts.map +1 -1
  29. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.script.js +1 -1
  30. package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.script.js.map +1 -1
  31. package/dist/components/ViewLayout/ViewLayout.vue.script.js +1 -1
  32. package/dist/components/ViewLayout/ViewLayout.vue.script.js.map +1 -1
  33. package/dist/components/ViewLayout/ViewLayoutContent.vue.js +1 -1
  34. package/dist/components/ViewLayout/ViewLayoutContent.vue.js.map +1 -1
  35. package/dist/components/ViewLayout/ViewLayoutSection.vue.script.js +1 -1
  36. package/dist/components/ViewLayout/ViewLayoutSection.vue.script.js.map +1 -1
  37. package/dist/hooks/use-file-dialog.js +2 -1
  38. package/dist/hooks/use-file-dialog.js.map +1 -1
  39. package/dist/plugins/posthog/index.js.map +1 -1
  40. package/dist/plugins/posthog/sanitize-event-payload.js +1 -1
  41. package/dist/plugins/posthog/sanitize-event-payload.js.map +1 -1
  42. package/dist/style.css +298 -275
  43. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
  44. package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
  45. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +38 -6
  46. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
  47. package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
  48. package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
  49. package/dist/v2/blocks/operation-block/components/Header.vue.script.js +1 -1
  50. package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
  51. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.js +1 -1
  52. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.script.js +1 -1
  53. package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.script.js.map +1 -1
  54. package/dist/v2/blocks/operation-block/helpers/decode-buffer.js.map +1 -1
  55. package/dist/v2/blocks/operation-block/helpers/get-cookie-header-keys.js.map +1 -1
  56. package/dist/v2/blocks/operation-block/helpers/har-to-fetch-request.js.map +1 -1
  57. package/dist/v2/blocks/operation-block/helpers/har-to-fetch-response.js.map +1 -1
  58. package/dist/v2/blocks/operation-block/helpers/persist-response-cookies.js.map +1 -1
  59. package/dist/v2/blocks/operation-block/helpers/persist-script-environment.d.ts +53 -0
  60. package/dist/v2/blocks/operation-block/helpers/persist-script-environment.d.ts.map +1 -0
  61. package/dist/v2/blocks/operation-block/helpers/persist-script-environment.js +91 -0
  62. package/dist/v2/blocks/operation-block/helpers/persist-script-environment.js.map +1 -0
  63. package/dist/v2/blocks/operation-block/helpers/response-cache.js.map +1 -1
  64. package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
  65. package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js.map +1 -1
  66. package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts.map +1 -1
  67. package/dist/v2/blocks/request-block/RequestBlock.vue.js +1 -1
  68. package/dist/v2/blocks/request-block/RequestBlock.vue.js.map +1 -1
  69. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +58 -29
  70. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
  71. package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
  72. package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
  73. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +1 -1
  74. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
  75. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.d.ts.map +1 -1
  76. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.script.js +1 -1
  77. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.script.js.map +1 -1
  78. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.d.ts.map +1 -1
  79. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js +1 -1
  80. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js.map +1 -1
  81. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.script.js +1 -1
  82. package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.script.js.map +1 -1
  83. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
  84. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +1 -1
  85. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
  86. package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts +2 -0
  87. package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts.map +1 -1
  88. package/dist/v2/blocks/request-block/components/RequestParams.vue.js.map +1 -1
  89. package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js +5 -3
  90. package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js.map +1 -1
  91. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +2 -0
  92. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
  93. package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
  94. package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
  95. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js +6 -3
  96. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
  97. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +8 -0
  98. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
  99. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
  100. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +29 -16
  101. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
  102. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js +1 -1
  103. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js.map +1 -1
  104. package/dist/v2/blocks/request-block/helpers/create-parameter-handlers.js.map +1 -1
  105. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js +1 -1
  106. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js.map +1 -1
  107. package/dist/v2/blocks/request-block/helpers/files.js.map +1 -1
  108. package/dist/v2/blocks/request-block/helpers/fold-structured-body-rows.js.map +1 -1
  109. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +10 -5
  110. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js.map +1 -1
  111. package/dist/v2/blocks/request-block/helpers/get-parameter-content.js.map +1 -1
  112. package/dist/v2/blocks/request-block/helpers/get-parameter-schema.js.map +1 -1
  113. package/dist/v2/blocks/request-block/helpers/get-structured-body-rows.js.map +1 -1
  114. package/dist/v2/blocks/request-block/helpers/group-by.js.map +1 -1
  115. package/dist/v2/blocks/request-block/helpers/group-global-cookies.d.ts +54 -0
  116. package/dist/v2/blocks/request-block/helpers/group-global-cookies.d.ts.map +1 -0
  117. package/dist/v2/blocks/request-block/helpers/group-global-cookies.js +56 -0
  118. package/dist/v2/blocks/request-block/helpers/group-global-cookies.js.map +1 -0
  119. package/dist/v2/blocks/request-block/helpers/structured-body-codec.js +1 -1
  120. package/dist/v2/blocks/request-block/helpers/structured-body-codec.js.map +1 -1
  121. package/dist/v2/blocks/request-block/helpers/validate-parameter.js.map +1 -1
  122. package/dist/v2/blocks/response-block/ResponseBlock.vue.d.ts.map +1 -1
  123. package/dist/v2/blocks/response-block/ResponseBlock.vue.js +1 -1
  124. package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js +1 -1
  125. package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js.map +1 -1
  126. package/dist/v2/blocks/response-block/components/Headers.vue.script.js +1 -1
  127. package/dist/v2/blocks/response-block/components/Headers.vue.script.js.map +1 -1
  128. package/dist/v2/blocks/response-block/components/ResponseBody.vue.js +1 -1
  129. package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js +1 -1
  130. package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js.map +1 -1
  131. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.script.js +1 -1
  132. package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.script.js.map +1 -1
  133. package/dist/v2/blocks/response-block/components/ResponseBodyInfo.vue.js +1 -1
  134. package/dist/v2/blocks/response-block/components/ResponseBodyInfo.vue.js.map +1 -1
  135. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.d.ts.map +1 -1
  136. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.js +1 -1
  137. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.js.map +1 -1
  138. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.script.js +10 -3
  139. package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.script.js.map +1 -1
  140. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.js +1 -1
  141. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.script.js +1 -1
  142. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.script.js.map +1 -1
  143. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.d.ts.map +1 -1
  144. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.script.js +1 -1
  145. package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.script.js.map +1 -1
  146. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.script.js +1 -1
  147. package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.script.js.map +1 -1
  148. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.script.js +1 -1
  149. package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.script.js.map +1 -1
  150. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js +1 -1
  151. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js.map +1 -1
  152. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.js +1 -1
  153. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.script.js +1 -1
  154. package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.script.js.map +1 -1
  155. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.d.ts.map +1 -1
  156. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.js +1 -1
  157. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.script.js +1 -1
  158. package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.script.js.map +1 -1
  159. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.script.js +1 -1
  160. package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.script.js.map +1 -1
  161. package/dist/v2/blocks/response-block/helpers/extract-filename.js.map +1 -1
  162. package/dist/v2/blocks/response-block/helpers/get-content-length.js.map +1 -1
  163. package/dist/v2/blocks/response-block/helpers/media-types.d.ts +1 -1
  164. package/dist/v2/blocks/response-block/helpers/media-types.d.ts.map +1 -1
  165. package/dist/v2/blocks/response-block/helpers/media-types.js +12 -0
  166. package/dist/v2/blocks/response-block/helpers/media-types.js.map +1 -1
  167. package/dist/v2/blocks/response-block/helpers/parse-set-cookie.js.map +1 -1
  168. package/dist/v2/blocks/response-block/helpers/prettify-jsonc-string.js.map +1 -1
  169. package/dist/v2/blocks/response-block/helpers/prettify-ndjson.d.ts +12 -0
  170. package/dist/v2/blocks/response-block/helpers/prettify-ndjson.d.ts.map +1 -0
  171. package/dist/v2/blocks/response-block/helpers/prettify-ndjson.js +19 -0
  172. package/dist/v2/blocks/response-block/helpers/prettify-ndjson.js.map +1 -0
  173. package/dist/v2/blocks/response-block/helpers/process-response-body.js.map +1 -1
  174. package/dist/v2/blocks/response-block/helpers/resolve-response-body-handler.js.map +1 -1
  175. package/dist/v2/blocks/response-block/helpers/resolve-response-content-type.js +7 -1
  176. package/dist/v2/blocks/response-block/helpers/resolve-response-content-type.js.map +1 -1
  177. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
  178. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
  179. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +1 -1
  180. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
  181. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.d.ts.map +1 -1
  182. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js +1 -1
  183. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js +1 -1
  184. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js.map +1 -1
  185. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.d.ts.map +1 -1
  186. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js +1 -1
  187. package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js.map +1 -1
  188. package/dist/v2/blocks/scalar-address-bar-block/components/httpStatusCodeColors.js +3 -1
  189. package/dist/v2/blocks/scalar-address-bar-block/components/httpStatusCodeColors.js.map +1 -1
  190. package/dist/v2/blocks/scalar-address-bar-block/helpers/is-placeholder-path.js.map +1 -1
  191. package/dist/v2/blocks/scalar-address-bar-block/helpers/refocus-blur-target.js.map +1 -1
  192. package/dist/v2/blocks/scalar-address-bar-block/hooks/use-loading-animation.js.map +1 -1
  193. package/dist/v2/blocks/scalar-address-bar-block/hooks/use-path-masking.js.map +1 -1
  194. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.d.ts.map +1 -1
  195. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js +1 -1
  196. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
  197. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.d.ts.map +1 -1
  198. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.script.js +1 -1
  199. package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.script.js.map +1 -1
  200. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
  201. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +1 -1
  202. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
  203. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.d.ts.map +1 -1
  204. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.script.js +1 -1
  205. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.script.js.map +1 -1
  206. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.d.ts.map +1 -1
  207. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js +1 -1
  208. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js.map +1 -1
  209. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.d.ts.map +1 -1
  210. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js +1 -1
  211. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js.map +1 -1
  212. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.d.ts.map +1 -1
  213. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.script.js +1 -1
  214. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.script.js.map +1 -1
  215. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts.map +1 -1
  216. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js +3 -3
  217. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js.map +1 -1
  218. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
  219. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
  220. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js +24 -17
  221. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
  222. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.js.map +1 -1
  223. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js +5 -0
  224. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js.map +1 -1
  225. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-callback.js +1 -1
  226. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-callback.js.map +1 -1
  227. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows.d.ts +20 -0
  228. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows.d.ts.map +1 -0
  229. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows.js +27 -0
  230. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows.js.map +1 -0
  231. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +2 -2
  232. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
  233. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js.map +1 -1
  234. package/dist/v2/blocks/scalar-auth-selector-block/helpers/resolve-default-oauth2-redirect-url.js.map +1 -1
  235. package/dist/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize.js.map +1 -1
  236. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts.map +1 -1
  237. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js +15 -6
  238. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js.map +1 -1
  239. package/dist/v2/components/code-input/CodeInput.vue.d.ts.map +1 -1
  240. package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
  241. package/dist/v2/components/code-input/CodeInput.vue.script.js +6 -1
  242. package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
  243. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -1
  244. package/dist/v2/components/code-input/CodeInputLite.vue.js +1 -1
  245. package/dist/v2/components/code-input/CodeInputLite.vue.script.js +5 -1
  246. package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -1
  247. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js +1 -1
  248. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js.map +1 -1
  249. package/dist/v2/components/code-input/code-variable-widget.js +1 -0
  250. package/dist/v2/components/code-input/code-variable-widget.js.map +1 -1
  251. package/dist/v2/components/code-input/helpers/build-pill-context.js.map +1 -1
  252. package/dist/v2/components/code-input/helpers/lookup-variable-value.js.map +1 -1
  253. package/dist/v2/components/code-input/helpers/pill-signature.js.map +1 -1
  254. package/dist/v2/components/code-input/helpers/serialize-value.js.map +1 -1
  255. package/dist/v2/components/context-menu/ContextMenu.vue.script.js +1 -1
  256. package/dist/v2/components/context-menu/ContextMenu.vue.script.js.map +1 -1
  257. package/dist/v2/components/data-table/DataTable.vue.script.js +1 -1
  258. package/dist/v2/components/data-table/DataTable.vue.script.js.map +1 -1
  259. package/dist/v2/components/data-table/DataTableCell.vue.script.js +1 -1
  260. package/dist/v2/components/data-table/DataTableCell.vue.script.js.map +1 -1
  261. package/dist/v2/components/data-table/DataTableCheckbox.vue.script.js +1 -1
  262. package/dist/v2/components/data-table/DataTableCheckbox.vue.script.js.map +1 -1
  263. package/dist/v2/components/data-table/DataTableHeader.vue.script.js +1 -1
  264. package/dist/v2/components/data-table/DataTableHeader.vue.script.js.map +1 -1
  265. package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
  266. package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
  267. package/dist/v2/components/data-table/DataTableInput.vue.script.js +1 -1
  268. package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
  269. package/dist/v2/components/data-table/DataTableInputSelect.vue.d.ts.map +1 -1
  270. package/dist/v2/components/data-table/DataTableInputSelect.vue.script.js +3 -2
  271. package/dist/v2/components/data-table/DataTableInputSelect.vue.script.js.map +1 -1
  272. package/dist/v2/components/data-table/DataTableRow.vue.js +1 -1
  273. package/dist/v2/components/data-table/DataTableRow.vue.js.map +1 -1
  274. package/dist/v2/components/data-table/DataTableText.vue.script.js +1 -1
  275. package/dist/v2/components/data-table/DataTableText.vue.script.js.map +1 -1
  276. package/dist/v2/components/forms/ConfirmationForm.vue.d.ts.map +1 -1
  277. package/dist/v2/components/forms/ConfirmationForm.vue.script.js +1 -1
  278. package/dist/v2/components/forms/ConfirmationForm.vue.script.js.map +1 -1
  279. package/dist/v2/components/layout/CollapsibleSection.vue.d.ts.map +1 -1
  280. package/dist/v2/components/layout/CollapsibleSection.vue.script.js +1 -1
  281. package/dist/v2/components/layout/CollapsibleSection.vue.script.js.map +1 -1
  282. package/dist/v2/components/layout/ValueEmitter.vue.d.ts +1 -1
  283. package/dist/v2/components/layout/ValueEmitter.vue.d.ts.map +1 -1
  284. package/dist/v2/components/layout/ValueEmitter.vue.script.js +1 -1
  285. package/dist/v2/components/layout/ValueEmitter.vue.script.js.map +1 -1
  286. package/dist/v2/components/modals/DeleteModal.vue.d.ts.map +1 -1
  287. package/dist/v2/components/modals/DeleteModal.vue.script.js +1 -1
  288. package/dist/v2/components/modals/DeleteModal.vue.script.js.map +1 -1
  289. package/dist/v2/components/modals/ModalClientContainer.vue.js +1 -1
  290. package/dist/v2/components/modals/ModalClientContainer.vue.script.js +1 -1
  291. package/dist/v2/components/modals/ModalClientContainer.vue.script.js.map +1 -1
  292. package/dist/v2/components/resize/Resize.vue.js +1 -1
  293. package/dist/v2/components/resize/Resize.vue.script.js +1 -1
  294. package/dist/v2/components/resize/Resize.vue.script.js.map +1 -1
  295. package/dist/v2/components/resize/use-split-resize.js +4 -2
  296. package/dist/v2/components/resize/use-split-resize.js.map +1 -1
  297. package/dist/v2/components/server/ServerDropdown.vue.d.ts.map +1 -1
  298. package/dist/v2/components/server/ServerDropdown.vue.script.js +1 -1
  299. package/dist/v2/components/server/ServerDropdown.vue.script.js.map +1 -1
  300. package/dist/v2/components/server/ServerDropdownItem.vue.d.ts.map +1 -1
  301. package/dist/v2/components/server/ServerDropdownItem.vue.js +1 -1
  302. package/dist/v2/components/server/ServerDropdownItem.vue.script.js +1 -1
  303. package/dist/v2/components/server/ServerDropdownItem.vue.script.js.map +1 -1
  304. package/dist/v2/components/sidebar/Sidebar.vue.d.ts.map +1 -1
  305. package/dist/v2/components/sidebar/Sidebar.vue.script.js +3 -3
  306. package/dist/v2/components/sidebar/Sidebar.vue.script.js.map +1 -1
  307. package/dist/v2/components/sidebar/SidebarMenu.vue.d.ts.map +1 -1
  308. package/dist/v2/components/sidebar/SidebarMenu.vue.script.js +1 -1
  309. package/dist/v2/components/sidebar/SidebarMenu.vue.script.js.map +1 -1
  310. package/dist/v2/components/sidebar/SidebarToggle.vue.script.js +1 -1
  311. package/dist/v2/components/sidebar/SidebarToggle.vue.script.js.map +1 -1
  312. package/dist/v2/constants.js +1 -1
  313. package/dist/v2/features/command-palette/components/CommandActionForm.vue.script.js +1 -1
  314. package/dist/v2/features/command-palette/components/CommandActionForm.vue.script.js.map +1 -1
  315. package/dist/v2/features/command-palette/components/CommandActionInput.vue.script.js +1 -1
  316. package/dist/v2/features/command-palette/components/CommandActionInput.vue.script.js.map +1 -1
  317. package/dist/v2/features/environments/EnvironmentsList.vue.d.ts.map +1 -1
  318. package/dist/v2/features/environments/EnvironmentsList.vue.script.js +1 -1
  319. package/dist/v2/features/environments/EnvironmentsList.vue.script.js.map +1 -1
  320. package/dist/v2/features/environments/components/Environment.vue.d.ts.map +1 -1
  321. package/dist/v2/features/environments/components/Environment.vue.script.js +1 -1
  322. package/dist/v2/features/environments/components/Environment.vue.script.js.map +1 -1
  323. package/dist/v2/features/environments/components/EnvironmentColors.vue.script.js +3 -2
  324. package/dist/v2/features/environments/components/EnvironmentColors.vue.script.js.map +1 -1
  325. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.d.ts.map +1 -1
  326. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.script.js +1 -1
  327. package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.script.js.map +1 -1
  328. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.d.ts.map +1 -1
  329. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.script.js +1 -1
  330. package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.script.js.map +1 -1
  331. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.d.ts.map +1 -1
  332. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js +1 -1
  333. package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js.map +1 -1
  334. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.d.ts.map +1 -1
  335. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js +1 -1
  336. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js +1 -1
  337. package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js.map +1 -1
  338. package/dist/v2/features/modal/Modal.vue.d.ts.map +1 -1
  339. package/dist/v2/features/modal/Modal.vue.script.js +1 -1
  340. package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
  341. package/dist/v2/features/modal/helpers/create-api-client-modal.js +11 -0
  342. package/dist/v2/features/modal/helpers/create-api-client-modal.js.map +1 -1
  343. package/dist/v2/features/modal/helpers/map-hidden-clients-config.js.map +1 -1
  344. package/dist/v2/features/modal/helpers/resolve-route-parameters.js +1 -1
  345. package/dist/v2/features/modal/helpers/resolve-route-parameters.js.map +1 -1
  346. package/dist/v2/features/modal/hooks/use-modal-sidebar.js.map +1 -1
  347. package/dist/v2/features/modal/modal-events.js.map +1 -1
  348. package/dist/v2/features/operation/Operation.vue.script.js +1 -1
  349. package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
  350. package/dist/v2/features/search/components/DocumentSearchModal.vue.d.ts.map +1 -1
  351. package/dist/v2/features/search/components/DocumentSearchModal.vue.js +1 -1
  352. package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js +1 -1
  353. package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js.map +1 -1
  354. package/dist/v2/features/search/components/SearchResult.vue.d.ts.map +1 -1
  355. package/dist/v2/features/search/components/SearchResult.vue.script.js +1 -1
  356. package/dist/v2/features/search/components/SearchResult.vue.script.js.map +1 -1
  357. package/dist/v2/features/search/helpers/create-fuse-instance.js.map +1 -1
  358. package/dist/v2/features/search/helpers/create-search-index.js.map +1 -1
  359. package/dist/v2/features/search/hooks/use-document-search.js.map +1 -1
  360. package/dist/v2/features/search/hooks/use-search-index.js.map +1 -1
  361. package/dist/v2/helpers/generate-location-id.js.map +1 -1
  362. package/dist/v2/helpers/handle-hotkeys.js +1 -1
  363. package/dist/v2/helpers/handle-hotkeys.js.map +1 -1
  364. package/dist/v2/helpers/test-utils.js.map +1 -1
  365. package/dist/v2/hooks/use-global-hot-keys.js.map +1 -1
  366. package/dist/v2/hooks/use-scroll-lock.js.map +1 -1
  367. package/dist/v2/workspace-events.js.map +1 -1
  368. package/dist/vue-styles.css +229 -236
  369. package/package.json +20 -20
@@ -1 +1 @@
1
- {"version":3,"file":"persist-response-cookies.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/persist-response-cookies.ts"],"sourcesContent":["import type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport { parseSetCookie } from 'set-cookie-parser'\n\n/**\n * A single change to apply to the persisted document cookie jar in response to a\n * server's `Set-Cookie` headers. This mirrors how a browser stores server-set\n * cookies so that values like a Django CSRF token survive a page reload and get\n * replayed on the next request.\n */\ntype ResponseCookieAction =\n | {\n type: 'upsert'\n /** The cookie fields to store. Merged over the existing cookie when `index` is set. */\n cookie: Pick<XScalarCookie, 'name' | 'value' | 'domain' | 'path'>\n /** Index of the existing cookie to update, or undefined to add a new one. */\n index?: number\n }\n | {\n type: 'delete'\n cookieName: string\n /** Index of the existing cookie to remove. */\n index: number\n }\n\n/**\n * Resolve the real target URL a request was sent to, so cookies are scoped to\n * the API host rather than the proxy. When a request is proxied, the target URL\n * is carried in the `scalar_url` query parameter; otherwise the URL is used as-is.\n */\nexport const getCookieRequestUrl = (payloadUrl: string): string => {\n try {\n // Fall back to the proxied URL when `scalar_url` is missing or empty, so an\n // empty query value never scopes cookies against a placeholder host.\n return new URL(payloadUrl).searchParams.get('scalar_url') || payloadUrl\n } catch {\n return payloadUrl\n }\n}\n\n/**\n * Compute the default cookie path from a request pathname, following the browser\n * default-path algorithm (RFC 6265, section 5.1.4): the request path up to, but\n * not including, its rightmost slash — or \"/\" when there is nothing before it.\n */\nconst getDefaultPath = (pathname: string): string => {\n if (!pathname.startsWith('/')) {\n return '/'\n }\n\n const lastSlash = pathname.lastIndexOf('/')\n\n return lastSlash <= 0 ? '/' : pathname.slice(0, lastSlash)\n}\n\n/**\n * Derive the host and default path a cookie should be scoped to from the request\n * URL. The URL is parsed defensively: `getCookieRequestUrl` may hand back a value\n * that is not a valid URL (for example a malformed `scalar_url`), and a throw here\n * would otherwise abort persistence after an otherwise successful request.\n */\nconst getRequestScope = (requestUrl: string): { hostname: string; defaultPath: string } => {\n try {\n const { hostname, pathname } = new URL(requestUrl, 'https://example.com')\n\n return { hostname, defaultPath: getDefaultPath(pathname) }\n } catch {\n return { hostname: '', defaultPath: '/' }\n }\n}\n\n/** Two stored cookies share an identity when name, domain, and path all match. */\nconst isSameCookie = (a: Pick<XScalarCookie, 'name' | 'domain' | 'path'>, b: XScalarCookie): boolean =>\n a.name === b.name && (a.domain ?? '') === (b.domain ?? '') && (a.path ?? '') === (b.path ?? '')\n\n/**\n * Translate a response's `Set-Cookie` headers into a list of changes for the\n * document cookie jar.\n *\n * Scalar sends requests through a proxy and reads `Set-Cookie` from a custom\n * header because browsers hide it from `fetch`, so it has to maintain its own\n * cookie jar instead of relying on the browser. This function is that jar's\n * write path: it decides which cookies to add, update, or remove.\n *\n * Cookies are scoped like a browser would scope them — using the `Set-Cookie`\n * `Domain`/`Path` attributes, or falling back to the request host and default\n * path — so they are only replayed on matching requests. Expired cookies (an\n * `Expires` in the past or a non-positive `Max-Age`) remove the matching cookie,\n * matching how a server deletes a cookie.\n *\n * @param cookieHeaderKeys - Serialized `Set-Cookie` values from the response\n * @param documentCookies - The current persisted document cookies (order matches the store)\n * @param requestUrl - The request URL, used to derive the default domain and path\n * @param now - Current time in ms, injectable for testing\n */\nexport const getResponseCookieActions = ({\n cookieHeaderKeys,\n documentCookies,\n requestUrl,\n now = Date.now(),\n}: {\n cookieHeaderKeys: string[]\n documentCookies: XScalarCookie[]\n requestUrl: string\n now?: number\n}): ResponseCookieAction[] => {\n const { hostname, defaultPath } = getRequestScope(requestUrl)\n\n /**\n * Collapse the response's `Set-Cookie` headers into one final state per cookie\n * identity. A browser applies them in order, so a later header for the same\n * name/domain/path wins — whether it sets a new value or expires the cookie.\n * Resolving this first also keeps a single action per identity, so the same\n * stored cookie never gets a conflicting upsert and delete on the same index.\n */\n const resolved = new Map<\n string,\n { cookie: Pick<XScalarCookie, 'name' | 'value' | 'domain' | 'path'>; expired: boolean }\n >()\n\n for (const header of cookieHeaderKeys) {\n // Each header holds a single Set-Cookie value, so take the first parsed cookie.\n const [parsed] = parseSetCookie(header)\n\n if (!parsed?.name) {\n continue\n }\n\n // Scope the cookie the way a browser would, so it is only replayed on matching requests.\n const domain = parsed.domain || hostname\n const path = parsed.path || defaultPath\n\n // A cookie is deleted when it is already expired via Expires or Max-Age.\n const expired =\n (parsed.maxAge !== undefined && parsed.maxAge <= 0) ||\n (parsed.expires instanceof Date && parsed.expires.getTime() <= now)\n\n resolved.set(`${parsed.name}\\n${domain}\\n${path}`, {\n cookie: { name: parsed.name, value: parsed.value, domain, path },\n expired,\n })\n }\n\n const upserts: ResponseCookieAction[] = []\n const deletes: ResponseCookieAction[] = []\n\n for (const { cookie, expired } of resolved.values()) {\n const index = documentCookies.findIndex((existing) => isSameCookie(cookie, existing))\n\n if (expired) {\n if (index !== -1) {\n deletes.push({ type: 'delete', cookieName: cookie.name, index })\n }\n continue\n }\n\n upserts.push({\n type: 'upsert',\n cookie,\n ...(index === -1 ? {} : { index }),\n })\n }\n\n /**\n * Apply index-based changes (updates and deletes) before appends, and process\n * deletes from the highest index down, so earlier indices stay valid as the\n * underlying array shrinks.\n */\n const indexed = [...upserts.filter((action) => action.index !== undefined), ...deletes].sort(\n (a, b) => (b.index ?? 0) - (a.index ?? 0),\n )\n const appends = upserts.filter((action) => action.index === undefined)\n\n return [...indexed, ...appends]\n}\n"],"mappings":";;;;;;;AA6BA,IAAa,uBAAuB,eAA+B;AACjE,KAAI;AAGF,SAAO,IAAI,IAAI,WAAW,CAAC,aAAa,IAAI,aAAa,IAAI;SACvD;AACN,SAAO;;;;;;;;AASX,IAAM,kBAAkB,aAA6B;AACnD,KAAI,CAAC,SAAS,WAAW,IAAI,CAC3B,QAAO;CAGT,MAAM,YAAY,SAAS,YAAY,IAAI;AAE3C,QAAO,aAAa,IAAI,MAAM,SAAS,MAAM,GAAG,UAAU;;;;;;;;AAS5D,IAAM,mBAAmB,eAAkE;AACzF,KAAI;EACF,MAAM,EAAE,UAAU,aAAa,IAAI,IAAI,YAAY,sBAAsB;AAEzE,SAAO;GAAE;GAAU,aAAa,eAAe,SAAS;GAAE;SACpD;AACN,SAAO;GAAE,UAAU;GAAI,aAAa;GAAK;;;;AAK7C,IAAM,gBAAgB,GAAoD,MACxE,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,SAAS,EAAE,UAAU,QAAQ,EAAE,QAAQ,SAAS,EAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;AAsB9F,IAAa,4BAA4B,EACvC,kBACA,iBACA,YACA,MAAM,KAAK,KAAK,OAMY;CAC5B,MAAM,EAAE,UAAU,gBAAgB,gBAAgB,WAAW;;;;;;;;CAS7D,MAAM,2BAAW,IAAI,KAGlB;AAEH,MAAK,MAAM,UAAU,kBAAkB;EAErC,MAAM,CAAC,UAAU,eAAe,OAAO;AAEvC,MAAI,CAAC,QAAQ,KACX;EAIF,MAAM,SAAS,OAAO,UAAU;EAChC,MAAM,OAAO,OAAO,QAAQ;EAG5B,MAAM,UACH,OAAO,WAAW,KAAA,KAAa,OAAO,UAAU,KAChD,OAAO,mBAAmB,QAAQ,OAAO,QAAQ,SAAS,IAAI;AAEjE,WAAS,IAAI,GAAG,OAAO,KAAK,IAAI,OAAO,IAAI,QAAQ;GACjD,QAAQ;IAAE,MAAM,OAAO;IAAM,OAAO,OAAO;IAAO;IAAQ;IAAM;GAChE;GACD,CAAC;;CAGJ,MAAM,UAAkC,EAAE;CAC1C,MAAM,UAAkC,EAAE;AAE1C,MAAK,MAAM,EAAE,QAAQ,aAAa,SAAS,QAAQ,EAAE;EACnD,MAAM,QAAQ,gBAAgB,WAAW,aAAa,aAAa,QAAQ,SAAS,CAAC;AAErF,MAAI,SAAS;AACX,OAAI,UAAU,GACZ,SAAQ,KAAK;IAAE,MAAM;IAAU,YAAY,OAAO;IAAM;IAAO,CAAC;AAElE;;AAGF,UAAQ,KAAK;GACX,MAAM;GACN;GACA,GAAI,UAAU,KAAK,EAAE,GAAG,EAAE,OAAO;GAClC,CAAC;;;;;;;CAQJ,MAAM,UAAU,CAAC,GAAG,QAAQ,QAAQ,WAAW,OAAO,UAAU,KAAA,EAAU,EAAE,GAAG,QAAQ,CAAC,MACrF,GAAG,OAAO,EAAE,SAAS,MAAM,EAAE,SAAS,GACxC;CACD,MAAM,UAAU,QAAQ,QAAQ,WAAW,OAAO,UAAU,KAAA,EAAU;AAEtE,QAAO,CAAC,GAAG,SAAS,GAAG,QAAQ"}
1
+ {"version":3,"file":"persist-response-cookies.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/persist-response-cookies.ts"],"sourcesContent":["import type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport { parseSetCookie } from 'set-cookie-parser'\n\n/**\n * A single change to apply to the persisted document cookie jar in response to a\n * server's `Set-Cookie` headers. This mirrors how a browser stores server-set\n * cookies so that values like a Django CSRF token survive a page reload and get\n * replayed on the next request.\n */\ntype ResponseCookieAction =\n | {\n type: 'upsert'\n /** The cookie fields to store. Merged over the existing cookie when `index` is set. */\n cookie: Pick<XScalarCookie, 'name' | 'value' | 'domain' | 'path'>\n /** Index of the existing cookie to update, or undefined to add a new one. */\n index?: number\n }\n | {\n type: 'delete'\n cookieName: string\n /** Index of the existing cookie to remove. */\n index: number\n }\n\n/**\n * Resolve the real target URL a request was sent to, so cookies are scoped to\n * the API host rather than the proxy. When a request is proxied, the target URL\n * is carried in the `scalar_url` query parameter; otherwise the URL is used as-is.\n */\nexport const getCookieRequestUrl = (payloadUrl: string): string => {\n try {\n // Fall back to the proxied URL when `scalar_url` is missing or empty, so an\n // empty query value never scopes cookies against a placeholder host.\n return new URL(payloadUrl).searchParams.get('scalar_url') || payloadUrl\n } catch {\n return payloadUrl\n }\n}\n\n/**\n * Compute the default cookie path from a request pathname, following the browser\n * default-path algorithm (RFC 6265, section 5.1.4): the request path up to, but\n * not including, its rightmost slash — or \"/\" when there is nothing before it.\n */\nconst getDefaultPath = (pathname: string): string => {\n if (!pathname.startsWith('/')) {\n return '/'\n }\n\n const lastSlash = pathname.lastIndexOf('/')\n\n return lastSlash <= 0 ? '/' : pathname.slice(0, lastSlash)\n}\n\n/**\n * Derive the host and default path a cookie should be scoped to from the request\n * URL. The URL is parsed defensively: `getCookieRequestUrl` may hand back a value\n * that is not a valid URL (for example a malformed `scalar_url`), and a throw here\n * would otherwise abort persistence after an otherwise successful request.\n */\nconst getRequestScope = (requestUrl: string): { hostname: string; defaultPath: string } => {\n try {\n const { hostname, pathname } = new URL(requestUrl, 'https://example.com')\n\n return { hostname, defaultPath: getDefaultPath(pathname) }\n } catch {\n return { hostname: '', defaultPath: '/' }\n }\n}\n\n/** Two stored cookies share an identity when name, domain, and path all match. */\nconst isSameCookie = (a: Pick<XScalarCookie, 'name' | 'domain' | 'path'>, b: XScalarCookie): boolean =>\n a.name === b.name && (a.domain ?? '') === (b.domain ?? '') && (a.path ?? '') === (b.path ?? '')\n\n/**\n * Translate a response's `Set-Cookie` headers into a list of changes for the\n * document cookie jar.\n *\n * Scalar sends requests through a proxy and reads `Set-Cookie` from a custom\n * header because browsers hide it from `fetch`, so it has to maintain its own\n * cookie jar instead of relying on the browser. This function is that jar's\n * write path: it decides which cookies to add, update, or remove.\n *\n * Cookies are scoped like a browser would scope them — using the `Set-Cookie`\n * `Domain`/`Path` attributes, or falling back to the request host and default\n * path — so they are only replayed on matching requests. Expired cookies (an\n * `Expires` in the past or a non-positive `Max-Age`) remove the matching cookie,\n * matching how a server deletes a cookie.\n *\n * @param cookieHeaderKeys - Serialized `Set-Cookie` values from the response\n * @param documentCookies - The current persisted document cookies (order matches the store)\n * @param requestUrl - The request URL, used to derive the default domain and path\n * @param now - Current time in ms, injectable for testing\n */\nexport const getResponseCookieActions = ({\n cookieHeaderKeys,\n documentCookies,\n requestUrl,\n now = Date.now(),\n}: {\n cookieHeaderKeys: string[]\n documentCookies: XScalarCookie[]\n requestUrl: string\n now?: number\n}): ResponseCookieAction[] => {\n const { hostname, defaultPath } = getRequestScope(requestUrl)\n\n /**\n * Collapse the response's `Set-Cookie` headers into one final state per cookie\n * identity. A browser applies them in order, so a later header for the same\n * name/domain/path wins — whether it sets a new value or expires the cookie.\n * Resolving this first also keeps a single action per identity, so the same\n * stored cookie never gets a conflicting upsert and delete on the same index.\n */\n const resolved = new Map<\n string,\n { cookie: Pick<XScalarCookie, 'name' | 'value' | 'domain' | 'path'>; expired: boolean }\n >()\n\n for (const header of cookieHeaderKeys) {\n // Each header holds a single Set-Cookie value, so take the first parsed cookie.\n const [parsed] = parseSetCookie(header)\n\n if (!parsed?.name) {\n continue\n }\n\n // Scope the cookie the way a browser would, so it is only replayed on matching requests.\n const domain = parsed.domain || hostname\n const path = parsed.path || defaultPath\n\n // A cookie is deleted when it is already expired via Expires or Max-Age.\n const expired =\n (parsed.maxAge !== undefined && parsed.maxAge <= 0) ||\n (parsed.expires instanceof Date && parsed.expires.getTime() <= now)\n\n resolved.set(`${parsed.name}\\n${domain}\\n${path}`, {\n cookie: { name: parsed.name, value: parsed.value, domain, path },\n expired,\n })\n }\n\n const upserts: ResponseCookieAction[] = []\n const deletes: ResponseCookieAction[] = []\n\n for (const { cookie, expired } of resolved.values()) {\n const index = documentCookies.findIndex((existing) => isSameCookie(cookie, existing))\n\n if (expired) {\n if (index !== -1) {\n deletes.push({ type: 'delete', cookieName: cookie.name, index })\n }\n continue\n }\n\n upserts.push({\n type: 'upsert',\n cookie,\n ...(index === -1 ? {} : { index }),\n })\n }\n\n /**\n * Apply index-based changes (updates and deletes) before appends, and process\n * deletes from the highest index down, so earlier indices stay valid as the\n * underlying array shrinks.\n */\n const indexed = [...upserts.filter((action) => action.index !== undefined), ...deletes].sort(\n (a, b) => (b.index ?? 0) - (a.index ?? 0),\n )\n const appends = upserts.filter((action) => action.index === undefined)\n\n return [...indexed, ...appends]\n}\n"],"mappings":";;;;;;;AA6BA,IAAa,uBAAuB,eAA+B;CACjE,IAAI;EAGF,OAAO,IAAI,IAAI,UAAU,CAAC,CAAC,aAAa,IAAI,YAAY,KAAK;CAC/D,QAAQ;EACN,OAAO;CACT;AACF;;;;;;AAOA,IAAM,kBAAkB,aAA6B;CACnD,IAAI,CAAC,SAAS,WAAW,GAAG,GAC1B,OAAO;CAGT,MAAM,YAAY,SAAS,YAAY,GAAG;CAE1C,OAAO,aAAa,IAAI,MAAM,SAAS,MAAM,GAAG,SAAS;AAC3D;;;;;;;AAQA,IAAM,mBAAmB,eAAkE;CACzF,IAAI;EACF,MAAM,EAAE,UAAU,aAAa,IAAI,IAAI,YAAY,qBAAqB;EAExE,OAAO;GAAE;GAAU,aAAa,eAAe,QAAQ;EAAE;CAC3D,QAAQ;EACN,OAAO;GAAE,UAAU;GAAI,aAAa;EAAI;CAC1C;AACF;;AAGA,IAAM,gBAAgB,GAAoD,MACxE,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,SAAS,EAAE,UAAU,QAAQ,EAAE,QAAQ,SAAS,EAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;AAsB9F,IAAa,4BAA4B,EACvC,kBACA,iBACA,YACA,MAAM,KAAK,IAAI,QAMa;CAC5B,MAAM,EAAE,UAAU,gBAAgB,gBAAgB,UAAU;;;;;;;;CAS5D,MAAM,2BAAW,IAAI,IAGnB;CAEF,KAAK,MAAM,UAAU,kBAAkB;EAErC,MAAM,CAAC,UAAU,eAAe,MAAM;EAEtC,IAAI,CAAC,QAAQ,MACX;EAIF,MAAM,SAAS,OAAO,UAAU;EAChC,MAAM,OAAO,OAAO,QAAQ;EAG5B,MAAM,UACH,OAAO,WAAW,KAAA,KAAa,OAAO,UAAU,KAChD,OAAO,mBAAmB,QAAQ,OAAO,QAAQ,QAAQ,KAAK;EAEjE,SAAS,IAAI,GAAG,OAAO,KAAK,IAAI,OAAO,IAAI,QAAQ;GACjD,QAAQ;IAAE,MAAM,OAAO;IAAM,OAAO,OAAO;IAAO;IAAQ;GAAK;GAC/D;EACF,CAAC;CACH;CAEA,MAAM,UAAkC,CAAC;CACzC,MAAM,UAAkC,CAAC;CAEzC,KAAK,MAAM,EAAE,QAAQ,aAAa,SAAS,OAAO,GAAG;EACnD,MAAM,QAAQ,gBAAgB,WAAW,aAAa,aAAa,QAAQ,QAAQ,CAAC;EAEpF,IAAI,SAAS;GACX,IAAI,UAAU,IACZ,QAAQ,KAAK;IAAE,MAAM;IAAU,YAAY,OAAO;IAAM;GAAM,CAAC;GAEjE;EACF;EAEA,QAAQ,KAAK;GACX,MAAM;GACN;GACA,GAAI,UAAU,KAAK,CAAC,IAAI,EAAE,MAAM;EAClC,CAAC;CACH;;;;;;CAOA,MAAM,UAAU,CAAC,GAAG,QAAQ,QAAQ,WAAW,OAAO,UAAU,KAAA,CAAS,GAAG,GAAG,OAAO,CAAC,CAAC,MACrF,GAAG,OAAO,EAAE,SAAS,MAAM,EAAE,SAAS,EACzC;CACA,MAAM,UAAU,QAAQ,QAAQ,WAAW,OAAO,UAAU,KAAA,CAAS;CAErE,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO;AAChC"}
@@ -0,0 +1,53 @@
1
+ import type { CollectionType } from '@scalar/workspace-store/events';
2
+ import type { VariableEntry } from '@scalar/workspace-store/request-example';
3
+ import type { XScalarEnvVar } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments';
4
+ /**
5
+ * A single change to persist to the active environment in response to a script's
6
+ * `pm.environment.set()` / `pm.environment.unset()`. Shapes mirror the workspace event
7
+ * bus payloads (`environment:upsert:environment-variable` / `:delete:environment-variable`)
8
+ * so the caller can emit each action directly.
9
+ */
10
+ type EnvironmentPersistenceAction = {
11
+ environmentName: string;
12
+ } & CollectionType & ({
13
+ type: 'upsert';
14
+ variable: {
15
+ name: string;
16
+ value: string;
17
+ };
18
+ index?: number;
19
+ } | {
20
+ type: 'delete';
21
+ index: number;
22
+ });
23
+ /**
24
+ * Resolve which environment variables a script changed and where to persist them.
25
+ *
26
+ * The active environment is a merge of workspace- and document-scoped variables:
27
+ * `getActiveEnvironment` concatenates them as `[...workspaceVariables, ...documentVariables]`.
28
+ * We use that ordering to map each changed variable back to the scope and index it came
29
+ * from, so updates mutate the correct collection in place instead of creating duplicates.
30
+ * New variables are added to whichever scope actually defines the active environment, so the
31
+ * upsert target exists (the mutator no-ops when the environment is missing from a collection).
32
+ *
33
+ * Variables present before the scripts ran but gone afterwards were removed via
34
+ * `pm.environment.unset()` and are emitted as deletes. Deletes splice the underlying array,
35
+ * so they are ordered last and by descending index — an earlier splice must not invalidate the
36
+ * index of a later one. Upserts run first because they replace in place without shifting.
37
+ */
38
+ export declare const getEnvironmentPersistenceActions: ({ environmentName, seededVariables, scriptVariables, mergedVariables, documentVariables, environmentExistsOnDocument, }: {
39
+ /** Name of the active environment being written to. */
40
+ environmentName: string;
41
+ /** Environment values seeded into the store before the scripts ran. */
42
+ seededVariables: Record<string, string>;
43
+ /** Environment scope read back from the store after the scripts ran. */
44
+ scriptVariables: VariableEntry[] | Record<string, string>;
45
+ /** The merged (workspace + document) variables of the active environment. */
46
+ mergedVariables: XScalarEnvVar[];
47
+ /** The document-scoped variables of the active environment (appended last in the merge). */
48
+ documentVariables: XScalarEnvVar[];
49
+ /** Whether the active environment is defined on the document (vs. the workspace). */
50
+ environmentExistsOnDocument: boolean;
51
+ }) => EnvironmentPersistenceAction[];
52
+ export {};
53
+ //# sourceMappingURL=persist-script-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persist-script-environment.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/persist-script-environment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2EAA2E,CAAA;AAE9G;;;;;GAKG;AACH,KAAK,4BAA4B,GAAG;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE,GAAG,cAAc,GAC9E,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAMrH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gCAAgC,GAAI,yHAO9C;IACD,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAA;IACvB,uEAAuE;IACvE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,wEAAwE;IACxE,eAAe,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACzD,6EAA6E;IAC7E,eAAe,EAAE,aAAa,EAAE,CAAA;IAChC,4FAA4F;IAC5F,iBAAiB,EAAE,aAAa,EAAE,CAAA;IAClC,qFAAqF;IACrF,2BAA2B,EAAE,OAAO,CAAA;CACrC,KAAG,4BAA4B,EA4E/B,CAAA"}
@@ -0,0 +1,91 @@
1
+ //#region src/v2/blocks/operation-block/helpers/persist-script-environment.ts
2
+ /** Normalize the store's environment scope, which may be an array or a plain record. */
3
+ var toEntries = (variables) => Array.isArray(variables) ? variables : Object.entries(variables).map(([key, value]) => ({
4
+ key,
5
+ value
6
+ }));
7
+ /**
8
+ * Resolve which environment variables a script changed and where to persist them.
9
+ *
10
+ * The active environment is a merge of workspace- and document-scoped variables:
11
+ * `getActiveEnvironment` concatenates them as `[...workspaceVariables, ...documentVariables]`.
12
+ * We use that ordering to map each changed variable back to the scope and index it came
13
+ * from, so updates mutate the correct collection in place instead of creating duplicates.
14
+ * New variables are added to whichever scope actually defines the active environment, so the
15
+ * upsert target exists (the mutator no-ops when the environment is missing from a collection).
16
+ *
17
+ * Variables present before the scripts ran but gone afterwards were removed via
18
+ * `pm.environment.unset()` and are emitted as deletes. Deletes splice the underlying array,
19
+ * so they are ordered last and by descending index — an earlier splice must not invalidate the
20
+ * index of a later one. Upserts run first because they replace in place without shifting.
21
+ */
22
+ var getEnvironmentPersistenceActions = ({ environmentName, seededVariables, scriptVariables, mergedVariables, documentVariables, environmentExistsOnDocument }) => {
23
+ const workspaceCount = Math.max(0, mergedVariables.length - documentVariables.length);
24
+ const documentIndexByName = new Map(documentVariables.map((variable, index) => [variable.name, index]));
25
+ const workspaceIndexByName = new Map(mergedVariables.slice(0, workspaceCount).map((variable, index) => [variable.name, index]));
26
+ /**
27
+ * Locate an existing variable by name, preferring the document scope on collisions since
28
+ * document values win when the environment is merged for reads.
29
+ */
30
+ const findExisting = (key) => {
31
+ const documentIndex = documentIndexByName.get(key);
32
+ if (documentIndex !== void 0) return {
33
+ collectionType: "document",
34
+ index: documentIndex
35
+ };
36
+ const workspaceIndex = workspaceIndexByName.get(key);
37
+ if (workspaceIndex !== void 0) return {
38
+ collectionType: "workspace",
39
+ index: workspaceIndex
40
+ };
41
+ };
42
+ const upserts = [];
43
+ const deletes = [];
44
+ const scriptKeys = /* @__PURE__ */ new Set();
45
+ for (const { key, value } of toEntries(scriptVariables)) {
46
+ scriptKeys.add(key);
47
+ if (seededVariables[key] === value) continue;
48
+ const existing = findExisting(key);
49
+ if (existing) upserts.push({
50
+ type: "upsert",
51
+ environmentName,
52
+ variable: {
53
+ name: key,
54
+ value
55
+ },
56
+ ...existing
57
+ });
58
+ else upserts.push({
59
+ type: "upsert",
60
+ environmentName,
61
+ variable: {
62
+ name: key,
63
+ value
64
+ },
65
+ collectionType: environmentExistsOnDocument ? "document" : "workspace"
66
+ });
67
+ }
68
+ for (const key of Object.keys(seededVariables)) {
69
+ if (scriptKeys.has(key)) continue;
70
+ const documentIndex = documentIndexByName.get(key);
71
+ if (documentIndex !== void 0) deletes.push({
72
+ type: "delete",
73
+ environmentName,
74
+ index: documentIndex,
75
+ collectionType: "document"
76
+ });
77
+ const workspaceIndex = workspaceIndexByName.get(key);
78
+ if (workspaceIndex !== void 0) deletes.push({
79
+ type: "delete",
80
+ environmentName,
81
+ index: workspaceIndex,
82
+ collectionType: "workspace"
83
+ });
84
+ }
85
+ deletes.sort((a, b) => b.index - a.index);
86
+ return [...upserts, ...deletes];
87
+ };
88
+ //#endregion
89
+ export { getEnvironmentPersistenceActions };
90
+
91
+ //# sourceMappingURL=persist-script-environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persist-script-environment.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/persist-script-environment.ts"],"sourcesContent":["import type { CollectionType } from '@scalar/workspace-store/events'\nimport type { VariableEntry } from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvVar } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\n\n/**\n * A single change to persist to the active environment in response to a script's\n * `pm.environment.set()` / `pm.environment.unset()`. Shapes mirror the workspace event\n * bus payloads (`environment:upsert:environment-variable` / `:delete:environment-variable`)\n * so the caller can emit each action directly.\n */\ntype EnvironmentPersistenceAction = { environmentName: string } & CollectionType &\n ({ type: 'upsert'; variable: { name: string; value: string }; index?: number } | { type: 'delete'; index: number })\n\n/** Normalize the store's environment scope, which may be an array or a plain record. */\nconst toEntries = (variables: VariableEntry[] | Record<string, string>): VariableEntry[] =>\n Array.isArray(variables) ? variables : Object.entries(variables).map(([key, value]) => ({ key, value }))\n\n/**\n * Resolve which environment variables a script changed and where to persist them.\n *\n * The active environment is a merge of workspace- and document-scoped variables:\n * `getActiveEnvironment` concatenates them as `[...workspaceVariables, ...documentVariables]`.\n * We use that ordering to map each changed variable back to the scope and index it came\n * from, so updates mutate the correct collection in place instead of creating duplicates.\n * New variables are added to whichever scope actually defines the active environment, so the\n * upsert target exists (the mutator no-ops when the environment is missing from a collection).\n *\n * Variables present before the scripts ran but gone afterwards were removed via\n * `pm.environment.unset()` and are emitted as deletes. Deletes splice the underlying array,\n * so they are ordered last and by descending index — an earlier splice must not invalidate the\n * index of a later one. Upserts run first because they replace in place without shifting.\n */\nexport const getEnvironmentPersistenceActions = ({\n environmentName,\n seededVariables,\n scriptVariables,\n mergedVariables,\n documentVariables,\n environmentExistsOnDocument,\n}: {\n /** Name of the active environment being written to. */\n environmentName: string\n /** Environment values seeded into the store before the scripts ran. */\n seededVariables: Record<string, string>\n /** Environment scope read back from the store after the scripts ran. */\n scriptVariables: VariableEntry[] | Record<string, string>\n /** The merged (workspace + document) variables of the active environment. */\n mergedVariables: XScalarEnvVar[]\n /** The document-scoped variables of the active environment (appended last in the merge). */\n documentVariables: XScalarEnvVar[]\n /** Whether the active environment is defined on the document (vs. the workspace). */\n environmentExistsOnDocument: boolean\n}): EnvironmentPersistenceAction[] => {\n // Workspace variables occupy the front of the merged array; document variables the tail.\n const workspaceCount = Math.max(0, mergedVariables.length - documentVariables.length)\n\n const documentIndexByName = new Map(documentVariables.map((variable, index) => [variable.name, index]))\n const workspaceIndexByName = new Map(\n mergedVariables.slice(0, workspaceCount).map((variable, index) => [variable.name, index]),\n )\n\n /**\n * Locate an existing variable by name, preferring the document scope on collisions since\n * document values win when the environment is merged for reads.\n */\n const findExisting = (\n key: string,\n ): { collectionType: CollectionType['collectionType']; index: number } | undefined => {\n const documentIndex = documentIndexByName.get(key)\n if (documentIndex !== undefined) {\n return { collectionType: 'document', index: documentIndex }\n }\n const workspaceIndex = workspaceIndexByName.get(key)\n if (workspaceIndex !== undefined) {\n return { collectionType: 'workspace', index: workspaceIndex }\n }\n return undefined\n }\n\n const upserts: EnvironmentPersistenceAction[] = []\n const deletes: Array<Extract<EnvironmentPersistenceAction, { type: 'delete' }>> = []\n const scriptKeys = new Set<string>()\n\n for (const { key, value } of toEntries(scriptVariables)) {\n scriptKeys.add(key)\n\n // Skip values the script did not touch.\n if (seededVariables[key] === value) {\n continue\n }\n\n const existing = findExisting(key)\n if (existing) {\n // Update an existing variable in place.\n upserts.push({ type: 'upsert', environmentName, variable: { name: key, value }, ...existing })\n } else {\n // New variable — add it to whichever scope holds the active environment.\n upserts.push({\n type: 'upsert',\n environmentName,\n variable: { name: key, value },\n collectionType: environmentExistsOnDocument ? 'document' : 'workspace',\n })\n }\n }\n\n // Removals: keys present before the scripts ran but absent afterwards (pm.environment.unset).\n // Delete from every scope that defines the name — not just the one that wins on reads. A copy\n // left behind in another scope would resurface on the next seed, so the unset would not stick.\n for (const key of Object.keys(seededVariables)) {\n if (scriptKeys.has(key)) {\n continue\n }\n const documentIndex = documentIndexByName.get(key)\n if (documentIndex !== undefined) {\n deletes.push({ type: 'delete', environmentName, index: documentIndex, collectionType: 'document' })\n }\n const workspaceIndex = workspaceIndexByName.get(key)\n if (workspaceIndex !== undefined) {\n deletes.push({ type: 'delete', environmentName, index: workspaceIndex, collectionType: 'workspace' })\n }\n }\n\n // Highest index first so each splice leaves lower indices — including cross-scope ones,\n // which live in independent arrays — valid for the deletes that follow.\n deletes.sort((a, b) => b.index - a.index)\n\n return [...upserts, ...deletes]\n}\n"],"mappings":";;AAcA,IAAM,aAAa,cACjB,MAAM,QAAQ,SAAS,IAAI,YAAY,OAAO,QAAQ,SAAS,CAAC,CAAC,KAAK,CAAC,KAAK,YAAY;CAAE;CAAK;AAAM,EAAE;;;;;;;;;;;;;;;;AAiBzG,IAAa,oCAAoC,EAC/C,iBACA,iBACA,iBACA,iBACA,mBACA,kCAcoC;CAEpC,MAAM,iBAAiB,KAAK,IAAI,GAAG,gBAAgB,SAAS,kBAAkB,MAAM;CAEpF,MAAM,sBAAsB,IAAI,IAAI,kBAAkB,KAAK,UAAU,UAAU,CAAC,SAAS,MAAM,KAAK,CAAC,CAAC;CACtG,MAAM,uBAAuB,IAAI,IAC/B,gBAAgB,MAAM,GAAG,cAAc,CAAC,CAAC,KAAK,UAAU,UAAU,CAAC,SAAS,MAAM,KAAK,CAAC,CAC1F;;;;;CAMA,MAAM,gBACJ,QACoF;EACpF,MAAM,gBAAgB,oBAAoB,IAAI,GAAG;EACjD,IAAI,kBAAkB,KAAA,GACpB,OAAO;GAAE,gBAAgB;GAAY,OAAO;EAAc;EAE5D,MAAM,iBAAiB,qBAAqB,IAAI,GAAG;EACnD,IAAI,mBAAmB,KAAA,GACrB,OAAO;GAAE,gBAAgB;GAAa,OAAO;EAAe;CAGhE;CAEA,MAAM,UAA0C,CAAC;CACjD,MAAM,UAA4E,CAAC;CACnF,MAAM,6BAAa,IAAI,IAAY;CAEnC,KAAK,MAAM,EAAE,KAAK,WAAW,UAAU,eAAe,GAAG;EACvD,WAAW,IAAI,GAAG;EAGlB,IAAI,gBAAgB,SAAS,OAC3B;EAGF,MAAM,WAAW,aAAa,GAAG;EACjC,IAAI,UAEF,QAAQ,KAAK;GAAE,MAAM;GAAU;GAAiB,UAAU;IAAE,MAAM;IAAK;GAAM;GAAG,GAAG;EAAS,CAAC;OAG7F,QAAQ,KAAK;GACX,MAAM;GACN;GACA,UAAU;IAAE,MAAM;IAAK;GAAM;GAC7B,gBAAgB,8BAA8B,aAAa;EAC7D,CAAC;CAEL;CAKA,KAAK,MAAM,OAAO,OAAO,KAAK,eAAe,GAAG;EAC9C,IAAI,WAAW,IAAI,GAAG,GACpB;EAEF,MAAM,gBAAgB,oBAAoB,IAAI,GAAG;EACjD,IAAI,kBAAkB,KAAA,GACpB,QAAQ,KAAK;GAAE,MAAM;GAAU;GAAiB,OAAO;GAAe,gBAAgB;EAAW,CAAC;EAEpG,MAAM,iBAAiB,qBAAqB,IAAI,GAAG;EACnD,IAAI,mBAAmB,KAAA,GACrB,QAAQ,KAAK;GAAE,MAAM;GAAU;GAAiB,OAAO;GAAgB,gBAAgB;EAAY,CAAC;CAExG;CAIA,QAAQ,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;CAExC,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO;AAChC"}
@@ -1 +1 @@
1
- {"version":3,"file":"response-cache.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/response-cache.ts"],"sourcesContent":["import { isDefined } from '@scalar/helpers/array/is-defined'\nimport type { RequestPayload } from '@scalar/workspace-store/request-example'\n\nimport type { ResponseInstance } from '@/v2/blocks/operation-block/helpers/send-request'\n\n/**\n * In-memory cache of operation example id → { response, request }.\n * Restores the last response when navigating back to an operation until\n * the user refreshes the page or makes a new request.\n */\nexport const responseCache = new Map<string, { response: ResponseInstance; requestPayload: RequestPayload }>()\n\n/**\n * Constructs a unique cache key for a specific operation/example.\n * The key is composed of the HTTP method, request path, and the example key,\n * delimited by \"|\", e.g. \"GET|/pets|123\".\n *\n * @param method - HTTP method (e.g., \"GET\", \"POST\")\n * @param path - The request path (e.g., \"/pets\")\n * @param exampleKey - A unique key identifying the example/request variant\n * @param documentSlug - Optionally add the document slug to the key\n * @returns The constructed cache key string\n */\nexport function getOperationExampleKey(\n method: string,\n path: string,\n exampleKey: string,\n documentSlug?: string,\n): string {\n return [documentSlug, method, path, exampleKey].filter(isDefined).join('|')\n}\n\n/**\n * Determines if a response is a streaming response (e.g., server-sent events).\n * Assumes streaming responses include a 'reader' property.\n *\n * @param response - The response instance to check\n * @returns True if response is streaming, otherwise false\n */\nexport function isStreamingResponse(response: ResponseInstance): boolean {\n return 'reader' in response\n}\n"],"mappings":";;;;;;;AAUA,IAAa,gCAAgB,IAAI,KAA6E;;;;;;;;;;;;AAa9G,SAAgB,uBACd,QACA,MACA,YACA,cACQ;AACR,QAAO;EAAC;EAAc;EAAQ;EAAM;EAAW,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI;;;;;;;;;AAU7E,SAAgB,oBAAoB,UAAqC;AACvE,QAAO,YAAY"}
1
+ {"version":3,"file":"response-cache.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/response-cache.ts"],"sourcesContent":["import { isDefined } from '@scalar/helpers/array/is-defined'\nimport type { RequestPayload } from '@scalar/workspace-store/request-example'\n\nimport type { ResponseInstance } from '@/v2/blocks/operation-block/helpers/send-request'\n\n/**\n * In-memory cache of operation example id → { response, request }.\n * Restores the last response when navigating back to an operation until\n * the user refreshes the page or makes a new request.\n */\nexport const responseCache = new Map<string, { response: ResponseInstance; requestPayload: RequestPayload }>()\n\n/**\n * Constructs a unique cache key for a specific operation/example.\n * The key is composed of the HTTP method, request path, and the example key,\n * delimited by \"|\", e.g. \"GET|/pets|123\".\n *\n * @param method - HTTP method (e.g., \"GET\", \"POST\")\n * @param path - The request path (e.g., \"/pets\")\n * @param exampleKey - A unique key identifying the example/request variant\n * @param documentSlug - Optionally add the document slug to the key\n * @returns The constructed cache key string\n */\nexport function getOperationExampleKey(\n method: string,\n path: string,\n exampleKey: string,\n documentSlug?: string,\n): string {\n return [documentSlug, method, path, exampleKey].filter(isDefined).join('|')\n}\n\n/**\n * Determines if a response is a streaming response (e.g., server-sent events).\n * Assumes streaming responses include a 'reader' property.\n *\n * @param response - The response instance to check\n * @returns True if response is streaming, otherwise false\n */\nexport function isStreamingResponse(response: ResponseInstance): boolean {\n return 'reader' in response\n}\n"],"mappings":";;;;;;;AAUA,IAAa,gCAAgB,IAAI,IAA4E;;;;;;;;;;;;AAa7G,SAAgB,uBACd,QACA,MACA,YACA,cACQ;CACR,OAAO;EAAC;EAAc;EAAQ;EAAM;CAAU,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,KAAK,GAAG;AAC5E;;;;;;;;AASA,SAAgB,oBAAoB,UAAqC;CACvE,OAAO,YAAY;AACrB"}
@@ -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}: {\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}): 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 response = 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 // Extract response metadata early for reuse\n const contentType = response.headers.get('content-type')\n const responseHeaders = normalizeHeaders(response.headers, isUsingProxy)\n const responseUrl = new URL(response.url)\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 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 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 headers: responseHeaders,\n cookieHeaderKeys,\n data: responseData,\n size: arrayBuffer.byteLength,\n duration,\n method,\n status: response.status,\n path: fullPath,\n },\n originalResponse: response.clone(),\n },\n ]\n}\n"],"mappings":";;;;;;;;;;;;;;AAmDA,IAAM,uBAAuB;CAAC;CAAK;CAAK;CAAI;;;;;;;;;;;;;;AAkB5C,IAAa,cAAc,OAAO,EAChC,cACA,gBACA,SACA,UAAU,EAAE,EACZ,cAAc,YAqBX;AACH,KAAI;EAEF,MAAM,YAAY,YAAY,KAAK;EAGnC,MAAM,WAAW,YAAY,GACzB,MAAM,YAAY,GAAG,eAAe,GACpC,MAAM,YAAY,WAAW,qBAAqB,GAAG,eAAe,CAAC;EAEzE,MAAM,UAAU,YAAY,KAAK;EACjC,MAAM,YAAY,KAAK,KAAK;EAC5B,MAAM,WAAW,UAAU;EAG3B,MAAM,cAAc,SAAS,QAAQ,IAAI,eAAe;EACxD,MAAM,kBAAkB,iBAAiB,SAAS,SAAS,aAAa;EACxE,MAAM,cAAc,IAAI,IAAI,SAAS,IAAI;EACzC,MAAM,WAAW,YAAY,WAAW,YAAY;EACpD,MAAM,aAAa,SAAS,cAAc,gBAAgB,SAAS,SAAS,QAAQ;EACpF,MAAM,SAAU,eAAe,GAAG,UAAU;EAC5C,MAAM,iBAAiB,qBAAqB,SAAS,SAAS,OAAO;;;;;;AAOrE,MAAI,aAAa,WAAW,oBAAoB,IAAI,SAAS,KAC3D,QAAO,uBAAuB;GAC5B;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;AAGJ,SAAO,sBAAsB;GAC3B;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;UACK,OAAO;AACd,SAAO,CAAC,eAAe,OAAO,OAAO,eAAe,EAAE,KAAK;;;;;;;;;;AAW/D,IAAM,mBAAmB,aAAwC;CAC/D,MAAM,SAAS,eAAe,SAAS,QAAQ,IAAI,oBAAoB,IAAI,GAAG,CAAC,KAAK,MAClF,gBAAgB,EAAE,MAAM,EAAE,OAAO;EAC/B,GAAG;EACH,UAAU,EAAE;EACb,CAAC,CACH;AAED,KAAI,OAAO,OACT,QAAO;AAGT,QAAO;;;;;;AAOT,IAAM,0BAA0B,EAC9B,UACA,gBACA,WACA,UACA,iBACA,YACA,QACA,eAeI;CACJ,MAAM,qBAAqB,IAAI,SAAS,MAAM;EAC5C,QAAQ,SAAS;EACjB;EACA,SAAS,SAAS;EACnB,CAAC;CAGF,MAAM,mBADe,gBAAgB,mBAAmB,IACf,oBAAoB,mBAAmB,QAAQ;AAExF,QAAO,CACL,MACA;EACE;EACA;EACA,UAAU;GACR,GAAG;GACH,SAAS;GACT;GACA,QAAQ,SAAS,KAAM,WAAW;GAClC;GACA;GACA,MAAM;GACP;EACD,kBAAkB,mBAAmB,OAAO;EAC7C,CACF;;;;;;AAOH,IAAM,wBAAwB,OAAO,EACnC,UACA,gBACA,WACA,UACA,iBACA,YACA,QACA,UACA,aACA,gBACA,cAoBG;CAMH,MAAM,cAAc,MADG,SAAS,OAAO,CACE,aAAa;CACtD,MAAM,eAAe,2BAA2B,YAAY;CAC5D,MAAM,cAAc,wBAAwB,YAAY,CAAC;CAEzD,MAAM,eAAe,MAAM,aAAa,aAAa,cAD/B,2BAA2B,aAAa,QAAQ,CACW;;;;;CAMjF,MAAM,qBAAqB,IAAI,SAAS,iBAAiB,OAAO,aAAa;EAC3E,QAAQ,SAAS;EACjB;EACA,SAAS,SAAS;EACnB,CAAC;CAGF,MAAM,mBADe,gBAAgB,mBAAmB,IACf,oBAAoB,mBAAmB,QAAQ;AAExF,QAAO,CACL,MACA;EACE;EACA;EACA,UAAU;GACR,GAAG;GACH,SAAS;GACT;GACA,MAAM;GACN,MAAM,YAAY;GAClB;GACA;GACA,QAAQ,SAAS;GACjB,MAAM;GACP;EACD,kBAAkB,SAAS,OAAO;EACnC,CACF"}
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}: {\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}): 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 response = 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 // Extract response metadata early for reuse\n const contentType = response.headers.get('content-type')\n const responseHeaders = normalizeHeaders(response.headers, isUsingProxy)\n const responseUrl = new URL(response.url)\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 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 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 headers: responseHeaders,\n cookieHeaderKeys,\n data: responseData,\n size: arrayBuffer.byteLength,\n duration,\n method,\n status: response.status,\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,YAqBX;CACH,IAAI;EAEF,MAAM,YAAY,YAAY,IAAI;EAGlC,MAAM,WAAW,WAAW,IACxB,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;EAG3B,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;EACvD,MAAM,kBAAkB,iBAAiB,SAAS,SAAS,YAAY;EACvE,MAAM,cAAc,IAAI,IAAI,SAAS,GAAG;EACxC,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,sBAAsB;GAC3B;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,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,SAAS;GACT;GACA,MAAM;GACN,MAAM,YAAY;GAClB;GACA;GACA,QAAQ,SAAS;GACjB,MAAM;EACR;EACA,kBAAkB,SAAS,MAAM;CACnC,CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate-path-parameters.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/validate-path-parameters.ts"],"sourcesContent":["import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { getExample, isParamDisabled } from '@scalar/workspace-store/request-example'\nimport type { ParameterObject, ReferenceType } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\ntype ValidatePathParametersResult = { ok: true } | { ok: false; invalidParams: string[] }\n\n/** Treats undefined, null, and blank/whitespace strings as empty. */\nconst isEmptyParamValue = (value: unknown): boolean => {\n if (value === undefined || value === null) {\n return true\n }\n if (typeof value === 'string') {\n return value.trim() === ''\n }\n return false\n}\n\n/**\n * Validates that all required path parameters have non-empty values.\n *\n * Path parameters are always required per the OpenAPI specification.\n * Returns the names of any path parameters that are missing values.\n */\nexport const validatePathParameters = (\n parameters: ReferenceType<ParameterObject>[] = [],\n exampleKey: string = 'default',\n): ValidatePathParametersResult => {\n const invalidParams: string[] = []\n\n for (const referencedParam of parameters) {\n const param = getResolvedRef(referencedParam)\n if (param.in !== 'path') {\n continue\n }\n\n const example = getExample(param, exampleKey, undefined)\n if (isParamDisabled(param, example)) {\n continue\n }\n\n if (isEmptyParamValue(example?.value)) {\n invalidParams.push(param.name)\n }\n }\n\n return invalidParams.length > 0 ? { ok: false, invalidParams } : { ok: true }\n}\n"],"mappings":";;;;AAOA,IAAM,qBAAqB,UAA4B;AACrD,KAAI,UAAU,KAAA,KAAa,UAAU,KACnC,QAAO;AAET,KAAI,OAAO,UAAU,SACnB,QAAO,MAAM,MAAM,KAAK;AAE1B,QAAO;;;;;;;;AAST,IAAa,0BACX,aAA+C,EAAE,EACjD,aAAqB,cACY;CACjC,MAAM,gBAA0B,EAAE;AAElC,MAAK,MAAM,mBAAmB,YAAY;EACxC,MAAM,QAAQ,eAAe,gBAAgB;AAC7C,MAAI,MAAM,OAAO,OACf;EAGF,MAAM,UAAU,WAAW,OAAO,YAAY,KAAA,EAAU;AACxD,MAAI,gBAAgB,OAAO,QAAQ,CACjC;AAGF,MAAI,kBAAkB,SAAS,MAAM,CACnC,eAAc,KAAK,MAAM,KAAK;;AAIlC,QAAO,cAAc,SAAS,IAAI;EAAE,IAAI;EAAO;EAAe,GAAG,EAAE,IAAI,MAAM"}
1
+ {"version":3,"file":"validate-path-parameters.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/validate-path-parameters.ts"],"sourcesContent":["import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { getExample, isParamDisabled } from '@scalar/workspace-store/request-example'\nimport type { ParameterObject, ReferenceType } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\ntype ValidatePathParametersResult = { ok: true } | { ok: false; invalidParams: string[] }\n\n/** Treats undefined, null, and blank/whitespace strings as empty. */\nconst isEmptyParamValue = (value: unknown): boolean => {\n if (value === undefined || value === null) {\n return true\n }\n if (typeof value === 'string') {\n return value.trim() === ''\n }\n return false\n}\n\n/**\n * Validates that all required path parameters have non-empty values.\n *\n * Path parameters are always required per the OpenAPI specification.\n * Returns the names of any path parameters that are missing values.\n */\nexport const validatePathParameters = (\n parameters: ReferenceType<ParameterObject>[] = [],\n exampleKey: string = 'default',\n): ValidatePathParametersResult => {\n const invalidParams: string[] = []\n\n for (const referencedParam of parameters) {\n const param = getResolvedRef(referencedParam)\n if (param.in !== 'path') {\n continue\n }\n\n const example = getExample(param, exampleKey, undefined)\n if (isParamDisabled(param, example)) {\n continue\n }\n\n if (isEmptyParamValue(example?.value)) {\n invalidParams.push(param.name)\n }\n }\n\n return invalidParams.length > 0 ? { ok: false, invalidParams } : { ok: true }\n}\n"],"mappings":";;;;AAOA,IAAM,qBAAqB,UAA4B;CACrD,IAAI,UAAU,KAAA,KAAa,UAAU,MACnC,OAAO;CAET,IAAI,OAAO,UAAU,UACnB,OAAO,MAAM,KAAK,MAAM;CAE1B,OAAO;AACT;;;;;;;AAQA,IAAa,0BACX,aAA+C,CAAC,GAChD,aAAqB,cACY;CACjC,MAAM,gBAA0B,CAAC;CAEjC,KAAK,MAAM,mBAAmB,YAAY;EACxC,MAAM,QAAQ,eAAe,eAAe;EAC5C,IAAI,MAAM,OAAO,QACf;EAGF,MAAM,UAAU,WAAW,OAAO,YAAY,KAAA,CAAS;EACvD,IAAI,gBAAgB,OAAO,OAAO,GAChC;EAGF,IAAI,kBAAkB,SAAS,KAAK,GAClC,cAAc,KAAK,MAAM,IAAI;CAEjC;CAEA,OAAO,cAAc,SAAS,IAAI;EAAE,IAAI;EAAO;CAAc,IAAI,EAAE,IAAI,KAAK;AAC9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"RequestBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/request-block/RequestBlock.vue"],"names":[],"mappings":"AAurBA,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;AAGvC,OAAO,EAIL,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;AAarE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAA;AACjG,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,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,uDAAuD;IACvD,OAAO,CAAC,EAAE,aAAa,CAAA;CACxB,CAAA;AA6zBD,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":"AA0sBA,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;AAGvC,OAAO,EAIL,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;AAcrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAA;AACjG,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,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,uDAAuD;IACvD,OAAO,CAAC,EAAE,aAAa,CAAA;CACxB,CAAA;AAm1BD,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-f52d9c1f"]]);
5
+ var RequestBlock_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RequestBlock_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-1ac895c0"]]);
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 {\n filterGlobalCookie,\n getEnvironmentVariables,\n getResolvedUrl,\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.1/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 { 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\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 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 /** 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 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} = 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 .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 as TableRow\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\nconst defaultCookies = computed(() => {\n const environmentVariables = getEnvironmentVariables(environment)\n const resolvedUrl = getResolvedUrl({\n server,\n path,\n })\n const url = replaceEnvVariables(resolvedUrl, environmentVariables)\n\n const disabledGlobalCookies =\n operation['x-scalar-disable-parameters']?.['global-cookies']?.[\n exampleKey\n ] ?? {}\n\n const transform = (\n cookie: XScalarCookie,\n location: 'document' | 'workspace',\n ) => {\n return {\n name: cookie.name,\n value: cookie.value,\n globalRoute: { page: location, path: 'cookies' } as const,\n isReadonly: true,\n isDisabled: disabledGlobalCookies[cookie.name.toLowerCase()] ?? false,\n } satisfies TableRow\n }\n\n const globalCookies = [\n {\n location: 'workspace',\n cookies: workspaceCookies,\n },\n {\n location: 'document',\n cookies: documentCookies,\n },\n ] as const\n\n return globalCookies.flatMap(({ location, cookies }) => {\n return cookies\n .filter((cookie) =>\n filterGlobalCookie({\n cookie,\n url,\n disabledGlobalCookies: {},\n }),\n )\n .map((cookie) => transform(cookie, location))\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 () =>\n Object.fromEntries(\n filters.value.map((section) => [section, sectionIds[section]]),\n ) as Record<Filter, string>,\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 const summary = (event.target as HTMLInputElement).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: createParameterHandlers('cookie', eventBus, meta.value, {\n context: cookies.value ?? [],\n globalParameters: defaultCookies.value.length,\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\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 :environment\n :exampleKey\n :requestBody=\"getResolvedRef(operation.requestBody)\"\n :requestBodyCompositionSelection\n title=\"Request Body\"\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 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 {\n filterGlobalCookie,\n getEnvironmentVariables,\n getResolvedUrl,\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.1/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 { 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\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 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 /** 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 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} = 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 .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 as TableRow\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 () =>\n Object.fromEntries(\n filters.value.map((section) => [section, sectionIds[section]]),\n ) as Record<Filter, string>,\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 const summary = (event.target as HTMLInputElement).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\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 :environment\n :exampleKey\n :requestBody=\"getResolvedRef(operation.requestBody)\"\n :requestBodyCompositionSelection\n title=\"Request Body\"\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":""}
@@ -6,6 +6,7 @@ import RequestParams_default from "./components/RequestParams.vue.js";
6
6
  import { createParameterHandlers } from "./helpers/create-parameter-handlers.js";
7
7
  import { createParameterRows } from "./helpers/create-parameter-rows.js";
8
8
  import { groupBy } from "./helpers/group-by.js";
9
+ import { groupGlobalCookies } from "./helpers/group-global-cookies.js";
9
10
  import AuthSelector_default from "../scalar-auth-selector-block/components/AuthSelector.vue.js";
10
11
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, openBlock, ref, renderList, resolveDynamicComponent, toDisplayString, toHandlers, unref, useId, vShow, watch, withCtx, withDirectives } from "vue";
11
12
  import { filterGlobalCookie, getEnvironmentVariables, getResolvedUrl } from "@scalar/workspace-store/request-example";
@@ -28,7 +29,7 @@ var _hoisted_4 = {
28
29
  class: "text-c-1 flex h-8 items-center"
29
30
  };
30
31
  var _hoisted_5 = ["id", "role"];
31
- var RequestBlock_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
32
+ var RequestBlock_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
32
33
  __name: "RequestBlock",
33
34
  props: {
34
35
  authMeta: { default: () => ({ type: "document" }) },
@@ -136,39 +137,64 @@ var RequestBlock_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ d
136
137
  });
137
138
  });
138
139
  const headers = computed(() => [...defaultHeaders.value, ...sections.value.header ?? []]);
139
- const defaultCookies = computed(() => {
140
+ /** Resolved request URL, used to filter global cookies by their domain and path. */
141
+ const requestCookieUrl = computed(() => {
140
142
  const environmentVariables = getEnvironmentVariables(__props.environment);
141
- const url = replaceEnvVariables(getResolvedUrl({
143
+ return replaceEnvVariables(getResolvedUrl({
142
144
  server: __props.server,
143
145
  path: __props.path
144
146
  }), environmentVariables);
145
- const disabledGlobalCookies = __props.operation["x-scalar-disable-parameters"]?.["global-cookies"]?.[__props.exampleKey] ?? {};
146
- const transform = (cookie, location) => {
147
- return {
148
- name: cookie.name,
149
- value: cookie.value,
150
- globalRoute: {
151
- page: location,
152
- path: "cookies"
153
- },
154
- isReadonly: true,
155
- isDisabled: disabledGlobalCookies[cookie.name.toLowerCase()] ?? false
156
- };
157
- };
158
- return [{
147
+ });
148
+ /**
149
+ * Global cookies grouped by name. Same-named cookies collapse into a single logical cookie so
150
+ * duplicate names no longer share one disabled state (which made toggling one toggle them all).
151
+ * A name with multiple values becomes a preset the user can switch between.
152
+ */
153
+ const globalCookieGroups = computed(() => groupGlobalCookies({
154
+ sources: [{
159
155
  location: "workspace",
160
156
  cookies: __props.workspaceCookies
161
157
  }, {
162
158
  location: "document",
163
159
  cookies: __props.documentCookies
164
- }].flatMap(({ location, cookies }) => {
165
- return cookies.filter((cookie) => filterGlobalCookie({
166
- cookie,
167
- url,
168
- disabledGlobalCookies: {}
169
- })).map((cookie) => transform(cookie, location));
170
- });
160
+ }],
161
+ shouldInclude: (cookie) => filterGlobalCookie({
162
+ cookie: {
163
+ ...cookie,
164
+ isDisabled: false
165
+ },
166
+ url: requestCookieUrl.value,
167
+ disabledGlobalCookies: {}
168
+ })
169
+ }));
170
+ const defaultCookies = computed(() => {
171
+ const disabledGlobalCookies = __props.operation["x-scalar-disable-parameters"]?.["global-cookies"]?.[__props.exampleKey] ?? {};
172
+ return globalCookieGroups.value.map((group) => ({
173
+ name: group.name,
174
+ value: group.selectedValue,
175
+ globalRoute: {
176
+ page: group.location,
177
+ path: "cookies"
178
+ },
179
+ isReadonly: true,
180
+ isDisabled: disabledGlobalCookies[group.name.toLowerCase()] ?? false,
181
+ presetOptions: group.isPreset ? group.options : void 0
182
+ }));
171
183
  });
184
+ /**
185
+ * Switch a grouped global cookie preset to the chosen value by enabling the matching sibling and
186
+ * disabling the rest. Selection is written back to the source `x-scalar-cookies` list so it
187
+ * persists, and the send path drops disabled cookies, so only the selected value is sent.
188
+ */
189
+ const handleSelectCookiePreset = (index, value) => {
190
+ const group = globalCookieGroups.value[index];
191
+ if (!group) return;
192
+ for (const sibling of group.siblings) __props.eventBus.emit("cookie:upsert:cookie", {
193
+ collectionType: sibling.location,
194
+ index: sibling.index,
195
+ payload: { isDisabled: sibling.value !== value }
196
+ });
197
+ };
172
198
  const cookies = computed(() => [...defaultCookies.value ?? [], ...sections.value.cookie ?? []]);
173
199
  /** Currently selected filter for the request sections */
174
200
  const selectedFilter = ref("All");
@@ -196,7 +222,7 @@ var RequestBlock_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ d
196
222
  };
197
223
  /** Filters available based on operation state */
198
224
  const filters = computed(() => {
199
- const availableFilters = new Set(["All", ...OPERATION_SECTIONS]);
225
+ const availableFilters = /* @__PURE__ */ new Set(["All", ...OPERATION_SECTIONS]);
200
226
  if (!sections.value.path?.length) availableFilters.delete("Variables");
201
227
  if (!canMethodHaveBody(__props.method)) availableFilters.delete("Body");
202
228
  if (isAuthHidden.value) availableFilters.delete("Auth");
@@ -252,10 +278,13 @@ var RequestBlock_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ d
252
278
  /** Parameter handlers */
253
279
  const parameterHandlers = computed(() => ({
254
280
  path: createParameterHandlers("path", __props.eventBus, meta.value, { context: sections.value.path ?? [] }),
255
- cookie: createParameterHandlers("cookie", __props.eventBus, meta.value, {
256
- context: cookies.value ?? [],
257
- globalParameters: defaultCookies.value.length
258
- }),
281
+ cookie: {
282
+ ...createParameterHandlers("cookie", __props.eventBus, meta.value, {
283
+ context: cookies.value ?? [],
284
+ globalParameters: defaultCookies.value.length
285
+ }),
286
+ selectPreset: handleSelectCookiePreset
287
+ },
259
288
  header: createParameterHandlers("header", __props.eventBus, meta.value, {
260
289
  context: headers.value,
261
290
  defaultParameters: defaultHeaders.value.length