@scalar/workspace-store 0.68.0 → 0.68.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +8 -1
- package/dist/entities/auth/schema.d.ts +390 -0
- package/dist/entities/auth/schema.d.ts.map +1 -1
- package/dist/entities/auth/schema.js +12 -8
- package/dist/events/definitions/auth.d.ts +7 -0
- package/dist/events/definitions/auth.d.ts.map +1 -1
- package/dist/helpers/auth-secret-fields.d.ts +9 -0
- package/dist/helpers/auth-secret-fields.d.ts.map +1 -0
- package/dist/helpers/auth-secret-fields.js +42 -0
- package/dist/helpers/chunk-index.d.ts +2 -0
- package/dist/helpers/chunk-index.d.ts.map +1 -1
- package/dist/helpers/chunk-index.js +8 -1
- package/dist/helpers/encode-path-parameter.d.ts +20 -0
- package/dist/helpers/encode-path-parameter.d.ts.map +1 -0
- package/dist/helpers/encode-path-parameter.js +51 -0
- package/dist/helpers/get-tag-kind.d.ts +6 -0
- package/dist/helpers/get-tag-kind.d.ts.map +1 -0
- package/dist/helpers/get-tag-kind.js +7 -0
- package/dist/helpers/resolve-form-schema.d.ts +9 -0
- package/dist/helpers/resolve-form-schema.d.ts.map +1 -0
- package/dist/helpers/resolve-form-schema.js +143 -0
- package/dist/helpers/resolve-schema-with-annotations.d.ts +11 -0
- package/dist/helpers/resolve-schema-with-annotations.d.ts.map +1 -0
- package/dist/helpers/resolve-schema-with-annotations.js +57 -0
- package/dist/helpers/resolve-security-requirements.d.ts +15 -0
- package/dist/helpers/resolve-security-requirements.d.ts.map +1 -0
- package/dist/helpers/resolve-security-requirements.js +222 -0
- package/dist/mutators/auth.d.ts +1 -0
- package/dist/mutators/auth.d.ts.map +1 -1
- package/dist/mutators/auth.js +29 -0
- package/dist/mutators/index.d.ts +2 -0
- package/dist/mutators/index.d.ts.map +1 -1
- package/dist/navigation/helpers/get-navigation-tag-names.d.ts +5 -0
- package/dist/navigation/helpers/get-navigation-tag-names.d.ts.map +1 -0
- package/dist/navigation/helpers/get-navigation-tag-names.js +3 -0
- package/dist/navigation/helpers/traverse-paths.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-paths.js +4 -2
- package/dist/navigation/helpers/traverse-schemas.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-schemas.js +4 -2
- package/dist/navigation/helpers/traverse-tags.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-tags.js +8 -4
- package/dist/navigation/helpers/traverse-webhooks.d.ts.map +1 -1
- package/dist/navigation/helpers/traverse-webhooks.js +4 -2
- package/dist/request-example/builder/body/build-request-body.d.ts.map +1 -1
- package/dist/request-example/builder/body/build-request-body.js +3 -5
- package/dist/request-example/builder/body/schema-value-coercion.d.ts.map +1 -1
- package/dist/request-example/builder/body/schema-value-coercion.js +5 -7
- package/dist/request-example/builder/build-request.d.ts.map +1 -1
- package/dist/request-example/builder/build-request.js +3 -0
- package/dist/request-example/builder/header/build-request-parameters.d.ts +7 -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 +22 -1
- package/dist/request-example/builder/helpers/get-example-from-schema.d.ts +2 -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 +25 -4
- package/dist/request-example/builder/request-factory.d.ts +6 -1
- package/dist/request-example/builder/request-factory.d.ts.map +1 -1
- package/dist/request-example/builder/request-factory.js +3 -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 +22 -7
- 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/security/extract-security-scheme-secrets.d.ts.map +1 -1
- package/dist/request-example/context/security/extract-security-scheme-secrets.js +33 -34
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +34 -7
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-request-parameters.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/build-request-parameters.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build-request-parameters.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/header/build-request-parameters.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,qEAAqE,CAAA;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAA;AAElH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAoB5E;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB;AACjC,qBAAqB;AACrB,aAAY,aAAa,CAAC,eAAe,CAAC,EAAO;AACjD,qCAAqC;AACrC,cAAa,MAAkB;AAC/B,6DAA6D;AAC7D,iBAAiB,MAAM,KACtB;IACD,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;IAC9D,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;CA+JvC,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isDefined } from '@scalar/helpers/array/is-defined';
|
|
2
|
+
import { getCookieSerializationError } from '@scalar/helpers/http/get-cookie-serialization-error';
|
|
2
3
|
import { isObject } from '@scalar/helpers/object/is-object';
|
|
3
4
|
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
4
5
|
import { xScalarCookieSchema, } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies';
|
|
@@ -23,7 +24,9 @@ export const buildRequestParameters = (
|
|
|
23
24
|
/** All parameters */
|
|
24
25
|
parameters = [],
|
|
25
26
|
/** The key of the current example */
|
|
26
|
-
exampleName = 'default'
|
|
27
|
+
exampleName = 'default',
|
|
28
|
+
/** Reserved path expansion was introduced in OpenAPI 3.2. */
|
|
29
|
+
openapiVersion) => {
|
|
27
30
|
const result = {
|
|
28
31
|
cookies: [],
|
|
29
32
|
headers: {},
|
|
@@ -123,6 +126,15 @@ exampleName = 'default') => {
|
|
|
123
126
|
// Path parameters use simple style by default
|
|
124
127
|
const serialized = serializeSimpleStyle(deSerializedValue, getExplode(param, false));
|
|
125
128
|
result.pathVariables[paramName] = String(serialized);
|
|
129
|
+
if (openapiVersion?.startsWith('3.2.') && 'schema' in param && param.allowReserved === true) {
|
|
130
|
+
;
|
|
131
|
+
(result.reservedPathParameters ??= {})[paramName] = {
|
|
132
|
+
value: deSerializedValue,
|
|
133
|
+
originalValue: String(serialized),
|
|
134
|
+
style: param.style ?? 'simple',
|
|
135
|
+
explode: getExplode(param, false),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
126
138
|
break;
|
|
127
139
|
}
|
|
128
140
|
case 'query': {
|
|
@@ -130,6 +142,15 @@ exampleName = 'default') => {
|
|
|
130
142
|
break;
|
|
131
143
|
}
|
|
132
144
|
case 'cookie': {
|
|
145
|
+
const [major, minor] = (openapiVersion ?? '').split('.');
|
|
146
|
+
const error = major === '3' && minor === '2' && !('content' in param)
|
|
147
|
+
? getCookieSerializationError(param, deSerializedValue)
|
|
148
|
+
: undefined;
|
|
149
|
+
if (error) {
|
|
150
|
+
;
|
|
151
|
+
(result.cookieErrors ??= []).push(error);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
133
154
|
if ('style' in param && param.style === 'cookie') {
|
|
134
155
|
result.cookies.push(...serializeCookieStyle(paramName, deSerializedValue, getExplode(param, true)).map((cookie) => coerceValue(xScalarCookieSchema, { ...cookie, path: '/' })));
|
|
135
156
|
break;
|
|
@@ -7,6 +7,8 @@ export declare const selectExampleComposition: (schema: SchemaObject, schemaPath
|
|
|
7
7
|
export type GetExampleFromSchemaOptions = {
|
|
8
8
|
/** Internal provenance capture, excluded from persistent result caches. */
|
|
9
9
|
[EXAMPLE_EVALUATION]?: ExampleEvaluationState;
|
|
10
|
+
/** Preserve binary filename examples as File objects for multipart serializers. */
|
|
11
|
+
binaryAsFile?: boolean;
|
|
10
12
|
/** Fallback string for empty string values. */
|
|
11
13
|
emptyString?: string;
|
|
12
14
|
/** @deprecated Use getXmlExampleFromSchema for schema-aware XML serialization. */
|
|
@@ -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;AAE1E,OAAO,EAAE,kBAAkB,EAA0B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,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;AAE1E,OAAO,EAAE,kBAAkB,EAA0B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAwZ9G,gGAAgG;AAChG,eAAO,MAAM,wBAAwB,GACnC,QAAQ,YAAY,EACpB,YAAY,MAAM,EAAE,EACpB,UAAU,2BAA2B,EACrC,mBAAiB,EACjB,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,YAAY,GAAG,SAmBjB,CAAA;AAuZD,sEAAsE;AACtE,MAAM,MAAM,2BAA2B,GAAG;IACxC,2EAA2E;IAC3E,CAAC,kBAAkB,CAAC,CAAC,EAAE,sBAAsB,CAAA;IAC7C,mFAAmF;IACnF,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kFAAkF;IAClF,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;AAwPD;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,yBAAyB,GAC7B,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,OA8OF,CAAA;AAoBD,gGAAgG;AAChG,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,YAAY,EACpB,UAAU,2BAA2B,EACrC,UAAS,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAAC,CAAM,KAC5D,OA2BF,CAAA"}
|
|
@@ -63,10 +63,10 @@ const getPropertyNamesEnumValues = (schema) => {
|
|
|
63
63
|
};
|
|
64
64
|
/**
|
|
65
65
|
* Generate example values for string types based on their format.
|
|
66
|
-
*
|
|
66
|
+
* Binary examples use filename placeholders unless the caller requests File objects.
|
|
67
67
|
*/
|
|
68
68
|
const guessFromFormat = (schema, makeUpRandomData = false, fallback = '') => {
|
|
69
|
-
//
|
|
69
|
+
// Binary filename placeholders are converted to File objects only for multipart callers.
|
|
70
70
|
if ('type' in schema && schema.type === 'string' && 'format' in schema && schema.format === 'binary') {
|
|
71
71
|
return '@filename';
|
|
72
72
|
}
|
|
@@ -197,6 +197,10 @@ const mergeExamples = (baseValue, newValue) => {
|
|
|
197
197
|
if (Array.isArray(baseValue) && Array.isArray(newValue)) {
|
|
198
198
|
return [...baseValue, ...newValue];
|
|
199
199
|
}
|
|
200
|
+
// Files are scalar payloads; spreading them would erase their filename and bytes.
|
|
201
|
+
if (baseValue instanceof File || newValue instanceof File) {
|
|
202
|
+
return newValue;
|
|
203
|
+
}
|
|
200
204
|
if (baseValue && typeof baseValue === 'object' && newValue && typeof newValue === 'object') {
|
|
201
205
|
return { ...baseValue, ...newValue };
|
|
202
206
|
}
|
|
@@ -667,6 +671,7 @@ const getUnionPrimitiveValue = (schema, makeUpRandomData, emptyString) => {
|
|
|
667
671
|
};
|
|
668
672
|
/** Create stable cache key from the options object */
|
|
669
673
|
const createOptionsCacheKey = (options) => JSON.stringify({
|
|
674
|
+
binaryAsFile: options?.binaryAsFile,
|
|
670
675
|
emptyString: options?.emptyString,
|
|
671
676
|
xml: options?.xml,
|
|
672
677
|
mode: options?.mode,
|
|
@@ -1092,11 +1097,27 @@ const generateExampleFromSchema = (schema, options, { level = 0, parentSchema, n
|
|
|
1092
1097
|
seen.delete(targetValue);
|
|
1093
1098
|
return cache(_schema, null, cacheKey, skipCache);
|
|
1094
1099
|
};
|
|
1100
|
+
/** Keep binary provenance for multipart callers without resolving schemas on the default data path. */
|
|
1101
|
+
const asBinaryFile = (schema, value, enabled = false) => {
|
|
1102
|
+
if (!enabled || typeof value !== 'string' || !value.startsWith('@')) {
|
|
1103
|
+
return value;
|
|
1104
|
+
}
|
|
1105
|
+
const resolved = resolve.schema(schema);
|
|
1106
|
+
if (resolved &&
|
|
1107
|
+
'type' in resolved &&
|
|
1108
|
+
resolved.type === 'string' &&
|
|
1109
|
+
'format' in resolved &&
|
|
1110
|
+
resolved.format === 'binary') {
|
|
1111
|
+
return new File([], value.slice(1), { lastModified: 0 });
|
|
1112
|
+
}
|
|
1113
|
+
return value;
|
|
1114
|
+
};
|
|
1095
1115
|
/** Generate data, optionally retaining the exact schema decisions for another output format. */
|
|
1096
1116
|
export const getExampleFromSchema = (schema, options, context = {}) => {
|
|
1097
1117
|
const capture = options?.[EXAMPLE_EVALUATION];
|
|
1098
1118
|
if (!capture) {
|
|
1099
|
-
|
|
1119
|
+
const value = generateExampleFromSchema(schema, options, context);
|
|
1120
|
+
return asBinaryFile(schema, value, options?.binaryAsFile);
|
|
1100
1121
|
}
|
|
1101
1122
|
const node = {
|
|
1102
1123
|
schema,
|
|
@@ -1115,7 +1136,7 @@ export const getExampleFromSchema = (schema, options, context = {}) => {
|
|
|
1115
1136
|
}
|
|
1116
1137
|
capture.stack.push(node);
|
|
1117
1138
|
try {
|
|
1118
|
-
node.value = generateExampleFromSchema(schema, options, context);
|
|
1139
|
+
node.value = asBinaryFile(schema, generateExampleFromSchema(schema, options, context), options?.binaryAsFile);
|
|
1119
1140
|
return node.value;
|
|
1120
1141
|
}
|
|
1121
1142
|
finally {
|
|
@@ -2,6 +2,7 @@ import type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensi
|
|
|
2
2
|
import type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies';
|
|
3
3
|
import type { ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
4
4
|
import type { OperationObject } from '@scalar/workspace-store/schemas/v3.2/strict/operation';
|
|
5
|
+
import type { ReservedPathParameter } from '../../helpers/encode-path-parameter.js';
|
|
5
6
|
import { type QuerystringParameter } from '../../helpers/querystring-parameter.js';
|
|
6
7
|
import { type BuildRequestSecurityResult } from '../../request-example/builder/security/build-request-security.js';
|
|
7
8
|
import type { SecuritySchemeObjectSecret } from '../../request-example/builder/security/secret-types.js';
|
|
@@ -74,6 +75,8 @@ import { type RequestBody } from './body/build-request-body.js';
|
|
|
74
75
|
* ```
|
|
75
76
|
*/
|
|
76
77
|
export type RequestFactory = {
|
|
78
|
+
/** Invalid active cookie declarations, retained for previews and reported before sending. */
|
|
79
|
+
cookieErrors?: string[];
|
|
77
80
|
/**
|
|
78
81
|
* The base API server URL prior to environment or server variable substitution.
|
|
79
82
|
* May still contain placeholders such as `{version}` or `{region}`.
|
|
@@ -94,6 +97,8 @@ export type RequestFactory = {
|
|
|
94
97
|
variables: Record<string, string>;
|
|
95
98
|
/** Names whose example is already URI-encoded. */
|
|
96
99
|
serializedParameters?: Set<string>;
|
|
100
|
+
/** Schema-based values using OpenAPI 3.2 reserved expansion. */
|
|
101
|
+
reservedParameters?: Record<string, ReservedPathParameter>;
|
|
97
102
|
/**
|
|
98
103
|
* The raw request path string, as entered by the user or read from the OpenAPI schema.
|
|
99
104
|
* Placeholders are not yet substituted.
|
|
@@ -198,7 +203,7 @@ export declare const requestFactory: ({ exampleName, globalCookies, method, oper
|
|
|
198
203
|
/** The selected security schemes for the current operation */
|
|
199
204
|
selectedSecuritySchemes: SecuritySchemeObjectSecret[];
|
|
200
205
|
/** Selected anyOf/oneOf request-body variants keyed by schema path */
|
|
201
|
-
/** Originating OpenAPI version, used for
|
|
206
|
+
/** Originating OpenAPI version, used for version-specific serialization. */
|
|
202
207
|
openapiVersion?: string;
|
|
203
208
|
requestBodyCompositionSelection?: Record<string, number>;
|
|
204
209
|
}) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-factory.d.ts","sourceRoot":"","sources":["../../../src/request-example/builder/request-factory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uDAAuD,CAAA;AAE5F,OAAO,EAAE,KAAK,oBAAoB,EAA2B,MAAM,iCAAiC,CAAA;AAEpG,OAAO,EACL,KAAK,0BAA0B,EAEhC,MAAM,2DAA2D,CAAA;AAClE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAA;AACjG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,EAAE,KAAK,WAAW,EAAoB,MAAM,2BAA2B,CAAA;AAG9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,IAAI,EAAE;QACJ;;;;;WAKG;QACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QACjC,kDAAkD;QAClD,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QAClC;;;;;WAKG;QACH,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IAED;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;OAGG;IACH,KAAK,EAAE,eAAe,CAAA;IAEtB,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAE1B,oFAAoF;IACpF,WAAW,CAAC,EAAE,oBAAoB,CAAA;IAElC;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAA;IAEhB;;;;OAIG;IACH,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;IAExB;;;;OAIG;IACH,OAAO,EAAE,aAAa,EAAE,CAAA;IAExB;;;OAGG;IACH,KAAK,EAAE,YAAY,CAAA;IAEnB;;;;OAIG;IACH,QAAQ,EAAE,0BAA0B,EAAE,CAAA;IAEtC;;;OAGG;IACH,8BAA8B,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAE5C;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;QACf;;;WAGG;QACH,UAAU,EAAE,OAAO,CAAA;QACnB;;;WAGG;QACH,eAAe,EAAE,OAAO,CAAA;KACzB,CAAC,CAAA;CACH,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,kLAa5B,kBAAkB,GAAG;IACtB,2BAA2B;IAC3B,SAAS,EAAE,eAAe,CAAA;IAC1B,8CAA8C;IAC9C,WAAW,EAAE,kBAAkB,CAAA;IAC/B,mCAAmC;IACnC,aAAa,EAAE,aAAa,EAAE,CAAA;IAC9B,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAA;IAChB,wBAAwB;IACxB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,qEAAqE;IACrE,UAAU,EAAE,OAAO,CAAA;IACnB,8DAA8D;IAC9D,uBAAuB,EAAE,0BAA0B,EAAE,CAAA;IACrD,sEAAsE;IACtE
|
|
1
|
+
{"version":3,"file":"request-factory.d.ts","sourceRoot":"","sources":["../../../src/request-example/builder/request-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ import { buildRequestParameters } from './header/build-request-parameters.js';
|
|
|
15
15
|
export const requestFactory = ({ exampleName, globalCookies, method, operation, path, proxyUrl, server, defaultHeaders, isElectron, selectedSecuritySchemes, openapiVersion, requestBodyCompositionSelection, }) => {
|
|
16
16
|
const requestBody = getResolvedRef(operation.requestBody);
|
|
17
17
|
/** Build out the request parameters */
|
|
18
|
-
const params = buildRequestParameters(operation.parameters ?? [], exampleName);
|
|
18
|
+
const params = buildRequestParameters(operation.parameters ?? [], exampleName, openapiVersion);
|
|
19
19
|
const querystringParameter = operation.parameters
|
|
20
20
|
?.map((parameter) => getResolvedRef(parameter))
|
|
21
21
|
.find((parameter) => parameter?.in === 'querystring');
|
|
@@ -52,11 +52,13 @@ export const requestFactory = ({ exampleName, globalCookies, method, operation,
|
|
|
52
52
|
headers.set('Pragma', 'no-cache');
|
|
53
53
|
}
|
|
54
54
|
const request = {
|
|
55
|
+
...(params.cookieErrors ? { cookieErrors: params.cookieErrors } : {}),
|
|
55
56
|
baseUrl,
|
|
56
57
|
proxyUrl,
|
|
57
58
|
path: {
|
|
58
59
|
variables: params.pathVariables,
|
|
59
60
|
...(params.serializedPathParameters ? { serializedParameters: params.serializedPathParameters } : {}),
|
|
61
|
+
...(params.reservedPathParameters ? { reservedParameters: params.reservedPathParameters } : {}),
|
|
60
62
|
raw: path,
|
|
61
63
|
},
|
|
62
64
|
query: params.urlParams,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-request-factory-url.d.ts","sourceRoot":"","sources":["../../../src/request-example/builder/resolve-request-factory-url.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"resolve-request-factory-url.d.ts","sourceRoot":"","sources":["../../../src/request-example/builder/resolve-request-factory-url.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,8BAA8B,CAAA;AAWnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAA;AAE/E;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAG,6BAAsC,CAAA;AAEjF;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAG,6BAAsC,CAAA;AAEjF,MAAM,MAAM,6BAA6B,GAAG,OAAO,2BAA2B,GAAG,OAAO,2BAA2B,CAAA;AAEnH,MAAM,MAAM,8BAA8B,GAAG,MAAM,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAA;AAK1F;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GACnC,SAAS,cAAc,EACvB,SAAS;IACP,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC,CAAA;IACzE,mBAAmB,EAAE,eAAe,CAAA;IACpC;;;OAGG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAA;CACxC,KACA,8BAuFF,CAAA"}
|
|
@@ -3,6 +3,7 @@ import { err, ok } from '@scalar/helpers/types/result';
|
|
|
3
3
|
import { safeRun } from '@scalar/helpers/types/safe-run';
|
|
4
4
|
import { isRelativePath } from '@scalar/helpers/url/is-relative-path';
|
|
5
5
|
import { mergeSearchParams, mergeUrls } from '@scalar/helpers/url/merge-urls';
|
|
6
|
+
import { assertReservedPathUrl, encodePathParameter, serializeReservedPathParameter, } from '../../helpers/encode-path-parameter.js';
|
|
6
7
|
import { serializeQuerystringParameter } from '../../helpers/querystring-parameter.js';
|
|
7
8
|
/**
|
|
8
9
|
* Discriminated error code when the merged request URL is not a complete absolute target
|
|
@@ -21,12 +22,21 @@ const INCOMPLETE_MERGED_URL_MESSAGE = 'No server URL is configured for this requ
|
|
|
21
22
|
*/
|
|
22
23
|
export const resolveRequestFactoryUrl = (request, options) => {
|
|
23
24
|
const variables = options.envVariables;
|
|
24
|
-
const pathVariablesEncoded = safeRun(() => Object.fromEntries(Object.entries(request.path.variables).map(([key, value]) =>
|
|
25
|
-
|
|
26
|
-
request.path.
|
|
27
|
-
?
|
|
28
|
-
:
|
|
29
|
-
|
|
25
|
+
const pathVariablesEncoded = safeRun(() => Object.fromEntries(Object.entries(request.path.variables).map(([key, value]) => {
|
|
26
|
+
const replace = (text) => replaceEnvVariables(text, variables);
|
|
27
|
+
const reserved = request.path.reservedParameters && Object.hasOwn(request.path.reservedParameters, key)
|
|
28
|
+
? request.path.reservedParameters[key]
|
|
29
|
+
: undefined;
|
|
30
|
+
const encoded = request.path.serializedParameters?.has(key)
|
|
31
|
+
? replace(value)
|
|
32
|
+
: reserved
|
|
33
|
+
? serializeReservedPathParameter(key, {
|
|
34
|
+
...reserved,
|
|
35
|
+
value: value === reserved.originalValue ? reserved.value : value,
|
|
36
|
+
}, replace)
|
|
37
|
+
: encodePathParameter(replace(value));
|
|
38
|
+
return [key, encoded];
|
|
39
|
+
})));
|
|
30
40
|
if (!pathVariablesEncoded.ok) {
|
|
31
41
|
return err(INVALID_REQUEST_FACTORY_URL, 'The request URL contains invalid characters in path parameters.');
|
|
32
42
|
}
|
|
@@ -44,7 +54,12 @@ export const resolveRequestFactoryUrl = (request, options) => {
|
|
|
44
54
|
const origin = globalThis.window?.location?.origin;
|
|
45
55
|
const urlBase = origin && origin !== 'null' ? origin : 'http://localhost:3000';
|
|
46
56
|
// Fallback for modal layout without a base server url (it should use the current origin)
|
|
47
|
-
const urlParsed = safeRun(() =>
|
|
57
|
+
const urlParsed = safeRun(() => {
|
|
58
|
+
if (request.path.reservedParameters && Object.keys(request.path.reservedParameters).length) {
|
|
59
|
+
assertReservedPathUrl(mergedUrl);
|
|
60
|
+
}
|
|
61
|
+
return new URL(mergedUrl, urlBase);
|
|
62
|
+
});
|
|
48
63
|
if (!urlParsed.ok) {
|
|
49
64
|
return err(INVALID_REQUEST_FACTORY_URL, 'The request URL could not be parsed. Check the server URL and path for invalid characters.');
|
|
50
65
|
}
|
|
@@ -2,7 +2,10 @@ import type { EncryptionSchemeType, SaslSchemeType } from '../../../request-exam
|
|
|
2
2
|
import type { XScalarAuthUrl, XScalarCredentialsLocation, XScalarSecretClientCertificate, XScalarSecretClientId, XScalarSecretClientSecret, XScalarSecretHTTP, XScalarSecretPrivateKey, XScalarSecretRedirectUri, XScalarSecretRefreshToken, XScalarSecretServiceName, XScalarSecretToken, XScalarTokenUrl } from '../../../schemas/extensions/security/index.js';
|
|
3
3
|
import type { OAuthFlowAuthorizationCode, OAuthFlowClientCredentials, OAuthFlowDeviceAuthorization, OAuthFlowImplicit, OAuthFlowPassword } from '../../../schemas/v3.2/strict/oauth-flow.js';
|
|
4
4
|
import type { ApiKeyObject, HttpObject, MutualTlsObject, OAuth2Object, OpenIdConnectObject } from '../../../schemas/v3.2/strict/security-scheme.js';
|
|
5
|
-
type OAuthFlowCommonSecret = XScalarSecretClientId & XScalarSecretToken & XScalarSecretRefreshToken & XScalarAuthUrl & XScalarTokenUrl
|
|
5
|
+
type OAuthFlowCommonSecret = XScalarSecretClientId & XScalarSecretToken & XScalarSecretRefreshToken & XScalarAuthUrl & XScalarTokenUrl & {
|
|
6
|
+
/** Explicit clears are carried to the auth UI to prevent default prefill after remount. */
|
|
7
|
+
'x-scalar-secret-cleared-fields'?: string[];
|
|
8
|
+
};
|
|
6
9
|
export type OAuthFlowImplicitSecret = OAuthFlowImplicit & OAuthFlowCommonSecret & XScalarSecretRedirectUri;
|
|
7
10
|
export type OAuthFlowPasswordSecret = OAuthFlowPassword & OAuthFlowCommonSecret & XScalarSecretHTTP & XScalarSecretClientSecret & XScalarCredentialsLocation;
|
|
8
11
|
export type OAuthFlowClientCredentialsSecret = OAuthFlowClientCredentials & OAuthFlowCommonSecret & XScalarSecretClientSecret & XScalarCredentialsLocation;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-types.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/security/secret-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAA;AAClH,OAAO,KAAK,EACV,cAAc,EACd,0BAA0B,EAC1B,8BAA8B,EAC9B,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EAChB,MAAM,+BAA+B,CAAA;AACtC,OAAO,KAAK,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,4BAA4B,EAC5B,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,eAAe,EACf,YAAY,EACZ,mBAAmB,EACpB,MAAM,uCAAuC,CAAA;AAE9C,KAAK,qBAAqB,GAAG,qBAAqB,GAChD,kBAAkB,GAClB,yBAAyB,GACzB,cAAc,GACd,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"secret-types.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/security/secret-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAA;AAClH,OAAO,KAAK,EACV,cAAc,EACd,0BAA0B,EAC1B,8BAA8B,EAC9B,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EAChB,MAAM,+BAA+B,CAAA;AACtC,OAAO,KAAK,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,4BAA4B,EAC5B,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,kCAAkC,CAAA;AACzC,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,eAAe,EACf,YAAY,EACZ,mBAAmB,EACpB,MAAM,uCAAuC,CAAA;AAE9C,KAAK,qBAAqB,GAAG,qBAAqB,GAChD,kBAAkB,GAClB,yBAAyB,GACzB,cAAc,GACd,eAAe,GAAG;IAChB,2FAA2F;IAC3F,gCAAgC,CAAC,EAAE,MAAM,EAAE,CAAA;CAC5C,CAAA;AAEH,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG,qBAAqB,GAAG,wBAAwB,CAAA;AAE1G,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GACrD,qBAAqB,GACrB,iBAAiB,GACjB,yBAAyB,GACzB,0BAA0B,CAAA;AAE5B,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,GACvE,qBAAqB,GACrB,yBAAyB,GACzB,0BAA0B,CAAA;AAE5B,MAAM,MAAM,gCAAgC,GAAG,0BAA0B,GACvE,qBAAqB,GACrB,yBAAyB,GACzB,wBAAwB,GACxB,0BAA0B,CAAA;AAE5B,6FAA6F;AAC7F,MAAM,MAAM,kCAAkC,GAAG,4BAA4B,GAC3E,qBAAqB,GACrB,yBAAyB,CAAA;AAE3B,MAAM,MAAM,sBAAsB,GAAG;IACnC,mBAAmB,CAAC,EAAE,kCAAkC,CAAA;IACxD,QAAQ,CAAC,EAAE,uBAAuB,CAAA;IAClC,QAAQ,CAAC,EAAE,uBAAuB,CAAA;IAClC,iBAAiB,CAAC,EAAE,gCAAgC,CAAA;IACpD,iBAAiB,CAAC,EAAE,gCAAgC,CAAA;CACrD,CAAA;AAED,gFAAgF;AAChF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,QAAQ,CAAA;IACd,EAAE,EAAE,MAAM,GAAG,UAAU,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,YAAY,GAAG,kBAAkB,CAAC,GAAG,kBAAkB,CAAA;AACzF,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,iBAAiB,GAAG,kBAAkB,CAAA;AAClF,wGAAwG;AACxG,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAA;AACnD,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;IAAE,KAAK,EAAE,sBAAsB,CAAA;CAAE,CAAA;AAChG,MAAM,MAAM,yBAAyB,GAAG,mBAAmB,GAAG;IAAE,KAAK,CAAC,EAAE,sBAAsB,CAAA;CAAE,CAAA;AAEhG;;;GAGG;AACH,KAAK,oBAAoB,CAAC,CAAC,SAAS,MAAM,IAAI;IAC5C,IAAI,EAAE,CAAC,CAAA;IACP,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,cAAc,CAAC,GAAG,iBAAiB,CAAA;AAEvF,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,MAAM,CAAC,GAAG,8BAA8B,GAAG,uBAAuB,CAAA;AAEtH,wFAAwF;AACxF,MAAM,MAAM,sBAAsB,GAAG,oBAAoB,CAAC,oBAAoB,CAAC,GAAG,kBAAkB,CAAA;AAEpG,4FAA4F;AAC5F,MAAM,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,GAAG,wBAAwB,CAAA;AAE1F,MAAM,MAAM,0BAA0B,GAClC,kBAAkB,GAClB,gBAAgB,GAChB,qBAAqB,GACrB,yBAAyB,GACzB,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,sBAAsB,GACtB,kBAAkB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-security-scheme-secrets.d.ts","sourceRoot":"","sources":["../../../../src/request-example/context/security/extract-security-scheme-secrets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAA2C,MAAM,uCAAuC,CAAA;
|
|
1
|
+
{"version":3,"file":"extract-security-scheme-secrets.d.ts","sourceRoot":"","sources":["../../../../src/request-example/context/security/extract-security-scheme-secrets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAA2C,MAAM,uCAAuC,CAAA;AAE/G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iDAAiD,CAAA;AAQlF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAA;AAExG,OAAO,KAAK,EAEV,kBAAkB,EAClB,sBAAsB,EAUtB,gBAAgB,EAChB,0BAA0B,EAE3B,MAAM,iDAAiD,CAAA;AAGxD,wGAAwG;AACxG,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,WAAW,CAAC,cAAc,CAAC,CAAA;AAEjF,KAAK,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,sBAAsB,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,QAAQ,CAAA;AACrG,KAAK,gBAAgB,GAAG;KACrB,CAAC,IAAI,gBAAgB,GAAG;QACvB,IAAI,EAAE,CAAC,CAAA;QACP,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,KAAK,CAAC,EAAE,MAAM,CAAA;KACf;CACF,CAAC,gBAAgB,CAAC,CAAA;AAyNnB,6DAA6D;AAC7D,eAAO,MAAM,4BAA4B,GAEvC,QAAQ,gBAAgB,GAAG,gBAAgB,GAAG,CAAC,kBAAkB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACvF,WAAW,SAAS,EACpB,MAAM,MAAM,EACZ,cAAc,MAAM,EACpB,oBAAoB,MAAM,KACzB,0BAqHF,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isObject } from '@scalar/helpers/object/is-object';
|
|
2
2
|
import { objectEntries } from '@scalar/helpers/object/object-entries';
|
|
3
|
+
import { isSecretFieldCleared } from '@scalar/workspace-store/helpers/auth-secret-fields';
|
|
3
4
|
/**
|
|
4
5
|
* Maps x-scalar-secret fields to their corresponding input field names.
|
|
5
6
|
* This allows us to fall back to config values when auth store secrets are not available.
|
|
@@ -14,24 +15,30 @@ const SECRET_TO_INPUT_FIELD_MAP = {
|
|
|
14
15
|
'x-scalar-secret-auth-url': 'authorizationUrl',
|
|
15
16
|
'x-scalar-secret-token-url': 'tokenUrl',
|
|
16
17
|
};
|
|
17
|
-
const mergeFlowSecrets = (properties, configSecrets, authStoreSecrets = {}, oauth2RedirectUri) =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}));
|
|
18
|
+
const mergeFlowSecrets = (properties, configSecrets, authStoreSecrets = {}, oauth2RedirectUri) => {
|
|
19
|
+
const clearedFields = properties.filter((property) => isSecretFieldCleared(authStoreSecrets, property));
|
|
20
|
+
const values = Object.fromEntries(properties.map((property) => {
|
|
21
|
+
// Preserve explicit clears, while legacy schema-filled empties still inherit defaults.
|
|
22
|
+
const authStoreValue = typeof authStoreSecrets[property] === 'string' ? authStoreSecrets[property] : undefined;
|
|
23
|
+
const configValue = typeof configSecrets[property] === 'string' ? configSecrets[property] : undefined;
|
|
24
|
+
const configInputValue = typeof configSecrets[SECRET_TO_INPUT_FIELD_MAP[property]] === 'string'
|
|
25
|
+
? configSecrets[SECRET_TO_INPUT_FIELD_MAP[property]]
|
|
26
|
+
: undefined;
|
|
27
|
+
// oauth2RedirectUri (top-level config option) is used as a global fallback for the redirect URI,
|
|
28
|
+
// applied only when neither the auth store nor per-scheme config have a value. This ensures
|
|
29
|
+
// the configured redirect URI persists when switching between documents with the same OAuth config,
|
|
30
|
+
// because each document starts with no stored redirect URI (authStoreValue === undefined).
|
|
31
|
+
const value = property === 'x-scalar-secret-redirect-uri' || isSecretFieldCleared(authStoreSecrets, property)
|
|
32
|
+
? (authStoreValue ?? configValue ?? configInputValue ?? oauth2RedirectUri ?? '')
|
|
33
|
+
: authStoreValue || configValue || configInputValue || '';
|
|
34
|
+
return [property, value];
|
|
35
|
+
}));
|
|
36
|
+
return { ...values, ...(clearedFields.length ? { 'x-scalar-secret-cleared-fields': clearedFields } : {}) };
|
|
37
|
+
};
|
|
38
|
+
const storedSecret = (secrets, field) => {
|
|
39
|
+
const value = secrets && Reflect.get(secrets, field);
|
|
40
|
+
return typeof value === 'string' && (value || isSecretFieldCleared(secrets ?? {}, field)) ? value : undefined;
|
|
41
|
+
};
|
|
35
42
|
/** Secret extensions are not part of the strict scheme types, so they are read the same way the OAuth flows read theirs */
|
|
36
43
|
const documentSecret = (scheme, property) => {
|
|
37
44
|
const value = property in scheme ? Reflect.get(scheme, property) : undefined;
|
|
@@ -151,10 +158,8 @@ scheme, authStore, name, documentSlug, oauth2RedirectUri) => {
|
|
|
151
158
|
const storeSecrets = secrets?.type === 'apiKey' ? secrets : undefined;
|
|
152
159
|
return {
|
|
153
160
|
...scheme,
|
|
154
|
-
'x-scalar-secret-token': storeSecrets
|
|
155
|
-
documentSecret(scheme, 'x-scalar-secret-token') ||
|
|
156
|
-
scheme.value ||
|
|
157
|
-
'',
|
|
161
|
+
'x-scalar-secret-token': storedSecret(storeSecrets, 'x-scalar-secret-token') ??
|
|
162
|
+
(documentSecret(scheme, 'x-scalar-secret-token') || scheme.value || ''),
|
|
158
163
|
};
|
|
159
164
|
}
|
|
160
165
|
// Handle HTTP Auth security schemes (e.g., Basic, Bearer)
|
|
@@ -162,18 +167,12 @@ scheme, authStore, name, documentSlug, oauth2RedirectUri) => {
|
|
|
162
167
|
const storeSecrets = secrets?.type === 'http' ? secrets : undefined;
|
|
163
168
|
return {
|
|
164
169
|
...scheme,
|
|
165
|
-
'x-scalar-secret-token': storeSecrets
|
|
166
|
-
documentSecret(scheme, 'x-scalar-secret-token') ||
|
|
167
|
-
|
|
168
|
-
'',
|
|
169
|
-
'x-scalar-secret-
|
|
170
|
-
documentSecret(scheme, 'x-scalar-secret-
|
|
171
|
-
scheme.username ||
|
|
172
|
-
'',
|
|
173
|
-
'x-scalar-secret-password': storeSecrets?.['x-scalar-secret-password'] ||
|
|
174
|
-
documentSecret(scheme, 'x-scalar-secret-password') ||
|
|
175
|
-
scheme.password ||
|
|
176
|
-
'',
|
|
170
|
+
'x-scalar-secret-token': storedSecret(storeSecrets, 'x-scalar-secret-token') ??
|
|
171
|
+
(documentSecret(scheme, 'x-scalar-secret-token') || scheme.token || ''),
|
|
172
|
+
'x-scalar-secret-username': storedSecret(storeSecrets, 'x-scalar-secret-username') ??
|
|
173
|
+
(documentSecret(scheme, 'x-scalar-secret-username') || scheme.username || ''),
|
|
174
|
+
'x-scalar-secret-password': storedSecret(storeSecrets, 'x-scalar-secret-password') ??
|
|
175
|
+
(documentSecret(scheme, 'x-scalar-secret-password') || scheme.password || ''),
|
|
177
176
|
};
|
|
178
177
|
}
|
|
179
178
|
// Handle OAuth2 security schemes and all supported flows
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -5,7 +5,7 @@ import { isHttpMethod } from '@scalar/helpers/http/is-http-method';
|
|
|
5
5
|
import { parseJsonPointerSegments } from '@scalar/helpers/json/parse-json-pointer-segments';
|
|
6
6
|
import { getValueAtPath } from '@scalar/helpers/object/get-value-at-path';
|
|
7
7
|
import { preventPollution } from '@scalar/helpers/object/prevent-pollution';
|
|
8
|
-
import { extensions as bundleExtensions } from '@scalar/json-magic/bundle';
|
|
8
|
+
import { bundle, extensions as bundleExtensions } from '@scalar/json-magic/bundle';
|
|
9
9
|
import { fetchUrls, readFiles } from '@scalar/json-magic/bundle/plugins/node';
|
|
10
10
|
import { escapeJsonPointer } from '@scalar/json-magic/helpers/escape-json-pointer';
|
|
11
11
|
import { unescapeJsonPointer } from '@scalar/json-magic/helpers/unescape-json-pointer';
|
|
@@ -14,7 +14,7 @@ import { upgrade } from '@scalar/openapi-upgrader';
|
|
|
14
14
|
import { asyncApiObjectSchema } from '@scalar/schemas/asyncapi/3.1';
|
|
15
15
|
import { coerce } from '@scalar/validation';
|
|
16
16
|
import { asyncApiChunkGroups } from './helpers/asyncapi-chunk-groups.js';
|
|
17
|
-
import { CHUNK_INDEX_KEY, buildChunkIndex, chunkRefTemplates, chunkReference, fillChunkRef, navigationHeader, } from './helpers/chunk-index.js';
|
|
17
|
+
import { CHUNK_INDEX_KEY, buildChunkIndex, chunkRefTemplates, chunkReference, encodeSsrComponentName, fillChunkRef, navigationHeader, } from './helpers/chunk-index.js';
|
|
18
18
|
import { createChunkWriter } from './helpers/create-chunk-writer.js';
|
|
19
19
|
import { deepClone } from './helpers/deep-clone.js';
|
|
20
20
|
import { encodeChunkName } from './helpers/encode-chunk-name.js';
|
|
@@ -23,8 +23,9 @@ import { keyOf } from './helpers/general.js';
|
|
|
23
23
|
import { getResolvedRef } from './helpers/get-resolved-ref.js';
|
|
24
24
|
import { mergeObjects } from './helpers/merge-object.js';
|
|
25
25
|
import { normalizeBooleanSchemas } from './helpers/normalize-boolean-schemas.js';
|
|
26
|
+
import { resolveSecurityRequirements } from './helpers/resolve-security-requirements.js';
|
|
26
27
|
import { createNavigation, traverseAsyncApiDocument } from './navigation/index.js';
|
|
27
|
-
import { resolveOpenApiDocument } from './plugins/bundler/openapi-document.js';
|
|
28
|
+
import { openApiDocument, resolveOpenApiDocument } from './plugins/bundler/openapi-document.js';
|
|
28
29
|
import { extensions } from './schemas/extensions.js';
|
|
29
30
|
import { isAsyncApiDocument } from './schemas/type-guards.js';
|
|
30
31
|
import { coerceValue } from './schemas/typebox-coerce.js';
|
|
@@ -62,7 +63,12 @@ const resolveLocalReferences = (document) => createMagicProxy(document, {
|
|
|
62
63
|
* because the generated chunks keep their `#/x-ext/…` pointers and the client resolves those against
|
|
63
64
|
* the document root. Only the client's export path (`purgeInternalDocumentKeys`) strips them.
|
|
64
65
|
*/
|
|
65
|
-
const BUNDLED_EXTERNAL_KEYS = [
|
|
66
|
+
const BUNDLED_EXTERNAL_KEYS = [
|
|
67
|
+
bundleExtensions.externalDocuments,
|
|
68
|
+
bundleExtensions.externalDocumentsMappings,
|
|
69
|
+
'x-scalar-security-uri-aliases',
|
|
70
|
+
'x-scalar-original-security-keys',
|
|
71
|
+
];
|
|
66
72
|
/**
|
|
67
73
|
* Copies the buckets bundling parks external documents in onto the coerced document.
|
|
68
74
|
*
|
|
@@ -157,7 +163,7 @@ export function externalizeComponentReferences(document, meta) {
|
|
|
157
163
|
type,
|
|
158
164
|
Object.fromEntries(Object.keys(component).map((name) => {
|
|
159
165
|
const ref = meta.mode === 'ssr'
|
|
160
|
-
? `${meta.baseUrl}/${meta.name}/components/${type}/${name}#`
|
|
166
|
+
? `${meta.baseUrl}/${meta.name}/components/${type}/${encodeSsrComponentName(name)}#`
|
|
161
167
|
: `./chunks/${encodeChunkName(meta.name)}/components/${encodeChunkName(type)}/${encodeChunkName(name)}.json#`;
|
|
162
168
|
return [name, { '$ref': ref, $global: true }];
|
|
163
169
|
})),
|
|
@@ -502,7 +508,17 @@ export async function createServerWorkspaceStore(workspaceProps) {
|
|
|
502
508
|
console.warn(`Failed to load document "${input.name}"`);
|
|
503
509
|
return;
|
|
504
510
|
}
|
|
505
|
-
|
|
511
|
+
const loaded = document.data;
|
|
512
|
+
const isThreeTwo = typeof loaded.openapi === 'string' && /^3\.2\.\d+$/.test(loaded.openapi);
|
|
513
|
+
// URI resolution adds working aliases; keep the caller's authored object unchanged.
|
|
514
|
+
const data = isThreeTwo ? JSON.parse(document.raw) : loaded;
|
|
515
|
+
const origin = 'url' in input ? input.url : 'path' in input ? input.path : undefined;
|
|
516
|
+
const loaders = [fetchUrls(), readFiles()];
|
|
517
|
+
if (isThreeTwo) {
|
|
518
|
+
await bundle(data, { origin, treeShake: false, urlMap: true, plugins: [openApiDocument(), ...loaders] });
|
|
519
|
+
await resolveSecurityRequirements(data, { origin, loaders });
|
|
520
|
+
}
|
|
521
|
+
addDocumentSync(data, { name: input.name, ...input.meta }, navigationOptions);
|
|
506
522
|
}
|
|
507
523
|
catch (error) {
|
|
508
524
|
// Honours the contract above: a document that cannot be processed is skipped rather than
|
|
@@ -592,7 +608,18 @@ export async function createServerWorkspaceStore(workspaceProps) {
|
|
|
592
608
|
const segments = pointerPath.split('/').slice(1);
|
|
593
609
|
const path = segments[1] === 'asyncapi'
|
|
594
610
|
? segments.map((segment) => escapeJsonPointer(decodeURIComponent(segment).replaceAll('~1', '/').replaceAll('~0', '~')))
|
|
595
|
-
: parseJsonPointerSegments(
|
|
611
|
+
: parseJsonPointerSegments(segments[1] === 'components' && !pointer.startsWith('#')
|
|
612
|
+
? `/${segments
|
|
613
|
+
.map((segment) => {
|
|
614
|
+
try {
|
|
615
|
+
return decodeURIComponent(segment);
|
|
616
|
+
}
|
|
617
|
+
catch {
|
|
618
|
+
return segment;
|
|
619
|
+
}
|
|
620
|
+
})
|
|
621
|
+
.join('/')}`
|
|
622
|
+
: pointerPath).map((segment, index) => segments[1] === 'components' && index >= 3 ? segment : escapeJsonPointer(segment));
|
|
596
623
|
return getValueAtPath(assets, path);
|
|
597
624
|
},
|
|
598
625
|
addDocument,
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"openapi",
|
|
17
17
|
"scalar"
|
|
18
18
|
],
|
|
19
|
-
"version": "0.68.
|
|
19
|
+
"version": "0.68.2",
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=22"
|
|
22
22
|
},
|
|
@@ -153,14 +153,14 @@
|
|
|
153
153
|
"CHANGELOG.md"
|
|
154
154
|
],
|
|
155
155
|
"dependencies": {
|
|
156
|
-
"@scalar/asyncapi-upgrader": "0.1.
|
|
157
|
-
"@scalar/helpers": "0.16.
|
|
158
|
-
"@scalar/json-magic": "0.15.
|
|
159
|
-
"@scalar/openapi-upgrader": "0.4.
|
|
160
|
-
"@scalar/schemas": "0.
|
|
161
|
-
"@scalar/snippetz": "0.10.
|
|
156
|
+
"@scalar/asyncapi-upgrader": "0.1.16",
|
|
157
|
+
"@scalar/helpers": "0.16.2",
|
|
158
|
+
"@scalar/json-magic": "0.15.6",
|
|
159
|
+
"@scalar/openapi-upgrader": "0.4.3",
|
|
160
|
+
"@scalar/schemas": "0.13.1",
|
|
161
|
+
"@scalar/snippetz": "0.10.7",
|
|
162
162
|
"@scalar/typebox": "0.1.3",
|
|
163
|
-
"@scalar/types": "0.
|
|
163
|
+
"@scalar/types": "0.23.1",
|
|
164
164
|
"@scalar/validation": "0.6.6",
|
|
165
165
|
"js-base64": "^3.9.2",
|
|
166
166
|
"type-fest": "^5.8.0",
|