@scalar/api-client 3.8.5 → 3.10.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 (60) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/plugins/posthog/sanitize-event-payload.d.ts.map +1 -1
  3. package/dist/plugins/posthog/sanitize-event-payload.js +2 -0
  4. package/dist/plugins/posthog/sanitize-event-payload.js.map +1 -1
  5. package/dist/style.css +16 -19
  6. package/dist/v2/blocks/channel-operation-block/helpers/connect-websocket.d.ts +46 -0
  7. package/dist/v2/blocks/channel-operation-block/helpers/connect-websocket.d.ts.map +1 -0
  8. package/dist/v2/blocks/channel-operation-block/helpers/websocket-session.d.ts +59 -0
  9. package/dist/v2/blocks/channel-operation-block/helpers/websocket-session.d.ts.map +1 -0
  10. package/dist/v2/blocks/channel-operation-block/index.d.ts +3 -0
  11. package/dist/v2/blocks/channel-operation-block/index.d.ts.map +1 -0
  12. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
  13. package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
  14. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +4 -0
  15. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
  16. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts +7 -4
  17. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts.map +1 -1
  18. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js +1 -1
  19. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js.map +1 -1
  20. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js +28 -15
  21. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js.map +1 -1
  22. package/dist/v2/blocks/operation-code-sample/helpers/find-client.d.ts +31 -31
  23. package/dist/v2/blocks/operation-code-sample/helpers/find-client.d.ts.map +1 -1
  24. package/dist/v2/blocks/operation-code-sample/helpers/find-client.js +32 -39
  25. package/dist/v2/blocks/operation-code-sample/helpers/find-client.js.map +1 -1
  26. package/dist/v2/blocks/operation-code-sample/helpers/format-language.d.ts +8 -0
  27. package/dist/v2/blocks/operation-code-sample/helpers/format-language.d.ts.map +1 -0
  28. package/dist/v2/blocks/operation-code-sample/helpers/format-language.js +70 -0
  29. package/dist/v2/blocks/operation-code-sample/helpers/format-language.js.map +1 -0
  30. package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.d.ts +17 -2
  31. package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.d.ts.map +1 -1
  32. package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.js +26 -3
  33. package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.js.map +1 -1
  34. package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.d.ts.map +1 -1
  35. package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js +2 -2
  36. package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js.map +1 -1
  37. package/dist/v2/blocks/operation-code-sample/helpers/get-clients.d.ts +2 -1
  38. package/dist/v2/blocks/operation-code-sample/helpers/get-clients.d.ts.map +1 -1
  39. package/dist/v2/blocks/operation-code-sample/helpers/get-clients.js +23 -17
  40. package/dist/v2/blocks/operation-code-sample/helpers/get-clients.js.map +1 -1
  41. package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.d.ts +38 -3
  42. package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.d.ts.map +1 -1
  43. package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.js +74 -8
  44. package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.js.map +1 -1
  45. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.d.ts.map +1 -1
  46. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js +12 -87
  47. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js.map +1 -1
  48. package/dist/v2/blocks/operation-code-sample/index.d.ts +1 -1
  49. package/dist/v2/blocks/operation-code-sample/index.d.ts.map +1 -1
  50. package/dist/v2/blocks/operation-code-sample/index.js +2 -2
  51. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
  52. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
  53. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +11 -6
  54. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
  55. package/dist/v2/constants.js +1 -1
  56. package/dist/v2/workspace-events.d.ts.map +1 -1
  57. package/dist/v2/workspace-events.js +2 -0
  58. package/dist/v2/workspace-events.js.map +1 -1
  59. package/dist/vue-styles.css +7 -7
  60. package/package.json +19 -14
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @scalar/api-client
2
2
 
