@scalar/api-client 3.10.4 → 3.12.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.
- package/CHANGELOG.md +26 -0
- package/dist/plugins/posthog/sanitize-event-payload.d.ts.map +1 -1
- package/dist/plugins/posthog/sanitize-event-payload.js +1 -0
- package/dist/plugins/posthog/sanitize-event-payload.js.map +1 -1
- package/dist/style.css +25 -74
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +10 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts +7 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.js +2 -2
- package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js +1 -2
- package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.js +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +48 -11
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts +2 -2
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +2 -6
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts +4 -0
- package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestParams.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +3 -11
- package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +8 -10
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +27 -11
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/create-parameter-handlers.d.ts +9 -6
- package/dist/v2/blocks/request-block/helpers/create-parameter-handlers.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/helpers/create-parameter-handlers.js +45 -4
- package/dist/v2/blocks/request-block/helpers/create-parameter-handlers.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/create-parameter-rows.d.ts +4 -0
- package/dist/v2/blocks/request-block/helpers/create-parameter-rows.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js +94 -10
- package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.d.ts +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/modal/Modal.vue.js.map +1 -1
- package/dist/v2/features/modal/Modal.vue.script.js +1 -1
- package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
- package/dist/v2/features/modal/helpers/create-api-client-modal.js +1 -1
- package/dist/v2/features/operation/Operation.vue.script.js +1 -1
- package/dist/v2/workspace-events.d.ts.map +1 -1
- package/dist/v2/workspace-events.js +1 -0
- package/dist/v2/workspace-events.js.map +1 -1
- package/dist/vue-styles.css +10 -52
- package/package.json +13 -24
- package/dist/v2/blocks/operation-code-sample/components/ExamplePicker.vue.d.ts +0 -16
- package/dist/v2/blocks/operation-code-sample/components/ExamplePicker.vue.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/components/ExamplePicker.vue.js +0 -7
- package/dist/v2/blocks/operation-code-sample/components/ExamplePicker.vue.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/components/ExamplePicker.vue.script.js +0 -53
- package/dist/v2/blocks/operation-code-sample/components/ExamplePicker.vue.script.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/components/HttpMethod.vue.d.ts +0 -26
- package/dist/v2/blocks/operation-code-sample/components/HttpMethod.vue.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/components/HttpMethod.vue.js +0 -7
- package/dist/v2/blocks/operation-code-sample/components/HttpMethod.vue.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/components/HttpMethod.vue.script.js +0 -33
- package/dist/v2/blocks/operation-code-sample/components/HttpMethod.vue.script.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts +0 -141
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js +0 -9
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js +0 -272
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/filter-clients-by-query.d.ts +0 -9
- package/dist/v2/blocks/operation-code-sample/helpers/filter-clients-by-query.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/filter-clients-by-query.js +0 -37
- package/dist/v2/blocks/operation-code-sample/helpers/filter-clients-by-query.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/find-client.d.ts +0 -41
- package/dist/v2/blocks/operation-code-sample/helpers/find-client.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/find-client.js +0 -48
- package/dist/v2/blocks/operation-code-sample/helpers/find-client.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/format-language.d.ts +0 -8
- package/dist/v2/blocks/operation-code-sample/helpers/format-language.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/format-language.js +0 -70
- package/dist/v2/blocks/operation-code-sample/helpers/format-language.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.d.ts +0 -30
- package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.js +0 -63
- package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.d.ts +0 -39
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js +0 -38
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-clients.d.ts +0 -13
- package/dist/v2/blocks/operation-code-sample/helpers/get-clients.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-clients.js +0 -37
- package/dist/v2/blocks/operation-code-sample/helpers/get-clients.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.d.ts +0 -45
- package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.js +0 -84
- package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-resolved-ref-deep.d.ts +0 -27
- package/dist/v2/blocks/operation-code-sample/helpers/get-resolved-ref-deep.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-resolved-ref-deep.js +0 -41
- package/dist/v2/blocks/operation-code-sample/helpers/get-resolved-ref-deep.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-secrets.d.ts +0 -4
- package/dist/v2/blocks/operation-code-sample/helpers/get-secrets.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-secrets.js +0 -18
- package/dist/v2/blocks/operation-code-sample/helpers/get-secrets.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-snippet.d.ts +0 -8
- package/dist/v2/blocks/operation-code-sample/helpers/get-snippet.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-snippet.js +0 -38
- package/dist/v2/blocks/operation-code-sample/helpers/get-snippet.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.d.ts +0 -72
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.js +0 -114
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.d.ts +0 -13
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js +0 -196
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.d.ts +0 -24
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.js +0 -237
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.d.ts +0 -15
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.js +0 -65
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-server-url.d.ts +0 -6
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-server-url.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-server-url.js +0 -19
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-server-url.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/index.d.ts +0 -9
- package/dist/v2/blocks/operation-code-sample/index.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/index.js +0 -8
- package/dist/v2/blocks/operation-code-sample/types.d.ts +0 -46
- package/dist/v2/blocks/operation-code-sample/types.d.ts.map +0 -1
- package/dist/v2/blocks/request-block/helpers/is-param-disabled.d.ts +0 -13
- package/dist/v2/blocks/request-block/helpers/is-param-disabled.d.ts.map +0 -1
- package/dist/v2/blocks/request-block/helpers/is-param-disabled.js +0 -21
- package/dist/v2/blocks/request-block/helpers/is-param-disabled.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @scalar/api-client
|
|
2
2
|
|
|
3
|
+
## 3.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#8519](https://github.com/scalar/scalar/pull/8519): refactor: extract the code example block into `@scalar/blocks/code-example`. `api-client`, `api-client-react`, and `api-reference` now import `CodeExample`, `findClient`, `generateClientOptions`, and the related helpers from the new package. `workspace-store` exports `isParamDisabled` with an optional `defaultDisabled` argument.
|
|
8
|
+
|
|
9
|
+
**Breaking (`@scalar/api-client`):** the `@scalar/api-client/blocks/operation-code-sample` and `@scalar/api-client/v2/blocks/operation-code-sample` export paths have been removed. Import from `@scalar/blocks/code-example` instead, and use the renamed `CodeExample` / `CodeExampleProps` (previously `OperationCodeSample` / `OperationCodeSampleProps`).
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#9584](https://github.com/scalar/scalar/pull/9584): Show the trailing-bracket name (`filter[ids][]`) on expanded `deepObject` array parameter rows so the table matches the serialized request, and keep edited array leaves as arrays when writing the value back
|
|
14
|
+
- [#9548](https://github.com/scalar/scalar/pull/9548): Keep request and response example pickers in sync across operations. Selecting an example (e.g. "Use case 1") now selects the example with the same key on every other operation that defines it, mirroring how the programming-language selection already syncs. Operations that do not have a matching example keep their current selection.
|
|
15
|
+
|
|
16
|
+
## 3.11.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- [#9515](https://github.com/scalar/scalar/pull/9515): feat: add `requestBuilt` client plugin hook and `onRequestBuilt` configuration callback that receive the exact fetch `Request` that is sent over the wire
|
|
21
|
+
|
|
22
|
+
The hook runs after the request has been built, right before it is sent. Header mutations apply to the outgoing request and the body bytes match what the server receives, which makes request signing possible: hashing the body of a rebuilt `multipart/form-data` request would produce a different multipart boundary than the request that is actually sent.
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- [#9558](https://github.com/scalar/scalar/pull/9558): Fix the request runner dropping a manually typed auth token when the document name is not slug-safe (e.g. documents loaded via `sources`). The modal now reads auth secrets under the same document key they are written to.
|
|
27
|
+
- [#9497](https://github.com/scalar/scalar/pull/9497): Fix renaming an auto-expanded query parameter row: the committed key is applied to the request and persists in the table without writing partial in-progress edits, and the original key no longer reappears as an empty suggestion
|
|
28
|
+
|
|
3
29
|
## 3.10.4
|
|
4
30
|
|
|
5
31
|
### 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,
|
|
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,gBAqI5B,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"}
|
|
@@ -69,6 +69,7 @@ var TRACKED_EVENTS = {
|
|
|
69
69
|
"workspace:update:color-mode": empty,
|
|
70
70
|
"workspace:update:theme": empty,
|
|
71
71
|
"workspace:update:selected-client": empty,
|
|
72
|
+
"workspace:update:selected-example": empty,
|
|
72
73
|
"workspace:update:active-proxy": (payload) => ({ enabled: !!payload }),
|
|
73
74
|
"workspace:update:active-environment": empty,
|
|
74
75
|
"update:dark-mode": empty,
|
|
@@ -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 '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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"}
|
|
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:selected-example': 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
|
@@ -442,7 +442,16 @@
|
|
|
442
442
|
border-width: 1px;
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
-
:where(.scalar-app) input
|
|
445
|
+
:where(.scalar-app) input, :where(.scalar-app) select, :where(.scalar-app) textarea {
|
|
446
|
+
text-align: start;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
:where(.scalar-app) input::placeholder, :where(.scalar-app) text-area::placeholder {
|
|
450
|
+
color: var(--scalar-color-3);
|
|
451
|
+
font-family: var(--scalar-font);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
:where(.scalar-app) ::-webkit-input-placeholder {
|
|
446
455
|
color: var(--scalar-color-3);
|
|
447
456
|
font-family: var(--scalar-font);
|
|
448
457
|
}
|
|
@@ -1860,7 +1869,7 @@
|
|
|
1860
1869
|
border-radius: 2px;
|
|
1861
1870
|
}
|
|
1862
1871
|
|
|
1863
|
-
.sidebar-heading-type[data-v-
|
|
1872
|
+
.sidebar-heading-type[data-v-bdef8365] {
|
|
1864
1873
|
text-transform: uppercase;
|
|
1865
1874
|
color: var(--method-color, var(--scalar-color-1));
|
|
1866
1875
|
font-size: 10px;
|
|
@@ -2374,10 +2383,6 @@
|
|
|
2374
2383
|
margin-top: auto;
|
|
2375
2384
|
}
|
|
2376
2385
|
|
|
2377
|
-
.scalar-app .mt-px {
|
|
2378
|
-
margin-top: 1px;
|
|
2379
|
-
}
|
|
2380
|
-
|
|
2381
2386
|
.scalar-app .-mr-0\.5 {
|
|
2382
2387
|
margin-right: -2px;
|
|
2383
2388
|
}
|
|
@@ -2735,10 +2740,6 @@
|
|
|
2735
2740
|
max-height: 160px;
|
|
2736
2741
|
}
|
|
2737
2742
|
|
|
2738
|
-
.scalar-app .max-h-80 {
|
|
2739
|
-
max-height: 320px;
|
|
2740
|
-
}
|
|
2741
|
-
|
|
2742
2743
|
.scalar-app .max-h-\[60svh\] {
|
|
2743
2744
|
max-height: 60svh;
|
|
2744
2745
|
}
|
|
@@ -3004,10 +3005,6 @@
|
|
|
3004
3005
|
min-width: 32px;
|
|
3005
3006
|
}
|
|
3006
3007
|
|
|
3007
|
-
.scalar-app .min-w-32 {
|
|
3008
|
-
min-width: 128px;
|
|
3009
|
-
}
|
|
3010
|
-
|
|
3011
3008
|
.scalar-app .min-w-\[4\.5rem\] {
|
|
3012
3009
|
min-width: 4.5rem;
|
|
3013
3010
|
}
|
|
@@ -3881,10 +3878,6 @@
|
|
|
3881
3878
|
padding-block: 1px;
|
|
3882
3879
|
}
|
|
3883
3880
|
|
|
3884
|
-
.scalar-app .py-0\.75 {
|
|
3885
|
-
padding-block: 3px;
|
|
3886
|
-
}
|
|
3887
|
-
|
|
3888
3881
|
.scalar-app .py-1 {
|
|
3889
3882
|
padding-block: 4px;
|
|
3890
3883
|
}
|
|
@@ -4065,6 +4058,10 @@
|
|
|
4065
4058
|
text-align: right;
|
|
4066
4059
|
}
|
|
4067
4060
|
|
|
4061
|
+
.scalar-app .text-start {
|
|
4062
|
+
text-align: start;
|
|
4063
|
+
}
|
|
4064
|
+
|
|
4068
4065
|
.scalar-app .font-code {
|
|
4069
4066
|
font-family: var(--scalar-font-code);
|
|
4070
4067
|
}
|
|
@@ -5544,10 +5541,6 @@
|
|
|
5544
5541
|
rotate: 90deg;
|
|
5545
5542
|
}
|
|
5546
5543
|
|
|
5547
|
-
.scalar-app .ui-open\:rotate-180[data-headlessui-state~="open"], :where([data-headlessui-state~="open"]) :is(.scalar-app .ui-open\:rotate-180) {
|
|
5548
|
-
rotate: 180deg;
|
|
5549
|
-
}
|
|
5550
|
-
|
|
5551
5544
|
.scalar-app .last\:ui-open\:border-b-0:last-child[data-headlessui-state~="open"], :where([data-headlessui-state~="open"]) .scalar-app .last\:ui-open\:border-b-0:last-child {
|
|
5552
5545
|
border-bottom-style: var(--tw-border-style);
|
|
5553
5546
|
border-bottom-width: 0;
|
|
@@ -6450,19 +6443,19 @@ to {
|
|
|
6450
6443
|
background: color-mix(in srgb, var(--scalar-background-3), transparent 40%);
|
|
6451
6444
|
}
|
|
6452
6445
|
|
|
6453
|
-
[data-v-
|
|
6446
|
+
[data-v-6b2d7899] .code-input-lite__editor {
|
|
6454
6447
|
background-color: transparent;
|
|
6455
6448
|
font-family: var(--scalar-font);
|
|
6456
6449
|
font-size: var(--scalar-small);
|
|
6457
6450
|
padding: 5px 8px;
|
|
6458
6451
|
}
|
|
6459
|
-
[data-v-
|
|
6452
|
+
[data-v-6b2d7899] .scalar-pill:not(:last-of-type) {
|
|
6460
6453
|
margin-right: 0.15em;
|
|
6461
6454
|
}
|
|
6462
|
-
[data-v-
|
|
6455
|
+
[data-v-6b2d7899] .scalar-pill:not(:first-of-type) {
|
|
6463
6456
|
margin-left: 0.5px;
|
|
6464
6457
|
}
|
|
6465
|
-
.filemask[data-v-
|
|
6458
|
+
.filemask[data-v-6b2d7899] {
|
|
6466
6459
|
mask-image: linear-gradient(
|
|
6467
6460
|
to right,
|
|
6468
6461
|
transparent 0,
|
|
@@ -6522,20 +6515,20 @@ input[data-v-a6f4752a]::placeholder {
|
|
|
6522
6515
|
-moz-text-security: disc;
|
|
6523
6516
|
}
|
|
6524
6517
|
|
|
6525
|
-
.request-section-content[data-v-
|
|
6518
|
+
.request-section-content[data-v-f52d9c1f] {
|
|
6526
6519
|
--scalar-border-width: 0.5px;
|
|
6527
6520
|
}
|
|
6528
|
-
.request-section-content-filter[data-v-
|
|
6521
|
+
.request-section-content-filter[data-v-f52d9c1f] {
|
|
6529
6522
|
box-shadow: 0 -10px 0 10px var(--scalar-background-1);
|
|
6530
6523
|
}
|
|
6531
|
-
.request-item:focus-within .request-meta-buttons[data-v-
|
|
6524
|
+
.request-item:focus-within .request-meta-buttons[data-v-f52d9c1f] {
|
|
6532
6525
|
opacity: 1;
|
|
6533
6526
|
}
|
|
6534
|
-
.group-hover-input[data-v-
|
|
6527
|
+
.group-hover-input[data-v-f52d9c1f] {
|
|
6535
6528
|
border-width: var(--scalar-border-width);
|
|
6536
6529
|
border-color: transparent;
|
|
6537
6530
|
}
|
|
6538
|
-
.group:hover .group-hover-input[data-v-
|
|
6531
|
+
.group:hover .group-hover-input[data-v-f52d9c1f] {
|
|
6539
6532
|
background: color-mix(
|
|
6540
6533
|
in srgb,
|
|
6541
6534
|
var(--scalar-background-1),
|
|
@@ -6543,7 +6536,7 @@ input[data-v-a6f4752a]::placeholder {
|
|
|
6543
6536
|
);
|
|
6544
6537
|
border-color: var(--scalar-border-color);
|
|
6545
6538
|
}
|
|
6546
|
-
.group-hover-input[data-v-
|
|
6539
|
+
.group-hover-input[data-v-f52d9c1f]:focus {
|
|
6547
6540
|
background: transparent !important;
|
|
6548
6541
|
border-color: var(--scalar-border-color) !important;
|
|
6549
6542
|
}
|
|
@@ -6648,48 +6641,6 @@ to {
|
|
|
6648
6641
|
transform: translateY(0);
|
|
6649
6642
|
}
|
|
6650
6643
|
}
|
|
6651
|
-
|
|
6652
|
-
.request-card[data-v-70ede25b] {
|
|
6653
|
-
color: var(--scalar-color-1);
|
|
6654
|
-
font-size: var(--scalar-font-size-3);
|
|
6655
|
-
}
|
|
6656
|
-
.request-method[data-v-70ede25b] {
|
|
6657
|
-
font-family: var(--scalar-font-code);
|
|
6658
|
-
text-transform: uppercase;
|
|
6659
|
-
margin-right: 6px;
|
|
6660
|
-
}
|
|
6661
|
-
.request-card-footer[data-v-70ede25b] {
|
|
6662
|
-
display: flex;
|
|
6663
|
-
justify-content: flex-end;
|
|
6664
|
-
padding: 6px;
|
|
6665
|
-
flex-shrink: 0;
|
|
6666
|
-
position: relative;
|
|
6667
|
-
}
|
|
6668
|
-
.request-card-footer-addon[data-v-70ede25b] {
|
|
6669
|
-
display: flex;
|
|
6670
|
-
align-items: center;
|
|
6671
|
-
|
|
6672
|
-
flex: 1;
|
|
6673
|
-
min-width: 0;
|
|
6674
|
-
}
|
|
6675
|
-
.request-editor-section[data-v-70ede25b] {
|
|
6676
|
-
display: flex;
|
|
6677
|
-
flex: 1;
|
|
6678
|
-
}
|
|
6679
|
-
.request-card-simple[data-v-70ede25b] {
|
|
6680
|
-
display: flex;
|
|
6681
|
-
align-items: center;
|
|
6682
|
-
justify-content: space-between;
|
|
6683
|
-
|
|
6684
|
-
padding: 8px 8px 8px 12px;
|
|
6685
|
-
|
|
6686
|
-
font-size: var(--scalar-small);
|
|
6687
|
-
}
|
|
6688
|
-
.code-snippet[data-v-70ede25b] {
|
|
6689
|
-
display: flex;
|
|
6690
|
-
flex-direction: column;
|
|
6691
|
-
width: 100%;
|
|
6692
|
-
}
|
|
6693
6644
|
/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */
|
|
6694
6645
|
[data-radix-popper-content-wrapper]:has(.scalar-api-client-context-menu) {
|
|
6695
6646
|
z-index: 1000 !important;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"OperationBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"names":[],"mappings":"AA8lBA,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAA;AACrF,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAA;AAG/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iDAAiD,CAAA;AACnF,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAML,KAAK,qBAAqB,EAE1B,KAAK,0BAA0B,EAChC,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uDAAuD,CAAA;AAoB5F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAKrD;;;;;;;;;;;;GAYG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAMzC,MAAM,MAAM,mBAAmB,GAAG;IAChC,gBAAgB;IAChB,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,uBAAuB;IACvB,QAAQ,EAAE,eAAe,CAAA;IACzB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,wBAAwB;IACxB,gBAAgB,EAAE,aAAa,EAAE,CAAA;IACjC,uBAAuB;IACvB,eAAe,EAAE,aAAa,EAAE,CAAA;IAChC,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,6BAA6B;IAC7B,MAAM,EAAE,cAAc,CAAA;IACtB,mBAAmB;IACnB,WAAW,EAAE,gBAAgB,CAAA;IAC7B,oCAAoC;IACpC,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,oBAAoB;IACpB,MAAM,EAAE,YAAY,CAAA;IACpB,gCAAgC;IAChC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,gCAAgC;IAChC,cAAc,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC,yBAAyB,CAAC,CAAA;IACtE,mDAAmD;IACnD,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,sCAAsC;IACtC,UAAU,EAAE,UAAU,CAAA;IACtB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oBAAoB;IACpB,MAAM,CAAC,EAAE,SAAS,GAAG,eAAe,CAAA;IACpC,uBAAuB;IACvB,SAAS,EAAE,eAAe,CAAA;IAC1B,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,QAAQ,EAAE,QAAQ,CAAA;IAClB,wCAAwC;IACxC,eAAe,EAAE,qBAAqB,CAAA;IACtC,qBAAqB;IACrB,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,uBAAuB;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,8CAA8C;IAC9C,WAAW,EAAE,kBAAkB,CAAA;IAC/B,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,kCAAkC;IAClC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,0CAA0C;IAC1C,uBAAuB,EAAE,0BAA0B,EAAE,CAAA;IACrD,4BAA4B;IAC5B,oBAAoB,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;IACjD,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,sEAAsE;IACtE,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxD,6CAA6C;IAC7C,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;CAChC,CAAA;AACD,QAAA,MAAM,YAAY,kTAglBd,CAAC"}
|
|
@@ -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\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":""}
|
|
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 { generateClientOptions } from '@scalar/blocks/code-example'\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 { 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 // Build the fetch Request once so the requestBuilt hook observes the exact bytes that are\n // sent. Rebuilding it later would generate a different multipart boundary, which breaks\n // plugins that hash the body (for example, request signing).\n const request = buildSafeBodyRequest(...built.data.requestPayload)\n\n // Execute the requestBuilt hook (plugins receive the exact fetch Request that will be sent)\n await executeHook(\n {\n request,\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'requestBuilt',\n plugins,\n )\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 request,\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":""}
|
|
@@ -5,7 +5,6 @@ import { harToFetchRequest } from "./helpers/har-to-fetch-request.js";
|
|
|
5
5
|
import { harToFetchResponse } from "./helpers/har-to-fetch-response.js";
|
|
6
6
|
import { getOperationExampleKey, isStreamingResponse, responseCache } from "./helpers/response-cache.js";
|
|
7
7
|
import { validatePathParameters } from "./helpers/validate-path-parameters.js";
|
|
8
|
-
import { generateClientOptions } from "../operation-code-sample/helpers/generate-client-options.js";
|
|
9
8
|
import RequestBlock_default from "../request-block/RequestBlock.vue.js";
|
|
10
9
|
import ResponseBlock_default from "../response-block/ResponseBlock.vue.js";
|
|
11
10
|
import Header_default from "./components/Header.vue.js";
|
|
@@ -14,6 +13,7 @@ import { buildRequest, createVariablesStoreForRequest, getEnvironmentVariables,
|
|
|
14
13
|
import { ERRORS } from "@scalar/helpers/errors/normalize-error";
|
|
15
14
|
import { isElectron } from "@scalar/helpers/general/is-electron";
|
|
16
15
|
import { buildSafeBodyRequest } from "@scalar/helpers/http/can-method-have-body";
|
|
16
|
+
import { generateClientOptions } from "@scalar/blocks/code-example";
|
|
17
17
|
import { executeHook } from "@scalar/oas-utils/helpers";
|
|
18
18
|
import { AVAILABLE_CLIENTS } from "@scalar/types/snippetz";
|
|
19
19
|
import { useClipboard } from "@scalar/use-hooks/useClipboard";
|
|
@@ -132,6 +132,14 @@ var OperationBlock_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
132
132
|
return;
|
|
133
133
|
}
|
|
134
134
|
abortController.value = built.data.controller;
|
|
135
|
+
const request = buildSafeBodyRequest(...built.data.requestPayload);
|
|
136
|
+
await executeHook({
|
|
137
|
+
request,
|
|
138
|
+
requestBuilder,
|
|
139
|
+
document: __props.document,
|
|
140
|
+
operation: __props.operation,
|
|
141
|
+
variablesStore
|
|
142
|
+
}, "requestBuilt", __props.plugins);
|
|
135
143
|
__props.eventBus.emit("hooks:on:request:sent", { meta: {
|
|
136
144
|
method: __props.method,
|
|
137
145
|
path: __props.path,
|
|
@@ -141,6 +149,7 @@ var OperationBlock_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
141
149
|
const [sendError, sendResult] = await sendRequest({
|
|
142
150
|
isUsingProxy: built.data.isUsingProxy,
|
|
143
151
|
requestPayload: built.data.requestPayload,
|
|
152
|
+
request,
|
|
144
153
|
plugins: __props.plugins,
|
|
145
154
|
customFetch: toValue(__props.options)?.customFetch
|
|
146
155
|
});
|
|
@@ -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\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":"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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 { generateClientOptions } from '@scalar/blocks/code-example'\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 { 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 // Build the fetch Request once so the requestBuilt hook observes the exact bytes that are\n // sent. Rebuilding it later would generate a different multipart boundary, which breaks\n // plugins that hash the body (for example, request signing).\n const request = buildSafeBodyRequest(...built.data.requestPayload)\n\n // Execute the requestBuilt hook (plugins receive the exact fetch Request that will be sent)\n await executeHook(\n {\n request,\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'requestBuilt',\n plugins,\n )\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 request,\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":"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"}
|
|
@@ -42,9 +42,15 @@ export type CustomFetch = typeof fetch;
|
|
|
42
42
|
* @param isUsingProxy - Whether the request is being proxied for header handling
|
|
43
43
|
* @returns A tuple with either an error or the response data
|
|
44
44
|
*/
|
|
45
|
-
export declare const sendRequest: ({ isUsingProxy, requestPayload, plugins, customFetch, }: {
|
|
45
|
+
export declare const sendRequest: ({ isUsingProxy, requestPayload, request, plugins, customFetch, }: {
|
|
46
46
|
isUsingProxy: boolean;
|
|
47
47
|
requestPayload: RequestPayload;
|
|
48
|
+
/**
|
|
49
|
+
* Pre-built fetch Request to send as-is. When provided, it is used instead of rebuilding
|
|
50
|
+
* from the request payload so plugin hooks observe the exact bytes that go over the wire
|
|
51
|
+
* (rebuilding a multipart body generates a different boundary).
|
|
52
|
+
*/
|
|
53
|
+
request?: Request;
|
|
48
54
|
/** Registered client plugins for custom content type handling */
|
|
49
55
|
plugins?: ClientPlugin[];
|
|
50
56
|
/** Optional custom fetch implementation, overrides the global fetch */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send-request.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAkB,MAAM,wCAAwC,CAAA;AAGnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAKnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAA;AAY7E,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IACzD,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,CACE;IACE,wBAAwB;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,qDAAqD;IACrD,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAA;CAChD,CACJ,CAAA;AAKH,2EAA2E;AAC3E,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAA;AAEtC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,
|
|
1
|
+
{"version":3,"file":"send-request.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAkB,MAAM,wCAAwC,CAAA;AAGnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAKnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAA;AAY7E,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IACzD,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,CACE;IACE,wBAAwB;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,qDAAqD;IACrD,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAA;CAChD,CACJ,CAAA;AAKH,2EAA2E;AAC3E,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAA;AAEtC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,kEAM/B;IACD,YAAY,EAAE,OAAO,CAAA;IACrB,cAAc,EAAE,cAAc,CAAA;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iEAAiE;IACjE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,uEAAuE;IACvE,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,KAAG,OAAO,CACT,aAAa,CAAC;IACZ,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,QAAQ,CAAA;CAC3B,CAAC,CA0DH,CAAA"}
|
|
@@ -30,10 +30,10 @@ var NO_BODY_STATUS_CODES = [
|
|
|
30
30
|
* @param isUsingProxy - Whether the request is being proxied for header handling
|
|
31
31
|
* @returns A tuple with either an error or the response data
|
|
32
32
|
*/
|
|
33
|
-
var sendRequest = async ({ isUsingProxy, requestPayload, plugins = [], customFetch = fetch }) => {
|
|
33
|
+
var sendRequest = async ({ isUsingProxy, requestPayload, request, plugins = [], customFetch = fetch }) => {
|
|
34
34
|
try {
|
|
35
35
|
const startTime = performance.now();
|
|
36
|
-
const response = isElectron() ? await customFetch(...requestPayload) : await customFetch(buildSafeBodyRequest(...requestPayload));
|
|
36
|
+
const response = isElectron() ? await customFetch(...requestPayload) : await customFetch(request ?? buildSafeBodyRequest(...requestPayload));
|
|
37
37
|
const endTime = performance.now();
|
|
38
38
|
const timestamp = Date.now();
|
|
39
39
|
const duration = endTime - startTime;
|