@naturalcycles/js-lib 15.46.0 → 15.47.0
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/dist/http/fetcher.d.ts +1 -1
- package/dist/http/fetcher.js +1 -1
- package/dist/promise/pProps.js +1 -1
- package/dist/promise/pTimeout.js +1 -1
- package/dist/semver.js +1 -0
- package/dist/web.d.ts +1 -1
- package/dist/web.js +1 -1
- package/package.json +3 -4
- package/readme.md +0 -8
- package/src/http/fetcher.ts +1 -1
- package/src/promise/pProps.ts +1 -1
- package/src/promise/pTimeout.ts +1 -1
- package/src/semver.ts +1 -0
- package/src/types.ts +4 -4
- package/src/web.ts +1 -1
- package/src/zod/zod.shared.schemas.ts +1 -1
- package/dist/json-schema/from-data/generateJsonSchemaFromData.d.ts +0 -8
- package/dist/json-schema/from-data/generateJsonSchemaFromData.js +0 -87
- package/dist/json-schema/index.d.ts +0 -5
- package/dist/json-schema/index.js +0 -5
- package/dist/json-schema/jsonSchema.cnst.d.ts +0 -2
- package/dist/json-schema/jsonSchema.cnst.js +0 -38
- package/dist/json-schema/jsonSchema.model.d.ts +0 -121
- package/dist/json-schema/jsonSchema.model.js +0 -1
- package/dist/json-schema/jsonSchema.util.d.ts +0 -8
- package/dist/json-schema/jsonSchema.util.js +0 -27
- package/dist/json-schema/jsonSchemaBuilder.d.ts +0 -159
- package/dist/json-schema/jsonSchemaBuilder.js +0 -412
- package/dist/json-schema/jsonSchemas.d.ts +0 -2
- package/dist/json-schema/jsonSchemas.js +0 -6
- package/src/json-schema/from-data/generateJsonSchemaFromData.ts +0 -121
- package/src/json-schema/index.ts +0 -5
- package/src/json-schema/jsonSchema.cnst.ts +0 -52
- package/src/json-schema/jsonSchema.model.ts +0 -172
- package/src/json-schema/jsonSchema.util.ts +0 -36
- package/src/json-schema/jsonSchemaBuilder.ts +0 -590
- package/src/json-schema/jsonSchemas.ts +0 -8
|
@@ -1,590 +0,0 @@
|
|
|
1
|
-
import { _uniq } from '../array/array.util.js'
|
|
2
|
-
import { _numberEnumValues, _stringEnumValues, getEnumType } from '../enum.util.js'
|
|
3
|
-
import { _assert } from '../error/assert.js'
|
|
4
|
-
import { _deepCopy } from '../object/object.util.js'
|
|
5
|
-
import { _sortObject } from '../object/sortObject.js'
|
|
6
|
-
import {
|
|
7
|
-
type AnyObject,
|
|
8
|
-
type BaseDBEntity,
|
|
9
|
-
type IsoDate,
|
|
10
|
-
type IsoDateTime,
|
|
11
|
-
JWT_REGEX,
|
|
12
|
-
type NumberEnum,
|
|
13
|
-
type StringEnum,
|
|
14
|
-
type UnixTimestamp,
|
|
15
|
-
type UnixTimestampMillis,
|
|
16
|
-
} from '../types.js'
|
|
17
|
-
import { JSON_SCHEMA_ORDER } from './jsonSchema.cnst.js'
|
|
18
|
-
import type {
|
|
19
|
-
JsonSchema,
|
|
20
|
-
JsonSchemaAllOf,
|
|
21
|
-
JsonSchemaAny,
|
|
22
|
-
JsonSchemaArray,
|
|
23
|
-
JsonSchemaBoolean,
|
|
24
|
-
JsonSchemaConst,
|
|
25
|
-
JsonSchemaEnum,
|
|
26
|
-
JsonSchemaNull,
|
|
27
|
-
JsonSchemaNumber,
|
|
28
|
-
JsonSchemaObject,
|
|
29
|
-
JsonSchemaOneOf,
|
|
30
|
-
JsonSchemaRef,
|
|
31
|
-
JsonSchemaString,
|
|
32
|
-
JsonSchemaTuple,
|
|
33
|
-
} from './jsonSchema.model.js'
|
|
34
|
-
import { mergeJsonSchemaObjects } from './jsonSchema.util.js'
|
|
35
|
-
|
|
36
|
-
/* eslint-disable id-denylist, @typescript-eslint/explicit-module-boundary-types */
|
|
37
|
-
|
|
38
|
-
export interface JsonSchemaBuilder<T = unknown> {
|
|
39
|
-
build: () => JsonSchema<T>
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Fluent (chainable) API to manually create Json Schemas.
|
|
44
|
-
* Inspired by Joi and Zod.
|
|
45
|
-
*/
|
|
46
|
-
export const j = {
|
|
47
|
-
any<T = unknown>() {
|
|
48
|
-
return new JsonSchemaAnyBuilder<T, JsonSchemaAny<T>>({})
|
|
49
|
-
},
|
|
50
|
-
const<T extends string | number | boolean | null>(value: T) {
|
|
51
|
-
return new JsonSchemaAnyBuilder<T, JsonSchemaConst<T>>({
|
|
52
|
-
const: value,
|
|
53
|
-
})
|
|
54
|
-
},
|
|
55
|
-
null() {
|
|
56
|
-
return new JsonSchemaAnyBuilder<null, JsonSchemaNull>({
|
|
57
|
-
type: 'null',
|
|
58
|
-
})
|
|
59
|
-
},
|
|
60
|
-
ref<T = unknown>($ref: string) {
|
|
61
|
-
return new JsonSchemaAnyBuilder<T, JsonSchemaRef<T>>({
|
|
62
|
-
$ref,
|
|
63
|
-
})
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
enum<const T extends readonly (string | number | boolean | null)[] | StringEnum | NumberEnum>(
|
|
67
|
-
input: T,
|
|
68
|
-
) {
|
|
69
|
-
let enumValues: readonly (string | number | boolean | null)[] | undefined
|
|
70
|
-
|
|
71
|
-
if (Array.isArray(input)) {
|
|
72
|
-
enumValues = input
|
|
73
|
-
} else if (typeof input === 'object') {
|
|
74
|
-
const enumType = getEnumType(input)
|
|
75
|
-
if (enumType === 'NumberEnum') {
|
|
76
|
-
enumValues = _numberEnumValues(input as NumberEnum)
|
|
77
|
-
} else if (enumType === 'StringEnum') {
|
|
78
|
-
enumValues = _stringEnumValues(input as StringEnum)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
_assert(enumValues, 'Unsupported enum input')
|
|
83
|
-
|
|
84
|
-
return new JsonSchemaAnyBuilder<
|
|
85
|
-
T extends readonly (infer U)[]
|
|
86
|
-
? U
|
|
87
|
-
: T extends StringEnum
|
|
88
|
-
? T[keyof T]
|
|
89
|
-
: T extends NumberEnum
|
|
90
|
-
? T[keyof T]
|
|
91
|
-
: never,
|
|
92
|
-
JsonSchemaEnum<any>
|
|
93
|
-
>({
|
|
94
|
-
enum: enumValues as any[],
|
|
95
|
-
})
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
boolean() {
|
|
99
|
-
return new JsonSchemaAnyBuilder<boolean, JsonSchemaBoolean>({
|
|
100
|
-
type: 'boolean',
|
|
101
|
-
})
|
|
102
|
-
},
|
|
103
|
-
buffer() {
|
|
104
|
-
return new JsonSchemaAnyBuilder<Buffer, JsonSchemaAny<Buffer>>({ instanceof: 'Buffer' })
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
// number types
|
|
108
|
-
number<T extends number = number>() {
|
|
109
|
-
return new JsonSchemaNumberBuilder<T>()
|
|
110
|
-
},
|
|
111
|
-
integer<T extends number = number>() {
|
|
112
|
-
return new JsonSchemaNumberBuilder<T>().integer()
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
// string types
|
|
116
|
-
string<T extends string = string>() {
|
|
117
|
-
return new JsonSchemaStringBuilder<T>()
|
|
118
|
-
},
|
|
119
|
-
|
|
120
|
-
// complex types
|
|
121
|
-
object,
|
|
122
|
-
dbEntity<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: P) {
|
|
123
|
-
return j
|
|
124
|
-
.object<BaseDBEntity>({
|
|
125
|
-
id: j.string(),
|
|
126
|
-
created: j.integer().unixTimestamp2000(),
|
|
127
|
-
updated: j.integer().unixTimestamp2000(),
|
|
128
|
-
})
|
|
129
|
-
.extend(j.object(props)) as JsonSchemaObjectBuilder<
|
|
130
|
-
BaseDBEntity & {
|
|
131
|
-
[K in keyof P]: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never
|
|
132
|
-
}
|
|
133
|
-
>
|
|
134
|
-
},
|
|
135
|
-
|
|
136
|
-
rootObject<T extends AnyObject>(props: {
|
|
137
|
-
[K in keyof T]: JsonSchemaAnyBuilder<T[K]>
|
|
138
|
-
}) {
|
|
139
|
-
return new JsonSchemaObjectBuilder<T>().addProperties(props).$schemaDraft7()
|
|
140
|
-
},
|
|
141
|
-
array<T extends JsonSchemaAnyBuilder<any>>(itemSchema: T) {
|
|
142
|
-
return new JsonSchemaArrayBuilder<T['infer']>(itemSchema)
|
|
143
|
-
},
|
|
144
|
-
tuple<T extends any[] = unknown[]>(items: JsonSchemaAnyBuilder[]) {
|
|
145
|
-
return new JsonSchemaTupleBuilder<T>(items)
|
|
146
|
-
},
|
|
147
|
-
oneOf<Builders extends JsonSchemaAnyBuilder<any, any, any>[]>(
|
|
148
|
-
items: [...Builders],
|
|
149
|
-
): JsonSchemaAnyBuilder<
|
|
150
|
-
Builders[number] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never,
|
|
151
|
-
JsonSchemaOneOf<Builders[number] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never>
|
|
152
|
-
> {
|
|
153
|
-
return new JsonSchemaAnyBuilder({
|
|
154
|
-
oneOf: items.map(b => b.build()),
|
|
155
|
-
}) as any
|
|
156
|
-
},
|
|
157
|
-
allOf<T = unknown>(items: JsonSchemaAnyBuilder[]) {
|
|
158
|
-
return new JsonSchemaAnyBuilder<T, JsonSchemaAllOf<T>>({
|
|
159
|
-
allOf: items.map(b => b.build()),
|
|
160
|
-
})
|
|
161
|
-
},
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export class JsonSchemaAnyBuilder<
|
|
165
|
-
T = unknown,
|
|
166
|
-
SCHEMA_TYPE extends JsonSchema<T> = JsonSchema<T>,
|
|
167
|
-
Opt extends boolean = false,
|
|
168
|
-
> implements JsonSchemaBuilder<T>
|
|
169
|
-
{
|
|
170
|
-
constructor(protected schema: SCHEMA_TYPE) {}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Used in ObjectBuilder to access schema.optionalProperty
|
|
174
|
-
*/
|
|
175
|
-
getSchema(): SCHEMA_TYPE {
|
|
176
|
-
return this.schema
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
$schema($schema: string): this {
|
|
180
|
-
Object.assign(this.schema, { $schema })
|
|
181
|
-
return this
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
$schemaDraft7(): this {
|
|
185
|
-
this.$schema('http://json-schema.org/draft-07/schema#')
|
|
186
|
-
return this
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
$id($id: string): this {
|
|
190
|
-
Object.assign(this.schema, { $id })
|
|
191
|
-
return this
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
title(title: string): this {
|
|
195
|
-
Object.assign(this.schema, { title })
|
|
196
|
-
return this
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
description(description: string): this {
|
|
200
|
-
Object.assign(this.schema, { description })
|
|
201
|
-
return this
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
deprecated(deprecated = true): this {
|
|
205
|
-
Object.assign(this.schema, { deprecated })
|
|
206
|
-
return this
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
type(type: string): this {
|
|
210
|
-
Object.assign(this.schema, { type })
|
|
211
|
-
return this
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
default(v: any): this {
|
|
215
|
-
Object.assign(this.schema, { default: v })
|
|
216
|
-
return this
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
instanceof(of: string): this {
|
|
220
|
-
Object.assign(this.schema, { type: 'object', instanceof: of })
|
|
221
|
-
return this
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>
|
|
225
|
-
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>
|
|
226
|
-
optional(
|
|
227
|
-
optional: false,
|
|
228
|
-
): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined>>, false>
|
|
229
|
-
optional(optional = true): JsonSchemaAnyBuilder<any, JsonSchema<any>, false> {
|
|
230
|
-
if (optional) {
|
|
231
|
-
this.schema.optionalField = true
|
|
232
|
-
} else {
|
|
233
|
-
this.schema.optionalField = undefined
|
|
234
|
-
}
|
|
235
|
-
return this
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
nullable(): JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt> {
|
|
239
|
-
return new JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt>({
|
|
240
|
-
anyOf: [this.build(), { type: 'null' }],
|
|
241
|
-
})
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Produces a "clean schema object" without methods.
|
|
246
|
-
* Same as if it would be JSON.stringified.
|
|
247
|
-
*/
|
|
248
|
-
build(): SCHEMA_TYPE {
|
|
249
|
-
return _sortObject(JSON.parse(JSON.stringify(this.schema)), JSON_SCHEMA_ORDER)
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt> {
|
|
253
|
-
return new JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt>(_deepCopy(this.schema))
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* @experimental
|
|
258
|
-
*/
|
|
259
|
-
infer!: T
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export class JsonSchemaNumberBuilder<
|
|
263
|
-
T extends number = number,
|
|
264
|
-
Opt extends boolean = false,
|
|
265
|
-
> extends JsonSchemaAnyBuilder<T, JsonSchemaNumber<T>, Opt> {
|
|
266
|
-
constructor() {
|
|
267
|
-
super({
|
|
268
|
-
type: 'number',
|
|
269
|
-
})
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
integer(): this {
|
|
273
|
-
Object.assign(this.schema, { type: 'integer' })
|
|
274
|
-
return this
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
multipleOf(multipleOf: number): this {
|
|
278
|
-
Object.assign(this.schema, { multipleOf })
|
|
279
|
-
return this
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
min(minimum: number): this {
|
|
283
|
-
Object.assign(this.schema, { minimum })
|
|
284
|
-
return this
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
exclusiveMin(exclusiveMinimum: number): this {
|
|
288
|
-
Object.assign(this.schema, { exclusiveMinimum })
|
|
289
|
-
return this
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
max(maximum: number): this {
|
|
293
|
-
Object.assign(this.schema, { maximum })
|
|
294
|
-
return this
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
exclusiveMax(exclusiveMaximum: number): this {
|
|
298
|
-
Object.assign(this.schema, { exclusiveMaximum })
|
|
299
|
-
return this
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Both ranges are inclusive.
|
|
304
|
-
*/
|
|
305
|
-
range(minimum: number, maximum: number): this {
|
|
306
|
-
Object.assign(this.schema, { minimum, maximum })
|
|
307
|
-
return this
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
format(format: string): this {
|
|
311
|
-
Object.assign(this.schema, { format })
|
|
312
|
-
return this
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
int32 = (): this => this.format('int32')
|
|
316
|
-
int64 = (): this => this.format('int64')
|
|
317
|
-
float = (): this => this.format('float')
|
|
318
|
-
double = (): this => this.format('double')
|
|
319
|
-
|
|
320
|
-
unixTimestamp = (): JsonSchemaNumberBuilder<UnixTimestamp> =>
|
|
321
|
-
this.integer().branded<UnixTimestamp>().format('unixTimestamp').description('UnixTimestamp')
|
|
322
|
-
|
|
323
|
-
unixTimestamp2000 = (): JsonSchemaNumberBuilder<UnixTimestamp> =>
|
|
324
|
-
this.integer()
|
|
325
|
-
.branded<UnixTimestamp>()
|
|
326
|
-
.format('unixTimestamp2000')
|
|
327
|
-
.description('UnixTimestamp2000')
|
|
328
|
-
|
|
329
|
-
unixTimestampMillis = (): JsonSchemaNumberBuilder<UnixTimestampMillis> =>
|
|
330
|
-
this.integer()
|
|
331
|
-
.branded<UnixTimestampMillis>()
|
|
332
|
-
.format('unixTimestampMillis')
|
|
333
|
-
.description('UnixTimestampMillis')
|
|
334
|
-
|
|
335
|
-
unixTimestampMillis2000 = (): JsonSchemaNumberBuilder<UnixTimestampMillis> =>
|
|
336
|
-
this.integer()
|
|
337
|
-
.branded<UnixTimestampMillis>()
|
|
338
|
-
.format('unixTimestampMillis2000')
|
|
339
|
-
.description('UnixTimestampMillis2000')
|
|
340
|
-
|
|
341
|
-
utcOffset = (): this => this.format('utcOffset')
|
|
342
|
-
utcOffsetHours = (): this => this.format('utcOffsetHours')
|
|
343
|
-
|
|
344
|
-
branded<B extends number>(): JsonSchemaNumberBuilder<B> {
|
|
345
|
-
return this as unknown as JsonSchemaNumberBuilder<B>
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
export class JsonSchemaStringBuilder<
|
|
350
|
-
T extends string = string,
|
|
351
|
-
Opt extends boolean = false,
|
|
352
|
-
> extends JsonSchemaAnyBuilder<T, JsonSchemaString<T>, Opt> {
|
|
353
|
-
constructor() {
|
|
354
|
-
super({
|
|
355
|
-
type: 'string',
|
|
356
|
-
})
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
regex(pattern: RegExp): this {
|
|
360
|
-
return this.pattern(pattern.source)
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
pattern(pattern: string): this {
|
|
364
|
-
Object.assign(this.schema, { pattern })
|
|
365
|
-
return this
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
min(minLength: number): this {
|
|
369
|
-
Object.assign(this.schema, { minLength })
|
|
370
|
-
return this
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
max(maxLength: number): this {
|
|
374
|
-
Object.assign(this.schema, { maxLength })
|
|
375
|
-
return this
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
length(minLength: number, maxLength: number): this {
|
|
379
|
-
Object.assign(this.schema, { minLength, maxLength })
|
|
380
|
-
return this
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
format(format: string): this {
|
|
384
|
-
Object.assign(this.schema, { format })
|
|
385
|
-
return this
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
email = (): this => this.format('email')
|
|
389
|
-
url = (): this => this.format('url')
|
|
390
|
-
ipv4 = (): this => this.format('ipv4')
|
|
391
|
-
ipv6 = (): this => this.format('ipv6')
|
|
392
|
-
password = (): this => this.format('password')
|
|
393
|
-
id = (): this => this.format('id')
|
|
394
|
-
slug = (): this => this.format('slug')
|
|
395
|
-
semVer = (): this => this.format('semVer')
|
|
396
|
-
languageTag = (): this => this.format('languageTag')
|
|
397
|
-
countryCode = (): this => this.format('countryCode')
|
|
398
|
-
currency = (): this => this.format('currency')
|
|
399
|
-
|
|
400
|
-
trim(trim = true): this {
|
|
401
|
-
Object.assign(this.schema, { transform: { ...this.schema.transform, trim } })
|
|
402
|
-
return this
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
toLowerCase(toLowerCase = true): this {
|
|
406
|
-
Object.assign(this.schema, { transform: { ...this.schema.transform, toLowerCase } })
|
|
407
|
-
return this
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
toUpperCase(toUpperCase = true): this {
|
|
411
|
-
Object.assign(this.schema, { transform: { ...this.schema.transform, toUpperCase } })
|
|
412
|
-
return this
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
truncate(toLength: number): this {
|
|
416
|
-
Object.assign(this.schema, { transform: { ...this.schema.transform, truncate: toLength } })
|
|
417
|
-
return this
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
branded<B extends string>(): JsonSchemaStringBuilder<B> {
|
|
421
|
-
return this as unknown as JsonSchemaStringBuilder<B>
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
426
|
-
*/
|
|
427
|
-
isoDate(): JsonSchemaStringBuilder<IsoDate> {
|
|
428
|
-
return this.format('IsoDate').branded<IsoDate>().description('IsoDate')
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
|
|
433
|
-
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
434
|
-
*/
|
|
435
|
-
isoDateTime(): JsonSchemaStringBuilder<IsoDateTime> {
|
|
436
|
-
return this.format('IsoDateTime').branded<IsoDateTime>().description('IsoDateTime')
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
jwt(): this {
|
|
440
|
-
return this.regex(JWT_REGEX)
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
export class JsonSchemaObjectBuilder<
|
|
445
|
-
T extends AnyObject,
|
|
446
|
-
Opt extends boolean = false,
|
|
447
|
-
> extends JsonSchemaAnyBuilder<T, JsonSchemaObject<T>, Opt> {
|
|
448
|
-
constructor() {
|
|
449
|
-
super({
|
|
450
|
-
type: 'object',
|
|
451
|
-
properties: {} as T,
|
|
452
|
-
required: [],
|
|
453
|
-
additionalProperties: false,
|
|
454
|
-
})
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
addProperties(props?: { [k in keyof T]: JsonSchemaBuilder<T[k]> }): this {
|
|
458
|
-
if (!props) return this
|
|
459
|
-
|
|
460
|
-
Object.entries(props).forEach(([k, builder]: [keyof T, JsonSchemaBuilder]) => {
|
|
461
|
-
const schema = builder.build()
|
|
462
|
-
if (!schema.optionalField) {
|
|
463
|
-
this.schema.required.push(k)
|
|
464
|
-
} else {
|
|
465
|
-
schema.optionalField = undefined
|
|
466
|
-
}
|
|
467
|
-
this.schema.properties[k] = schema
|
|
468
|
-
})
|
|
469
|
-
|
|
470
|
-
this.required(this.schema.required) // ensure it's sorted and _uniq
|
|
471
|
-
|
|
472
|
-
return this
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Ensures `required` is always sorted and _uniq
|
|
477
|
-
*/
|
|
478
|
-
required(required: (keyof T)[]): this {
|
|
479
|
-
Object.assign(this.schema, { required })
|
|
480
|
-
this.schema.required = _uniq(required).sort()
|
|
481
|
-
return this
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
addRequired(required: (keyof T)[]): this {
|
|
485
|
-
return this.required([...this.schema.required, ...required])
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
minProps(minProperties: number): this {
|
|
489
|
-
Object.assign(this.schema, { minProperties })
|
|
490
|
-
return this
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
maxProps(maxProperties: number): this {
|
|
494
|
-
Object.assign(this.schema, { maxProperties })
|
|
495
|
-
return this
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
additionalProps(additionalProperties: boolean): this {
|
|
499
|
-
Object.assign(this.schema, { additionalProperties })
|
|
500
|
-
return this
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
baseDBEntity(): JsonSchemaObjectBuilder<T & BaseDBEntity> {
|
|
504
|
-
Object.assign(this.schema.properties, {
|
|
505
|
-
id: { type: 'string' },
|
|
506
|
-
created: { type: 'number', format: 'unixTimestamp2000' },
|
|
507
|
-
updated: { type: 'number', format: 'unixTimestamp2000' },
|
|
508
|
-
})
|
|
509
|
-
|
|
510
|
-
return this.addRequired(['id', 'created', 'updated']) as any
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
extend<T2 extends AnyObject>(
|
|
514
|
-
s2: JsonSchemaObjectBuilder<T2>,
|
|
515
|
-
): JsonSchemaObjectBuilder<T & T2 extends infer O ? { [K in keyof O]: O[K] } : never> {
|
|
516
|
-
const builder = new JsonSchemaObjectBuilder<any>()
|
|
517
|
-
Object.assign(builder.schema, _deepCopy(this.schema))
|
|
518
|
-
mergeJsonSchemaObjects(builder.schema, s2.schema)
|
|
519
|
-
return builder
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
export class JsonSchemaArrayBuilder<ITEM, Opt extends boolean = false> extends JsonSchemaAnyBuilder<
|
|
524
|
-
ITEM[],
|
|
525
|
-
JsonSchemaArray<ITEM>,
|
|
526
|
-
Opt
|
|
527
|
-
> {
|
|
528
|
-
constructor(itemsSchema: JsonSchemaBuilder<ITEM>) {
|
|
529
|
-
super({
|
|
530
|
-
type: 'array',
|
|
531
|
-
items: itemsSchema.build(),
|
|
532
|
-
})
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
min(minItems: number): this {
|
|
536
|
-
Object.assign(this.schema, { minItems })
|
|
537
|
-
return this
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
max(maxItems: number): this {
|
|
541
|
-
Object.assign(this.schema, { maxItems })
|
|
542
|
-
return this
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
unique(uniqueItems = true): this {
|
|
546
|
-
Object.assign(this.schema, { uniqueItems })
|
|
547
|
-
return this
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
export class JsonSchemaTupleBuilder<T extends any[]> extends JsonSchemaAnyBuilder<
|
|
552
|
-
T,
|
|
553
|
-
JsonSchemaTuple<T>
|
|
554
|
-
> {
|
|
555
|
-
constructor(items: JsonSchemaBuilder[]) {
|
|
556
|
-
super({
|
|
557
|
-
type: 'array',
|
|
558
|
-
items: items.map(b => b.build()),
|
|
559
|
-
minItems: items.length,
|
|
560
|
-
maxItems: items.length,
|
|
561
|
-
})
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
function object<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props?: {
|
|
566
|
-
[K in keyof P]: P[K] & JsonSchemaAnyBuilder<any, any, any>
|
|
567
|
-
}): JsonSchemaObjectBuilder<
|
|
568
|
-
{
|
|
569
|
-
[K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer Opt>
|
|
570
|
-
? Opt extends true
|
|
571
|
-
? never
|
|
572
|
-
: K
|
|
573
|
-
: never]: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never
|
|
574
|
-
} & {
|
|
575
|
-
[K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer Opt>
|
|
576
|
-
? Opt extends true
|
|
577
|
-
? K
|
|
578
|
-
: never
|
|
579
|
-
: never]?: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never
|
|
580
|
-
} extends infer O
|
|
581
|
-
? { [K in keyof O]: O[K] }
|
|
582
|
-
: never
|
|
583
|
-
>
|
|
584
|
-
function object<T extends AnyObject>(props?: {
|
|
585
|
-
[K in keyof T]: JsonSchemaAnyBuilder<T[K]>
|
|
586
|
-
}): JsonSchemaObjectBuilder<T>
|
|
587
|
-
|
|
588
|
-
function object(props?: any): any {
|
|
589
|
-
return new JsonSchemaObjectBuilder<any>().addProperties(props)
|
|
590
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { BaseDBEntity } from '../types.js'
|
|
2
|
-
import { j } from './jsonSchemaBuilder.js'
|
|
3
|
-
|
|
4
|
-
export const baseDBEntityJsonSchema = j.object<BaseDBEntity>({
|
|
5
|
-
id: j.string(),
|
|
6
|
-
created: j.integer().unixTimestamp2000(),
|
|
7
|
-
updated: j.integer().unixTimestamp2000(),
|
|
8
|
-
})
|