@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.
Files changed (37) hide show
  1. package/dist/http/fetcher.d.ts +1 -1
  2. package/dist/http/fetcher.js +1 -1
  3. package/dist/promise/pProps.js +1 -1
  4. package/dist/promise/pTimeout.js +1 -1
  5. package/dist/semver.js +1 -0
  6. package/dist/web.d.ts +1 -1
  7. package/dist/web.js +1 -1
  8. package/package.json +3 -4
  9. package/readme.md +0 -8
  10. package/src/http/fetcher.ts +1 -1
  11. package/src/promise/pProps.ts +1 -1
  12. package/src/promise/pTimeout.ts +1 -1
  13. package/src/semver.ts +1 -0
  14. package/src/types.ts +4 -4
  15. package/src/web.ts +1 -1
  16. package/src/zod/zod.shared.schemas.ts +1 -1
  17. package/dist/json-schema/from-data/generateJsonSchemaFromData.d.ts +0 -8
  18. package/dist/json-schema/from-data/generateJsonSchemaFromData.js +0 -87
  19. package/dist/json-schema/index.d.ts +0 -5
  20. package/dist/json-schema/index.js +0 -5
  21. package/dist/json-schema/jsonSchema.cnst.d.ts +0 -2
  22. package/dist/json-schema/jsonSchema.cnst.js +0 -38
  23. package/dist/json-schema/jsonSchema.model.d.ts +0 -121
  24. package/dist/json-schema/jsonSchema.model.js +0 -1
  25. package/dist/json-schema/jsonSchema.util.d.ts +0 -8
  26. package/dist/json-schema/jsonSchema.util.js +0 -27
  27. package/dist/json-schema/jsonSchemaBuilder.d.ts +0 -159
  28. package/dist/json-schema/jsonSchemaBuilder.js +0 -412
  29. package/dist/json-schema/jsonSchemas.d.ts +0 -2
  30. package/dist/json-schema/jsonSchemas.js +0 -6
  31. package/src/json-schema/from-data/generateJsonSchemaFromData.ts +0 -121
  32. package/src/json-schema/index.ts +0 -5
  33. package/src/json-schema/jsonSchema.cnst.ts +0 -52
  34. package/src/json-schema/jsonSchema.model.ts +0 -172
  35. package/src/json-schema/jsonSchema.util.ts +0 -36
  36. package/src/json-schema/jsonSchemaBuilder.ts +0 -590
  37. 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
- })