@scalar/oas-utils 0.10.7 → 0.10.9

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.
Files changed (129) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/entities/cookie/cookie.js +11 -15
  3. package/dist/entities/cookie/index.js +1 -5
  4. package/dist/entities/environment/environment.js +7 -11
  5. package/dist/entities/environment/index.js +1 -5
  6. package/dist/entities/hotkeys/hotkeys.js +116 -111
  7. package/dist/entities/hotkeys/index.js +1 -6
  8. package/dist/entities/shared/index.js +1 -7
  9. package/dist/entities/shared/utility.js +9 -9
  10. package/dist/entities/spec/collection.js +91 -89
  11. package/dist/entities/spec/index.js +10 -59
  12. package/dist/entities/spec/operation.js +6 -6
  13. package/dist/entities/spec/parameters.js +38 -38
  14. package/dist/entities/spec/request-examples.js +421 -331
  15. package/dist/entities/spec/requests.js +102 -84
  16. package/dist/entities/spec/server.js +61 -46
  17. package/dist/entities/spec/spec-objects.js +121 -76
  18. package/dist/entities/spec/x-scalar-environments.js +18 -20
  19. package/dist/entities/spec/x-scalar-secrets.js +6 -8
  20. package/dist/entities/workspace/index.js +1 -7
  21. package/dist/entities/workspace/workspace.js +47 -46
  22. package/dist/helpers/client-plugins.js +13 -13
  23. package/dist/helpers/fetch-document.js +30 -25
  24. package/dist/helpers/fetch-with-proxy-fallback.js +26 -21
  25. package/dist/helpers/index.d.ts +1 -2
  26. package/dist/helpers/index.d.ts.map +1 -1
  27. package/dist/helpers/index.js +80 -119
  28. package/dist/helpers/normalize-mime-type-object.js +19 -18
  29. package/dist/helpers/normalize-mime-type.js +11 -9
  30. package/dist/helpers/operation-stability.js +25 -20
  31. package/dist/helpers/parse.d.ts +0 -4
  32. package/dist/helpers/parse.d.ts.map +1 -1
  33. package/dist/helpers/parse.js +77 -77
  34. package/dist/helpers/schema-model.js +13 -16
  35. package/dist/helpers/security/get-schemes.js +7 -8
  36. package/dist/helpers/security/has-token.js +18 -19
  37. package/dist/helpers/security/index.js +2 -7
  38. package/dist/helpers/servers.js +128 -79
  39. package/dist/helpers/should-ignore-entity.js +4 -5
  40. package/dist/migrations/data-version.js +15 -7
  41. package/dist/migrations/generate-types.js +34 -37
  42. package/dist/migrations/index.js +4 -18
  43. package/dist/migrations/local-storage.js +31 -29
  44. package/dist/migrations/migrate-to-indexdb.js +706 -529
  45. package/dist/migrations/migrator.js +58 -54
  46. package/dist/migrations/semver.js +24 -24
  47. package/dist/migrations/v-0.0.0/types.generated.js +1 -1
  48. package/dist/migrations/v-2.1.0/migration.js +272 -258
  49. package/dist/migrations/v-2.1.0/types.generated.js +1 -1
  50. package/dist/migrations/v-2.2.0/migration.js +99 -96
  51. package/dist/migrations/v-2.2.0/types.generated.js +1 -1
  52. package/dist/migrations/v-2.3.0/migration.js +45 -48
  53. package/dist/migrations/v-2.3.0/types.generated.js +1 -1
  54. package/dist/migrations/v-2.4.0/migration.js +25 -25
  55. package/dist/migrations/v-2.4.0/types.generated.js +1 -1
  56. package/dist/migrations/v-2.5.0/migration.js +122 -139
  57. package/dist/migrations/v-2.5.0/types.generated.js +1 -1
  58. package/dist/spec-getters/get-example-from-schema.js +489 -385
  59. package/dist/spec-getters/get-parameters-from-operation.js +39 -23
  60. package/dist/spec-getters/get-request-body-from-operation.d.ts.map +1 -1
  61. package/dist/spec-getters/get-request-body-from-operation.js +168 -126
  62. package/dist/spec-getters/get-server-variable-examples.js +10 -13
  63. package/dist/spec-getters/index.js +4 -11
  64. package/dist/transforms/import-spec.js +381 -291
  65. package/dist/transforms/index.js +1 -11
  66. package/package.json +15 -19
  67. package/dist/entities/cookie/cookie.js.map +0 -7
  68. package/dist/entities/cookie/index.js.map +0 -7
  69. package/dist/entities/environment/environment.js.map +0 -7
  70. package/dist/entities/environment/index.js.map +0 -7
  71. package/dist/entities/hotkeys/hotkeys.js.map +0 -7
  72. package/dist/entities/hotkeys/index.js.map +0 -7
  73. package/dist/entities/shared/index.js.map +0 -7
  74. package/dist/entities/shared/utility.js.map +0 -7
  75. package/dist/entities/spec/collection.js.map +0 -7
  76. package/dist/entities/spec/index.js.map +0 -7
  77. package/dist/entities/spec/operation.js.map +0 -7
  78. package/dist/entities/spec/parameters.js.map +0 -7
  79. package/dist/entities/spec/request-examples.js.map +0 -7
  80. package/dist/entities/spec/requests.js.map +0 -7
  81. package/dist/entities/spec/server.js.map +0 -7
  82. package/dist/entities/spec/spec-objects.js.map +0 -7
  83. package/dist/entities/spec/x-scalar-environments.js.map +0 -7
  84. package/dist/entities/spec/x-scalar-secrets.js.map +0 -7
  85. package/dist/entities/workspace/index.js.map +0 -7
  86. package/dist/entities/workspace/workspace.js.map +0 -7
  87. package/dist/helpers/client-plugins.js.map +0 -7
  88. package/dist/helpers/fetch-document.js.map +0 -7
  89. package/dist/helpers/fetch-with-proxy-fallback.js.map +0 -7
  90. package/dist/helpers/index.js.map +0 -7
  91. package/dist/helpers/normalize-mime-type-object.js.map +0 -7
  92. package/dist/helpers/normalize-mime-type.js.map +0 -7
  93. package/dist/helpers/operation-stability.js.map +0 -7
  94. package/dist/helpers/parse.js.map +0 -7
  95. package/dist/helpers/pretty-print-json.d.ts +0 -9
  96. package/dist/helpers/pretty-print-json.d.ts.map +0 -1
  97. package/dist/helpers/pretty-print-json.js +0 -38
  98. package/dist/helpers/pretty-print-json.js.map +0 -7
  99. package/dist/helpers/schema-model.js.map +0 -7
  100. package/dist/helpers/security/get-schemes.js.map +0 -7
  101. package/dist/helpers/security/has-token.js.map +0 -7
  102. package/dist/helpers/security/index.js.map +0 -7
  103. package/dist/helpers/servers.js.map +0 -7
  104. package/dist/helpers/should-ignore-entity.js.map +0 -7
  105. package/dist/migrations/data-version.js.map +0 -7
  106. package/dist/migrations/generate-types.js.map +0 -7
  107. package/dist/migrations/index.js.map +0 -7
  108. package/dist/migrations/local-storage.js.map +0 -7
  109. package/dist/migrations/migrate-to-indexdb.js.map +0 -7
  110. package/dist/migrations/migrator.js.map +0 -7
  111. package/dist/migrations/semver.js.map +0 -7
  112. package/dist/migrations/v-0.0.0/types.generated.js.map +0 -7
  113. package/dist/migrations/v-2.1.0/migration.js.map +0 -7
  114. package/dist/migrations/v-2.1.0/types.generated.js.map +0 -7
  115. package/dist/migrations/v-2.2.0/migration.js.map +0 -7
  116. package/dist/migrations/v-2.2.0/types.generated.js.map +0 -7
  117. package/dist/migrations/v-2.3.0/migration.js.map +0 -7
  118. package/dist/migrations/v-2.3.0/types.generated.js.map +0 -7
  119. package/dist/migrations/v-2.4.0/migration.js.map +0 -7
  120. package/dist/migrations/v-2.4.0/types.generated.js.map +0 -7
  121. package/dist/migrations/v-2.5.0/migration.js.map +0 -7
  122. package/dist/migrations/v-2.5.0/types.generated.js.map +0 -7
  123. package/dist/spec-getters/get-example-from-schema.js.map +0 -7
  124. package/dist/spec-getters/get-parameters-from-operation.js.map +0 -7
  125. package/dist/spec-getters/get-request-body-from-operation.js.map +0 -7
  126. package/dist/spec-getters/get-server-variable-examples.js.map +0 -7
  127. package/dist/spec-getters/index.js.map +0 -7
  128. package/dist/transforms/import-spec.js.map +0 -7
  129. package/dist/transforms/index.js.map +0 -7
