@scalar/workspace-store 0.59.0 → 0.61.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 +61 -0
- package/README.md +6 -0
- package/dist/channel-example/build-connection-url.d.ts.map +1 -1
- package/dist/channel-example/build-connection-url.js +3 -3
- package/dist/channel-example/dedupe-requirements.d.ts +1 -1
- package/dist/channel-example/get-async-api-protocols.js +2 -2
- package/dist/channel-example/get-asyncapi-security-requirements.d.ts +1 -1
- package/dist/channel-example/get-channel-connection-security.d.ts +1 -1
- package/dist/channel-example/get-channel-operations.d.ts.map +1 -1
- package/dist/channel-example/get-channel-operations.js +4 -1
- package/dist/channel-example/get-channel-parameters.d.ts.map +1 -1
- package/dist/channel-example/get-channel-parameters.js +3 -1
- package/dist/channel-example/resolve-channel.d.ts.map +1 -1
- package/dist/channel-example/resolve-channel.js +2 -0
- package/dist/channel-example/resolve-operation-channel.d.ts.map +1 -1
- package/dist/channel-example/resolve-operation-channel.js +4 -0
- package/dist/channel-example/resolve-operation-with-traits.js +2 -2
- package/dist/channel-example/servers.d.ts.map +1 -1
- package/dist/channel-example/servers.js +3 -1
- package/dist/channel-example/types.d.ts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +3 -3
- package/dist/entities/auth/schema.d.ts +470 -20
- package/dist/entities/auth/schema.d.ts.map +1 -1
- package/dist/entities/auth/schema.js +2 -2
- package/dist/events/definitions/auth.d.ts +2 -2
- package/dist/events/definitions/document.d.ts +1 -1
- package/dist/events/definitions/operation.d.ts +3 -2
- package/dist/events/definitions/operation.d.ts.map +1 -1
- package/dist/events/definitions/server.d.ts +1 -1
- package/dist/events/old-definitions.d.ts +1 -1
- package/dist/helpers/create-chunk-writer.d.ts +6 -0
- package/dist/helpers/create-chunk-writer.d.ts.map +1 -0
- package/dist/helpers/create-chunk-writer.js +44 -0
- package/dist/helpers/dynamic-ref.d.ts +13 -2
- package/dist/helpers/dynamic-ref.d.ts.map +1 -1
- package/dist/helpers/dynamic-ref.js +20 -7
- package/dist/helpers/encode-chunk-name.d.ts +3 -0
- package/dist/helpers/encode-chunk-name.d.ts.map +1 -0
- package/dist/helpers/encode-chunk-name.js +9 -0
- package/dist/helpers/for-each-path-item-operation.d.ts +2 -2
- package/dist/helpers/get-first-server.d.ts +1 -1
- package/dist/helpers/get-resolved-ref.d.ts +6 -1
- package/dist/helpers/get-resolved-ref.d.ts.map +1 -1
- package/dist/helpers/get-resolved-ref.js +3 -10
- package/dist/helpers/is-non-optional-security-requirement.d.ts +1 -1
- package/dist/helpers/merge-object.d.ts +2 -2
- package/dist/helpers/merge-object.d.ts.map +1 -1
- package/dist/helpers/merge-object.js +2 -5
- package/dist/mutators/auth.d.ts +1 -1
- package/dist/mutators/auth.d.ts.map +1 -1
- package/dist/mutators/auth.js +15 -6
- package/dist/mutators/index.d.ts +10 -10
- package/dist/mutators/operation/body.js +2 -2
- package/dist/mutators/operation/helpers/fetch-request-to-har.d.ts.map +1 -1
- package/dist/mutators/operation/helpers/fetch-request-to-har.js +12 -2
- package/dist/mutators/operation/helpers/har-to-operation.d.ts +1 -1
- package/dist/mutators/operation/helpers/har-to-operation.d.ts.map +1 -1
- package/dist/mutators/operation/helpers/har-to-operation.js +9 -5
- package/dist/mutators/operation/helpers/sync-path-parameters.d.ts +2 -2
- package/dist/mutators/operation/history.js +2 -2
- package/dist/mutators/operation/operation.d.ts.map +1 -1
- package/dist/mutators/operation/operation.js +4 -0
- package/dist/mutators/operation/parameters.js +1 -1
- package/dist/mutators/server.d.ts +3 -3
- package/dist/mutators/server.js +1 -1
- package/dist/mutators/tag.d.ts.map +1 -1
- package/dist/mutators/tag.js +4 -0
- package/dist/navigation/helpers/get-openapi-object.d.ts +1 -1
- package/dist/navigation/helpers/traverse-asyncapi-document.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-asyncapi-document.js +2 -2
- package/dist/navigation/helpers/traverse-description.d.ts +1 -1
- package/dist/navigation/helpers/traverse-document.d.ts +1 -1
- package/dist/navigation/helpers/traverse-examples.d.ts +12 -1
- package/dist/navigation/helpers/traverse-examples.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-examples.js +22 -1
- package/dist/navigation/helpers/traverse-paths.d.ts +1 -1
- package/dist/navigation/helpers/traverse-schemas.d.ts +1 -1
- package/dist/navigation/helpers/traverse-tags.d.ts +1 -1
- package/dist/navigation/helpers/traverse-webhooks.d.ts +1 -1
- package/dist/navigation/helpers/update-order-ids.d.ts +2 -2
- package/dist/navigation/index.d.ts +1 -0
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +1 -0
- package/dist/navigation/types.d.ts +1 -1
- package/dist/persistence/index.d.ts.map +1 -1
- package/dist/persistence/index.js +10 -10
- package/dist/persistence/indexdb.d.ts.map +1 -1
- package/dist/persistence/indexdb.js +7 -5
- package/dist/persistence/migrations/v2-team-to-local.d.ts.map +1 -1
- package/dist/persistence/migrations/v2-team-to-local.js +3 -4
- package/dist/plugins/bundler/index.d.ts +5 -2
- package/dist/plugins/bundler/index.d.ts.map +1 -1
- package/dist/plugins/bundler/index.js +24 -26
- package/dist/request-example/builder/body/build-request-body.d.ts +2 -1
- package/dist/request-example/builder/body/build-request-body.d.ts.map +1 -1
- package/dist/request-example/builder/body/build-request-body.js +65 -4
- package/dist/request-example/builder/body/encode-multipart-body.d.ts +9 -0
- package/dist/request-example/builder/body/encode-multipart-body.d.ts.map +1 -0
- package/dist/request-example/builder/body/encode-multipart-body.js +29 -0
- package/dist/request-example/builder/body/get-request-body-example.d.ts +1 -1
- package/dist/request-example/builder/body/get-selected-body-content-type.d.ts +1 -1
- package/dist/request-example/builder/body/schema-value-coercion.d.ts +1 -1
- package/dist/request-example/builder/body/schema-value-coercion.js +1 -1
- package/dist/request-example/builder/body/serialize-form-property.d.ts +1 -1
- package/dist/request-example/builder/body/serialize-multipart-array.d.ts +16 -0
- package/dist/request-example/builder/body/serialize-multipart-array.d.ts.map +1 -0
- package/dist/request-example/builder/body/serialize-multipart-array.js +37 -0
- package/dist/request-example/builder/build-request.d.ts.map +1 -1
- package/dist/request-example/builder/build-request.js +12 -7
- package/dist/request-example/builder/header/build-request-parameters.d.ts +1 -1
- package/dist/request-example/builder/header/build-request-parameters.d.ts.map +1 -1
- package/dist/request-example/builder/header/build-request-parameters.js +7 -1
- package/dist/request-example/builder/header/de-serialize-parameter.d.ts +1 -1
- package/dist/request-example/builder/header/de-serialize-parameter.d.ts.map +1 -1
- package/dist/request-example/builder/header/de-serialize-parameter.js +17 -6
- package/dist/request-example/builder/header/is-param-disabled.d.ts +1 -1
- package/dist/request-example/builder/header/serialize-parameter.d.ts.map +1 -1
- package/dist/request-example/builder/header/serialize-parameter.js +13 -14
- package/dist/request-example/builder/helpers/get-example-from-schema.d.ts +9 -1
- package/dist/request-example/builder/helpers/get-example-from-schema.d.ts.map +1 -1
- package/dist/request-example/builder/helpers/get-example-from-schema.js +255 -20
- package/dist/request-example/builder/helpers/get-example.d.ts +1 -1
- package/dist/request-example/builder/helpers/get-example.js +2 -2
- package/dist/request-example/builder/helpers/get-resolved-url.d.ts +1 -1
- package/dist/request-example/builder/helpers/get-server-variables.d.ts +1 -1
- package/dist/request-example/builder/index.d.ts +1 -0
- package/dist/request-example/builder/index.d.ts.map +1 -1
- package/dist/request-example/builder/index.js +1 -0
- package/dist/request-example/builder/request-factory.d.ts +2 -2
- package/dist/request-example/builder/security/broker-scheme-types.d.ts.map +1 -1
- package/dist/request-example/builder/security/broker-scheme-types.js +2 -2
- package/dist/request-example/builder/security/build-request-security.d.ts.map +1 -1
- package/dist/request-example/builder/security/build-request-security.js +3 -4
- package/dist/request-example/builder/security/secret-types.d.ts +13 -4
- package/dist/request-example/builder/security/secret-types.d.ts.map +1 -1
- package/dist/request-example/context/get-request-example-context.d.ts +3 -3
- package/dist/request-example/context/get-request-example-context.js +1 -1
- package/dist/request-example/context/headers.d.ts +1 -1
- package/dist/request-example/context/headers.js +1 -1
- package/dist/request-example/context/helpers/combine-params.d.ts +1 -1
- package/dist/request-example/context/security/extract-security-scheme-secrets.d.ts +16 -3
- package/dist/request-example/context/security/extract-security-scheme-secrets.d.ts.map +1 -1
- package/dist/request-example/context/security/extract-security-scheme-secrets.js +21 -19
- package/dist/request-example/context/security/get-security-requirements.d.ts +2 -2
- package/dist/request-example/context/security/get-security-schemes.d.ts +1 -1
- package/dist/request-example/context/security/get-selected-security.d.ts +1 -1
- package/dist/request-example/context/security/is-auth-optional.d.ts +1 -1
- package/dist/request-example/context/security/merge-security.d.ts +3 -3
- package/dist/request-example/context/security/merge-security.d.ts.map +1 -1
- package/dist/request-example/context/security/merge-security.js +40 -11
- package/dist/request-example/context/servers.d.ts +2 -2
- package/dist/request-example/functions.d.ts.map +1 -1
- package/dist/request-example/index.d.ts +1 -1
- package/dist/request-example/index.d.ts.map +1 -1
- package/dist/request-example/index.js +1 -1
- package/dist/resolve.d.ts +1 -1
- package/dist/resolve.js +1 -1
- package/dist/schemas/extensions/document/x-scalar-default-request-body-view.d.ts +23 -0
- package/dist/schemas/extensions/document/x-scalar-default-request-body-view.d.ts.map +1 -0
- package/dist/schemas/extensions/document/x-scalar-default-request-body-view.js +23 -0
- package/dist/schemas/navigation.d.ts +4 -4
- package/dist/schemas/navigation.js +1 -1
- package/dist/schemas/reference-config/index.d.ts +94 -4
- package/dist/schemas/reference-config/index.d.ts.map +1 -1
- package/dist/schemas/reference-config/settings.d.ts +95 -5
- package/dist/schemas/reference-config/settings.d.ts.map +1 -1
- package/dist/schemas/reference-config/settings.js +1 -1
- package/dist/schemas/type-guards.d.ts +1 -1
- package/dist/schemas/v3.1/openapi/index.d.ts +2 -0
- package/dist/schemas/v3.1/openapi/index.d.ts.map +1 -1
- package/dist/schemas/v3.1/openapi/index.js +13 -1
- package/dist/schemas/v3.1/strict/openapi-document.d.ts +284 -1
- package/dist/schemas/v3.1/strict/openapi-document.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/openapi-document.js +2 -1
- package/dist/schemas/v3.1/strict/security-scheme.d.ts +13 -1
- package/dist/schemas/v3.1/strict/security-scheme.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/security-scheme.js +11 -1
- package/dist/schemas/v3.2/openapi/index.d.ts +2 -0
- package/dist/schemas/v3.2/openapi/index.d.ts.map +1 -1
- package/dist/schemas/v3.2/openapi/index.js +13 -1
- package/dist/schemas/v3.2/strict/oauth-flow.d.ts +23 -1
- package/dist/schemas/v3.2/strict/oauth-flow.d.ts.map +1 -1
- package/dist/schemas/v3.2/strict/oauth-flow.js +6 -1
- package/dist/schemas/v3.2/strict/oauthflows.d.ts +20 -0
- package/dist/schemas/v3.2/strict/oauthflows.d.ts.map +1 -1
- package/dist/schemas/v3.2/strict/openapi-document.d.ts +1439 -141
- package/dist/schemas/v3.2/strict/openapi-document.d.ts.map +1 -1
- package/dist/schemas/v3.2/strict/openapi-document.js +2 -1
- package/dist/schemas/v3.2/strict/security-scheme.d.ts +29 -6
- package/dist/schemas/v3.2/strict/security-scheme.d.ts.map +1 -1
- package/dist/schemas/v3.2/strict/security-scheme.js +16 -3
- package/dist/schemas/workspace-specification/index.d.ts +1 -1
- package/dist/schemas/workspace.d.ts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +23 -20
- package/package.json +9 -9
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { HTTP_METHODS } from '@scalar/helpers/http/http-methods';
|
|
7
7
|
import { isObject } from '@scalar/helpers/object/is-object';
|
|
8
|
+
import { isSchemaPath } from '@scalar/helpers/openapi/is-schema-path';
|
|
9
|
+
import { resolveReferencePath } from '@scalar/json-magic/bundle';
|
|
8
10
|
import { isLocalRef } from '../../helpers/general.js';
|
|
9
11
|
import { syncParametersForPathChange, } from '../../mutators/operation/helpers/sync-path-parameters.js';
|
|
10
12
|
import { getResolvedRef } from '../../plugins/bundler/helpers.js';
|
|
@@ -49,15 +51,18 @@ export const externalValueResolver = () => {
|
|
|
49
51
|
if (typeof externalValue !== 'string') {
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
|
-
|
|
54
|
+
// `externalValue` may be relative (for example `/examples/pet.json`). Resolve it against the
|
|
55
|
+
// origin of the document it lives in so it becomes an absolute URL a loader can fetch.
|
|
56
|
+
const resolvedValue = resolveReferencePath(context.origin, externalValue);
|
|
57
|
+
const loader = context.loaders.find((it) => it.validate(resolvedValue));
|
|
53
58
|
// We can not process the external value
|
|
54
59
|
if (!loader) {
|
|
55
60
|
return;
|
|
56
61
|
}
|
|
57
|
-
if (!cache.has(
|
|
58
|
-
cache.set(
|
|
62
|
+
if (!cache.has(resolvedValue)) {
|
|
63
|
+
cache.set(resolvedValue, loader.exec(resolvedValue));
|
|
59
64
|
}
|
|
60
|
-
const result = await cache.get(
|
|
65
|
+
const result = await cache.get(resolvedValue);
|
|
61
66
|
// If fetch is successful, assign the data to the node's 'value' property
|
|
62
67
|
if (result?.ok) {
|
|
63
68
|
node['value'] = result.data;
|
|
@@ -199,35 +204,28 @@ export const normalizeAuthSchemes = () => {
|
|
|
199
204
|
};
|
|
200
205
|
/**
|
|
201
206
|
* Lifecycle plugin to normalize $ref nodes:
|
|
202
|
-
* Ensures that for any
|
|
207
|
+
* Ensures that for any OpenAPI Reference Object containing a $ref, only $ref,
|
|
203
208
|
* summary, description, and $status properties are preserved.
|
|
204
209
|
* This keeps $ref references clean and predictable for downstream consumers.
|
|
210
|
+
*
|
|
211
|
+
* Schema Objects are deliberately skipped: in JSON Schema 2020-12 a $ref may
|
|
212
|
+
* carry sibling keywords, so their siblings must not be stripped.
|
|
205
213
|
*/
|
|
206
214
|
export const normalizeRefs = () => {
|
|
207
215
|
return {
|
|
208
216
|
type: 'lifecycle',
|
|
209
217
|
onBeforeNodeProcess: (node, context) => {
|
|
210
|
-
const { path } = context;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
//
|
|
220
|
-
const keepProperties = new Set([
|
|
221
|
-
'$ref',
|
|
222
|
-
'summary',
|
|
223
|
-
'description',
|
|
224
|
-
'$status',
|
|
225
|
-
'$id',
|
|
226
|
-
'$anchor',
|
|
227
|
-
'$dynamicAnchor',
|
|
228
|
-
'$dynamicRef',
|
|
229
|
-
'$defs',
|
|
230
|
-
]);
|
|
218
|
+
const { path, referencedFromPath } = context;
|
|
219
|
+
const isSchema = isSchemaPath(path) || isSchemaPath(referencedFromPath);
|
|
220
|
+
// Normalization only applies to OpenAPI Reference Objects, where a `$ref` may sit next to nothing but
|
|
221
|
+
// `summary` and `description`. Schema Objects are left untouched: in JSON Schema 2020-12 a `$ref` may
|
|
222
|
+
// legally carry sibling keywords — for example a `$defs`/`$dynamicAnchor` binding that specializes a
|
|
223
|
+
// generic template (the `Paginated<T>` pattern) — and such schemas appear inline, in reusable schemas,
|
|
224
|
+
// and in raw external schema documents. Stripping those siblings would discard the binding and leave
|
|
225
|
+
// `$dynamicRef` resolving to the template's empty fallback. See https://github.com/scalar/scalar/issues/9414.
|
|
226
|
+
if (typeof node['$ref'] === 'string' && !isSchema) {
|
|
227
|
+
// Remove any other properties from the node and only keep the '$ref', 'summary', 'description' and '$status'
|
|
228
|
+
const keepProperties = new Set(['$ref', 'summary', 'description', '$status']);
|
|
231
229
|
Object.keys(node).forEach((key) => {
|
|
232
230
|
if (!keepProperties.has(key)) {
|
|
233
231
|
delete node[key];
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { RequestBodyObject } from '@scalar/workspace-store/schemas/v3.
|
|
1
|
+
import type { RequestBodyObject } from '@scalar/workspace-store/schemas/v3.2/strict/request-body';
|
|
2
2
|
type FormData = {
|
|
3
3
|
mode: 'formdata';
|
|
4
4
|
value: ({
|
|
5
5
|
type: 'text';
|
|
6
6
|
key: string;
|
|
7
7
|
value: string;
|
|
8
|
+
contentType?: string;
|
|
8
9
|
} | {
|
|
9
10
|
type: 'file';
|
|
10
11
|
key: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-request-body.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/build-request-body.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0DAA0D,CAAA;
|
|
1
|
+
{"version":3,"file":"build-request-body.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/build-request-body.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0DAA0D,CAAA;AASjG,KAAK,QAAQ,GAAG;IACd,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,CACH;QACE,IAAI,EAAE,MAAM,CAAA;QACZ,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,GACD;QACE,IAAI,EAAE,MAAM,CAAA;QACZ,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,IAAI,CAAA;QACX,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,GACD;QACE,IAAI,EAAE,MAAM,CAAA;QACZ,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,IAAI,CAAA;QACX,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CACJ,EAAE,CAAA;CACJ,CAAA;AAwBD,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE;QACL,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;KACd,EAAE,CAAA;CACJ,CAAA;AAED,KAAK,GAAG,GAAG;IACT,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,GAAG,CAAA;AAKrD;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAC3B,aAAa,iBAAiB,GAAG,SAAS;AAC1C,qCAAqC;AACrC,oBAAuB;AACvB,sEAAsE;AACtE,kCAAkC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACvD,WAAW,GAAG,IAuUhB,CAAA"}
|
|
@@ -3,10 +3,32 @@ import { isObject } from '@scalar/helpers/object/is-object';
|
|
|
3
3
|
import { setValueAtPath } from '@scalar/helpers/object/set-value-at-path';
|
|
4
4
|
import { getResolvedRef, mergeSiblingReferences } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
5
5
|
import { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy';
|
|
6
|
+
import { isObjectSchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards';
|
|
6
7
|
import { getExampleFromBody } from './get-request-body-example.js';
|
|
7
8
|
import { getSelectedBodyContentType } from './get-selected-body-content-type.js';
|
|
8
9
|
import { buildDottedNestedRowPredicate, coerceLeafValueToSchemaType, resolveLeafSchema } from './schema-value-coercion.js';
|
|
9
10
|
import { serializeFormPropertyWithEncoding } from './serialize-form-property.js';
|
|
11
|
+
import { serializeMultipartArray } from './serialize-multipart-array.js';
|
|
12
|
+
/** Preserve per-item media types while keeping uploaded file bytes and names intact. */
|
|
13
|
+
const toMultipartPart = (part) => {
|
|
14
|
+
if (part.value instanceof File) {
|
|
15
|
+
const file = part.value;
|
|
16
|
+
return {
|
|
17
|
+
type: 'file',
|
|
18
|
+
key: part.key,
|
|
19
|
+
value: part.contentType && part.contentType !== file.type
|
|
20
|
+
? new File([file], file.name, { type: part.contentType, lastModified: file.lastModified })
|
|
21
|
+
: file,
|
|
22
|
+
contentType: part.contentType,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
type: 'text',
|
|
27
|
+
key: part.key,
|
|
28
|
+
value: part.value,
|
|
29
|
+
...(part.contentType ? { contentType: part.contentType } : {}),
|
|
30
|
+
};
|
|
31
|
+
};
|
|
10
32
|
const getMultipartEncodingContentType = (requestBody, bodyContentType, fieldName) => requestBody.content[bodyContentType]?.encoding?.[fieldName]?.contentType;
|
|
11
33
|
/**
|
|
12
34
|
* Create the fetch request body
|
|
@@ -29,6 +51,22 @@ requestBodyCompositionSelection) => {
|
|
|
29
51
|
if (!example) {
|
|
30
52
|
return null;
|
|
31
53
|
}
|
|
54
|
+
// Optional body properties default to "not sent", matching how optional parameters are
|
|
55
|
+
// dropped by `isParamDisabled`. We only know a property is optional when the body has an
|
|
56
|
+
// object schema that declares it outside `required`, so undeclared and required keys are
|
|
57
|
+
// always kept. This mirrors the unchecked-by-default checkbox in the Test Request panel.
|
|
58
|
+
// The array (edited) form path is unaffected: it carries its own per-row `isDisabled`.
|
|
59
|
+
const resolvedBodySchema = getResolvedRef(requestBody.content[bodyContentType]?.schema, mergeSiblingReferences);
|
|
60
|
+
const objectBodySchema = resolvedBodySchema && isObjectSchema(resolvedBodySchema) ? resolvedBodySchema : undefined;
|
|
61
|
+
// Composition (allOf/oneOf/anyOf) can mark a property required inside a subschema we do not
|
|
62
|
+
// merge here, so skip dropping entirely for composed schemas rather than risk removing an
|
|
63
|
+
// effectively-required field.
|
|
64
|
+
const isComposed = Boolean(objectBodySchema?.allOf || objectBodySchema?.oneOf || objectBodySchema?.anyOf);
|
|
65
|
+
const bodyProperties = objectBodySchema && !isComposed ? objectBodySchema.properties : undefined;
|
|
66
|
+
const requiredBodyProperties = new Set(objectBodySchema && !isComposed ? (objectBodySchema.required ?? []) : []);
|
|
67
|
+
// `Object.hasOwn` (not `in`) so an undeclared key named like an `Object.prototype` member
|
|
68
|
+
// (`toString`, `constructor`, …) is not misread as declared-and-optional and dropped.
|
|
69
|
+
const isOptionalBodyProperty = (key) => Boolean(bodyProperties && Object.hasOwn(bodyProperties, key) && !requiredBodyProperties.has(key));
|
|
32
70
|
// Form data - array format (from UI editor)
|
|
33
71
|
if ((bodyContentType === 'multipart/form-data' || bodyContentType === 'application/x-www-form-urlencoded') &&
|
|
34
72
|
Array.isArray(example.value)) {
|
|
@@ -86,6 +124,16 @@ requestBodyCompositionSelection) => {
|
|
|
86
124
|
return;
|
|
87
125
|
}
|
|
88
126
|
const partEncoding = requestBody.content[bodyContentType]?.encoding?.[name];
|
|
127
|
+
if (result.mode === 'formdata') {
|
|
128
|
+
// Older saved form rows store JSON text. Only restore arrays declared by the schema.
|
|
129
|
+
const schema = resolveLeafSchema(multipartSchema, [name]);
|
|
130
|
+
const restored = coerceLeafValueToSchemaType(value, schema);
|
|
131
|
+
const arrayParts = serializeMultipartArray(name, Array.isArray(restored) ? restored : value, partEncoding);
|
|
132
|
+
if (arrayParts) {
|
|
133
|
+
result.value.push(...arrayParts.map(toMultipartPart));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
89
137
|
// When the encoding sets style/explode, serialize objects/arrays RFC6570-style
|
|
90
138
|
// (bracket or exploded notation) instead of JSON, so the wire request matches the
|
|
91
139
|
// generated code snippet.
|
|
@@ -122,9 +170,9 @@ requestBodyCompositionSelection) => {
|
|
|
122
170
|
const serializedValue = typeof value === 'object' && value !== null ? JSON.stringify(unpackProxyObject(value)) : String(value);
|
|
123
171
|
if (result.mode === 'formdata' && partContentType) {
|
|
124
172
|
return result.value.push({
|
|
125
|
-
type: '
|
|
173
|
+
type: 'text',
|
|
126
174
|
key: name,
|
|
127
|
-
value:
|
|
175
|
+
value: serializedValue,
|
|
128
176
|
contentType: partContentType,
|
|
129
177
|
});
|
|
130
178
|
}
|
|
@@ -148,6 +196,10 @@ requestBodyCompositionSelection) => {
|
|
|
148
196
|
};
|
|
149
197
|
// Convert object properties to form fields
|
|
150
198
|
for (const [key, value] of Object.entries(example.value)) {
|
|
199
|
+
// Optional properties are left out unless the user enabled them (edited form path).
|
|
200
|
+
if (isOptionalBodyProperty(key)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
151
203
|
if (key && value !== undefined && value !== null) {
|
|
152
204
|
const partEncoding = requestBody.content[bodyContentType]?.encoding?.[key];
|
|
153
205
|
// Encoding style/explode turns objects into bracket or exploded notation.
|
|
@@ -177,7 +229,16 @@ requestBodyCompositionSelection) => {
|
|
|
177
229
|
if (!key || value === undefined || value === null) {
|
|
178
230
|
continue;
|
|
179
231
|
}
|
|
232
|
+
// Optional properties are left out unless the user enabled them (edited form path).
|
|
233
|
+
if (isOptionalBodyProperty(key)) {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
180
236
|
const partEncoding = requestBody.content[bodyContentType]?.encoding?.[key];
|
|
237
|
+
const arrayParts = serializeMultipartArray(key, value, partEncoding);
|
|
238
|
+
if (arrayParts) {
|
|
239
|
+
result.value.push(...arrayParts.map(toMultipartPart));
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
181
242
|
// Encoding style/explode turns objects into bracket or exploded notation instead of
|
|
182
243
|
// the default single JSON part.
|
|
183
244
|
const styleParts = serializeFormPropertyWithEncoding(key, value, partEncoding);
|
|
@@ -207,9 +268,9 @@ requestBodyCompositionSelection) => {
|
|
|
207
268
|
const serializedValue = typeof value === 'object' && value !== null ? JSON.stringify(unpackProxyObject(value)) : String(value);
|
|
208
269
|
if (partContentType) {
|
|
209
270
|
result.value.push({
|
|
210
|
-
type: '
|
|
271
|
+
type: 'text',
|
|
211
272
|
key,
|
|
212
|
-
value:
|
|
273
|
+
value: serializedValue,
|
|
213
274
|
contentType: partContentType,
|
|
214
275
|
});
|
|
215
276
|
continue;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RequestBody } from './build-request-body.js';
|
|
2
|
+
/**
|
|
3
|
+
* Encode typed text fields without turning them into file uploads.
|
|
4
|
+
* Blob parts retain binary bytes and keep request construction synchronous.
|
|
5
|
+
*/
|
|
6
|
+
export declare const encodeMultipartBody: (parts: Extract<RequestBody, {
|
|
7
|
+
mode: "formdata";
|
|
8
|
+
}>["value"]) => Blob;
|
|
9
|
+
//# sourceMappingURL=encode-multipart-body.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encode-multipart-body.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/encode-multipart-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAUvD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC,OAAO,CAAC,KAAG,IAqBhG,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Escape disposition parameters using the same percent escapes as browser form submissions. */
|
|
2
|
+
const escapeParameter = (value) => value
|
|
3
|
+
.replace(/\r\n|\r|\n/g, '\r\n')
|
|
4
|
+
.replace(/\r/g, '%0D')
|
|
5
|
+
.replace(/\n/g, '%0A')
|
|
6
|
+
.replace(/"/g, '%22');
|
|
7
|
+
/**
|
|
8
|
+
* Encode typed text fields without turning them into file uploads.
|
|
9
|
+
* Blob parts retain binary bytes and keep request construction synchronous.
|
|
10
|
+
*/
|
|
11
|
+
export const encodeMultipartBody = (parts) => {
|
|
12
|
+
// getRandomValues also works on HTTP playgrounds, where randomUUID is unavailable.
|
|
13
|
+
const random = crypto.getRandomValues(new Uint8Array(24));
|
|
14
|
+
const boundary = `----scalar-${Array.from(random, (byte) => byte.toString(16).padStart(2, '0')).join('')}`;
|
|
15
|
+
const chunks = parts.flatMap((part) => {
|
|
16
|
+
const filename = part.type === 'file' ? part.value.name : part.type === 'blob' ? 'blob' : undefined;
|
|
17
|
+
const contentType = part.contentType ?? (part.type === 'text' ? undefined : part.value.type || 'application/octet-stream');
|
|
18
|
+
// A media type comes from the API description and must never inject part headers.
|
|
19
|
+
if (contentType && /[\r\n\0]/.test(contentType)) {
|
|
20
|
+
throw new Error('Invalid multipart content type');
|
|
21
|
+
}
|
|
22
|
+
const disposition = `Content-Disposition: form-data; name="${escapeParameter(part.key)}"${filename === undefined ? '' : `; filename="${escapeParameter(filename)}"`}`;
|
|
23
|
+
const headers = `--${boundary}\r\n${disposition}\r\n${contentType ? `Content-Type: ${contentType}\r\n` : ''}\r\n`;
|
|
24
|
+
// Match native FormData line endings for ordinary text; explicitly typed data keeps its bytes.
|
|
25
|
+
const value = part.type === 'text' && !part.contentType ? part.value.replace(/\r\n|\r|\n/g, '\r\n') : part.value;
|
|
26
|
+
return [headers, value, '\r\n'];
|
|
27
|
+
});
|
|
28
|
+
return new Blob([...chunks, `--${boundary}--\r\n`], { type: `multipart/form-data; boundary=${boundary}` });
|
|
29
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExampleObject, RequestBodyObject } from '@scalar/workspace-store/schemas/v3.
|
|
1
|
+
import type { ExampleObject, RequestBodyObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
2
2
|
/**
|
|
3
3
|
* Generate a write-mode example directly from a request body's schema, ignoring any stored example.
|
|
4
4
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RequestBodyObject } from '@scalar/workspace-store/schemas/v3.
|
|
1
|
+
import type { RequestBodyObject } from '@scalar/workspace-store/schemas/v3.2/strict/request-body';
|
|
2
2
|
/**
|
|
3
3
|
* Returns the selected body content type for the given request body and exampleKey.
|
|
4
4
|
* Priority:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.
|
|
1
|
+
import type { SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
2
2
|
/**
|
|
3
3
|
* Walk an object schema along a dotted-row path and return the resolved leaf schema,
|
|
4
4
|
* or undefined when any segment is not a declared object property.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getResolvedRef, mergeSiblingReferences } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
2
|
-
import { isObjectSchema } from '@scalar/workspace-store/schemas/v3.
|
|
2
|
+
import { isObjectSchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards';
|
|
3
3
|
/** Normalize a schema's `type` (string | string[] | absent) into a plain string array. */
|
|
4
4
|
const normalizeSchemaTypes = (schema) => {
|
|
5
5
|
const type = 'type' in schema ? schema.type : undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EncodingObject } from '@scalar/workspace-store/schemas/v3.
|
|
1
|
+
import type { EncodingObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
2
2
|
/** A single serialized form field, ready to become a multipart part or a urlencoded pair. */
|
|
3
3
|
export type SerializedFormProperty = {
|
|
4
4
|
key: string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { EncodingObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document';
|
|
2
|
+
/** A multipart array item shared by the request builder and code snippets. */
|
|
3
|
+
export type MultipartArrayPart = {
|
|
4
|
+
key: string;
|
|
5
|
+
value: string | File;
|
|
6
|
+
contentType?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Named multipart arrays produce one part per item, using the same property name.
|
|
10
|
+
* Encoding applies to each item, including its content type. Without an explicit
|
|
11
|
+
* style, nested arrays remain individual JSON values instead of expanding again.
|
|
12
|
+
*
|
|
13
|
+
* @see https://spec.openapis.org/oas/v3.2.0.html#encoding-by-name
|
|
14
|
+
*/
|
|
15
|
+
export declare const serializeMultipartArray: (key: string, value: unknown, encoding?: EncodingObject) => MultipartArrayPart[] | null;
|
|
16
|
+
//# sourceMappingURL=serialize-multipart-array.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize-multipart-array.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/serialize-multipart-array.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAA;AAIlG,8EAA8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,MAAM,EACX,OAAO,OAAO,EACd,WAAW,cAAc,KACxB,kBAAkB,EAAE,GAAG,IA+BzB,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { parseMimeType } from '@scalar/helpers/http/mime-type';
|
|
2
|
+
import { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy';
|
|
3
|
+
import { serializeFormPropertyWithEncoding } from './serialize-form-property.js';
|
|
4
|
+
/**
|
|
5
|
+
* Named multipart arrays produce one part per item, using the same property name.
|
|
6
|
+
* Encoding applies to each item, including its content type. Without an explicit
|
|
7
|
+
* style, nested arrays remain individual JSON values instead of expanding again.
|
|
8
|
+
*
|
|
9
|
+
* @see https://spec.openapis.org/oas/v3.2.0.html#encoding-by-name
|
|
10
|
+
*/
|
|
11
|
+
export const serializeMultipartArray = (key, value, encoding) => {
|
|
12
|
+
if (!Array.isArray(value)) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const hasStyle = encoding?.style !== undefined || encoding?.explode !== undefined || encoding?.allowReserved !== undefined;
|
|
16
|
+
const contentType = hasStyle ? undefined : encoding?.contentType;
|
|
17
|
+
return value.flatMap((item) => {
|
|
18
|
+
const parts = serializeFormPropertyWithEncoding(key, item, encoding);
|
|
19
|
+
if (parts) {
|
|
20
|
+
return parts;
|
|
21
|
+
}
|
|
22
|
+
if (item instanceof File) {
|
|
23
|
+
return [{ key, value: unpackProxyObject(item), ...(contentType ? { contentType } : {}) }];
|
|
24
|
+
}
|
|
25
|
+
const structured = typeof item === 'object' && item !== null;
|
|
26
|
+
const itemContentType = contentType ?? (!hasStyle && structured ? 'application/json' : undefined);
|
|
27
|
+
const subtype = itemContentType ? parseMimeType(itemContentType).subtype : undefined;
|
|
28
|
+
const isJson = subtype === 'json' || subtype?.endsWith('+json');
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
key,
|
|
32
|
+
value: structured || isJson ? JSON.stringify(unpackProxyObject(item)) : String(item),
|
|
33
|
+
...(itemContentType ? { contentType: itemContentType } : {}),
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
});
|
|
37
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-request.d.ts","sourceRoot":"","sources":["../../../src/request-example/builder/build-request.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"build-request.d.ts","sourceRoot":"","sources":["../../../src/request-example/builder/build-request.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,8BAA8B,CAAA;AAQnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAA;AAC/E,OAAO,EACL,KAAK,6BAA6B,EAEnC,MAAM,uDAAuD,CAAA;AAK9D;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;AAuClD;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,GACtC,SAAS,cAAc,EACvB,cAAc,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,iBAAiB;IAAE,6BAA6B,CAAC,EAAE,OAAO,CAAA;CAAE,KAC3D,MAyBF,CAAA;AAED;;;;;KAKK;AACL,MAAM,MAAM,gBAAgB,GAAG;IAC7B,kGAAkG;IAClG,cAAc,EAAE,cAAc,CAAA;IAC9B,2BAA2B;IAC3B,UAAU,EAAE,eAAe,CAAA;IAC3B,0DAA0D;IAC1D,YAAY,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,wGAAwG;AACxG,eAAO,MAAM,oBAAoB,EAAG,sBAA+B,CAAA;AAEnE,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,GAAG,OAAO,oBAAoB,CAAA;AAEjG,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,gBAAgB,EAAE,uBAAuB,CAAC,CAAA;AAElF,eAAO,MAAM,YAAY,GACvB,SAAS,cAAc,EACvB,SAAS;IACP,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC;;;OAGG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAA;CACxC,KACA,kBAMF,CAAA"}
|
|
@@ -4,6 +4,7 @@ import { err, ok } from '@scalar/helpers/types/result';
|
|
|
4
4
|
import { safeRun } from '@scalar/helpers/types/safe-run';
|
|
5
5
|
import { redirectToProxy, shouldUseProxy } from '@scalar/helpers/url/redirect-to-proxy';
|
|
6
6
|
import { encode as encodeBase64 } from 'js-base64';
|
|
7
|
+
import { encodeMultipartBody } from '../../request-example/builder/body/encode-multipart-body.js';
|
|
7
8
|
import { buildRequestCookieHeader } from '../../request-example/builder/header/build-request-cookie-header.js';
|
|
8
9
|
import { applyAllowReservedToUrl } from '../../request-example/builder/helpers/apply-allow-reserved-to-url.js';
|
|
9
10
|
import { resolveRequestFactoryUrl, } from '../../request-example/builder/resolve-request-factory-url.js';
|
|
@@ -93,14 +94,18 @@ const buildRequestInner = (request, options) => {
|
|
|
93
94
|
return request.body.value;
|
|
94
95
|
}
|
|
95
96
|
if (request.body?.mode === 'formdata') {
|
|
97
|
+
const parts = request.body.value.map((item) => ({
|
|
98
|
+
...item,
|
|
99
|
+
key: replaceEnvVariables(item.key, replace),
|
|
100
|
+
}));
|
|
101
|
+
const resolvedParts = parts.map((item) => item.type === 'text' ? { ...item, value: replaceEnvVariables(item.value, replace) } : item);
|
|
102
|
+
if (request.body.value.some((item) => item.type === 'text' && item.contentType)) {
|
|
103
|
+
const encoded = encodeMultipartBody(resolvedParts);
|
|
104
|
+
headers.set('content-type', encoded.type);
|
|
105
|
+
return encoded;
|
|
106
|
+
}
|
|
96
107
|
const form = new FormData();
|
|
97
|
-
|
|
98
|
-
if (item.type === 'text') {
|
|
99
|
-
form.append(replaceEnvVariables(item.key, replace), replaceEnvVariables(item.value, replace));
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
form.append(replaceEnvVariables(item.key, replace), item.value);
|
|
103
|
-
});
|
|
108
|
+
resolvedParts.forEach((item) => form.append(item.key, item.value));
|
|
104
109
|
return form;
|
|
105
110
|
}
|
|
106
111
|
if (request.body?.mode === 'urlencoded') {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies';
|
|
2
|
-
import type { ParameterObject, ReferenceType } from '@scalar/workspace-store/schemas/v3.
|
|
2
|
+
import type { ParameterObject, ReferenceType } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
3
3
|
/**
|
|
4
4
|
* Converts the parameters into a set of headers, cookies and url params while
|
|
5
5
|
* replacing environment variables and extracting example values. Also builds up a record of the path
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-request-parameters.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/build-request-parameters.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,qEAAqE,CAAA;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAA;AAoBlH;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB;AACjC,qBAAqB;AACrB,aAAY,aAAa,CAAC,eAAe,CAAC,EAAO;AACjD,qCAAqC;AACrC,cAAa,MAAkB,KAC9B;IACD,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,4BAA4B,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACzC,SAAS,EAAE,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"build-request-parameters.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/build-request-parameters.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,qEAAqE,CAAA;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAA;AAoBlH;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB;AACjC,qBAAqB;AACrB,aAAY,aAAa,CAAC,eAAe,CAAC,EAAO;AACjD,qCAAqC;AACrC,cAAa,MAAkB,KAC9B;IACD,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,4BAA4B,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACzC,SAAS,EAAE,eAAe,CAAA;CA6F3B,CAAA"}
|
|
@@ -38,6 +38,8 @@ exampleName = 'default') => {
|
|
|
38
38
|
// Second pass: process all parameters
|
|
39
39
|
for (const referencedParam of parameters) {
|
|
40
40
|
const param = getResolvedRef(referencedParam);
|
|
41
|
+
if (!param)
|
|
42
|
+
continue;
|
|
41
43
|
const example = getExample(param, exampleName, undefined);
|
|
42
44
|
// Skip disabled examples
|
|
43
45
|
if (!example || isParamDisabled(param, example)) {
|
|
@@ -80,7 +82,11 @@ exampleName = 'default') => {
|
|
|
80
82
|
result.pathVariables[paramName] = String(serialized);
|
|
81
83
|
break;
|
|
82
84
|
}
|
|
83
|
-
|
|
85
|
+
// The 3.2 `querystring` location represents the whole query string. Handle it like a
|
|
86
|
+
// regular query parameter so schema-based values still expand into the query string
|
|
87
|
+
// instead of being silently dropped.
|
|
88
|
+
case 'query':
|
|
89
|
+
case 'querystring': {
|
|
84
90
|
processQueryParameter(param, paramName, deSerializedValue, result.urlParams, result.allowReservedQueryParameters);
|
|
85
91
|
break;
|
|
86
92
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ParameterObject, ParameterWithSchemaObject } from '@scalar/workspace-store/schemas/v3.
|
|
1
|
+
import type { ParameterObject, ParameterWithSchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
2
2
|
/**
|
|
3
3
|
* Coerces a parameter example from the UI (always a string from CodeInput) into a value
|
|
4
4
|
* request building can serialize. Only structured types are parsed; primitives stay as strings.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"de-serialize-parameter.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/de-serialize-parameter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"de-serialize-parameter.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/de-serialize-parameter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,yBAAyB,EAC1B,MAAM,8DAA8D,CAAA;AAErE;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,OAAO,EAAE,OAAO,eAAe,QAS5E,CAAA;AA0DD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,GAAI,SAAS,OAAO,EAAE,QAAQ,yBAAyB,CAAC,QAAQ,CAAC,QA6BnG,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isObjectLike } from '@scalar/helpers/object/is-object';
|
|
1
2
|
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
2
3
|
/**
|
|
3
4
|
* Coerces a parameter example from the UI (always a string from CodeInput) into a value
|
|
@@ -39,7 +40,7 @@ const structuredSchemaTypes = new Set(['array', 'object']);
|
|
|
39
40
|
*/
|
|
40
41
|
const getStructuredType = (schema) => {
|
|
41
42
|
const resolved = getResolvedRef(schema);
|
|
42
|
-
if (!resolved
|
|
43
|
+
if (!isObjectLike(resolved)) {
|
|
43
44
|
return undefined;
|
|
44
45
|
}
|
|
45
46
|
if ('type' in resolved && resolved.type) {
|
|
@@ -80,13 +81,23 @@ export const deSerializeSchemaValue = (example, schema) => {
|
|
|
80
81
|
const type = getStructuredType(schema);
|
|
81
82
|
if (type) {
|
|
82
83
|
try {
|
|
83
|
-
|
|
84
|
+
const parsed = JSON.parse(example);
|
|
85
|
+
if (type !== 'array' || Array.isArray(parsed)) {
|
|
86
|
+
return parsed;
|
|
87
|
+
}
|
|
88
|
+
// A bare numeric string is valid JSON too (e.g. a 20-digit reference number), but parsing it
|
|
89
|
+
// would turn it into a precision-losing JS number instead of the array the schema expects. A
|
|
90
|
+
// quoted string is a deliberate escape hatch, so keep it as a single-item array.
|
|
91
|
+
if (typeof parsed === 'string') {
|
|
92
|
+
return [parsed];
|
|
93
|
+
}
|
|
84
94
|
}
|
|
85
95
|
catch {
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
// Not JSON at all: fall through to the comma-split handling below.
|
|
97
|
+
}
|
|
98
|
+
// Arrays: users often type `foo,bar` instead of JSON — split to match default form+explode query style.
|
|
99
|
+
if (type === 'array') {
|
|
100
|
+
return example.split(/,\s?/).filter((v) => v !== '');
|
|
90
101
|
}
|
|
91
102
|
}
|
|
92
103
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExampleObject, ParameterObject } from '@scalar/workspace-store/schemas/v3.
|
|
1
|
+
import type { ExampleObject, ParameterObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
2
2
|
/**
|
|
3
3
|
* Determines if a parameter is disabled
|
|
4
4
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serialize-parameter.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/serialize-parameter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"serialize-parameter.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/serialize-parameter.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,OAAO,EAAE,aAAa,MAAM,KAAG,MAa3E,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,EAAE,SAAS,OAAO,KAAG,OAqBvE,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,OAAO,EACd,SAAS,OAAO,KACf,OAAO,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CA4BjD,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,4BAA4B,GACvC,OAAO,OAAO,EACd,SAAS,OAAO,KACf,OAAO,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CA2CjD,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GAAI,OAAO,OAAO,KAAG,MAe7D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,OAAO,KAAG,MAa5D,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,GAAI,WAAW,MAAM,EAAE,OAAO,OAAO,KAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAoChH,CAAA"}
|