@scalar/workspace-store 0.54.3 → 0.54.4

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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # @scalar/workspace-store
2
2
 
3
+ ## 0.54.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#9465](https://github.com/scalar/scalar/pull/9465): Resolve JSON Schema 2020-12 `$dynamicRef` against the active `$dynamicAnchor` when generating examples, so generic patterns like `PaginatedResponse<T>` and recursive trees produce concrete example data instead of empty placeholders
8
+ - [#9494](https://github.com/scalar/scalar/pull/9494): Preserve document-level UI settings (watch mode, selected server, environments, sidebar order) and user-configured servers across `rebaseDocument` — previously every rebase (e.g. a watch mode pull) silently wiped them
9
+
3
10
  ## 0.54.3
4
11
 
5
12
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -952,6 +952,25 @@ export const createWorkspaceStore = (workspaceProps) => {
952
952
  // the document type discriminator.
953
953
  originalDocuments[name] = mergedDocument;
954
954
  intermediateDocuments[name] = deepClone(mergedDocument);
955
+ // Document-level UI settings never come from the upstream source and
956
+ // would otherwise be wiped on every rebase. Carry over only the keys
957
+ // that are actually set so we don't spread `undefined` into the
958
+ // rebuilt document. The strict document type does not declare every
959
+ // x-scalar-* UI extension, so read them through an untyped view.
960
+ const isOpenApi = isOpenApiDocument(activeDocumentRaw);
961
+ const environments = isOpenApi ? activeDocumentRaw['x-scalar-environments'] : undefined;
962
+ const order = isOpenApi ? activeDocumentRaw['x-scalar-order'] : undefined;
963
+ // Keep user-configured servers when the merged document has none
964
+ // (build-time generated specs typically declare no servers). When the
965
+ // merged result already carries servers — whether from upstream or
966
+ // preserved local edits — those stay authoritative.
967
+ const mergedServers = mergedDocument.servers;
968
+ const activeServers = activeDocumentRaw.servers;
969
+ const mergedHasServers = Array.isArray(mergedServers) && mergedServers.length > 0;
970
+ const activeHasServers = Array.isArray(activeServers) && activeServers.length > 0;
971
+ const preservedServers = !isAsyncApiDocument(mergedDocument) && !mergedHasServers && activeHasServers
972
+ ? deepClone(activeServers)
973
+ : undefined;
955
974
  // add the new active document to the workspace but don't re-initialize
956
975
  await addInMemoryDocument({
957
976
  ...input,
@@ -969,6 +988,12 @@ export const createWorkspaceStore = (workspaceProps) => {
969
988
  ...input.meta,
970
989
  // Preserve the registry meta
971
990
  'x-scalar-registry-meta': activeDocumentRaw['x-scalar-registry-meta'],
991
+ // Preserve document-level UI settings (see note above).
992
+ 'x-scalar-watch-mode': activeDocumentRaw['x-scalar-watch-mode'],
993
+ 'x-scalar-selected-server': activeDocumentRaw['x-scalar-selected-server'],
994
+ ...(environments !== undefined ? { 'x-scalar-environments': environments } : {}),
995
+ ...(order !== undefined ? { 'x-scalar-order': order } : {}),
996
+ ...(preservedServers !== undefined ? { servers: preservedServers } : {}),
972
997
  // Flag local edits that need pushing - see note above.
973
998
  'x-scalar-is-dirty': hasLocalChangesAgainstUpstream,
974
999
  },
@@ -0,0 +1,24 @@
1
+ import type { SchemaObject } from '../schemas/v3.1/strict/schema.js';
2
+ /**
3
+ * The dynamic scope, ordered outermost-first.
4
+ *
5
+ * Each entry is a schema resource on the current evaluation path. When a `$dynamicRef` is resolved,
6
+ * the outermost entry that declares a matching `$dynamicAnchor` wins.
7
+ */
8
+ export type DynamicScope = SchemaObject[];
9
+ /** Narrow a schema to one that carries a `$dynamicRef`. */
10
+ export declare const isDynamicRef: (schema: unknown) => schema is SchemaObject & {
11
+ $dynamicRef: string;
12
+ };
13
+ export declare const collectDynamicAnchors: (resource: SchemaObject) => Map<string, SchemaObject>;
14
+ /** Append a schema to the dynamic scope when it could hold a `$dynamicAnchor`, otherwise return it unchanged. */
15
+ export declare const pushDynamicScope: (scope: DynamicScope, schema: SchemaObject) => DynamicScope;
16
+ /**
17
+ * Resolve a `$dynamicRef` fragment against the dynamic scope.
18
+ *
19
+ * Scans the scope outermost-first and returns the first resource that declares a `$dynamicAnchor` with
20
+ * the referenced name. Returns `undefined` when nothing matches, in which case callers should leave the
21
+ * reference unresolved (the schema renders as it did before, with no regression).
22
+ */
23
+ export declare const resolveDynamicRef: (dynamicRef: string, scope: DynamicScope) => SchemaObject | undefined;
24
+ //# sourceMappingURL=dynamic-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-ref.d.ts","sourceRoot":"","sources":["../../src/helpers/dynamic-ref.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAiBhE;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,EAAE,CAAA;AAEzC,2DAA2D;AAC3D,eAAO,MAAM,YAAY,GAAI,QAAQ,OAAO,KAAG,MAAM,IAAI,YAAY,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAItB,CAAA;AAqBvE,eAAO,MAAM,qBAAqB,GAAI,UAAU,YAAY,KAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAgCtF,CAAA;AAED,iHAAiH;AACjH,eAAO,MAAM,gBAAgB,GAAI,OAAO,YAAY,EAAE,QAAQ,YAAY,KAAG,YAClB,CAAA;AAE3D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,EAAE,OAAO,YAAY,KAAG,YAAY,GAAG,SAe1F,CAAA"}
@@ -0,0 +1,74 @@
1
+ import { getResolvedRef, mergeSiblingReferences } from '../helpers/get-resolved-ref.js';
2
+ import { unpackProxyObject } from '../helpers/unpack-proxy.js';
3
+ /** Narrow a schema to one that carries a `$dynamicRef`. */
4
+ export const isDynamicRef = (schema) => typeof schema === 'object' &&
5
+ schema !== null &&
6
+ '$dynamicRef' in schema &&
7
+ typeof schema.$dynamicRef === 'string';
8
+ /**
9
+ * Whether a schema introduces something a `$dynamicRef` could later bind to.
10
+ *
11
+ * We only grow the dynamic scope with schemas that could hold a `$dynamicAnchor`: those declaring one
12
+ * directly, or resource boundaries (`$id`) / definition containers (`$defs`) that may hold one. Plain
13
+ * subschemas are skipped to keep the scope small.
14
+ */
15
+ const carriesDynamicAnchor = (schema) => '$dynamicAnchor' in schema || '$id' in schema || '$defs' in schema;
16
+ /**
17
+ * Collect the `$dynamicAnchor` declarations of a single schema resource, keyed by anchor name.
18
+ *
19
+ * Anchors are looked for at the resource root and inside `$defs` — the two placements used by the
20
+ * common generic and recursive patterns. Anchors nested deeper are not collected (a documented v1
21
+ * limitation). Each target is dereferenced so callers receive the concrete schema the anchor points to.
22
+ */
23
+ const anchorCache = new WeakMap();
24
+ export const collectDynamicAnchors = (resource) => {
25
+ // Cache per raw schema object so repeated lookups during a walk stay cheap.
26
+ const cacheTarget = unpackProxyObject(resource, { depth: 1 });
27
+ const cached = anchorCache.get(cacheTarget);
28
+ if (cached) {
29
+ return cached;
30
+ }
31
+ const anchors = new Map();
32
+ const add = (node) => {
33
+ if (!node || typeof node !== 'object') {
34
+ return;
35
+ }
36
+ const anchor = node.$dynamicAnchor;
37
+ if (typeof anchor === 'string' && !anchors.has(anchor)) {
38
+ // Resolve any sibling `$ref` so the stored target is the concrete schema (e.g. `User`).
39
+ anchors.set(anchor, getResolvedRef(node, mergeSiblingReferences));
40
+ }
41
+ };
42
+ add(resource);
43
+ const defs = resource.$defs;
44
+ if (defs && typeof defs === 'object') {
45
+ for (const key of Object.keys(defs)) {
46
+ add(defs[key]);
47
+ }
48
+ }
49
+ anchorCache.set(cacheTarget, anchors);
50
+ return anchors;
51
+ };
52
+ /** Append a schema to the dynamic scope when it could hold a `$dynamicAnchor`, otherwise return it unchanged. */
53
+ export const pushDynamicScope = (scope, schema) => carriesDynamicAnchor(schema) ? [...scope, schema] : scope;
54
+ /**
55
+ * Resolve a `$dynamicRef` fragment against the dynamic scope.
56
+ *
57
+ * Scans the scope outermost-first and returns the first resource that declares a `$dynamicAnchor` with
58
+ * the referenced name. Returns `undefined` when nothing matches, in which case callers should leave the
59
+ * reference unresolved (the schema renders as it did before, with no regression).
60
+ */
61
+ export const resolveDynamicRef = (dynamicRef, scope) => {
62
+ // Only plain-name fragments (`#itemType`) are supported; a non-fragment URI is not a dynamic anchor.
63
+ const name = dynamicRef.startsWith('#') ? dynamicRef.slice(1) : undefined;
64
+ if (!name || name.startsWith('/')) {
65
+ return undefined;
66
+ }
67
+ for (const resource of scope) {
68
+ const match = collectDynamicAnchors(resource).get(name);
69
+ if (match) {
70
+ return match;
71
+ }
72
+ }
73
+ return undefined;
74
+ };
@@ -1,3 +1,4 @@
1
+ import { type DynamicScope } from '../../../helpers/dynamic-ref.js';
1
2
  import type { SchemaObject } from '../../../schemas/v3.1/strict/openapi-document.js';
2
3
  type GetExampleFromSchemaOptions = {
3
4
  /** Fallback string for empty string values. */
@@ -28,13 +29,15 @@ type GetExampleFromSchemaOptions = {
28
29
  * @param name - The name of the property being processed.
29
30
  * @returns An example value for the given schema.
30
31
  */
31
- export declare const getExampleFromSchema: (schema: SchemaObject, options?: GetExampleFromSchemaOptions, { level, parentSchema, name, seen, schemaPath, }?: Partial<{
32
+ export declare const getExampleFromSchema: (schema: SchemaObject, options?: GetExampleFromSchemaOptions, { level, parentSchema, name, seen, schemaPath, dynamicScope, }?: Partial<{
32
33
  level: number;
33
34
  parentSchema: SchemaObject;
34
35
  name: string;
35
36
  seen: WeakSet<object>;
36
37
  /** Internal traversal path used to resolve nested composition selections. */
37
38
  schemaPath: string[];
39
+ /** Chain of schema resources entered so far, used to resolve `$dynamicRef` (JSON Schema 2020-12). */
40
+ dynamicScope: DynamicScope;
38
41
  }>) => unknown;
39
42
  export {};
40
43
  //# sourceMappingURL=get-example-from-schema.d.ts.map
@@ -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":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAypB1E,KAAK,2BAA2B,GAAG;IACjC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,qDAAqD;IACrD,8BAA8B,CAAC,EAAE,OAAO,CAAA;IACxC,0DAA0D;IAC1D,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC9C,CAAA;AAeD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,YAAY,EACpB,UAAU,2BAA2B,EACrC,mDAMG,OAAO,CAAC;IACT,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,YAAY,CAAA;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IACrB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,CAAM,KACN,OAqKF,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":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAqD,MAAM,uBAAuB,CAAA;AAG5G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAisB1E,KAAK,2BAA2B,GAAG;IACjC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,qDAAqD;IACrD,8BAA8B,CAAC,EAAE,OAAO,CAAA;IACxC,0DAA0D;IAC1D,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC9C,CAAA;AAeD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,YAAY,EACpB,UAAU,2BAA2B,EACrC,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,OAmMF,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { isDefined } from '@scalar/helpers/array/is-defined';
2
+ import { isDynamicRef, pushDynamicScope, resolveDynamicRef } from '../../../helpers/dynamic-ref.js';
2
3
  import { unpackProxyObject } from '../../../helpers/unpack-proxy.js';
3
4
  import { resolve } from '../../../resolve.js';
4
5
  /** Maximum recursion depth to prevent infinite loops in circular references */
@@ -108,9 +109,13 @@ const getRequiredNames = (parentSchema) => {
108
109
  * Cache the result for a schema if it is an object type.
109
110
  * Primitive values are not cached to avoid unnecessary WeakMap operations.
110
111
  * Stores a map of cacheKey strings which is made up of the options object.
112
+ *
113
+ * Skips the cache while a dynamic scope is active: the same shared schema node can resolve to
114
+ * different examples depending on the dynamic scope it was reached through, so caching it by object
115
+ * identity would leak one scope's result into another.
111
116
  */
112
- const cache = (schema, result, cacheKey) => {
113
- if (typeof result !== 'object' || result === null) {
117
+ const cache = (schema, result, cacheKey, skip = false) => {
118
+ if (skip || typeof result !== 'object' || result === null) {
114
119
  return result;
115
120
  }
116
121
  const rawSchema = getSchemaCacheTarget(schema);
@@ -313,8 +318,11 @@ const sortPropertyNamesByXOrder = (properties) => Object.keys(properties).sort((
313
318
  * Build an example for an object schema, including properties, patternProperties,
314
319
  * additionalProperties, and composition (allOf/oneOf/anyOf) merging.
315
320
  */
316
- const handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath) => {
321
+ const handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath, dynamicScope) => {
317
322
  const response = {};
323
+ // Children are evaluated with this schema added to the dynamic scope so nested `$dynamicRef`s bind here.
324
+ const childScope = pushDynamicScope(dynamicScope, schema);
325
+ const skipCache = dynamicScope.length > 0;
318
326
  if ('properties' in schema && schema.properties) {
319
327
  const properties = schema.properties;
320
328
  const propertyNames = sortPropertyNamesByXOrder(properties);
@@ -332,6 +340,7 @@ const handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath)
332
340
  name: propertyName,
333
341
  schemaPath: [...schemaPath, propertyName],
334
342
  seen,
343
+ dynamicScope: childScope,
335
344
  });
336
345
  if (typeof value !== 'undefined') {
337
346
  response[propertyXmlName ?? propertyName] = value;
@@ -350,6 +359,7 @@ const handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath)
350
359
  name: pattern,
351
360
  schemaPath: [...schemaPath, pattern],
352
361
  seen,
362
+ dynamicScope: childScope,
353
363
  });
354
364
  }
355
365
  }
@@ -376,6 +386,7 @@ const handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath)
376
386
  level: level + 1,
377
387
  schemaPath: [...schemaPath, additionalName],
378
388
  seen,
389
+ dynamicScope: childScope,
379
390
  })
380
391
  : 'anything';
381
392
  if (propertyNamesEnum && propertyNamesEnum.length > 0) {
@@ -396,6 +407,7 @@ const handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath)
396
407
  level: level + 1,
397
408
  schemaPath,
398
409
  seen,
410
+ dynamicScope: childScope,
399
411
  }));
400
412
  }
401
413
  }