@@ -1,417 +1,521 @@
1
- import { isDefined } from "@scalar/helpers/array/is-defined";
2
- import { getRaw } from "@scalar/json-magic/magic-proxy";
3
- import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
4
- import { unpackOverridesProxy } from "@scalar/workspace-store/helpers/overrides-proxy";
1
+ import { isDefined } from '@scalar/helpers/array/is-defined';
2
+ import { getRaw } from '@scalar/json-magic/magic-proxy';
3
+ import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
4
+ import { unpackOverridesProxy } from '@scalar/workspace-store/helpers/overrides-proxy';
5
+ /** Maximum recursion depth to prevent infinite loops in circular references */
5
6
  const MAX_LEVELS_DEEP = 10;
6
- const DEFAULT_ADDITIONAL_PROPERTIES_NAME = "additionalProperty";
7
- const currentISOString = (/* @__PURE__ */ new Date()).toISOString();
8
- const currentDateString = currentISOString.split("T")[0];
9
- const currentTimeString = currentISOString.split("T")[1].split(".")[0];
7
+ /** Default name used for additional properties when no custom name is provided */
8
+ const DEFAULT_ADDITIONAL_PROPERTIES_NAME = 'additionalProperty';
9
+ /**
10
+ * Pre-computed date/time values to avoid expensive Date operations on every call.
11
+ * These are calculated once at module load time for better performance.
12
+ */
13
+ const currentISOString = new Date().toISOString();
14
+ const currentDateString = currentISOString.split('T')[0];
15
+ const currentTimeString = currentISOString.split('T')[1].split('.')[0];
16
+ /**
17
+ * Mapping of OpenAPI string formats to example values.
18
+ * Used to generate realistic examples for different string formats.
19
+ */
10
20
  const genericExampleValues = {
11
- "date-time": currentISOString,
12
- "date": currentDateString,
13
- "email": "hello@example.com",
14
- "hostname": "example.com",
15
- // https://tools.ietf.org/html/rfc6531#section-3.3
16
- "idn-email": "jane.doe@example.com",
17
- // https://tools.ietf.org/html/rfc5890#section-2.3.2.3
18
- "idn-hostname": "example.com",
19
- "ipv4": "127.0.0.1",
20
- "ipv6": "51d4:7fab:bfbf:b7d7:b2cb:d4b4:3dad:d998",
21
- "iri-reference": "/entitiy/1",
22
- // https://tools.ietf.org/html/rfc3987
23
- "iri": "https://example.com/entity/123",
24
- "json-pointer": "/nested/objects",
25
- "password": "super-secret",
26
- "regex": "/[a-z]/",
27
- // https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01
28
- "relative-json-pointer": "1/nested/objects",
29
- // full-time in https://tools.ietf.org/html/rfc3339#section-5.6
30
- "time": currentTimeString,
31
- // either a URI or relative-reference https://tools.ietf.org/html/rfc3986#section-4.1
32
- "uri-reference": "../folder",
33
- "uri-template": "https://example.com/{id}",
34
- "uri": "https://example.com",
35
- "uuid": "123e4567-e89b-12d3-a456-426614174000",
36
- "object-id": "6592008029c8c3e4dc76256c"
21
+ 'date-time': currentISOString,
22
+ 'date': currentDateString,
23
+ 'email': 'hello@example.com',
24
+ 'hostname': 'example.com',
25
+ // https://tools.ietf.org/html/rfc6531#section-3.3
26
+ 'idn-email': 'jane.doe@example.com',
27
+ // https://tools.ietf.org/html/rfc5890#section-2.3.2.3
28
+ 'idn-hostname': 'example.com',
29
+ 'ipv4': '127.0.0.1',
30
+ 'ipv6': '51d4:7fab:bfbf:b7d7:b2cb:d4b4:3dad:d998',
31
+ 'iri-reference': '/entitiy/1',
32
+ // https://tools.ietf.org/html/rfc3987
33
+ 'iri': 'https://example.com/entity/123',
34
+ 'json-pointer': '/nested/objects',
35
+ 'password': 'super-secret',
36
+ 'regex': '/[a-z]/',
37
+ // https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01
38
+ 'relative-json-pointer': '1/nested/objects',
39
+ // full-time in https://tools.ietf.org/html/rfc3339#section-5.6
40
+ 'time': currentTimeString,
41
+ // either a URI or relative-reference https://tools.ietf.org/html/rfc3986#section-4.1
42
+ 'uri-reference': '../folder',
43
+ 'uri-template': 'https://example.com/{id}',
44
+ 'uri': 'https://example.com',
45
+ 'uuid': '123e4567-e89b-12d3-a456-426614174000',
46
+ 'object-id': '6592008029c8c3e4dc76256c',
37
47
  };
