@ditojs/server 2.53.0 → 2.53.1
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/package.json +2 -2
- package/src/schema/schema.js +85 -57
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/server",
|
|
3
|
-
"version": "2.53.
|
|
3
|
+
"version": "2.53.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Dito.js Server – Dito.js is a declarative and modern web framework, based on Objection.js, Koa.js and Vue.js",
|
|
6
6
|
"repository": "https://github.com/ditojs/dito/tree/master/packages/server",
|
|
@@ -90,5 +90,5 @@
|
|
|
90
90
|
"objection": "^3.1.5",
|
|
91
91
|
"typescript": "^5.8.3"
|
|
92
92
|
},
|
|
93
|
-
"gitHead": "
|
|
93
|
+
"gitHead": "542865f8e49144518b8c9ea1bc4521c0aa5456df"
|
|
94
94
|
}
|
package/src/schema/schema.js
CHANGED
|
@@ -10,24 +10,42 @@ function getSchemaCache(options) {
|
|
|
10
10
|
return (schemaCaches[key] ||= new WeakMap())
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function convertSchema(
|
|
13
|
+
export function convertSchema(
|
|
14
|
+
schema,
|
|
15
|
+
options = {},
|
|
16
|
+
parentEntry = null
|
|
17
|
+
) {
|
|
14
18
|
const original = schema
|
|
19
|
+
const isRoot = parentEntry === null
|
|
15
20
|
|
|
16
21
|
const schemaCache = getSchemaCache(options)
|
|
17
22
|
if (schemaCache.has(original)) {
|
|
18
|
-
const { schema, definitions } = schemaCache.get(original)
|
|
19
|
-
|
|
23
|
+
const { schema, definitions, parentEntries } = schemaCache.get(original)
|
|
24
|
+
parentEntries.push(parentEntry)
|
|
25
|
+
if (definitions) {
|
|
26
|
+
if (isRoot) {
|
|
27
|
+
return { ...schema, definitions }
|
|
28
|
+
} else {
|
|
29
|
+
mergeDefinitions(parentEntry.definitions, definitions)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
20
32
|
return schema
|
|
21
33
|
}
|
|
22
34
|
|
|
35
|
+
const entry = {
|
|
36
|
+
schema: null,
|
|
37
|
+
definitions: {},
|
|
38
|
+
parentEntries: parentEntry ? [parentEntry] : []
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// To prevent circular references, cache the entry before all conversion work.
|
|
42
|
+
schemaCache.set(original, entry)
|
|
43
|
+
|
|
23
44
|
let definitions = null
|
|
24
45
|
if (isArray(schema)) {
|
|
25
46
|
// Needed for allOf, anyOf, oneOf, not, items, see below:
|
|
26
|
-
schema = schema.map(
|
|
47
|
+
schema = schema.map(item => convertSchema(item, options, entry))
|
|
27
48
|
} else if (isObject(schema)) {
|
|
28
|
-
const isRoot = rootDefinitions === null
|
|
29
|
-
rootDefinitions ??= {}
|
|
30
|
-
|
|
31
49
|
// Create a shallow clone so we can modify and return:
|
|
32
50
|
// Also collect and propagate the definitions up to the root schema through
|
|
33
51
|
// `options.definitions`, as passed from `Model static get jsonSchema()`:
|
|
@@ -47,21 +65,13 @@ export function convertSchema(schema, options = {}, rootDefinitions = null) {
|
|
|
47
65
|
}
|
|
48
66
|
|
|
49
67
|
// Convert array items
|
|
50
|
-
schema.prefixItems &&= convertSchema(
|
|
51
|
-
|
|
52
|
-
options,
|
|
53
|
-
rootDefinitions
|
|
54
|
-
)
|
|
55
|
-
schema.items &&= convertSchema(
|
|
56
|
-
schema.items,
|
|
57
|
-
options,
|
|
58
|
-
rootDefinitions
|
|
59
|
-
)
|
|
68
|
+
schema.prefixItems &&= convertSchema(schema.prefixItems, options, entry)
|
|
69
|
+
schema.items &&= convertSchema(schema.items, options, entry)
|
|
60
70
|
|
|
61
71
|
// Handle nested allOf, anyOf, oneOf & co. fields
|
|
62
72
|
for (const key of ['allOf', 'anyOf', 'oneOf', 'not', '$extend']) {
|
|
63
73
|
if (key in schema) {
|
|
64
|
-
schema[key] = convertSchema(schema[key], options,
|
|
74
|
+
schema[key] = convertSchema(schema[key], options, entry)
|
|
65
75
|
}
|
|
66
76
|
}
|
|
67
77
|
|
|
@@ -115,14 +125,15 @@ export function convertSchema(schema, options = {}, rootDefinitions = null) {
|
|
|
115
125
|
schema.enum.push(null)
|
|
116
126
|
}
|
|
117
127
|
|
|
118
|
-
//
|
|
119
|
-
//
|
|
128
|
+
// Convert properties last. This is needed for circular references
|
|
129
|
+
// to work correctly, as the properties may reference the same schema
|
|
130
|
+
// that is being converted right now.
|
|
120
131
|
let hasConvertedProperties = false
|
|
121
132
|
if (schema.properties) {
|
|
122
133
|
const { properties, required } = convertProperties(
|
|
123
134
|
schema.properties,
|
|
124
135
|
options,
|
|
125
|
-
|
|
136
|
+
entry
|
|
126
137
|
)
|
|
127
138
|
schema.properties = properties
|
|
128
139
|
if (required.length > 0) {
|
|
@@ -135,7 +146,7 @@ export function convertSchema(schema, options = {}, rootDefinitions = null) {
|
|
|
135
146
|
const { properties } = convertProperties(
|
|
136
147
|
schema.patternProperties,
|
|
137
148
|
options,
|
|
138
|
-
|
|
149
|
+
entry
|
|
139
150
|
)
|
|
140
151
|
schema.patternProperties = properties
|
|
141
152
|
hasConvertedProperties = true
|
|
@@ -149,44 +160,45 @@ export function convertSchema(schema, options = {}, rootDefinitions = null) {
|
|
|
149
160
|
// explicitly set to `true`:
|
|
150
161
|
schema.unevaluatedProperties = false
|
|
151
162
|
}
|
|
152
|
-
|
|
153
|
-
if (isRoot && hasDefinitions(rootDefinitions)) {
|
|
154
|
-
schema.definitions = rootDefinitions
|
|
155
|
-
}
|
|
156
163
|
}
|
|
157
164
|
|
|
158
|
-
|
|
159
|
-
schemaCache.set(original, entry)
|
|
165
|
+
entry.schema = schema
|
|
160
166
|
|
|
161
|
-
//
|
|
162
|
-
//
|
|
167
|
+
// Only convert definitions once `entry.schema` is set, so that it works as
|
|
168
|
+
// expected with circular references.
|
|
163
169
|
if (definitions) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
170
|
+
mergeDefinitions(
|
|
171
|
+
entry.definitions,
|
|
172
|
+
convertDefinitions(definitions, options, entry)
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (Object.keys(entry.definitions).length > 0) {
|
|
177
|
+
// Propagate the definitions up the parent entry chains, that due to
|
|
178
|
+
// circular references may not be up to date yet.
|
|
179
|
+
mergeDefinitionsRecursively(entry, entry.definitions)
|
|
180
|
+
if (isRoot) {
|
|
181
|
+
schema.definitions = entry.definitions
|
|
182
|
+
}
|
|
167
183
|
}
|
|
168
184
|
|
|
169
185
|
return schema
|
|
170
186
|
}
|
|
171
187
|
|
|
172
|
-
function convertProperties(schemaProperties, options,
|
|
188
|
+
function convertProperties(schemaProperties, options, entry) {
|
|
173
189
|
const properties = {}
|
|
174
190
|
const required = []
|
|
175
191
|
for (const [key, property] of Object.entries(schemaProperties)) {
|
|
176
|
-
properties[key] = convertSchema(property, options,
|
|
192
|
+
properties[key] = convertSchema(property, options, entry)
|
|
177
193
|
if (property?.required) {
|
|
178
194
|
required.push(key)
|
|
179
195
|
}
|
|
180
196
|
}
|
|
181
|
-
return { properties, required
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function hasDefinitions(definitions) {
|
|
185
|
-
return definitions && Object.keys(definitions).length > 0
|
|
197
|
+
return { properties, required }
|
|
186
198
|
}
|
|
187
199
|
|
|
188
|
-
function convertDefinitions(definitions, options) {
|
|
189
|
-
|
|
200
|
+
function convertDefinitions(definitions, options, entry) {
|
|
201
|
+
let converted = null
|
|
190
202
|
for (const [key, schema] of Object.entries(definitions)) {
|
|
191
203
|
if (!key.startsWith('#')) {
|
|
192
204
|
throw new Error(
|
|
@@ -197,25 +209,41 @@ function convertDefinitions(definitions, options) {
|
|
|
197
209
|
}`
|
|
198
210
|
)
|
|
199
211
|
}
|
|
200
|
-
converted
|
|
212
|
+
converted ??= {}
|
|
213
|
+
converted[key] = convertSchema(schema, options, entry)
|
|
201
214
|
}
|
|
202
|
-
return
|
|
215
|
+
return converted
|
|
203
216
|
}
|
|
204
217
|
|
|
205
218
|
function mergeDefinitions(definitions, defs) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
220
|
+
const definition = definitions[key]
|
|
221
|
+
if (definition && !equals(definition, def)) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
`Duplicate nested definition for '${key}' with different schema: ${
|
|
224
|
+
JSON.stringify(def, null, 2)
|
|
225
|
+
}, ${
|
|
226
|
+
JSON.stringify(definition, null, 2)
|
|
227
|
+
}`
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
definitions[key] ??= def
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function mergeDefinitionsRecursively(
|
|
235
|
+
entry,
|
|
236
|
+
definitions,
|
|
237
|
+
visited = new WeakSet()
|
|
238
|
+
) {
|
|
239
|
+
if (!visited.has(entry)) {
|
|
240
|
+
visited.add(entry)
|
|
241
|
+
|
|
242
|
+
if (definitions !== entry.definitions) {
|
|
243
|
+
mergeDefinitions(entry.definitions, definitions)
|
|
244
|
+
}
|
|
245
|
+
for (const parentEntry of entry.parentEntries) {
|
|
246
|
+
mergeDefinitionsRecursively(parentEntry, definitions, visited)
|
|
219
247
|
}
|
|
220
248
|
}
|
|
221
249
|
}
|