@api-client/core 0.19.19 → 0.19.20
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/build/src/authorization/Utils.js +3 -3
- package/build/src/authorization/Utils.js.map +1 -1
- package/build/src/modeling/ApiModel.d.ts +16 -5
- package/build/src/modeling/ApiModel.d.ts.map +1 -1
- package/build/src/modeling/ApiModel.js +17 -2
- package/build/src/modeling/ApiModel.js.map +1 -1
- package/build/src/modeling/ApiValidation.d.ts.map +1 -1
- package/build/src/modeling/ApiValidation.js +2 -1
- package/build/src/modeling/ApiValidation.js.map +1 -1
- package/build/src/modeling/DomainProperty.d.ts +12 -0
- package/build/src/modeling/DomainProperty.d.ts.map +1 -1
- package/build/src/modeling/DomainProperty.js +23 -28
- package/build/src/modeling/DomainProperty.js.map +1 -1
- package/build/src/modeling/DomainSerialization.js +1 -1
- package/build/src/modeling/DomainSerialization.js.map +1 -1
- package/build/src/modeling/ExposedEntity.d.ts +15 -1
- package/build/src/modeling/ExposedEntity.d.ts.map +1 -1
- package/build/src/modeling/ExposedEntity.js +42 -4
- package/build/src/modeling/ExposedEntity.js.map +1 -1
- package/build/src/modeling/actions/Action.d.ts.map +1 -1
- package/build/src/modeling/actions/Action.js +1 -0
- package/build/src/modeling/actions/Action.js.map +1 -1
- package/build/src/modeling/actions/ListAction.d.ts +3 -17
- package/build/src/modeling/actions/ListAction.d.ts.map +1 -1
- package/build/src/modeling/actions/ListAction.js +18 -38
- package/build/src/modeling/actions/ListAction.js.map +1 -1
- package/build/src/modeling/actions/SearchAction.d.ts +4 -4
- package/build/src/modeling/actions/SearchAction.d.ts.map +1 -1
- package/build/src/modeling/actions/SearchAction.js +16 -13
- package/build/src/modeling/actions/SearchAction.js.map +1 -1
- package/build/src/modeling/generators/oas_312/OasGenerator.d.ts +32 -0
- package/build/src/modeling/generators/oas_312/OasGenerator.d.ts.map +1 -0
- package/build/src/modeling/generators/oas_312/OasGenerator.js +1452 -0
- package/build/src/modeling/generators/oas_312/OasGenerator.js.map +1 -0
- package/build/src/modeling/generators/oas_312/OasSchemaGenerator.d.ts +27 -0
- package/build/src/modeling/generators/oas_312/OasSchemaGenerator.d.ts.map +1 -0
- package/build/src/modeling/generators/oas_312/OasSchemaGenerator.js +295 -0
- package/build/src/modeling/generators/oas_312/OasSchemaGenerator.js.map +1 -0
- package/build/src/modeling/generators/oas_312/types.d.ts +1010 -0
- package/build/src/modeling/generators/oas_312/types.d.ts.map +1 -0
- package/build/src/modeling/generators/oas_312/types.js +2 -0
- package/build/src/modeling/generators/oas_312/types.js.map +1 -0
- package/build/src/modeling/generators/oas_320/OasGenerator.d.ts +16 -0
- package/build/src/modeling/generators/oas_320/OasGenerator.d.ts.map +1 -0
- package/build/src/modeling/generators/oas_320/OasGenerator.js +306 -0
- package/build/src/modeling/generators/oas_320/OasGenerator.js.map +1 -0
- package/build/src/modeling/generators/oas_320/OasSchemaGenerator.d.ts +25 -0
- package/build/src/modeling/generators/oas_320/OasSchemaGenerator.d.ts.map +1 -0
- package/build/src/modeling/generators/oas_320/OasSchemaGenerator.js +237 -0
- package/build/src/modeling/generators/oas_320/OasSchemaGenerator.js.map +1 -0
- package/build/src/modeling/generators/oas_320/types.d.ts +1219 -0
- package/build/src/modeling/generators/oas_320/types.d.ts.map +1 -0
- package/build/src/modeling/generators/oas_320/types.js +2 -0
- package/build/src/modeling/generators/oas_320/types.js.map +1 -0
- package/build/src/modeling/types.d.ts +50 -13
- package/build/src/modeling/types.d.ts.map +1 -1
- package/build/src/modeling/types.js.map +1 -1
- package/build/src/modeling/validation/api_model_rules.d.ts +1 -0
- package/build/src/modeling/validation/api_model_rules.d.ts.map +1 -1
- package/build/src/modeling/validation/api_model_rules.js +105 -29
- package/build/src/modeling/validation/api_model_rules.js.map +1 -1
- package/build/src/models/ProjectRequest.d.ts.map +1 -1
- package/build/src/models/ProjectRequest.js +0 -4
- package/build/src/models/ProjectRequest.js.map +1 -1
- package/build/src/models/transformers/ArcDexieTransformer.d.ts.map +1 -1
- package/build/src/models/transformers/ArcDexieTransformer.js +0 -4
- package/build/src/models/transformers/ArcDexieTransformer.js.map +1 -1
- package/build/src/models/transformers/ImportUtils.js +1 -1
- package/build/src/models/transformers/ImportUtils.js.map +1 -1
- package/build/src/models/transformers/PostmanBackupTransformer.d.ts.map +1 -1
- package/build/src/models/transformers/PostmanBackupTransformer.js +0 -4
- package/build/src/models/transformers/PostmanBackupTransformer.js.map +1 -1
- package/build/src/runtime/constants.d.ts +7 -0
- package/build/src/runtime/constants.d.ts.map +1 -0
- package/build/src/runtime/constants.js +8 -0
- package/build/src/runtime/constants.js.map +1 -0
- package/build/src/runtime/http-engine/ntlm/Des.d.ts.map +1 -1
- package/build/src/runtime/http-engine/ntlm/Des.js +1 -0
- package/build/src/runtime/http-engine/ntlm/Des.js.map +1 -1
- package/build/src/runtime/variables/EvalFunctions.d.ts.map +1 -1
- package/build/src/runtime/variables/EvalFunctions.js +0 -1
- package/build/src/runtime/variables/EvalFunctions.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/eslint.config.js +6 -0
- package/package.json +3 -1
- package/src/authorization/Utils.ts +3 -3
- package/src/modeling/ApiModel.ts +23 -8
- package/src/modeling/ApiValidation.ts +2 -0
- package/src/modeling/DomainProperty.ts +22 -18
- package/src/modeling/DomainSerialization.ts +1 -1
- package/src/modeling/ExposedEntity.ts +44 -4
- package/src/modeling/actions/Action.ts +1 -0
- package/src/modeling/actions/ListAction.ts +12 -30
- package/src/modeling/actions/SearchAction.ts +11 -8
- package/src/modeling/generators/oas_312/OasGenerator.ts +1685 -0
- package/src/modeling/generators/oas_312/OasSchemaGenerator.ts +322 -0
- package/src/modeling/generators/oas_312/types.ts +1052 -0
- package/src/modeling/generators/oas_320/OasGenerator.ts +359 -0
- package/src/modeling/generators/oas_320/OasSchemaGenerator.ts +255 -0
- package/src/modeling/generators/oas_320/types.ts +1259 -0
- package/src/modeling/types.ts +55 -22
- package/src/modeling/validation/api_model_rules.ts +103 -32
- package/src/models/ProjectRequest.ts +0 -4
- package/src/models/transformers/ArcDexieTransformer.ts +0 -4
- package/src/models/transformers/ImportUtils.ts +1 -1
- package/src/models/transformers/PostmanBackupTransformer.ts +0 -5
- package/src/runtime/constants.ts +9 -0
- package/src/runtime/http-engine/ntlm/Des.ts +1 -0
- package/src/runtime/variables/EvalFunctions.ts +0 -1
- package/tests/test-utils.ts +6 -2
- package/tests/unit/decorators/observed.spec.ts +8 -24
- package/tests/unit/decorators/observed_recursive.spec.ts +0 -1
- package/tests/unit/events/EventsTestHelpers.ts +0 -1
- package/tests/unit/events/events_polyfills.ts +0 -1
- package/tests/unit/legacy-transformers/DataTestHelper.ts +0 -2
- package/tests/unit/legacy-transformers/LegacyExportProcessor.spec.ts +0 -1
- package/tests/unit/modeling/actions/ListAction.spec.ts +9 -69
- package/tests/unit/modeling/actions/SearchAction.spec.ts +9 -35
- package/tests/unit/modeling/api_model.spec.ts +28 -0
- package/tests/unit/modeling/definitions/sku.spec.ts +0 -2
- package/tests/unit/modeling/domain_property.spec.ts +20 -1
- package/tests/unit/modeling/exposed_entity.spec.ts +71 -0
- package/tests/unit/modeling/generators/OasGenerator.spec.ts +302 -0
- package/tests/unit/modeling/validation/api_model_rules.spec.ts +113 -15
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import type { ReferenceObject, SchemaObject } from './types.js'
|
|
2
|
+
import { AssociationWebBindings, PropertyWebBindings } from '../../Bindings.js'
|
|
3
|
+
import type { DomainEntity } from '../../DomainEntity.js'
|
|
4
|
+
import type { DomainProperty } from '../../DomainProperty.js'
|
|
5
|
+
import { SemanticType } from '../../Semantics.js'
|
|
6
|
+
|
|
7
|
+
interface SemanticExtension {
|
|
8
|
+
'x-api-now-semantics'?: Record<string, unknown>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getSemanticName(id: string): string {
|
|
12
|
+
return id.split('#')[1]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class OasSchemaGenerator {
|
|
16
|
+
private memorySchemas: Record<string, SchemaObject> = {}
|
|
17
|
+
private memoryNames: Record<string, string> = {}
|
|
18
|
+
|
|
19
|
+
#hasFileUpload = false
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A flag that determines whether any of the properties has the `FileURL` or `ImageURL` semantic.
|
|
23
|
+
*/
|
|
24
|
+
get hasFileUpload(): boolean {
|
|
25
|
+
return this.#hasFileUpload
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Retrieves the dictionary of all processed OAS JSON schemas.
|
|
30
|
+
*/
|
|
31
|
+
public getSchemas(): Record<string, SchemaObject> {
|
|
32
|
+
const result: Record<string, SchemaObject> = {}
|
|
33
|
+
for (const [key, value] of Object.entries(this.memorySchemas)) {
|
|
34
|
+
result[this.memoryNames[key]] = value
|
|
35
|
+
}
|
|
36
|
+
return result
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Generates schemas recursively for an entity and returns the $ref pointing to the root representation.
|
|
41
|
+
* @param entity
|
|
42
|
+
*/
|
|
43
|
+
public generateRootRef(entity: DomainEntity): ReferenceObject {
|
|
44
|
+
this.generateEntity(entity)
|
|
45
|
+
return { $ref: `#/components/schemas/${this.generateSchemaKey(entity)}` }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Generates a schema key for an entity.
|
|
50
|
+
*/
|
|
51
|
+
public generateSchemaKey(entity: DomainEntity): string {
|
|
52
|
+
return entity.info.name || 'entity ' + entity.key
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private generateEntity(entity: DomainEntity): void {
|
|
56
|
+
if (this.memorySchemas[entity.key]) {
|
|
57
|
+
return // Already processed or processing
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Preemptively assign to avoid infinite recursion over bidirectional associations
|
|
61
|
+
const schema: SchemaObject & SemanticExtension = {
|
|
62
|
+
type: 'object',
|
|
63
|
+
properties: {},
|
|
64
|
+
required: [],
|
|
65
|
+
}
|
|
66
|
+
this.memorySchemas[entity.key] = schema
|
|
67
|
+
const schemaKey = this.generateSchemaKey(entity)
|
|
68
|
+
this.memoryNames[entity.key] = schemaKey
|
|
69
|
+
if (entity.info.displayName) {
|
|
70
|
+
schema.title = entity.info.displayName
|
|
71
|
+
}
|
|
72
|
+
if (entity.info.description) {
|
|
73
|
+
schema.description = entity.info.description
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (entity.semantics.length > 0) {
|
|
77
|
+
schema['x-api-now-semantics'] = {}
|
|
78
|
+
for (const semantic of entity.semantics) {
|
|
79
|
+
schema['x-api-now-semantics'][getSemanticName(semantic.id)] = semantic.config ? semantic.config : {}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const required: string[] = []
|
|
84
|
+
|
|
85
|
+
for (const prop of entity.properties) {
|
|
86
|
+
if (prop.required && !prop.readOnly) {
|
|
87
|
+
required.push(prop.info.name || prop.key)
|
|
88
|
+
}
|
|
89
|
+
if (!schema.properties) {
|
|
90
|
+
schema.properties = {}
|
|
91
|
+
}
|
|
92
|
+
const webBindings = prop.readBinding('web') as PropertyWebBindings | undefined
|
|
93
|
+
if (webBindings?.hidden) {
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
schema.properties[prop.info.name || prop.key] = this.mapPropertyBase(prop, webBindings)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (const assoc of entity.associations) {
|
|
100
|
+
const bindings = assoc.readBinding('web') as AssociationWebBindings | undefined
|
|
101
|
+
if (bindings?.hidden) {
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const targets = Array.from(assoc.listTargets())
|
|
106
|
+
if (targets.length === 0) continue
|
|
107
|
+
|
|
108
|
+
const linked = assoc.schema?.linked === true
|
|
109
|
+
const targetRefs: (SchemaObject | ReferenceObject)[] = []
|
|
110
|
+
|
|
111
|
+
for (const targetEntity of targets) {
|
|
112
|
+
if (linked) {
|
|
113
|
+
// When an entity is linked then we treat it as a regular property, which value is a key to
|
|
114
|
+
// the target entity. The consuming application has to construct the endpoint manually.
|
|
115
|
+
const targetName = targetEntity.info.displayName || targetEntity.info.name || targetEntity.key
|
|
116
|
+
targetRefs.push({
|
|
117
|
+
type: 'string',
|
|
118
|
+
description: `The ID of the linked ${targetName}.`,
|
|
119
|
+
})
|
|
120
|
+
} else {
|
|
121
|
+
// If not linked, embed the resource as a reference to the schema.
|
|
122
|
+
if (targetEntity !== entity) {
|
|
123
|
+
this.generateEntity(targetEntity)
|
|
124
|
+
}
|
|
125
|
+
targetRefs.push({ $ref: `#/components/schemas/${this.generateSchemaKey(targetEntity)}` })
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let assocSchema: SchemaObject | ReferenceObject
|
|
130
|
+
if (targetRefs.length > 1) {
|
|
131
|
+
const unionType = assoc.schema?.unionType || 'anyOf'
|
|
132
|
+
if (unionType === 'oneOf') {
|
|
133
|
+
assocSchema = { oneOf: targetRefs }
|
|
134
|
+
} else if (unionType === 'allOf') {
|
|
135
|
+
assocSchema = { allOf: targetRefs }
|
|
136
|
+
} else {
|
|
137
|
+
assocSchema = { anyOf: targetRefs }
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
assocSchema = targetRefs[0]
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const propName = assoc.info.name || assoc.key
|
|
144
|
+
if (!schema.properties) {
|
|
145
|
+
schema.properties = {}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (assoc.multiple) {
|
|
149
|
+
schema.properties[propName] = {
|
|
150
|
+
type: 'array',
|
|
151
|
+
items: assocSchema,
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
schema.properties[propName] = assocSchema
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (required.length > 0) {
|
|
159
|
+
schema.required = required
|
|
160
|
+
} else {
|
|
161
|
+
delete schema.required
|
|
162
|
+
}
|
|
163
|
+
const example = entity.toExample('application/json', {
|
|
164
|
+
// renderExamples: true,
|
|
165
|
+
renderMocked: false,
|
|
166
|
+
renderOptional: true,
|
|
167
|
+
})
|
|
168
|
+
if (example) {
|
|
169
|
+
if (typeof example === 'string') {
|
|
170
|
+
try {
|
|
171
|
+
schema.example = JSON.parse(example)
|
|
172
|
+
} catch {
|
|
173
|
+
schema.example = example
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
schema.example = example
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private mapPropertyBase(prop: DomainProperty, webBindings?: PropertyWebBindings): SchemaObject | ReferenceObject {
|
|
182
|
+
const base: SchemaObject & SemanticExtension = {}
|
|
183
|
+
|
|
184
|
+
if (prop.readOnly) {
|
|
185
|
+
base.readOnly = true
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (prop.writeOnly) {
|
|
189
|
+
base.writeOnly = true
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (prop.deprecated) {
|
|
193
|
+
base.deprecated = true
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (prop.schema) {
|
|
197
|
+
if (prop.schema.minimum !== undefined) {
|
|
198
|
+
if (prop.schema.exclusiveMinimum) {
|
|
199
|
+
base.exclusiveMinimum = prop.schema.minimum
|
|
200
|
+
} else {
|
|
201
|
+
base.minimum = prop.schema.minimum
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (prop.schema.maximum !== undefined) {
|
|
205
|
+
if (prop.schema.exclusiveMaximum) {
|
|
206
|
+
base.exclusiveMaximum = prop.schema.maximum
|
|
207
|
+
} else {
|
|
208
|
+
base.maximum = prop.schema.maximum
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (prop.schema.pattern) {
|
|
212
|
+
base.pattern = prop.schema.pattern
|
|
213
|
+
}
|
|
214
|
+
if (prop.schema.enum) {
|
|
215
|
+
base.enum = [...prop.schema.enum]
|
|
216
|
+
}
|
|
217
|
+
if (prop.schema.defaultValue?.value !== undefined) {
|
|
218
|
+
base.default = prop.schema.defaultValue.value
|
|
219
|
+
}
|
|
220
|
+
if (prop.schema.examples && prop.schema.examples.length > 0) {
|
|
221
|
+
// AMF incorrectly ignores `examples` property in JSON Schema in OAS 3.1 version.
|
|
222
|
+
// A temporary workaround is to set the `example` property instead of `examples`.
|
|
223
|
+
// const examples: ExampleObject[] = []
|
|
224
|
+
// for (const example of prop.schema.examples) {
|
|
225
|
+
// const value: ExampleObject = {
|
|
226
|
+
// value: example,
|
|
227
|
+
// }
|
|
228
|
+
// examples.push(value)
|
|
229
|
+
// }
|
|
230
|
+
// base.examples = examples
|
|
231
|
+
base.example = prop.schema.examples[0]
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (prop.info.displayName) {
|
|
236
|
+
base.title = prop.info.displayName
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (prop.info.description) {
|
|
240
|
+
base.description = prop.info.description
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (prop.hasSemantic(SemanticType.Password)) {
|
|
244
|
+
base.format = 'password'
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (webBindings?.xml) {
|
|
248
|
+
base.xml = { ...webBindings.xml }
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (prop.semantics.length > 0) {
|
|
252
|
+
base['x-api-now-semantics'] = {}
|
|
253
|
+
for (const semantic of prop.semantics) {
|
|
254
|
+
if (!this.#hasFileUpload && (semantic.id === SemanticType.FileURL || semantic.id === SemanticType.ImageURL)) {
|
|
255
|
+
this.#hasFileUpload = true
|
|
256
|
+
}
|
|
257
|
+
base['x-api-now-semantics'][getSemanticName(semantic.id)] = semantic.config ? semantic.config : {}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
switch (prop.type) {
|
|
262
|
+
case 'string':
|
|
263
|
+
base.type = 'string'
|
|
264
|
+
break
|
|
265
|
+
case 'number':
|
|
266
|
+
if (webBindings?.format === 'int32' || webBindings?.format === 'int64') {
|
|
267
|
+
base.type = 'integer'
|
|
268
|
+
} else {
|
|
269
|
+
base.type = 'number'
|
|
270
|
+
}
|
|
271
|
+
if (prop.schema?.multipleOf !== undefined) {
|
|
272
|
+
base.multipleOf = prop.schema.multipleOf
|
|
273
|
+
}
|
|
274
|
+
break
|
|
275
|
+
case 'boolean':
|
|
276
|
+
base.type = 'boolean'
|
|
277
|
+
break
|
|
278
|
+
case 'date':
|
|
279
|
+
base.type = 'string'
|
|
280
|
+
base.format = 'date'
|
|
281
|
+
break
|
|
282
|
+
case 'datetime':
|
|
283
|
+
base.type = 'string'
|
|
284
|
+
base.format = 'date-time'
|
|
285
|
+
break
|
|
286
|
+
case 'time':
|
|
287
|
+
base.type = 'string'
|
|
288
|
+
base.format = 'time'
|
|
289
|
+
break
|
|
290
|
+
case 'binary':
|
|
291
|
+
base.type = 'string'
|
|
292
|
+
if (webBindings?.format) {
|
|
293
|
+
base.format = webBindings.format
|
|
294
|
+
} else {
|
|
295
|
+
base.format = 'binary'
|
|
296
|
+
}
|
|
297
|
+
if (webBindings?.fileTypes && webBindings.fileTypes.length > 0) {
|
|
298
|
+
const typesStr = webBindings.fileTypes.join(', ')
|
|
299
|
+
// Standard JSON Schema keyword for media wrapping (single value string usually,
|
|
300
|
+
// but some tools handle comma separated)
|
|
301
|
+
base.contentMediaType = webBindings.fileTypes.length === 1 ? webBindings.fileTypes[0] : typesStr
|
|
302
|
+
// Vendor extension for tools supporting multiple explicit arrays
|
|
303
|
+
// ;(base as any)['x-file-types'] = webBindings.fileTypes
|
|
304
|
+
// Append to description so viewers can always see the requirements natively
|
|
305
|
+
const typesDesc = `**Allowed file types:** ${typesStr}`
|
|
306
|
+
base.description = base.description ? `${base.description}\n\n${typesDesc}` : typesDesc
|
|
307
|
+
}
|
|
308
|
+
break
|
|
309
|
+
default:
|
|
310
|
+
base.type = 'string' // fallback
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (prop.multiple) {
|
|
314
|
+
return {
|
|
315
|
+
type: 'array',
|
|
316
|
+
items: base,
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return base
|
|
321
|
+
}
|
|
322
|
+
}
|