48
+ /**
49
+ * Extract enum values from the propertyNames keyword of an object schema.
50
+ * JSON Schema's propertyNames constrains which keys are valid in a map/dict.
51
+ */
38
52
  const getPropertyNamesEnumValues = (schema) => {
39
- if (!("propertyNames" in schema) || !schema.propertyNames) {
40
- return void 0;
41
- }
42
- const resolved = getResolvedRef(schema.propertyNames);
43
- if (resolved && "enum" in resolved && Array.isArray(resolved.enum) && resolved.enum.length > 0) {
44
- return resolved.enum;
45
- }
46
- return void 0;
53
+ if (!('propertyNames' in schema) || !schema.propertyNames) {
54
+ return undefined;
55
+ }
56
+ const resolved = getResolvedRef(schema.propertyNames);
57
+ if (resolved && 'enum' in resolved && Array.isArray(resolved.enum) && resolved.enum.length > 0) {
58
+ return resolved.enum;
59
+ }
60
+ return undefined;
47
61
  };
48
- const guessFromFormat = (schema, makeUpRandomData = false, fallback = "") => {
49
- if ("type" in schema && schema.type === "string" && "format" in schema && schema.format === "binary") {
50
- return new File([""], "filename");
51
- }
52
- if (makeUpRandomData && "format" in schema && schema.format) {
53
- return genericExampleValues[schema.format] ?? fallback;
54
- }
55
- return fallback;
62
+ /**
63
+ * Generate example values for string types based on their format.
64
+ * Special handling for binary format which returns a File object.
65
+ */
66
+ const guessFromFormat = (schema, makeUpRandomData = false, fallback = '') => {
67
+ // Handle binary format specially - return a File object
68
+ if ('type' in schema && schema.type === 'string' && 'format' in schema && schema.format === 'binary') {
69
+ return new File([''], 'filename');
70
+ }
71
+ // Return format-specific example if we have one and are making up data
72
+ if (makeUpRandomData && 'format' in schema && schema.format) {
73
+ return genericExampleValues[schema.format] ?? fallback;
74
+ }
75
+ return fallback;
56
76
  };
57
- const resultCache = /* @__PURE__ */ new WeakMap();
58
- const requiredNamesCache = /* @__PURE__ */ new WeakMap();
77
+ /**
78
+ * WeakMap cache for memoizing resolved example results.
79
+ * Uses the resolved schema object as the key for efficient lookups.
80
+ */
81
+ const resultCache = new WeakMap();
82
+ /** Cache required property names per parent schema for O(1) membership checks */
83
+ const requiredNamesCache = new WeakMap();
84
+ /**
85
+ * Retrieves the set of required property names from a schema.
86
+ * Caches the result in a WeakMap for efficient lookups.
87
+ */
59
88
  const getRequiredNames = (parentSchema) => {
60
- if (!parentSchema) {
61
- return void 0;
62
- }
63
- const cached = requiredNamesCache.get(parentSchema);
64
- if (cached) {
65
- return cached;
66
- }
67
- if ("required" in parentSchema) {
68
- const required = parentSchema.required;
69
- if (Array.isArray(required) && required.length > 0) {
70
- const set = new Set(required);
71
- requiredNamesCache.set(parentSchema, set);
72
- return set;
73
- }
74
- }
75
- return void 0;
89
+ if (!parentSchema) {
90
+ return undefined;
91
+ }
92
+ const cached = requiredNamesCache.get(parentSchema);
93
+ if (cached) {
94
+ return cached;
95
+ }
96
+ if ('required' in parentSchema) {
97
+ const required = parentSchema.required;
98
+ if (Array.isArray(required) && required.length > 0) {
99
+ const set = new Set(required);
100
+ requiredNamesCache.set(parentSchema, set);
101
+ return set;
102
+ }
103
+ }
104
+ return undefined;
76
105
  };
106
+ /**
107
+ * Cache the result for a schema if it is an object type.
108
+ * Primitive values are not cached to avoid unnecessary WeakMap operations.
109
+ */
77
110
  const cache = (schema, result) => {
78
- if (typeof result !== "object" || result === null) {
111
+ if (typeof result !== 'object' || result === null) {
112
+ return result;
113
+ }
114
+ resultCache.set(getRaw(unpackOverridesProxy(schema)), result);
79
115
  return result;
80
- }
81
- resultCache.set(getRaw(unpackOverridesProxy(schema)), result);
82
- return result;
83
116
  };
117
+ /**
118
+ * Check if a schema uses composition keywords (allOf, oneOf, anyOf).
119
+ * These require special handling for merging or selecting schemas.
120
+ */
84
121
  const isComposed = (schema) => !!(schema.allOf || schema.oneOf || schema.anyOf);
122
+ /**
123
+ * Determine if a property should be omitted based on the options.
124
+ * Properties are omitted if they are not required and the option is enabled.
125
+ */
85
126
  const shouldOmitProperty = (schema, parentSchema, propertyName, options) => {
86
- if (options?.omitEmptyAndOptionalProperties !== true) {
87
- return false;
88
- }
89
- const isContainer = "type" in schema && (schema.type === "object" || schema.type === "array") || isComposed(schema);
90
- if (isContainer) {
91
- return false;
92
- }
93
- if ("examples" in schema && Array.isArray(schema.examples) && schema.examples.length > 0 || "example" in schema && schema.example !== void 0 || "default" in schema && schema.default !== void 0 || "const" in schema && schema.const !== void 0 || "enum" in schema && Array.isArray(schema.enum) && schema.enum.length > 0) {
94
- return false;
95
- }
96
- const name = propertyName ?? schema.title ?? "";
97
- const requiredNames = getRequiredNames(parentSchema);
98
- const isRequired = requiredNames ? requiredNames.has(name) : false;
99
- return !isRequired;
127
+ if (options?.omitEmptyAndOptionalProperties !== true) {
128
+ return false;
129
+ }
130
+ // Never omit container types (objects/arrays) or composed schemas
131
+ const isContainer = ('type' in schema && (schema.type === 'object' || schema.type === 'array')) || isComposed(schema);
132
+ if (isContainer) {
133
+ return false;
134
+ }
135
+ // Do not omit if explicit example-like values are present
136
+ if (('examples' in schema && Array.isArray(schema.examples) && schema.examples.length > 0) ||
137
+ ('example' in schema && schema.example !== undefined) ||
138
+ ('default' in schema && schema.default !== undefined) ||
139
+ ('const' in schema && schema.const !== undefined) ||
140
+ ('enum' in schema && Array.isArray(schema.enum) && schema.enum.length > 0)) {
141
+ return false;
142
+ }
143
+ // Check if the property is required
144
+ const name = propertyName ?? schema.title ?? '';
145
+ const requiredNames = getRequiredNames(parentSchema);
146
+ const isRequired = requiredNames ? requiredNames.has(name) : false;
147
+ return !isRequired;
100
148
  };
149
+ /**
150
+ * Merge two example values with predictable semantics.
151
+ * Arrays are concatenated, objects are merged, otherwise the new value wins.
152
+ */
101
153
  const mergeExamples = (baseValue, newValue) => {
102
- if (Array.isArray(baseValue) && Array.isArray(newValue)) {
103
- return [...baseValue, ...newValue];
104
- }
105
- if (baseValue && typeof baseValue === "object" && newValue && typeof newValue === "object") {
106
- return { ...baseValue, ...newValue };
107
- }
108
- return newValue;
154
+ if (Array.isArray(baseValue) && Array.isArray(newValue)) {
155
+ return [...baseValue, ...newValue];
156
+ }
157
+ if (baseValue && typeof baseValue === 'object' && newValue && typeof newValue === 'object') {
158
+ return { ...baseValue, ...newValue };
159
+ }
160
+ return newValue;
109
161
  };
162
+ /**
163
+ * Build an example for an object schema, including properties, patternProperties,
164
+ * additionalProperties, and composition (allOf/oneOf/anyOf) merging.
165
+ */
110
166
  const handleObjectSchema = (schema, options, level, seen) => {
111
- const response = {};
112
- if ("properties" in schema && schema.properties) {
113
- const propertyNames = Object.keys(schema.properties);
114
- const limit = propertyNames.length;
115
- for (let i = 0; i < limit; i++) {
116
- const propertyName = propertyNames[i];
117
- const propertySchema = getResolvedRef(schema.properties[propertyName]);
118
- if (!propertySchema) {
119
- continue;
120
- }
121
- const propertyXmlName = options?.xml && "xml" in propertySchema ? propertySchema.xml?.name : void 0;
122
- const value = getExampleFromSchema(propertySchema, options, {
123
- level: level + 1,
124
- parentSchema: schema,
125
- name: propertyName,
126
- seen
127
- });
128
- if (typeof value !== "undefined") {
129
- response[propertyXmlName ?? propertyName] = value;
130
- }
131
- }
132
- }
133
- if ("patternProperties" in schema && schema.patternProperties) {
134
- for (const pattern of Object.keys(schema.patternProperties)) {
135
- const propertySchema = getResolvedRef(schema.patternProperties[pattern]);
136
- if (!propertySchema) {
137
- continue;
138
- }
139
- response[pattern] = getExampleFromSchema(propertySchema, options, {
140
- level: level + 1,
141
- parentSchema: schema,
142
- name: pattern,
143
- seen
144
- });
145
- }
146
- }
147
- if ("additionalProperties" in schema && schema.additionalProperties !== void 0 && schema.additionalProperties !== false) {
148
- const additional = getResolvedRef(schema.additionalProperties);
149
- const isAnyType = schema.additionalProperties === true || typeof schema.additionalProperties === "object" && Object.keys(schema.additionalProperties).length === 0;
150
- const hasCustomName = typeof additional === "object" && "x-additionalPropertiesName" in additional && typeof additional["x-additionalPropertiesName"] === "string" && additional["x-additionalPropertiesName"].trim().length > 0;
151
- const propertyNamesEnum = hasCustomName ? void 0 : getPropertyNamesEnumValues(schema);
152
- const additionalName = hasCustomName ? additional["x-additionalPropertiesName"].trim() : DEFAULT_ADDITIONAL_PROPERTIES_NAME;
153
- const additionalValue = isAnyType ? "anything" : typeof additional === "object" ? getExampleFromSchema(additional, options, {
154
- level: level + 1,
155
- seen
156
- }) : "anything";
157
- if (propertyNamesEnum && propertyNamesEnum.length > 0) {
158
- response[String(propertyNamesEnum[0])] = additionalValue;
159
- } else {
160
- response[additionalName] = additionalValue;
161
- }
162
- }
163
- if (schema.oneOf?.[0]) {
164
- Object.assign(
165
- response,
166
- getExampleFromSchema(getResolvedRef(schema.oneOf[0]), options, {
167
- level: level + 1,
168
- seen
169
- })
170
- );
171
- } else if (schema.anyOf?.[0]) {
172
- Object.assign(
173
- response,
174
- getExampleFromSchema(getResolvedRef(schema.anyOf[0]), options, {
175
- level: level + 1,
176
- seen
177
- })
178
- );
179
- } else if (Array.isArray(schema.allOf) && schema.allOf.length > 0) {
180
- let merged = response;
181
- for (const item of schema.allOf) {
182
- const ex = getExampleFromSchema(getResolvedRef(item), options, {
183
- level: level + 1,
184
- parentSchema: schema,
185
- seen
186
- });
187
- merged = mergeExamples(merged, ex);
188
- }
189
- if (merged && typeof merged === "object") {
190
- Object.assign(response, merged);
191
- }
192
- }
193
- if (options?.xml && "xml" in schema && schema.xml?.name && level === 0) {
194
- const wrapped = {};
195
- wrapped[schema.xml.name] = response;
196
- return cache(schema, wrapped);
197
- }
198
- return cache(schema, response);
167
+ const response = {};
168
+ if ('properties' in schema && schema.properties) {
169
+ const propertyNames = Object.keys(schema.properties);
170
+ const limit = propertyNames.length;
171
+ for (let i = 0; i < limit; i++) {
172
+ const propertyName = propertyNames[i];
173
+ const propertySchema = getResolvedRef(schema.properties[propertyName]);
174
+ if (!propertySchema) {
175
+ continue;
176
+ }
177
+ const propertyXmlName = options?.xml && 'xml' in propertySchema ? propertySchema.xml?.name : undefined;
178
+ const value = getExampleFromSchema(propertySchema, options, {
179
+ level: level + 1,
180
+ parentSchema: schema,
181
+ name: propertyName,
182
+ seen,
183
+ });
184
+ if (typeof value !== 'undefined') {
185
+ response[propertyXmlName ?? propertyName] = value;
186
+ }
187
+ }
188
+ }
189
+ if ('patternProperties' in schema && schema.patternProperties) {
190
+ for (const pattern of Object.keys(schema.patternProperties)) {
191
+ const propertySchema = getResolvedRef(schema.patternProperties[pattern]);
192
+ if (!propertySchema) {
193
+ continue;
194
+ }
195
+ response[pattern] = getExampleFromSchema(propertySchema, options, {
196
+ level: level + 1,
197
+ parentSchema: schema,
198
+ name: pattern,
199
+ seen,
200
+ });
201
+ }
202
+ }
203
+ if ('additionalProperties' in schema &&
204
+ schema.additionalProperties !== undefined &&
205
+ schema.additionalProperties !== false) {
206
+ const additional = getResolvedRef(schema.additionalProperties);
207
+ const isAnyType = schema.additionalProperties === true ||
208
+ (typeof schema.additionalProperties === 'object' && Object.keys(schema.additionalProperties).length === 0);
209
+ // Check for explicit x-additionalPropertiesName first
210
+ const hasCustomName = typeof additional === 'object' &&
211
+ 'x-additionalPropertiesName' in additional &&
212
+ typeof additional['x-additionalPropertiesName'] === 'string' &&
213
+ additional['x-additionalPropertiesName'].trim().length > 0;
214
+ // Use propertyNames enum values as example keys when no custom name is set
215
+ const propertyNamesEnum = hasCustomName ? undefined : getPropertyNamesEnumValues(schema);
216
+ const additionalName = hasCustomName
217
+ ? additional['x-additionalPropertiesName'].trim()
218
+ : DEFAULT_ADDITIONAL_PROPERTIES_NAME;
219
+ const additionalValue = isAnyType
220
+ ? 'anything'
221
+ : typeof additional === 'object'
222
+ ? getExampleFromSchema(additional, options, {
223
+ level: level + 1,
224
+ seen,
225
+ })
226
+ : 'anything';
227
+ if (propertyNamesEnum && propertyNamesEnum.length > 0) {
228
+ // Use the first enum value as a realistic example key
229
+ response[String(propertyNamesEnum[0])] = additionalValue;
230
+ }
231
+ else {
232
+ response[additionalName] = additionalValue;
233
+ }
234
+ }
235
+ // onOf
236
+ if (schema.oneOf?.[0]) {
237
+ Object.assign(response, getExampleFromSchema(getResolvedRef(schema.oneOf[0]), options, {
238
+ level: level + 1,
239
+ seen,
240
+ }));
241
+ }
242
+ // anyOf
243
+ else if (schema.anyOf?.[0]) {
244
+ Object.assign(response, getExampleFromSchema(getResolvedRef(schema.anyOf[0]), options, {
245
+ level: level + 1,
246
+ seen,
247
+ }));
248
+ }
249
+ // allOf
250
+ else if (Array.isArray(schema.allOf) && schema.allOf.length > 0) {
251
+ let merged = response;
252
+ for (const item of schema.allOf) {
253
+ const ex = getExampleFromSchema(getResolvedRef(item), options, {
254
+ level: level + 1,
255
+ parentSchema: schema,
256
+ seen,
257
+ });
258
+ merged = mergeExamples(merged, ex);
259
+ }
260
+ if (merged && typeof merged === 'object') {
261
+ Object.assign(response, merged);
262
+ }
263
+ }
264
+ if (options?.xml && 'xml' in schema && schema.xml?.name && level === 0) {
265
+ const wrapped = {};
266
+ wrapped[schema.xml.name] = response;
267
+ return cache(schema, wrapped);
268
+ }
269
+ return cache(schema, response);
199
270
  };
271
+ /** Build an example for an array schema, including items, allOf, oneOf/anyOf, and XML wrapping */
200
272
  const handleArraySchema = (schema, options, level, seen) => {
201
- const items = "items" in schema ? getResolvedRef(schema.items) : void 0;
202
- const itemsXmlTagName = items && typeof items === "object" && "xml" in items ? items.xml?.name : void 0;
203
- const wrapItems = !!(options?.xml && "xml" in schema && schema.xml?.wrapped && itemsXmlTagName);
204
- if (schema.example !== void 0) {
205
- return cache(schema, wrapItems ? { [itemsXmlTagName]: schema.example } : schema.example);
206
- }
207
- if (items && typeof items === "object") {
208
- if (Array.isArray(items.allOf) && items.allOf.length > 0) {
209
- const allOf = items.allOf.filter(isDefined);
210
- const first = getResolvedRef(allOf[0]);
211
- if (first && typeof first === "object" && "type" in first && first.type === "object") {
212
- const combined = { type: "object", allOf };
213
- const merged = getExampleFromSchema(combined, options, {
214
- level: level + 1,
215
- parentSchema: schema,
216
- seen
273
+ const items = 'items' in schema ? getResolvedRef(schema.items) : undefined;
274
+ const itemsXmlTagName = items && typeof items === 'object' && 'xml' in items ? items.xml?.name : undefined;
275
+ const wrapItems = !!(options?.xml && 'xml' in schema && schema.xml?.wrapped && itemsXmlTagName);
276
+ if (schema.example !== undefined) {
277
+ return cache(schema, wrapItems ? { [itemsXmlTagName]: schema.example } : schema.example);
278
+ }
279
+ if (items && typeof items === 'object') {
280
+ if (Array.isArray(items.allOf) && items.allOf.length > 0) {
281
+ const allOf = items.allOf.filter(isDefined);
282
+ const first = getResolvedRef(allOf[0]);
283
+ if (first && typeof first === 'object' && 'type' in first && first.type === 'object') {
284
+ const combined = { type: 'object', allOf };
285
+ const merged = getExampleFromSchema(combined, options, {
286
+ level: level + 1,
287
+ parentSchema: schema,
288
+ seen,
289
+ });
290
+ return cache(schema, wrapItems ? [{ [itemsXmlTagName]: merged }] : [merged]);
291
+ }
292
+ const examples = allOf
293
+ .map((s) => getExampleFromSchema(getResolvedRef(s), options, {
294
+ level: level + 1,
295
+ parentSchema: schema,
296
+ seen,
297
+ }))
298
+ .filter(isDefined);
299
+ return cache(schema, wrapItems ? examples.map((e) => ({ [itemsXmlTagName]: e })) : examples);
300
+ }
301
+ const union = items.anyOf || items.oneOf;
302
+ if (union && union.length > 0) {
303
+ const first = union[0];
304
+ const ex = getExampleFromSchema(getResolvedRef(first), options, {
305
+ level: level + 1,
306
+ parentSchema: schema,
307
+ seen,
308
+ });
309
+ return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex]);
310
+ }
311
+ }
312
+ const isObject = items && typeof items === 'object' && (('type' in items && items.type === 'object') || 'properties' in items);
313
+ const isArray = items && typeof items === 'object' && (('type' in items && items.type === 'array') || 'items' in items);
314
+ if (items && typeof items === 'object' && (('type' in items && items.type) || isObject || isArray)) {
315
+ const ex = getExampleFromSchema(items, options, {
316
+ level: level + 1,
317
+ seen,
217
318
  });
218
- return cache(schema, wrapItems ? [{ [itemsXmlTagName]: merged }] : [merged]);
219
- }
220
- const examples = allOf.map(
221
- (s) => getExampleFromSchema(getResolvedRef(s), options, {
222
- level: level + 1,
223
- parentSchema: schema,
224
- seen
225
- })
226
- ).filter(isDefined);
227
- return cache(
228
- schema,
229
- wrapItems ? examples.map((e) => ({ [itemsXmlTagName]: e })) : examples
230
- );
231
- }
232
- const union = items.anyOf || items.oneOf;
233
- if (union && union.length > 0) {
234
- const first = union[0];
235
- const ex = getExampleFromSchema(getResolvedRef(first), options, {
236
- level: level + 1,
237
- parentSchema: schema,
238
- seen
239
- });
240
- return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex]);
241
- }
242
- }
243
- const isObject = items && typeof items === "object" && ("type" in items && items.type === "object" || "properties" in items);
244
- const isArray = items && typeof items === "object" && ("type" in items && items.type === "array" || "items" in items);
245
- if (items && typeof items === "object" && ("type" in items && items.type || isObject || isArray)) {
246
- const ex = getExampleFromSchema(items, options, {
247
- level: level + 1,
248
- seen
249
- });
250
- return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex]);
251
- }
252
- return cache(schema, []);
319
+ return cache(schema, wrapItems ? [{ [itemsXmlTagName]: ex }] : [ex]);
320
+ }
321
+ return cache(schema, []);
253
322
  };
