@scalar/workspace-store 0.62.0 → 0.64.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 +36 -0
- package/README.md +88 -0
- package/dist/client.d.ts +28 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +217 -135
- package/dist/helpers/chunk-index.d.ts +95 -0
- package/dist/helpers/chunk-index.d.ts.map +1 -0
- package/dist/helpers/chunk-index.js +139 -0
- package/dist/helpers/detect-changes-proxy.d.ts +7 -6
- package/dist/helpers/detect-changes-proxy.d.ts.map +1 -1
- package/dist/helpers/detect-changes-proxy.js +83 -38
- package/dist/helpers/document-revision.d.ts +26 -0
- package/dist/helpers/document-revision.d.ts.map +1 -0
- package/dist/helpers/document-revision.js +47 -0
- package/dist/helpers/external-examples.d.ts +17 -0
- package/dist/helpers/external-examples.d.ts.map +1 -0
- package/dist/helpers/external-examples.js +50 -0
- package/dist/helpers/get-resolved-ref-deep.d.ts.map +1 -1
- package/dist/helpers/get-resolved-ref-deep.js +25 -13
- package/dist/helpers/get-resolved-ref.d.ts.map +1 -1
- package/dist/helpers/get-resolved-ref.js +61 -3
- package/dist/helpers/operation-examples.d.ts +6 -0
- package/dist/helpers/operation-examples.d.ts.map +1 -0
- package/dist/helpers/operation-examples.js +45 -0
- package/dist/helpers/unpack-proxy.d.ts +10 -0
- package/dist/helpers/unpack-proxy.d.ts.map +1 -1
- package/dist/helpers/unpack-proxy.js +15 -0
- package/dist/helpers/use-external-examples.d.ts +15 -0
- package/dist/helpers/use-external-examples.d.ts.map +1 -0
- package/dist/helpers/use-external-examples.js +55 -0
- package/dist/mutators/operation/parameters.d.ts.map +1 -1
- package/dist/mutators/operation/parameters.js +28 -9
- 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 +12 -3
- package/dist/request-example/builder/header/is-param-disabled.d.ts +2 -2
- package/dist/request-example/builder/header/is-param-disabled.d.ts.map +1 -1
- package/dist/request-example/builder/header/is-param-disabled.js +5 -4
- 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 +21 -1
- package/dist/request-example/builder/helpers/get-example.d.ts +2 -0
- package/dist/request-example/builder/helpers/get-example.d.ts.map +1 -1
- package/dist/request-example/builder/helpers/get-example.js +9 -7
- package/dist/request-example/context/headers.d.ts.map +1 -1
- package/dist/request-example/context/headers.js +3 -4
- package/dist/resolve.d.ts +10 -2
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +9 -1
- package/dist/schemas/v3.2/strict/openapi-document.d.ts.map +1 -1
- package/dist/schemas/v3.2/strict/openapi-document.js +17 -1
- package/dist/server.d.ts +16 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +34 -9
- package/package.json +3 -3
|
@@ -1,7 +1,64 @@
|
|
|
1
1
|
import { isObject } from '@scalar/helpers/object/is-object';
|
|
2
|
+
/**
|
|
3
|
+
* Keys the store writes on an externalized stub for its own bookkeeping.
|
|
4
|
+
*
|
|
5
|
+
* They describe the stub — whether it is shared across documents, whether its chunk has loaded — not the
|
|
6
|
+
* node it points at.
|
|
7
|
+
*/
|
|
8
|
+
const STUB_BOOKKEEPING_KEYS = new Set(['$global', '$status']);
|
|
9
|
+
const isReferenceNode = (value) => typeof value === 'object' && value !== null && '$ref' in value;
|
|
10
|
+
/**
|
|
11
|
+
* Whether a reference is pure indirection: a `$ref` and the store's own bookkeeping, nothing more.
|
|
12
|
+
*
|
|
13
|
+
* A reference that carries anything else is a schema in its own right — an `$id` opens a schema
|
|
14
|
+
* resource, `$defs` and `$dynamicAnchor` bind a generic's type parameter, and `description` annotates
|
|
15
|
+
* the target — so it stays its own hop and the caller resolves it as it descends, the way it always
|
|
16
|
+
* has. Collapsing such a node into the one it points at merges two schema resources into one, and the
|
|
17
|
+
* `$dynamicRef` in the inner one then has no outer scope left to bind against.
|
|
18
|
+
*/
|
|
19
|
+
const isPassThroughReference = (node) => {
|
|
20
|
+
for (const key of Object.keys(node)) {
|
|
21
|
+
if (key !== '$ref' && key !== '$ref-value' && !STUB_BOOKKEEPING_KEYS.has(key)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Follow `$ref-value` onward for as long as it lands on another reference that is pure indirection.
|
|
29
|
+
*
|
|
30
|
+
* A reference can point at a second reference. `resolve()` on a static or SSR workspace leaves exactly
|
|
31
|
+
* that behind: the component stays in the document as a `{ $ref: '#/x-ext/<hash>', $global: true }` stub
|
|
32
|
+
* and the content lives under `x-ext`, so `#/components/schemas/User` reaches the schema in two hops.
|
|
33
|
+
* Stopping at the first hop hands consumers the stub, a node with no `type` and no `properties`, which
|
|
34
|
+
* renders as an empty, non-expandable schema.
|
|
35
|
+
*
|
|
36
|
+
* Stops at a reference that has not been resolved yet and hands that node back, which is what a single
|
|
37
|
+
* hop onto an unresolved reference produces today. `seen` terminates a reference cycle on the node it
|
|
38
|
+
* comes back around to rather than looping.
|
|
39
|
+
*
|
|
40
|
+
* @param value - The value the first hop produced.
|
|
41
|
+
* @param seen - References already crossed, including the node the chain started at.
|
|
42
|
+
*/
|
|
43
|
+
const followPassThroughReferences = (value, seen) => {
|
|
44
|
+
let current = value;
|
|
45
|
+
while (isReferenceNode(current) && isPassThroughReference(current) && !seen.has(current)) {
|
|
46
|
+
const next = current['$ref-value'];
|
|
47
|
+
if (next === undefined) {
|
|
48
|
+
return current;
|
|
49
|
+
}
|
|
50
|
+
seen.add(current);
|
|
51
|
+
current = next;
|
|
52
|
+
}
|
|
53
|
+
return current;
|
|
54
|
+
};
|
|
2
55
|
const defaultTransform = (node) => {
|
|
3
56
|
// Unresolved references have no value; callers must account for that state.
|
|
4
|
-
|
|
57
|
+
const value = node['$ref-value'];
|
|
58
|
+
if (value === undefined) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
return followPassThroughReferences(value, new Set([node]));
|
|
5
62
|
};
|
|
6
63
|
/**
|
|
7
64
|
* Transform for getResolvedRef that merges sibling properties of a $ref wrapper
|
|
@@ -10,15 +67,16 @@ const defaultTransform = (node) => {
|
|
|
10
67
|
*/
|
|
11
68
|
export const mergeSiblingReferences = (node) => {
|
|
12
69
|
const { '$ref-value': value, ...rest } = node;
|
|
70
|
+
const target = value === undefined ? undefined : followPassThroughReferences(value, new Set([node]));
|
|
13
71
|
// A reference can land on something that is not a record: a pointer that aims at a string
|
|
14
72
|
// (`$ref: '#/info/title'`), one that was never resolved, or one whose target is an array. Spreading
|
|
15
73
|
// any of those copies it index by index, so a reference to a title becomes `{ 0: 'G', 1: 'a', … }`
|
|
16
74
|
// and every consumer downstream treats those digits as real properties. There is nothing to merge
|
|
17
75
|
// siblings onto in that case, so only the siblings survive.
|
|
18
|
-
if (!isObject(
|
|
76
|
+
if (!isObject(target)) {
|
|
19
77
|
return rest;
|
|
20
78
|
}
|
|
21
|
-
return { ...
|
|
79
|
+
return { ...target, ...rest };
|
|
22
80
|
};
|
|
23
81
|
export function getResolvedRef(node, transform = defaultTransform) {
|
|
24
82
|
if (typeof node === 'object' && node !== null && '$ref' in node) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ExampleObject, OperationObject } from '../schemas/v3.2/strict/openapi-document.js';
|
|
2
|
+
/** The request body and parameter examples needed by a single request, never its responses. */
|
|
3
|
+
export declare const getOperationExamples: (operation: OperationObject, key: string, contentType?: string) => (ExampleObject | undefined)[];
|
|
4
|
+
/** Overlay fetched values for request consumers without persisting them as document edits. */
|
|
5
|
+
export declare const resolveOperationExamples: (operation: OperationObject, key: string, contentType: string | undefined, resolve: (example: ExampleObject | undefined) => ExampleObject | undefined) => OperationObject;
|
|
6
|
+
//# sourceMappingURL=operation-examples.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-examples.d.ts","sourceRoot":"","sources":["../../src/helpers/operation-examples.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAmB,eAAe,EAAE,MAAM,wCAAwC,CAAA;AAE7G,+FAA+F;AAC/F,eAAO,MAAM,oBAAoB,GAC/B,WAAW,eAAe,EAC1B,KAAK,MAAM,EACX,cAAc,MAAM,KACnB,CAAC,aAAa,GAAG,SAAS,CAAC,EAS7B,CAAA;AAED,8FAA8F;AAC9F,eAAO,MAAM,wBAAwB,GACnC,WAAW,eAAe,EAC1B,KAAK,MAAM,EACX,aAAa,MAAM,GAAG,SAAS,EAC/B,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,KAAK,aAAa,GAAG,SAAS,KACzE,eA6BF,CAAA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getResolvedRef } from '../helpers/get-resolved-ref.js';
|
|
2
|
+
import { getExample } from '../request-example/builder/helpers/get-example.js';
|
|
3
|
+
/** The request body and parameter examples needed by a single request, never its responses. */
|
|
4
|
+
export const getOperationExamples = (operation, key, contentType) => {
|
|
5
|
+
const body = getResolvedRef(operation.requestBody);
|
|
6
|
+
return [
|
|
7
|
+
body ? getExample(body, key, contentType) : undefined,
|
|
8
|
+
...(operation.parameters ?? []).map((parameter) => {
|
|
9
|
+
const resolved = getResolvedRef(parameter);
|
|
10
|
+
return resolved ? getExample(resolved, key, undefined) : undefined;
|
|
11
|
+
}),
|
|
12
|
+
];
|
|
13
|
+
};
|
|
14
|
+
/** Overlay fetched values for request consumers without persisting them as document edits. */
|
|
15
|
+
export const resolveOperationExamples = (operation, key, contentType, resolve) => {
|
|
16
|
+
const mapMedia = (media) => {
|
|
17
|
+
const selected = key || Object.keys(media.examples ?? {})[0];
|
|
18
|
+
const example = selected ? getResolvedRef(media.examples?.[selected]) : undefined;
|
|
19
|
+
const resolved = resolve(example);
|
|
20
|
+
return selected && resolved && resolved !== example
|
|
21
|
+
? { ...media, examples: { ...media.examples, [selected]: resolved } }
|
|
22
|
+
: media;
|
|
23
|
+
};
|
|
24
|
+
const body = getResolvedRef(operation.requestBody);
|
|
25
|
+
const type = contentType ?? Object.keys(body?.content ?? {})[0];
|
|
26
|
+
return {
|
|
27
|
+
...operation,
|
|
28
|
+
...(body && type && body.content[type]
|
|
29
|
+
? {
|
|
30
|
+
requestBody: { ...body, content: { ...body.content, [type]: mapMedia(body.content[type]) } },
|
|
31
|
+
}
|
|
32
|
+
: {}),
|
|
33
|
+
parameters: operation.parameters?.map((parameter) => {
|
|
34
|
+
const resolved = getResolvedRef(parameter);
|
|
35
|
+
if (!resolved)
|
|
36
|
+
return parameter;
|
|
37
|
+
const content = 'content' in resolved ? resolved.content : undefined;
|
|
38
|
+
const mediaType = Object.keys(content ?? {})[0];
|
|
39
|
+
if (mediaType && content?.[mediaType]) {
|
|
40
|
+
return { ...resolved, content: { ...content, [mediaType]: mapMedia(content[mediaType]) } };
|
|
41
|
+
}
|
|
42
|
+
return { ...resolved, ...mapMedia(resolved) };
|
|
43
|
+
}),
|
|
44
|
+
};
|
|
45
|
+
};
|
|
@@ -13,6 +13,16 @@
|
|
|
13
13
|
* @param depth - Optional, limits recursion depth. `null` means unlimited depth (default is 1).
|
|
14
14
|
* @returns - A plain object or array with all proxies removed up to the specified depth.
|
|
15
15
|
*/
|
|
16
|
+
/**
|
|
17
|
+
* Strips the known proxies (Vue reactivity, overrides, detect-changes, magic) from a value without
|
|
18
|
+
* touching its properties, returning the raw object underneath.
|
|
19
|
+
*
|
|
20
|
+
* Use this when the raw object is wanted as an identity — a cache key or a cycle guard — rather than as
|
|
21
|
+
* data. `unpackProxyObject` walks the value's own properties and writes each one back, which costs a
|
|
22
|
+
* read and a write per property and mutates the object it unpacks; callers that only compare identities
|
|
23
|
+
* pay for neither.
|
|
24
|
+
*/
|
|
25
|
+
export declare const unpackProxyShallow: <T>(input: T) => T;
|
|
16
26
|
export declare const unpackProxyObject: <T>(input: T, { depth }?: {
|
|
17
27
|
depth?: number | null;
|
|
18
28
|
}) => T;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unpack-proxy.d.ts","sourceRoot":"","sources":["../../src/helpers/unpack-proxy.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,EAAE,OAAO,CAAC,EAAE,YAAe;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,KAAG,CAsE9F,CAAA"}
|
|
1
|
+
{"version":3,"file":"unpack-proxy.d.ts","sourceRoot":"","sources":["../../src/helpers/unpack-proxy.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;GAcG;AACH;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,CAMhD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,CAAC,EAAE,OAAO,CAAC,EAAE,YAAe;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,KAAG,CAsE9F,CAAA"}
|
|
@@ -17,6 +17,21 @@ import { unpackOverridesProxy } from '../helpers/overrides-proxy.js';
|
|
|
17
17
|
* @param depth - Optional, limits recursion depth. `null` means unlimited depth (default is 1).
|
|
18
18
|
* @returns - A plain object or array with all proxies removed up to the specified depth.
|
|
19
19
|
*/
|
|
20
|
+
/**
|
|
21
|
+
* Strips the known proxies (Vue reactivity, overrides, detect-changes, magic) from a value without
|
|
22
|
+
* touching its properties, returning the raw object underneath.
|
|
23
|
+
*
|
|
24
|
+
* Use this when the raw object is wanted as an identity — a cache key or a cycle guard — rather than as
|
|
25
|
+
* data. `unpackProxyObject` walks the value's own properties and writes each one back, which costs a
|
|
26
|
+
* read and a write per property and mutates the object it unpacks; callers that only compare identities
|
|
27
|
+
* pay for neither.
|
|
28
|
+
*/
|
|
29
|
+
export const unpackProxyShallow = (input) => {
|
|
30
|
+
if (typeof input !== 'object' || input === null) {
|
|
31
|
+
return input;
|
|
32
|
+
}
|
|
33
|
+
return unpackDetectChangesProxy(toRaw(getRaw(unpackOverridesProxy(input))));
|
|
34
|
+
};
|
|
20
35
|
export const unpackProxyObject = (input, { depth = 0 } = {}) => {
|
|
21
36
|
// Internal DFS helper to recursively strip all known proxies (Vue, overrides, detect-changes, magic proxies)
|
|
22
37
|
const dfs = (value, currentDepth = 0) => {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ComponentPublicInstance, type ComputedRef, type InjectionKey, type Ref } from 'vue';
|
|
2
|
+
import { type ExternalExampleResolver } from '../helpers/external-examples.js';
|
|
3
|
+
import type { ExampleObject } from '../schemas/v3.2/strict/openapi-document.js';
|
|
4
|
+
/** Supply the current document's resolver so consumers share downloads and invalidation. */
|
|
5
|
+
export declare const EXTERNAL_EXAMPLES: InjectionKey<() => ExternalExampleResolver>;
|
|
6
|
+
/** Observe current visibility, rather than mounting, to avoid fetching every operation on a long page. */
|
|
7
|
+
export declare const useExampleVisibility: (target: Ref<Element | ComponentPublicInstance | null>) => Ref<boolean>;
|
|
8
|
+
/** Resolve only the selected examples and expose immutable views of their downloaded values. */
|
|
9
|
+
export declare const useExternalExamples: (examples: () => (ExampleObject | undefined)[], enabled?: () => boolean, resolver?: () => ExternalExampleResolver) => {
|
|
10
|
+
pending: ComputedRef<boolean>;
|
|
11
|
+
failed: ComputedRef<boolean>;
|
|
12
|
+
resolve: (example: ExampleObject | undefined) => ExampleObject | undefined;
|
|
13
|
+
retry: () => Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=use-external-examples.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-external-examples.d.ts","sourceRoot":"","sources":["../../src/helpers/use-external-examples.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,GAAG,EAOT,MAAM,KAAK,CAAA;AAEZ,OAAO,EAAE,KAAK,uBAAuB,EAAiC,MAAM,6BAA6B,CAAA;AACzG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAE3E,4FAA4F;AAC5F,eAAO,MAAM,iBAAiB,EAAE,YAAY,CAAC,MAAM,uBAAuB,CAA+B,CAAA;AAEzG,0GAA0G;AAC1G,eAAO,MAAM,oBAAoB,GAAI,QAAQ,GAAG,CAAC,OAAO,GAAG,uBAAuB,GAAG,IAAI,CAAC,KAAG,GAAG,CAAC,OAAO,CAuBvG,CAAA;AAED,gGAAgG;AAChG,eAAO,MAAM,mBAAmB,GAC9B,UAAU,MAAM,CAAC,aAAa,GAAG,SAAS,CAAC,EAAE,EAC7C,UAAS,MAAM,OAAoB,EACnC,WAAW,MAAM,uBAAuB,KACvC;IACD,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAC7B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAC5B,OAAO,EAAE,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,KAAK,aAAa,GAAG,SAAS,CAAA;IAC1E,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAgC3B,CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { computed, inject, onScopeDispose, ref, watch, watchEffect, } from 'vue';
|
|
2
|
+
import { createExternalExampleResolver } from '../helpers/external-examples.js';
|
|
3
|
+
/** Supply the current document's resolver so consumers share downloads and invalidation. */
|
|
4
|
+
export const EXTERNAL_EXAMPLES = Symbol('external-examples');
|
|
5
|
+
/** Observe current visibility, rather than mounting, to avoid fetching every operation on a long page. */
|
|
6
|
+
export const useExampleVisibility = (target) => {
|
|
7
|
+
const visible = ref(false);
|
|
8
|
+
let observer;
|
|
9
|
+
watch(target, (element) => {
|
|
10
|
+
observer?.disconnect();
|
|
11
|
+
visible.value = false;
|
|
12
|
+
const node = element && ('$el' in element ? element.$el : element);
|
|
13
|
+
if (typeof Element === 'undefined' || !(node instanceof Element))
|
|
14
|
+
return;
|
|
15
|
+
if (typeof IntersectionObserver === 'undefined') {
|
|
16
|
+
visible.value = true;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
observer = new IntersectionObserver(([entry]) => {
|
|
20
|
+
visible.value = entry?.isIntersecting ?? false;
|
|
21
|
+
});
|
|
22
|
+
observer.observe(node);
|
|
23
|
+
}, { flush: 'post' });
|
|
24
|
+
onScopeDispose(() => observer?.disconnect());
|
|
25
|
+
return visible;
|
|
26
|
+
};
|
|
27
|
+
/** Resolve only the selected examples and expose immutable views of their downloaded values. */
|
|
28
|
+
export const useExternalExamples = (examples, enabled = () => true, resolver) => {
|
|
29
|
+
const fallback = createExternalExampleResolver();
|
|
30
|
+
const getResolver = resolver ?? inject(EXTERNAL_EXAMPLES, () => fallback);
|
|
31
|
+
const states = computed(() => examples()
|
|
32
|
+
.filter((example) => example !== undefined && example.value === undefined && !!example.externalValue)
|
|
33
|
+
.map((example) => getResolver()(example)));
|
|
34
|
+
watchEffect(() => {
|
|
35
|
+
if (!enabled())
|
|
36
|
+
return;
|
|
37
|
+
for (const state of states.value) {
|
|
38
|
+
if (state.status === 'idle')
|
|
39
|
+
void state.load();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
pending: computed(() => states.value.some((state) => state.status !== 'loaded')),
|
|
44
|
+
failed: computed(() => states.value.some((state) => state.status === 'error')),
|
|
45
|
+
resolve: (example) => {
|
|
46
|
+
if (!example || example.value !== undefined || !example.externalValue)
|
|
47
|
+
return example;
|
|
48
|
+
const state = getResolver()(example);
|
|
49
|
+
return state.status === 'loaded' ? { ...example, value: state.value } : example;
|
|
50
|
+
},
|
|
51
|
+
retry: async () => {
|
|
52
|
+
await Promise.all(states.value.map((state) => state.load()));
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../../src/mutators/operation/parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAIrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAmClD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,wBAAwB,GACnC,UAAU,iBAAiB,GAAG,IAAI,EAClC,4CAA4C,eAAe,CAAC,4BAA4B,CAAC,
|
|
1
|
+
{"version":3,"file":"parameters.d.ts","sourceRoot":"","sources":["../../../src/mutators/operation/parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAIrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAmClD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,wBAAwB,GACnC,UAAU,iBAAiB,GAAG,IAAI,EAClC,4CAA4C,eAAe,CAAC,4BAA4B,CAAC,SAuE1F,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,8BAA8B,GACzC,UAAU,iBAAiB,GAAG,IAAI,EAClC,uCAAuC,eAAe,CAAC,mCAAmC,CAAC,SA8C5F,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,GACnC,UAAU,iBAAiB,GAAG,IAAI,EAClC,6BAA6B,eAAe,CAAC,4BAA4B,CAAC,SAkC3E,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,4BAA4B,GACvC,UAAU,iBAAiB,GAAG,IAAI,EAClC,gBAAgB,eAAe,CAAC,iCAAiC,CAAC,SAanE,CAAA"}
|
|
@@ -2,6 +2,7 @@ import { getPathItemOperation } from '../../helpers/for-each-path-item-operation
|
|
|
2
2
|
import { getResolvedRef } from '../../helpers/get-resolved-ref.js';
|
|
3
3
|
import { unpackProxyObject } from '../../helpers/unpack-proxy.js';
|
|
4
4
|
import { isOpenApiDocument } from '../../schemas/type-guards.js';
|
|
5
|
+
import { isContentTypeParameterObject } from '../../schemas/v3.2/strict/type-guards.js';
|
|
5
6
|
const getPathItemsForParameterMutation = (pathItemRef) => {
|
|
6
7
|
if (!pathItemRef || typeof pathItemRef !== 'object') {
|
|
7
8
|
return [];
|
|
@@ -40,23 +41,41 @@ const getPathItemsForParameterMutation = (pathItemRef) => {
|
|
|
40
41
|
export const upsertOperationParameter = (document, { meta, type, payload, originalParameter }) => {
|
|
41
42
|
// We are editing an existing parameter
|
|
42
43
|
if (originalParameter) {
|
|
43
|
-
// To support content-type parameters in the API client, we just assume an
|
|
44
|
-
// examples property can be set.
|
|
45
44
|
const param = originalParameter;
|
|
45
|
+
const target = isContentTypeParameterObject(param) ? Object.values(param.content ?? {})[0] : param;
|
|
46
|
+
if (!target) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (target !== param) {
|
|
50
|
+
// Keep authored examples and migrate edits saved by older clients. Those edits
|
|
51
|
+
// already take precedence when reading, so they must also win during migration.
|
|
52
|
+
target.examples = {
|
|
53
|
+
...(target.example !== undefined ? { default: { value: target.example } } : {}),
|
|
54
|
+
...target.examples,
|
|
55
|
+
...('example' in param && param.example !== undefined ? { default: { value: param.example } } : {}),
|
|
56
|
+
...('examples' in param ? param.examples : {}),
|
|
57
|
+
};
|
|
58
|
+
// A media type cannot carry both the singular example and the examples map.
|
|
59
|
+
delete target.example;
|
|
60
|
+
if ('examples' in param) {
|
|
61
|
+
delete param.examples;
|
|
62
|
+
}
|
|
63
|
+
if ('example' in param) {
|
|
64
|
+
delete param.example;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
46
67
|
// Only update the name when the payload carries a non-empty value — an
|
|
47
68
|
// empty name in the payload means the key input blurred before rendering
|
|
48
69
|
// its initial value and should not overwrite the existing parameter name.
|
|
49
70
|
if (payload.name || !param.name) {
|
|
50
71
|
param.name = payload.name;
|
|
51
72
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
param.examples[meta.exampleKey] = {};
|
|
73
|
+
target.examples ??= {};
|
|
74
|
+
target.examples[meta.exampleKey] ??= {};
|
|
75
|
+
const example = getResolvedRef(target.examples[meta.exampleKey]);
|
|
76
|
+
if (!example) {
|
|
77
|
+
return;
|
|
58
78
|
}
|
|
59
|
-
const example = getResolvedRef(param.examples[meta.exampleKey]);
|
|
60
79
|
// Update the example value and disabled state
|
|
61
80
|
example.value = payload.value;
|
|
62
81
|
example['x-disabled'] = payload.isDisabled;
|
|
@@ -20,9 +20,12 @@ export declare const loadingStatus: () => LifecyclePlugin;
|
|
|
20
20
|
*
|
|
21
21
|
* This is useful for inlining external content (like examples or schemas) into the OpenAPI document during bundling.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
23
|
+
* In lazy mode, preserve the absolute URL for on-demand client resolution without fetching a payload.
|
|
24
|
+
* The default eager mode remains available to existing bundler consumers.
|
|
24
25
|
*/
|
|
25
|
-
export declare const externalValueResolver: (
|
|
26
|
+
export declare const externalValueResolver: (options?: {
|
|
27
|
+
lazy?: boolean;
|
|
28
|
+
}) => LifecyclePlugin;
|
|
26
29
|
/**
|
|
27
30
|
* Lifecycle plugin to resolve $ref on any object, including non-standard locations like the info object.
|
|
28
31
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/bundler/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,KAAK,eAAe,EAAwB,MAAM,2BAA2B,CAAA;AAStF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,QAAO,eAahC,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/bundler/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,KAAK,eAAe,EAAwB,MAAM,2BAA2B,CAAA;AAStF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,QAAO,eAahC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAU;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,KAAG,eA2CpE,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,QAAO,eAwCjC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,mBAAmB,QAAO,eAuBtC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,oBAAoB,QAAO,eAuBvC,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,QAAO,eAyBhC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,QAAO,eAkFrC,CAAA;AAKD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAO,eAaxC,CAAA"}
|
|
@@ -39,21 +39,30 @@ export const loadingStatus = () => {
|
|
|
39
39
|
*
|
|
40
40
|
* This is useful for inlining external content (like examples or schemas) into the OpenAPI document during bundling.
|
|
41
41
|
*
|
|
42
|
-
*
|
|
42
|
+
* In lazy mode, preserve the absolute URL for on-demand client resolution without fetching a payload.
|
|
43
|
+
* The default eager mode remains available to existing bundler consumers.
|
|
43
44
|
*/
|
|
44
|
-
export const externalValueResolver = () => {
|
|
45
|
+
export const externalValueResolver = (options) => {
|
|
45
46
|
return {
|
|
46
47
|
type: 'lifecycle',
|
|
47
48
|
onAfterNodeProcess: async (node, context) => {
|
|
48
49
|
const externalValue = node['externalValue'];
|
|
49
50
|
const cache = context.resolutionCache;
|
|
50
51
|
// Only process if 'externalValue' is a string
|
|
51
|
-
if (typeof externalValue !== 'string') {
|
|
52
|
+
if (typeof externalValue !== 'string' || node['value'] !== undefined) {
|
|
52
53
|
return;
|
|
53
54
|
}
|
|
54
55
|
// `externalValue` may be relative (for example `/examples/pet.json`). Resolve it against the
|
|
55
56
|
// origin of the document it lives in so it becomes an absolute URL a loader can fetch.
|
|
56
57
|
const resolvedValue = resolveReferencePath(context.origin, externalValue);
|
|
58
|
+
if (options?.lazy) {
|
|
59
|
+
const path = context.path.at(-2) === 'examples' ? context.path : (context.referencedFromPath ?? context.path);
|
|
60
|
+
if (path.at(-2) !== 'examples' || isSchemaPath(path))
|
|
61
|
+
return;
|
|
62
|
+
// Preserve the referenced document origin before bundling loses that context.
|
|
63
|
+
node['externalValue'] = resolvedValue;
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
57
66
|
const loader = context.loaders.find((it) => it.validate(resolvedValue));
|
|
58
67
|
// We can not process the external value
|
|
59
68
|
if (!loader) {
|
|
@@ -3,11 +3,11 @@ import type { ExampleObject, ParameterObject } from '@scalar/workspace-store/sch
|
|
|
3
3
|
* Determines if a parameter is disabled
|
|
4
4
|
*
|
|
5
5
|
* First we explicitly check if its been disabled via the `x-disabled` extension.
|
|
6
|
-
*
|
|
6
|
+
* Populated examples are enabled unless explicitly disabled. Empty optional parameters stay disabled.
|
|
7
7
|
*
|
|
8
8
|
* @param param - The parameter to check.
|
|
9
9
|
* @param example - The example to check.
|
|
10
|
-
* @param defaultDisabled - When true (default), optional parameters are treated as disabled unless explicitly enabled. When false, only parameters explicitly marked `x-disabled: true` are disabled.
|
|
10
|
+
* @param defaultDisabled - When true (default), empty optional parameters are treated as disabled unless explicitly enabled. When false, only parameters explicitly marked `x-disabled: true` are disabled.
|
|
11
11
|
* @returns true if the parameter is disabled, false otherwise.
|
|
12
12
|
*/
|
|
13
13
|
export declare const isParamDisabled: (param: ParameterObject, example: ExampleObject | undefined, defaultDisabled?: boolean) => boolean;
|
|
@@ -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;AAElH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,eAAe,EACtB,SAAS,aAAa,GAAG,SAAS,EAClC,kBAAiB,OAAc,
|
|
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;AAElH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,eAAe,EACtB,SAAS,aAAa,GAAG,SAAS,EAClC,kBAAiB,OAAc,KAC9B,OAgBF,CAAA"}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* Determines if a parameter is disabled
|
|
3
3
|
*
|
|
4
4
|
* First we explicitly check if its been disabled via the `x-disabled` extension.
|
|
5
|
-
*
|
|
5
|
+
* Populated examples are enabled unless explicitly disabled. Empty optional parameters stay disabled.
|
|
6
6
|
*
|
|
7
7
|
* @param param - The parameter to check.
|
|
8
8
|
* @param example - The example to check.
|
|
9
|
-
* @param defaultDisabled - When true (default), optional parameters are treated as disabled unless explicitly enabled. When false, only parameters explicitly marked `x-disabled: true` are disabled.
|
|
9
|
+
* @param defaultDisabled - When true (default), empty optional parameters are treated as disabled unless explicitly enabled. When false, only parameters explicitly marked `x-disabled: true` are disabled.
|
|
10
10
|
* @returns true if the parameter is disabled, false otherwise.
|
|
11
11
|
*/
|
|
12
12
|
export const isParamDisabled = (param, example, defaultDisabled = true) => {
|
|
@@ -15,8 +15,9 @@ export const isParamDisabled = (param, example, defaultDisabled = true) => {
|
|
|
15
15
|
if (typeof xDisabled === 'boolean') {
|
|
16
16
|
return xDisabled;
|
|
17
17
|
}
|
|
18
|
-
//
|
|
19
|
-
|
|
18
|
+
// Keep the editor, generated snippets, and outgoing requests aligned for pre-populated values.
|
|
19
|
+
const hasValue = example?.value !== undefined && example.value !== '' && example.value !== null;
|
|
20
|
+
if (!defaultDisabled || hasValue) {
|
|
20
21
|
return false;
|
|
21
22
|
}
|
|
22
23
|
// Otherwise, disable optional parameters (except path parameters which are always required)
|
|
@@ -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;AA+wB1E,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;
|
|
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;AA+wB1E,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,OAmNF,CAAA"}
|
|
@@ -646,6 +646,26 @@ const createOptionsCacheKey = (options) => JSON.stringify({
|
|
|
646
646
|
? Object.entries(options.compositionSelection).sort(([a], [b]) => a.localeCompare(b))
|
|
647
647
|
: undefined,
|
|
648
648
|
});
|
|
649
|
+
/** Sentinel for "nothing memoized yet", since `undefined` is itself a valid options value. */
|
|
650
|
+
const NO_OPTIONS = Symbol('NO_OPTIONS');
|
|
651
|
+
/** The options object `lastOptionsKey` was built from. */
|
|
652
|
+
let lastOptions = NO_OPTIONS;
|
|
653
|
+
let lastOptionsKey = '';
|
|
654
|
+
/**
|
|
655
|
+
* The options half of the result-cache key, built once per top-level call instead of once per node.
|
|
656
|
+
*
|
|
657
|
+
* `createOptionsCacheKey` serializes the whole options object, and every schema the walk enters needs
|
|
658
|
+
* the same string. The walk is synchronous and passes the same `options` object down, so rebuilding at
|
|
659
|
+
* level 0, or whenever the identity changes, is enough: a caller that mutates its options object in
|
|
660
|
+
* place still gets a fresh key on its next top-level call, exactly as before.
|
|
661
|
+
*/
|
|
662
|
+
const getOptionsCacheKey = (options, level) => {
|
|
663
|
+
if (level === 0 || options !== lastOptions) {
|
|
664
|
+
lastOptionsKey = createOptionsCacheKey(options);
|
|
665
|
+
lastOptions = options;
|
|
666
|
+
}
|
|
667
|
+
return lastOptionsKey;
|
|
668
|
+
};
|
|
649
669
|
/** Stand-in for a truncated schema whose shape cannot be read off the document. */
|
|
650
670
|
const MAX_DEPTH_EXCEEDED = '[Max Depth Exceeded]';
|
|
651
671
|
/** How long a chain of composition wrappers may be unwrapped before the stack becomes the concern. */
|
|
@@ -867,7 +887,7 @@ export const getExampleFromSchema = (schema, options, { level = 0, parentSchema,
|
|
|
867
887
|
}
|
|
868
888
|
seen.add(targetValue);
|
|
869
889
|
/** Make the cache key unique per options and schema path */
|
|
870
|
-
const cacheKey =
|
|
890
|
+
const cacheKey = getOptionsCacheKey(options, level) + (schemaPath.length > 0 ? `:path:${schemaPath.join('.')}` : '');
|
|
871
891
|
// Check cache first for performance - avoid recomputing the same schema (skipped under a dynamic scope)
|
|
872
892
|
if (!skipCache) {
|
|
873
893
|
const cached = resultCache.get(targetValue)?.get(cacheKey);
|
|
@@ -4,6 +4,8 @@ import type { ExampleObject, MediaTypeObject, ParameterObject, RequestBodyObject
|
|
|
4
4
|
* Or the [deprecated] `example` field.
|
|
5
5
|
* If no exampleKey is provided it will fallback to the first example in the examples object then the [deprecated]
|
|
6
6
|
* `example` field.
|
|
7
|
+
* When the parameter carries both its own `examples`/`example` and a `content` object, the parameter-level value
|
|
8
|
+
* takes priority to preserve edits saved by older clients before they are migrated into the media type.
|
|
7
9
|
* Used both for send-request and generating code snippets.
|
|
8
10
|
*/
|
|
9
11
|
export declare const getExample: (param: ParameterObject | RequestBodyObject | MediaTypeObject, exampleName: string | undefined, contentType: string | undefined) => ExampleObject | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-example.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/helpers/get-example.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,eAAe,EACf,iBAAiB,EAClB,MAAM,8DAA8D,CAAA;AAgCrE
|
|
1
|
+
{"version":3,"file":"get-example.d.ts","sourceRoot":"","sources":["../../../../src/request-example/builder/helpers/get-example.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,eAAe,EACf,iBAAiB,EAClB,MAAM,8DAA8D,CAAA;AAgCrE;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,eAAe,GAAG,iBAAiB,GAAG,eAAe,EAC5D,aAAa,MAAM,GAAG,SAAS,EAC/B,aAAa,MAAM,GAAG,SAAS,KAC9B,aAAa,GAAG,SA6ClB,CAAA"}
|
|
@@ -23,20 +23,22 @@ const getExampleFromExamples = (examples, exampleField, exampleName) => {
|
|
|
23
23
|
* Or the [deprecated] `example` field.
|
|
24
24
|
* If no exampleKey is provided it will fallback to the first example in the examples object then the [deprecated]
|
|
25
25
|
* `example` field.
|
|
26
|
+
* When the parameter carries both its own `examples`/`example` and a `content` object, the parameter-level value
|
|
27
|
+
* takes priority to preserve edits saved by older clients before they are migrated into the media type.
|
|
26
28
|
* Used both for send-request and generating code snippets.
|
|
27
29
|
*/
|
|
28
30
|
export const getExample = (param, exampleName, contentType) => {
|
|
29
|
-
//
|
|
30
|
-
if ('
|
|
31
|
-
const
|
|
32
|
-
const result = getExampleFromExamples(content?.examples, content?.example, exampleName);
|
|
31
|
+
// Schema-based parameters and content-based parameter edits saved by older clients.
|
|
32
|
+
if ('examples' in param || 'example' in param) {
|
|
33
|
+
const result = getExampleFromExamples(param.examples, param.example, exampleName);
|
|
33
34
|
if (result !== undefined) {
|
|
34
35
|
return result;
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
|
-
//
|
|
38
|
-
if ('
|
|
39
|
-
const
|
|
38
|
+
// Content based parameters
|
|
39
|
+
if ('content' in param) {
|
|
40
|
+
const content = param.content?.[contentType ?? Object.keys(param.content)[0] ?? ''];
|
|
41
|
+
const result = getExampleFromExamples(content?.examples, content?.example, exampleName);
|
|
40
42
|
if (result !== undefined) {
|
|
41
43
|
return result;
|
|
42
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../../src/request-example/context/headers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../../src/request-example/context/headers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AAcnG;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GAAI,YAAY,MAAM,KAAG,MACQ,CAAA;AAE3E;;GAEG;AACH,eAAO,MAAM,qCAAqC,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CACK,CAAA;AAgDlH;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GACvC,WAAW,eAAe,EAC1B,aAAa,MAAM,EACnB,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,CAIpB,CAAA;AAEJ;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,GAAI,0FAU/B;IACD,MAAM,EAAE,UAAU,CAAA;IAClB,SAAS,EAAE,eAAe,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,OAAO,CAAC,EAAE;QACR,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,EAAE,OAAO,CAAA;KACpB,CAAA;CACF,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAuCxB,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { canMethodHaveBody } from '@scalar/helpers/http/can-method-have-body';
|
|
2
2
|
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
3
3
|
import { isParamDisabled } from '../../request-example/builder/header/is-param-disabled.js';
|
|
4
|
+
import { getExample } from '../../request-example/builder/helpers/get-example.js';
|
|
4
5
|
/** Default Accept header value to accept all response types. */
|
|
5
6
|
const DEFAULT_ACCEPT = '*/*';
|
|
6
7
|
const CONVENTIONAL_DEFAULT_HEADER_NAMES = {
|
|
@@ -21,8 +22,7 @@ export const restoreConventionalHeaderName = (headerName) => CONVENTIONAL_DEFAUL
|
|
|
21
22
|
export const restoreConventionalDefaultHeaderNames = (headers) => Object.fromEntries(Object.entries(headers).map(([name, value]) => [restoreConventionalHeaderName(name), value]));
|
|
22
23
|
/**
|
|
23
24
|
* Lowercase names of **enabled** operation parameters with `in: header` for the given example.
|
|
24
|
-
* Uses the same rules as the request builder
|
|
25
|
-
* as disabled unless `examples[exampleName]['x-disabled']` is explicitly `false`.
|
|
25
|
+
* Uses the same example selection and enablement rules as the request builder, including schema defaults.
|
|
26
26
|
*/
|
|
27
27
|
const getEnabledOperationHeaderParameterNames = (operation, exampleName) => {
|
|
28
28
|
const names = new Set();
|
|
@@ -31,8 +31,7 @@ const getEnabledOperationHeaderParameterNames = (operation, exampleName) => {
|
|
|
31
31
|
if (!param || param.in !== 'header') {
|
|
32
32
|
continue;
|
|
33
33
|
}
|
|
34
|
-
const
|
|
35
|
-
const example = rawExample ? getResolvedRef(rawExample) : undefined;
|
|
34
|
+
const example = getExample(param, exampleName, undefined);
|
|
36
35
|
if (!isParamDisabled(param, example)) {
|
|
37
36
|
names.add(param.name.toLowerCase());
|
|
38
37
|
}
|
package/dist/resolve.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { MaybeRefSchemaObject, SchemaObject } from './schemas/v3.2/strict/schema.js';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* A resolved schema is a read-only view.
|
|
4
|
+
*
|
|
5
|
+
* What comes back is either the document's own node or a shallow merge over it, so the nested values
|
|
6
|
+
* are the document's either way and a write reaches the document without going through the store. The
|
|
7
|
+
* `Readonly` says so to the compiler at the one level where a write is cheap to make by accident; a
|
|
8
|
+
* caller with a change to make copies what it needs, or goes through a store mutation.
|
|
9
|
+
*/
|
|
10
|
+
type ResolvedSchema<T> = T extends undefined ? undefined : Readonly<SchemaObject & {
|
|
3
11
|
$ref?: string;
|
|
4
|
-
}
|
|
12
|
+
}>;
|
|
5
13
|
export declare const resolve: {
|
|
6
14
|
schema: <T extends MaybeRefSchemaObject | undefined>(schema: T) => ResolvedSchema<T>;
|
|
7
15
|
};
|
package/dist/resolve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAEtF,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAEtF;;;;;;;GAOG;AACH,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC,YAAY,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAWrG,eAAO,MAAM,OAAO;aACT,CAAC,SAAS,oBAAoB,GAAG,SAAS,UAAU,CAAC,KAAG,cAAc,CAAC,CAAC,CAAC;CAQnF,CAAA"}
|
package/dist/resolve.js
CHANGED
|
@@ -3,12 +3,20 @@ import { getResolvedRef, mergeSiblingReferences } from './helpers/get-resolved-r
|
|
|
3
3
|
import { compose } from './schemas/compose.js';
|
|
4
4
|
import { coerceValue } from './schemas/typebox-coerce.js';
|
|
5
5
|
import { SchemaObjectSchema } from './schemas/v3.2/strict/openapi-document.js';
|
|
6
|
+
/**
|
|
7
|
+
* The coercion target: a schema object that may still carry the `$ref` it was resolved from.
|
|
8
|
+
*
|
|
9
|
+
* `Type.Composite` merges every property of `SchemaObjectSchema` to build this, so it belongs at module
|
|
10
|
+
* scope. `resolve.schema` runs once per property of every schema a render walks, and rebuilding the
|
|
11
|
+
* composite per call dominated that walk.
|
|
12
|
+
*/
|
|
13
|
+
const resolvedSchemaSchema = compose(SchemaObjectSchema, Type.Object({ $ref: Type.Optional(Type.String()) }));
|
|
6
14
|
export const resolve = {
|
|
7
15
|
schema: (schema) => {
|
|
8
16
|
if (schema === undefined) {
|
|
9
17
|
return undefined;
|
|
10
18
|
}
|
|
11
19
|
const resoled = getResolvedRef(schema, mergeSiblingReferences);
|
|
12
|
-
return coerceValue(
|
|
20
|
+
return coerceValue(resolvedSchemaSchema, resoled);
|
|
13
21
|
},
|
|
14
22
|
};
|