-
Notifications
You must be signed in to change notification settings - Fork 12k
/
transforms.ts
106 lines (90 loc) · 2.92 KB
/
transforms.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { JsonObject, JsonValue, isJsonArray, isJsonObject } from '../utils';
import { JsonPointer } from './interface';
import { JsonSchema } from './schema';
import { getTypesOfSchema } from './utility';
export function addUndefinedDefaults(
value: JsonValue,
_pointer: JsonPointer,
schema?: JsonSchema,
): JsonValue {
if (typeof schema === 'boolean' || schema === undefined) {
return value;
}
value ??= schema.default;
const types = getTypesOfSchema(schema);
if (types.size === 0) {
return value;
}
let type;
if (types.size === 1) {
// only one potential type
type = Array.from(types)[0];
} else if (types.size === 2 && types.has('array') && types.has('object')) {
// need to create one of them and array is simpler
type = 'array';
} else if (schema.properties && types.has('object')) {
// assume object
type = 'object';
} else if (schema.items && types.has('array')) {
// assume array
type = 'array';
} else {
// anything else needs to be checked by the consumer anyway
return value;
}
if (type === 'array') {
return value == undefined ? [] : value;
}
if (type === 'object') {
let newValue;
if (value == undefined) {
newValue = {} as JsonObject;
} else if (isJsonObject(value)) {
newValue = value;
} else {
return value;
}
if (!isJsonObject(schema.properties)) {
return newValue;
}
for (const [propName, schemaObject] of Object.entries(schema.properties)) {
if (propName === '$schema' || !isJsonObject(schemaObject)) {
continue;
}
const value = newValue[propName];
if (value === undefined) {
newValue[propName] = schemaObject.default;
} else if (isJsonObject(value)) {
// Basic support for oneOf and anyOf.
const propertySchemas = schemaObject.oneOf || schemaObject.anyOf;
const allProperties = Object.keys(value);
// Locate a schema which declares all the properties that the object contains.
const adjustedSchema =
isJsonArray(propertySchemas) &&
propertySchemas.find((s) => {
if (!isJsonObject(s)) {
return false;
}
const schemaType = getTypesOfSchema(s);
if (schemaType.size === 1 && schemaType.has('object') && isJsonObject(s.properties)) {
const properties = Object.keys(s.properties);
return allProperties.every((key) => properties.includes(key));
}
return false;
});
if (adjustedSchema && isJsonObject(adjustedSchema)) {
newValue[propName] = addUndefinedDefaults(value, _pointer, adjustedSchema);
}
}
}
return newValue;
}
return value;
}