323
+ /** Return primitive example value for single-type schemas, or undefined if not primitive */
254
324
  const getPrimitiveValue = (schema, makeUpRandomData, emptyString) => {
255
- if ("type" in schema && schema.type && !Array.isArray(schema.type)) {
256
- switch (schema.type) {
257
- case "string":
258
- return guessFromFormat(schema, makeUpRandomData, emptyString ?? "");
259
- case "boolean":
260
- return true;
261
- case "integer":
262
- return "minimum" in schema && typeof schema.minimum === "number" ? schema.minimum : 1;
263
- case "number":
264
- return "minimum" in schema && typeof schema.minimum === "number" ? schema.minimum : 1;
265
- case "array":
266
- return [];
267
- default:
268
- return void 0;
269
- }
270
- }
271
- return void 0;
325
+ if ('type' in schema && schema.type && !Array.isArray(schema.type)) {
326
+ switch (schema.type) {
327
+ case 'string':
328
+ return guessFromFormat(schema, makeUpRandomData, emptyString ?? '');
329
+ case 'boolean':
330
+ return true;
331
+ case 'integer':
332
+ return 'minimum' in schema && typeof schema.minimum === 'number' ? schema.minimum : 1;
333
+ case 'number':
334
+ return 'minimum' in schema && typeof schema.minimum === 'number' ? schema.minimum : 1;
335
+ case 'array':
336
+ return [];
337
+ default:
338
+ return undefined;
339
+ }
340
+ }
341
+ return undefined;
272
342
  };