3
+ ## 3.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#9398](https://github.com/scalar/scalar/pull/9398): feat: read code samples from x-readme, x-stainless and x-scalar extensions
8
+
9
+ In addition to `x-codeSamples`, the code sample picker now reads custom samples from `x-scalar-examples`, `x-stainless-snippets`, `x-stainless-examples`, and `x-readme.code-samples`. When more than one is present on an operation, the highest-priority source is used (x-scalar-examples > x-stainless-snippets > x-stainless-examples > x-readme > x-codeSamples).
10
+
11
+ ### Patch Changes
12
+
13
+ - [#9438](https://github.com/scalar/scalar/pull/9438): feat(api-reference): add an AsyncAPI server selector
14
+
15
+ Adds a server selector for AsyncAPI documents in the API reference introduction. It mirrors the OpenAPI server selector but works with the AsyncAPI server shape (a named map of `host`/`protocol`/`pathname`), labelling each server with its constructed connection URL.
16
+
17
+ Server selection and variable changes are now persisted to the workspace store via new `asyncapi-server:update:selected` and `asyncapi-server:update:variables` events and their mutators, mirroring the OpenAPI wiring.
18
+
19
+ - [#9404](https://github.com/scalar/scalar/pull/9404): Send `multipart/form-data` and `application/x-www-form-urlencoded` object properties using their OpenAPI encoding `style`/`explode` (for example `style: deepObject` produces `address[city]=...` bracket notation) instead of always JSON-stringifying them. The request sent over the wire now matches the generated code snippet.
20
+ - [#9408](https://github.com/scalar/scalar/pull/9408): Render the client library name as a plain label instead of a dropdown when only a single client is available
21
+
22
+ ## 3.9.0
23
+
24
+ ### Minor Changes
25
+
26
+ - [#9341](https://github.com/scalar/scalar/pull/9341): feat: add WebSocket session transport and plugin hooks for AsyncAPI
27
+
28
+ Add WebSocketSession with connect, send, and close helpers, plus connectWebSocket orchestration using Result-based errors. Extend ClientPlugin with optional webSocketHooks (beforeConnect, onWebSocketMessage, onWebSocketClose).
29
+
30
+ ### Patch Changes
31
+
32
+ - [#9310](https://github.com/scalar/scalar/pull/9310): Add an ESM standalone build (`dist/browser/standalone.esm.js`) alongside the existing UMD bundle. The new bundle works as a side-effect script (registers `window.Scalar.createApiReference` and reads `data-*` configuration) and exports `createApiReference` for direct ESM consumers. It is fully minified through Rolldown's native minifier and uses code splitting so heavy features load asynchronously after first paint:
33
+ - The API client modal (request editor, response viewer, CodeMirror) is now `await import`'d inside `onMounted` instead of statically imported, moving ~265 KB into a `chunks/modal-*.js` chunk that loads in the background.
34
+ - The Agent Scalar chat interface (already wrapped in `defineAsyncComponent`) becomes a real `chunks/AgentScalarChatInterface-*.js` chunk (~200 KB), loaded only when the agent is enabled.
35
+ - The 84 per-icon dynamic imports from `@scalar/icons/library` are coalesced into a single `chunks/icons-*.js`.
36
+
37
+ Net effect: initial sync load drops from ~3.32 MB (UMD) to ~2.73 MB (ESM) — a ~570 KB improvement — while total bundle size shrinks by ~140 KB.
38
+
39
+ Also adds an `@scalar/api-client/modal/map-hidden-clients-config` deep export so consumers that only need the lightweight client-list helper don't pull the full modal barrel into their static graph.
40
+
41
+ - [#9323](https://github.com/scalar/scalar/pull/9323): Fixed `x-codeSamples` entries that share a `lang`: multiple code samples with the same language but different labels (e.g. separate sync and async examples) were all marked selected and showed the same snippet. Each sample is now keyed by its position, so every one stays individually selectable.
42
+ - [#9338](https://github.com/scalar/scalar/pull/9338): perf: warm up the request scripts sandbox on mount when scripts are present, so the first request no longer pays the sandbox cold-start cost
43
+
3
44
  ## 3.8.5
4
45
 
5
46
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize-event-payload.d.ts","sourceRoot":"","sources":["../../../src/plugins/posthog/sanitize-event-payload.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAuBxE;;;;;;GAMG;AACH,KAAK,gBAAgB,CAAC,CAAC,SAAS,MAAM,kBAAkB,GAAG,MAAM,kBAAkB,IAAI,CACrF,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAA;AAEpD,4EAA4E;AAC5E,KAAK,gBAAgB,GAAG;KACrB,CAAC,IAAI,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS;CACjE,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,gBAkI5B,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,MAAM,kBAAkB,EACrE,OAAO,CAAC,EACR,SAAS,kBAAkB,CAAC,CAAC,CAAC,KAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAMpD,CAAA"}
1
+ {"version":3,"file":"sanitize-event-payload.d.ts","sourceRoot":"","sources":["../../../src/plugins/posthog/sanitize-event-payload.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAuBxE;;;;;;GAMG;AACH,KAAK,gBAAgB,CAAC,CAAC,SAAS,MAAM,kBAAkB,GAAG,MAAM,kBAAkB,IAAI,CACrF,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAA;AAEpD,4EAA4E;AAC5E,KAAK,gBAAgB,GAAG;KACrB,CAAC,IAAI,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,SAAS;CACjE,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,gBAoI5B,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,MAAM,kBAAkB,EACrE,OAAO,CAAC,EACR,SAAS,kBAAkB,CAAC,CAAC,CAAC,KAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAMpD,CAAA"}
@@ -98,6 +98,8 @@ var TRACKED_EVENTS = {
98
98
  "server:update:variables": void 0,
99
99
  "server:update:selected": void 0,
100
100
  "server:clear:servers": void 0,
101
+ "asyncapi-server:update:selected": void 0,
102
+ "asyncapi-server:update:variables": void 0,
101
103
  "tabs:update:tabs": void 0,
102
104
  "tabs:close:tab": void 0,
103
105
  "tabs:close:other-tabs": void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize-event-payload.js","names":[],"sources":["../../../src/plugins/posthog/sanitize-event-payload.ts"],"sourcesContent":["import { getValueAtPath } from '@scalar/helpers/object/get-value-at-path'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\n\n/**\n * Builds an extractor that pulls a string from `payload` at `path` and emits\n * it under `{ [key]: value }`. Returns `{}` when the leaf is missing or is\n * not a string.\n *\n * `key` defaults to the dotted form of `path` (e.g. `['meta', 'type']` becomes\n * `'meta.type'`), matching the existing PostHog property names.\n *\n * Built on `getValueAtPath`, so null/undefined traversal and missing segments\n * are handled centrally.\n */\nconst stringAtPath = (path: string[], key: string = path.join('.')) => {\n return (payload: unknown): Record<string, unknown> => {\n const value = getValueAtPath(payload, path)\n return typeof value === 'string' ? { [key]: value } : {}\n }\n}\n\n/** Extractor for events whose only useful property is the fact they fired. */\nconst empty = (): Record<string, unknown> => ({})\n\n/**\n * Allowlist of events that should be forwarded to PostHog.\n *\n * Each key is an event name; its value is an extractor that pulls only the\n * safe, non-PII properties we want to track. Events not in this map are\n * silently dropped — this keeps the analytics surface explicit and auditable.\n */\ntype PayloadExtractor<K extends keyof ApiReferenceEvents = keyof ApiReferenceEvents> = (\n payload: ApiReferenceEvents[K],\n) => Record<string, unknown> | ApiReferenceEvents[K]\n\n/** Maps every event to either a typed extractor or `undefined` (opt-out) */\ntype TrackedEventsMap = {\n [K in keyof ApiReferenceEvents]: PayloadExtractor<K> | undefined\n}\n\nexport const TRACKED_EVENTS: TrackedEventsMap = {\n // Auth events — track the scheme type so we know which auth methods are popular\n 'auth:update:selected-security-schemes': stringAtPath(['meta', 'type']),\n 'auth:update:active-index': stringAtPath(['meta', 'type']),\n 'auth:update:security-scheme': stringAtPath(['payload', 'type']),\n 'auth:clear:selected-security-schemes': stringAtPath(['meta', 'type']),\n 'auth:update:selected-scopes': stringAtPath(['meta', 'type']),\n 'auth:delete:security-scheme': empty,\n 'auth:clear:security-scheme-secrets': empty,\n 'auth:upsert:scopes': empty,\n 'auth:delete:scopes': empty,\n\n // Cookie events — track whether it belongs to a document or workspace\n 'cookie:upsert:cookie': stringAtPath(['collectionType']),\n 'cookie:delete:cookie': stringAtPath(['collectionType']),\n\n // Environment events — same document-vs-workspace distinction\n 'environment:upsert:environment': stringAtPath(['collectionType']),\n 'environment:delete:environment': stringAtPath(['collectionType']),\n 'environment:upsert:environment-variable': stringAtPath(['collectionType']),\n 'environment:delete:environment-variable': stringAtPath(['collectionType']),\n\n // Document lifecycle\n 'document:create:empty-document': empty,\n 'document:delete:document': empty,\n 'document:update:info': empty,\n 'document:update:icon': empty,\n 'document:update:watch-mode': empty,\n\n // Operation events — contentType helps us understand payload format usage\n 'operation:send:request:hotkey': empty,\n 'operation:cancel:request': empty,\n 'operation:create:operation': empty,\n 'operation:delete:operation': empty,\n 'operation:create:draft-example': empty,\n 'operation:delete:example': empty,\n 'operation:update:requestBody:contentType': stringAtPath(['payload', 'contentType']),\n 'operation:update:pathMethod': empty,\n 'operation:rename:example': empty,\n 'operation:reload:history': empty,\n\n // UI events — track which surfaces users interact with\n 'ui:open:client-modal': empty,\n 'ui:open:command-palette': empty,\n 'ui:open:settings': empty,\n 'ui:download:document': stringAtPath(['format']),\n 'ui:toggle:sidebar': empty,\n 'ui:save:local-document': empty,\n 'copy-url:address-bar': empty,\n 'tabs:add:tab': empty,\n 'tabs:copy:url': empty,\n\n // Server events\n 'server:add:server': empty,\n 'server:delete:server': empty,\n\n // Tag events\n 'tag:create:tag': empty,\n 'tag:delete:tag': empty,\n\n // Request lifecycle hooks — lets us measure request volume without capturing bodies\n 'hooks:on:request:sent': empty,\n 'hooks:on:request:complete': empty,\n 'hooks:on:rebase:document:complete': empty,\n\n // Workspace preference events\n 'workspace:update:color-mode': empty,\n 'workspace:update:theme': empty,\n 'workspace:update:selected-client': empty,\n 'workspace:update:active-proxy': (payload) => ({ enabled: !!payload }),\n 'workspace:update:active-environment': empty,\n\n // Meta events\n 'update:dark-mode': empty,\n 'update:active-document': empty,\n 'update:selected-client': empty,\n\n // Account funnel events\n 'log:login-click': empty,\n 'log:register-click': empty,\n 'log:user-login': empty,\n 'log:user-logout': empty,\n\n // Document sync and save events\n 'log:save-document': empty,\n 'log:sync-pull-document': empty,\n 'log:sync-push-document': empty,\n\n // ---------------------------------------------------------------------------\n // Do not track — explicitly opted out so new events cause a type error\n // until they are consciously placed above with a payload\n // ---------------------------------------------------------------------------\n 'auth:update:security-scheme-secrets': undefined,\n 'analytics:on:show-more': undefined,\n 'analytics:on:loaded': undefined,\n 'document:update:extension': undefined,\n 'operation:update:meta': undefined,\n 'operation:update:extension': undefined,\n 'operation:upsert:parameter': undefined,\n 'operation:update:extra-parameters': undefined,\n 'operation:delete:parameter': undefined,\n 'operation:delete-all:parameters': undefined,\n 'operation:update:requestBody:value': undefined,\n 'operation:update:requestBody:formValue': undefined,\n 'server:initialize:servers': undefined,\n 'server:update:server': undefined,\n 'server:update:variables': undefined,\n 'server:update:selected': undefined,\n 'server:clear:servers': undefined,\n 'tabs:update:tabs': undefined,\n 'tabs:close:tab': undefined,\n 'tabs:close:other-tabs': undefined,\n 'tabs:navigate:previous': undefined,\n 'tabs:navigate:next': undefined,\n 'tabs:focus:tab': undefined,\n 'tabs:focus:tab-last': undefined,\n 'ui:focus:address-bar': undefined,\n 'ui:focus:send-button': undefined,\n 'ui:focus:search': undefined,\n 'ui:open:create-workspace': undefined,\n 'ui:close:client-modal': undefined,\n 'ui:navigate': undefined,\n 'toggle:nav-item': undefined,\n 'select:nav-item': undefined,\n 'intersecting:nav-item': undefined,\n 'scroll-to:nav-item': undefined,\n 'scroll-to:model-by-name': undefined,\n 'copy-url:nav-item': undefined,\n 'tag:edit:tag': undefined,\n 'workspace:update:name': undefined,\n}\n\n/**\n * Returns sanitized properties for a tracked event, or `null` if the event\n * should not be captured at all.\n *\n * This is the only function that the PostHog plugin needs to call — it\n * encapsulates both the \"should we track this?\" decision and the \"what\n * properties are safe to send?\" extraction in one step.\n */\nexport const sanitizeEventPayload = <K extends keyof ApiReferenceEvents>(\n event: K,\n payload: ApiReferenceEvents[K],\n): Record<string, unknown> | ApiReferenceEvents[K] | null => {\n const extractor = TRACKED_EVENTS[event]\n if (!extractor) {\n return null\n }\n return extractor(payload)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sanitize-event-payload.js","names":[],"sources":["../../../src/plugins/posthog/sanitize-event-payload.ts"],"sourcesContent":["import { getValueAtPath } from '@scalar/helpers/object/get-value-at-path'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\n\n/**\n * Builds an extractor that pulls a string from `payload` at `path` and emits\n * it under `{ [key]: value }`. Returns `{}` when the leaf is missing or is\n * not a string.\n *\n * `key` defaults to the dotted form of `path` (e.g. `['meta', 'type']` becomes\n * `'meta.type'`), matching the existing PostHog property names.\n *\n * Built on `getValueAtPath`, so null/undefined traversal and missing segments\n * are handled centrally.\n */\nconst stringAtPath = (path: string[], key: string = path.join('.')) => {\n return (payload: unknown): Record<string, unknown> => {\n const value = getValueAtPath(payload, path)\n return typeof value === 'string' ? { [key]: value } : {}\n }\n}\n\n/** Extractor for events whose only useful property is the fact they fired. */\nconst empty = (): Record<string, unknown> => ({})\n\n/**\n * Allowlist of events that should be forwarded to PostHog.\n *\n * Each key is an event name; its value is an extractor that pulls only the\n * safe, non-PII properties we want to track. Events not in this map are\n * silently dropped — this keeps the analytics surface explicit and auditable.\n */\ntype PayloadExtractor<K extends keyof ApiReferenceEvents = keyof ApiReferenceEvents> = (\n payload: ApiReferenceEvents[K],\n) => Record<string, unknown> | ApiReferenceEvents[K]\n\n/** Maps every event to either a typed extractor or `undefined` (opt-out) */\ntype TrackedEventsMap = {\n [K in keyof ApiReferenceEvents]: PayloadExtractor<K> | undefined\n}\n\nexport const TRACKED_EVENTS: TrackedEventsMap = {\n // Auth events — track the scheme type so we know which auth methods are popular\n 'auth:update:selected-security-schemes': stringAtPath(['meta', 'type']),\n 'auth:update:active-index': stringAtPath(['meta', 'type']),\n 'auth:update:security-scheme': stringAtPath(['payload', 'type']),\n 'auth:clear:selected-security-schemes': stringAtPath(['meta', 'type']),\n 'auth:update:selected-scopes': stringAtPath(['meta', 'type']),\n 'auth:delete:security-scheme': empty,\n 'auth:clear:security-scheme-secrets': empty,\n 'auth:upsert:scopes': empty,\n 'auth:delete:scopes': empty,\n\n // Cookie events — track whether it belongs to a document or workspace\n 'cookie:upsert:cookie': stringAtPath(['collectionType']),\n 'cookie:delete:cookie': stringAtPath(['collectionType']),\n\n // Environment events — same document-vs-workspace distinction\n 'environment:upsert:environment': stringAtPath(['collectionType']),\n 'environment:delete:environment': stringAtPath(['collectionType']),\n 'environment:upsert:environment-variable': stringAtPath(['collectionType']),\n 'environment:delete:environment-variable': stringAtPath(['collectionType']),\n\n // Document lifecycle\n 'document:create:empty-document': empty,\n 'document:delete:document': empty,\n 'document:update:info': empty,\n 'document:update:icon': empty,\n 'document:update:watch-mode': empty,\n\n // Operation events — contentType helps us understand payload format usage\n 'operation:send:request:hotkey': empty,\n 'operation:cancel:request': empty,\n 'operation:create:operation': empty,\n 'operation:delete:operation': empty,\n 'operation:create:draft-example': empty,\n 'operation:delete:example': empty,\n 'operation:update:requestBody:contentType': stringAtPath(['payload', 'contentType']),\n 'operation:update:pathMethod': empty,\n 'operation:rename:example': empty,\n 'operation:reload:history': empty,\n\n // UI events — track which surfaces users interact with\n 'ui:open:client-modal': empty,\n 'ui:open:command-palette': empty,\n 'ui:open:settings': empty,\n 'ui:download:document': stringAtPath(['format']),\n 'ui:toggle:sidebar': empty,\n 'ui:save:local-document': empty,\n 'copy-url:address-bar': empty,\n 'tabs:add:tab': empty,\n 'tabs:copy:url': empty,\n\n // Server events\n 'server:add:server': empty,\n 'server:delete:server': empty,\n\n // Tag events\n 'tag:create:tag': empty,\n 'tag:delete:tag': empty,\n\n // Request lifecycle hooks — lets us measure request volume without capturing bodies\n 'hooks:on:request:sent': empty,\n 'hooks:on:request:complete': empty,\n 'hooks:on:rebase:document:complete': empty,\n\n // Workspace preference events\n 'workspace:update:color-mode': empty,\n 'workspace:update:theme': empty,\n 'workspace:update:selected-client': empty,\n 'workspace:update:active-proxy': (payload) => ({ enabled: !!payload }),\n 'workspace:update:active-environment': empty,\n\n // Meta events\n 'update:dark-mode': empty,\n 'update:active-document': empty,\n 'update:selected-client': empty,\n\n // Account funnel events\n 'log:login-click': empty,\n 'log:register-click': empty,\n 'log:user-login': empty,\n 'log:user-logout': empty,\n\n // Document sync and save events\n 'log:save-document': empty,\n 'log:sync-pull-document': empty,\n 'log:sync-push-document': empty,\n\n // ---------------------------------------------------------------------------\n // Do not track — explicitly opted out so new events cause a type error\n // until they are consciously placed above with a payload\n // ---------------------------------------------------------------------------\n 'auth:update:security-scheme-secrets': undefined,\n 'analytics:on:show-more': undefined,\n 'analytics:on:loaded': undefined,\n 'document:update:extension': undefined,\n 'operation:update:meta': undefined,\n 'operation:update:extension': undefined,\n 'operation:upsert:parameter': undefined,\n 'operation:update:extra-parameters': undefined,\n 'operation:delete:parameter': undefined,\n 'operation:delete-all:parameters': undefined,\n 'operation:update:requestBody:value': undefined,\n 'operation:update:requestBody:formValue': undefined,\n 'server:initialize:servers': undefined,\n 'server:update:server': undefined,\n 'server:update:variables': undefined,\n 'server:update:selected': undefined,\n 'server:clear:servers': undefined,\n 'asyncapi-server:update:selected': undefined,\n 'asyncapi-server:update:variables': undefined,\n 'tabs:update:tabs': undefined,\n 'tabs:close:tab': undefined,\n 'tabs:close:other-tabs': undefined,\n 'tabs:navigate:previous': undefined,\n 'tabs:navigate:next': undefined,\n 'tabs:focus:tab': undefined,\n 'tabs:focus:tab-last': undefined,\n 'ui:focus:address-bar': undefined,\n 'ui:focus:send-button': undefined,\n 'ui:focus:search': undefined,\n 'ui:open:create-workspace': undefined,\n 'ui:close:client-modal': undefined,\n 'ui:navigate': undefined,\n 'toggle:nav-item': undefined,\n 'select:nav-item': undefined,\n 'intersecting:nav-item': undefined,\n 'scroll-to:nav-item': undefined,\n 'scroll-to:model-by-name': undefined,\n 'copy-url:nav-item': undefined,\n 'tag:edit:tag': undefined,\n 'workspace:update:name': undefined,\n}\n\n/**\n * Returns sanitized properties for a tracked event, or `null` if the event\n * should not be captured at all.\n *\n * This is the only function that the PostHog plugin needs to call — it\n * encapsulates both the \"should we track this?\" decision and the \"what\n * properties are safe to send?\" extraction in one step.\n */\nexport const sanitizeEventPayload = <K extends keyof ApiReferenceEvents>(\n event: K,\n payload: ApiReferenceEvents[K],\n): Record<string, unknown> | ApiReferenceEvents[K] | null => {\n const extractor = TRACKED_EVENTS[event]\n if (!extractor) {\n return null\n }\n return extractor(payload)\n}\n"],"mappings":"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"}
package/dist/style.css CHANGED
@@ -102,12 +102,9 @@
102
102
  --scalar-radius: 3px;
103
103
  --scalar-radius-lg: 6px;
104
104
  --scalar-radius-xl: 8px;
105
- --scalar-font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
106
- "Helvetica Neue", sans-serif;
107
- --scalar-font-code: "JetBrains Mono", ui-monospace, Menlo, Monaco,
108
- "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono",
109
- "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono",
110
- "Courier New", monospace;
105
+ --scalar-font: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
106
+ "Noto Color Emoji";
107
+ --scalar-font-code: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
111
108
  --scalar-heading-1: 24px;
112
109
  --scalar-page-description: 16px;
113
110
  --scalar-heading-2: 20px;
@@ -165,7 +162,7 @@
165
162
  --scalar-scrollbar-color: #0000002e;
166
163
  --scalar-button-1: #000;
167
164
  --scalar-button-1-hover: #000c;
168
- --scalar-button-1-color: #ffffffe6;
165
+ --scalar-button-1-color: #fff;
169
166
  --scalar-shadow-1: 0 1px 3px 0 #0000001c;
170
167
  --scalar-shadow-2: #00000014 0px 13px 20px 0px, #00000014 0px 3px 8px 0px, #eeeeed 0px 0 0 .5px;
171
168
  --scalar-lifted-brightness: 1;
@@ -259,7 +256,7 @@
259
256
  --scalar-link-color-hover: var(--scalar-link-color);
260
257
  --scalar-button-1: #000;
261
258
  --scalar-button-1-hover: #000c;
262
- --scalar-button-1-color: #ffffffe6;
259
+ --scalar-button-1-color: #fff;
263
260
  --scalar-tooltip-background: #1a1a1ae6;
264
261
  --scalar-tooltip-color: #ffffffd9;
265
262
  --scalar-color-alert: var(--scalar-color-orange);
@@ -666,6 +663,10 @@
666
663
  }
667
664
  }
668
665
 
666
+ .scalar-code-block pre {
667
+ font-variant-ligatures: none;
668
+ }
669
+
669
670
  .scalar-code-block.bg-b-1 .scalar-code-copy-backdrop {
670
671
  background-color: var(--scalar-background-1);
671
672
  }
@@ -2008,10 +2009,6 @@
2008
2009
  top: 1lh;
2009
2010
  }
2010
2011
 
2011
- .scalar-app .top-\[calc\(10px\+0\.5lh\)\] {
2012
- top: calc(10px + .5lh);
2013
- }
2014
-
2015
2012
  .scalar-app .top-\[calc\(100\%\+4px\)\] {
2016
2013
  top: calc(100% + 4px);
2017
2014
  }
@@ -6546,34 +6543,34 @@ to {
6546
6543
  }
6547
6544
  }
6548
6545
 
6549
- .request-card[data-v-49c97039] {
6546
+ .request-card[data-v-70ede25b] {
6550
6547
  color: var(--scalar-color-1);
6551
6548
  font-size: var(--scalar-font-size-3);
6552
6549
  }
6553
- .request-method[data-v-49c97039] {
6550
+ .request-method[data-v-70ede25b] {
6554
6551
  font-family: var(--scalar-font-code);
6555
6552
  text-transform: uppercase;
6556
6553
  margin-right: 6px;
6557
6554
  }
6558
- .request-card-footer[data-v-49c97039] {
6555
+ .request-card-footer[data-v-70ede25b] {
6559
6556
  display: flex;
6560
6557
  justify-content: flex-end;
6561
6558
  padding: 6px;
6562
6559
  flex-shrink: 0;
6563
6560
  position: relative;
6564
6561
  }
6565
- .request-card-footer-addon[data-v-49c97039] {
6562
+ .request-card-footer-addon[data-v-70ede25b] {
6566
6563
  display: flex;
6567
6564
  align-items: center;
6568
6565
 
6569
6566
  flex: 1;
6570
6567
  min-width: 0;
6571
6568
  }
6572
- .request-editor-section[data-v-49c97039] {
6569
+ .request-editor-section[data-v-70ede25b] {
6573
6570
  display: flex;
6574
6571
  flex: 1;
6575
6572
  }
6576
- .request-card-simple[data-v-49c97039] {
6573
+ .request-card-simple[data-v-70ede25b] {
6577
6574
  display: flex;
6578
6575
  align-items: center;
6579
6576
  justify-content: space-between;
@@ -6582,7 +6579,7 @@ to {
6582
6579
 
6583
6580
  font-size: var(--scalar-small);
6584
6581
  }
6585
- .code-snippet[data-v-49c97039] {
6582
+ .code-snippet[data-v-70ede25b] {
6586
6583
  display: flex;
6587
6584
  flex-direction: column;
6588
6585
  width: 100%;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * WebSocket connection orchestrator for AsyncAPI channel operations.
3
+ *
4
+ * Mirrors the `sendRequest` pattern: accepts a connection URL, optional plugins,
5
+ * and a session, then wires up the lifecycle. Plugin hooks (`beforeConnect`,
6
+ * `onWebSocketMessage`, `onWebSocketClose`) run at the appropriate points.
7
+ *
8
+ * Browser WebSocket cannot set arbitrary headers on the handshake, so auth is
9
+ * applied via query parameters. The proxy URL is intentionally unused here
10
+ * because WebSocket traffic does not go through an HTTP CORS proxy.
11
+ */
12
+ import { type Result } from '@scalar/helpers/types/result';
13
+ import type { ClientPlugin } from '@scalar/oas-utils/helpers';
14
+ import type { WebSocketCloseInfo, WebSocketFrame, WebSocketSession, WebSocketSessionState } from './websocket-session';
15
+ export type ConnectWebSocketOptions = {
16
+ connectionUrl: string;
17
+ protocols?: string | string[];
18
+ session: WebSocketSession;
19
+ plugins?: ClientPlugin[];
20
+ callbacks?: {
21
+ onFrame?: (frame: WebSocketFrame) => void;
22
+ onStateChange?: (state: WebSocketSessionState, previous: WebSocketSessionState) => void;
23
+ onError?: (event: Event) => void;
24
+ onClose?: (info: WebSocketCloseInfo) => void;
25
+ onOpen?: () => void;
26
+ };
27
+ /** Injectable WebSocket constructor for tests or Electron override */
28
+ customWebSocket?: typeof WebSocket;
29
+ };
30
+ export type ConnectWebSocketData = {
31
+ session: WebSocketSession;
32
+ };
33
+ /** Failure code when the WebSocket handshake or connection cannot be established. */
34
+ export declare const WEBSOCKET_CONNECTION_FAILED: "WEBSOCKET_CONNECTION_FAILED";
35
+ export declare const WEBSOCKET_CONNECTION_FAILED_MESSAGE: "The WebSocket connection could not be established";
36
+ export type ConnectWebSocketFailureCode = typeof WEBSOCKET_CONNECTION_FAILED;
37
+ export type ConnectWebSocketResult = Result<ConnectWebSocketData, ConnectWebSocketFailureCode>;
38
+ /**
39
+ * Connects a WebSocket session after running plugin `beforeConnect` hooks.
40
+ *
41
+ * Resolves once the socket opens, or returns a failure result on error or close
42
+ * before open. After the initial connect, the session stays alive and messages
43
+ * flow through `onFrame` until the caller (or the server) closes it.
44
+ */
45
+ export declare const connectWebSocket: ({ connectionUrl, protocols, session, plugins, callbacks, customWebSocket, }: ConnectWebSocketOptions) => Promise<ConnectWebSocketResult>;
46
+ //# sourceMappingURL=connect-websocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-websocket.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/channel-operation-block/helpers/connect-websocket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,8BAA8B,CAAA;AAEnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAG7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAEtH,MAAM,MAAM,uBAAuB,GAAG;IACpC,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC7B,OAAO,EAAE,gBAAgB,CAAA;IACzB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;QACzC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAA;QACvF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;QAChC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;QAC5C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;KACpB,CAAA;IACD,sEAAsE;IACtE,eAAe,CAAC,EAAE,OAAO,SAAS,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,2BAA2B,EAAG,6BAAsC,CAAA;AAEjF,eAAO,MAAM,mCAAmC,EAAG,mDAA4D,CAAA;AAE/G,MAAM,MAAM,2BAA2B,GAAG,OAAO,2BAA2B,CAAA;AAE5E,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,oBAAoB,EAAE,2BAA2B,CAAC,CAAA;AAK9F;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAU,6EAOpC,uBAAuB,KAAG,OAAO,CAAC,sBAAsB,CAmD1D,CAAA"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * WebSocket session abstraction for the AsyncAPI channel operation transport.
3
+ *
4
+ * Manages the lifecycle of a single WebSocket connection: connect, send, close.
5
+ * The session tracks connection state transitions and bidirectional message frames,
6
+ * emitting callbacks so the UI can render a live message log.
7
+ *
8
+ * Browser WebSocket does not support custom headers on the handshake request.
9
+ * Auth is applied via query parameters or Sec-WebSocket-Protocol where applicable.
10
+ * In Electron, a richer handshake path may be used in the future.
11
+ */
12
+ export type WebSocketSessionState = 'idle' | 'connecting' | 'open' | 'closing' | 'closed' | 'error';
13
+ export type WebSocketFrameOpcode = 'text' | 'binary' | 'close';
14
+ export type WebSocketFrame = {
15
+ direction: 'incoming' | 'outgoing';
16
+ timestamp: number;
17
+ data: string | ArrayBuffer;
18
+ opcode: WebSocketFrameOpcode;
19
+ };
20
+ export type WebSocketCloseInfo = {
21
+ code: number;
22
+ reason: string;
23
+ wasClean: boolean;
24
+ };
25
+ export type WebSocketSessionCallbacks = {
26
+ onFrame?: (frame: WebSocketFrame) => void;
27
+ onStateChange?: (state: WebSocketSessionState, previous: WebSocketSessionState) => void;
28
+ onError?: (event: Event) => void;
29
+ onClose?: (info: WebSocketCloseInfo) => void;
30
+ onOpen?: () => void;
31
+ };
32
+ export type WebSocketConnectOptions = {
33
+ url: string;
34
+ protocols?: string | string[];
35
+ callbacks?: WebSocketSessionCallbacks;
36
+ /** Injectable WebSocket constructor for testing or Electron override */
37
+ customWebSocket?: typeof WebSocket;
38
+ };
39
+ export type WebSocketSession = {
40
+ readonly state: WebSocketSessionState;
41
+ readonly frames: WebSocketFrame[];
42
+ readonly closeInfo: WebSocketCloseInfo | null;
43
+ readonly url: string | null;
44
+ connect: (options: WebSocketConnectOptions) => void;
45
+ send: (data: string) => void;
46
+ close: (code?: number, reason?: string) => void;
47
+ clearFrames: () => void;
48
+ destroy: () => void;
49
+ };
50
+ /**
51
+ * Creates a new WebSocket session with lifecycle management.
52
+ *
53
+ * The session starts in `idle` state and transitions through `connecting` -> `open`
54
+ * on success, or `connecting` -> `error` on failure. Calling `close()` transitions
55
+ * through `closing` -> `closed`. Frames are accumulated in the session for the UI
56
+ * message log.
57
+ */
58
+ export declare const createWebSocketSession: () => WebSocketSession;
59
+ //# sourceMappingURL=websocket-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-session.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/channel-operation-block/helpers/websocket-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEnG,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE9D,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,UAAU,GAAG,UAAU,CAAA;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAC1B,MAAM,EAAE,oBAAoB,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;IACzC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACvF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC5C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC7B,SAAS,CAAC,EAAE,yBAAyB,CAAA;IACrC,wEAAwE;IACxE,eAAe,CAAC,EAAE,OAAO,SAAS,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAA;IACrC,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,CAAA;IACjC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI,CAAA;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,OAAO,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAA;IACnD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/C,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,QAAO,gBA0KzC,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { type ConnectWebSocketData, type ConnectWebSocketFailureCode, type ConnectWebSocketOptions, type ConnectWebSocketResult, WEBSOCKET_CONNECTION_FAILED, WEBSOCKET_CONNECTION_FAILED_MESSAGE, connectWebSocket, } from './helpers/connect-websocket';
2
+ export { type WebSocketCloseInfo, type WebSocketConnectOptions, type WebSocketFrame, type WebSocketFrameOpcode, type WebSocketSession, type WebSocketSessionCallbacks, type WebSocketSessionState, createWebSocketSession, } from './helpers/websocket-session';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/channel-operation-block/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,2BAA2B,EAC3B,mCAAmC,EACnC,gBAAgB,GACjB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,sBAAsB,GACvB,MAAM,6BAA6B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"OperationBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"OperationBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"OperationBlock.vue.js","names":[],"sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * OperationBlock\n *\n * Orchestrates the operation view by wiring together the Header, OperationBlock,\n * and ResponseBlock. Forwards user interactions to the workspace event bus and\n * passes through configuration such as auth, servers, plugins, and environment.\n * This component keeps the Operation page lean by centralizing event emission\n * and prop wiring between the blocks.\n *\n * Notable behavior:\n * - Uses operation['x-scalar-method'] and operation['x-scalar-path'] to provide\n * draft overrides for the UI when present.\n */\nexport default {\n name: 'OperationBlock',\n}\n\nexport type OperationBlockProps = {\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Application version */\n appVersion: string\n /** Openapi document */\n document: OpenApiDocument\n /** Openapi document slug */\n documentSlug: string\n /** Workspace cookies */\n workspaceCookies: XScalarCookie[]\n /** Document cookies */\n documentCookies: XScalarCookie[]\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** HTTP clients */\n httpClients: AvailableClients\n /** The history for the operation */\n history?: HistoryEntry[]\n /** Client layout */\n layout: ClientLayout\n /** Currently selected server */\n server: ServerObject | null\n /** Currently selected client */\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** Meta information for the server */\n serverMeta: ServerMeta\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Operation object */\n operation: OperationObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Meta information for the auth update */\n authMeta: AuthMeta\n /** Document defined security schemes */\n securitySchemes: MergedSecuritySchemes\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** For environment variables in the inputs */\n environment: XScalarEnvironment\n /** The proxy URL for sending requests */\n proxyUrl: string\n /** Currently selected security */\n selectedSecurity: SelectedSecurity\n /** Currently selected security schemes */\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n /** Security requirements */\n securityRequirements: OpenApiDocument['security']\n /** Default headers */\n defaultHeaders: Record<string, string>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n /** Subset of config options for the modal */\n options?: ModalProps['options']\n}\n</script>\n<script setup lang=\"ts\">\nimport { ERRORS } 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 as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { executeHook, type ClientPlugin } from '@scalar/oas-utils/helpers'\nimport {\n AVAILABLE_CLIENTS,\n type AvailableClients,\n} from '@scalar/types/snippetz'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type { HistoryEntry } from '@scalar/workspace-store/entities/history/schema'\nimport type {\n AuthMeta,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n requestFactory,\n resolveExecutableRequestUrl,\n type MergedSecuritySchemes,\n type RequestPayload,\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 ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/operation'\nimport { computed, onBeforeUnmount, onMounted, ref, toValue, watch } from 'vue'\n\nimport ViewLayout from '@/components/ViewLayout/ViewLayout.vue'\nimport ViewLayoutContent from '@/components/ViewLayout/ViewLayoutContent.vue'\nimport { harToFetchRequest } from '@/v2/blocks/operation-block/helpers/har-to-fetch-request'\nimport { harToFetchResponse } from '@/v2/blocks/operation-block/helpers/har-to-fetch-response'\nimport {\n getOperationExampleKey,\n isStreamingResponse,\n responseCache,\n} from '@/v2/blocks/operation-block/helpers/response-cache'\nimport {\n sendRequest,\n type ResponseInstance,\n} from '@/v2/blocks/operation-block/helpers/send-request'\nimport { validatePathParameters } from '@/v2/blocks/operation-block/helpers/validate-path-parameters'\nimport { generateClientOptions } from '@/v2/blocks/operation-code-sample'\nimport { RequestBlock } from '@/v2/blocks/request-block'\nimport { ResponseBlock } from '@/v2/blocks/response-block'\nimport { type History } from '@/v2/blocks/scalar-address-bar-block'\nimport type { ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport Header from './components/Header.vue'\n\nconst {\n authMeta,\n environment,\n eventBus,\n exampleKey,\n document,\n documentSlug,\n workspaceCookies = [],\n documentCookies = [],\n hideClientButton,\n httpClients = AVAILABLE_CLIENTS,\n history = [],\n layout,\n method,\n operation,\n path,\n plugins = [],\n proxyUrl,\n requestBodyCompositionSelection,\n securitySchemes,\n selectedClient,\n server,\n environments,\n options,\n activeEnvironment,\n serverMeta,\n selectedSecurity,\n selectedSecuritySchemes,\n securityRequirements,\n defaultHeaders,\n} = defineProps<OperationBlockProps>()\n\n/** Hoist up client generation so it doesn't get re-generated on every operation */\nconst clientOptions = computed(() => generateClientOptions(httpClients))\n\nconst { toast } = useToasts()\nconst { copyToClipboard } = useClipboard()\n\n// Refs\nconst abortController = ref<AbortController | null>(null)\nconst response = ref<ResponseInstance | null>(null)\nconst requestPayload = ref<RequestPayload | null>(null)\n\n/** Cancel the request */\nconst cancelRequest = () => abortController.value?.abort(ERRORS.REQUEST_ABORTED)\n\n/**\n * Copy the executable URL — same pipeline as Send (`requestFactory` +\n * `resolveExecutableRequestUrl`), including security query params.\n */\nconst copyAddressBarUrl = async (): Promise<void> => {\n const { request } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies: [...workspaceCookies, ...documentCookies],\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n await copyToClipboard(\n resolveExecutableRequestUrl(request, getEnvironmentVariables(environment)),\n )\n}\n\n/** Execute the current operation example */\nconst handleExecute = async () => {\n eventBus.flushDebouncedEmits?.()\n\n const pathValidation = validatePathParameters(\n operation.parameters ?? [],\n exampleKey,\n )\n if (pathValidation.ok === false) {\n toast('Path parameters must have values.', 'error')\n return\n }\n\n const globalCookies = [...workspaceCookies, ...documentCookies]\n\n const { request: requestBuilder } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies,\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n // Stop any previous streaming response\n if (response.value && 'reader' in response.value) {\n response.value.reader.cancel()\n }\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Execute the beforeRequest hook (plugins receive RequestFactory, not fetch Request)\n await executeHook(\n {\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'beforeRequest',\n plugins,\n )\n\n const envVariables = {\n ...getEnvironmentVariables(environment),\n ...variablesStore.getVariables(),\n }\n\n // Build the fetch Request after hooks may have mutated the factory\n const built = buildRequest(requestBuilder, {\n envVariables,\n allowMissingRequestServerBase: layout === 'modal',\n })\n if (!built.ok) {\n toast(built.message ?? built.error, 'error')\n return\n }\n\n // Store the abort controller for cancellation\n abortController.value = built.data.controller\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:sent', {\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n /** Execute the request */\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: built.data.isUsingProxy,\n requestPayload: built.data.requestPayload,\n plugins,\n customFetch: toValue(options)?.customFetch,\n })\n\n if (sendResult) {\n // Execute the responseReceived hook\n await executeHook(\n {\n response: sendResult.originalResponse.clone(),\n requestBuilder,\n request: buildSafeBodyRequest(...sendResult.requestPayload),\n document,\n operation,\n variablesStore,\n },\n 'responseReceived',\n plugins,\n )\n }\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:complete', {\n payload: sendResult\n ? {\n response: sendResult.originalResponse.clone(),\n requestPayload: sendResult.requestPayload,\n duration: sendResult.response.duration,\n timestamp: sendResult.timestamp,\n }\n : undefined,\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n if (sendError) {\n // clean up the response and request\n response.value = null\n requestPayload.value = null\n abortController.value = null\n\n toast(sendError.message, 'error')\n return\n }\n\n // Store the response\n response.value = sendResult.response\n requestPayload.value = sendResult.requestPayload\n\n // Cache non-streaming responses so they can be restored when navigating back\n if (!isStreamingResponse(sendResult.response)) {\n responseCache.set(getOperationExampleKey(method, path, exampleKey), {\n response: sendResult.response,\n requestPayload: sendResult.requestPayload,\n })\n }\n}\n\nonMounted(() => {\n eventBus.on('operation:send:request:hotkey', handleExecute)\n eventBus.on('operation:cancel:request', cancelRequest)\n eventBus.on('copy-url:address-bar', copyAddressBarUrl)\n})\nonBeforeUnmount(() => {\n eventBus.off('operation:send:request:hotkey', handleExecute)\n eventBus.off('operation:cancel:request', cancelRequest)\n eventBus.off('copy-url:address-bar', copyAddressBarUrl)\n})\n\nconst operationHistory = computed<History[]>(() =>\n history\n .map((entry) => ({\n method: entry.request.method as HttpMethodType,\n path: entry.request.url,\n duration: entry.time,\n status: entry.response.status,\n }))\n .reverse(),\n)\n\nconst handleSelectHistoryItem = ({ index }: { index: number }) => {\n const transformedIndex = (history.length ?? 0) - index - 1\n const historyItem = history[transformedIndex]\n if (!historyItem) {\n return\n }\n\n const navigate = () =>\n eventBus.emit('ui:navigate', {\n page: 'example',\n method,\n path,\n exampleName: 'draft',\n callback: (status) => {\n // Do not replace the response if the navigation was not successful\n if (status !== 'success') {\n return\n }\n // Reconstruct the response\n const fetchResponse = harToFetchResponse({\n harResponse: historyItem.response,\n url: historyItem.request.url,\n method,\n path,\n duration: historyItem.time,\n })\n\n // Reconstruct the request\n const fetchRequest = harToFetchRequest({\n harRequest: historyItem.request,\n })\n\n // Update the response and request\n response.value = fetchResponse\n requestPayload.value = fetchRequest\n },\n })\n\n eventBus.emit('operation:reload:history', {\n meta: {\n path,\n method,\n },\n index: transformedIndex,\n callback: navigate,\n })\n}\n\nconst handleNavigateSettings = () => {\n eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'overview',\n operationPath: path,\n method,\n })\n}\n\n/**\n * When the path, method, or example key changes, restore the response panel\n * for the new operation from the best available source:\n *\n * 1. `responseCache` — in-memory, populated on every successful send.\n * Has the live response object (including streams) so it wins.\n * 2. `history` — persisted in the workspace store. Used as a fallback when\n * the in-memory cache is empty (page reload, fresh app session, etc.)\n * so navigating to an operation that has been called before shows the\n * last response instead of an empty panel.\n * 3. Otherwise clear.\n *\n * Only the response is restored from history — the user's request inputs are\n * left alone, so we never silently overwrite an in-progress draft.\n */\nwatch(\n [() => path, () => method, () => exampleKey],\n ([newPath, newMethod, newExampleKey]) => {\n const cached = responseCache.get(\n getOperationExampleKey(newMethod, newPath, newExampleKey),\n )\n\n if (cached) {\n response.value = cached.response\n requestPayload.value = cached.requestPayload\n } else {\n // History is keyed only by document/path/method but each entry carries\n // the example it came from, so we walk from the end and pick the most\n // recent entry that matches the active example. Otherwise a cache miss\n // on example B would restore example A's response. Only runs on a\n // cache miss — the common case (in-session navigation) skips it.\n const latest = (() => {\n for (let i = history.length - 1; i >= 0; i--) {\n const entry = history[i]\n if (entry?.meta.example === newExampleKey) {\n return entry\n }\n }\n return undefined\n })()\n\n if (latest) {\n response.value = harToFetchResponse({\n harResponse: latest.response,\n url: latest.request.url,\n method: newMethod,\n path: newPath,\n duration: latest.time,\n })\n requestPayload.value = null\n } else {\n response.value = null\n requestPayload.value = null\n }\n }\n\n // Cancel any in-flight request\n cancelRequest()\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n // We cancel the request if the component is unmounted\n cancelRequest()\n})\n</script>\n<template>\n <div class=\"bg-b-1 flex h-full flex-col\">\n <div\n class=\"lg:min-h-header flex w-full flex-wrap items-center justify-center p-2 lg:p-0\">\n <!-- Address Bar -->\n <Header\n :activeEnvironment\n :documentSlug\n :documentUrl\n :environment\n :environments\n :eventBus\n :exampleKey\n :hideClientButton\n :history=\"operationHistory\"\n :integration\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n :source\n @execute=\"handleExecute\"\n @navigate:settings=\"handleNavigateSettings\"\n @select:history:item=\"handleSelectHistoryItem\" />\n </div>\n\n <ViewLayout class=\"border-t\">\n <ViewLayoutContent class=\"flex-1\">\n <!-- Request Section -->\n <RequestBlock\n :authMeta\n :clientOptions\n :defaultHeaders\n :documentCookies\n :environment\n :eventBus\n :exampleKey\n :layout\n :method\n :operation\n :options=\"toValue(options)\"\n :path\n :plugins\n :proxyUrl\n :requestBodyCompositionSelection\n :securityRequirements\n :securitySchemes\n :selectedClient\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :workspaceCookies />\n\n <!-- Response Section -->\n <ResponseBlock\n :appVersion\n :eventBus\n :layout\n :plugins\n :requestPayload\n :response\n :totalPerformedRequests=\"operationHistory.length\" />\n </ViewLayoutContent>\n </ViewLayout>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"OperationBlock.vue.js","names":[],"sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * OperationBlock\n *\n * Orchestrates the operation view by wiring together the Header, OperationBlock,\n * and ResponseBlock. Forwards user interactions to the workspace event bus and\n * passes through configuration such as auth, servers, plugins, and environment.\n * This component keeps the Operation page lean by centralizing event emission\n * and prop wiring between the blocks.\n *\n * Notable behavior:\n * - Uses operation['x-scalar-method'] and operation['x-scalar-path'] to provide\n * draft overrides for the UI when present.\n */\nexport default {\n name: 'OperationBlock',\n}\n\nexport type OperationBlockProps = {\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Application version */\n appVersion: string\n /** Openapi document */\n document: OpenApiDocument\n /** Openapi document slug */\n documentSlug: string\n /** Workspace cookies */\n workspaceCookies: XScalarCookie[]\n /** Document cookies */\n documentCookies: XScalarCookie[]\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** HTTP clients */\n httpClients: AvailableClients\n /** The history for the operation */\n history?: HistoryEntry[]\n /** Client layout */\n layout: ClientLayout\n /** Currently selected server */\n server: ServerObject | null\n /** Currently selected client */\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** Meta information for the server */\n serverMeta: ServerMeta\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Operation object */\n operation: OperationObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Meta information for the auth update */\n authMeta: AuthMeta\n /** Document defined security schemes */\n securitySchemes: MergedSecuritySchemes\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** For environment variables in the inputs */\n environment: XScalarEnvironment\n /** The proxy URL for sending requests */\n proxyUrl: string\n /** Currently selected security */\n selectedSecurity: SelectedSecurity\n /** Currently selected security schemes */\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n /** Security requirements */\n securityRequirements: OpenApiDocument['security']\n /** Default headers */\n defaultHeaders: Record<string, string>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n /** Subset of config options for the modal */\n options?: ModalProps['options']\n}\n</script>\n<script setup lang=\"ts\">\nimport { ERRORS } 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 as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { executeHook, type ClientPlugin } from '@scalar/oas-utils/helpers'\nimport {\n AVAILABLE_CLIENTS,\n type AvailableClients,\n} from '@scalar/types/snippetz'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type { HistoryEntry } from '@scalar/workspace-store/entities/history/schema'\nimport type {\n AuthMeta,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n requestFactory,\n resolveExecutableRequestUrl,\n type MergedSecuritySchemes,\n type RequestPayload,\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 ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/operation'\nimport { computed, onBeforeUnmount, onMounted, ref, toValue, watch } from 'vue'\n\nimport ViewLayout from '@/components/ViewLayout/ViewLayout.vue'\nimport ViewLayoutContent from '@/components/ViewLayout/ViewLayoutContent.vue'\nimport { harToFetchRequest } from '@/v2/blocks/operation-block/helpers/har-to-fetch-request'\nimport { harToFetchResponse } from '@/v2/blocks/operation-block/helpers/har-to-fetch-response'\nimport {\n getOperationExampleKey,\n isStreamingResponse,\n responseCache,\n} from '@/v2/blocks/operation-block/helpers/response-cache'\nimport {\n sendRequest,\n type ResponseInstance,\n} from '@/v2/blocks/operation-block/helpers/send-request'\nimport { validatePathParameters } from '@/v2/blocks/operation-block/helpers/validate-path-parameters'\nimport { generateClientOptions } from '@/v2/blocks/operation-code-sample'\nimport { RequestBlock } from '@/v2/blocks/request-block'\nimport { ResponseBlock } from '@/v2/blocks/response-block'\nimport { type History } from '@/v2/blocks/scalar-address-bar-block'\nimport type { ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport Header from './components/Header.vue'\n\nconst {\n authMeta,\n environment,\n eventBus,\n exampleKey,\n document,\n documentSlug,\n workspaceCookies = [],\n documentCookies = [],\n hideClientButton,\n httpClients = AVAILABLE_CLIENTS,\n history = [],\n layout,\n method,\n operation,\n path,\n plugins = [],\n proxyUrl,\n requestBodyCompositionSelection,\n securitySchemes,\n selectedClient,\n server,\n environments,\n options,\n activeEnvironment,\n serverMeta,\n selectedSecurity,\n selectedSecuritySchemes,\n securityRequirements,\n defaultHeaders,\n} = defineProps<OperationBlockProps>()\n\n/** Hoist up client generation so it doesn't get re-generated on every operation */\nconst clientOptions = computed(() => generateClientOptions(httpClients))\n\nconst { toast } = useToasts()\nconst { copyToClipboard } = useClipboard()\n\n// Refs\nconst abortController = ref<AbortController | null>(null)\nconst response = ref<ResponseInstance | null>(null)\nconst requestPayload = ref<RequestPayload | null>(null)\n\n/** Cancel the request */\nconst cancelRequest = () => abortController.value?.abort(ERRORS.REQUEST_ABORTED)\n\n/**\n * Copy the executable URL — same pipeline as Send (`requestFactory` +\n * `resolveExecutableRequestUrl`), including security query params.\n */\nconst copyAddressBarUrl = async (): Promise<void> => {\n const { request } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies: [...workspaceCookies, ...documentCookies],\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n await copyToClipboard(\n resolveExecutableRequestUrl(request, getEnvironmentVariables(environment)),\n )\n}\n\n/** Execute the current operation example */\nconst handleExecute = async () => {\n eventBus.flushDebouncedEmits?.()\n\n const pathValidation = validatePathParameters(\n operation.parameters ?? [],\n exampleKey,\n )\n if (pathValidation.ok === false) {\n toast('Path parameters must have values.', 'error')\n return\n }\n\n const globalCookies = [...workspaceCookies, ...documentCookies]\n\n const { request: requestBuilder } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies,\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n // Stop any previous streaming response\n if (response.value && 'reader' in response.value) {\n response.value.reader.cancel()\n }\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Execute the beforeRequest hook (plugins receive RequestFactory, not fetch Request)\n await executeHook(\n {\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'beforeRequest',\n plugins,\n )\n\n const envVariables = {\n ...getEnvironmentVariables(environment),\n ...variablesStore.getVariables(),\n }\n\n // Build the fetch Request after hooks may have mutated the factory\n const built = buildRequest(requestBuilder, {\n envVariables,\n allowMissingRequestServerBase: layout === 'modal',\n })\n if (!built.ok) {\n toast(built.message ?? built.error, 'error')\n return\n }\n\n // Store the abort controller for cancellation\n abortController.value = built.data.controller\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:sent', {\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n /** Execute the request */\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: built.data.isUsingProxy,\n requestPayload: built.data.requestPayload,\n plugins,\n customFetch: toValue(options)?.customFetch,\n })\n\n if (sendResult) {\n // Execute the responseReceived hook\n await executeHook(\n {\n response: sendResult.originalResponse.clone(),\n requestBuilder,\n request: buildSafeBodyRequest(...sendResult.requestPayload),\n document,\n operation,\n variablesStore,\n },\n 'responseReceived',\n plugins,\n )\n }\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:complete', {\n payload: sendResult\n ? {\n response: sendResult.originalResponse.clone(),\n requestPayload: sendResult.requestPayload,\n duration: sendResult.response.duration,\n timestamp: sendResult.timestamp,\n }\n : undefined,\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n if (sendError) {\n // clean up the response and request\n response.value = null\n requestPayload.value = null\n abortController.value = null\n\n toast(sendError.message, 'error')\n return\n }\n\n // Store the response\n response.value = sendResult.response\n requestPayload.value = sendResult.requestPayload\n\n // Cache non-streaming responses so they can be restored when navigating back\n if (!isStreamingResponse(sendResult.response)) {\n responseCache.set(getOperationExampleKey(method, path, exampleKey), {\n response: sendResult.response,\n requestPayload: sendResult.requestPayload,\n })\n }\n}\n\nonMounted(() => {\n eventBus.on('operation:send:request:hotkey', handleExecute)\n eventBus.on('operation:cancel:request', cancelRequest)\n eventBus.on('copy-url:address-bar', copyAddressBarUrl)\n\n // Let plugins warm up per-operation resources (e.g. the scripts sandbox) so the first request\n // does not pay their cold-start cost.\n void executeHook({ document, operation }, 'onRequestMount', plugins)\n})\nonBeforeUnmount(() => {\n eventBus.off('operation:send:request:hotkey', handleExecute)\n eventBus.off('operation:cancel:request', cancelRequest)\n eventBus.off('copy-url:address-bar', copyAddressBarUrl)\n})\n\nconst operationHistory = computed<History[]>(() =>\n history\n .map((entry) => ({\n method: entry.request.method as HttpMethodType,\n path: entry.request.url,\n duration: entry.time,\n status: entry.response.status,\n }))\n .reverse(),\n)\n\nconst handleSelectHistoryItem = ({ index }: { index: number }) => {\n const transformedIndex = (history.length ?? 0) - index - 1\n const historyItem = history[transformedIndex]\n if (!historyItem) {\n return\n }\n\n const navigate = () =>\n eventBus.emit('ui:navigate', {\n page: 'example',\n method,\n path,\n exampleName: 'draft',\n callback: (status) => {\n // Do not replace the response if the navigation was not successful\n if (status !== 'success') {\n return\n }\n // Reconstruct the response\n const fetchResponse = harToFetchResponse({\n harResponse: historyItem.response,\n url: historyItem.request.url,\n method,\n path,\n duration: historyItem.time,\n })\n\n // Reconstruct the request\n const fetchRequest = harToFetchRequest({\n harRequest: historyItem.request,\n })\n\n // Update the response and request\n response.value = fetchResponse\n requestPayload.value = fetchRequest\n },\n })\n\n eventBus.emit('operation:reload:history', {\n meta: {\n path,\n method,\n },\n index: transformedIndex,\n callback: navigate,\n })\n}\n\nconst handleNavigateSettings = () => {\n eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'overview',\n operationPath: path,\n method,\n })\n}\n\n/**\n * When the path, method, or example key changes, restore the response panel\n * for the new operation from the best available source:\n *\n * 1. `responseCache` — in-memory, populated on every successful send.\n * Has the live response object (including streams) so it wins.\n * 2. `history` — persisted in the workspace store. Used as a fallback when\n * the in-memory cache is empty (page reload, fresh app session, etc.)\n * so navigating to an operation that has been called before shows the\n * last response instead of an empty panel.\n * 3. Otherwise clear.\n *\n * Only the response is restored from history — the user's request inputs are\n * left alone, so we never silently overwrite an in-progress draft.\n */\nwatch(\n [() => path, () => method, () => exampleKey],\n ([newPath, newMethod, newExampleKey]) => {\n const cached = responseCache.get(\n getOperationExampleKey(newMethod, newPath, newExampleKey),\n )\n\n if (cached) {\n response.value = cached.response\n requestPayload.value = cached.requestPayload\n } else {\n // History is keyed only by document/path/method but each entry carries\n // the example it came from, so we walk from the end and pick the most\n // recent entry that matches the active example. Otherwise a cache miss\n // on example B would restore example A's response. Only runs on a\n // cache miss — the common case (in-session navigation) skips it.\n const latest = (() => {\n for (let i = history.length - 1; i >= 0; i--) {\n const entry = history[i]\n if (entry?.meta.example === newExampleKey) {\n return entry\n }\n }\n return undefined\n })()\n\n if (latest) {\n response.value = harToFetchResponse({\n harResponse: latest.response,\n url: latest.request.url,\n method: newMethod,\n path: newPath,\n duration: latest.time,\n })\n requestPayload.value = null\n } else {\n response.value = null\n requestPayload.value = null\n }\n }\n\n // Cancel any in-flight request\n cancelRequest()\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n // We cancel the request if the component is unmounted\n cancelRequest()\n})\n</script>\n<template>\n <div class=\"bg-b-1 flex h-full flex-col\">\n <div\n class=\"lg:min-h-header flex w-full flex-wrap items-center justify-center p-2 lg:p-0\">\n <!-- Address Bar -->\n <Header\n :activeEnvironment\n :documentSlug\n :documentUrl\n :environment\n :environments\n :eventBus\n :exampleKey\n :hideClientButton\n :history=\"operationHistory\"\n :integration\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n :source\n @execute=\"handleExecute\"\n @navigate:settings=\"handleNavigateSettings\"\n @select:history:item=\"handleSelectHistoryItem\" />\n </div>\n\n <ViewLayout class=\"border-t\">\n <ViewLayoutContent class=\"flex-1\">\n <!-- Request Section -->\n <RequestBlock\n :authMeta\n :clientOptions\n :defaultHeaders\n :documentCookies\n :environment\n :eventBus\n :exampleKey\n :layout\n :method\n :operation\n :options=\"toValue(options)\"\n :path\n :plugins\n :proxyUrl\n :requestBodyCompositionSelection\n :securityRequirements\n :securitySchemes\n :selectedClient\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :workspaceCookies />\n\n <!-- Response Section -->\n <ResponseBlock\n :appVersion\n :eventBus\n :layout\n :plugins\n :requestPayload\n :response\n :totalPerformedRequests=\"operationHistory.length\" />\n </ViewLayoutContent>\n </ViewLayout>\n </div>\n</template>\n"],"mappings":""}
@@ -183,6 +183,10 @@ var OperationBlock_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
183
183
  __props.eventBus.on("operation:send:request:hotkey", handleExecute);
184
184
  __props.eventBus.on("operation:cancel:request", cancelRequest);
185
185
  __props.eventBus.on("copy-url:address-bar", copyAddressBarUrl);
186
+ executeHook({
187
+ document: __props.document,
188
+ operation: __props.operation
189
+ }, "onRequestMount", __props.plugins);
186
190
  });
187
191
  onBeforeUnmount(() => {
188
192
  __props.eventBus.off("operation:send:request:hotkey", handleExecute);
@@ -1 +1 @@
1
- {"version":3,"file":"OperationBlock.vue.script.js","names":[],"sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * OperationBlock\n *\n * Orchestrates the operation view by wiring together the Header, OperationBlock,\n * and ResponseBlock. Forwards user interactions to the workspace event bus and\n * passes through configuration such as auth, servers, plugins, and environment.\n * This component keeps the Operation page lean by centralizing event emission\n * and prop wiring between the blocks.\n *\n * Notable behavior:\n * - Uses operation['x-scalar-method'] and operation['x-scalar-path'] to provide\n * draft overrides for the UI when present.\n */\nexport default {\n name: 'OperationBlock',\n}\n\nexport type OperationBlockProps = {\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Application version */\n appVersion: string\n /** Openapi document */\n document: OpenApiDocument\n /** Openapi document slug */\n documentSlug: string\n /** Workspace cookies */\n workspaceCookies: XScalarCookie[]\n /** Document cookies */\n documentCookies: XScalarCookie[]\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** HTTP clients */\n httpClients: AvailableClients\n /** The history for the operation */\n history?: HistoryEntry[]\n /** Client layout */\n layout: ClientLayout\n /** Currently selected server */\n server: ServerObject | null\n /** Currently selected client */\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** Meta information for the server */\n serverMeta: ServerMeta\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Operation object */\n operation: OperationObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Meta information for the auth update */\n authMeta: AuthMeta\n /** Document defined security schemes */\n securitySchemes: MergedSecuritySchemes\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** For environment variables in the inputs */\n environment: XScalarEnvironment\n /** The proxy URL for sending requests */\n proxyUrl: string\n /** Currently selected security */\n selectedSecurity: SelectedSecurity\n /** Currently selected security schemes */\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n /** Security requirements */\n securityRequirements: OpenApiDocument['security']\n /** Default headers */\n defaultHeaders: Record<string, string>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n /** Subset of config options for the modal */\n options?: ModalProps['options']\n}\n</script>\n<script setup lang=\"ts\">\nimport { ERRORS } 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 as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { executeHook, type ClientPlugin } from '@scalar/oas-utils/helpers'\nimport {\n AVAILABLE_CLIENTS,\n type AvailableClients,\n} from '@scalar/types/snippetz'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type { HistoryEntry } from '@scalar/workspace-store/entities/history/schema'\nimport type {\n AuthMeta,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n requestFactory,\n resolveExecutableRequestUrl,\n type MergedSecuritySchemes,\n type RequestPayload,\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 ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/operation'\nimport { computed, onBeforeUnmount, onMounted, ref, toValue, watch } from 'vue'\n\nimport ViewLayout from '@/components/ViewLayout/ViewLayout.vue'\nimport ViewLayoutContent from '@/components/ViewLayout/ViewLayoutContent.vue'\nimport { harToFetchRequest } from '@/v2/blocks/operation-block/helpers/har-to-fetch-request'\nimport { harToFetchResponse } from '@/v2/blocks/operation-block/helpers/har-to-fetch-response'\nimport {\n getOperationExampleKey,\n isStreamingResponse,\n responseCache,\n} from '@/v2/blocks/operation-block/helpers/response-cache'\nimport {\n sendRequest,\n type ResponseInstance,\n} from '@/v2/blocks/operation-block/helpers/send-request'\nimport { validatePathParameters } from '@/v2/blocks/operation-block/helpers/validate-path-parameters'\nimport { generateClientOptions } from '@/v2/blocks/operation-code-sample'\nimport { RequestBlock } from '@/v2/blocks/request-block'\nimport { ResponseBlock } from '@/v2/blocks/response-block'\nimport { type History } from '@/v2/blocks/scalar-address-bar-block'\nimport type { ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport Header from './components/Header.vue'\n\nconst {\n authMeta,\n environment,\n eventBus,\n exampleKey,\n document,\n documentSlug,\n workspaceCookies = [],\n documentCookies = [],\n hideClientButton,\n httpClients = AVAILABLE_CLIENTS,\n history = [],\n layout,\n method,\n operation,\n path,\n plugins = [],\n proxyUrl,\n requestBodyCompositionSelection,\n securitySchemes,\n selectedClient,\n server,\n environments,\n options,\n activeEnvironment,\n serverMeta,\n selectedSecurity,\n selectedSecuritySchemes,\n securityRequirements,\n defaultHeaders,\n} = defineProps<OperationBlockProps>()\n\n/** Hoist up client generation so it doesn't get re-generated on every operation */\nconst clientOptions = computed(() => generateClientOptions(httpClients))\n\nconst { toast } = useToasts()\nconst { copyToClipboard } = useClipboard()\n\n// Refs\nconst abortController = ref<AbortController | null>(null)\nconst response = ref<ResponseInstance | null>(null)\nconst requestPayload = ref<RequestPayload | null>(null)\n\n/** Cancel the request */\nconst cancelRequest = () => abortController.value?.abort(ERRORS.REQUEST_ABORTED)\n\n/**\n * Copy the executable URL — same pipeline as Send (`requestFactory` +\n * `resolveExecutableRequestUrl`), including security query params.\n */\nconst copyAddressBarUrl = async (): Promise<void> => {\n const { request } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies: [...workspaceCookies, ...documentCookies],\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n await copyToClipboard(\n resolveExecutableRequestUrl(request, getEnvironmentVariables(environment)),\n )\n}\n\n/** Execute the current operation example */\nconst handleExecute = async () => {\n eventBus.flushDebouncedEmits?.()\n\n const pathValidation = validatePathParameters(\n operation.parameters ?? [],\n exampleKey,\n )\n if (pathValidation.ok === false) {\n toast('Path parameters must have values.', 'error')\n return\n }\n\n const globalCookies = [...workspaceCookies, ...documentCookies]\n\n const { request: requestBuilder } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies,\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n // Stop any previous streaming response\n if (response.value && 'reader' in response.value) {\n response.value.reader.cancel()\n }\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Execute the beforeRequest hook (plugins receive RequestFactory, not fetch Request)\n await executeHook(\n {\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'beforeRequest',\n plugins,\n )\n\n const envVariables = {\n ...getEnvironmentVariables(environment),\n ...variablesStore.getVariables(),\n }\n\n // Build the fetch Request after hooks may have mutated the factory\n const built = buildRequest(requestBuilder, {\n envVariables,\n allowMissingRequestServerBase: layout === 'modal',\n })\n if (!built.ok) {\n toast(built.message ?? built.error, 'error')\n return\n }\n\n // Store the abort controller for cancellation\n abortController.value = built.data.controller\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:sent', {\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n /** Execute the request */\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: built.data.isUsingProxy,\n requestPayload: built.data.requestPayload,\n plugins,\n customFetch: toValue(options)?.customFetch,\n })\n\n if (sendResult) {\n // Execute the responseReceived hook\n await executeHook(\n {\n response: sendResult.originalResponse.clone(),\n requestBuilder,\n request: buildSafeBodyRequest(...sendResult.requestPayload),\n document,\n operation,\n variablesStore,\n },\n 'responseReceived',\n plugins,\n )\n }\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:complete', {\n payload: sendResult\n ? {\n response: sendResult.originalResponse.clone(),\n requestPayload: sendResult.requestPayload,\n duration: sendResult.response.duration,\n timestamp: sendResult.timestamp,\n }\n : undefined,\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n if (sendError) {\n // clean up the response and request\n response.value = null\n requestPayload.value = null\n abortController.value = null\n\n toast(sendError.message, 'error')\n return\n }\n\n // Store the response\n response.value = sendResult.response\n requestPayload.value = sendResult.requestPayload\n\n // Cache non-streaming responses so they can be restored when navigating back\n if (!isStreamingResponse(sendResult.response)) {\n responseCache.set(getOperationExampleKey(method, path, exampleKey), {\n response: sendResult.response,\n requestPayload: sendResult.requestPayload,\n })\n }\n}\n\nonMounted(() => {\n eventBus.on('operation:send:request:hotkey', handleExecute)\n eventBus.on('operation:cancel:request', cancelRequest)\n eventBus.on('copy-url:address-bar', copyAddressBarUrl)\n})\nonBeforeUnmount(() => {\n eventBus.off('operation:send:request:hotkey', handleExecute)\n eventBus.off('operation:cancel:request', cancelRequest)\n eventBus.off('copy-url:address-bar', copyAddressBarUrl)\n})\n\nconst operationHistory = computed<History[]>(() =>\n history\n .map((entry) => ({\n method: entry.request.method as HttpMethodType,\n path: entry.request.url,\n duration: entry.time,\n status: entry.response.status,\n }))\n .reverse(),\n)\n\nconst handleSelectHistoryItem = ({ index }: { index: number }) => {\n const transformedIndex = (history.length ?? 0) - index - 1\n const historyItem = history[transformedIndex]\n if (!historyItem) {\n return\n }\n\n const navigate = () =>\n eventBus.emit('ui:navigate', {\n page: 'example',\n method,\n path,\n exampleName: 'draft',\n callback: (status) => {\n // Do not replace the response if the navigation was not successful\n if (status !== 'success') {\n return\n }\n // Reconstruct the response\n const fetchResponse = harToFetchResponse({\n harResponse: historyItem.response,\n url: historyItem.request.url,\n method,\n path,\n duration: historyItem.time,\n })\n\n // Reconstruct the request\n const fetchRequest = harToFetchRequest({\n harRequest: historyItem.request,\n })\n\n // Update the response and request\n response.value = fetchResponse\n requestPayload.value = fetchRequest\n },\n })\n\n eventBus.emit('operation:reload:history', {\n meta: {\n path,\n method,\n },\n index: transformedIndex,\n callback: navigate,\n })\n}\n\nconst handleNavigateSettings = () => {\n eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'overview',\n operationPath: path,\n method,\n })\n}\n\n/**\n * When the path, method, or example key changes, restore the response panel\n * for the new operation from the best available source:\n *\n * 1. `responseCache` — in-memory, populated on every successful send.\n * Has the live response object (including streams) so it wins.\n * 2. `history` — persisted in the workspace store. Used as a fallback when\n * the in-memory cache is empty (page reload, fresh app session, etc.)\n * so navigating to an operation that has been called before shows the\n * last response instead of an empty panel.\n * 3. Otherwise clear.\n *\n * Only the response is restored from history — the user's request inputs are\n * left alone, so we never silently overwrite an in-progress draft.\n */\nwatch(\n [() => path, () => method, () => exampleKey],\n ([newPath, newMethod, newExampleKey]) => {\n const cached = responseCache.get(\n getOperationExampleKey(newMethod, newPath, newExampleKey),\n )\n\n if (cached) {\n response.value = cached.response\n requestPayload.value = cached.requestPayload\n } else {\n // History is keyed only by document/path/method but each entry carries\n // the example it came from, so we walk from the end and pick the most\n // recent entry that matches the active example. Otherwise a cache miss\n // on example B would restore example A's response. Only runs on a\n // cache miss — the common case (in-session navigation) skips it.\n const latest = (() => {\n for (let i = history.length - 1; i >= 0; i--) {\n const entry = history[i]\n if (entry?.meta.example === newExampleKey) {\n return entry\n }\n }\n return undefined\n })()\n\n if (latest) {\n response.value = harToFetchResponse({\n harResponse: latest.response,\n url: latest.request.url,\n method: newMethod,\n path: newPath,\n duration: latest.time,\n })\n requestPayload.value = null\n } else {\n response.value = null\n requestPayload.value = null\n }\n }\n\n // Cancel any in-flight request\n cancelRequest()\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n // We cancel the request if the component is unmounted\n cancelRequest()\n})\n</script>\n<template>\n <div class=\"bg-b-1 flex h-full flex-col\">\n <div\n class=\"lg:min-h-header flex w-full flex-wrap items-center justify-center p-2 lg:p-0\">\n <!-- Address Bar -->\n <Header\n :activeEnvironment\n :documentSlug\n :documentUrl\n :environment\n :environments\n :eventBus\n :exampleKey\n :hideClientButton\n :history=\"operationHistory\"\n :integration\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n :source\n @execute=\"handleExecute\"\n @navigate:settings=\"handleNavigateSettings\"\n @select:history:item=\"handleSelectHistoryItem\" />\n </div>\n\n <ViewLayout class=\"border-t\">\n <ViewLayoutContent class=\"flex-1\">\n <!-- Request Section -->\n <RequestBlock\n :authMeta\n :clientOptions\n :defaultHeaders\n :documentCookies\n :environment\n :eventBus\n :exampleKey\n :layout\n :method\n :operation\n :options=\"toValue(options)\"\n :path\n :plugins\n :proxyUrl\n :requestBodyCompositionSelection\n :securityRequirements\n :securitySchemes\n :selectedClient\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :workspaceCookies />\n\n <!-- Response Section -->\n <ResponseBlock\n :appVersion\n :eventBus\n :layout\n :plugins\n :requestPayload\n :response\n :totalPerformedRequests=\"operationHistory.length\" />\n </ViewLayoutContent>\n </ViewLayout>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"OperationBlock.vue.script.js","names":[],"sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * OperationBlock\n *\n * Orchestrates the operation view by wiring together the Header, OperationBlock,\n * and ResponseBlock. Forwards user interactions to the workspace event bus and\n * passes through configuration such as auth, servers, plugins, and environment.\n * This component keeps the Operation page lean by centralizing event emission\n * and prop wiring between the blocks.\n *\n * Notable behavior:\n * - Uses operation['x-scalar-method'] and operation['x-scalar-path'] to provide\n * draft overrides for the UI when present.\n */\nexport default {\n name: 'OperationBlock',\n}\n\nexport type OperationBlockProps = {\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Application version */\n appVersion: string\n /** Openapi document */\n document: OpenApiDocument\n /** Openapi document slug */\n documentSlug: string\n /** Workspace cookies */\n workspaceCookies: XScalarCookie[]\n /** Document cookies */\n documentCookies: XScalarCookie[]\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** HTTP clients */\n httpClients: AvailableClients\n /** The history for the operation */\n history?: HistoryEntry[]\n /** Client layout */\n layout: ClientLayout\n /** Currently selected server */\n server: ServerObject | null\n /** Currently selected client */\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** Meta information for the server */\n serverMeta: ServerMeta\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Operation object */\n operation: OperationObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Meta information for the auth update */\n authMeta: AuthMeta\n /** Document defined security schemes */\n securitySchemes: MergedSecuritySchemes\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** For environment variables in the inputs */\n environment: XScalarEnvironment\n /** The proxy URL for sending requests */\n proxyUrl: string\n /** Currently selected security */\n selectedSecurity: SelectedSecurity\n /** Currently selected security schemes */\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n /** Security requirements */\n securityRequirements: OpenApiDocument['security']\n /** Default headers */\n defaultHeaders: Record<string, string>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n /** Subset of config options for the modal */\n options?: ModalProps['options']\n}\n</script>\n<script setup lang=\"ts\">\nimport { ERRORS } 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 as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { executeHook, type ClientPlugin } from '@scalar/oas-utils/helpers'\nimport {\n AVAILABLE_CLIENTS,\n type AvailableClients,\n} from '@scalar/types/snippetz'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type { HistoryEntry } from '@scalar/workspace-store/entities/history/schema'\nimport type {\n AuthMeta,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n requestFactory,\n resolveExecutableRequestUrl,\n type MergedSecuritySchemes,\n type RequestPayload,\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 ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/operation'\nimport { computed, onBeforeUnmount, onMounted, ref, toValue, watch } from 'vue'\n\nimport ViewLayout from '@/components/ViewLayout/ViewLayout.vue'\nimport ViewLayoutContent from '@/components/ViewLayout/ViewLayoutContent.vue'\nimport { harToFetchRequest } from '@/v2/blocks/operation-block/helpers/har-to-fetch-request'\nimport { harToFetchResponse } from '@/v2/blocks/operation-block/helpers/har-to-fetch-response'\nimport {\n getOperationExampleKey,\n isStreamingResponse,\n responseCache,\n} from '@/v2/blocks/operation-block/helpers/response-cache'\nimport {\n sendRequest,\n type ResponseInstance,\n} from '@/v2/blocks/operation-block/helpers/send-request'\nimport { validatePathParameters } from '@/v2/blocks/operation-block/helpers/validate-path-parameters'\nimport { generateClientOptions } from '@/v2/blocks/operation-code-sample'\nimport { RequestBlock } from '@/v2/blocks/request-block'\nimport { ResponseBlock } from '@/v2/blocks/response-block'\nimport { type History } from '@/v2/blocks/scalar-address-bar-block'\nimport type { ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport Header from './components/Header.vue'\n\nconst {\n authMeta,\n environment,\n eventBus,\n exampleKey,\n document,\n documentSlug,\n workspaceCookies = [],\n documentCookies = [],\n hideClientButton,\n httpClients = AVAILABLE_CLIENTS,\n history = [],\n layout,\n method,\n operation,\n path,\n plugins = [],\n proxyUrl,\n requestBodyCompositionSelection,\n securitySchemes,\n selectedClient,\n server,\n environments,\n options,\n activeEnvironment,\n serverMeta,\n selectedSecurity,\n selectedSecuritySchemes,\n securityRequirements,\n defaultHeaders,\n} = defineProps<OperationBlockProps>()\n\n/** Hoist up client generation so it doesn't get re-generated on every operation */\nconst clientOptions = computed(() => generateClientOptions(httpClients))\n\nconst { toast } = useToasts()\nconst { copyToClipboard } = useClipboard()\n\n// Refs\nconst abortController = ref<AbortController | null>(null)\nconst response = ref<ResponseInstance | null>(null)\nconst requestPayload = ref<RequestPayload | null>(null)\n\n/** Cancel the request */\nconst cancelRequest = () => abortController.value?.abort(ERRORS.REQUEST_ABORTED)\n\n/**\n * Copy the executable URL — same pipeline as Send (`requestFactory` +\n * `resolveExecutableRequestUrl`), including security query params.\n */\nconst copyAddressBarUrl = async (): Promise<void> => {\n const { request } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies: [...workspaceCookies, ...documentCookies],\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n await copyToClipboard(\n resolveExecutableRequestUrl(request, getEnvironmentVariables(environment)),\n )\n}\n\n/** Execute the current operation example */\nconst handleExecute = async () => {\n eventBus.flushDebouncedEmits?.()\n\n const pathValidation = validatePathParameters(\n operation.parameters ?? [],\n exampleKey,\n )\n if (pathValidation.ok === false) {\n toast('Path parameters must have values.', 'error')\n return\n }\n\n const globalCookies = [...workspaceCookies, ...documentCookies]\n\n const { request: requestBuilder } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies,\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n // Stop any previous streaming response\n if (response.value && 'reader' in response.value) {\n response.value.reader.cancel()\n }\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Execute the beforeRequest hook (plugins receive RequestFactory, not fetch Request)\n await executeHook(\n {\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'beforeRequest',\n plugins,\n )\n\n const envVariables = {\n ...getEnvironmentVariables(environment),\n ...variablesStore.getVariables(),\n }\n\n // Build the fetch Request after hooks may have mutated the factory\n const built = buildRequest(requestBuilder, {\n envVariables,\n allowMissingRequestServerBase: layout === 'modal',\n })\n if (!built.ok) {\n toast(built.message ?? built.error, 'error')\n return\n }\n\n // Store the abort controller for cancellation\n abortController.value = built.data.controller\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:sent', {\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n /** Execute the request */\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: built.data.isUsingProxy,\n requestPayload: built.data.requestPayload,\n plugins,\n customFetch: toValue(options)?.customFetch,\n })\n\n if (sendResult) {\n // Execute the responseReceived hook\n await executeHook(\n {\n response: sendResult.originalResponse.clone(),\n requestBuilder,\n request: buildSafeBodyRequest(...sendResult.requestPayload),\n document,\n operation,\n variablesStore,\n },\n 'responseReceived',\n plugins,\n )\n }\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:complete', {\n payload: sendResult\n ? {\n response: sendResult.originalResponse.clone(),\n requestPayload: sendResult.requestPayload,\n duration: sendResult.response.duration,\n timestamp: sendResult.timestamp,\n }\n : undefined,\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n if (sendError) {\n // clean up the response and request\n response.value = null\n requestPayload.value = null\n abortController.value = null\n\n toast(sendError.message, 'error')\n return\n }\n\n // Store the response\n response.value = sendResult.response\n requestPayload.value = sendResult.requestPayload\n\n // Cache non-streaming responses so they can be restored when navigating back\n if (!isStreamingResponse(sendResult.response)) {\n responseCache.set(getOperationExampleKey(method, path, exampleKey), {\n response: sendResult.response,\n requestPayload: sendResult.requestPayload,\n })\n }\n}\n\nonMounted(() => {\n eventBus.on('operation:send:request:hotkey', handleExecute)\n eventBus.on('operation:cancel:request', cancelRequest)\n eventBus.on('copy-url:address-bar', copyAddressBarUrl)\n\n // Let plugins warm up per-operation resources (e.g. the scripts sandbox) so the first request\n // does not pay their cold-start cost.\n void executeHook({ document, operation }, 'onRequestMount', plugins)\n})\nonBeforeUnmount(() => {\n eventBus.off('operation:send:request:hotkey', handleExecute)\n eventBus.off('operation:cancel:request', cancelRequest)\n eventBus.off('copy-url:address-bar', copyAddressBarUrl)\n})\n\nconst operationHistory = computed<History[]>(() =>\n history\n .map((entry) => ({\n method: entry.request.method as HttpMethodType,\n path: entry.request.url,\n duration: entry.time,\n status: entry.response.status,\n }))\n .reverse(),\n)\n\nconst handleSelectHistoryItem = ({ index }: { index: number }) => {\n const transformedIndex = (history.length ?? 0) - index - 1\n const historyItem = history[transformedIndex]\n if (!historyItem) {\n return\n }\n\n const navigate = () =>\n eventBus.emit('ui:navigate', {\n page: 'example',\n method,\n path,\n exampleName: 'draft',\n callback: (status) => {\n // Do not replace the response if the navigation was not successful\n if (status !== 'success') {\n return\n }\n // Reconstruct the response\n const fetchResponse = harToFetchResponse({\n harResponse: historyItem.response,\n url: historyItem.request.url,\n method,\n path,\n duration: historyItem.time,\n })\n\n // Reconstruct the request\n const fetchRequest = harToFetchRequest({\n harRequest: historyItem.request,\n })\n\n // Update the response and request\n response.value = fetchResponse\n requestPayload.value = fetchRequest\n },\n })\n\n eventBus.emit('operation:reload:history', {\n meta: {\n path,\n method,\n },\n index: transformedIndex,\n callback: navigate,\n })\n}\n\nconst handleNavigateSettings = () => {\n eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'overview',\n operationPath: path,\n method,\n })\n}\n\n/**\n * When the path, method, or example key changes, restore the response panel\n * for the new operation from the best available source:\n *\n * 1. `responseCache` — in-memory, populated on every successful send.\n * Has the live response object (including streams) so it wins.\n * 2. `history` — persisted in the workspace store. Used as a fallback when\n * the in-memory cache is empty (page reload, fresh app session, etc.)\n * so navigating to an operation that has been called before shows the\n * last response instead of an empty panel.\n * 3. Otherwise clear.\n *\n * Only the response is restored from history — the user's request inputs are\n * left alone, so we never silently overwrite an in-progress draft.\n */\nwatch(\n [() => path, () => method, () => exampleKey],\n ([newPath, newMethod, newExampleKey]) => {\n const cached = responseCache.get(\n getOperationExampleKey(newMethod, newPath, newExampleKey),\n )\n\n if (cached) {\n response.value = cached.response\n requestPayload.value = cached.requestPayload\n } else {\n // History is keyed only by document/path/method but each entry carries\n // the example it came from, so we walk from the end and pick the most\n // recent entry that matches the active example. Otherwise a cache miss\n // on example B would restore example A's response. Only runs on a\n // cache miss — the common case (in-session navigation) skips it.\n const latest = (() => {\n for (let i = history.length - 1; i >= 0; i--) {\n const entry = history[i]\n if (entry?.meta.example === newExampleKey) {\n return entry\n }\n }\n return undefined\n })()\n\n if (latest) {\n response.value = harToFetchResponse({\n harResponse: latest.response,\n url: latest.request.url,\n method: newMethod,\n path: newPath,\n duration: latest.time,\n })\n requestPayload.value = null\n } else {\n response.value = null\n requestPayload.value = null\n }\n }\n\n // Cancel any in-flight request\n cancelRequest()\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n // We cancel the request if the component is unmounted\n cancelRequest()\n})\n</script>\n<template>\n <div class=\"bg-b-1 flex h-full flex-col\">\n <div\n class=\"lg:min-h-header flex w-full flex-wrap items-center justify-center p-2 lg:p-0\">\n <!-- Address Bar -->\n <Header\n :activeEnvironment\n :documentSlug\n :documentUrl\n :environment\n :environments\n :eventBus\n :exampleKey\n :hideClientButton\n :history=\"operationHistory\"\n :integration\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n :source\n @execute=\"handleExecute\"\n @navigate:settings=\"handleNavigateSettings\"\n @select:history:item=\"handleSelectHistoryItem\" />\n </div>\n\n <ViewLayout class=\"border-t\">\n <ViewLayoutContent class=\"flex-1\">\n <!-- Request Section -->\n <RequestBlock\n :authMeta\n :clientOptions\n :defaultHeaders\n :documentCookies\n :environment\n :eventBus\n :exampleKey\n :layout\n :method\n :operation\n :options=\"toValue(options)\"\n :path\n :plugins\n :proxyUrl\n :requestBodyCompositionSelection\n :securityRequirements\n :securitySchemes\n :selectedClient\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :workspaceCookies />\n\n <!-- Response Section -->\n <ResponseBlock\n :appVersion\n :eventBus\n :layout\n :plugins\n :requestPayload\n :response\n :totalPerformedRequests=\"operationHistory.length\" />\n </ViewLayoutContent>\n </ViewLayout>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;CAeE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyKR,MAAM,gBAAgB,eAAe,sBAAsB,QAAA,YAAY,CAAA;EAEvE,MAAM,EAAE,UAAU,WAAU;EAC5B,MAAM,EAAE,oBAAoB,cAAa;EAGzC,MAAM,kBAAkB,IAA4B,KAAI;EACxD,MAAM,WAAW,IAA6B,KAAI;EAClD,MAAM,iBAAiB,IAA2B,KAAI;;EAGtD,MAAM,sBAAsB,gBAAgB,OAAO,MAAM,OAAO,gBAAe;;;;;EAM/E,MAAM,oBAAoB,YAA2B;GACnD,MAAM,EAAE,YAAY,eAAe;IACjC,gBAAa,QAAA;IACb,aAAU,QAAA;IACV,aAAa,QAAA;IACb,eAAe,CAAC,GAAG,QAAA,kBAAkB,GAAG,QAAA,gBAAgB;IACxD,QAAK,QAAA;IACL,WAAQ,QAAA;IACR,MAAG,QAAA;IACH,UAAO,QAAA;IACP,QAAK,QAAA;IACL,yBAAsB,QAAA;IACtB,YAAY,YAAY;IACxB,iCAA8B,QAAA;IAC/B,CAAA;AAED,SAAM,gBACJ,4BAA4B,SAAS,wBAAwB,QAAA,YAAY,CAAC,CAC5E;;;EAIF,MAAM,gBAAgB,YAAY;AAChC,WAAA,SAAS,uBAAsB;AAM/B,OAJuB,uBACrB,QAAA,UAAU,cAAc,EAAE,EAC1B,QAAA,WACF,CACmB,OAAO,OAAO;AAC/B,UAAM,qCAAqC,QAAO;AAClD;;GAGF,MAAM,gBAAgB,CAAC,GAAG,QAAA,kBAAkB,GAAG,QAAA,gBAAe;GAE9D,MAAM,EAAE,SAAS,mBAAmB,eAAe;IACjD,gBAAa,QAAA;IACb,aAAU,QAAA;IACV,aAAa,QAAA;IACb;IACA,QAAK,QAAA;IACL,WAAQ,QAAA;IACR,MAAG,QAAA;IACH,UAAO,QAAA;IACP,QAAK,QAAA;IACL,yBAAsB,QAAA;IACtB,YAAY,YAAY;IACxB,iCAA8B,QAAA;IAC/B,CAAA;AAGD,OAAI,SAAS,SAAS,YAAY,SAAS,MACzC,UAAS,MAAM,OAAO,QAAO;GAG/B,MAAM,iBAAiB,gCAA+B;AAGtD,SAAM,YACJ;IACE;IACA,UAAO,QAAA;IACP,WAAQ,QAAA;IACR;IACD,EACD,iBACA,QAAA,QACF;GAQA,MAAM,QAAQ,aAAa,gBAAgB;IACzC,cAPmB;KACnB,GAAG,wBAAwB,QAAA,YAAY;KACvC,GAAG,eAAe,cAAc;KAClC;IAKE,+BAA+B,QAAA,WAAW;IAC3C,CAAA;AACD,OAAI,CAAC,MAAM,IAAI;AACb,UAAM,MAAM,WAAW,MAAM,OAAO,QAAO;AAC3C;;AAIF,mBAAgB,QAAQ,MAAM,KAAK;AAGnC,WAAA,SAAS,KAAK,yBAAyB,EACrC,MAAM;IACJ,QAAK,QAAA;IACL,MAAG,QAAA;IACH,YAAS,QAAA;IACV,EACF,CAAA;;GAGD,MAAM,CAAC,WAAW,cAAc,MAAM,YAAY;IAChD,cAAc,MAAM,KAAK;IACzB,gBAAgB,MAAM,KAAK;IAC3B,SAAM,QAAA;IACN,aAAa,QAAQ,QAAA,QAAQ,EAAE;IAChC,CAAA;AAED,OAAI,WAEF,OAAM,YACJ;IACE,UAAU,WAAW,iBAAiB,OAAO;IAC7C;IACA,SAAS,qBAAqB,GAAG,WAAW,eAAe;IAC3D,UAAO,QAAA;IACP,WAAQ,QAAA;IACR;IACD,EACD,oBACA,QAAA,QACF;AAIF,WAAA,SAAS,KAAK,6BAA6B;IACzC,SAAS,aACL;KACE,UAAU,WAAW,iBAAiB,OAAO;KAC7C,gBAAgB,WAAW;KAC3B,UAAU,WAAW,SAAS;KAC9B,WAAW,WAAW;KACxB,GACA,KAAA;IACJ,MAAM;KACJ,QAAK,QAAA;KACL,MAAG,QAAA;KACH,YAAS,QAAA;KACV;IACF,CAAA;AAED,OAAI,WAAW;AAEb,aAAS,QAAQ;AACjB,mBAAe,QAAQ;AACvB,oBAAgB,QAAQ;AAExB,UAAM,UAAU,SAAS,QAAO;AAChC;;AAIF,YAAS,QAAQ,WAAW;AAC5B,kBAAe,QAAQ,WAAW;AAGlC,OAAI,CAAC,oBAAoB,WAAW,SAAS,CAC3C,eAAc,IAAI,uBAAuB,QAAA,QAAQ,QAAA,MAAM,QAAA,WAAW,EAAE;IAClE,UAAU,WAAW;IACrB,gBAAgB,WAAW;IAC5B,CAAA;;AAIL,kBAAgB;AACd,WAAA,SAAS,GAAG,iCAAiC,cAAa;AAC1D,WAAA,SAAS,GAAG,4BAA4B,cAAa;AACrD,WAAA,SAAS,GAAG,wBAAwB,kBAAiB;AAIhD,eAAY;IAAE,UAAO,QAAA;IAAG,WAAQ,QAAA;IAAG,EAAE,kBAAkB,QAAA,QAAO;IACpE;AACD,wBAAsB;AACpB,WAAA,SAAS,IAAI,iCAAiC,cAAa;AAC3D,WAAA,SAAS,IAAI,4BAA4B,cAAa;AACtD,WAAA,SAAS,IAAI,wBAAwB,kBAAiB;IACvD;EAED,MAAM,mBAAmB,eACvB,QAAA,QACG,KAAK,WAAW;GACf,QAAQ,MAAM,QAAQ;GACtB,MAAM,MAAM,QAAQ;GACpB,UAAU,MAAM;GAChB,QAAQ,MAAM,SAAS;GACxB,EAAC,CACD,SAAS,CACd;EAEA,MAAM,2BAA2B,EAAE,YAA+B;GAChE,MAAM,oBAAoB,QAAA,QAAQ,UAAU,KAAK,QAAQ;GACzD,MAAM,cAAc,QAAA,QAAQ;AAC5B,OAAI,CAAC,YACH;GAGF,MAAM,iBACJ,QAAA,SAAS,KAAK,eAAe;IAC3B,MAAM;IACN,QAAK,QAAA;IACL,MAAG,QAAA;IACH,aAAa;IACb,WAAW,WAAW;AAEpB,SAAI,WAAW,UACb;KAGF,MAAM,gBAAgB,mBAAmB;MACvC,aAAa,YAAY;MACzB,KAAK,YAAY,QAAQ;MACzB,QAAK,QAAA;MACL,MAAG,QAAA;MACH,UAAU,YAAY;MACvB,CAAA;KAGD,MAAM,eAAe,kBAAkB,EACrC,YAAY,YAAY,SACzB,CAAA;AAGD,cAAS,QAAQ;AACjB,oBAAe,QAAQ;;IAE1B,CAAA;AAEH,WAAA,SAAS,KAAK,4BAA4B;IACxC,MAAM;KACJ,MAAG,QAAA;KACH,QAAK,QAAA;KACN;IACD,OAAO;IACP,UAAU;IACX,CAAA;;EAGH,MAAM,+BAA+B;AACnC,WAAA,SAAS,KAAK,eAAe;IAC3B,MAAM;IACN,MAAM;IACN,eAAe,QAAA;IACf,QAAK,QAAA;IACN,CAAA;;;;;;;;;;;;;;;;;AAkBH,QACE;SAAO,QAAA;SAAY,QAAA;SAAc,QAAA;GAAW,GAC3C,CAAC,SAAS,WAAW,mBAAmB;GACvC,MAAM,SAAS,cAAc,IAC3B,uBAAuB,WAAW,SAAS,cAAc,CAC3D;AAEA,OAAI,QAAQ;AACV,aAAS,QAAQ,OAAO;AACxB,mBAAe,QAAQ,OAAO;UACzB;IAML,MAAM,gBAAgB;AACpB,UAAK,IAAI,IAAI,QAAA,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;MAC5C,MAAM,QAAQ,QAAA,QAAQ;AACtB,UAAI,OAAO,KAAK,YAAY,cAC1B,QAAO;;QAIV;AAEH,QAAI,QAAQ;AACV,cAAS,QAAQ,mBAAmB;MAClC,aAAa,OAAO;MACpB,KAAK,OAAO,QAAQ;MACpB,QAAQ;MACR,MAAM;MACN,UAAU,OAAO;MAClB,CAAA;AACD,oBAAe,QAAQ;WAClB;AACL,cAAS,QAAQ;AACjB,oBAAe,QAAQ;;;AAK3B,kBAAc;KAEhB,EAAE,WAAW,MAAM,CACrB;AAEA,wBAAsB;AAEpB,kBAAc;IACf;;uBAGC,mBAiEM,OAjEN,YAiEM,CAhEJ,mBAwBM,OAxBN,YAwBM,CArBJ,YAoBmD,gBAAA;IAnBhD,mBAAA,QAAA;IACA,cAAA,QAAA;IACA,aAAA,QAAA;IACA,aAAA,QAAA;IACA,cAAA,QAAA;IACA,UAAA,QAAA;IACA,YAAA,QAAA;IACA,kBAAA,QAAA;IACA,SAAS,iBAAA;IACT,aAAA,QAAA;IACA,QAAA,QAAA;IACA,QAAA,QAAA;IACA,MAAA,QAAA;IACA,QAAA,QAAA;IACA,YAAA,QAAA;IACA,SAAA,QAAA;IACA,QAAA,QAAA;IACA,WAAS;IACT,uBAAmB;IACnB,yBAAqB;;;;;;;;;;;;;;;;;;;SAG1B,YAqCa,oBAAA,EArCD,OAAM,YAAU,EAAA;2BAoCN,CAnCpB,YAmCoB,2BAAA,EAnCD,OAAM,UAAQ,EAAA;4BAwBT,CAtBtB,YAsBsB,MAAA,qBAAA,EAAA;MArBnB,UAAA,QAAA;MACA,eAAA,cAAA;MACA,gBAAA,QAAA;MACA,iBAAA,QAAA;MACA,aAAA,QAAA;MACA,UAAA,QAAA;MACA,YAAA,QAAA;MACA,QAAA,QAAA;MACA,QAAA,QAAA;MACA,WAAA,QAAA;MACA,SAAS,QAAQ,QAAA,QAAO;MACxB,MAAA,QAAA;MACA,SAAA,QAAA;MACA,UAAA,QAAA;MACA,iCAAA,QAAA;MACA,sBAAA,QAAA;MACA,iBAAA,QAAA;MACA,gBAAA,QAAA;MACA,kBAAA,QAAA;MACA,yBAAA,QAAA;MACA,QAAA,QAAA;MACA,kBAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;SAGH,YAOsD,MAAA,sBAAA,EAAA;MANnD,YAAA,QAAA;MACA,UAAA,QAAA;MACA,QAAA,QAAA;MACA,SAAA,QAAA;MACA,gBAAA,eAAA;MACA,UAAA,SAAA;MACA,wBAAwB,iBAAA,MAAiB"}