@@ -407,6 +419,7 @@ const handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath)
407
419
  level: level + 1,
408
420
  parentSchema: schema,
409
421
  seen,
422
+ dynamicScope: childScope,
410
423
  });
411
424
  merged = mergeExamples(merged, ex);
412
425
  }
@@ -417,18 +430,33 @@ const handleObjectSchema = (schema, options, level, seen, cacheKey, schemaPath)
417
430
  if (options?.xml && 'xml' in schema && schema.xml?.name && level === 0) {
418
431
  const wrapped = {};
419
432
  wrapped[schema.xml.name] = response;
420
- return cache(schema, wrapped, cacheKey);
433
+ return cache(schema, wrapped, cacheKey, skipCache);
421
434
  }
422
- return cache(schema, response, cacheKey);
435
+ return cache(schema, response, cacheKey, skipCache);
423
436
  };
424
437
  /** Build an example for an array schema, including items, allOf, oneOf/anyOf, and XML wrapping */
425
- const handleArraySchema = (schema, options, level, seen, cacheKey, schemaPath) => {
426
- const items = 'items' in schema ? resolve.schema(schema.items) : undefined;
438
+ const handleArraySchema = (schema, options, level, seen, cacheKey, schemaPath, dynamicScope) => {
439
+ const childScope = pushDynamicScope(dynamicScope, schema);
440
+ const skipCache = dynamicScope.length > 0;
441
+ let items = 'items' in schema ? resolve.schema(schema.items) : undefined;
442
+ // Bind a dynamic item type (e.g. the generic `PaginatedResponse<T>` pattern) before inspecting it.
443
+ // Crossing a `$dynamicRef` leaves the static schema graph, so the cycle guard built up by the outer
444
+ // walk no longer applies to the bound type. Restart `seen` for the item recursion so recursive trees
445
+ // (e.g. a category whose children reference the same anchor) render their nested levels instead of
446
+ // tripping the shared guard. Depth stays bounded by `MAX_LEVELS_DEEP`.
447
+ let itemsSeen = seen;
448
+ if (items && isDynamicRef(items)) {
449
+ const resolvedDynamic = resolveDynamicRef(items.$dynamicRef, childScope);
450
+ if (resolvedDynamic) {
451
+ items = resolvedDynamic;
452
+ itemsSeen = new WeakSet();
453
+ }
454
+ }
427
455
  const itemsSchemaPath = [...schemaPath, 'items'];
428
456
  const itemsXmlTagName = items && typeof items === 'object' && 'xml' in items ? items.xml?.name : undefined;
429
457
  const wrapItems = !!(options?.xml && 'xml' in schema && schema.xml?.wrapped && itemsXmlTagName);
430
458
  if (schema.example !== undefined) {
431
- return cache(schema, wrapItems ? { [itemsXmlTagName]: schema.example } : schema.example, cacheKey);
459
+ return cache(schema, wrapItems ? { [itemsXmlTagName]: schema.example } : schema.example, cacheKey, skipCache);
432
460
  }
433
461
  if (items && typeof items === 'object') {
434
462
  if (Array.isArray(items.allOf) && items.allOf.length > 0) {
@@ -440,19 +468,21 @@ const handleArraySchema = (schema, options, level, seen, cacheKey, schemaPath) =
440
468
  level: level + 1,
441
469
  parentSchema: schema,
442
470
  schemaPath: itemsSchemaPath,
443
- seen,
471
+ seen: itemsSeen,
472
+ dynamicScope: childScope,
444
473
  });
445
- return cache(schema, wrapItems ? [{ [itemsXmlTagName]: merged }] : [merged], cacheKey);
474
+ return cache(schema, wrapItems ? [{ [itemsXmlTagName]: merged }] : [merged], cacheKey, skipCache);
446
475
  }
447
476
  const examples = allOf
448
477
  .map((s) => getExampleFromSchema(resolve.schema(s), options, {
449
478
  level: level + 1,
450
479
  parentSchema: schema,
451
480
  schemaPath: itemsSchemaPath,
452
- seen,
481
+ seen: itemsSeen,
482
+ dynamicScope: childScope,
453
483
  }))
454
484
  .filter(isDefined);
455
- return cache(schema, wrapItems ? examples.map((e) => ({ [itemsXmlTagName]: e })) : examples, cacheKey);
485
+ return cache(schema, wrapItems ? examples.map((e) => ({ [itemsXmlTagName]: e })) : examples, cacheKey, skipCache);
456
486
  }