343
+ /** Return primitive example value for union-type schemas (type: string[]) */
273
344
  const getUnionPrimitiveValue = (schema, makeUpRandomData, emptyString) => {
274
- if ("type" in schema && Array.isArray(schema.type)) {
275
- if (schema.type.includes("null")) {
276
- return null;
277
- }
278
- const first = schema.type[0];
279
- if (first) {
280
- switch (first) {
281
- case "string":
282
- return guessFromFormat(schema, makeUpRandomData, emptyString ?? "");
283
- case "boolean":
284
- return true;
285
- case "integer":
286
- return "minimum" in schema && typeof schema.minimum === "number" ? schema.minimum : 1;
287
- case "number":
288
- return "minimum" in schema && typeof schema.minimum === "number" ? schema.minimum : 1;
289
- case "null":
290
- return null;
291
- default:
292
- return void 0;
293
- }
294
- }
295
- }
296
- return void 0;
345
+ if ('type' in schema && Array.isArray(schema.type)) {
346
+ if (schema.type.includes('null')) {
347
+ return null;
348
+ }
349
+ const first = schema.type[0];
350
+ if (first) {
351
+ switch (first) {
352
+ case 'string':
353
+ return guessFromFormat(schema, makeUpRandomData, emptyString ?? '');
354
+ case 'boolean':
355
+ return true;
356
+ case 'integer':
357
+ return 'minimum' in schema && typeof schema.minimum === 'number' ? schema.minimum : 1;
358
+ case 'number':
359
+ return 'minimum' in schema && typeof schema.minimum === 'number' ? schema.minimum : 1;
360
+ case 'null':
361
+ return null;
362
+ default:
363
+ return undefined;
364
+ }
365
+ }
366
+ }
367
+ return undefined;
297
368
  };
