@mintlify/validation 0.1.395 → 0.1.397

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.
@@ -1,3 +1,4 @@
1
+ import lcm from 'lcm';
1
2
  export const stringFileFormats = ['binary', 'base64'];
2
3
  export const structuredDataContentTypes = [
3
4
  'multipart/form-data',
@@ -79,3 +80,232 @@ export function recursivelyFindDescription(schema, name) {
79
80
  }
80
81
  return undefined;
81
82
  }
83
+ export function sortSchemas(schemas) {
84
+ // all schemas with no `type` field go at the end of the array to avoid
85
+ // caling `copyKeyIfDefined` for discriminators with empty types unless
86
+ // we're certain the schema's title is the last possible option
87
+ schemas.sort((a, b) => {
88
+ var _a, _b;
89
+ const aDepth = (_a = a._depth) !== null && _a !== void 0 ? _a : 0;
90
+ const bDepth = (_b = b._depth) !== null && _b !== void 0 ? _b : 0;
91
+ if (aDepth !== bDepth) {
92
+ return aDepth - bDepth;
93
+ }
94
+ if (a.type && !b.type)
95
+ return -1;
96
+ if (!a.type && b.type)
97
+ return 1;
98
+ return 0;
99
+ });
100
+ }
101
+ export function mergeTypes(acc, curr) {
102
+ // schemas are meant to be immutable, so copy the type
103
+ let currType = curr.type;
104
+ // don't throw an error if type is being constricted
105
+ if (acc.type === 'integer' && currType === 'number') {
106
+ currType = 'integer';
107
+ }
108
+ else if (acc.type === 'number' && currType === 'integer') {
109
+ acc.type = 'integer';
110
+ }
111
+ else if (acc.type === undefined && currType !== undefined) {
112
+ acc.type = currType;
113
+ }
114
+ else if (acc.type !== undefined && currType === undefined) {
115
+ currType = acc.type;
116
+ }
117
+ if (acc.type !== currType) {
118
+ throw new Error(`${acc.type} vs ${currType}`);
119
+ }
120
+ }
121
+ export function normalizeMinMax(schema) {
122
+ // we're technically breaking immutability rules here, but it's probably okay because
123
+ // it will be the same every time - we're just normalizing the maximum/minimum
124
+ // and exclusiveMaximum/exclusiveMinimum properties
125
+ if (typeof schema.exclusiveMaximum === 'number') {
126
+ if (schema.maximum === undefined || schema.maximum >= schema.exclusiveMaximum) {
127
+ schema.maximum = schema.exclusiveMaximum;
128
+ schema.exclusiveMaximum = true;
129
+ }
130
+ else {
131
+ schema.exclusiveMaximum = undefined;
132
+ }
133
+ }
134
+ if (typeof schema.exclusiveMinimum === 'number') {
135
+ if (schema.minimum === undefined || schema.minimum <= schema.exclusiveMinimum) {
136
+ schema.minimum = schema.exclusiveMinimum;
137
+ schema.exclusiveMinimum = true;
138
+ }
139
+ else {
140
+ schema.exclusiveMinimum = undefined;
141
+ }
142
+ }
143
+ }
144
+ const combine = (schema1, schema2, key, transform) => {
145
+ var _a;
146
+ return schema1[key] !== undefined && schema2[key] !== undefined
147
+ ? transform(schema1[key], schema2[key])
148
+ : (_a = schema1[key]) !== null && _a !== void 0 ? _a : schema2[key];
149
+ };
150
+ const combineKeyIfDefined = (key, source, destination, transform) => {
151
+ addKeyIfDefined(key, combine(source, destination, key, transform), destination);
152
+ };
153
+ export function combineTitle(acc, curr) {
154
+ if (curr.discriminator == undefined &&
155
+ (curr.type != undefined || acc.title == undefined) &&
156
+ !(curr.isAllOf && curr.refIdentifier && curr.refIdentifier !== curr.isAllOf)) {
157
+ copyKeyIfDefined('title', curr, acc);
158
+ }
159
+ }
160
+ export function copyAndCombineKeys(acc, curr) {
161
+ copyKeyIfDefined('refIdentifier', curr, acc);
162
+ copyKeyIfDefined('examples', curr, acc);
163
+ copyKeyIfDefined('format', curr, acc);
164
+ copyKeyIfDefined('default', curr, acc);
165
+ copyKeyIfDefined('x-default', curr, acc);
166
+ copyKeyIfDefined('const', curr, acc);
167
+ combineKeyIfDefined('multipleOf', curr, acc, lcm);
168
+ combineKeyIfDefined('maxLength', curr, acc, Math.min);
169
+ combineKeyIfDefined('minLength', curr, acc, Math.max);
170
+ combineKeyIfDefined('maxItems', curr, acc, Math.min);
171
+ combineKeyIfDefined('minItems', curr, acc, Math.max);
172
+ combineKeyIfDefined('maxProperties', curr, acc, Math.min);
173
+ combineKeyIfDefined('minProperties', curr, acc, Math.max);
174
+ combineKeyIfDefined('required', curr, acc, (a, b) => b.concat(a.filter((value) => !b.includes(value))));
175
+ combineKeyIfDefined('enum', curr, acc, (a, b) => b.filter((value) => a.includes(value)));
176
+ combineKeyIfDefined('readOnly', curr, acc, (a, b) => a && b);
177
+ combineKeyIfDefined('writeOnly', curr, acc, (a, b) => a && b);
178
+ combineKeyIfDefined('deprecated', curr, acc, (a, b) => a || b);
179
+ const combinedMaximum = combine(curr, acc, 'maximum', Math.min);
180
+ const combinedMinimum = combine(curr, acc, 'minimum', Math.max);
181
+ const exclusiveMaximum = (acc.maximum === combinedMaximum ? acc.exclusiveMaximum : undefined) ||
182
+ (curr.maximum === combinedMaximum ? curr.exclusiveMaximum : undefined);
183
+ addKeyIfDefined('exclusiveMaximum', exclusiveMaximum, acc);
184
+ const exclusiveMinimum = (acc.minimum === combinedMinimum ? acc.exclusiveMinimum : undefined) ||
185
+ (curr.minimum === combinedMinimum ? curr.exclusiveMinimum : undefined);
186
+ addKeyIfDefined('exclusiveMinimum', exclusiveMinimum, acc);
187
+ addKeyIfDefined('maximum', combinedMaximum, acc);
188
+ addKeyIfDefined('minimum', combinedMinimum, acc);
189
+ }
190
+ export function combineExamples(acc, curr) {
191
+ var _a, _b;
192
+ // don't use coalesce operator, since null is a valid example
193
+ const example1 = ((_a = acc.examples) === null || _a === void 0 ? void 0 : _a[0]) !== undefined ? acc.examples[0] : acc.example;
194
+ const example2 = ((_b = curr.examples) === null || _b === void 0 ? void 0 : _b[0]) !== undefined ? curr.examples[0] : curr.example;
195
+ if (example1 && example2 && typeof example1 === 'object' && typeof example2 === 'object') {
196
+ acc.example = Object.assign(Object.assign({}, example1), example2);
197
+ }
198
+ else {
199
+ // don't use coalesce operator, since null is a valid example
200
+ addKeyIfDefined('example', example2 !== undefined ? example2 : example1, acc);
201
+ }
202
+ }
203
+ export function combineProperties(acc, curr, componentSchemas, location) {
204
+ if (curr.properties) {
205
+ Object.entries(curr.properties)
206
+ .filter(([_, subschema]) => {
207
+ // dereference just for the readOnly/writeOnly check
208
+ if ('$ref' in subschema) {
209
+ const dereferencedSchema = dereference('schemas', subschema.$ref, componentSchemas);
210
+ if (!dereferencedSchema)
211
+ return true;
212
+ subschema = dereferencedSchema;
213
+ }
214
+ if (subschema.readOnly && location === 'request')
215
+ return false;
216
+ if (subschema.writeOnly && location === 'response')
217
+ return false;
218
+ return true;
219
+ })
220
+ .forEach(([property, subschema]) => {
221
+ var _a;
222
+ const properties = (_a = acc.properties) !== null && _a !== void 0 ? _a : {};
223
+ const currSchemaArr = properties[property];
224
+ if (currSchemaArr) {
225
+ currSchemaArr.allOf.push(subschema);
226
+ }
227
+ else {
228
+ properties[property] = { allOf: [subschema] };
229
+ }
230
+ acc.properties = properties;
231
+ });
232
+ }
233
+ }
234
+ export function combineDescription(acc, curr, schemas) {
235
+ var _a, _b;
236
+ if (((_a = acc.properties) === null || _a === void 0 ? void 0 : _a.type) && curr.discriminator && !acc.description) {
237
+ let name = undefined;
238
+ const allOf = (_b = acc.properties.type.allOf[0]) !== null && _b !== void 0 ? _b : {};
239
+ if ('const' in allOf && typeof allOf.const === 'string') {
240
+ name = allOf.const;
241
+ }
242
+ const description = recursivelyFindDescription(curr, name) ||
243
+ schemas.flatMap((schema) => recursivelyFindDescription(schema, name)).filter(Boolean)[0];
244
+ if (description) {
245
+ acc.description = description;
246
+ }
247
+ }
248
+ else if (acc.description &&
249
+ curr.description &&
250
+ !curr.discriminator &&
251
+ !acc.description.includes(curr.description)) {
252
+ acc.description = `${acc.description}\n${curr.description}`;
253
+ }
254
+ else if (!acc.description) {
255
+ copyKeyIfDefined('description', curr, acc);
256
+ }
257
+ }
258
+ export function combineAdditionalProperties(acc, curr) {
259
+ var _a;
260
+ if (curr.additionalProperties === false) {
261
+ acc.additionalProperties = false;
262
+ }
263
+ else if (acc.additionalProperties !== false &&
264
+ curr.additionalProperties &&
265
+ typeof curr.additionalProperties === 'object') {
266
+ const additionalProperties = (_a = acc.additionalProperties) !== null && _a !== void 0 ? _a : { allOf: [] };
267
+ additionalProperties.allOf.push(curr.additionalProperties);
268
+ acc.additionalProperties = additionalProperties;
269
+ }
270
+ }
271
+ export function discriminatorAndSchemaRefsMatch(schema) {
272
+ const discriminator = schema.discriminator;
273
+ if (discriminator === null || discriminator === void 0 ? void 0 : discriminator.mapping) {
274
+ const discriminatedRefs = Object.values(discriminator.mapping).map((ref) => ref);
275
+ const schemaRefs = [];
276
+ if ('allOf' in schema) {
277
+ if (Array.isArray(schema.allOf)) {
278
+ schema.allOf.forEach((ref) => {
279
+ if ('$ref' in ref) {
280
+ schemaRefs.push(ref.$ref);
281
+ }
282
+ });
283
+ }
284
+ }
285
+ if ('oneOf' in schema) {
286
+ if (Array.isArray(schema.oneOf)) {
287
+ schema.oneOf.forEach((ref) => {
288
+ if ('$ref' in ref) {
289
+ schemaRefs.push(ref.$ref);
290
+ }
291
+ });
292
+ }
293
+ }
294
+ if ('anyOf' in schema) {
295
+ if (Array.isArray(schema.anyOf)) {
296
+ schema.anyOf.forEach((ref) => {
297
+ if ('$ref' in ref) {
298
+ schemaRefs.push(ref.$ref);
299
+ }
300
+ });
301
+ }
302
+ }
303
+ const discriminatedRefsSet = new Set(discriminatedRefs);
304
+ const schemaRefsSet = new Set(schemaRefs);
305
+ return (discriminatedRefsSet.size === schemaRefsSet.size &&
306
+ [...discriminatedRefsSet].every((ref) => schemaRefsSet.has(ref)));
307
+ }
308
+ else {
309
+ return false;
310
+ }
311
+ }