457
487
  const compositionKeyword = items.oneOf ? 'oneOf' : items.anyOf ? 'anyOf' : undefined;
458
488
  const union = compositionKeyword ? items[compositionKeyword] : undefined;
@@ -463,9 +493,10 @@ const handleArraySchema = (schema, options, level, seen, cacheKey, schemaPath) =
463
493
  level: level + 1,
464
494
  parentSchema: schema,
465
495
  schemaPath: itemsSchemaPath,
466
- seen,
496
+ seen: itemsSeen,
497
+ dynamicScope: childScope,
467
498
  });
468
- return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex], cacheKey);
499
+ return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex], cacheKey, skipCache);
469
500
  }
470
501
  }
471
502
  const isObject = items && typeof items === 'object' && (('type' in items && items.type === 'object') || 'properties' in items);
@@ -474,11 +505,12 @@ const handleArraySchema = (schema, options, level, seen, cacheKey, schemaPath) =
474
505
  const ex = getExampleFromSchema(items, options, {
475
506
  level: level + 1,
476
507
  schemaPath: itemsSchemaPath,
477
- seen,
508
+ seen: itemsSeen,
509
+ dynamicScope: childScope,
478
510
  });
479
- return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex], cacheKey);
511
+ return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex], cacheKey, skipCache);
480
512
  }