298
- const getExampleFromSchema = (schema, options, args) => {
299
- const { level = 0, parentSchema, name, seen = /* @__PURE__ */ new WeakSet() } = args ?? {};
300
- const _schema = getResolvedRef(schema);
301
- if (!isDefined(_schema)) {
302
- return void 0;
303
- }
304
- const targetValue = getRaw(unpackOverridesProxy(_schema));
305
- if (seen.has(targetValue)) {
306
- return void 0;
307
- }
308
- seen.add(targetValue);
309
- if (resultCache.has(targetValue)) {
310
- seen.delete(targetValue);
311
- return resultCache.get(targetValue);
312
- }
313
- if (level > MAX_LEVELS_DEEP) {
314
- seen.delete(targetValue);
315
- return "[Max Depth Exceeded]";
316
- }
317
- const makeUpRandomData = !!options?.emptyString;
318
- if (_schema.deprecated || options?.mode === "write" && _schema.readOnly || options?.mode === "read" && _schema.writeOnly || shouldOmitProperty(_schema, parentSchema, name, options)) {
319
- seen.delete(targetValue);
320
- return void 0;
321
- }
322
- if ("x-variable" in _schema && _schema["x-variable"]) {
323
- const value = options?.variables?.[_schema["x-variable"]];
324
- if (value !== void 0) {
325
- if ("type" in _schema && (_schema.type === "number" || _schema.type === "integer")) {
369
+ /**
370
+ * Generate an example value from a given OpenAPI SchemaObject.
371
+ *
372
+ * This function recursively processes OpenAPI schemas to create realistic example data.
373
+ * It handles all OpenAPI schema types including primitives, objects, arrays, and
374
+ * composition schemas (allOf, oneOf, anyOf).
375
+ * Uses a tonne of caching for maximum performance.
376
+ *
377
+ * @param schema - The OpenAPI SchemaObject to generate an example from.
378
+ * @param options - Options to customize example generation.
379
+ * @param level - The current recursion depth.
380
+ * @param parentSchema - The parent schema, if any.
381
+ * @param name - The name of the property being processed.
382
+ * @returns An example value for the given schema.
383
+ *
384
+ * @deprecated Use the one from `@scalar/api-client/v2/blocks/operation-code-sample` instead.
385
+ */
386
+ export const getExampleFromSchema = (schema, options, args) => {
387
+ const { level = 0, parentSchema, name, seen = new WeakSet() } = args ?? {};
388
+ // Resolve any $ref references to get the actual schema
389
+ const _schema = getResolvedRef(schema);
390
+ if (!isDefined(_schema)) {
391
+ return undefined;
392
+ }
393
+ // Unpack from all proxies to get the raw schema object for cycle detection
394
+ const targetValue = getRaw(unpackOverridesProxy(_schema));
395
+ if (seen.has(targetValue)) {
396
+ return undefined;
397
+ }
398
+ seen.add(targetValue);
399
+ // Check cache first for performance - avoid recomputing the same schema
400
+ if (resultCache.has(targetValue)) {
326
401
  seen.delete(targetValue);
327
- return cache(_schema, Number(value));
328
- }
329
- seen.delete(targetValue);
330
- return cache(_schema, value);
402
+ return resultCache.get(targetValue);
331
403
  }
332
- }
333
- if (Array.isArray(_schema.examples) && _schema.examples.length > 0) {
334
- seen.delete(targetValue);
335
- return cache(_schema, _schema.examples[0]);
336
- }
337
- if (_schema.example !== void 0) {
338
- seen.delete(targetValue);
339
- return cache(_schema, _schema.example);
340
- }
341
- if (_schema.default !== void 0) {
342
- seen.delete(targetValue);
343
- return cache(_schema, _schema.default);
344
- }
345
- if (_schema.const !== void 0) {
346
- seen.delete(targetValue);
347
- return cache(_schema, _schema.const);
348
- }
349
- if (Array.isArray(_schema.enum) && _schema.enum.length > 0) {
350
- seen.delete(targetValue);
351
- return cache(_schema, _schema.enum[0]);
352
- }
353
- if ("properties" in _schema || "type" in _schema && _schema.type === "object") {
354
- const result = handleObjectSchema(_schema, options, level, seen);
355
- seen.delete(targetValue);
356
- return result;
357
- }
358
- if ("type" in _schema && _schema.type === "array" || "items" in _schema) {
359
- const result = handleArraySchema(_schema, options, level, seen);
360
- seen.delete(targetValue);
361
- return result;
362
- }
363
- const primitive = getPrimitiveValue(_schema, makeUpRandomData, options?.emptyString);
364
- if (primitive !== void 0) {
365
- seen.delete(targetValue);
366
- return cache(_schema, primitive);
367
- }
368
- const discriminate = _schema.oneOf || _schema.anyOf;
369
- if (Array.isArray(discriminate) && discriminate.length > 0) {
370
- for (const item of discriminate) {
371
- const resolved = getResolvedRef(item);
372
- if (resolved && (!("type" in resolved) || resolved.type !== "null")) {
404
+ // Prevent infinite recursion in circular references
405
+ if (level > MAX_LEVELS_DEEP) {
373
406
  seen.delete(targetValue);
374
- return cache(
375
- _schema,
376
- getExampleFromSchema(resolved, options, {
377
- level: level + 1,
378
- seen
379
- })
380
- );
381
- }
407
+ return '[Max Depth Exceeded]';
382
408
  }
383
- seen.delete(targetValue);
384
- return cache(_schema, null);
385
- }
386
- if (Array.isArray(_schema.allOf) && _schema.allOf.length > 0) {
387
- let merged = void 0;
388
- const items = _schema.allOf;
389
- for (const item of items) {
390
- const ex = getExampleFromSchema(item, options, {
391
- level: level + 1,
392
- parentSchema: _schema,
393
- seen
394
- });
395
- if (merged === void 0) {
396
- merged = ex;
397
- } else if (merged && typeof merged === "object" && ex && typeof ex === "object") {
398
- merged = mergeExamples(merged, ex);
399
- } else if (ex !== void 0) {
400
- merged = ex;
401
- }
409
+ // Determine if we should generate realistic example data
410
+ const makeUpRandomData = !!options?.emptyString;
411
+ // Early exits for schemas that should not be included (deprecated, readOnly, writeOnly, omitEmptyAndOptionalProperties)
412
+ if (_schema.deprecated ||
413
+ (options?.mode === 'write' && _schema.readOnly) ||
414
+ (options?.mode === 'read' && _schema.writeOnly) ||
415
+ shouldOmitProperty(_schema, parentSchema, name, options)) {
416
+ seen.delete(targetValue);
417
+ return undefined;
402
418
  }
419
+ // Handle custom variables (x-variable extension)
420
+ if ('x-variable' in _schema && _schema['x-variable']) {
421
+ const value = options?.variables?.[_schema['x-variable']];
422
+ if (value !== undefined) {
423
+ // Type coercion for numeric types
424
+ if ('type' in _schema && (_schema.type === 'number' || _schema.type === 'integer')) {
425
+ seen.delete(targetValue);
426
+ return cache(_schema, Number(value));
427
+ }
428
+ seen.delete(targetValue);
429
+ return cache(_schema, value);
430
+ }
431
+ }
432
+ // Priority order: examples > example > default > const > enum
433
+ if (Array.isArray(_schema.examples) && _schema.examples.length > 0) {
434
+ seen.delete(targetValue);
435
+ return cache(_schema, _schema.examples[0]);
436
+ }
437
+ if (_schema.example !== undefined) {
438
+ seen.delete(targetValue);
439
+ return cache(_schema, _schema.example);
440
+ }
441
+ if (_schema.default !== undefined) {
442
+ seen.delete(targetValue);
443
+ return cache(_schema, _schema.default);
444
+ }
445
+ if (_schema.const !== undefined) {
446
+ seen.delete(targetValue);
447
+ return cache(_schema, _schema.const);
448
+ }
449
+ if (Array.isArray(_schema.enum) && _schema.enum.length > 0) {
450
+ seen.delete(targetValue);
451
+ return cache(_schema, _schema.enum[0]);
452
+ }
453
+ // Handle object types - check for properties to identify objects
454
+ if ('properties' in _schema || ('type' in _schema && _schema.type === 'object')) {
455
+ const result = handleObjectSchema(_schema, options, level, seen);
456
+ seen.delete(targetValue);
457
+ return result;
458
+ }
459
+ // Handle array types
460
+ if (('type' in _schema && _schema.type === 'array') || 'items' in _schema) {
461
+ const result = handleArraySchema(_schema, options, level, seen);
462
+ seen.delete(targetValue);
463
+ return result;
464
+ }
465
+ // Handle primitive types without allocating temporary objects
466
+ const primitive = getPrimitiveValue(_schema, makeUpRandomData, options?.emptyString);
467
+ if (primitive !== undefined) {
468
+ seen.delete(targetValue);
469
+ return cache(_schema, primitive);
470
+ }
471
+ // Handle composition schemas (oneOf, anyOf) at root level
472
+ const discriminate = _schema.oneOf || _schema.anyOf;
473
+ if (Array.isArray(discriminate) && discriminate.length > 0) {
474
+ // Find the first non-null type without allocating intermediate arrays
475
+ for (const item of discriminate) {
476
+ const resolved = getResolvedRef(item);
477
+ if (resolved && (!('type' in resolved) || resolved.type !== 'null')) {
478
+ seen.delete(targetValue);
479
+ return cache(_schema, getExampleFromSchema(resolved, options, {
480
+ level: level + 1,
481
+ seen,
482
+ }));
483
+ }
484
+ }
485
+ seen.delete(targetValue);
486
+ return cache(_schema, null);
487
+ }
488
+ // Handle allOf at root level (non-object/array schemas)
489
+ if (Array.isArray(_schema.allOf) && _schema.allOf.length > 0) {
490
+ let merged = undefined;
491
+ const items = _schema.allOf;
492
+ for (const item of items) {
493
+ const ex = getExampleFromSchema(item, options, {
494
+ level: level + 1,
495
+ parentSchema: _schema,
496
+ seen,
497
+ });
498
+ if (merged === undefined) {
499
+ merged = ex;
500
+ }
501
+ else if (merged && typeof merged === 'object' && ex && typeof ex === 'object') {
502
+ merged = mergeExamples(merged, ex);
503
+ }
504
+ else if (ex !== undefined) {
505
+ // Prefer the latest defined primitive value
506
+ merged = ex;
507
+ }
508
+ }
509
+ seen.delete(targetValue);
510
+ return cache(_schema, merged ?? null);
511
+ }
512
+ // Handle union types (array of types)
513
+ const unionPrimitive = getUnionPrimitiveValue(_schema, makeUpRandomData, options?.emptyString);
514
+ if (unionPrimitive !== undefined) {
515
+ seen.delete(targetValue);
516
+ return cache(_schema, unionPrimitive);
517
+ }
518
+ // Default fallback
403
519
  seen.delete(targetValue);
404
- return cache(_schema, merged ?? null);
405
- }
406
- const unionPrimitive = getUnionPrimitiveValue(_schema, makeUpRandomData, options?.emptyString);
407
- if (unionPrimitive !== void 0) {
408
- seen.delete(targetValue);
409
- return cache(_schema, unionPrimitive);
410
- }
411
- seen.delete(targetValue);
412
- return cache(_schema, null);
413
- };
414
- export {
415
- getExampleFromSchema
520
+ return cache(_schema, null);
416
521
  };
417
- //# sourceMappingURL=get-example-from-schema.js.map