@scalar/api-client 2.39.0 → 2.39.2
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 +15 -0
- package/dist/hooks/useClientConfig.d.ts +18 -0
- package/dist/hooks/useClientConfig.d.ts.map +1 -1
- package/dist/style.css +23 -28
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +2 -0
- 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 +6 -2
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-body.d.ts +3 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-body.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-body.js +2 -2
- package/dist/v2/blocks/operation-block/helpers/build-request-body.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/build-request.d.ts +3 -1
- package/dist/v2/blocks/operation-block/helpers/build-request.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/build-request.js +2 -2
- package/dist/v2/blocks/operation-block/helpers/build-request.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts +5 -0
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js +1 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js +6 -3
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.d.ts +3 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js +3 -2
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-example-from-schema.d.ts +5 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-example-from-schema.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-example-from-schema.js +51 -25
- package/dist/v2/blocks/operation-code-sample/helpers/get-example-from-schema.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.d.ts +6 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.js +3 -2
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.d.ts +2 -2
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js +5 -3
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts +1 -0
- 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 +4 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts +2 -0
- package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +3 -2
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +2 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.js +1 -3
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js +2 -3
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +6 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-request-body-example.d.ts +1 -1
- package/dist/v2/blocks/request-block/helpers/get-request-body-example.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-request-body-example.js +6 -2
- package/dist/v2/blocks/request-block/helpers/get-request-body-example.js.map +1 -1
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/app/helpers/routes.d.ts +2 -0
- package/dist/v2/features/app/helpers/routes.d.ts.map +1 -1
- package/dist/v2/features/collection/DocumentCollection.vue.d.ts.map +1 -1
- package/dist/v2/features/collection/DocumentCollection.vue.js.map +1 -1
- package/dist/v2/features/collection/DocumentCollection.vue.script.js +71 -48
- package/dist/v2/features/collection/DocumentCollection.vue.script.js.map +1 -1
- package/dist/v2/features/modal/Modal.vue.d.ts +3 -1
- package/dist/v2/features/modal/Modal.vue.d.ts.map +1 -1
- package/dist/v2/features/modal/Modal.vue.js.map +1 -1
- package/dist/v2/features/modal/Modal.vue.script.js +4 -0
- package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
- package/dist/v2/features/modal/helpers/create-api-client-modal.d.ts.map +1 -1
- package/dist/v2/features/modal/helpers/create-api-client-modal.js +3 -0
- package/dist/v2/features/modal/helpers/create-api-client-modal.js.map +1 -1
- package/dist/v2/features/modal/modal-events.d.ts +2 -1
- package/dist/v2/features/modal/modal-events.d.ts.map +1 -1
- package/dist/v2/features/modal/modal-events.js +3 -1
- package/dist/v2/features/modal/modal-events.js.map +1 -1
- package/dist/v2/features/operation/Operation.vue.d.ts +4 -0
- package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
- package/dist/v2/features/operation/Operation.vue.js.map +1 -1
- package/dist/v2/features/operation/Operation.vue.script.js +4 -1
- package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
- package/dist/v2/helpers/download-document.d.ts +2 -0
- package/dist/v2/helpers/download-document.d.ts.map +1 -0
- package/dist/v2/helpers/download-document.js +42 -0
- package/dist/v2/helpers/download-document.js.map +1 -0
- package/dist/v2/posthog.d.ts.map +1 -1
- package/dist/v2/posthog.js +1 -0
- package/dist/v2/posthog.js.map +1 -1
- package/dist/views/Request/ResponseSection/ResponseEmpty.vue.script.js +1 -1
- package/package.json +13 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationCodeSample.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"OperationCodeSample.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"names":[],"mappings":"AAmeA,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAErF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAiBrE,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6DAA6D,CAAA;AAM7G,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;IACpC;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC;;;;OAIG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACzC;;OAEG;IACH,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;IACpC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;OAEG;IACH,eAAe,EAAE,0BAA0B,EAAE,CAAA;IAC7C;;OAEG;IACH,MAAM,EAAE,cAAc,CAAA;IACtB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,SAAS,EAAE,eAAe,CAAA;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAA;IAC5B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;IAC/B;;;OAGG;IACH,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzD,CAAA;AAED;;;;;;;;GAQG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IA8KlB,8DAA8D;sBAC1C,MAAM;;;;IAD1B,8DAA8D;sBAC1C,MAAM;;;;YA1JhB,MAAM,OAAO;YACb,CAAC,EAAE,WAAW,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO;EA8gB3D,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
|
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_
|
|
|
2
2
|
import OperationCodeSample_vue_vue_type_script_setup_true_lang_default from "./OperationCodeSample.vue.script.js";
|
|
3
3
|
/* empty css */
|
|
4
4
|
//#region src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue
|
|
5
|
-
var OperationCodeSample_default = /* @__PURE__ */ _plugin_vue_export_helper_default(OperationCodeSample_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
5
|
+
var OperationCodeSample_default = /* @__PURE__ */ _plugin_vue_export_helper_default(OperationCodeSample_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-f52db2cc"]]);
|
|
6
6
|
//#endregion
|
|
7
7
|
export { OperationCodeSample_default as default };
|
|
8
8
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationCodeSample.vue.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type OperationCodeSampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown\n *\n * @defaults to shell/curl or a custom sample if one is available\n */\n selectedClient?: AvailableClients[number]\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event scalar-update-selected-example - removed for now, we can bring it back when we need it\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n ScalarCodeBlock,\n ScalarCombobox,\n ScalarVirtualText,\n} from '@scalar/components'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type AvailableClients } from '@scalar/snippetz'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { operationToHar } from '@v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport HttpMethod from '@/v2/blocks/operation-code-sample/components/HttpMethod.vue'\nimport { filterClientsByQuery } from '@/v2/blocks/operation-code-sample/helpers/filter-clients-by-query'\nimport { findClient } from '@/v2/blocks/operation-code-sample/helpers/find-client'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '@/v2/blocks/operation-code-sample/types'\nimport type { SecuritySchemeObjectSecret } from '@/v2/blocks/scalar-auth-selector-block/helpers/secret-types'\n\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport ExamplePicker from './ExamplePicker.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n} = defineProps<OperationCodeSampleProps>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/** The currently selected example key with v-model support */\nconst selectedExampleKey = defineModel<string>('selectedExample', {\n default: '',\n})\n\n// Set default value to the first example\nonBeforeMount(() => {\n selectedExampleKey.value ||= Object.keys(requestBodyExamples.value)[0] ?? ''\n})\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: selectedExampleKey.value,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExampleKey.value,\n globalCookies,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clients.length\"\n #actions>\n <ScalarCombobox\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n v-model=\"selectedExampleKey\"\n :examples=\"requestBodyExamples\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"OperationCodeSample.vue.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type OperationCodeSampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown\n *\n * @defaults to shell/curl or a custom sample if one is available\n */\n selectedClient?: AvailableClients[number]\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n /**\n * When the request body schema uses oneOf/anyOf, use these selected variants\n * for the example snippet (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event scalar-update-selected-example - removed for now, we can bring it back when we need it\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n ScalarCodeBlock,\n ScalarCombobox,\n ScalarVirtualText,\n} from '@scalar/components'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type AvailableClients } from '@scalar/snippetz'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { operationToHar } from '@v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport HttpMethod from '@/v2/blocks/operation-code-sample/components/HttpMethod.vue'\nimport { filterClientsByQuery } from '@/v2/blocks/operation-code-sample/helpers/filter-clients-by-query'\nimport { findClient } from '@/v2/blocks/operation-code-sample/helpers/find-client'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '@/v2/blocks/operation-code-sample/types'\nimport type { SecuritySchemeObjectSecret } from '@/v2/blocks/scalar-auth-selector-block/helpers/secret-types'\n\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport ExamplePicker from './ExamplePicker.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n requestBodyCompositionSelection,\n} = defineProps<OperationCodeSampleProps>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/** The currently selected example key with v-model support */\nconst selectedExampleKey = defineModel<string>('selectedExample', {\n default: '',\n})\n\n// Set default value to the first example\nonBeforeMount(() => {\n selectedExampleKey.value ||= Object.keys(requestBodyExamples.value)[0] ?? ''\n})\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: selectedExampleKey.value,\n requestBodyCompositionSelection,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExampleKey.value,\n globalCookies,\n requestBodyCompositionSelection,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clients.length\"\n #actions>\n <ScalarCombobox\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n v-model=\"selectedExampleKey\"\n :examples=\"requestBodyExamples\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":""}
|
|
@@ -37,7 +37,8 @@ var OperationCodeSample_vue_vue_type_script_setup_true_lang_default = /* @__PURE
|
|
|
37
37
|
fallback: { type: Boolean },
|
|
38
38
|
generateLabel: { type: Function },
|
|
39
39
|
isWebhook: { type: Boolean },
|
|
40
|
-
globalCookies: {}
|
|
40
|
+
globalCookies: {},
|
|
41
|
+
requestBodyCompositionSelection: {}
|
|
41
42
|
}, {
|
|
42
43
|
"selectedExample": { default: "" },
|
|
43
44
|
"selectedExampleModifiers": {}
|
|
@@ -75,7 +76,8 @@ var OperationCodeSample_vue_vue_type_script_setup_true_lang_default = /* @__PURE
|
|
|
75
76
|
operation: __props.operation,
|
|
76
77
|
method: __props.method,
|
|
77
78
|
path: __props.path,
|
|
78
|
-
example: selectedExampleKey.value
|
|
79
|
+
example: selectedExampleKey.value,
|
|
80
|
+
requestBodyCompositionSelection: __props.requestBodyCompositionSelection
|
|
79
81
|
});
|
|
80
82
|
} catch (error) {
|
|
81
83
|
console.error("[webhookHar]", error);
|
|
@@ -96,7 +98,8 @@ var OperationCodeSample_vue_vue_type_script_setup_true_lang_default = /* @__PURE
|
|
|
96
98
|
server: __props.selectedServer,
|
|
97
99
|
securitySchemes: __props.securitySchemes,
|
|
98
100
|
example: selectedExampleKey.value,
|
|
99
|
-
globalCookies: __props.globalCookies
|
|
101
|
+
globalCookies: __props.globalCookies,
|
|
102
|
+
requestBodyCompositionSelection: __props.requestBodyCompositionSelection
|
|
100
103
|
});
|
|
101
104
|
});
|
|
102
105
|
/** The language for the code block, used for syntax highlighting */
|
package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationCodeSample.vue.script.js","names":["$slots"],"sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type OperationCodeSampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown\n *\n * @defaults to shell/curl or a custom sample if one is available\n */\n selectedClient?: AvailableClients[number]\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event scalar-update-selected-example - removed for now, we can bring it back when we need it\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n ScalarCodeBlock,\n ScalarCombobox,\n ScalarVirtualText,\n} from '@scalar/components'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type AvailableClients } from '@scalar/snippetz'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { operationToHar } from '@v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport HttpMethod from '@/v2/blocks/operation-code-sample/components/HttpMethod.vue'\nimport { filterClientsByQuery } from '@/v2/blocks/operation-code-sample/helpers/filter-clients-by-query'\nimport { findClient } from '@/v2/blocks/operation-code-sample/helpers/find-client'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '@/v2/blocks/operation-code-sample/types'\nimport type { SecuritySchemeObjectSecret } from '@/v2/blocks/scalar-auth-selector-block/helpers/secret-types'\n\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport ExamplePicker from './ExamplePicker.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n} = defineProps<OperationCodeSampleProps>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/** The currently selected example key with v-model support */\nconst selectedExampleKey = defineModel<string>('selectedExample', {\n default: '',\n})\n\n// Set default value to the first example\nonBeforeMount(() => {\n selectedExampleKey.value ||= Object.keys(requestBodyExamples.value)[0] ?? ''\n})\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: selectedExampleKey.value,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExampleKey.value,\n globalCookies,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clients.length\"\n #actions>\n <ScalarCombobox\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n v-model=\"selectedExampleKey\"\n :examples=\"requestBodyExamples\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OperationCodeSample.vue.script.js","names":["$slots"],"sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type OperationCodeSampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown\n *\n * @defaults to shell/curl or a custom sample if one is available\n */\n selectedClient?: AvailableClients[number]\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n /**\n * When the request body schema uses oneOf/anyOf, use these selected variants\n * for the example snippet (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event scalar-update-selected-example - removed for now, we can bring it back when we need it\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n ScalarCodeBlock,\n ScalarCombobox,\n ScalarVirtualText,\n} from '@scalar/components'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type AvailableClients } from '@scalar/snippetz'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { operationToHar } from '@v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport HttpMethod from '@/v2/blocks/operation-code-sample/components/HttpMethod.vue'\nimport { filterClientsByQuery } from '@/v2/blocks/operation-code-sample/helpers/filter-clients-by-query'\nimport { findClient } from '@/v2/blocks/operation-code-sample/helpers/find-client'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '@/v2/blocks/operation-code-sample/types'\nimport type { SecuritySchemeObjectSecret } from '@/v2/blocks/scalar-auth-selector-block/helpers/secret-types'\n\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport ExamplePicker from './ExamplePicker.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n requestBodyCompositionSelection,\n} = defineProps<OperationCodeSampleProps>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/** The currently selected example key with v-model support */\nconst selectedExampleKey = defineModel<string>('selectedExample', {\n default: '',\n})\n\n// Set default value to the first example\nonBeforeMount(() => {\n selectedExampleKey.value ||= Object.keys(requestBodyExamples.value)[0] ?? ''\n})\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: selectedExampleKey.value,\n requestBodyCompositionSelection,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExampleKey.value,\n globalCookies,\n requestBodyCompositionSelection,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clients.length\"\n #actions>\n <ScalarCombobox\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n v-model=\"selectedExampleKey\"\n :examples=\"requestBodyExamples\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -28,8 +28,10 @@ type GenerateCodeSnippetProps = {
|
|
|
28
28
|
globalCookies?: XScalarCookie[];
|
|
29
29
|
/** Whether to include default headers (e.g., Accept, Content-Type) automatically. */
|
|
30
30
|
includeDefaultHeaders?: boolean;
|
|
31
|
+
/** Selected oneOf/anyOf variants for nested request body example generation. */
|
|
32
|
+
requestBodyCompositionSelection?: Record<string, number>;
|
|
31
33
|
};
|
|
32
34
|
/** Generate the code snippet for the selected example OR operation */
|
|
33
|
-
export declare const generateCodeSnippet: ({ clientId, customCodeSamples, includeDefaultHeaders, operation, method, path, example, contentType, server, securitySchemes, globalCookies, }: GenerateCodeSnippetProps) => string;
|
|
35
|
+
export declare const generateCodeSnippet: ({ clientId, customCodeSamples, includeDefaultHeaders, operation, method, path, example, contentType, server, securitySchemes, globalCookies, requestBodyCompositionSelection, }: GenerateCodeSnippetProps) => string;
|
|
34
36
|
export {};
|
|
35
37
|
//# sourceMappingURL=generate-code-snippet.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-code-snippet.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/generate-code-snippet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,kBAAkB,CAAA;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sDAAsD,CAAA;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAGjH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6DAA6D,CAAA;AAG7G,OAAO,EAAE,KAAK,kBAAkB,EAAoB,MAAM,2BAA2B,CAAA;AAErF,KAAK,wBAAwB,GAAG;IAC9B,wGAAwG;IACxG,QAAQ,EAAE,eAAe,GAAG,kBAAkB,GAAG,SAAS,CAAA;IAC1D,qFAAqF;IACrF,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,mFAAmF;IACnF,iBAAiB,EAAE,WAAW,EAAE,CAAA;IAChC,0EAA0E;IAC1E,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,gEAAgE;IAChE,MAAM,EAAE,UAAU,CAAA;IAClB,wEAAwE;IACxE,SAAS,EAAE,eAAe,CAAA;IAC1B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,iFAAiF;IACjF,eAAe,EAAE,0BAA0B,EAAE,CAAA;IAC7C,mEAAmE;IACnE,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,mCAAmC;IACnC,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;IAC/B,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"generate-code-snippet.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/generate-code-snippet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,kBAAkB,CAAA;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sDAAsD,CAAA;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAGjH,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6DAA6D,CAAA;AAG7G,OAAO,EAAE,KAAK,kBAAkB,EAAoB,MAAM,2BAA2B,CAAA;AAErF,KAAK,wBAAwB,GAAG;IAC9B,wGAAwG;IACxG,QAAQ,EAAE,eAAe,GAAG,kBAAkB,GAAG,SAAS,CAAA;IAC1D,qFAAqF;IACrF,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,mFAAmF;IACnF,iBAAiB,EAAE,WAAW,EAAE,CAAA;IAChC,0EAA0E;IAC1E,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,gEAAgE;IAChE,MAAM,EAAE,UAAU,CAAA;IAClB,wEAAwE;IACxE,SAAS,EAAE,eAAe,CAAA;IAC1B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,iFAAiF;IACjF,eAAe,EAAE,0BAA0B,EAAE,CAAA;IAC7C,mEAAmE;IACnE,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,mCAAmC;IACnC,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;IAC/B,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,gFAAgF;IAChF,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzD,CAAA;AAED,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,GAAI,iLAajC,wBAAwB,KAAG,MAwC7B,CAAA"}
|
|
@@ -3,7 +3,7 @@ import { generateCustomId } from "./generate-client-options.js";
|
|
|
3
3
|
import { getSnippet } from "../../../../views/Components/CodeSnippet/helpers/get-snippet.js";
|
|
4
4
|
//#region src/v2/blocks/operation-code-sample/helpers/generate-code-snippet.ts
|
|
5
5
|
/** Generate the code snippet for the selected example OR operation */
|
|
6
|
-
var generateCodeSnippet = ({ clientId, customCodeSamples, includeDefaultHeaders = false, operation, method, path, example, contentType, server, securitySchemes, globalCookies }) => {
|
|
6
|
+
var generateCodeSnippet = ({ clientId, customCodeSamples, includeDefaultHeaders = false, operation, method, path, example, contentType, server, securitySchemes, globalCookies, requestBodyCompositionSelection }) => {
|
|
7
7
|
try {
|
|
8
8
|
if (!clientId) return "";
|
|
9
9
|
if (clientId.startsWith("custom")) return customCodeSamples.find((example) => generateCustomId(example) === clientId)?.source ?? "Custom example not found";
|
|
@@ -16,7 +16,8 @@ var generateCodeSnippet = ({ clientId, customCodeSamples, includeDefaultHeaders
|
|
|
16
16
|
securitySchemes,
|
|
17
17
|
example,
|
|
18
18
|
globalCookies,
|
|
19
|
-
includeDefaultHeaders
|
|
19
|
+
includeDefaultHeaders,
|
|
20
|
+
requestBodyCompositionSelection
|
|
20
21
|
});
|
|
21
22
|
const [targetKey, clientKey] = clientId.split("/");
|
|
22
23
|
const [error, payload] = getSnippet(targetKey, clientKey, harRequest);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-code-snippet.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/generate-code-snippet.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { AvailableClient, ClientId, TargetId } from '@scalar/snippetz'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport { operationToHar } from '@/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport type { SecuritySchemeObjectSecret } from '@/v2/blocks/scalar-auth-selector-block/helpers/secret-types'\nimport { getSnippet } from '@/views/Components/CodeSnippet/helpers/get-snippet'\n\nimport { type CustomCodeSampleId, generateCustomId } from './generate-client-options'\n\ntype GenerateCodeSnippetProps = {\n /** The selected client/language for code generation (e.g., 'node/fetch') or a custom code sample ID. */\n clientId: AvailableClient | CustomCodeSampleId | undefined\n /** The Content-Type header value for the request body (e.g., 'application/json'). */\n contentType: string | undefined\n /** Array of custom code samples defined in the OpenAPI x-codeSamples extension. */\n customCodeSamples: XCodeSample[]\n /** The specific example value to use when generating the code snippet. */\n example: string | undefined\n /** The HTTP method for the operation (e.g., GET, POST, PUT). */\n method: HttpMethod\n /** The OpenAPI operation object containing request/response details. */\n operation: OperationObject\n /** The API endpoint path (e.g., '/users/{id}'). */\n path: string\n /** Array of security schemes to apply to the request (e.g., API keys, OAuth). */\n securitySchemes: SecuritySchemeObjectSecret[]\n /** The server object defining the base URL for the API request. */\n server: ServerObject | null\n /** Workspace + document cookies */\n globalCookies?: XScalarCookie[]\n /** Whether to include default headers (e.g., Accept, Content-Type) automatically. */\n includeDefaultHeaders?: boolean\n}\n\n/** Generate the code snippet for the selected example OR operation */\nexport const generateCodeSnippet = ({\n clientId,\n customCodeSamples,\n includeDefaultHeaders = false,\n operation,\n method,\n path,\n example,\n contentType,\n server,\n securitySchemes,\n globalCookies,\n}: GenerateCodeSnippetProps): string => {\n try {\n if (!clientId) {\n return ''\n }\n\n // Use the selected custom example\n if (clientId.startsWith('custom')) {\n return (\n customCodeSamples.find((example) => generateCustomId(example) === clientId)?.source ??\n 'Custom example not found'\n )\n }\n\n const harRequest = operationToHar({\n operation,\n contentType,\n method,\n path,\n server,\n securitySchemes,\n example,\n globalCookies,\n includeDefaultHeaders,\n })\n\n const [targetKey, clientKey] = clientId.split('/') as [TargetId, ClientId<TargetId>]\n\n const [error, payload] = getSnippet(targetKey, clientKey, harRequest)\n if (error) {\n console.error('[generateCodeSnippet]', error)\n return error.message ?? 'Error generating code snippet'\n }\n\n return payload\n } catch (error) {\n console.error('[generateCodeSnippet]', error)\n return 'Error generating code snippet'\n }\n}\n"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"generate-code-snippet.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/generate-code-snippet.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { AvailableClient, ClientId, TargetId } from '@scalar/snippetz'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport { operationToHar } from '@/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport type { SecuritySchemeObjectSecret } from '@/v2/blocks/scalar-auth-selector-block/helpers/secret-types'\nimport { getSnippet } from '@/views/Components/CodeSnippet/helpers/get-snippet'\n\nimport { type CustomCodeSampleId, generateCustomId } from './generate-client-options'\n\ntype GenerateCodeSnippetProps = {\n /** The selected client/language for code generation (e.g., 'node/fetch') or a custom code sample ID. */\n clientId: AvailableClient | CustomCodeSampleId | undefined\n /** The Content-Type header value for the request body (e.g., 'application/json'). */\n contentType: string | undefined\n /** Array of custom code samples defined in the OpenAPI x-codeSamples extension. */\n customCodeSamples: XCodeSample[]\n /** The specific example value to use when generating the code snippet. */\n example: string | undefined\n /** The HTTP method for the operation (e.g., GET, POST, PUT). */\n method: HttpMethod\n /** The OpenAPI operation object containing request/response details. */\n operation: OperationObject\n /** The API endpoint path (e.g., '/users/{id}'). */\n path: string\n /** Array of security schemes to apply to the request (e.g., API keys, OAuth). */\n securitySchemes: SecuritySchemeObjectSecret[]\n /** The server object defining the base URL for the API request. */\n server: ServerObject | null\n /** Workspace + document cookies */\n globalCookies?: XScalarCookie[]\n /** Whether to include default headers (e.g., Accept, Content-Type) automatically. */\n includeDefaultHeaders?: boolean\n /** Selected oneOf/anyOf variants for nested request body example generation. */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/** Generate the code snippet for the selected example OR operation */\nexport const generateCodeSnippet = ({\n clientId,\n customCodeSamples,\n includeDefaultHeaders = false,\n operation,\n method,\n path,\n example,\n contentType,\n server,\n securitySchemes,\n globalCookies,\n requestBodyCompositionSelection,\n}: GenerateCodeSnippetProps): string => {\n try {\n if (!clientId) {\n return ''\n }\n\n // Use the selected custom example\n if (clientId.startsWith('custom')) {\n return (\n customCodeSamples.find((example) => generateCustomId(example) === clientId)?.source ??\n 'Custom example not found'\n )\n }\n\n const harRequest = operationToHar({\n operation,\n contentType,\n method,\n path,\n server,\n securitySchemes,\n example,\n globalCookies,\n includeDefaultHeaders,\n requestBodyCompositionSelection,\n })\n\n const [targetKey, clientKey] = clientId.split('/') as [TargetId, ClientId<TargetId>]\n\n const [error, payload] = getSnippet(targetKey, clientKey, harRequest)\n if (error) {\n console.error('[generateCodeSnippet]', error)\n return error.message ?? 'Error generating code snippet'\n }\n\n return payload\n } catch (error) {\n console.error('[generateCodeSnippet]', error)\n return 'Error generating code snippet'\n }\n}\n"],"mappings":";;;;;AAwCA,IAAa,uBAAuB,EAClC,UACA,mBACA,wBAAwB,OACxB,WACA,QACA,MACA,SACA,aACA,QACA,iBACA,eACA,sCACsC;AACtC,KAAI;AACF,MAAI,CAAC,SACH,QAAO;AAIT,MAAI,SAAS,WAAW,SAAS,CAC/B,QACE,kBAAkB,MAAM,YAAY,iBAAiB,QAAQ,KAAK,SAAS,EAAE,UAC7E;EAIJ,MAAM,aAAa,eAAe;GAChC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;EAEF,MAAM,CAAC,WAAW,aAAa,SAAS,MAAM,IAAI;EAElD,MAAM,CAAC,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW;AACrE,MAAI,OAAO;AACT,WAAQ,MAAM,yBAAyB,MAAM;AAC7C,UAAO,MAAM,WAAW;;AAG1B,SAAO;UACA,OAAO;AACd,UAAQ,MAAM,yBAAyB,MAAM;AAC7C,SAAO"}
|
|
@@ -10,6 +10,8 @@ type GetExampleFromSchemaOptions = {
|
|
|
10
10
|
variables?: Record<string, unknown>;
|
|
11
11
|
/** Whether to omit empty and optional properties. */
|
|
12
12
|
omitEmptyAndOptionalProperties?: boolean;
|
|
13
|
+
/** Selected oneOf/anyOf variants keyed by schema path. */
|
|
14
|
+
compositionSelection?: Record<string, number>;
|
|
13
15
|
};
|
|
14
16
|
/**
|
|
15
17
|
* Generate an example value from a given OpenAPI SchemaObject.
|
|
@@ -26,11 +28,13 @@ type GetExampleFromSchemaOptions = {
|
|
|
26
28
|
* @param name - The name of the property being processed.
|
|
27
29
|
* @returns An example value for the given schema.
|
|
28
30
|
*/
|
|
29
|
-
export declare const getExampleFromSchema: (schema: SchemaObject, options?: GetExampleFromSchemaOptions, { level, parentSchema, name, seen, }?: Partial<{
|
|
31
|
+
export declare const getExampleFromSchema: (schema: SchemaObject, options?: GetExampleFromSchemaOptions, { level, parentSchema, name, seen, schemaPath, }?: Partial<{
|
|
30
32
|
level: number;
|
|
31
33
|
parentSchema: SchemaObject;
|
|
32
34
|
name: string;
|
|
33
35
|
seen: WeakSet<object>;
|
|
36
|
+
/** Internal traversal path used to resolve nested composition selections. */
|
|
37
|
+
schemaPath: string[];
|
|
34
38
|
}>) => unknown;
|
|
35
39
|
export {};
|
|
36
40
|
//# sourceMappingURL=get-example-from-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-example-from-schema.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/get-example-from-schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;
|
|
1
|
+
{"version":3,"file":"get-example-from-schema.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/get-example-from-schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAwfhG,KAAK,2BAA2B,GAAG;IACjC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,qDAAqD;IACrD,8BAA8B,CAAC,EAAE,OAAO,CAAA;IACxC,0DAA0D;IAC1D,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC9C,CAAA;AAeD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,YAAY,EACpB,UAAU,2BAA2B,EACrC,mDAMG,OAAO,CAAC;IACT,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,YAAY,CAAA;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IACrB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,CAAM,KACN,OAiKF,CAAA"}
|
|
@@ -126,11 +126,17 @@ var mergeExamples = (baseValue, newValue) => {
|
|
|
126
126
|
};
|
|
127
127
|
return newValue;
|
|
128
128
|
};
|
|
129
|
+
var getCompositionSelectionKey = (schemaPath, composition) => [...schemaPath, composition].join(".");
|
|
130
|
+
var getCompositionSelectionIndex = (schemaPath, composition, options, length) => {
|
|
131
|
+
const rawIndex = options?.compositionSelection?.[getCompositionSelectionKey(schemaPath, composition)];
|
|
132
|
+
if (typeof rawIndex !== "number" || Number.isNaN(rawIndex)) return;
|
|
133
|
+
return Math.max(0, Math.min(rawIndex, length - 1));
|
|
134
|
+
};
|
|
129
135
|
/**
|
|
130
136
|
* Build an example for an object schema, including properties, patternProperties,
|
|
131
137
|
* additionalProperties, and composition (allOf/oneOf/anyOf) merging.
|
|
132
138
|
*/
|
|
133
|
-
var handleObjectSchema = (schema, options, level, seen, cacheKey) => {
|
|
139
|
+
var handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath) => {
|
|
134
140
|
const response = {};
|
|
135
141
|
if ("properties" in schema && schema.properties) {
|
|
136
142
|
const propertyNames = Object.keys(schema.properties);
|
|
@@ -144,6 +150,7 @@ var handleObjectSchema = (schema, options, level, seen, cacheKey) => {
|
|
|
144
150
|
level: level + 1,
|
|
145
151
|
parentSchema: schema,
|
|
146
152
|
name: propertyName,
|
|
153
|
+
schemaPath: [...schemaPath, propertyName],
|
|
147
154
|
seen
|
|
148
155
|
});
|
|
149
156
|
if (typeof value !== "undefined") response[propertyXmlName ?? propertyName] = value;
|
|
@@ -156,6 +163,7 @@ var handleObjectSchema = (schema, options, level, seen, cacheKey) => {
|
|
|
156
163
|
level: level + 1,
|
|
157
164
|
parentSchema: schema,
|
|
158
165
|
name: pattern,
|
|
166
|
+
schemaPath: [...schemaPath, pattern],
|
|
159
167
|
seen
|
|
160
168
|
});
|
|
161
169
|
}
|
|
@@ -167,20 +175,23 @@ var handleObjectSchema = (schema, options, level, seen, cacheKey) => {
|
|
|
167
175
|
const additionalName = hasCustomName ? additional["x-additionalPropertiesName"].trim() : DEFAULT_ADDITIONAL_PROPERTIES_NAME;
|
|
168
176
|
const additionalValue = isAnyType ? "anything" : typeof additional === "object" ? getExampleFromSchema(additional, options, {
|
|
169
177
|
level: level + 1,
|
|
178
|
+
schemaPath: [...schemaPath, additionalName],
|
|
170
179
|
seen
|
|
171
180
|
}) : "anything";
|
|
172
181
|
if (propertyNamesEnum && propertyNamesEnum.length > 0) response[String(propertyNamesEnum[0])] = additionalValue;
|
|
173
182
|
else response[additionalName] = additionalValue;
|
|
174
183
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
+
const compositionKeyword = schema.oneOf ? "oneOf" : schema.anyOf ? "anyOf" : void 0;
|
|
185
|
+
const oneOfAnyOf = compositionKeyword ? schema[compositionKeyword] : void 0;
|
|
186
|
+
if (compositionKeyword && oneOfAnyOf?.length) {
|
|
187
|
+
const index = getCompositionSelectionIndex(schemaPath, compositionKeyword, options, oneOfAnyOf.length) ?? 0;
|
|
188
|
+
const chosen = resolve.schema(oneOfAnyOf[index]);
|
|
189
|
+
if (chosen) Object.assign(response, getExampleFromSchema(chosen, options, {
|
|
190
|
+
level: level + 1,
|
|
191
|
+
schemaPath,
|
|
192
|
+
seen
|
|
193
|
+
}));
|
|
194
|
+
} else if (Array.isArray(schema.allOf) && schema.allOf.length > 0) {
|
|
184
195
|
let merged = response;
|
|
185
196
|
for (const item of schema.allOf) {
|
|
186
197
|
const ex = getExampleFromSchema(resolve.schema(item), options, {
|
|
@@ -200,8 +211,9 @@ var handleObjectSchema = (schema, options, level, seen, cacheKey) => {
|
|
|
200
211
|
return cache(schema, response, cacheKey);
|
|
201
212
|
};
|
|
202
213
|
/** Build an example for an array schema, including items, allOf, oneOf/anyOf, and XML wrapping */
|
|
203
|
-
var handleArraySchema = (schema, options, level, seen, cacheKey) => {
|
|
214
|
+
var handleArraySchema = (schema, options, level, seen, cacheKey, schemaPath) => {
|
|
204
215
|
const items = "items" in schema ? resolve.schema(schema.items) : void 0;
|
|
216
|
+
const itemsSchemaPath = [...schemaPath, "items"];
|
|
205
217
|
const itemsXmlTagName = items && typeof items === "object" && "xml" in items ? items.xml?.name : void 0;
|
|
206
218
|
const wrapItems = !!(options?.xml && "xml" in schema && schema.xml?.wrapped && itemsXmlTagName);
|
|
207
219
|
if (schema.example !== void 0) return cache(schema, wrapItems ? { [itemsXmlTagName]: schema.example } : schema.example, cacheKey);
|
|
@@ -216,6 +228,7 @@ var handleArraySchema = (schema, options, level, seen, cacheKey) => {
|
|
|
216
228
|
}, options, {
|
|
217
229
|
level: level + 1,
|
|
218
230
|
parentSchema: schema,
|
|
231
|
+
schemaPath: itemsSchemaPath,
|
|
219
232
|
seen
|
|
220
233
|
});
|
|
221
234
|
return cache(schema, wrapItems ? [{ [itemsXmlTagName]: merged }] : [merged], cacheKey);
|
|
@@ -223,16 +236,19 @@ var handleArraySchema = (schema, options, level, seen, cacheKey) => {
|
|
|
223
236
|
const examples = allOf.map((s) => getExampleFromSchema(resolve.schema(s), options, {
|
|
224
237
|
level: level + 1,
|
|
225
238
|
parentSchema: schema,
|
|
239
|
+
schemaPath: itemsSchemaPath,
|
|
226
240
|
seen
|
|
227
241
|
})).filter(isDefined);
|
|
228
242
|
return cache(schema, wrapItems ? examples.map((e) => ({ [itemsXmlTagName]: e })) : examples, cacheKey);
|
|
229
243
|
}
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const
|
|
244
|
+
const compositionKeyword = items.oneOf ? "oneOf" : items.anyOf ? "anyOf" : void 0;
|
|
245
|
+
const union = compositionKeyword ? items[compositionKeyword] : void 0;
|
|
246
|
+
if (compositionKeyword && union && union.length > 0) {
|
|
247
|
+
const selected = union[getCompositionSelectionIndex(itemsSchemaPath, compositionKeyword, options, union.length) ?? 0];
|
|
248
|
+
const ex = getExampleFromSchema(resolve.schema(selected), options, {
|
|
234
249
|
level: level + 1,
|
|
235
250
|
parentSchema: schema,
|
|
251
|
+
schemaPath: itemsSchemaPath,
|
|
236
252
|
seen
|
|
237
253
|
});
|
|
238
254
|
return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex], cacheKey);
|
|
@@ -243,6 +259,7 @@ var handleArraySchema = (schema, options, level, seen, cacheKey) => {
|
|
|
243
259
|
if (items && typeof items === "object" && ("type" in items && items.type || isObject || isArray)) {
|
|
244
260
|
const ex = getExampleFromSchema(items, options, {
|
|
245
261
|
level: level + 1,
|
|
262
|
+
schemaPath: itemsSchemaPath,
|
|
246
263
|
seen
|
|
247
264
|
});
|
|
248
265
|
return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex], cacheKey);
|
|
@@ -281,7 +298,8 @@ var createOptionsCacheKey = (options) => JSON.stringify({
|
|
|
281
298
|
xml: options?.xml,
|
|
282
299
|
mode: options?.mode,
|
|
283
300
|
variables: options?.variables,
|
|
284
|
-
omitEmptyAndOptionalProperties: options?.omitEmptyAndOptionalProperties
|
|
301
|
+
omitEmptyAndOptionalProperties: options?.omitEmptyAndOptionalProperties,
|
|
302
|
+
compositionSelection: options?.compositionSelection ? Object.entries(options.compositionSelection).sort(([a], [b]) => a.localeCompare(b)) : void 0
|
|
285
303
|
});
|
|
286
304
|
/**
|
|
287
305
|
* Generate an example value from a given OpenAPI SchemaObject.
|
|
@@ -298,14 +316,14 @@ var createOptionsCacheKey = (options) => JSON.stringify({
|
|
|
298
316
|
* @param name - The name of the property being processed.
|
|
299
317
|
* @returns An example value for the given schema.
|
|
300
318
|
*/
|
|
301
|
-
var getExampleFromSchema = (schema, options, { level = 0, parentSchema, name, seen = /* @__PURE__ */ new WeakSet() } = {}) => {
|
|
319
|
+
var getExampleFromSchema = (schema, options, { level = 0, parentSchema, name, seen = /* @__PURE__ */ new WeakSet(), schemaPath = [] } = {}) => {
|
|
302
320
|
const _schema = resolve.schema(schema);
|
|
303
321
|
if (!isDefined(_schema)) return;
|
|
304
322
|
const targetValue = getSchemaCacheTarget(_schema);
|
|
305
323
|
if (seen.has(targetValue)) return;
|
|
306
324
|
seen.add(targetValue);
|
|
307
|
-
/** Make the cache key unique per options */
|
|
308
|
-
const cacheKey = createOptionsCacheKey(options);
|
|
325
|
+
/** Make the cache key unique per options and schema path */
|
|
326
|
+
const cacheKey = createOptionsCacheKey(options) + (schemaPath.length > 0 ? `:path:${schemaPath.join(".")}` : "");
|
|
309
327
|
const cached = resultCache.get(targetValue)?.get(cacheKey);
|
|
310
328
|
if (typeof cached !== "undefined") {
|
|
311
329
|
seen.delete(targetValue);
|
|
@@ -352,12 +370,12 @@ var getExampleFromSchema = (schema, options, { level = 0, parentSchema, name, se
|
|
|
352
370
|
return cache(_schema, _schema.enum[0], cacheKey);
|
|
353
371
|
}
|
|
354
372
|
if ("properties" in _schema || "type" in _schema && _schema.type === "object") {
|
|
355
|
-
const result = handleObjectSchema(_schema, options, level, seen, cacheKey);
|
|
373
|
+
const result = handleObjectSchema(_schema, options, level, seen, cacheKey, schemaPath);
|
|
356
374
|
seen.delete(targetValue);
|
|
357
375
|
return result;
|
|
358
376
|
}
|
|
359
377
|
if ("type" in _schema && _schema.type === "array" || "items" in _schema) {
|
|
360
|
-
const result = handleArraySchema(_schema, options, level, seen, cacheKey);
|
|
378
|
+
const result = handleArraySchema(_schema, options, level, seen, cacheKey, schemaPath);
|
|
361
379
|
seen.delete(targetValue);
|
|
362
380
|
return result;
|
|
363
381
|
}
|
|
@@ -366,14 +384,21 @@ var getExampleFromSchema = (schema, options, { level = 0, parentSchema, name, se
|
|
|
366
384
|
seen.delete(targetValue);
|
|
367
385
|
return cache(_schema, primitive, cacheKey);
|
|
368
386
|
}
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
387
|
+
const compositionKeyword = _schema.oneOf ? "oneOf" : _schema.anyOf ? "anyOf" : void 0;
|
|
388
|
+
const discriminate = compositionKeyword ? _schema[compositionKeyword] : void 0;
|
|
389
|
+
if (compositionKeyword && Array.isArray(discriminate) && discriminate.length > 0) {
|
|
390
|
+
const index = getCompositionSelectionIndex(schemaPath, compositionKeyword, options, discriminate.length);
|
|
391
|
+
const candidate = index !== void 0 ? discriminate[index] : discriminate.find((item) => {
|
|
372
392
|
const resolved = resolve.schema(item);
|
|
373
|
-
|
|
393
|
+
return resolved && (!("type" in resolved) || resolved.type !== "null");
|
|
394
|
+
});
|
|
395
|
+
if (candidate) {
|
|
396
|
+
const resolved = resolve.schema(candidate);
|
|
397
|
+
if (resolved) {
|
|
374
398
|
seen.delete(targetValue);
|
|
375
399
|
return cache(_schema, getExampleFromSchema(resolved, options, {
|
|
376
400
|
level: level + 1,
|
|
401
|
+
schemaPath,
|
|
377
402
|
seen
|
|
378
403
|
}), cacheKey);
|
|
379
404
|
}
|
|
@@ -388,6 +413,7 @@ var getExampleFromSchema = (schema, options, { level = 0, parentSchema, name, se
|
|
|
388
413
|
const ex = getExampleFromSchema(item, options, {
|
|
389
414
|
level: level + 1,
|
|
390
415
|
parentSchema: _schema,
|
|
416
|
+
schemaPath,
|
|
391
417
|
seen
|
|
392
418
|
});
|
|
393
419
|
if (merged === void 0) merged = ex;
|