@naturalcycles/js-lib 15.34.0 → 15.36.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/array/array.util.d.ts +1 -1
- package/dist/array/array.util.js +7 -13
- package/dist/decorators/asyncMemo.decorator.d.ts +3 -3
- package/dist/decorators/asyncMemo.decorator.js +3 -3
- package/dist/decorators/logMethod.decorator.js +1 -1
- package/dist/error/error.util.d.ts +1 -1
- package/dist/error/error.util.js +1 -1
- package/dist/json-schema/jsonSchema.model.d.ts +2 -2
- package/dist/json-schema/jsonSchemaBuilder.d.ts +57 -34
- package/dist/json-schema/jsonSchemaBuilder.js +40 -9
- package/dist/json-schema/jsonSchemas.d.ts +1 -1
- package/dist/object/object.util.d.ts +1 -3
- package/dist/object/object.util.js +3 -5
- package/dist/promise/pMap.js +2 -2
- package/dist/string/safeJsonStringify.js +2 -1
- package/dist/string/string.util.d.ts +1 -1
- package/dist/string/string.util.js +1 -1
- package/dist/typeFest.d.ts +0 -7
- package/dist/types.d.ts +1 -3
- package/dist/types.js +1 -1
- package/package.json +1 -1
- package/src/array/array.util.ts +7 -13
- package/src/browser/analytics.util.ts +2 -0
- package/src/decorators/asyncMemo.decorator.ts +3 -3
- package/src/decorators/logMethod.decorator.ts +1 -1
- package/src/error/error.util.ts +1 -1
- package/src/json-schema/jsonSchema.model.ts +2 -2
- package/src/json-schema/jsonSchemaBuilder.ts +106 -48
- package/src/object/object.util.ts +3 -5
- package/src/promise/pMap.ts +2 -2
- package/src/string/safeJsonStringify.ts +2 -2
- package/src/string/string.util.ts +1 -1
- package/src/typeFest.ts +0 -7
- package/src/types.ts +1 -3
|
@@ -5,7 +5,7 @@ import type { AbortablePredicate, FalsyValue, Mapper, Predicate, SortDirection,
|
|
|
5
5
|
*
|
|
6
6
|
* @param array The array to process.
|
|
7
7
|
* @param size The length of each chunk.
|
|
8
|
-
* @
|
|
8
|
+
* @returns Returns the new array containing chunks.
|
|
9
9
|
*
|
|
10
10
|
* https://lodash.com/docs#chunk
|
|
11
11
|
*
|
package/dist/array/array.util.js
CHANGED
|
@@ -6,7 +6,7 @@ import { END } from '../types.js';
|
|
|
6
6
|
*
|
|
7
7
|
* @param array The array to process.
|
|
8
8
|
* @param size The length of each chunk.
|
|
9
|
-
* @
|
|
9
|
+
* @returns Returns the new array containing chunks.
|
|
10
10
|
*
|
|
11
11
|
* https://lodash.com/docs#chunk
|
|
12
12
|
*
|
|
@@ -79,8 +79,7 @@ export function _pushUniqBy(a, mapper, ...items) {
|
|
|
79
79
|
*/
|
|
80
80
|
export function _uniqBy(arr, mapper) {
|
|
81
81
|
const map = new Map();
|
|
82
|
-
for (
|
|
83
|
-
const item = arr[i];
|
|
82
|
+
for (const item of arr) {
|
|
84
83
|
const key = item === undefined || item === null ? item : mapper(item);
|
|
85
84
|
if (!map.has(key))
|
|
86
85
|
map.set(key, item);
|
|
@@ -109,8 +108,7 @@ export function _uniqBy(arr, mapper) {
|
|
|
109
108
|
*/
|
|
110
109
|
export function _by(items, mapper) {
|
|
111
110
|
const map = {};
|
|
112
|
-
for (
|
|
113
|
-
const v = items[i];
|
|
111
|
+
for (const v of items) {
|
|
114
112
|
const k = mapper(v);
|
|
115
113
|
if (k !== undefined) {
|
|
116
114
|
map[k] = v;
|
|
@@ -123,8 +121,7 @@ export function _by(items, mapper) {
|
|
|
123
121
|
*/
|
|
124
122
|
export function _mapBy(items, mapper) {
|
|
125
123
|
const map = new Map();
|
|
126
|
-
for (
|
|
127
|
-
const item = items[i];
|
|
124
|
+
for (const item of items) {
|
|
128
125
|
const key = mapper(item);
|
|
129
126
|
if (key !== undefined) {
|
|
130
127
|
map.set(key, item);
|
|
@@ -145,8 +142,7 @@ export function _mapBy(items, mapper) {
|
|
|
145
142
|
*/
|
|
146
143
|
export function _groupBy(items, mapper) {
|
|
147
144
|
const map = {};
|
|
148
|
-
for (
|
|
149
|
-
const item = items[i];
|
|
145
|
+
for (const item of items) {
|
|
150
146
|
const key = mapper(item);
|
|
151
147
|
if (key !== undefined) {
|
|
152
148
|
;
|
|
@@ -444,8 +440,7 @@ export function _maxByOrUndefined(array, mapper) {
|
|
|
444
440
|
return;
|
|
445
441
|
let maxItem;
|
|
446
442
|
let max;
|
|
447
|
-
for (
|
|
448
|
-
const item = array[i];
|
|
443
|
+
for (const item of array) {
|
|
449
444
|
const v = mapper(item);
|
|
450
445
|
if (v !== undefined && (max === undefined || v > max)) {
|
|
451
446
|
maxItem = item;
|
|
@@ -459,8 +454,7 @@ export function _minByOrUndefined(array, mapper) {
|
|
|
459
454
|
return;
|
|
460
455
|
let minItem;
|
|
461
456
|
let min;
|
|
462
|
-
for (
|
|
463
|
-
const item = array[i];
|
|
457
|
+
for (const item of array) {
|
|
464
458
|
const v = mapper(item);
|
|
465
459
|
if (v !== undefined && (min === undefined || v < min)) {
|
|
466
460
|
minItem = item;
|
|
@@ -25,12 +25,12 @@ export interface AsyncMemoInstance {
|
|
|
25
25
|
getCache: (instance: AnyAsyncFunction) => AsyncMemoCache | undefined;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Like
|
|
28
|
+
* Like `@_Memo`, but allowing async MemoCache implementation.
|
|
29
29
|
*
|
|
30
|
-
* Implementation is more complex than
|
|
30
|
+
* Implementation is more complex than `@_Memo`, because it needs to handle "in-flight" Promises
|
|
31
31
|
* while waiting for cache to resolve, to prevent "async swarm" issue.
|
|
32
32
|
*
|
|
33
|
-
* @experimental consider normal
|
|
33
|
+
* @experimental consider normal `@_Memo` for most of the cases, it's stable and predictable
|
|
34
34
|
*/
|
|
35
35
|
export declare const _AsyncMemo: <FN>(opt: AsyncMemoOptions<FN>) => MethodDecorator<FN>;
|
|
36
36
|
/**
|
|
@@ -3,12 +3,12 @@ import { _objectAssign, MISS } from '../types.js';
|
|
|
3
3
|
import { _getTargetMethodSignature } from './decorator.util.js';
|
|
4
4
|
import { jsonMemoSerializer } from './memo.util.js';
|
|
5
5
|
/**
|
|
6
|
-
* Like
|
|
6
|
+
* Like `@_Memo`, but allowing async MemoCache implementation.
|
|
7
7
|
*
|
|
8
|
-
* Implementation is more complex than
|
|
8
|
+
* Implementation is more complex than `@_Memo`, because it needs to handle "in-flight" Promises
|
|
9
9
|
* while waiting for cache to resolve, to prevent "async swarm" issue.
|
|
10
10
|
*
|
|
11
|
-
* @experimental consider normal
|
|
11
|
+
* @experimental consider normal `@_Memo` for most of the cases, it's stable and predictable
|
|
12
12
|
*/
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
14
14
|
export const _AsyncMemo = (opt) => (target, key, descriptor) => {
|
|
@@ -70,7 +70,7 @@ export function _LogMethod(opt = {}) {
|
|
|
70
70
|
return descriptor;
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
-
//
|
|
73
|
+
// oxlint-disable-next-line max-params
|
|
74
74
|
function logFinished(logger, callSignature, started, sma, logResultFn, res, err) {
|
|
75
75
|
const millis = Date.now() - started;
|
|
76
76
|
const t = ['<<', callSignature, 'took', _ms(millis)];
|
|
@@ -83,7 +83,7 @@ export interface AppErrorOptions {
|
|
|
83
83
|
* data - optional "any" payload.
|
|
84
84
|
* data.userFriendly - if present, will be displayed to the User as is.
|
|
85
85
|
*
|
|
86
|
-
* Based on: https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801
|
|
86
|
+
* Based on: `https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801`
|
|
87
87
|
*/
|
|
88
88
|
export declare class AppError<DATA_TYPE extends ErrorData = ErrorData> extends Error {
|
|
89
89
|
data: DATA_TYPE;
|
package/dist/error/error.util.js
CHANGED
|
@@ -221,7 +221,7 @@ export function _errorDataAppend(err, data) {
|
|
|
221
221
|
* data - optional "any" payload.
|
|
222
222
|
* data.userFriendly - if present, will be displayed to the User as is.
|
|
223
223
|
*
|
|
224
|
-
* Based on: https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801
|
|
224
|
+
* Based on: `https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801`
|
|
225
225
|
*/
|
|
226
226
|
export class AppError extends Error {
|
|
227
227
|
data;
|
|
@@ -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 { AnyObject, BaseDBEntity, IsoDate, UnixTimestamp } from '../types.js';
|
|
1
|
+
import type { AnyObject, BaseDBEntity, IsoDate, IsoDateTime, 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,27 +8,36 @@ 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 = unknown>(value: T): JsonSchemaAnyBuilder<T, JsonSchemaConst<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>;
|
|
23
|
-
|
|
11
|
+
any<T = unknown>(): JsonSchemaAnyBuilder<T, JsonSchemaAny<T>, false>;
|
|
12
|
+
const<T = unknown>(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
|
+
/**
|
|
24
|
+
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
25
|
+
*/
|
|
26
|
+
isoDate(): JsonSchemaStringBuilder<IsoDate, false>;
|
|
27
|
+
/**
|
|
28
|
+
* Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
|
|
29
|
+
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
30
|
+
*/
|
|
31
|
+
isoDateTime(): JsonSchemaStringBuilder<IsoDateTime, false>;
|
|
24
32
|
object: typeof object;
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
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>;
|
|
34
|
+
rootObject<T extends AnyObject>(props: { [K in keyof T]: JsonSchemaAnyBuilder<T[K]>; }): JsonSchemaObjectBuilder<T, false>;
|
|
35
|
+
array<T extends JsonSchemaAnyBuilder<any>>(itemSchema: T): JsonSchemaArrayBuilder<T["infer"], false>;
|
|
27
36
|
tuple<T extends any[] = unknown[]>(items: JsonSchemaAnyBuilder[]): JsonSchemaTupleBuilder<T>;
|
|
28
|
-
oneOf<
|
|
29
|
-
allOf<T = unknown>(items: JsonSchemaAnyBuilder[]): JsonSchemaAnyBuilder<T, JsonSchemaAllOf<T
|
|
37
|
+
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>>;
|
|
38
|
+
allOf<T = unknown>(items: JsonSchemaAnyBuilder[]): JsonSchemaAnyBuilder<T, JsonSchemaAllOf<T>, false>;
|
|
30
39
|
};
|
|
31
|
-
export declare class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T> = JsonSchema<T
|
|
40
|
+
export declare class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T> = JsonSchema<T>, Opt extends boolean = false> implements JsonSchemaBuilder<T> {
|
|
32
41
|
protected schema: SCHEMA_TYPE;
|
|
33
42
|
constructor(schema: SCHEMA_TYPE);
|
|
34
43
|
/**
|
|
@@ -43,24 +52,23 @@ export declare class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonS
|
|
|
43
52
|
deprecated(deprecated?: boolean): this;
|
|
44
53
|
type(type: string): this;
|
|
45
54
|
default(v: any): this;
|
|
46
|
-
oneOf(schemas: JsonSchema[]): this;
|
|
47
|
-
allOf(schemas: JsonSchema[]): this;
|
|
48
55
|
instanceof(of: string): this;
|
|
49
|
-
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined
|
|
50
|
-
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined
|
|
51
|
-
optional(optional: false): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined
|
|
56
|
+
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>;
|
|
57
|
+
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>;
|
|
58
|
+
optional(optional: false): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined>>, false>;
|
|
59
|
+
nullable(): JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt>;
|
|
52
60
|
/**
|
|
53
61
|
* Produces a "clean schema object" without methods.
|
|
54
62
|
* Same as if it would be JSON.stringified.
|
|
55
63
|
*/
|
|
56
64
|
build(): SCHEMA_TYPE;
|
|
57
|
-
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE>;
|
|
65
|
+
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt>;
|
|
58
66
|
/**
|
|
59
67
|
* @experimental
|
|
60
68
|
*/
|
|
61
69
|
infer: T;
|
|
62
70
|
}
|
|
63
|
-
export declare class JsonSchemaNumberBuilder<T extends number = number> extends JsonSchemaAnyBuilder<T, JsonSchemaNumber<T
|
|
71
|
+
export declare class JsonSchemaNumberBuilder<T extends number = number, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaNumber<T>, Opt> {
|
|
64
72
|
constructor();
|
|
65
73
|
integer(): this;
|
|
66
74
|
multipleOf(multipleOf: number): this;
|
|
@@ -85,15 +93,15 @@ export declare class JsonSchemaNumberBuilder<T extends number = number> extends
|
|
|
85
93
|
utcOffsetHours: () => this;
|
|
86
94
|
branded<B extends number>(): JsonSchemaNumberBuilder<B>;
|
|
87
95
|
}
|
|
88
|
-
export declare class JsonSchemaStringBuilder<T extends string = string> extends JsonSchemaAnyBuilder<T, JsonSchemaString<T
|
|
96
|
+
export declare class JsonSchemaStringBuilder<T extends string = string, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaString<T>, Opt> {
|
|
89
97
|
constructor();
|
|
98
|
+
regex(pattern: RegExp): this;
|
|
90
99
|
pattern(pattern: string): this;
|
|
91
100
|
min(minLength: number): this;
|
|
92
101
|
max(maxLength: number): this;
|
|
93
102
|
length(minLength: number, maxLength: number): this;
|
|
94
103
|
format(format: string): this;
|
|
95
104
|
email: () => this;
|
|
96
|
-
isoDate: () => this;
|
|
97
105
|
url: () => this;
|
|
98
106
|
ipv4: () => this;
|
|
99
107
|
ipv6: () => this;
|
|
@@ -108,9 +116,18 @@ export declare class JsonSchemaStringBuilder<T extends string = string> extends
|
|
|
108
116
|
toLowerCase: (toLowerCase?: boolean) => this;
|
|
109
117
|
toUpperCase: (toUpperCase?: boolean) => this;
|
|
110
118
|
branded<B extends string>(): JsonSchemaStringBuilder<B>;
|
|
119
|
+
/**
|
|
120
|
+
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
121
|
+
*/
|
|
122
|
+
isoDate(): JsonSchemaStringBuilder<IsoDate>;
|
|
123
|
+
/**
|
|
124
|
+
* Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
|
|
125
|
+
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
126
|
+
*/
|
|
127
|
+
isoDateTime(): JsonSchemaStringBuilder<IsoDateTime>;
|
|
111
128
|
private transformModify;
|
|
112
129
|
}
|
|
113
|
-
export declare class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSchemaAnyBuilder<T, JsonSchemaObject<T
|
|
130
|
+
export declare class JsonSchemaObjectBuilder<T extends AnyObject, Opt extends boolean = false> extends JsonSchemaAnyBuilder<T, JsonSchemaObject<T>, Opt> {
|
|
114
131
|
constructor();
|
|
115
132
|
addProperties(props: {
|
|
116
133
|
[k in keyof T]: JsonSchemaBuilder<T[k]>;
|
|
@@ -124,9 +141,11 @@ export declare class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSc
|
|
|
124
141
|
maxProps(maxProperties: number): this;
|
|
125
142
|
additionalProps(additionalProperties: boolean): this;
|
|
126
143
|
baseDBEntity(): JsonSchemaObjectBuilder<T & BaseDBEntity>;
|
|
127
|
-
extend<T2 extends AnyObject>(s2: JsonSchemaObjectBuilder<T2>): JsonSchemaObjectBuilder<T & T2
|
|
144
|
+
extend<T2 extends AnyObject>(s2: JsonSchemaObjectBuilder<T2>): JsonSchemaObjectBuilder<T & T2 extends infer O ? {
|
|
145
|
+
[K in keyof O]: O[K];
|
|
146
|
+
} : never>;
|
|
128
147
|
}
|
|
129
|
-
export declare class JsonSchemaArrayBuilder<ITEM> extends JsonSchemaAnyBuilder<ITEM[], JsonSchemaArray<ITEM
|
|
148
|
+
export declare class JsonSchemaArrayBuilder<ITEM, Opt extends boolean = false> extends JsonSchemaAnyBuilder<ITEM[], JsonSchemaArray<ITEM>, Opt> {
|
|
130
149
|
constructor(itemsSchema: JsonSchemaBuilder<ITEM>);
|
|
131
150
|
min(minItems: number): this;
|
|
132
151
|
max(maxItems: number): this;
|
|
@@ -135,9 +154,13 @@ export declare class JsonSchemaArrayBuilder<ITEM> extends JsonSchemaAnyBuilder<I
|
|
|
135
154
|
export declare class JsonSchemaTupleBuilder<T extends any[]> extends JsonSchemaAnyBuilder<T, JsonSchemaTuple<T>> {
|
|
136
155
|
constructor(items: JsonSchemaBuilder[]);
|
|
137
156
|
}
|
|
138
|
-
declare function object<P extends Record<string, JsonSchemaAnyBuilder<any, any>>>(props: P): JsonSchemaObjectBuilder<{
|
|
139
|
-
[K in keyof P]: P[K] extends JsonSchemaAnyBuilder<infer U, any> ? U : never;
|
|
140
|
-
}
|
|
157
|
+
declare function object<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: P): JsonSchemaObjectBuilder<{
|
|
158
|
+
[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;
|
|
159
|
+
} & {
|
|
160
|
+
[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;
|
|
161
|
+
} extends infer O ? {
|
|
162
|
+
[K in keyof O]: O[K];
|
|
163
|
+
} : never>;
|
|
141
164
|
declare function object<T extends AnyObject>(props: {
|
|
142
165
|
[K in keyof T]: JsonSchemaAnyBuilder<T[K]>;
|
|
143
166
|
}): JsonSchemaObjectBuilder<T>;
|
|
@@ -56,12 +56,31 @@ export const j = {
|
|
|
56
56
|
string() {
|
|
57
57
|
return new JsonSchemaStringBuilder();
|
|
58
58
|
},
|
|
59
|
+
/**
|
|
60
|
+
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
61
|
+
*/
|
|
59
62
|
isoDate() {
|
|
60
63
|
return new JsonSchemaStringBuilder().isoDate();
|
|
61
64
|
},
|
|
65
|
+
/**
|
|
66
|
+
* Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
|
|
67
|
+
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
68
|
+
*/
|
|
69
|
+
isoDateTime() {
|
|
70
|
+
return new JsonSchemaStringBuilder().isoDateTime();
|
|
71
|
+
},
|
|
62
72
|
// email: () => new JsonSchemaStringBuilder().email(),
|
|
63
73
|
// complex types
|
|
64
74
|
object,
|
|
75
|
+
dbEntity(props) {
|
|
76
|
+
return j
|
|
77
|
+
.object({
|
|
78
|
+
id: j.string(),
|
|
79
|
+
created: j.unixTimestamp2000(),
|
|
80
|
+
updated: j.unixTimestamp2000(),
|
|
81
|
+
})
|
|
82
|
+
.extend(j.object(props));
|
|
83
|
+
},
|
|
65
84
|
rootObject(props) {
|
|
66
85
|
return new JsonSchemaObjectBuilder().addProperties(props).$schemaDraft7();
|
|
67
86
|
},
|
|
@@ -125,14 +144,6 @@ export class JsonSchemaAnyBuilder {
|
|
|
125
144
|
Object.assign(this.schema, { default: v });
|
|
126
145
|
return this;
|
|
127
146
|
}
|
|
128
|
-
oneOf(schemas) {
|
|
129
|
-
Object.assign(this.schema, { oneOf: schemas });
|
|
130
|
-
return this;
|
|
131
|
-
}
|
|
132
|
-
allOf(schemas) {
|
|
133
|
-
Object.assign(this.schema, { allOf: schemas });
|
|
134
|
-
return this;
|
|
135
|
-
}
|
|
136
147
|
instanceof(of) {
|
|
137
148
|
this.schema.instanceof = of;
|
|
138
149
|
return this;
|
|
@@ -146,6 +157,11 @@ export class JsonSchemaAnyBuilder {
|
|
|
146
157
|
}
|
|
147
158
|
return this;
|
|
148
159
|
}
|
|
160
|
+
nullable() {
|
|
161
|
+
return new JsonSchemaAnyBuilder({
|
|
162
|
+
anyOf: [this.build(), { type: 'null' }],
|
|
163
|
+
});
|
|
164
|
+
}
|
|
149
165
|
/**
|
|
150
166
|
* Produces a "clean schema object" without methods.
|
|
151
167
|
* Same as if it would be JSON.stringified.
|
|
@@ -222,6 +238,9 @@ export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
|
|
|
222
238
|
type: 'string',
|
|
223
239
|
});
|
|
224
240
|
}
|
|
241
|
+
regex(pattern) {
|
|
242
|
+
return this.pattern(pattern.source);
|
|
243
|
+
}
|
|
225
244
|
pattern(pattern) {
|
|
226
245
|
Object.assign(this.schema, { pattern });
|
|
227
246
|
return this;
|
|
@@ -243,7 +262,6 @@ export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
|
|
|
243
262
|
return this;
|
|
244
263
|
}
|
|
245
264
|
email = () => this.format('email');
|
|
246
|
-
isoDate = () => this.format('date').description('IsoDate'); // todo: make it custom isoDate instead
|
|
247
265
|
url = () => this.format('url');
|
|
248
266
|
ipv4 = () => this.format('ipv4');
|
|
249
267
|
ipv6 = () => this.format('ipv6');
|
|
@@ -260,6 +278,19 @@ export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
|
|
|
260
278
|
branded() {
|
|
261
279
|
return this;
|
|
262
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
283
|
+
*/
|
|
284
|
+
isoDate() {
|
|
285
|
+
return this.format('IsoDate').branded().description('IsoDate');
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
|
|
289
|
+
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
290
|
+
*/
|
|
291
|
+
isoDateTime() {
|
|
292
|
+
return this.format('IsoDateTime').branded().description('IsoDateTime');
|
|
293
|
+
}
|
|
263
294
|
transformModify(t, add) {
|
|
264
295
|
if (add) {
|
|
265
296
|
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>;
|
|
@@ -126,7 +126,6 @@ export declare function _filterEmptyValues<T extends AnyObject>(obj: T, opt?: Mu
|
|
|
126
126
|
*
|
|
127
127
|
* **Note:** This method mutates `object`.
|
|
128
128
|
*
|
|
129
|
-
* @category Object
|
|
130
129
|
* @param target The destination object.
|
|
131
130
|
* @param sources The source objects.
|
|
132
131
|
* @returns Returns `object`.
|
|
@@ -177,7 +176,7 @@ type PropertyPath = Many<PropertyKey>;
|
|
|
177
176
|
* @param obj The object to modify.
|
|
178
177
|
* @param path The path of the property to set.
|
|
179
178
|
* @param value The value to set.
|
|
180
|
-
* @
|
|
179
|
+
* @returns Returns object.
|
|
181
180
|
*
|
|
182
181
|
* Based on: https://stackoverflow.com/a/54733755/4919972
|
|
183
182
|
*/
|
|
@@ -185,7 +184,6 @@ export declare function _set<T extends AnyObject>(obj: T, path: PropertyPath, va
|
|
|
185
184
|
/**
|
|
186
185
|
* Checks if `path` is a direct property of `object` (not null, not undefined).
|
|
187
186
|
*
|
|
188
|
-
* @category Object
|
|
189
187
|
* @param obj The object to query.
|
|
190
188
|
* @param path The path to check.
|
|
191
189
|
* @returns Returns `true` if `path` exists, else `false`.
|
|
@@ -236,7 +236,6 @@ export function _filterEmptyValues(obj, opt = {}) {
|
|
|
236
236
|
*
|
|
237
237
|
* **Note:** This method mutates `object`.
|
|
238
238
|
*
|
|
239
|
-
* @category Object
|
|
240
239
|
* @param target The destination object.
|
|
241
240
|
* @param sources The source objects.
|
|
242
241
|
* @returns Returns `object`.
|
|
@@ -340,7 +339,7 @@ export function _get(obj = {}, path = '') {
|
|
|
340
339
|
return (path
|
|
341
340
|
.replaceAll(/\[([^\]]+)]/g, '.$1')
|
|
342
341
|
.split('.')
|
|
343
|
-
//
|
|
342
|
+
// oxlint-disable-next-line unicorn/no-array-reduce
|
|
344
343
|
.reduce((o, p) => o?.[p], obj));
|
|
345
344
|
}
|
|
346
345
|
/**
|
|
@@ -350,7 +349,7 @@ export function _get(obj = {}, path = '') {
|
|
|
350
349
|
* @param obj The object to modify.
|
|
351
350
|
* @param path The path of the property to set.
|
|
352
351
|
* @param value The value to set.
|
|
353
|
-
* @
|
|
352
|
+
* @returns Returns object.
|
|
354
353
|
*
|
|
355
354
|
* Based on: https://stackoverflow.com/a/54733755/4919972
|
|
356
355
|
*/
|
|
@@ -365,7 +364,7 @@ export function _set(obj, path, value) {
|
|
|
365
364
|
else if (!path.length) {
|
|
366
365
|
return obj;
|
|
367
366
|
}
|
|
368
|
-
//
|
|
367
|
+
// oxlint-disable-next-line unicorn/no-array-reduce
|
|
369
368
|
;
|
|
370
369
|
path.slice(0, -1).reduce((a, c, i) =>
|
|
371
370
|
// biome-ignore lint/style/useConsistentBuiltinInstantiation: ok
|
|
@@ -384,7 +383,6 @@ export function _set(obj, path, value) {
|
|
|
384
383
|
/**
|
|
385
384
|
* Checks if `path` is a direct property of `object` (not null, not undefined).
|
|
386
385
|
*
|
|
387
|
-
* @category Object
|
|
388
386
|
* @param obj The object to query.
|
|
389
387
|
* @param path The path to check.
|
|
390
388
|
* @returns Returns `true` if `path` exists, else `false`.
|
package/dist/promise/pMap.js
CHANGED
|
@@ -85,7 +85,7 @@ export async function pMap(iterable, mapper, opt = {}) {
|
|
|
85
85
|
}
|
|
86
86
|
ret[i] = value;
|
|
87
87
|
resolvingCount--;
|
|
88
|
-
next();
|
|
88
|
+
next(); // oxlint-disable-line no-callback-in-promise
|
|
89
89
|
}, (err) => {
|
|
90
90
|
if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
|
|
91
91
|
isSettled = true;
|
|
@@ -100,7 +100,7 @@ export async function pMap(iterable, mapper, opt = {}) {
|
|
|
100
100
|
logger?.error(err);
|
|
101
101
|
}
|
|
102
102
|
resolvingCount--;
|
|
103
|
-
next();
|
|
103
|
+
next(); // oxlint-disable-line no-callback-in-promise
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
};
|
|
@@ -13,7 +13,8 @@ export function _safeJsonStringify(obj, replacer, spaces, cycleReplacer) {
|
|
|
13
13
|
return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
/* eslint-disable
|
|
16
|
+
/* eslint-disable no-bitwise, no-implicit-coercion */
|
|
17
|
+
// oxlint-disable no-unused-expressions
|
|
17
18
|
function serializer(replacer, cycleReplacer) {
|
|
18
19
|
const stack = [];
|
|
19
20
|
const keys = [];
|
|
@@ -16,7 +16,7 @@ export declare function _lowerFirst(s: string): Uncapitalize<string>;
|
|
|
16
16
|
/**
|
|
17
17
|
* Like String.split(), but with limit, returning the tail together with last element.
|
|
18
18
|
*
|
|
19
|
-
* @
|
|
19
|
+
* @returns Returns the new array of string segments.
|
|
20
20
|
*/
|
|
21
21
|
export declare function _split(str: string, separator: string, limit: number): string[];
|
|
22
22
|
export declare function _removeWhitespace(s: string): string;
|
|
@@ -26,7 +26,7 @@ export function _lowerFirst(s) {
|
|
|
26
26
|
/**
|
|
27
27
|
* Like String.split(), but with limit, returning the tail together with last element.
|
|
28
28
|
*
|
|
29
|
-
* @
|
|
29
|
+
* @returns Returns the new array of string segments.
|
|
30
30
|
*/
|
|
31
31
|
export function _split(str, separator, limit) {
|
|
32
32
|
const parts = str.split(separator);
|
package/dist/typeFest.d.ts
CHANGED
|
@@ -37,8 +37,6 @@ type Filter<KeyType, ExcludeType> = IsEqual<KeyType, ExcludeType> extends true ?
|
|
|
37
37
|
type FooWithoutA = Except<Foo, 'a' | 'c'>;
|
|
38
38
|
//=> {b: string};
|
|
39
39
|
```
|
|
40
|
-
|
|
41
|
-
@category Utilities
|
|
42
40
|
*/
|
|
43
41
|
export type Except<ObjectType, KeysType extends keyof ObjectType> = {
|
|
44
42
|
[KeyType in keyof ObjectType as Filter<KeyType, KeysType>]: ObjectType[KeyType];
|
|
@@ -82,8 +80,6 @@ export type OmitIndexSignature<ObjectType> = {
|
|
|
82
80
|
|
|
83
81
|
const ab: Merge<Foo, Bar> = {a: 1, b: 2};
|
|
84
82
|
```
|
|
85
|
-
|
|
86
|
-
@category Utilities
|
|
87
83
|
*/
|
|
88
84
|
export type Merge<Destination, Source> = {
|
|
89
85
|
[Key in keyof OmitIndexSignature<Destination & Source>]: Key extends keyof Source ? Source[Key] : Key extends keyof Destination ? Destination[Key] : never;
|
|
@@ -109,7 +105,6 @@ export type Merge<Destination, Source> = {
|
|
|
109
105
|
type StringKeysAndUndefined = ConditionalKeys<Example, string | undefined>;
|
|
110
106
|
//=> 'a' | 'c'
|
|
111
107
|
```
|
|
112
|
-
@category Utilities
|
|
113
108
|
*/
|
|
114
109
|
export type ConditionalKeys<Base, Condition> = NonNullable<{
|
|
115
110
|
[Key in keyof Base]: Base[Key] extends Condition ? Key : never;
|
|
@@ -141,7 +136,6 @@ export type ConditionalKeys<Base, Condition> = NonNullable<{
|
|
|
141
136
|
type NonStringKeysOnly = ConditionalExcept<Example, string>;
|
|
142
137
|
//=> {b: string | number; c: () => void; d: {}}
|
|
143
138
|
```
|
|
144
|
-
@category Utilities
|
|
145
139
|
*/
|
|
146
140
|
export type ConditionalExcept<Base, Condition> = Except<Base, ConditionalKeys<Base, Condition>>;
|
|
147
141
|
/**
|
|
@@ -171,7 +165,6 @@ export type ConditionalExcept<Base, Condition> = Except<Base, ConditionalKeys<Ba
|
|
|
171
165
|
type StringKeysOnly = ConditionalPick<Example, string>;
|
|
172
166
|
//=> {a: string}
|
|
173
167
|
```
|
|
174
|
-
@category Utilities
|
|
175
168
|
*/
|
|
176
169
|
export type ConditionalPick<Base, Condition> = Pick<Base, ConditionalKeys<Base, Condition>>;
|
|
177
170
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -310,7 +310,7 @@ export type FalsyValue = false | '' | 0 | null | undefined;
|
|
|
310
310
|
* err.data = {} // can be done, because it was casted
|
|
311
311
|
* }
|
|
312
312
|
*/
|
|
313
|
-
export declare function _typeCast<T>(
|
|
313
|
+
export declare function _typeCast<T>(_v: any): asserts _v is T;
|
|
314
314
|
/**
|
|
315
315
|
* Type-safe Object.assign that checks that part is indeed a Partial<T>
|
|
316
316
|
*/
|
|
@@ -371,8 +371,6 @@ export type Class<T = any> = new (...args: any[]) => T;
|
|
|
371
371
|
data.foo.push('bar');
|
|
372
372
|
//=> error TS2339: Property 'push' does not exist on type 'readonly string[]'
|
|
373
373
|
```
|
|
374
|
-
|
|
375
|
-
@category Utilities
|
|
376
374
|
*/
|
|
377
375
|
export type ReadonlyDeep<T> = T extends Primitive | ((...args: any[]) => unknown) ? T : T extends ReadonlyMap<infer KeyType, infer ValueType> ? ReadonlyMapDeep<KeyType, ValueType> : T extends ReadonlySet<infer ItemType> ? ReadonlySetDeep<ItemType> : T extends object ? ReadonlyObjectDeep<T> : unknown;
|
|
378
376
|
/**
|
package/dist/types.js
CHANGED
|
@@ -59,7 +59,7 @@ export const _objectEntries = Object.entries;
|
|
|
59
59
|
* err.data = {} // can be done, because it was casted
|
|
60
60
|
* }
|
|
61
61
|
*/
|
|
62
|
-
export function _typeCast(
|
|
62
|
+
export function _typeCast(_v) { }
|
|
63
63
|
/**
|
|
64
64
|
* Type-safe Object.assign that checks that part is indeed a Partial<T>
|
|
65
65
|
*/
|
package/package.json
CHANGED
package/src/array/array.util.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { END } from '../types.js'
|
|
|
15
15
|
*
|
|
16
16
|
* @param array The array to process.
|
|
17
17
|
* @param size The length of each chunk.
|
|
18
|
-
* @
|
|
18
|
+
* @returns Returns the new array containing chunks.
|
|
19
19
|
*
|
|
20
20
|
* https://lodash.com/docs#chunk
|
|
21
21
|
*
|
|
@@ -91,8 +91,7 @@ export function _pushUniqBy<T>(a: T[], mapper: Mapper<T, any>, ...items: T[]): T
|
|
|
91
91
|
*/
|
|
92
92
|
export function _uniqBy<T>(arr: readonly T[], mapper: Mapper<T, any>): T[] {
|
|
93
93
|
const map = new Map<any, T>()
|
|
94
|
-
for (
|
|
95
|
-
const item = arr[i]!
|
|
94
|
+
for (const item of arr) {
|
|
96
95
|
const key = item === undefined || item === null ? item : mapper(item)
|
|
97
96
|
if (!map.has(key)) map.set(key, item)
|
|
98
97
|
}
|
|
@@ -121,8 +120,7 @@ export function _uniqBy<T>(arr: readonly T[], mapper: Mapper<T, any>): T[] {
|
|
|
121
120
|
*/
|
|
122
121
|
export function _by<T>(items: readonly T[], mapper: Mapper<T, any>): StringMap<T> {
|
|
123
122
|
const map: StringMap<T> = {}
|
|
124
|
-
for (
|
|
125
|
-
const v = items[i]!
|
|
123
|
+
for (const v of items) {
|
|
126
124
|
const k = mapper(v)
|
|
127
125
|
if (k !== undefined) {
|
|
128
126
|
map[k] = v
|
|
@@ -140,8 +138,7 @@ export function _mapBy<ITEM, KEY>(
|
|
|
140
138
|
mapper: Mapper<ITEM, KEY>,
|
|
141
139
|
): Map<KEY, ITEM> {
|
|
142
140
|
const map = new Map<KEY, ITEM>()
|
|
143
|
-
for (
|
|
144
|
-
const item = items[i]!
|
|
141
|
+
for (const item of items) {
|
|
145
142
|
const key = mapper(item)
|
|
146
143
|
if (key !== undefined) {
|
|
147
144
|
map.set(key, item)
|
|
@@ -164,8 +161,7 @@ export function _mapBy<ITEM, KEY>(
|
|
|
164
161
|
export function _groupBy<T>(items: readonly T[], mapper: Mapper<T, any>): StringMap<T[]> {
|
|
165
162
|
const map: StringMap<T[]> = {}
|
|
166
163
|
|
|
167
|
-
for (
|
|
168
|
-
const item = items[i]!
|
|
164
|
+
for (const item of items) {
|
|
169
165
|
const key = mapper(item)
|
|
170
166
|
if (key !== undefined) {
|
|
171
167
|
;(map[key] ||= []).push(item)
|
|
@@ -531,8 +527,7 @@ export function _maxByOrUndefined<T>(
|
|
|
531
527
|
let maxItem: T | undefined
|
|
532
528
|
let max: number | string | undefined
|
|
533
529
|
|
|
534
|
-
for (
|
|
535
|
-
const item = array[i]!
|
|
530
|
+
for (const item of array) {
|
|
536
531
|
const v = mapper(item)
|
|
537
532
|
if (v !== undefined && (max === undefined || v > max)) {
|
|
538
533
|
maxItem = item
|
|
@@ -551,8 +546,7 @@ export function _minByOrUndefined<T>(
|
|
|
551
546
|
let minItem: T | undefined
|
|
552
547
|
let min: number | string | undefined
|
|
553
548
|
|
|
554
|
-
for (
|
|
555
|
-
const item = array[i]!
|
|
549
|
+
for (const item of array) {
|
|
556
550
|
const v = mapper(item)
|
|
557
551
|
if (v !== undefined && (min === undefined || v < min)) {
|
|
558
552
|
minItem = item
|
|
@@ -36,12 +36,12 @@ export interface AsyncMemoInstance {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Like
|
|
39
|
+
* Like `@_Memo`, but allowing async MemoCache implementation.
|
|
40
40
|
*
|
|
41
|
-
* Implementation is more complex than
|
|
41
|
+
* Implementation is more complex than `@_Memo`, because it needs to handle "in-flight" Promises
|
|
42
42
|
* while waiting for cache to resolve, to prevent "async swarm" issue.
|
|
43
43
|
*
|
|
44
|
-
* @experimental consider normal
|
|
44
|
+
* @experimental consider normal `@_Memo` for most of the cases, it's stable and predictable
|
|
45
45
|
*/
|
|
46
46
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
47
47
|
export const _AsyncMemo =
|
|
@@ -138,7 +138,7 @@ export function _LogMethod(opt: LogMethodOptions = {}): MethodDecorator {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
//
|
|
141
|
+
// oxlint-disable-next-line max-params
|
|
142
142
|
function logFinished(
|
|
143
143
|
logger: CommonLogger,
|
|
144
144
|
callSignature: string,
|
package/src/error/error.util.ts
CHANGED
|
@@ -304,7 +304,7 @@ export interface AppErrorOptions {
|
|
|
304
304
|
* data - optional "any" payload.
|
|
305
305
|
* data.userFriendly - if present, will be displayed to the User as is.
|
|
306
306
|
*
|
|
307
|
-
* Based on: https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801
|
|
307
|
+
* Based on: `https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801`
|
|
308
308
|
*/
|
|
309
309
|
export class AppError<DATA_TYPE extends ErrorData = ErrorData> extends Error {
|
|
310
310
|
data!: DATA_TYPE
|
|
@@ -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,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 type { AnyObject, BaseDBEntity, IsoDate, UnixTimestamp } from '../types.js'
|
|
4
|
+
import type { AnyObject, BaseDBEntity, IsoDate, IsoDateTime, UnixTimestamp } from '../types.js'
|
|
5
5
|
import { JSON_SCHEMA_ORDER } from './jsonSchema.cnst.js'
|
|
6
6
|
import type {
|
|
7
7
|
JsonSchema,
|
|
@@ -77,16 +77,40 @@ export const j = {
|
|
|
77
77
|
unixTimestamp2000() {
|
|
78
78
|
return new JsonSchemaNumberBuilder<UnixTimestamp>().unixTimestamp2000()
|
|
79
79
|
},
|
|
80
|
+
|
|
80
81
|
// string types
|
|
81
82
|
string<T extends string = string>() {
|
|
82
83
|
return new JsonSchemaStringBuilder<T>()
|
|
83
84
|
},
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
88
|
+
*/
|
|
84
89
|
isoDate() {
|
|
85
90
|
return new JsonSchemaStringBuilder<IsoDate>().isoDate()
|
|
86
91
|
},
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
|
|
95
|
+
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
96
|
+
*/
|
|
97
|
+
isoDateTime() {
|
|
98
|
+
return new JsonSchemaStringBuilder<IsoDateTime>().isoDateTime()
|
|
99
|
+
},
|
|
100
|
+
|
|
87
101
|
// email: () => new JsonSchemaStringBuilder().email(),
|
|
88
102
|
// complex types
|
|
89
103
|
object,
|
|
104
|
+
dbEntity<T extends AnyObject>(props: T) {
|
|
105
|
+
return j
|
|
106
|
+
.object<BaseDBEntity>({
|
|
107
|
+
id: j.string(),
|
|
108
|
+
created: j.unixTimestamp2000(),
|
|
109
|
+
updated: j.unixTimestamp2000(),
|
|
110
|
+
})
|
|
111
|
+
.extend(j.object(props))
|
|
112
|
+
},
|
|
113
|
+
|
|
90
114
|
rootObject<T extends AnyObject>(props: {
|
|
91
115
|
[K in keyof T]: JsonSchemaAnyBuilder<T[K]>
|
|
92
116
|
}) {
|
|
@@ -98,10 +122,15 @@ export const j = {
|
|
|
98
122
|
tuple<T extends any[] = unknown[]>(items: JsonSchemaAnyBuilder[]) {
|
|
99
123
|
return new JsonSchemaTupleBuilder<T>(items)
|
|
100
124
|
},
|
|
101
|
-
oneOf<
|
|
102
|
-
|
|
125
|
+
oneOf<Builders extends JsonSchemaAnyBuilder<any, any, any>[]>(
|
|
126
|
+
items: [...Builders],
|
|
127
|
+
): JsonSchemaAnyBuilder<
|
|
128
|
+
Builders[number] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never,
|
|
129
|
+
JsonSchemaOneOf<Builders[number] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never>
|
|
130
|
+
> {
|
|
131
|
+
return new JsonSchemaAnyBuilder({
|
|
103
132
|
oneOf: items.map(b => b.build()),
|
|
104
|
-
})
|
|
133
|
+
}) as any
|
|
105
134
|
},
|
|
106
135
|
allOf<T = unknown>(items: JsonSchemaAnyBuilder[]) {
|
|
107
136
|
return new JsonSchemaAnyBuilder<T, JsonSchemaAllOf<T>>({
|
|
@@ -110,8 +139,11 @@ export const j = {
|
|
|
110
139
|
},
|
|
111
140
|
}
|
|
112
141
|
|
|
113
|
-
export class JsonSchemaAnyBuilder<
|
|
114
|
-
|
|
142
|
+
export class JsonSchemaAnyBuilder<
|
|
143
|
+
T = unknown,
|
|
144
|
+
SCHEMA_TYPE extends JsonSchema<T> = JsonSchema<T>,
|
|
145
|
+
Opt extends boolean = false,
|
|
146
|
+
> implements JsonSchemaBuilder<T>
|
|
115
147
|
{
|
|
116
148
|
constructor(protected schema: SCHEMA_TYPE) {}
|
|
117
149
|
|
|
@@ -162,27 +194,17 @@ export class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T>
|
|
|
162
194
|
return this
|
|
163
195
|
}
|
|
164
196
|
|
|
165
|
-
oneOf(schemas: JsonSchema[]): this {
|
|
166
|
-
Object.assign(this.schema, { oneOf: schemas })
|
|
167
|
-
return this
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
allOf(schemas: JsonSchema[]): this {
|
|
171
|
-
Object.assign(this.schema, { allOf: schemas })
|
|
172
|
-
return this
|
|
173
|
-
}
|
|
174
|
-
|
|
175
197
|
instanceof(of: string): this {
|
|
176
198
|
this.schema.instanceof = of
|
|
177
199
|
return this
|
|
178
200
|
}
|
|
179
201
|
|
|
180
|
-
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined
|
|
181
|
-
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined
|
|
202
|
+
optional(): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>
|
|
203
|
+
optional(optional: true): JsonSchemaAnyBuilder<T | undefined, JsonSchema<T | undefined>, true>
|
|
182
204
|
optional(
|
|
183
205
|
optional: false,
|
|
184
|
-
): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined
|
|
185
|
-
optional(optional = true): JsonSchemaAnyBuilder<any, JsonSchema<any
|
|
206
|
+
): JsonSchemaAnyBuilder<Exclude<T, undefined>, JsonSchema<Exclude<T, undefined>>, false>
|
|
207
|
+
optional(optional = true): JsonSchemaAnyBuilder<any, JsonSchema<any>, false> {
|
|
186
208
|
if (optional) {
|
|
187
209
|
this.schema.optionalField = true
|
|
188
210
|
} else {
|
|
@@ -191,6 +213,12 @@ export class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T>
|
|
|
191
213
|
return this
|
|
192
214
|
}
|
|
193
215
|
|
|
216
|
+
nullable(): JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt> {
|
|
217
|
+
return new JsonSchemaAnyBuilder<T | null, JsonSchema<T | null>, Opt>({
|
|
218
|
+
anyOf: [this.build(), { type: 'null' }],
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
|
|
194
222
|
/**
|
|
195
223
|
* Produces a "clean schema object" without methods.
|
|
196
224
|
* Same as if it would be JSON.stringified.
|
|
@@ -199,8 +227,8 @@ export class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T>
|
|
|
199
227
|
return _sortObject(JSON.parse(JSON.stringify(this.schema)), JSON_SCHEMA_ORDER)
|
|
200
228
|
}
|
|
201
229
|
|
|
202
|
-
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE> {
|
|
203
|
-
return new JsonSchemaAnyBuilder<T, SCHEMA_TYPE>(_deepCopy(this.schema))
|
|
230
|
+
clone(): JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt> {
|
|
231
|
+
return new JsonSchemaAnyBuilder<T, SCHEMA_TYPE, Opt>(_deepCopy(this.schema))
|
|
204
232
|
}
|
|
205
233
|
|
|
206
234
|
/**
|
|
@@ -209,10 +237,10 @@ export class JsonSchemaAnyBuilder<T = unknown, SCHEMA_TYPE extends JsonSchema<T>
|
|
|
209
237
|
infer!: T
|
|
210
238
|
}
|
|
211
239
|
|
|
212
|
-
export class JsonSchemaNumberBuilder<
|
|
213
|
-
T,
|
|
214
|
-
|
|
215
|
-
> {
|
|
240
|
+
export class JsonSchemaNumberBuilder<
|
|
241
|
+
T extends number = number,
|
|
242
|
+
Opt extends boolean = false,
|
|
243
|
+
> extends JsonSchemaAnyBuilder<T, JsonSchemaNumber<T>, Opt> {
|
|
216
244
|
constructor() {
|
|
217
245
|
super({
|
|
218
246
|
type: 'number',
|
|
@@ -282,16 +310,20 @@ export class JsonSchemaNumberBuilder<T extends number = number> extends JsonSche
|
|
|
282
310
|
}
|
|
283
311
|
}
|
|
284
312
|
|
|
285
|
-
export class JsonSchemaStringBuilder<
|
|
286
|
-
T,
|
|
287
|
-
|
|
288
|
-
> {
|
|
313
|
+
export class JsonSchemaStringBuilder<
|
|
314
|
+
T extends string = string,
|
|
315
|
+
Opt extends boolean = false,
|
|
316
|
+
> extends JsonSchemaAnyBuilder<T, JsonSchemaString<T>, Opt> {
|
|
289
317
|
constructor() {
|
|
290
318
|
super({
|
|
291
319
|
type: 'string',
|
|
292
320
|
})
|
|
293
321
|
}
|
|
294
322
|
|
|
323
|
+
regex(pattern: RegExp): this {
|
|
324
|
+
return this.pattern(pattern.source)
|
|
325
|
+
}
|
|
326
|
+
|
|
295
327
|
pattern(pattern: string): this {
|
|
296
328
|
Object.assign(this.schema, { pattern })
|
|
297
329
|
return this
|
|
@@ -318,7 +350,6 @@ export class JsonSchemaStringBuilder<T extends string = string> extends JsonSche
|
|
|
318
350
|
}
|
|
319
351
|
|
|
320
352
|
email = (): this => this.format('email')
|
|
321
|
-
isoDate = (): this => this.format('date').description('IsoDate') // todo: make it custom isoDate instead
|
|
322
353
|
url = (): this => this.format('url')
|
|
323
354
|
ipv4 = (): this => this.format('ipv4')
|
|
324
355
|
ipv6 = (): this => this.format('ipv6')
|
|
@@ -338,6 +369,21 @@ export class JsonSchemaStringBuilder<T extends string = string> extends JsonSche
|
|
|
338
369
|
return this as unknown as JsonSchemaStringBuilder<B>
|
|
339
370
|
}
|
|
340
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Accepts only the `YYYY-MM-DD` shape from all ISO 8601 variants.
|
|
374
|
+
*/
|
|
375
|
+
isoDate(): JsonSchemaStringBuilder<IsoDate> {
|
|
376
|
+
return this.format('IsoDate').branded<IsoDate>().description('IsoDate')
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Accepts strings that start with the `YYYY-MM-DDTHH:MM:SS` shape
|
|
381
|
+
* and optionally end with either a `Z` or a `+/-hh:mm` timezone part.
|
|
382
|
+
*/
|
|
383
|
+
isoDateTime(): JsonSchemaStringBuilder<IsoDateTime> {
|
|
384
|
+
return this.format('IsoDateTime').branded<IsoDateTime>().description('IsoDateTime')
|
|
385
|
+
}
|
|
386
|
+
|
|
341
387
|
private transformModify(t: 'trim' | 'toLowerCase' | 'toUpperCase', add: boolean): this {
|
|
342
388
|
if (add) {
|
|
343
389
|
this.schema.transform = _uniq([...(this.schema.transform || []), t])
|
|
@@ -351,10 +397,10 @@ export class JsonSchemaStringBuilder<T extends string = string> extends JsonSche
|
|
|
351
397
|
// contentEncoding?: string
|
|
352
398
|
}
|
|
353
399
|
|
|
354
|
-
export class JsonSchemaObjectBuilder<
|
|
355
|
-
T,
|
|
356
|
-
|
|
357
|
-
> {
|
|
400
|
+
export class JsonSchemaObjectBuilder<
|
|
401
|
+
T extends AnyObject,
|
|
402
|
+
Opt extends boolean = false,
|
|
403
|
+
> extends JsonSchemaAnyBuilder<T, JsonSchemaObject<T>, Opt> {
|
|
358
404
|
constructor() {
|
|
359
405
|
super({
|
|
360
406
|
type: 'object',
|
|
@@ -418,17 +464,20 @@ export class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSchemaAnyB
|
|
|
418
464
|
return this.addRequired(['id', 'created', 'updated']) as any
|
|
419
465
|
}
|
|
420
466
|
|
|
421
|
-
extend<T2 extends AnyObject>(
|
|
422
|
-
|
|
467
|
+
extend<T2 extends AnyObject>(
|
|
468
|
+
s2: JsonSchemaObjectBuilder<T2>,
|
|
469
|
+
): JsonSchemaObjectBuilder<T & T2 extends infer O ? { [K in keyof O]: O[K] } : never> {
|
|
470
|
+
const builder = new JsonSchemaObjectBuilder<any>()
|
|
423
471
|
Object.assign(builder.schema, _deepCopy(this.schema))
|
|
424
472
|
mergeJsonSchemaObjects(builder.schema, s2.schema)
|
|
425
473
|
return builder
|
|
426
474
|
}
|
|
427
475
|
}
|
|
428
476
|
|
|
429
|
-
export class JsonSchemaArrayBuilder<ITEM> extends JsonSchemaAnyBuilder<
|
|
477
|
+
export class JsonSchemaArrayBuilder<ITEM, Opt extends boolean = false> extends JsonSchemaAnyBuilder<
|
|
430
478
|
ITEM[],
|
|
431
|
-
JsonSchemaArray<ITEM
|
|
479
|
+
JsonSchemaArray<ITEM>,
|
|
480
|
+
Opt
|
|
432
481
|
> {
|
|
433
482
|
constructor(itemsSchema: JsonSchemaBuilder<ITEM>) {
|
|
434
483
|
super({
|
|
@@ -467,16 +516,25 @@ export class JsonSchemaTupleBuilder<T extends any[]> extends JsonSchemaAnyBuilde
|
|
|
467
516
|
}
|
|
468
517
|
}
|
|
469
518
|
|
|
470
|
-
|
|
471
|
-
// The issue is that in `j` we mix two approaches:
|
|
472
|
-
// 1) the builder driven approach
|
|
473
|
-
// 2) the type driven approach.
|
|
474
|
-
|
|
475
|
-
function object<P extends Record<string, JsonSchemaAnyBuilder<any, any>>>(
|
|
519
|
+
function object<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(
|
|
476
520
|
props: P,
|
|
477
|
-
): JsonSchemaObjectBuilder<
|
|
478
|
-
|
|
479
|
-
|
|
521
|
+
): JsonSchemaObjectBuilder<
|
|
522
|
+
{
|
|
523
|
+
[K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer Opt>
|
|
524
|
+
? Opt extends true
|
|
525
|
+
? never
|
|
526
|
+
: K
|
|
527
|
+
: never]: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never
|
|
528
|
+
} & {
|
|
529
|
+
[K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer Opt>
|
|
530
|
+
? Opt extends true
|
|
531
|
+
? K
|
|
532
|
+
: never
|
|
533
|
+
: never]?: P[K] extends JsonSchemaAnyBuilder<infer U, any, any> ? U : never
|
|
534
|
+
} extends infer O
|
|
535
|
+
? { [K in keyof O]: O[K] }
|
|
536
|
+
: never
|
|
537
|
+
>
|
|
480
538
|
function object<T extends AnyObject>(props: {
|
|
481
539
|
[K in keyof T]: JsonSchemaAnyBuilder<T[K]>
|
|
482
540
|
}): JsonSchemaObjectBuilder<T>
|
|
@@ -292,7 +292,6 @@ export function _filterEmptyValues<T extends AnyObject>(obj: T, opt: MutateOptio
|
|
|
292
292
|
*
|
|
293
293
|
* **Note:** This method mutates `object`.
|
|
294
294
|
*
|
|
295
|
-
* @category Object
|
|
296
295
|
* @param target The destination object.
|
|
297
296
|
* @param sources The source objects.
|
|
298
297
|
* @returns Returns `object`.
|
|
@@ -402,7 +401,7 @@ export function _get<T extends AnyObject>(obj = {} as T, path = ''): unknown {
|
|
|
402
401
|
path
|
|
403
402
|
.replaceAll(/\[([^\]]+)]/g, '.$1')
|
|
404
403
|
.split('.')
|
|
405
|
-
//
|
|
404
|
+
// oxlint-disable-next-line unicorn/no-array-reduce
|
|
406
405
|
.reduce((o, p) => o?.[p], obj)
|
|
407
406
|
)
|
|
408
407
|
}
|
|
@@ -417,7 +416,7 @@ type PropertyPath = Many<PropertyKey>
|
|
|
417
416
|
* @param obj The object to modify.
|
|
418
417
|
* @param path The path of the property to set.
|
|
419
418
|
* @param value The value to set.
|
|
420
|
-
* @
|
|
419
|
+
* @returns Returns object.
|
|
421
420
|
*
|
|
422
421
|
* Based on: https://stackoverflow.com/a/54733755/4919972
|
|
423
422
|
*/
|
|
@@ -432,7 +431,7 @@ export function _set<T extends AnyObject>(obj: T, path: PropertyPath, value: any
|
|
|
432
431
|
return obj as any
|
|
433
432
|
}
|
|
434
433
|
|
|
435
|
-
//
|
|
434
|
+
// oxlint-disable-next-line unicorn/no-array-reduce
|
|
436
435
|
;(path as any[]).slice(0, -1).reduce(
|
|
437
436
|
(
|
|
438
437
|
a,
|
|
@@ -458,7 +457,6 @@ export function _set<T extends AnyObject>(obj: T, path: PropertyPath, value: any
|
|
|
458
457
|
/**
|
|
459
458
|
* Checks if `path` is a direct property of `object` (not null, not undefined).
|
|
460
459
|
*
|
|
461
|
-
* @category Object
|
|
462
460
|
* @param obj The object to query.
|
|
463
461
|
* @param path The path to check.
|
|
464
462
|
* @returns Returns `true` if `path` exists, else `false`.
|
package/src/promise/pMap.ts
CHANGED
|
@@ -126,7 +126,7 @@ export async function pMap<IN, OUT>(
|
|
|
126
126
|
|
|
127
127
|
ret[i] = value
|
|
128
128
|
resolvingCount--
|
|
129
|
-
next()
|
|
129
|
+
next() // oxlint-disable-line no-callback-in-promise
|
|
130
130
|
},
|
|
131
131
|
(err: Error) => {
|
|
132
132
|
if (errorMode === ErrorMode.THROW_IMMEDIATELY) {
|
|
@@ -140,7 +140,7 @@ export async function pMap<IN, OUT>(
|
|
|
140
140
|
logger?.error(err)
|
|
141
141
|
}
|
|
142
142
|
resolvingCount--
|
|
143
|
-
next()
|
|
143
|
+
next() // oxlint-disable-line no-callback-in-promise
|
|
144
144
|
}
|
|
145
145
|
},
|
|
146
146
|
)
|
|
@@ -20,8 +20,8 @@ export function _safeJsonStringify(
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/* eslint-disable
|
|
24
|
-
|
|
23
|
+
/* eslint-disable no-bitwise, no-implicit-coercion */
|
|
24
|
+
// oxlint-disable no-unused-expressions
|
|
25
25
|
function serializer(replacer?: Reviver, cycleReplacer?: Reviver): Reviver {
|
|
26
26
|
const stack: any[] = []
|
|
27
27
|
const keys: string[] = []
|
|
@@ -31,7 +31,7 @@ export function _lowerFirst(s: string): Uncapitalize<string> {
|
|
|
31
31
|
/**
|
|
32
32
|
* Like String.split(), but with limit, returning the tail together with last element.
|
|
33
33
|
*
|
|
34
|
-
* @
|
|
34
|
+
* @returns Returns the new array of string segments.
|
|
35
35
|
*/
|
|
36
36
|
export function _split(str: string, separator: string, limit: number): string[] {
|
|
37
37
|
const parts = str.split(separator)
|
package/src/typeFest.ts
CHANGED
|
@@ -42,8 +42,6 @@ type Filter<KeyType, ExcludeType> =
|
|
|
42
42
|
type FooWithoutA = Except<Foo, 'a' | 'c'>;
|
|
43
43
|
//=> {b: string};
|
|
44
44
|
```
|
|
45
|
-
|
|
46
|
-
@category Utilities
|
|
47
45
|
*/
|
|
48
46
|
export type Except<ObjectType, KeysType extends keyof ObjectType> = {
|
|
49
47
|
[KeyType in keyof ObjectType as Filter<KeyType, KeysType>]: ObjectType[KeyType]
|
|
@@ -94,8 +92,6 @@ export type OmitIndexSignature<ObjectType> = {
|
|
|
94
92
|
|
|
95
93
|
const ab: Merge<Foo, Bar> = {a: 1, b: 2};
|
|
96
94
|
```
|
|
97
|
-
|
|
98
|
-
@category Utilities
|
|
99
95
|
*/
|
|
100
96
|
export type Merge<Destination, Source> = {
|
|
101
97
|
[Key in keyof OmitIndexSignature<Destination & Source>]: Key extends keyof Source
|
|
@@ -126,7 +122,6 @@ export type Merge<Destination, Source> = {
|
|
|
126
122
|
type StringKeysAndUndefined = ConditionalKeys<Example, string | undefined>;
|
|
127
123
|
//=> 'a' | 'c'
|
|
128
124
|
```
|
|
129
|
-
@category Utilities
|
|
130
125
|
*/
|
|
131
126
|
export type ConditionalKeys<Base, Condition> = NonNullable<
|
|
132
127
|
// Wrap in `NonNullable` to strip away the `undefined` type from the produced union.
|
|
@@ -169,7 +164,6 @@ export type ConditionalKeys<Base, Condition> = NonNullable<
|
|
|
169
164
|
type NonStringKeysOnly = ConditionalExcept<Example, string>;
|
|
170
165
|
//=> {b: string | number; c: () => void; d: {}}
|
|
171
166
|
```
|
|
172
|
-
@category Utilities
|
|
173
167
|
*/
|
|
174
168
|
export type ConditionalExcept<Base, Condition> = Except<Base, ConditionalKeys<Base, Condition>>
|
|
175
169
|
|
|
@@ -200,7 +194,6 @@ export type ConditionalExcept<Base, Condition> = Except<Base, ConditionalKeys<Ba
|
|
|
200
194
|
type StringKeysOnly = ConditionalPick<Example, string>;
|
|
201
195
|
//=> {a: string}
|
|
202
196
|
```
|
|
203
|
-
@category Utilities
|
|
204
197
|
*/
|
|
205
198
|
export type ConditionalPick<Base, Condition> = Pick<Base, ConditionalKeys<Base, Condition>>
|
|
206
199
|
|
package/src/types.ts
CHANGED
|
@@ -396,7 +396,7 @@ export type FalsyValue = false | '' | 0 | null | undefined
|
|
|
396
396
|
* err.data = {} // can be done, because it was casted
|
|
397
397
|
* }
|
|
398
398
|
*/
|
|
399
|
-
export function _typeCast<T>(
|
|
399
|
+
export function _typeCast<T>(_v: any): asserts _v is T {}
|
|
400
400
|
|
|
401
401
|
/**
|
|
402
402
|
* Type-safe Object.assign that checks that part is indeed a Partial<T>
|
|
@@ -469,8 +469,6 @@ export type Class<T = any> = new (...args: any[]) => T
|
|
|
469
469
|
data.foo.push('bar');
|
|
470
470
|
//=> error TS2339: Property 'push' does not exist on type 'readonly string[]'
|
|
471
471
|
```
|
|
472
|
-
|
|
473
|
-
@category Utilities
|
|
474
472
|
*/
|
|
475
473
|
/* eslint-disable @typescript-eslint/no-restricted-types */
|
|
476
474
|
export type ReadonlyDeep<T> = T extends Primitive | ((...args: any[]) => unknown)
|