@scalar/workspace-store 0.64.0 → 0.66.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 +121 -0
- package/README.md +45 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +109 -10
- package/dist/entities/auth/schema.d.ts +351 -20
- package/dist/entities/auth/schema.d.ts.map +1 -1
- package/dist/entities/auth/schema.js +3 -1
- package/dist/events/definitions/auth.d.ts +1 -2
- package/dist/events/definitions/auth.d.ts.map +1 -1
- package/dist/events/definitions/operation.d.ts +3 -4
- package/dist/events/definitions/operation.d.ts.map +1 -1
- package/dist/events/definitions/server.d.ts +1 -2
- package/dist/events/definitions/server.d.ts.map +1 -1
- package/dist/events/definitions/ui.d.ts +3 -4
- package/dist/events/definitions/ui.d.ts.map +1 -1
- package/dist/events/old-definitions.d.ts +1 -2
- package/dist/events/old-definitions.d.ts.map +1 -1
- package/dist/helpers/chunk-index.d.ts +20 -2
- package/dist/helpers/chunk-index.d.ts.map +1 -1
- package/dist/helpers/chunk-index.js +14 -1
- package/dist/helpers/external-examples.d.ts +2 -0
- package/dist/helpers/external-examples.d.ts.map +1 -1
- package/dist/helpers/external-examples.js +1 -0
- package/dist/helpers/for-each-path-item-operation.d.ts +6 -5
- package/dist/helpers/for-each-path-item-operation.d.ts.map +1 -1
- package/dist/helpers/for-each-path-item-operation.js +40 -14
- package/dist/helpers/get-example-value.d.ts +15 -0
- package/dist/helpers/get-example-value.d.ts.map +1 -0
- package/dist/helpers/get-example-value.js +28 -0
- package/dist/helpers/get-parameter-example.d.ts +14 -0
- package/dist/helpers/get-parameter-example.d.ts.map +1 -0
- package/dist/helpers/get-parameter-example.js +19 -0
- package/dist/helpers/get-resolved-ref.d.ts.map +1 -1
- package/dist/helpers/get-resolved-ref.js +12 -1
- package/dist/helpers/normalize-boolean-schemas.d.ts +10 -0
- package/dist/helpers/normalize-boolean-schemas.d.ts.map +1 -0
- package/dist/helpers/normalize-boolean-schemas.js +193 -0
- package/dist/helpers/operation-examples.d.ts.map +1 -1
- package/dist/helpers/operation-examples.js +5 -2
- package/dist/helpers/querystring-parameter.d.ts +21 -0
- package/dist/helpers/querystring-parameter.d.ts.map +1 -0
- package/dist/helpers/querystring-parameter.js +108 -0
- package/dist/helpers/serialize-stream-example.d.ts +8 -0
- package/dist/helpers/serialize-stream-example.d.ts.map +1 -0
- package/dist/helpers/serialize-stream-example.js +52 -0
- package/dist/helpers/use-external-examples.d.ts.map +1 -1
- package/dist/helpers/use-external-examples.js +8 -1
- package/dist/mutators/index.d.ts +3 -3
- package/dist/mutators/operation/body.d.ts.map +1 -1
- package/dist/mutators/operation/body.js +9 -2
- package/dist/mutators/operation/operation.d.ts.map +1 -1
- package/dist/mutators/operation/operation.js +4 -7
- package/dist/mutators/operation/parameters.d.ts.map +1 -1
- package/dist/mutators/operation/parameters.js +43 -3
- package/dist/navigation/get-navigation-options.d.ts.map +1 -1
- package/dist/navigation/get-navigation-options.js +19 -4
- package/dist/navigation/helpers/traverse-paths.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-paths.js +2 -2
- package/dist/navigation/helpers/traverse-webhooks.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-webhooks.js +2 -2
- package/dist/navigation/helpers/update-order-ids.d.ts +1 -2
- package/dist/navigation/helpers/update-order-ids.d.ts.map +1 -1
- package/dist/plugins/bundler/index.d.ts +1 -0
- package/dist/plugins/bundler/index.d.ts.map +1 -1
- package/dist/plugins/bundler/index.js +11 -3
- package/dist/plugins/bundler/openapi-document.d.ts +6 -0
- package/dist/plugins/bundler/openapi-document.d.ts.map +1 -0
- package/dist/plugins/bundler/openapi-document.js +57 -0
- package/dist/request-example/builder/body/build-multipart.d.ts +29 -0
- package/dist/request-example/builder/body/build-multipart.d.ts.map +1 -0
- package/dist/request-example/builder/body/build-multipart.js +191 -0
- package/dist/request-example/builder/body/build-request-body.d.ts +6 -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 +80 -23
- package/dist/request-example/builder/body/encode-multipart-body.d.ts +8 -8
- package/dist/request-example/builder/body/encode-multipart-body.d.ts.map +1 -1
- package/dist/request-example/builder/body/encode-multipart-body.js +56 -18
- package/dist/request-example/builder/body/get-request-body-example.d.ts.map +1 -1
- package/dist/request-example/builder/body/get-request-body-example.js +20 -6
- package/dist/request-example/builder/body/multipart-limits.d.ts +3 -0
- package/dist/request-example/builder/body/multipart-limits.d.ts.map +1 -0
- package/dist/request-example/builder/body/multipart-limits.js +2 -0
- package/dist/request-example/builder/body/serialize-form-property.d.ts +2 -0
- package/dist/request-example/builder/body/serialize-form-property.d.ts.map +1 -1
- package/dist/request-example/builder/body/serialize-form-property.js +3 -2
- package/dist/request-example/builder/body/serialize-multipart-array.d.ts +1 -1
- package/dist/request-example/builder/build-request.d.ts.map +1 -1
- package/dist/request-example/builder/build-request.js +7 -1
- package/dist/request-example/builder/header/build-request-parameters.d.ts +2 -0
- package/dist/request-example/builder/header/build-request-parameters.d.ts.map +1 -1
- package/dist/request-example/builder/header/build-request-parameters.js +54 -11
- package/dist/request-example/builder/header/is-param-disabled.d.ts.map +1 -1
- package/dist/request-example/builder/header/is-param-disabled.js +3 -1
- package/dist/request-example/builder/header/serialize-parameter.d.ts +11 -0
- package/dist/request-example/builder/header/serialize-parameter.d.ts.map +1 -1
- package/dist/request-example/builder/header/serialize-parameter.js +22 -0
- 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 +42 -3
- package/dist/request-example/builder/helpers/get-example.d.ts.map +1 -1
- package/dist/request-example/builder/helpers/get-example.js +5 -2
- package/dist/request-example/builder/index.d.ts +2 -2
- package/dist/request-example/builder/index.d.ts.map +1 -1
- package/dist/request-example/builder/index.js +1 -1
- package/dist/request-example/builder/request-factory.d.ts +7 -0
- package/dist/request-example/builder/request-factory.d.ts.map +1 -1
- package/dist/request-example/builder/request-factory.js +10 -1
- package/dist/request-example/builder/resolve-request-factory-url.d.ts.map +1 -1
- package/dist/request-example/builder/resolve-request-factory-url.js +18 -2
- package/dist/request-example/builder/security/secret-types.d.ts +4 -1
- package/dist/request-example/builder/security/secret-types.d.ts.map +1 -1
- package/dist/request-example/context/headers.d.ts +1 -2
- package/dist/request-example/context/headers.d.ts.map +1 -1
- 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 +15 -0
- package/dist/request-example/index.d.ts +5 -2
- package/dist/request-example/index.d.ts.map +1 -1
- package/dist/request-example/index.js +4 -1
- package/dist/request-example/types.d.ts +1 -2
- package/dist/request-example/types.d.ts.map +1 -1
- package/dist/request-example/xml/serialize-xml-part.d.ts +9 -0
- package/dist/request-example/xml/serialize-xml-part.d.ts.map +1 -0
- package/dist/request-example/xml/serialize-xml-part.js +12 -0
- package/dist/schemas/extensions/operation/x-code-samples.d.ts +22 -0
- package/dist/schemas/extensions/operation/x-code-samples.d.ts.map +1 -1
- package/dist/schemas/extensions/operation/x-code-samples.js +4 -0
- package/dist/schemas/extensions.d.ts +9 -0
- package/dist/schemas/extensions.d.ts.map +1 -1
- package/dist/schemas/extensions.js +9 -0
- package/dist/schemas/navigation.d.ts +40 -34
- package/dist/schemas/navigation.d.ts.map +1 -1
- package/dist/schemas/navigation.js +2 -3
- package/dist/schemas/reference-config/index.d.ts +24 -4
- package/dist/schemas/reference-config/index.d.ts.map +1 -1
- package/dist/schemas/reference-config/settings.d.ts +24 -4
- package/dist/schemas/reference-config/settings.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/oauthflows.d.ts +26 -0
- package/dist/schemas/v3.1/strict/oauthflows.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/oauthflows.js +3 -0
- package/dist/schemas/v3.1/strict/openapi-document.d.ts +1582 -147
- package/dist/schemas/v3.1/strict/openapi-document.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/operation.d.ts +8 -0
- package/dist/schemas/v3.1/strict/operation.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/path-item.d.ts +19 -0
- package/dist/schemas/v3.1/strict/path-item.d.ts.map +1 -1
- package/dist/schemas/v3.1/strict/path-item.js +5 -0
- package/dist/schemas/v3.2/openapi/index.d.ts +5 -0
- package/dist/schemas/v3.2/openapi/index.d.ts.map +1 -1
- package/dist/schemas/v3.2/openapi/index.js +48 -12
- package/dist/schemas/v3.2/openapi/reference.d.ts.map +1 -1
- package/dist/schemas/v3.2/openapi/reference.js +11 -3
- package/dist/schemas/v3.2/strict/openapi-document.d.ts +842 -140
- package/dist/schemas/v3.2/strict/openapi-document.d.ts.map +1 -1
- package/dist/schemas/v3.2/strict/openapi-document.js +6 -14
- package/dist/schemas/v3.2/strict/operation.d.ts +8 -0
- package/dist/schemas/v3.2/strict/operation.d.ts.map +1 -1
- package/dist/schemas/v3.2/strict/parameter.d.ts +14 -0
- package/dist/schemas/v3.2/strict/parameter.d.ts.map +1 -1
- package/dist/schemas/v3.2/strict/parameter.js +2 -0
- package/dist/server.d.ts +10 -6
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +67 -45
- package/package.json +19 -9
- package/dist/schemas/v3.1/openapi/index.d.ts +0 -149
- package/dist/schemas/v3.1/openapi/index.d.ts.map +0 -1
- package/dist/schemas/v3.1/openapi/index.js +0 -732
- package/dist/schemas/v3.1/openapi/reference.d.ts +0 -4
- package/dist/schemas/v3.1/openapi/reference.d.ts.map +0 -1
- package/dist/schemas/v3.1/openapi/reference.js +0 -29
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// import { replaceEnvVariables } from '@scalar/helpers/regex/replace-variables'
|
|
2
|
+
import { parseMimeType } from '@scalar/helpers/http/mime-type';
|
|
2
3
|
import { isObject } from '@scalar/helpers/object/is-object';
|
|
3
4
|
import { setValueAtPath } from '@scalar/helpers/object/set-value-at-path';
|
|
4
5
|
import { getResolvedRef, mergeSiblingReferences } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
5
6
|
import { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy';
|
|
6
7
|
import { isObjectSchema } from '@scalar/workspace-store/schemas/v3.2/strict/type-guards';
|
|
8
|
+
import { getExampleValue, getExplicitExampleText } from '../../../helpers/get-example-value.js';
|
|
9
|
+
import { buildMultipart, getMultipartItemSchema, isPositionalMultipart, needsMultipartEncoding, } from './build-multipart.js';
|
|
7
10
|
import { getExampleFromBody } from './get-request-body-example.js';
|
|
8
11
|
import { getSelectedBodyContentType } from './get-selected-body-content-type.js';
|
|
9
12
|
import { buildDottedNestedRowPredicate, coerceLeafValueToSchemaType, resolveLeafSchema } from './schema-value-coercion.js';
|
|
@@ -30,6 +33,33 @@ const toMultipartPart = (part) => {
|
|
|
30
33
|
};
|
|
31
34
|
};
|
|
32
35
|
const getMultipartEncodingContentType = (requestBody, bodyContentType, fieldName) => requestBody.content[bodyContentType]?.encoding?.[fieldName]?.contentType;
|
|
36
|
+
/** Preserve schema-backed nested objects and repeated flat fields from form editor rows. */
|
|
37
|
+
const regroupMultipartRows = (rows, multipartSchema) => {
|
|
38
|
+
const isDottedNestedRow = buildDottedNestedRowPredicate(multipartSchema);
|
|
39
|
+
const entries = [];
|
|
40
|
+
const regroupedByTopKey = new Map();
|
|
41
|
+
for (const row of rows) {
|
|
42
|
+
if (!isDottedNestedRow(row.name, row.value)) {
|
|
43
|
+
entries.push(row);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const segments = row.name.split('.');
|
|
47
|
+
const topKey = segments[0];
|
|
48
|
+
if (!topKey) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
let target = regroupedByTopKey.get(topKey);
|
|
52
|
+
if (!target) {
|
|
53
|
+
target = {};
|
|
54
|
+
regroupedByTopKey.set(topKey, target);
|
|
55
|
+
entries.push({ name: topKey, value: target });
|
|
56
|
+
}
|
|
57
|
+
// The form table stringifies leaf values; restore the schema-declared type so the
|
|
58
|
+
// regrouped JSON part keeps booleans/numbers/arrays instead of string-typing them.
|
|
59
|
+
setValueAtPath(target, segments.slice(1), coerceLeafValueToSchemaType(row.value, resolveLeafSchema(multipartSchema, segments)));
|
|
60
|
+
}
|
|
61
|
+
return entries;
|
|
62
|
+
};
|
|
33
63
|
/**
|
|
34
64
|
* Create the fetch request body
|
|
35
65
|
*/
|
|
@@ -51,6 +81,10 @@ requestBodyCompositionSelection) => {
|
|
|
51
81
|
if (!example) {
|
|
52
82
|
return null;
|
|
53
83
|
}
|
|
84
|
+
const explicitText = getExplicitExampleText(getExampleValue(example), bodyContentType);
|
|
85
|
+
if (explicitText !== undefined) {
|
|
86
|
+
return { mode: 'raw', value: explicitText, contentType: bodyContentType };
|
|
87
|
+
}
|
|
54
88
|
// Optional body properties default to "not sent", matching how optional parameters are
|
|
55
89
|
// dropped by `isParamDisabled`. We only know a property is optional when the body has an
|
|
56
90
|
// object schema that declares it outside `required`, so undeclared and required keys are
|
|
@@ -67,6 +101,51 @@ requestBodyCompositionSelection) => {
|
|
|
67
101
|
// `Object.hasOwn` (not `in`) so an undeclared key named like an `Object.prototype` member
|
|
68
102
|
// (`toString`, `constructor`, …) is not misread as declared-and-optional and dropped.
|
|
69
103
|
const isOptionalBodyProperty = (key) => Boolean(bodyProperties && Object.hasOwn(bodyProperties, key) && !requiredBodyProperties.has(key));
|
|
104
|
+
const media = requestBody.content[bodyContentType];
|
|
105
|
+
if (media && needsMultipartEncoding(bodyContentType, media)) {
|
|
106
|
+
// Raw editors store JSON text, while form editors store named rows.
|
|
107
|
+
const value = (() => {
|
|
108
|
+
if (typeof example.value !== 'string') {
|
|
109
|
+
return example.value;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return JSON.parse(example.value);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return example.value;
|
|
116
|
+
}
|
|
117
|
+
})();
|
|
118
|
+
// Already serialized payloads and uploaded bodies retain their bytes.
|
|
119
|
+
if (typeof value === 'string' || value instanceof Blob) {
|
|
120
|
+
return { mode: 'raw', value, contentType: bodyContentType };
|
|
121
|
+
}
|
|
122
|
+
const positional = isPositionalMultipart(bodyContentType, media);
|
|
123
|
+
const orderedValue = positional && parseMimeType(bodyContentType).essence === 'multipart/form-data' && Array.isArray(value)
|
|
124
|
+
? value
|
|
125
|
+
.filter((item) => !(isObject(item) && typeof item.name === 'string' && 'value' in item && item.isDisabled))
|
|
126
|
+
.map((item, index) => {
|
|
127
|
+
if (!isObject(item) || typeof item.name !== 'string' || !('value' in item)) {
|
|
128
|
+
return item;
|
|
129
|
+
}
|
|
130
|
+
const itemSchema = getMultipartItemSchema(resolvedBodySchema, index, media.itemSchema);
|
|
131
|
+
return {
|
|
132
|
+
[item.name]: coerceLeafValueToSchemaType(item.value, resolveLeafSchema(itemSchema, [item.name])),
|
|
133
|
+
};
|
|
134
|
+
})
|
|
135
|
+
: value;
|
|
136
|
+
const multipartParts = !positional && Array.isArray(value)
|
|
137
|
+
? regroupMultipartRows(value.filter((row) => !row.isDisabled), resolvedBodySchema).flatMap((row) => buildMultipart({
|
|
138
|
+
[row.name]: coerceLeafValueToSchemaType(row.value, resolveLeafSchema(resolvedBodySchema, [row.name])),
|
|
139
|
+
}, bodyContentType, media, resolvedBodySchema))
|
|
140
|
+
: buildMultipart(!positional && isObject(value)
|
|
141
|
+
? Object.fromEntries(Object.entries(value).filter(([key]) => !isOptionalBodyProperty(key)))
|
|
142
|
+
: orderedValue, bodyContentType, media, resolvedBodySchema);
|
|
143
|
+
return {
|
|
144
|
+
mode: 'multipart',
|
|
145
|
+
contentType: bodyContentType,
|
|
146
|
+
value: multipartParts,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
70
149
|
// Form data - array format (from UI editor)
|
|
71
150
|
if ((bodyContentType === 'multipart/form-data' || bodyContentType === 'application/x-www-form-urlencoded') &&
|
|
72
151
|
Array.isArray(example.value)) {
|
|
@@ -95,29 +174,7 @@ requestBodyCompositionSelection) => {
|
|
|
95
174
|
const multipartSchema = result.mode === 'formdata'
|
|
96
175
|
? getResolvedRef(requestBody.content[bodyContentType]?.schema, mergeSiblingReferences)
|
|
97
176
|
: undefined;
|
|
98
|
-
const
|
|
99
|
-
const entries = [];
|
|
100
|
-
const regroupedByTopKey = new Map();
|
|
101
|
-
for (const row of exampleValue) {
|
|
102
|
-
if (!isDottedNestedRow(row.name, row.value)) {
|
|
103
|
-
entries.push(row);
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
const segments = row.name.split('.');
|
|
107
|
-
const topKey = segments[0];
|
|
108
|
-
if (!topKey) {
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
let target = regroupedByTopKey.get(topKey);
|
|
112
|
-
if (!target) {
|
|
113
|
-
target = {};
|
|
114
|
-
regroupedByTopKey.set(topKey, target);
|
|
115
|
-
entries.push({ name: topKey, value: target });
|
|
116
|
-
}
|
|
117
|
-
// The form table stringifies leaf values; restore the schema-declared type so the
|
|
118
|
-
// regrouped JSON part keeps booleans/numbers/arrays instead of string-typing them.
|
|
119
|
-
setValueAtPath(target, segments.slice(1), coerceLeafValueToSchemaType(row.value, resolveLeafSchema(multipartSchema, segments)));
|
|
120
|
-
}
|
|
177
|
+
const entries = result.mode === 'formdata' ? regroupMultipartRows(exampleValue, multipartSchema) : exampleValue;
|
|
121
178
|
// Loop over all entries and add them to the form
|
|
122
179
|
entries.forEach(({ name, value }) => {
|
|
123
180
|
if (!name) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import type { MultipartPart } from './build-multipart.js';
|
|
2
|
+
/** Serialize nested multipart bodies for both fetch and synchronous code snippets. */
|
|
3
|
+
export declare const serializeMultipartBody: (parts: MultipartPart[], contentType?: string, replace?: (value: string) => string, nesting?: number) => {
|
|
4
|
+
chunks: BlobPart[];
|
|
5
|
+
contentType: string;
|
|
6
|
+
};
|
|
7
|
+
/** Encode multipart parts without losing binary bytes or assigning filenames to typed text. */
|
|
8
|
+
export declare const encodeMultipartBody: (parts: MultipartPart[], contentType?: string, replace?: (value: string) => string) => Blob;
|
|
9
9
|
//# sourceMappingURL=encode-multipart-body.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encode-multipart-body.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/encode-multipart-body.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"encode-multipart-body.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/encode-multipart-body.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AA0BtD,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,GACjC,OAAO,aAAa,EAAE,EACtB,oBAAmC,EACnC,UAAS,CAAC,KAAK,EAAE,MAAM,KAAK,MAAyB,EACrD,gBAAW,KACV;IAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CA6C3C,CAAA;AAED,+FAA+F;AAC/F,eAAO,MAAM,mBAAmB,GAC9B,OAAO,aAAa,EAAE,EACtB,oBAAmC,EACnC,UAAU,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,KAClC,IAGF,CAAA"}
|
|
@@ -1,29 +1,67 @@
|
|
|
1
|
+
import { parseMimeType } from '@scalar/helpers/http/mime-type';
|
|
2
|
+
import { MAX_MULTIPART_NESTING } from './multipart-limits.js';
|
|
1
3
|
/** Escape disposition parameters using the same percent escapes as browser form submissions. */
|
|
2
4
|
const escapeParameter = (value) => value
|
|
3
5
|
.replace(/\r\n|\r|\n/g, '\r\n')
|
|
4
6
|
.replace(/\r/g, '%0D')
|
|
5
7
|
.replace(/\n/g, '%0A')
|
|
6
8
|
.replace(/"/g, '%22');
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
/** Keep equal-length boundaries distinct from nested delimiters and resolved text. */
|
|
10
|
+
const createBoundary = (chunks) => {
|
|
11
|
+
const text = chunks.filter((chunk) => typeof chunk === 'string').join('');
|
|
12
|
+
for (const _attempt of Array.from({ length: 10 })) {
|
|
13
|
+
// getRandomValues also works on HTTP playgrounds, where randomUUID is unavailable.
|
|
14
|
+
// Binary blobs stay untouched; 192 random bits make accidental byte collisions negligible.
|
|
15
|
+
const random = crypto.getRandomValues(new Uint8Array(24));
|
|
16
|
+
const boundary = `----scalar-${Array.from(random, (byte) => byte.toString(16).padStart(2, '0')).join('')}`;
|
|
17
|
+
if (!text.includes(boundary)) {
|
|
18
|
+
return boundary;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
throw new Error('Unable to generate a distinct multipart boundary');
|
|
22
|
+
};
|
|
23
|
+
/** Serialize nested multipart bodies for both fetch and synchronous code snippets. */
|
|
24
|
+
export const serializeMultipartBody = (parts, contentType = 'multipart/form-data', replace = (value) => value, nesting = 0) => {
|
|
25
|
+
if (nesting >= MAX_MULTIPART_NESTING) {
|
|
26
|
+
throw new Error('Maximum multipart nesting exceeded');
|
|
27
|
+
}
|
|
28
|
+
if (/[\r\n\0]/.test(contentType)) {
|
|
29
|
+
throw new Error('Invalid multipart content type');
|
|
30
|
+
}
|
|
31
|
+
const mime = parseMimeType(contentType);
|
|
32
|
+
const partsChunks = parts.map((part) => {
|
|
33
|
+
const encoded = part.type === 'multipart'
|
|
34
|
+
? serializeMultipartBody(part.value, part.contentType, replace, nesting + 1)
|
|
35
|
+
: { chunks: [part.type === 'text' ? replace(part.value) : part.value], contentType: part.contentType };
|
|
16
36
|
const filename = part.type === 'file' ? part.value.name : part.type === 'blob' ? 'blob' : undefined;
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
if (
|
|
37
|
+
const partContentType = encoded.contentType ??
|
|
38
|
+
(part.type === 'file' || part.type === 'blob' ? part.value.type || 'application/octet-stream' : undefined);
|
|
39
|
+
if (partContentType && /[\r\n\0]/.test(partContentType)) {
|
|
20
40
|
throw new Error('Invalid multipart content type');
|
|
21
41
|
}
|
|
22
|
-
const disposition =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
42
|
+
const disposition = part.key === undefined
|
|
43
|
+
? ''
|
|
44
|
+
: `Content-Disposition: form-data; name="${escapeParameter(replace(part.key))}"${filename === undefined ? '' : `; filename="${escapeParameter(filename)}"`}\r\n`;
|
|
45
|
+
const extraHeaders = Object.entries(part.headers ?? {})
|
|
46
|
+
.map(([name, value]) => {
|
|
47
|
+
const resolved = replace(value);
|
|
48
|
+
if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name) || /[\r\n\0]/.test(resolved)) {
|
|
49
|
+
throw new Error('Invalid multipart header');
|
|
50
|
+
}
|
|
51
|
+
return name.toLowerCase() === 'content-type' ? '' : `${name}: ${resolved}\r\n`;
|
|
52
|
+
})
|
|
53
|
+
.join('');
|
|
54
|
+
const headers = `${disposition}${partContentType ? `Content-Type: ${partContentType}\r\n` : ''}${extraHeaders}\r\n`;
|
|
55
|
+
const chunks = encoded.chunks.map((value) => typeof value === 'string' && !part.contentType ? value.replace(/\r\n|\r|\n/g, '\r\n') : value);
|
|
56
|
+
return [headers, ...chunks, '\r\n'];
|
|
27
57
|
});
|
|
28
|
-
|
|
58
|
+
const boundary = createBoundary(partsChunks.flat());
|
|
59
|
+
mime.parameters.set('boundary', boundary);
|
|
60
|
+
const chunks = partsChunks.flatMap((part) => [`--${boundary}\r\n`, ...part]);
|
|
61
|
+
return { chunks: [...chunks, `--${boundary}--\r\n`], contentType: mime.toString() };
|
|
62
|
+
};
|
|
63
|
+
/** Encode multipart parts without losing binary bytes or assigning filenames to typed text. */
|
|
64
|
+
export const encodeMultipartBody = (parts, contentType = 'multipart/form-data', replace) => {
|
|
65
|
+
const encoded = serializeMultipartBody(parts, contentType, replace);
|
|
66
|
+
return new Blob(encoded.chunks, { type: encoded.contentType });
|
|
29
67
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-request-body-example.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/get-request-body-example.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EAElB,MAAM,8DAA8D,CAAA;
|
|
1
|
+
{"version":3,"file":"get-request-body-example.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/get-request-body-example.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EAElB,MAAM,8DAA8D,CAAA;AAQrE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GACnC,aAAa,iBAAiB,EAC9B,aAAa,MAAM,EACnB,kCAAkC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACvD,OAwBF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,aAAa,iBAAiB,EAC9B,aAAa,MAAM,EACnB,aAAa,MAAM,EACnB,kCAAkC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACvD,aAAa,GAAG,IAwBlB,CAAA"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseMimeType } from '@scalar/helpers/http/mime-type';
|
|
2
|
+
import { getExampleValue } from '../../../helpers/get-example-value.js';
|
|
2
3
|
import { getResolvedRefDeep } from '../../../helpers/get-resolved-ref-deep.js';
|
|
4
|
+
import { serializeStreamExample } from '../../../helpers/serialize-stream-example.js';
|
|
3
5
|
import { getExample } from '../../../request-example/builder/helpers/get-example.js';
|
|
4
6
|
import { getExampleFromSchema } from '../../../request-example/builder/helpers/get-example-from-schema.js';
|
|
5
7
|
/**
|
|
@@ -14,17 +16,22 @@ import { getExampleFromSchema } from '../../../request-example/builder/helpers/g
|
|
|
14
16
|
* Returns `undefined` when there is no schema for the content type.
|
|
15
17
|
*/
|
|
16
18
|
export const getSchemaExampleFromBody = (requestBody, contentType, requestBodyCompositionSelection) => {
|
|
17
|
-
const
|
|
19
|
+
const mediaType = requestBody.content?.[contentType];
|
|
20
|
+
const schema = mediaType?.schema ??
|
|
21
|
+
(mediaType?.itemSchema && parseMimeType(contentType).type === 'multipart'
|
|
22
|
+
? { type: 'array', items: mediaType.itemSchema }
|
|
23
|
+
: mediaType?.itemSchema);
|
|
18
24
|
if (!schema) {
|
|
19
25
|
return undefined;
|
|
20
26
|
}
|
|
21
27
|
const resolvedSchema = getResolvedRefDeep(schema);
|
|
22
|
-
|
|
28
|
+
const value = getExampleFromSchema(resolvedSchema, {
|
|
23
29
|
mode: 'write',
|
|
24
30
|
compositionSelection: requestBodyCompositionSelection,
|
|
25
31
|
}, {
|
|
26
32
|
schemaPath: ['requestBody'],
|
|
27
33
|
});
|
|
34
|
+
return serializeStreamExample(value, contentType, mediaType?.schema === undefined) ?? value;
|
|
28
35
|
};
|
|
29
36
|
/**
|
|
30
37
|
* Basically getExample + we generate an example from the schema if no example is found
|
|
@@ -34,12 +41,19 @@ export const getExampleFromBody = (requestBody, contentType, exampleName, reques
|
|
|
34
41
|
// `externalValue` (not yet resolved to a `value`) is treated as missing, so we fall back to a
|
|
35
42
|
// schema-generated example instead of building an empty request body.
|
|
36
43
|
const example = getExample(requestBody, exampleName, contentType);
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
const selected = getExampleValue(example);
|
|
45
|
+
if (example && selected) {
|
|
46
|
+
const stream = typeof selected.value === 'string' ? undefined : serializeStreamExample(selected.value, contentType, false);
|
|
47
|
+
if (stream !== undefined) {
|
|
48
|
+
return selected.source === 'data'
|
|
49
|
+
? { ...example, value: stream, serializedValue: stream }
|
|
50
|
+
: { ...example, value: stream };
|
|
51
|
+
}
|
|
52
|
+
return selected.source === 'value' ? example : { ...example, value: selected.value };
|
|
39
53
|
}
|
|
40
54
|
// Generate an example from the schema
|
|
41
55
|
const schemaExample = getSchemaExampleFromBody(requestBody, contentType, requestBodyCompositionSelection);
|
|
42
|
-
if (
|
|
56
|
+
if (schemaExample === undefined || schemaExample === null) {
|
|
43
57
|
return null;
|
|
44
58
|
}
|
|
45
59
|
return { value: schemaExample };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-limits.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/multipart-limits.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,eAAO,MAAM,qBAAqB,IAAI,CAAA"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { EncodingObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
2
|
+
/** Explicit RFC6570 fields select style serialization instead of media-type encoding. */
|
|
3
|
+
export declare const hasEncodingStyle: (encoding: EncodingObject | undefined) => boolean;
|
|
2
4
|
/** A single serialized form field, ready to become a multipart part or a urlencoded pair. */
|
|
3
5
|
export type SerializedFormProperty = {
|
|
4
6
|
key: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serialize-form-property.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/serialize-form-property.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAA;AASlG,6FAA6F;AAC7F,MAAM,MAAM,sBAAsB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAcnE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iCAAiC,GAC5C,KAAK,MAAM,EACX,OAAO,OAAO,EACd,UAAU,cAAc,GAAG,SAAS,KACnC,sBAAsB,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"serialize-form-property.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/body/serialize-form-property.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAA;AASlG,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,GAAI,UAAU,cAAc,GAAG,SAAS,KAAG,OACgD,CAAA;AAExH,6FAA6F;AAC7F,MAAM,MAAM,sBAAsB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAcnE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iCAAiC,GAC5C,KAAK,MAAM,EACX,OAAO,OAAO,EACd,UAAU,cAAc,GAAG,SAAS,KACnC,sBAAsB,EAAE,GAAG,IA0E7B,CAAA"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy';
|
|
2
2
|
import { serializeDeepObjectStyle, serializeFormStyle, serializePipeDelimitedStyle, serializeSpaceDelimitedStyle, } from '../header/serialize-parameter.js';
|
|
3
|
+
/** Explicit RFC6570 fields select style serialization instead of media-type encoding. */
|
|
4
|
+
export const hasEncodingStyle = (encoding) => !!encoding && (encoding.style !== undefined || encoding.explode !== undefined || encoding.allowReserved !== undefined);
|
|
3
5
|
/**
|
|
4
6
|
* Stringify a value emitted by `serializeFormStyle` into a form field value.
|
|
5
7
|
*
|
|
@@ -30,8 +32,7 @@ export const serializeFormPropertyWithEncoding = (key, value, encoding) => {
|
|
|
30
32
|
* Per OpenAPI 3.1.x: when style, explode, or allowReserved is explicitly set, the value
|
|
31
33
|
* is serialized as if it were a query-style parameter and contentType is ignored.
|
|
32
34
|
*/
|
|
33
|
-
const hasFormStyle =
|
|
34
|
-
(encoding.style !== undefined || encoding.explode !== undefined || encoding.allowReserved !== undefined);
|
|
35
|
+
const hasFormStyle = hasEncodingStyle(encoding);
|
|
35
36
|
if (!hasFormStyle) {
|
|
36
37
|
return null;
|
|
37
38
|
}
|
|
@@ -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 multipart array item shared by the request builder and code snippets. */
|
|
3
3
|
export type MultipartArrayPart = {
|
|
4
4
|
key: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-request.d.ts","sourceRoot":"","sources":["../../../src/request-example/builder/build-request.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build-request.d.ts","sourceRoot":"","sources":["../../../src/request-example/builder/build-request.ts"],"names":[],"mappings":"AAGA,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;AAwClD;;;;;;;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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isHttpMethod } from '@scalar/helpers/http/is-http-method';
|
|
1
2
|
import { X_SCALAR_DATE, X_SCALAR_DNT, X_SCALAR_REFERER, X_SCALAR_USER_AGENT } from '@scalar/helpers/http/scalar-headers';
|
|
2
3
|
import { replaceEnvVariables } from '@scalar/helpers/regex/replace-variables';
|
|
3
4
|
import { err, ok } from '@scalar/helpers/types/result';
|
|
@@ -88,6 +89,11 @@ const buildRequestInner = (request, options) => {
|
|
|
88
89
|
})();
|
|
89
90
|
/** Create a new body object with the replaced values */
|
|
90
91
|
const body = (() => {
|
|
92
|
+
if (request.body?.mode === 'multipart') {
|
|
93
|
+
const encoded = encodeMultipartBody(request.body.value, request.body.contentType, (value) => replaceEnvVariables(value, replace));
|
|
94
|
+
headers.set('content-type', encoded.type);
|
|
95
|
+
return encoded;
|
|
96
|
+
}
|
|
91
97
|
if (request.body?.mode === 'raw') {
|
|
92
98
|
if (typeof request.body.value === 'string') {
|
|
93
99
|
return replaceEnvVariables(request.body.value, replace);
|
|
@@ -201,7 +207,7 @@ const buildRequestInner = (request, options) => {
|
|
|
201
207
|
*
|
|
202
208
|
* @see https://github.com/whatwg/fetch/issues/50
|
|
203
209
|
*/
|
|
204
|
-
method: request.method.toUpperCase(),
|
|
210
|
+
method: isHttpMethod(request.method) ? request.method.toUpperCase() : request.method,
|
|
205
211
|
headers,
|
|
206
212
|
body,
|
|
207
213
|
cache: request.cache,
|
|
@@ -20,5 +20,7 @@ exampleName?: string) => {
|
|
|
20
20
|
pathVariables: Record<string, string>;
|
|
21
21
|
allowReservedQueryParameters: Set<string>;
|
|
22
22
|
urlParams: URLSearchParams;
|
|
23
|
+
serializedQuery?: string[];
|
|
24
|
+
serializedPathParameters?: Set<string>;
|
|
23
25
|
};
|
|
24
26
|
//# sourceMappingURL=build-request-parameters.d.ts.map
|
|
@@ -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;
|
|
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;AAqBlH;;;;;;;;;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;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,wBAAwB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CA8IvC,CAAA"}
|
|
@@ -3,10 +3,10 @@ import { isObject } from '@scalar/helpers/object/is-object';
|
|
|
3
3
|
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
4
4
|
import { xScalarCookieSchema, } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies';
|
|
5
5
|
import { coerceValue } from '@scalar/workspace-store/schemas/typebox-coerce';
|
|
6
|
+
import { getParameterExample } from '../../../helpers/get-parameter-example.js';
|
|
6
7
|
import { deSerializeParameter } from '../../../request-example/builder/header/de-serialize-parameter.js';
|
|
7
|
-
import { getExample } from '../helpers/get-example.js';
|
|
8
8
|
import { isParamDisabled } from './is-param-disabled.js';
|
|
9
|
-
import { serializeContentValue, serializeDeepObjectStyle, serializeFormStyle, serializeFormStyleForCookies, serializePipeDelimitedStyle, serializeSimpleStyle, serializeSpaceDelimitedStyle, } from './serialize-parameter.js';
|
|
9
|
+
import { serializeContentValue, serializeCookieStyle, serializeDeepObjectStyle, serializeFormStyle, serializeFormStyleForCookies, serializePipeDelimitedStyle, serializeSimpleStyle, serializeSpaceDelimitedStyle, } from './serialize-parameter.js';
|
|
10
10
|
/** Helper to get explode value with default */
|
|
11
11
|
const getExplode = (param, defaultValue) => 'explode' in param && param.explode !== undefined ? param.explode : defaultValue;
|
|
12
12
|
/**
|
|
@@ -38,15 +38,58 @@ 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)
|
|
41
|
+
if (!param) {
|
|
42
42
|
continue;
|
|
43
|
-
|
|
43
|
+
}
|
|
44
|
+
const selected = getParameterExample(param, exampleName);
|
|
45
|
+
const { example, value } = selected;
|
|
44
46
|
// Skip disabled examples
|
|
45
47
|
if (!example || isParamDisabled(param, example)) {
|
|
46
48
|
continue;
|
|
47
49
|
}
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
+
/** Parameter-level wire text already contains its name, delimiters, and encoding. */
|
|
51
|
+
if (selected.serialized) {
|
|
52
|
+
const wireValue = String(value);
|
|
53
|
+
switch (param.in) {
|
|
54
|
+
case 'query':
|
|
55
|
+
;
|
|
56
|
+
(result.serializedQuery ??= []).push(wireValue);
|
|
57
|
+
break;
|
|
58
|
+
case 'path':
|
|
59
|
+
result.pathVariables[param.name] = wireValue;
|
|
60
|
+
(result.serializedPathParameters ??= new Set()).add(param.name);
|
|
61
|
+
break;
|
|
62
|
+
case 'header':
|
|
63
|
+
result.headers[param.name] = wireValue;
|
|
64
|
+
break;
|
|
65
|
+
case 'cookie':
|
|
66
|
+
result.headers.Cookie = [result.headers.Cookie, wireValue].filter(Boolean).join('; ');
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (selected.mediaSerialized) {
|
|
72
|
+
const text = String(value);
|
|
73
|
+
switch (param.in) {
|
|
74
|
+
case 'query':
|
|
75
|
+
result.urlParams.set(param.name, text);
|
|
76
|
+
break;
|
|
77
|
+
case 'header':
|
|
78
|
+
result.headers[param.name] = text;
|
|
79
|
+
break;
|
|
80
|
+
case 'path':
|
|
81
|
+
result.pathVariables[param.name] = text;
|
|
82
|
+
break;
|
|
83
|
+
case 'cookie':
|
|
84
|
+
result.cookies.push(coerceValue(xScalarCookieSchema, {
|
|
85
|
+
name: encodeURIComponent(param.name),
|
|
86
|
+
value: encodeURIComponent(text),
|
|
87
|
+
path: '/',
|
|
88
|
+
}));
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
50
93
|
/** De-serialize the example value if it is a string and matches the schema type */
|
|
51
94
|
const deSerializedValue = deSerializeParameter(value, param);
|
|
52
95
|
const paramName = param.name;
|
|
@@ -82,15 +125,15 @@ exampleName = 'default') => {
|
|
|
82
125
|
result.pathVariables[paramName] = String(serialized);
|
|
83
126
|
break;
|
|
84
127
|
}
|
|
85
|
-
|
|
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': {
|
|
128
|
+
case 'query': {
|
|
90
129
|
processQueryParameter(param, paramName, deSerializedValue, result.urlParams, result.allowReservedQueryParameters);
|
|
91
130
|
break;
|
|
92
131
|
}
|
|
93
132
|
case 'cookie': {
|
|
133
|
+
if ('style' in param && param.style === 'cookie') {
|
|
134
|
+
result.cookies.push(...serializeCookieStyle(paramName, deSerializedValue, getExplode(param, true)).map((cookie) => coerceValue(xScalarCookieSchema, { ...cookie, path: '/' })));
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
94
137
|
processCookieParameter(paramName, deSerializedValue, getExplode(param, true), result.cookies);
|
|
95
138
|
break;
|
|
96
139
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-param-disabled.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/is-param-disabled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;
|
|
1
|
+
{"version":3,"file":"is-param-disabled.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/is-param-disabled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AAIlH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,eAAe,EACtB,SAAS,aAAa,GAAG,SAAS,EAClC,kBAAiB,OAAc,KAC9B,OAiBF,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getExampleValue } from '../../../helpers/get-example-value.js';
|
|
1
2
|
/**
|
|
2
3
|
* Determines if a parameter is disabled
|
|
3
4
|
*
|
|
@@ -16,7 +17,8 @@ export const isParamDisabled = (param, example, defaultDisabled = true) => {
|
|
|
16
17
|
return xDisabled;
|
|
17
18
|
}
|
|
18
19
|
// Keep the editor, generated snippets, and outgoing requests aligned for pre-populated values.
|
|
19
|
-
const
|
|
20
|
+
const value = getExampleValue(example)?.value;
|
|
21
|
+
const hasValue = value !== undefined && value !== '' && value !== null;
|
|
20
22
|
if (!defaultDisabled || hasValue) {
|
|
21
23
|
return false;
|
|
22
24
|
}
|
|
@@ -94,4 +94,15 @@ export declare const serializeDeepObjectStyle: (paramName: string, value: unknow
|
|
|
94
94
|
key: string;
|
|
95
95
|
value: string;
|
|
96
96
|
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Serializes OpenAPI 3.2 cookie style without escaping names or values.
|
|
99
|
+
* Cookie arrays and objects always expand into separate entries: explode: false
|
|
100
|
+
* is invalid because comma-separated cookie values violate RFC6265.
|
|
101
|
+
* Invalid declarations warn once per parameter name and retain the expanded fallback.
|
|
102
|
+
* Header builders join these entries with a semicolon and a single space.
|
|
103
|
+
*/
|
|
104
|
+
export declare const serializeCookieStyle: (name: string, value: unknown, explode?: boolean) => Array<{
|
|
105
|
+
name: string;
|
|
106
|
+
value: string;
|
|
107
|
+
}>;
|
|
97
108
|
//# sourceMappingURL=serialize-parameter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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"}
|
|
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;AAKD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,EACZ,OAAO,OAAO,EACd,iBAAc,KACb,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAcvC,CAAA"}
|
|
@@ -232,3 +232,25 @@ export const serializeDeepObjectStyle = (paramName, value) => {
|
|
|
232
232
|
}
|
|
233
233
|
return result;
|
|
234
234
|
};
|
|
235
|
+
// Request rebuilding and snippet rendering can serialize the same parameter repeatedly.
|
|
236
|
+
const warnedCookieParameterNames = new Set();
|
|
237
|
+
/**
|
|
238
|
+
* Serializes OpenAPI 3.2 cookie style without escaping names or values.
|
|
239
|
+
* Cookie arrays and objects always expand into separate entries: explode: false
|
|
240
|
+
* is invalid because comma-separated cookie values violate RFC6265.
|
|
241
|
+
* Invalid declarations warn once per parameter name and retain the expanded fallback.
|
|
242
|
+
* Header builders join these entries with a semicolon and a single space.
|
|
243
|
+
*/
|
|
244
|
+
export const serializeCookieStyle = (name, value, explode = true) => {
|
|
245
|
+
if (!explode && !warnedCookieParameterNames.has(name)) {
|
|
246
|
+
warnedCookieParameterNames.add(name);
|
|
247
|
+
console.warn(`Cookie parameter "${name}" uses invalid explode: false with style: cookie; serializing with explode: true.`);
|
|
248
|
+
}
|
|
249
|
+
if (Array.isArray(value)) {
|
|
250
|
+
return value.map((item) => ({ name, value: String(item) }));
|
|
251
|
+
}
|
|
252
|
+
if (isObjectLike(value)) {
|
|
253
|
+
return Object.entries(value).map(([key, item]) => ({ name: key, value: String(item) }));
|
|
254
|
+
}
|
|
255
|
+
return [{ name, value: String(value) }];
|
|
256
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-example-from-schema.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/helpers/get-example-from-schema.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAqD,MAAM,uBAAuB,CAAA;AAG5G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;
|
|
1
|
+
{"version":3,"file":"get-example-from-schema.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/helpers/get-example-from-schema.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAqD,MAAM,uBAAuB,CAAA;AAG5G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAiyB1E,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;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,0DAA0D;IAC1D,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC9C,CAAA;AAuPD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,YAAY,EACpB,UAAU,2BAA2B,EACrC,iEAOG,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;IACpB,qGAAqG;IACrG,YAAY,EAAE,YAAY,CAAA;CAC3B,CAAM,KACN,OAuPF,CAAA"}
|