@naturalcycles/js-lib 15.35.0 → 15.37.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/json-schema/jsonSchema.model.d.ts +2 -2
- package/dist/json-schema/jsonSchemaBuilder.d.ts +42 -35
- package/dist/json-schema/jsonSchemaBuilder.js +12 -8
- package/dist/json-schema/jsonSchemas.d.ts +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.js +1 -0
- package/package.json +1 -1
- package/src/json-schema/jsonSchema.model.ts +2 -2
- package/src/json-schema/jsonSchemaBuilder.ts +79 -48
- package/src/types.ts +1 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AnyObject, StringMap } from '../types.js';
|
|
2
|
-
export type JsonSchema<T = unknown> = JsonSchemaAny<T> | JsonSchemaOneOf<T> | JsonSchemaAllOf<T> | JsonSchemaAnyOf<T> | JsonSchemaNot<T> | JsonSchemaRef<T> | JsonSchemaConst<T> | JsonSchemaEnum<T> | JsonSchemaString | JsonSchemaNumber | JsonSchemaBoolean | JsonSchemaNull | JsonSchemaObject | JsonSchemaArray<T> | JsonSchemaTuple<T>;
|
|
2
|
+
export type JsonSchema<T = unknown> = JsonSchemaAny<T> | JsonSchemaOneOf<T> | JsonSchemaAllOf<T> | JsonSchemaAnyOf<T> | JsonSchemaNot<T> | JsonSchemaRef<T> | JsonSchemaConst<T> | JsonSchemaEnum<T> | JsonSchemaString | JsonSchemaNumber | JsonSchemaBoolean | JsonSchemaNull | JsonSchemaObject<T extends AnyObject ? T : AnyObject> | JsonSchemaArray<T> | JsonSchemaTuple<T>;
|
|
3
3
|
export interface JsonSchemaAny<T = unknown> {
|
|
4
4
|
$schema?: string;
|
|
5
5
|
$id?: string;
|
|
@@ -8,7 +8,7 @@ export interface JsonSchemaAny<T = unknown> {
|
|
|
8
8
|
deprecated?: boolean;
|
|
9
9
|
readOnly?: boolean;
|
|
10
10
|
writeOnly?: boolean;
|
|
11
|
-
type?: string;
|
|
11
|
+
type?: string | string[];
|
|
12
12
|
default?: T;
|
|
13
13
|
if?: JsonSchema;
|
|
14
14
|
then?: JsonSchema;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AnyObject, type BaseDBEntity, type IsoDate, type IsoDateTime, type UnixTimestamp } from '../types.js';
|
|
2
2
|
import type { JsonSchema, JsonSchemaAllOf, JsonSchemaAny, JsonSchemaArray, JsonSchemaBoolean, JsonSchemaConst, JsonSchemaEnum, JsonSchemaNull, JsonSchemaNumber, JsonSchemaObject, JsonSchemaOneOf, JsonSchemaRef, JsonSchemaString, JsonSchemaTuple } from './jsonSchema.model.js';
|
|
3
3
|
export interface JsonSchemaBuilder<T = unknown> {
|
|
4
4
|
build: () => JsonSchema<T>;
|
|
@@ -8,36 +8,37 @@ export interface JsonSchemaBuilder<T = unknown> {
|
|
|
8
8
|
* Inspired by Joi and Zod.
|
|
9
9
|
*/
|
|
10
10
|
export declare const j: {
|
|
11
|
-
any<T = unknown>(): JsonSchemaAnyBuilder<T, JsonSchemaAny<T
|
|
12
|
-
const<T
|
|
13
|
-
null(): JsonSchemaAnyBuilder<null, JsonSchemaNull>;
|
|
14
|
-
ref<T = unknown>($ref: string): JsonSchemaAnyBuilder<T, JsonSchemaRef<T
|
|
15
|
-
enum<T = unknown>(enumValues: T[]): JsonSchemaAnyBuilder<T, JsonSchemaEnum<T
|
|
16
|
-
boolean(): JsonSchemaAnyBuilder<boolean, JsonSchemaBoolean>;
|
|
17
|
-
buffer(): JsonSchemaAnyBuilder<Buffer<ArrayBufferLike>, JsonSchemaAny<Buffer<ArrayBufferLike
|
|
18
|
-
number<T extends number = number>(): JsonSchemaNumberBuilder<T>;
|
|
19
|
-
integer<T extends number = number>(): JsonSchemaNumberBuilder<T>;
|
|
20
|
-
unixTimestamp(): JsonSchemaNumberBuilder<UnixTimestamp>;
|
|
21
|
-
unixTimestamp2000(): JsonSchemaNumberBuilder<UnixTimestamp>;
|
|
22
|
-
string<T extends string = string>(): JsonSchemaStringBuilder<T>;
|
|
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<T = unknown>(enumValues: T[]): JsonSchemaAnyBuilder<T, JsonSchemaEnum<T>, 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
|
+
unixTimestamp(): JsonSchemaNumberBuilder<UnixTimestamp, false>;
|
|
21
|
+
unixTimestamp2000(): JsonSchemaNumberBuilder<UnixTimestamp, false>;
|
|
22
|
+
string<T extends string = string>(): JsonSchemaStringBuilder<T, false>;
|
|
23
|
+
jwt(): JsonSchemaStringBuilder<string, false>;
|
|
23
24
|
/**
|
|
24
25
|
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
25
26
|
*/
|
|
26
|
-
isoDate(): JsonSchemaStringBuilder<IsoDate>;
|
|
27
|
+
isoDate(): JsonSchemaStringBuilder<IsoDate, false>;
|
|
27
28
|
/**
|
|
28
29
|
* Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
|
|
29
30
|
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
30
31
|
*/
|
|
31
|
-
isoDateTime(): JsonSchemaStringBuilder<IsoDateTime>;
|
|
32
|
+
isoDateTime(): JsonSchemaStringBuilder<IsoDateTime, false>;
|
|
32
33
|
object: typeof object;
|
|
33
|
-
dbEntity<T extends AnyObject>(props: T): JsonSchemaObjectBuilder<BaseDBEntity & { [K in keyof T]: T[K] extends JsonSchemaAnyBuilder<infer U, any> ? U : never; }>;
|
|
34
|
-
rootObject<T extends AnyObject>(props: { [K in keyof T]: JsonSchemaAnyBuilder<T[K]>; }): JsonSchemaObjectBuilder<T>;
|
|
35
|
-
array<T extends JsonSchemaAnyBuilder<any>>(itemSchema: T): JsonSchemaArrayBuilder<T["infer"]>;
|
|
34
|
+
dbEntity<T extends AnyObject>(props: T): JsonSchemaObjectBuilder<BaseDBEntity & ({ [K in keyof T as T[K] extends JsonSchemaAnyBuilder<any, any, infer Opt extends boolean> ? Opt extends true ? never : K : never]: T[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never; } & { [K_1 in keyof T as T[K_1] extends JsonSchemaAnyBuilder<any, any, infer Opt extends boolean> ? Opt extends true ? K_1 : never : never]?: (T[K_1] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never) | undefined; } extends infer O ? { [K_2 in keyof O]: O[K_2]; } : never) extends infer O_1 ? { [K_3 in keyof O_1]: O_1[K_3]; } : never, false>;
|
|
35
|
+
rootObject<T extends AnyObject>(props: { [K in keyof T]: JsonSchemaAnyBuilder<T[K]>; }): JsonSchemaObjectBuilder<T, false>;
|
|
36
|
+
array<T extends JsonSchemaAnyBuilder<any>>(itemSchema: T): JsonSchemaArrayBuilder<T["infer"], false>;
|
|
36
37
|
tuple<T extends any[] = unknown[]>(items: JsonSchemaAnyBuilder[]): JsonSchemaTupleBuilder<T>;
|
|
37
|
-
oneOf<
|
|
38
|
-
allOf<T = unknown>(items: JsonSchemaAnyBuilder[]): JsonSchemaAnyBuilder<T, JsonSchemaAllOf<T
|
|
38
|
+
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>>;
|
|
39
|
+
allOf<T = unknown>(items: JsonSchemaAnyBuilder[]): JsonSchemaAnyBuilder<T, JsonSchemaAllOf<T>, false>;
|
|
39
40
|
};
|
|
40
|
-
export declare class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T> = JsonSchema<T
|
|
41
|
+
export declare class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T> = JsonSchema<T>, Opt extends boolean = false> implements JsonSchemaBuilder<T> {
|
|
41
42
|
protected schema: SCHEMA_TYPE;
|
|
42
43
|
constructor(schema: SCHEMA_TYPE);
|
|
43
44
|
/**
|
|
@@ -52,24 +53,23 @@ export declare class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonS
|
|
|
52
53
|
deprecated(deprecated?: boolean): this;
|
|
53
54
|
type(type: string): this;
|
|
54
55
|
default(v: any): this;
|
|
55
|
-
oneOf(schemas: JsonSchema[]): this;
|
|
56
|
-
allOf(schemas: JsonSchema[]): this;
|
|
57
56
|
instanceof(of: string): this;
|
|
58
|
-
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined
|
|
59
|
-
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined
|
|
60
|
-
optional(optional: false): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined
|
|
57
|
+
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>;
|
|
58
|
+
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>;
|
|
59
|
+
optional(optional: false): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined>>, false>;
|
|
60
|
+
nullable(): JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt>;
|
|
61
61
|
/**
|
|
62
62
|
* Produces a "clean schema object" without methods.
|
|
63
63
|
* Same as if it would be JSON.stringified.
|
|
64
64
|
*/
|
|
65
65
|
build(): SCHEMA_TYPE;
|
|
66
|
-
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE>;
|
|
66
|
+
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt>;
|
|
67
67
|
/**
|
|
68
68
|
* @experimental
|
|
69
69
|
*/
|
|
70
70
|
infer: T;
|
|
71
71
|
}
|
|
72
|
-
export declare class JsonSchemaNumberBuilder<T extends number = number> extends JsonSchemaAnyBuilder<T, JsonSchemaNumber<T
|
|
72
|
+
export declare class JsonSchemaNumberBuilder<T extends number = number, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaNumber<T>, Opt> {
|
|
73
73
|
constructor();
|
|
74
74
|
integer(): this;
|
|
75
75
|
multipleOf(multipleOf: number): this;
|
|
@@ -94,7 +94,7 @@ export declare class JsonSchemaNumberBuilder<T extends number = number> extends
|
|
|
94
94
|
utcOffsetHours: () => this;
|
|
95
95
|
branded<B extends number>(): JsonSchemaNumberBuilder<B>;
|
|
96
96
|
}
|
|
97
|
-
export declare class JsonSchemaStringBuilder<T extends string = string> extends JsonSchemaAnyBuilder<T, JsonSchemaString<T
|
|
97
|
+
export declare class JsonSchemaStringBuilder<T extends string = string, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaString<T>, Opt> {
|
|
98
98
|
constructor();
|
|
99
99
|
regex(pattern: RegExp): this;
|
|
100
100
|
pattern(pattern: string): this;
|
|
@@ -126,9 +126,10 @@ export declare class JsonSchemaStringBuilder<T extends string = string> extends
|
|
|
126
126
|
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
127
127
|
*/
|
|
128
128
|
isoDateTime(): JsonSchemaStringBuilder<IsoDateTime>;
|
|
129
|
+
jwt(): this;
|
|
129
130
|
private transformModify;
|
|
130
131
|
}
|
|
131
|
-
export declare class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSchemaAnyBuilder<T, JsonSchemaObject<T
|
|
132
|
+
export declare class JsonSchemaObjectBuilder<T extends AnyObject, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaObject<T>, Opt> {
|
|
132
133
|
constructor();
|
|
133
134
|
addProperties(props: {
|
|
134
135
|
[k in keyof T]: JsonSchemaBuilder<T[k]>;
|
|
@@ -142,9 +143,11 @@ export declare class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSc
|
|
|
142
143
|
maxProps(maxProperties: number): this;
|
|
143
144
|
additionalProps(additionalProperties: boolean): this;
|
|
144
145
|
baseDBEntity(): JsonSchemaObjectBuilder<T & BaseDBEntity>;
|
|
145
|
-
extend<T2 extends AnyObject>(s2: JsonSchemaObjectBuilder<T2>): JsonSchemaObjectBuilder<T & T2
|
|
146
|
+
extend<T2 extends AnyObject>(s2: JsonSchemaObjectBuilder<T2>): JsonSchemaObjectBuilder<T & T2 extends infer O ? {
|
|
147
|
+
[K in keyof O]: O[K];
|
|
148
|
+
} : never>;
|
|
146
149
|
}
|
|
147
|
-
export declare class JsonSchemaArrayBuilder<ITEM> extends JsonSchemaAnyBuilder<ITEM[], JsonSchemaArray<ITEM
|
|
150
|
+
export declare class JsonSchemaArrayBuilder<ITEM, Opt extends boolean = false> extends JsonSchemaAnyBuilder<ITEM[], JsonSchemaArray<ITEM>, Opt> {
|
|
148
151
|
constructor(itemsSchema: JsonSchemaBuilder<ITEM>);
|
|
149
152
|
min(minItems: number): this;
|
|
150
153
|
max(maxItems: number): this;
|
|
@@ -153,9 +156,13 @@ export declare class JsonSchemaArrayBuilder<ITEM> extends JsonSchemaAnyBuilder<I
|
|
|
153
156
|
export declare class JsonSchemaTupleBuilder<T extends any[]> extends JsonSchemaAnyBuilder<T, JsonSchemaTuple<T>> {
|
|
154
157
|
constructor(items: JsonSchemaBuilder[]);
|
|
155
158
|
}
|
|
156
|
-
declare function object<P extends Record<string, JsonSchemaAnyBuilder<any, any>>>(props: P): JsonSchemaObjectBuilder<{
|
|
157
|
-
[K in keyof P]: P[K] extends JsonSchemaAnyBuilder<infer U, any> ? U : never;
|
|
158
|
-
}
|
|
159
|
+
declare function object<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: P): JsonSchemaObjectBuilder<{
|
|
160
|
+
[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;
|
|
161
|
+
} & {
|
|
162
|
+
[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;
|
|
163
|
+
} extends infer O ? {
|
|
164
|
+
[K in keyof O]: O[K];
|
|
165
|
+
} : never>;
|
|
159
166
|
declare function object<T extends AnyObject>(props: {
|
|
160
167
|
[K in keyof T]: JsonSchemaAnyBuilder<T[K]>;
|
|
161
168
|
}): JsonSchemaObjectBuilder<T>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { _uniq } from '../array/array.util.js';
|
|
2
2
|
import { _deepCopy } from '../object/object.util.js';
|
|
3
3
|
import { _sortObject } from '../object/sortObject.js';
|
|
4
|
+
import { JWT_REGEX, } from '../types.js';
|
|
4
5
|
import { JSON_SCHEMA_ORDER } from './jsonSchema.cnst.js';
|
|
5
6
|
import { mergeJsonSchemaObjects } from './jsonSchema.util.js';
|
|
6
7
|
/**
|
|
@@ -56,6 +57,9 @@ export const j = {
|
|
|
56
57
|
string() {
|
|
57
58
|
return new JsonSchemaStringBuilder();
|
|
58
59
|
},
|
|
60
|
+
jwt() {
|
|
61
|
+
return new JsonSchemaStringBuilder().jwt();
|
|
62
|
+
},
|
|
59
63
|
/**
|
|
60
64
|
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
61
65
|
*/
|
|
@@ -144,14 +148,6 @@ export class JsonSchemaAnyBuilder {
|
|
|
144
148
|
Object.assign(this.schema, { default: v });
|
|
145
149
|
return this;
|
|
146
150
|
}
|
|
147
|
-
oneOf(schemas) {
|
|
148
|
-
Object.assign(this.schema, { oneOf: schemas });
|
|
149
|
-
return this;
|
|
150
|
-
}
|
|
151
|
-
allOf(schemas) {
|
|
152
|
-
Object.assign(this.schema, { allOf: schemas });
|
|
153
|
-
return this;
|
|
154
|
-
}
|
|
155
151
|
instanceof(of) {
|
|
156
152
|
this.schema.instanceof = of;
|
|
157
153
|
return this;
|
|
@@ -165,6 +161,11 @@ export class JsonSchemaAnyBuilder {
|
|
|
165
161
|
}
|
|
166
162
|
return this;
|
|
167
163
|
}
|
|
164
|
+
nullable() {
|
|
165
|
+
return new JsonSchemaAnyBuilder({
|
|
166
|
+
anyOf: [this.build(), { type: 'null' }],
|
|
167
|
+
});
|
|
168
|
+
}
|
|
168
169
|
/**
|
|
169
170
|
* Produces a "clean schema object" without methods.
|
|
170
171
|
* Same as if it would be JSON.stringified.
|
|
@@ -294,6 +295,9 @@ export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
|
|
|
294
295
|
isoDateTime() {
|
|
295
296
|
return this.format('IsoDateTime').branded().description('IsoDateTime');
|
|
296
297
|
}
|
|
298
|
+
jwt() {
|
|
299
|
+
return this.regex(JWT_REGEX);
|
|
300
|
+
}
|
|
297
301
|
transformModify(t, add) {
|
|
298
302
|
if (add) {
|
|
299
303
|
this.schema.transform = _uniq([...(this.schema.transform || []), t]);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { BaseDBEntity } from '../types.js';
|
|
2
|
-
export declare const baseDBEntityJsonSchema: import("./jsonSchemaBuilder.js").JsonSchemaObjectBuilder<BaseDBEntity>;
|
|
2
|
+
export declare const baseDBEntityJsonSchema: import("./jsonSchemaBuilder.js").JsonSchemaObjectBuilder<BaseDBEntity, false>;
|
package/dist/types.d.ts
CHANGED
|
@@ -266,6 +266,7 @@ export type ShortBoolean = '1';
|
|
|
266
266
|
export type Base64String = string;
|
|
267
267
|
export type Base64UrlString = string;
|
|
268
268
|
export type JWTString = string;
|
|
269
|
+
export declare const JWT_REGEX: RegExp;
|
|
269
270
|
export type SemVerString = string;
|
|
270
271
|
/**
|
|
271
272
|
* Named type for JSON.parse / JSON.stringify second argument
|
package/dist/types.js
CHANGED
|
@@ -20,6 +20,7 @@ export const _passUndefinedMapper = () => undefined;
|
|
|
20
20
|
export const _noop = (..._args) => undefined;
|
|
21
21
|
export const _passthroughPredicate = () => true;
|
|
22
22
|
export const _passNothingPredicate = () => false;
|
|
23
|
+
export const JWT_REGEX = /^[\w-]+\.[\w-]+\.[\w-]+$/;
|
|
23
24
|
/**
|
|
24
25
|
* Like _stringMapValues, but values are sorted.
|
|
25
26
|
*/
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@ export type JsonSchema<T = unknown> =
|
|
|
13
13
|
| JsonSchemaNumber
|
|
14
14
|
| JsonSchemaBoolean
|
|
15
15
|
| JsonSchemaNull
|
|
16
|
-
| JsonSchemaObject
|
|
16
|
+
| JsonSchemaObject<T extends AnyObject ? T : AnyObject>
|
|
17
17
|
| JsonSchemaArray<T>
|
|
18
18
|
| JsonSchemaTuple<T>
|
|
19
19
|
|
|
@@ -28,7 +28,7 @@ export interface JsonSchemaAny<T = unknown> {
|
|
|
28
28
|
readOnly?: boolean
|
|
29
29
|
writeOnly?: boolean
|
|
30
30
|
|
|
31
|
-
type?: string
|
|
31
|
+
type?: string | string[]
|
|
32
32
|
|
|
33
33
|
default?: T
|
|
34
34
|
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { _uniq } from '../array/array.util.js'
|
|
2
2
|
import { _deepCopy } from '../object/object.util.js'
|
|
3
3
|
import { _sortObject } from '../object/sortObject.js'
|
|
4
|
-
import
|
|
4
|
+
import {
|
|
5
|
+
type AnyObject,
|
|
6
|
+
type BaseDBEntity,
|
|
7
|
+
type IsoDate,
|
|
8
|
+
type IsoDateTime,
|
|
9
|
+
JWT_REGEX,
|
|
10
|
+
type JWTString,
|
|
11
|
+
type UnixTimestamp,
|
|
12
|
+
} from '../types.js'
|
|
5
13
|
import { JSON_SCHEMA_ORDER } from './jsonSchema.cnst.js'
|
|
6
14
|
import type {
|
|
7
15
|
JsonSchema,
|
|
@@ -35,7 +43,7 @@ export const j = {
|
|
|
35
43
|
any<T = unknown>() {
|
|
36
44
|
return new JsonSchemaAnyBuilder<T, JsonSchemaAny<T>>({})
|
|
37
45
|
},
|
|
38
|
-
const<T
|
|
46
|
+
const<T extends string | number | boolean | null>(value: T) {
|
|
39
47
|
return new JsonSchemaAnyBuilder<T, JsonSchemaConst<T>>({
|
|
40
48
|
const: value,
|
|
41
49
|
})
|
|
@@ -82,6 +90,9 @@ export const j = {
|
|
|
82
90
|
string<T extends string = string>() {
|
|
83
91
|
return new JsonSchemaStringBuilder<T>()
|
|
84
92
|
},
|
|
93
|
+
jwt() {
|
|
94
|
+
return new JsonSchemaStringBuilder<JWTString>().jwt()
|
|
95
|
+
},
|
|
85
96
|
|
|
86
97
|
/**
|
|
87
98
|
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
@@ -122,10 +133,15 @@ export const j = {
|
|
|
122
133
|
tuple<T extends any[] = unknown[]>(items: JsonSchemaAnyBuilder[]) {
|
|
123
134
|
return new JsonSchemaTupleBuilder<T>(items)
|
|
124
135
|
},
|
|
125
|
-
oneOf<
|
|
126
|
-
|
|
136
|
+
oneOf<Builders extends JsonSchemaAnyBuilder<any, any, any>[]>(
|
|
137
|
+
items: [...Builders],
|
|
138
|
+
): JsonSchemaAnyBuilder<
|
|
139
|
+
Builders[number] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never,
|
|
140
|
+
JsonSchemaOneOf<Builders[number] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never>
|
|
141
|
+
> {
|
|
142
|
+
return new JsonSchemaAnyBuilder({
|
|
127
143
|
oneOf: items.map(b => b.build()),
|
|
128
|
-
})
|
|
144
|
+
}) as any
|
|
129
145
|
},
|
|
130
146
|
allOf<T = unknown>(items: JsonSchemaAnyBuilder[]) {
|
|
131
147
|
return new JsonSchemaAnyBuilder<T, JsonSchemaAllOf<T>>({
|
|
@@ -134,8 +150,11 @@ export const j = {
|
|
|
134
150
|
},
|
|
135
151
|
}
|
|
136
152
|
|
|
137
|
-
export class JsonSchemaAnyBuilder<
|
|
138
|
-
|
|
153
|
+
export class JsonSchemaAnyBuilder<
|
|
154
|
+
T = unknown,
|
|
155
|
+
SCHEMA_TYPE extends JsonSchema<T> = JsonSchema<T>,
|
|
156
|
+
Opt extends boolean = false,
|
|
157
|
+
> implements JsonSchemaBuilder<T>
|
|
139
158
|
{
|
|
140
159
|
constructor(protected schema: SCHEMA_TYPE) {}
|
|
141
160
|
|
|
@@ -186,27 +205,17 @@ export class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T>
|
|
|
186
205
|
return this
|
|
187
206
|
}
|
|
188
207
|
|
|
189
|
-
oneOf(schemas: JsonSchema[]): this {
|
|
190
|
-
Object.assign(this.schema, { oneOf: schemas })
|
|
191
|
-
return this
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
allOf(schemas: JsonSchema[]): this {
|
|
195
|
-
Object.assign(this.schema, { allOf: schemas })
|
|
196
|
-
return this
|
|
197
|
-
}
|
|
198
|
-
|
|
199
208
|
instanceof(of: string): this {
|
|
200
209
|
this.schema.instanceof = of
|
|
201
210
|
return this
|
|
202
211
|
}
|
|
203
212
|
|
|
204
|
-
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined
|
|
205
|
-
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined
|
|
213
|
+
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>
|
|
214
|
+
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>
|
|
206
215
|
optional(
|
|
207
216
|
optional: false,
|
|
208
|
-
): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined
|
|
209
|
-
optional(optional = true): JsonSchemaAnyBuilder<any, JsonSchema<any
|
|
217
|
+
): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined>>, false>
|
|
218
|
+
optional(optional = true): JsonSchemaAnyBuilder<any, JsonSchema<any>, false> {
|
|
210
219
|
if (optional) {
|
|
211
220
|
this.schema.optionalField = true
|
|
212
221
|
} else {
|
|
@@ -215,6 +224,12 @@ export class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T>
|
|
|
215
224
|
return this
|
|
216
225
|
}
|
|
217
226
|
|
|
227
|
+
nullable(): JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt> {
|
|
228
|
+
return new JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt>({
|
|
229
|
+
anyOf: [this.build(), { type: 'null' }],
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
218
233
|
/**
|
|
219
234
|
* Produces a "clean schema object" without methods.
|
|
220
235
|
* Same as if it would be JSON.stringified.
|
|
@@ -223,8 +238,8 @@ export class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T>
|
|
|
223
238
|
return _sortObject(JSON.parse(JSON.stringify(this.schema)), JSON_SCHEMA_ORDER)
|
|
224
239
|
}
|
|
225
240
|
|
|
226
|
-
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE> {
|
|
227
|
-
return new JsonSchemaAnyBuilder<T, SCHEMA_TYPE>(_deepCopy(this.schema))
|
|
241
|
+
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt> {
|
|
242
|
+
return new JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt>(_deepCopy(this.schema))
|
|
228
243
|
}
|
|
229
244
|
|
|
230
245
|
/**
|
|
@@ -233,10 +248,10 @@ export class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T>
|
|
|
233
248
|
infer!: T
|
|
234
249
|
}
|
|
235
250
|
|
|
236
|
-
export class JsonSchemaNumberBuilder<
|
|
237
|
-
T,
|
|
238
|
-
|
|
239
|
-
> {
|
|
251
|
+
export class JsonSchemaNumberBuilder<
|
|
252
|
+
T extends number = number,
|
|
253
|
+
Opt extends boolean = false,
|
|
254
|
+
> extends JsonSchemaAnyBuilder<T, JsonSchemaNumber<T>, Opt> {
|
|
240
255
|
constructor() {
|
|
241
256
|
super({
|
|
242
257
|
type: 'number',
|
|
@@ -306,10 +321,10 @@ export class JsonSchemaNumberBuilder<T extends number = number> extends JsonSche
|
|
|
306
321
|
}
|
|
307
322
|
}
|
|
308
323
|
|
|
309
|
-
export class JsonSchemaStringBuilder<
|
|
310
|
-
T,
|
|
311
|
-
|
|
312
|
-
> {
|
|
324
|
+
export class JsonSchemaStringBuilder<
|
|
325
|
+
T extends string = string,
|
|
326
|
+
Opt extends boolean = false,
|
|
327
|
+
> extends JsonSchemaAnyBuilder<T, JsonSchemaString<T>, Opt> {
|
|
313
328
|
constructor() {
|
|
314
329
|
super({
|
|
315
330
|
type: 'string',
|
|
@@ -380,6 +395,10 @@ export class JsonSchemaStringBuilder<T extends string = string> extends JsonSche
|
|
|
380
395
|
return this.format('IsoDateTime').branded<IsoDateTime>().description('IsoDateTime')
|
|
381
396
|
}
|
|
382
397
|
|
|
398
|
+
jwt(): this {
|
|
399
|
+
return this.regex(JWT_REGEX)
|
|
400
|
+
}
|
|
401
|
+
|
|
383
402
|
private transformModify(t: 'trim' | 'toLowerCase' | 'toUpperCase', add: boolean): this {
|
|
384
403
|
if (add) {
|
|
385
404
|
this.schema.transform = _uniq([...(this.schema.transform || []), t])
|
|
@@ -393,10 +412,10 @@ export class JsonSchemaStringBuilder<T extends string = string> extends JsonSche
|
|
|
393
412
|
// contentEncoding?: string
|
|
394
413
|
}
|
|
395
414
|
|
|
396
|
-
export class JsonSchemaObjectBuilder<
|
|
397
|
-
T,
|
|
398
|
-
|
|
399
|
-
> {
|
|
415
|
+
export class JsonSchemaObjectBuilder<
|
|
416
|
+
T extends AnyObject,
|
|
417
|
+
Opt extends boolean = false,
|
|
418
|
+
> extends JsonSchemaAnyBuilder<T, JsonSchemaObject<T>, Opt> {
|
|
400
419
|
constructor() {
|
|
401
420
|
super({
|
|
402
421
|
type: 'object',
|
|
@@ -460,17 +479,20 @@ export class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSchemaAnyB
|
|
|
460
479
|
return this.addRequired(['id', 'created', 'updated']) as any
|
|
461
480
|
}
|
|
462
481
|
|
|
463
|
-
extend<T2 extends AnyObject>(
|
|
464
|
-
|
|
482
|
+
extend<T2 extends AnyObject>(
|
|
483
|
+
s2: JsonSchemaObjectBuilder<T2>,
|
|
484
|
+
): JsonSchemaObjectBuilder<T & T2 extends infer O ? { [K in keyof O]: O[K] } : never> {
|
|
485
|
+
const builder = new JsonSchemaObjectBuilder<any>()
|
|
465
486
|
Object.assign(builder.schema, _deepCopy(this.schema))
|
|
466
487
|
mergeJsonSchemaObjects(builder.schema, s2.schema)
|
|
467
488
|
return builder
|
|
468
489
|
}
|
|
469
490
|
}
|
|
470
491
|
|
|
471
|
-
export class JsonSchemaArrayBuilder<ITEM> extends JsonSchemaAnyBuilder<
|
|
492
|
+
export class JsonSchemaArrayBuilder<ITEM, Opt extends boolean = false> extends JsonSchemaAnyBuilder<
|
|
472
493
|
ITEM[],
|
|
473
|
-
JsonSchemaArray<ITEM
|
|
494
|
+
JsonSchemaArray<ITEM>,
|
|
495
|
+
Opt
|
|
474
496
|
> {
|
|
475
497
|
constructor(itemsSchema: JsonSchemaBuilder<ITEM>) {
|
|
476
498
|
super({
|
|
@@ -509,16 +531,25 @@ export class JsonSchemaTupleBuilder<T extends any[]> extends JsonSchemaAnyBuilde
|
|
|
509
531
|
}
|
|
510
532
|
}
|
|
511
533
|
|
|
512
|
-
|
|
513
|
-
// The issue is that in `j` we mix two approaches:
|
|
514
|
-
// 1) the builder driven approach
|
|
515
|
-
// 2) the type driven approach.
|
|
516
|
-
|
|
517
|
-
function object<P extends Record<string, JsonSchemaAnyBuilder<any, any>>>(
|
|
534
|
+
function object<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(
|
|
518
535
|
props: P,
|
|
519
|
-
): JsonSchemaObjectBuilder<
|
|
520
|
-
|
|
521
|
-
|
|
536
|
+
): JsonSchemaObjectBuilder<
|
|
537
|
+
{
|
|
538
|
+
[K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer Opt>
|
|
539
|
+
? Opt extends true
|
|
540
|
+
? never
|
|
541
|
+
: K
|
|
542
|
+
: never]: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never
|
|
543
|
+
} & {
|
|
544
|
+
[K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer Opt>
|
|
545
|
+
? Opt extends true
|
|
546
|
+
? K
|
|
547
|
+
: never
|
|
548
|
+
: never]?: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never
|
|
549
|
+
} extends infer O
|
|
550
|
+
? { [K in keyof O]: O[K] }
|
|
551
|
+
: never
|
|
552
|
+
>
|
|
522
553
|
function object<T extends AnyObject>(props: {
|
|
523
554
|
[K in keyof T]: JsonSchemaAnyBuilder<T[K]>
|
|
524
555
|
}): JsonSchemaObjectBuilder<T>
|
package/src/types.ts
CHANGED