@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,159 +0,0 @@
1
- import { type AnyObject, type BaseDBEntity, type IsoDate, type IsoDateTime, type NumberEnum, type StringEnum, type UnixTimestamp, type UnixTimestampMillis } from '../types.js';
2
- import type { JsonSchema, JsonSchemaAllOf, JsonSchemaAny, JsonSchemaArray, JsonSchemaBoolean, JsonSchemaConst, JsonSchemaEnum, JsonSchemaNull, JsonSchemaNumber, JsonSchemaObject, JsonSchemaOneOf, JsonSchemaRef, JsonSchemaString, JsonSchemaTuple } from './jsonSchema.model.js';
3
- export interface JsonSchemaBuilder<T = unknown> {
4
- build: () => JsonSchema<T>;
5
- }
6
- /**
7
- * Fluent (chainable) API to manually create Json Schemas.
8
- * Inspired by Joi and Zod.
9
- */
10
- export declare const j: {
11
- any<T = unknown>(): JsonSchemaAnyBuilder<T, JsonSchemaAny<T>, false>;
12
- const<T extends string | number | boolean | null>(value: T): JsonSchemaAnyBuilder<T, JsonSchemaConst<T>, false>;
13
- null(): JsonSchemaAnyBuilder<null, JsonSchemaNull, false>;
14
- ref<T = unknown>($ref: string): JsonSchemaAnyBuilder<T, JsonSchemaRef<T>, false>;
15
- enum<const T extends readonly (string | number | boolean | null)[] | StringEnum | NumberEnum>(input: T): JsonSchemaAnyBuilder<T extends readonly (infer U)[] ? U : T extends StringEnum ? T[keyof T] : T extends NumberEnum ? T[keyof T] : never, JsonSchemaEnum<any>, false>;
16
- boolean(): JsonSchemaAnyBuilder<boolean, JsonSchemaBoolean, false>;
17
- buffer(): JsonSchemaAnyBuilder<Buffer<ArrayBufferLike>, JsonSchemaAny<Buffer<ArrayBufferLike>>, false>;
18
- number<T extends number = number>(): JsonSchemaNumberBuilder<T, false>;
19
- integer<T extends number = number>(): JsonSchemaNumberBuilder<T, false>;
20
- string<T extends string = string>(): JsonSchemaStringBuilder<T, false>;
21
- object: typeof object;
22
- dbEntity<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: P): JsonSchemaObjectBuilder<BaseDBEntity & { [K in keyof P]: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never; }>;
23
- rootObject<T extends AnyObject>(props: { [K in keyof T]: JsonSchemaAnyBuilder<T[K]>; }): JsonSchemaObjectBuilder<T, false>;
24
- array<T extends JsonSchemaAnyBuilder<any>>(itemSchema: T): JsonSchemaArrayBuilder<T["infer"], false>;
25
- tuple<T extends any[] = unknown[]>(items: JsonSchemaAnyBuilder[]): JsonSchemaTupleBuilder<T>;
26
- oneOf<Builders extends JsonSchemaAnyBuilder<any, any, any>[]>(items: [...Builders]): JsonSchemaAnyBuilder<Builders[number] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never, JsonSchemaOneOf<Builders[number] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never>>;
27
- allOf<T = unknown>(items: JsonSchemaAnyBuilder[]): JsonSchemaAnyBuilder<T, JsonSchemaAllOf<T>, false>;
28
- };
29
- export declare class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T> = JsonSchema<T>, Opt extends boolean = false> implements JsonSchemaBuilder<T> {
30
- protected schema: SCHEMA_TYPE;
31
- constructor(schema: SCHEMA_TYPE);
32
- /**
33
- * Used in ObjectBuilder to access schema.optionalProperty
34
- */
35
- getSchema(): SCHEMA_TYPE;
36
- $schema($schema: string): this;
37
- $schemaDraft7(): this;
38
- $id($id: string): this;
39
- title(title: string): this;
40
- description(description: string): this;
41
- deprecated(deprecated?: boolean): this;
42
- type(type: string): this;
43
- default(v: any): this;
44
- instanceof(of: string): this;
45
- optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>;
46
- optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>;
47
- optional(optional: false): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined>>, false>;
48
- nullable(): JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt>;
49
- /**
50
- * Produces a "clean schema object" without methods.
51
- * Same as if it would be JSON.stringified.
52
- */
53
- build(): SCHEMA_TYPE;
54
- clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt>;
55
- /**
56
- * @experimental
57
- */
58
- infer: T;
59
- }
60
- export declare class JsonSchemaNumberBuilder<T extends number = number, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaNumber<T>, Opt> {
61
- constructor();
62
- integer(): this;
63
- multipleOf(multipleOf: number): this;
64
- min(minimum: number): this;
65
- exclusiveMin(exclusiveMinimum: number): this;
66
- max(maximum: number): this;
67
- exclusiveMax(exclusiveMaximum: number): this;
68
- /**
69
- * Both ranges are inclusive.
70
- */
71
- range(minimum: number, maximum: number): this;
72
- format(format: string): this;
73
- int32: () => this;
74
- int64: () => this;
75
- float: () => this;
76
- double: () => this;
77
- unixTimestamp: () => JsonSchemaNumberBuilder<UnixTimestamp>;
78
- unixTimestamp2000: () => JsonSchemaNumberBuilder<UnixTimestamp>;
79
- unixTimestampMillis: () => JsonSchemaNumberBuilder<UnixTimestampMillis>;
80
- unixTimestampMillis2000: () => JsonSchemaNumberBuilder<UnixTimestampMillis>;
81
- utcOffset: () => this;
82
- utcOffsetHours: () => this;
83
- branded<B extends number>(): JsonSchemaNumberBuilder<B>;
84
- }
85
- export declare class JsonSchemaStringBuilder<T extends string = string, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaString<T>, Opt> {
86
- constructor();
87
- regex(pattern: RegExp): this;
88
- pattern(pattern: string): this;
89
- min(minLength: number): this;
90
- max(maxLength: number): this;
91
- length(minLength: number, maxLength: number): this;
92
- format(format: string): this;
93
- email: () => this;
94
- url: () => this;
95
- ipv4: () => this;
96
- ipv6: () => this;
97
- password: () => this;
98
- id: () => this;
99
- slug: () => this;
100
- semVer: () => this;
101
- languageTag: () => this;
102
- countryCode: () => this;
103
- currency: () => this;
104
- trim(trim?: boolean): this;
105
- toLowerCase(toLowerCase?: boolean): this;
106
- toUpperCase(toUpperCase?: boolean): this;
107
- truncate(toLength: number): this;
108
- branded<B extends string>(): JsonSchemaStringBuilder<B>;
109
- /**
110
- * Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
111
- */
112
- isoDate(): JsonSchemaStringBuilder<IsoDate>;
113
- /**
114
- * Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
115
- * and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
116
- */
117
- isoDateTime(): JsonSchemaStringBuilder<IsoDateTime>;
118
- jwt(): this;
119
- }
120
- export declare class JsonSchemaObjectBuilder<T extends AnyObject, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaObject<T>, Opt> {
121
- constructor();
122
- addProperties(props?: {
123
- [k in keyof T]: JsonSchemaBuilder<T[k]>;
124
- }): this;
125
- /**
126
- * Ensures `required` is always sorted and _uniq
127
- */
128
- required(required: (keyof T)[]): this;
129
- addRequired(required: (keyof T)[]): this;
130
- minProps(minProperties: number): this;
131
- maxProps(maxProperties: number): this;
132
- additionalProps(additionalProperties: boolean): this;
133
- baseDBEntity(): JsonSchemaObjectBuilder<T & BaseDBEntity>;
134
- extend<T2 extends AnyObject>(s2: JsonSchemaObjectBuilder<T2>): JsonSchemaObjectBuilder<T & T2 extends infer O ? {
135
- [K in keyof O]: O[K];
136
- } : never>;
137
- }
138
- export declare class JsonSchemaArrayBuilder<ITEM, Opt extends boolean = false> extends JsonSchemaAnyBuilder<ITEM[], JsonSchemaArray<ITEM>, Opt> {
139
- constructor(itemsSchema: JsonSchemaBuilder<ITEM>);
140
- min(minItems: number): this;
141
- max(maxItems: number): this;
142
- unique(uniqueItems?: boolean): this;
143
- }
144
- export declare class JsonSchemaTupleBuilder<T extends any[]> extends JsonSchemaAnyBuilder<T, JsonSchemaTuple<T>> {
145
- constructor(items: JsonSchemaBuilder[]);
146
- }
147
- declare function object<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props?: {
148
- [K in keyof P]: P[K] & JsonSchemaAnyBuilder<any, any, any>;
149
- }): JsonSchemaObjectBuilder<{
150
- [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer Opt> ? Opt extends true ? never : K : never]: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never;
151
- } & {
152
- [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer Opt> ? Opt extends true ? K : never : never]?: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never;
153
- } extends infer O ? {
154
- [K in keyof O]: O[K];
155
- } : never>;
156
- declare function object<T extends AnyObject>(props?: {
157
- [K in keyof T]: JsonSchemaAnyBuilder<T[K]>;
158
- }): JsonSchemaObjectBuilder<T>;
159
- export {};
@@ -1,412 +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 { JWT_REGEX, } from '../types.js';
7
- import { JSON_SCHEMA_ORDER } from './jsonSchema.cnst.js';
8
- import { mergeJsonSchemaObjects } from './jsonSchema.util.js';
9
- /**
10
- * Fluent (chainable) API to manually create Json Schemas.
11
- * Inspired by Joi and Zod.
12
- */
13
- export const j = {
14
- any() {
15
- return new JsonSchemaAnyBuilder({});
16
- },
17
- const(value) {
18
- return new JsonSchemaAnyBuilder({
19
- const: value,
20
- });
21
- },
22
- null() {
23
- return new JsonSchemaAnyBuilder({
24
- type: 'null',
25
- });
26
- },
27
- ref($ref) {
28
- return new JsonSchemaAnyBuilder({
29
- $ref,
30
- });
31
- },
32
- enum(input) {
33
- let enumValues;
34
- if (Array.isArray(input)) {
35
- enumValues = input;
36
- }
37
- else if (typeof input === 'object') {
38
- const enumType = getEnumType(input);
39
- if (enumType === 'NumberEnum') {
40
- enumValues = _numberEnumValues(input);
41
- }
42
- else if (enumType === 'StringEnum') {
43
- enumValues = _stringEnumValues(input);
44
- }
45
- }
46
- _assert(enumValues, 'Unsupported enum input');
47
- return new JsonSchemaAnyBuilder({
48
- enum: enumValues,
49
- });
50
- },
51
- boolean() {
52
- return new JsonSchemaAnyBuilder({
53
- type: 'boolean',
54
- });
55
- },
56
- buffer() {
57
- return new JsonSchemaAnyBuilder({ instanceof: 'Buffer' });
58
- },
59
- // number types
60
- number() {
61
- return new JsonSchemaNumberBuilder();
62
- },
63
- integer() {
64
- return new JsonSchemaNumberBuilder().integer();
65
- },
66
- // string types
67
- string() {
68
- return new JsonSchemaStringBuilder();
69
- },
70
- // complex types
71
- object,
72
- dbEntity(props) {
73
- return j
74
- .object({
75
- id: j.string(),
76
- created: j.integer().unixTimestamp2000(),
77
- updated: j.integer().unixTimestamp2000(),
78
- })
79
- .extend(j.object(props));
80
- },
81
- rootObject(props) {
82
- return new JsonSchemaObjectBuilder().addProperties(props).$schemaDraft7();
83
- },
84
- array(itemSchema) {
85
- return new JsonSchemaArrayBuilder(itemSchema);
86
- },
87
- tuple(items) {
88
- return new JsonSchemaTupleBuilder(items);
89
- },
90
- oneOf(items) {
91
- return new JsonSchemaAnyBuilder({
92
- oneOf: items.map(b => b.build()),
93
- });
94
- },
95
- allOf(items) {
96
- return new JsonSchemaAnyBuilder({
97
- allOf: items.map(b => b.build()),
98
- });
99
- },
100
- };
101
- export class JsonSchemaAnyBuilder {
102
- schema;
103
- constructor(schema) {
104
- this.schema = schema;
105
- }
106
- /**
107
- * Used in ObjectBuilder to access schema.optionalProperty
108
- */
109
- getSchema() {
110
- return this.schema;
111
- }
112
- $schema($schema) {
113
- Object.assign(this.schema, { $schema });
114
- return this;
115
- }
116
- $schemaDraft7() {
117
- this.$schema('http://json-schema.org/draft-07/schema#');
118
- return this;
119
- }
120
- $id($id) {
121
- Object.assign(this.schema, { $id });
122
- return this;
123
- }
124
- title(title) {
125
- Object.assign(this.schema, { title });
126
- return this;
127
- }
128
- description(description) {
129
- Object.assign(this.schema, { description });
130
- return this;
131
- }
132
- deprecated(deprecated = true) {
133
- Object.assign(this.schema, { deprecated });
134
- return this;
135
- }
136
- type(type) {
137
- Object.assign(this.schema, { type });
138
- return this;
139
- }
140
- default(v) {
141
- Object.assign(this.schema, { default: v });
142
- return this;
143
- }
144
- instanceof(of) {
145
- Object.assign(this.schema, { type: 'object', instanceof: of });
146
- return this;
147
- }
148
- optional(optional = true) {
149
- if (optional) {
150
- this.schema.optionalField = true;
151
- }
152
- else {
153
- this.schema.optionalField = undefined;
154
- }
155
- return this;
156
- }
157
- nullable() {
158
- return new JsonSchemaAnyBuilder({
159
- anyOf: [this.build(), { type: 'null' }],
160
- });
161
- }
162
- /**
163
- * Produces a "clean schema object" without methods.
164
- * Same as if it would be JSON.stringified.
165
- */
166
- build() {
167
- return _sortObject(JSON.parse(JSON.stringify(this.schema)), JSON_SCHEMA_ORDER);
168
- }
169
- clone() {
170
- return new JsonSchemaAnyBuilder(_deepCopy(this.schema));
171
- }
172
- /**
173
- * @experimental
174
- */
175
- infer;
176
- }
177
- export class JsonSchemaNumberBuilder extends JsonSchemaAnyBuilder {
178
- constructor() {
179
- super({
180
- type: 'number',
181
- });
182
- }
183
- integer() {
184
- Object.assign(this.schema, { type: 'integer' });
185
- return this;
186
- }
187
- multipleOf(multipleOf) {
188
- Object.assign(this.schema, { multipleOf });
189
- return this;
190
- }
191
- min(minimum) {
192
- Object.assign(this.schema, { minimum });
193
- return this;
194
- }
195
- exclusiveMin(exclusiveMinimum) {
196
- Object.assign(this.schema, { exclusiveMinimum });
197
- return this;
198
- }
199
- max(maximum) {
200
- Object.assign(this.schema, { maximum });
201
- return this;
202
- }
203
- exclusiveMax(exclusiveMaximum) {
204
- Object.assign(this.schema, { exclusiveMaximum });
205
- return this;
206
- }
207
- /**
208
- * Both ranges are inclusive.
209
- */
210
- range(minimum, maximum) {
211
- Object.assign(this.schema, { minimum, maximum });
212
- return this;
213
- }
214
- format(format) {
215
- Object.assign(this.schema, { format });
216
- return this;
217
- }
218
- int32 = () => this.format('int32');
219
- int64 = () => this.format('int64');
220
- float = () => this.format('float');
221
- double = () => this.format('double');
222
- unixTimestamp = () => this.integer().branded().format('unixTimestamp').description('UnixTimestamp');
223
- unixTimestamp2000 = () => this.integer()
224
- .branded()
225
- .format('unixTimestamp2000')
226
- .description('UnixTimestamp2000');
227
- unixTimestampMillis = () => this.integer()
228
- .branded()
229
- .format('unixTimestampMillis')
230
- .description('UnixTimestampMillis');
231
- unixTimestampMillis2000 = () => this.integer()
232
- .branded()
233
- .format('unixTimestampMillis2000')
234
- .description('UnixTimestampMillis2000');
235
- utcOffset = () => this.format('utcOffset');
236
- utcOffsetHours = () => this.format('utcOffsetHours');
237
- branded() {
238
- return this;
239
- }
240
- }
241
- export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
242
- constructor() {
243
- super({
244
- type: 'string',
245
- });
246
- }
247
- regex(pattern) {
248
- return this.pattern(pattern.source);
249
- }
250
- pattern(pattern) {
251
- Object.assign(this.schema, { pattern });
252
- return this;
253
- }
254
- min(minLength) {
255
- Object.assign(this.schema, { minLength });
256
- return this;
257
- }
258
- max(maxLength) {
259
- Object.assign(this.schema, { maxLength });
260
- return this;
261
- }
262
- length(minLength, maxLength) {
263
- Object.assign(this.schema, { minLength, maxLength });
264
- return this;
265
- }
266
- format(format) {
267
- Object.assign(this.schema, { format });
268
- return this;
269
- }
270
- email = () => this.format('email');
271
- url = () => this.format('url');
272
- ipv4 = () => this.format('ipv4');
273
- ipv6 = () => this.format('ipv6');
274
- password = () => this.format('password');
275
- id = () => this.format('id');
276
- slug = () => this.format('slug');
277
- semVer = () => this.format('semVer');
278
- languageTag = () => this.format('languageTag');
279
- countryCode = () => this.format('countryCode');
280
- currency = () => this.format('currency');
281
- trim(trim = true) {
282
- Object.assign(this.schema, { transform: { ...this.schema.transform, trim } });
283
- return this;
284
- }
285
- toLowerCase(toLowerCase = true) {
286
- Object.assign(this.schema, { transform: { ...this.schema.transform, toLowerCase } });
287
- return this;
288
- }
289
- toUpperCase(toUpperCase = true) {
290
- Object.assign(this.schema, { transform: { ...this.schema.transform, toUpperCase } });
291
- return this;
292
- }
293
- truncate(toLength) {
294
- Object.assign(this.schema, { transform: { ...this.schema.transform, truncate: toLength } });
295
- return this;
296
- }
297
- branded() {
298
- return this;
299
- }
300
- /**
301
- * Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
302
- */
303
- isoDate() {
304
- return this.format('IsoDate').branded().description('IsoDate');
305
- }
306
- /**
307
- * Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
308
- * and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
309
- */
310
- isoDateTime() {
311
- return this.format('IsoDateTime').branded().description('IsoDateTime');
312
- }
313
- jwt() {
314
- return this.regex(JWT_REGEX);
315
- }
316
- }
317
- export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
318
- constructor() {
319
- super({
320
- type: 'object',
321
- properties: {},
322
- required: [],
323
- additionalProperties: false,
324
- });
325
- }
326
- addProperties(props) {
327
- if (!props)
328
- return this;
329
- Object.entries(props).forEach(([k, builder]) => {
330
- const schema = builder.build();
331
- if (!schema.optionalField) {
332
- this.schema.required.push(k);
333
- }
334
- else {
335
- schema.optionalField = undefined;
336
- }
337
- this.schema.properties[k] = schema;
338
- });
339
- this.required(this.schema.required); // ensure it's sorted and _uniq
340
- return this;
341
- }
342
- /**
343
- * Ensures `required` is always sorted and _uniq
344
- */
345
- required(required) {
346
- Object.assign(this.schema, { required });
347
- this.schema.required = _uniq(required).sort();
348
- return this;
349
- }
350
- addRequired(required) {
351
- return this.required([...this.schema.required, ...required]);
352
- }
353
- minProps(minProperties) {
354
- Object.assign(this.schema, { minProperties });
355
- return this;
356
- }
357
- maxProps(maxProperties) {
358
- Object.assign(this.schema, { maxProperties });
359
- return this;
360
- }
361
- additionalProps(additionalProperties) {
362
- Object.assign(this.schema, { additionalProperties });
363
- return this;
364
- }
365
- baseDBEntity() {
366
- Object.assign(this.schema.properties, {
367
- id: { type: 'string' },
368
- created: { type: 'number', format: 'unixTimestamp2000' },
369
- updated: { type: 'number', format: 'unixTimestamp2000' },
370
- });
371
- return this.addRequired(['id', 'created', 'updated']);
372
- }
373
- extend(s2) {
374
- const builder = new JsonSchemaObjectBuilder();
375
- Object.assign(builder.schema, _deepCopy(this.schema));
376
- mergeJsonSchemaObjects(builder.schema, s2.schema);
377
- return builder;
378
- }
379
- }
380
- export class JsonSchemaArrayBuilder extends JsonSchemaAnyBuilder {
381
- constructor(itemsSchema) {
382
- super({
383
- type: 'array',
384
- items: itemsSchema.build(),
385
- });
386
- }
387
- min(minItems) {
388
- Object.assign(this.schema, { minItems });
389
- return this;
390
- }
391
- max(maxItems) {
392
- Object.assign(this.schema, { maxItems });
393
- return this;
394
- }
395
- unique(uniqueItems = true) {
396
- Object.assign(this.schema, { uniqueItems });
397
- return this;
398
- }
399
- }
400
- export class JsonSchemaTupleBuilder extends JsonSchemaAnyBuilder {
401
- constructor(items) {
402
- super({
403
- type: 'array',
404
- items: items.map(b => b.build()),
405
- minItems: items.length,
406
- maxItems: items.length,
407
- });
408
- }
409
- }
410
- function object(props) {
411
- return new JsonSchemaObjectBuilder().addProperties(props);
412
- }
@@ -1,2 +0,0 @@
1
- import type { BaseDBEntity } from '../types.js';
2
- export declare const baseDBEntityJsonSchema: import("./jsonSchemaBuilder.js").JsonSchemaObjectBuilder<BaseDBEntity, false>;
@@ -1,6 +0,0 @@
1
- import { j } from './jsonSchemaBuilder.js';
2
- export const baseDBEntityJsonSchema = j.object({
3
- id: j.string(),
4
- created: j.integer().unixTimestamp2000(),
5
- updated: j.integer().unixTimestamp2000(),
6
- });
@@ -1,121 +0,0 @@
1
- import { _uniq } from '../../array/index.js'
2
- import { _stringMapEntries, type AnyObject, type StringMap } from '../../types.js'
3
- import type {
4
- JsonSchema,
5
- JsonSchemaArray,
6
- JsonSchemaBoolean,
7
- JsonSchemaNull,
8
- JsonSchemaNumber,
9
- JsonSchemaObject,
10
- JsonSchemaOneOf,
11
- JsonSchemaString,
12
- } from '../index.js'
13
-
14
- type PrimitiveType = 'undefined' | 'null' | 'boolean' | 'string' | 'number'
15
- type Type = PrimitiveType | 'array' | 'object'
16
-
17
- /**
18
- * Each row must be an object (current limitation).
19
- *
20
- * `additionalProperties` is set to `true`, cause it's safer.
21
- */
22
- export function generateJsonSchemaFromData<T extends AnyObject = AnyObject>(
23
- rows: AnyObject[],
24
- ): JsonSchemaObject<T> {
25
- return objectToJsonSchema(rows as any) as JsonSchemaObject<T>
26
- }
27
-
28
- function objectToJsonSchema(rows: AnyObject[]): JsonSchemaObject {
29
- const typesByKey: StringMap<Set<Type>> = {}
30
-
31
- rows.forEach(r => {
32
- Object.keys(r).forEach(key => {
33
- typesByKey[key] ||= new Set<Type>()
34
- typesByKey[key].add(getTypeOfValue(r[key]))
35
- })
36
- })
37
-
38
- const s: JsonSchemaObject = {
39
- type: 'object',
40
- properties: {},
41
- required: [],
42
- additionalProperties: true,
43
- }
44
-
45
- _stringMapEntries(typesByKey).forEach(([key, types]) => {
46
- const schema = mergeTypes(
47
- [...types],
48
- rows.map(r => r[key]),
49
- )
50
- if (!schema) return
51
- s.properties[key] = schema
52
- })
53
-
54
- // console.log(typesByKey)
55
-
56
- return s
57
- }
58
-
59
- function mergeTypes(types: Type[], samples: any[]): JsonSchema | undefined {
60
- // skip "undefined" types
61
- types = types.filter(t => t !== 'undefined')
62
-
63
- if (!types.length) return undefined
64
-
65
- if (types.length > 1) {
66
- // oneOf
67
- const s: JsonSchemaOneOf = {
68
- oneOf: types.map(type => mergeTypes([type], samples)!),
69
- }
70
-
71
- return s
72
- }
73
-
74
- const type = types[0]!
75
-
76
- if (type === 'null') {
77
- return {
78
- type: 'null',
79
- } as JsonSchemaNull
80
- }
81
-
82
- if (type === 'boolean') {
83
- return {
84
- type: 'boolean',
85
- } as JsonSchemaBoolean
86
- }
87
-
88
- if (type === 'string') {
89
- return {
90
- type: 'string',
91
- } as JsonSchemaString
92
- }
93
-
94
- if (type === 'number') {
95
- return {
96
- type: 'number',
97
- } as JsonSchemaNumber
98
- }
99
-
100
- if (type === 'object') {
101
- return objectToJsonSchema(samples.filter((r: any) => r && typeof r === 'object'))
102
- }
103
-
104
- if (type === 'array') {
105
- // possible feature: detect if it's a tuple
106
- // currently assume no-tuple
107
- const items = samples.filter(r => Array.isArray(r)).flat()
108
- const itemTypes = _uniq(items.map(i => getTypeOfValue(i)))
109
-
110
- return {
111
- type: 'array',
112
- items: mergeTypes(itemTypes, items),
113
- } as JsonSchemaArray
114
- }
115
- }
116
-
117
- function getTypeOfValue(v: any): Type {
118
- if (v === null) return 'null'
119
- if (Array.isArray(v)) return 'array'
120
- return typeof v as Type
121
- }