481
- return cache(schema, [], cacheKey);
513
+ return cache(schema, [], cacheKey, skipCache);
482
514
  };
483
515
  /** Return primitive example value for single-type schemas, or undefined if not primitive */
484
516
  const getPrimitiveValue = (schema, makeUpRandomData, emptyString) => {
@@ -552,12 +584,35 @@ const createOptionsCacheKey = (options) => JSON.stringify({
552
584
  * @param name - The name of the property being processed.
553
585
  * @returns An example value for the given schema.
554
586
  */
555
- export const getExampleFromSchema = (schema, options, { level = 0, parentSchema, name, seen = new WeakSet(), schemaPath = [], } = {}) => {
587
+ export const getExampleFromSchema = (schema, options, { level = 0, parentSchema, name, seen = new WeakSet(), schemaPath = [], dynamicScope = [], } = {}) => {
556
588
  // Resolve any $ref references to get the actual schema
557
589
  const _schema = resolve.schema(schema);
558
590
  if (!isDefined(_schema)) {
559
591
  return undefined;
560
592
  }
593
+ // Resolve a `$dynamicRef` against the active dynamic scope, then continue with the bound schema.
594
+ // When nothing matches, fall through and render the reference as before (no regression).
595
+ if (isDynamicRef(_schema)) {
596
+ const resolvedDynamic = resolveDynamicRef(_schema.$dynamicRef, dynamicScope);
597
+ if (resolvedDynamic) {
598
+ // The `seen` set guards against cycles in the static schema graph, but a `$dynamicRef` is resolved
599
+ // per evaluation path and intentionally points outside that graph. Re-entering the bound type with a
600
+ // fresh `seen` lets recursive examples (e.g. a category tree) render their nested levels instead of
601
+ // bailing out on the shared cycle guard. Depth stays bounded by `MAX_LEVELS_DEEP`.
602
+ return getExampleFromSchema(resolvedDynamic, options, {
603
+ level: level + 1,
604
+ parentSchema,
605
+ name,
606
+ seen: new WeakSet(),
607
+ schemaPath,
608
+ dynamicScope,
609
+ });
610
+ }
611
+ }
612
+ // Grow the scope with this schema so nested references can bind to its `$dynamicAnchor`s.
613
+ const childScope = pushDynamicScope(dynamicScope, _schema);
614
+ // The same shared node can resolve differently per scope, so skip the result cache under a scope.
615
+ const skipCache = dynamicScope.length > 0;
561
616
  // Unpack from all proxies to get the raw schema object for cycle detection
562
617
  const targetValue = getSchemaCacheTarget(_schema);
563
618
  if (seen.has(targetValue)) {
@@ -566,11 +621,13 @@ export const getExampleFromSchema = (schema, options, { level = 0, parentSchema,
566
621
  seen.add(targetValue);
567
622
  /** Make the cache key unique per options and schema path */
568
623
  const cacheKey = createOptionsCacheKey(options) + (schemaPath.length > 0 ? `:path:${schemaPath.join('.')}` : '');
569
- // Check cache first for performance - avoid recomputing the same schema
570
- const cached = resultCache.get(targetValue)?.get(cacheKey);
571
- if (typeof cached !== 'undefined') {
572
- seen.delete(targetValue);
573
- return cached;
624
+ // Check cache first for performance - avoid recomputing the same schema (skipped under a dynamic scope)
625
+ if (!skipCache) {
626
+ const cached = resultCache.get(targetValue)?.get(cacheKey);
627
+ if (typeof cached !== 'undefined') {
628
+ seen.delete(targetValue);
629
+ return cached;
630
+ }
574
631
  }
575
632
  // Prevent infinite recursion in circular references
576
633
  if (level > MAX_LEVELS_DEEP) {
@@ -591,45 +648,45 @@ export const getExampleFromSchema = (schema, options, { level = 0, parentSchema,
591
648
  // Type coercion for numeric types
592
649
  if ('type' in _schema && (_schema.type === 'number' || _schema.type === 'integer')) {
593
650
  seen.delete(targetValue);
594
- return cache(_schema, Number(value), cacheKey);
651
+ return cache(_schema, Number(value), cacheKey, skipCache);
595
652
  }
596
653
  seen.delete(targetValue);
597
- return cache(_schema, value, cacheKey);
654
+ return cache(_schema, value, cacheKey, skipCache);
598
655
  }
599
656
  }
600
657
  // Priority order: examples > example > default > const > enum
601
658
  if (Array.isArray(_schema.examples) && _schema.examples.length > 0) {
602
659
  seen.delete(targetValue);
603
- return cache(_schema, _schema.examples[0], cacheKey);
660
+ return cache(_schema, _schema.examples[0], cacheKey, skipCache);
604
661
  }
605
662
  if (_schema.example !== undefined) {
606
663
  seen.delete(targetValue);
607
- return cache(_schema, _schema.example, cacheKey);
664
+ return cache(_schema, _schema.example, cacheKey, skipCache);
608
665
  }
609
666
  if (_schema.default !== undefined) {
610
667
  const normalizedDefault = normalizeSchemaDefault(_schema);
611
668
  if (normalizedDefault !== INVALID_DEFAULT) {
612
669
  seen.delete(targetValue);
613
- return cache(_schema, normalizedDefault, cacheKey);
670
+ return cache(_schema, normalizedDefault, cacheKey, skipCache);
614
671
  }
615
672
  }
616
673
  if (_schema.const !== undefined) {
617
674
  seen.delete(targetValue);
618
- return cache(_schema, _schema.const, cacheKey);
675
+ return cache(_schema, _schema.const, cacheKey, skipCache);
619
676
  }
620
677
  if (Array.isArray(_schema.enum) && _schema.enum.length > 0) {
621
678
  seen.delete(targetValue);
622
- return cache(_schema, _schema.enum[0], cacheKey);
679
+ return cache(_schema, _schema.enum[0], cacheKey, skipCache);
623
680
  }
624
681
  // Handle object types - check for properties to identify objects
625
682
  if ('properties' in _schema || ('type' in _schema && _schema.type === 'object')) {
626
- const result = handleObjectSchema(_schema, options, level, seen, cacheKey, schemaPath);
683
+ const result = handleObjectSchema(_schema, options, level, seen, cacheKey, schemaPath, dynamicScope);
627
684
  seen.delete(targetValue);
628
685
  return result;
629
686
  }
630
687
  // Handle array types
631
688
  if (('type' in _schema && _schema.type === 'array') || 'items' in _schema) {
632
- const result = handleArraySchema(_schema, options, level, seen, cacheKey, schemaPath);
689
+ const result = handleArraySchema(_schema, options, level, seen, cacheKey, schemaPath, dynamicScope);
633
690
  seen.delete(targetValue);
634
691
  return result;
635
692
  }
@@ -637,7 +694,7 @@ export const getExampleFromSchema = (schema, options, { level = 0, parentSchema,
637
694
  const primitive = getPrimitiveValue(_schema, makeUpRandomData, options?.emptyString);
638
695
  if (primitive !== undefined) {
639
696
  seen.delete(targetValue);
640
- return cache(_schema, primitive, cacheKey);
697
+ return cache(_schema, primitive, cacheKey, skipCache);
641
698
  }
642
699
  // Handle composition schemas (oneOf, anyOf)
643
700
  const compositionKeyword = _schema.oneOf ? 'oneOf' : _schema.anyOf ? 'anyOf' : undefined;
@@ -658,11 +715,12 @@ export const getExampleFromSchema = (schema, options, { level = 0, parentSchema,
658
715
  level: level + 1,
659
716
  schemaPath,
660
717
  seen,
661
- }), cacheKey);
718
+ dynamicScope: childScope,
719
+ }), cacheKey, skipCache);
662
720
  }
663
721
  }
664
722
  seen.delete(targetValue);
665
- return cache(_schema, null, cacheKey);
723
+ return cache(_schema, null, cacheKey, skipCache);
666
724
  }
667
725
  // Handle allOf at root level (non-object/array schemas)
668
726
  if (Array.isArray(_schema.allOf) && _schema.allOf.length > 0) {
@@ -674,6 +732,7 @@ export const getExampleFromSchema = (schema, options, { level = 0, parentSchema,
674
732
  parentSchema: _schema,
675
733
  schemaPath,
676
734
  seen,
735
+ dynamicScope: childScope,
677
736
  });
678
737
  if (merged === undefined) {
679
738
  merged = ex;
@@ -687,15 +746,15 @@ export const getExampleFromSchema = (schema, options, { level = 0, parentSchema,
687
746
  }
688
747
  }
689
748
  seen.delete(targetValue);
690
- return cache(_schema, merged ?? null, cacheKey);
749
+ return cache(_schema, merged ?? null, cacheKey, skipCache);
691
750
  }
692
751
  // Handle union types (array of types)
693
752
  const unionPrimitive = getUnionPrimitiveValue(_schema, makeUpRandomData, options?.emptyString);
694
753
  if (unionPrimitive !== undefined) {
695
754
  seen.delete(targetValue);
696
- return cache(_schema, unionPrimitive, cacheKey);
755
+ return cache(_schema, unionPrimitive, cacheKey, skipCache);
697
756
  }
698
757
  // Default fallback
699
758
  seen.delete(targetValue);
700
- return cache(_schema, null, cacheKey);
759
+ return cache(_schema, null, cacheKey, skipCache);
701
760
  };
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "openapi",
17
17
  "scalar"
18
18
  ],
19
- "version": "0.54.3",
19
+ "version": "0.54.4",
20
20
  "engines": {
21
21
  "node": ">=22"
22
22
  },
@@ -150,11 +150,11 @@
150
150
  "yaml": "^2.8.3",
151
151
  "@scalar/helpers": "0.8.2",
152
152
  "@scalar/json-magic": "0.12.16",
153
- "@scalar/schemas": "0.4.3",
154
153
  "@scalar/openapi-upgrader": "0.2.9",
155
- "@scalar/snippetz": "0.9.16",
156
- "@scalar/types": "0.13.3",
157
- "@scalar/validation": "0.6.0"
154
+ "@scalar/schemas": "0.5.0",
155
+ "@scalar/types": "0.14.0",
156
+ "@scalar/validation": "0.6.0",
157
+ "@scalar/snippetz": "0.9.17"
158
158
  },
159
159
  "devDependencies": {
160
160
  "@google-cloud/storage": "7.16.0",