n4s 3.0.0 → 4.0.0-dev-1aae50
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/CHANGELOG.md +129 -0
- package/LICENSE +1 -2
- package/README.md +2 -5
- package/compose/package.json +7 -0
- package/compounds/package.json +7 -0
- package/dist/cjs/compose.development.js +139 -0
- package/dist/cjs/compose.js +7 -0
- package/dist/cjs/compose.production.js +1 -0
- package/dist/cjs/compounds.development.js +132 -0
- package/dist/cjs/compounds.js +7 -0
- package/dist/cjs/compounds.production.js +1 -0
- package/dist/cjs/n4s.development.js +602 -0
- package/dist/cjs/n4s.js +7 -0
- package/dist/cjs/n4s.production.js +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/schema.development.js +144 -0
- package/dist/cjs/schema.js +7 -0
- package/dist/cjs/schema.production.js +1 -0
- package/dist/es/compose.development.js +137 -0
- package/dist/es/compose.production.js +1 -0
- package/dist/es/compounds.development.js +130 -0
- package/dist/es/compounds.production.js +1 -0
- package/dist/es/n4s.development.js +597 -0
- package/dist/es/n4s.production.js +1 -0
- package/dist/es/package.json +1 -0
- package/dist/es/schema.development.js +140 -0
- package/dist/es/schema.production.js +1 -0
- package/dist/umd/compose.development.js +143 -0
- package/dist/umd/compose.production.js +1 -0
- package/dist/umd/compounds.development.js +136 -0
- package/dist/umd/compounds.production.js +1 -0
- package/dist/umd/n4s.development.js +606 -0
- package/dist/umd/n4s.production.js +1 -0
- package/dist/umd/schema.development.js +148 -0
- package/dist/umd/schema.production.js +1 -0
- package/docs/README.md +2 -5
- package/docs/_sidebar.md +1 -2
- package/docs/external.md +1 -28
- package/docs/rules.md +28 -0
- package/package.json +129 -42
- package/schema/package.json +7 -0
- package/tsconfig.json +8 -0
- package/types/compose.d.ts +134 -0
- package/types/compounds.d.ts +146 -0
- package/types/n4s.d.ts +167 -0
- package/types/schema.d.ts +151 -0
- package/config/jest/jest.setup.js +0 -14
- package/config/rollup/enforce.js +0 -8
- package/config/rollup/rollup.config.js +0 -3
- package/docs/compound.md +0 -187
- package/docs/custom.md +0 -52
- package/docs/template.md +0 -53
- package/esm/n4s.mjs.development.js +0 -1101
- package/esm/n4s.mjs.production.js +0 -1101
- package/esm/n4s.mjs.production.min.js +0 -1
- package/esm/package.json +0 -1
- package/jest.config.js +0 -3
- package/n4s.cjs.development.js +0 -1103
- package/n4s.cjs.production.js +0 -1103
- package/n4s.cjs.production.min.js +0 -1
- package/n4s.js +0 -7
- package/n4s.umd.development.js +0 -1109
- package/n4s.umd.production.js +0 -1192
- package/n4s.umd.production.min.js +0 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
type DropFirst<T extends unknown[]> = T extends [
|
|
2
|
+
unknown,
|
|
3
|
+
...infer U
|
|
4
|
+
] ? U : never;
|
|
5
|
+
type TStringable = string | ((...args: any[]) => string);
|
|
6
|
+
type TRuleReturn = boolean | {
|
|
7
|
+
pass: boolean;
|
|
8
|
+
message?: TStringable;
|
|
9
|
+
};
|
|
10
|
+
type TRuleDetailedResult = {
|
|
11
|
+
pass: boolean;
|
|
12
|
+
message?: string;
|
|
13
|
+
};
|
|
14
|
+
type TArgs = any[];
|
|
15
|
+
type TBaseRules = typeof baseRules;
|
|
16
|
+
type KBaseRules = keyof TBaseRules;
|
|
17
|
+
declare function condition(value: any, callback: (value: any) => TRuleReturn): TRuleReturn;
|
|
18
|
+
declare function endsWith(value: string, arg1: string): boolean;
|
|
19
|
+
declare function equals(value: unknown, arg1: unknown): boolean;
|
|
20
|
+
declare function greaterThan(value: number | string, gt: number | string): boolean;
|
|
21
|
+
declare function greaterThanOrEquals(value: string | number, gte: string | number): boolean;
|
|
22
|
+
declare function inside(value: unknown, arg1: string | unknown[]): boolean;
|
|
23
|
+
// The module is named "isArrayValue" since it
|
|
24
|
+
// is conflicting with a nested npm dependency.
|
|
25
|
+
// We may need to revisit this in the future.
|
|
26
|
+
declare function isArray(value: unknown): value is Array<unknown>;
|
|
27
|
+
declare function isBetween(value: number | string, min: number | string, max: number | string): boolean;
|
|
28
|
+
declare function isBlank(value: unknown): boolean;
|
|
29
|
+
declare function isBoolean(value: unknown): value is boolean;
|
|
30
|
+
declare function isEmpty(value: unknown): boolean;
|
|
31
|
+
declare function isNaN(value: unknown): boolean;
|
|
32
|
+
declare function isNegative(value: number | string): boolean;
|
|
33
|
+
declare function isNull(value: unknown): value is null;
|
|
34
|
+
declare function isNullish(value: any): value is null | undefined;
|
|
35
|
+
declare function isNumber(value: unknown): value is number;
|
|
36
|
+
declare function isNumeric(value: string | number): boolean;
|
|
37
|
+
declare function isStringValue(v: unknown): v is string;
|
|
38
|
+
declare function isTruthy(value: unknown): boolean;
|
|
39
|
+
declare function isUndefined(value?: unknown): boolean;
|
|
40
|
+
declare function lengthEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
41
|
+
declare function lessThan(value: string | number, lt: string | number): boolean;
|
|
42
|
+
declare function lessThanOrEquals(value: string | number, lte: string | number): boolean;
|
|
43
|
+
declare function longerThan(value: string | unknown[], arg1: string | number): boolean;
|
|
44
|
+
declare function longerThanOrEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
45
|
+
declare function matches(value: string, regex: RegExp | string): boolean;
|
|
46
|
+
declare function numberEquals(value: string | number, eq: string | number): boolean;
|
|
47
|
+
declare function shorterThan(value: string | unknown[], arg1: string | number): boolean;
|
|
48
|
+
declare function shorterThanOrEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
49
|
+
declare function startsWith(value: string, arg1: string): boolean;
|
|
50
|
+
declare const baseRules: {
|
|
51
|
+
condition: typeof condition;
|
|
52
|
+
doesNotEndWith: (value: string, arg1: string) => boolean;
|
|
53
|
+
doesNotStartWith: (value: string, arg1: string) => boolean;
|
|
54
|
+
endsWith: typeof endsWith;
|
|
55
|
+
equals: typeof equals;
|
|
56
|
+
greaterThan: typeof greaterThan;
|
|
57
|
+
greaterThanOrEquals: typeof greaterThanOrEquals;
|
|
58
|
+
gt: typeof greaterThan;
|
|
59
|
+
gte: typeof greaterThanOrEquals;
|
|
60
|
+
inside: typeof inside;
|
|
61
|
+
isArray: typeof isArray;
|
|
62
|
+
isBetween: typeof isBetween;
|
|
63
|
+
isBlank: typeof isBlank;
|
|
64
|
+
isBoolean: typeof isBoolean;
|
|
65
|
+
isEmpty: typeof isEmpty;
|
|
66
|
+
isEven: (value: any) => boolean;
|
|
67
|
+
isFalsy: (value: unknown) => boolean;
|
|
68
|
+
isNaN: typeof isNaN;
|
|
69
|
+
isNegative: typeof isNegative;
|
|
70
|
+
isNotArray: (value: unknown) => boolean;
|
|
71
|
+
isNotBetween: (value: string | number, min: string | number, max: string | number) => boolean;
|
|
72
|
+
isNotBlank: (value: unknown) => boolean;
|
|
73
|
+
isNotBoolean: (value: unknown) => boolean;
|
|
74
|
+
isNotEmpty: (value: unknown) => boolean;
|
|
75
|
+
isNotNaN: (value: unknown) => boolean;
|
|
76
|
+
isNotNull: (value: unknown) => boolean;
|
|
77
|
+
isNotNullish: (value: any) => boolean;
|
|
78
|
+
isNotNumber: (value: unknown) => boolean;
|
|
79
|
+
isNotNumeric: (value: string | number) => boolean;
|
|
80
|
+
isNotString: (v: unknown) => boolean;
|
|
81
|
+
isNotUndefined: (value?: unknown) => boolean;
|
|
82
|
+
isNull: typeof isNull;
|
|
83
|
+
isNullish: typeof isNullish;
|
|
84
|
+
isNumber: typeof isNumber;
|
|
85
|
+
isNumeric: typeof isNumeric;
|
|
86
|
+
isOdd: (value: any) => boolean;
|
|
87
|
+
isPositive: (value: string | number) => boolean;
|
|
88
|
+
isString: typeof isStringValue;
|
|
89
|
+
isTruthy: typeof isTruthy;
|
|
90
|
+
isUndefined: typeof isUndefined;
|
|
91
|
+
lengthEquals: typeof lengthEquals;
|
|
92
|
+
lengthNotEquals: (value: string | unknown[], arg1: string | number) => boolean;
|
|
93
|
+
lessThan: typeof lessThan;
|
|
94
|
+
lessThanOrEquals: typeof lessThanOrEquals;
|
|
95
|
+
longerThan: typeof longerThan;
|
|
96
|
+
longerThanOrEquals: typeof longerThanOrEquals;
|
|
97
|
+
lt: typeof lessThan;
|
|
98
|
+
lte: typeof lessThanOrEquals;
|
|
99
|
+
matches: typeof matches;
|
|
100
|
+
notEquals: (value: unknown, arg1: unknown) => boolean;
|
|
101
|
+
notInside: (value: unknown, arg1: string | unknown[]) => boolean;
|
|
102
|
+
notMatches: (value: string, regex: string | RegExp) => boolean;
|
|
103
|
+
numberEquals: typeof numberEquals;
|
|
104
|
+
numberNotEquals: (value: string | number, eq: string | number) => boolean;
|
|
105
|
+
shorterThan: typeof shorterThan;
|
|
106
|
+
shorterThanOrEquals: typeof shorterThanOrEquals;
|
|
107
|
+
startsWith: typeof startsWith;
|
|
108
|
+
};
|
|
109
|
+
type TRules<E = Record<string, unknown>> = n4s.EnforceCustomMatchers<TRules<E> & E> & Record<string, (...args: TArgs) => TRules<E> & E> & {
|
|
110
|
+
[P in KBaseRules]: (...args: DropFirst<Parameters<TBaseRules[P]>> | TArgs) => TRules<E> & E;
|
|
111
|
+
};
|
|
112
|
+
/* eslint-disable @typescript-eslint/no-namespace, @typescript-eslint/no-empty-interface */
|
|
113
|
+
declare global {
|
|
114
|
+
namespace n4s {
|
|
115
|
+
interface IRules<E> extends TRules<E> {
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
type TLazyRules = n4s.IRules<TLazyRuleMethods>;
|
|
120
|
+
type TLazy = TLazyRules & TLazyRuleMethods &
|
|
121
|
+
// This is a "catch all" hack to make TS happy while not
|
|
122
|
+
// losing type hints
|
|
123
|
+
Record<string, (...args: any[]) => any>;
|
|
124
|
+
type TLazyRuleMethods = TLazyRuleRunners & {
|
|
125
|
+
message: (message: TLazyMessage) => TLazy;
|
|
126
|
+
};
|
|
127
|
+
type TLazyRuleRunners = {
|
|
128
|
+
test: (value: unknown) => boolean;
|
|
129
|
+
run: (value: unknown) => TRuleDetailedResult;
|
|
130
|
+
};
|
|
131
|
+
type TLazyMessage = string | ((value: unknown, originalMessage?: TStringable) => string);
|
|
132
|
+
declare function allOf(value: unknown, ...rules: TLazy[]): TRuleDetailedResult;
|
|
133
|
+
declare function anyOf(value: unknown, ...rules: TLazy[]): TRuleDetailedResult;
|
|
134
|
+
declare function noneOf(value: unknown, ...rules: TLazy[]): TRuleDetailedResult;
|
|
135
|
+
declare function oneOf(value: unknown, ...rules: TLazy[]): TRuleDetailedResult;
|
|
136
|
+
declare global {
|
|
137
|
+
namespace n4s {
|
|
138
|
+
interface EnforceCustomMatchers<R> {
|
|
139
|
+
allOf: (...args: DropFirst<Parameters<typeof allOf>>) => R;
|
|
140
|
+
anyOf: (...args: DropFirst<Parameters<typeof anyOf>>) => R;
|
|
141
|
+
noneOf: (...args: DropFirst<Parameters<typeof noneOf>>) => R;
|
|
142
|
+
oneOf: (...args: DropFirst<Parameters<typeof oneOf>>) => R;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export {};
|
package/types/n4s.d.ts
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
declare const ctx: {
|
|
2
|
+
run: <R>(ctxRef: Partial<CTXType>, fn: (context: CTXType) => R) => R;
|
|
3
|
+
bind: <Fn extends (...args: any[]) => any>(ctxRef: Partial<CTXType>, fn: Fn) => Fn;
|
|
4
|
+
use: () => CTXType | undefined;
|
|
5
|
+
useX: (errorMessage?: string | undefined) => CTXType;
|
|
6
|
+
};
|
|
7
|
+
type CTXType = {
|
|
8
|
+
meta: Record<string, any>;
|
|
9
|
+
value: any;
|
|
10
|
+
set?: boolean;
|
|
11
|
+
parent: () => CTXType | null;
|
|
12
|
+
};
|
|
13
|
+
type TEnforceContext = null | {
|
|
14
|
+
meta: Record<string, any>;
|
|
15
|
+
value: any;
|
|
16
|
+
parent: () => TEnforceContext;
|
|
17
|
+
};
|
|
18
|
+
type DropFirst<T extends unknown[]> = T extends [
|
|
19
|
+
unknown,
|
|
20
|
+
...infer U
|
|
21
|
+
] ? U : never;
|
|
22
|
+
type TStringable = string | ((...args: any[]) => string);
|
|
23
|
+
type TRuleReturn = boolean | {
|
|
24
|
+
pass: boolean;
|
|
25
|
+
message?: TStringable;
|
|
26
|
+
};
|
|
27
|
+
type TRuleDetailedResult = {
|
|
28
|
+
pass: boolean;
|
|
29
|
+
message?: string;
|
|
30
|
+
};
|
|
31
|
+
type TArgs = any[];
|
|
32
|
+
type TRuleValue = any;
|
|
33
|
+
type TRuleBase = (value: TRuleValue, ...args: TArgs) => TRuleReturn;
|
|
34
|
+
type TRule = Record<string, TRuleBase>;
|
|
35
|
+
type TBaseRules = typeof baseRules;
|
|
36
|
+
type KBaseRules = keyof TBaseRules;
|
|
37
|
+
declare function condition(value: any, callback: (value: any) => TRuleReturn): TRuleReturn;
|
|
38
|
+
declare function endsWith(value: string, arg1: string): boolean;
|
|
39
|
+
declare function equals(value: unknown, arg1: unknown): boolean;
|
|
40
|
+
declare function greaterThan(value: number | string, gt: number | string): boolean;
|
|
41
|
+
declare function greaterThanOrEquals(value: string | number, gte: string | number): boolean;
|
|
42
|
+
declare function inside(value: unknown, arg1: string | unknown[]): boolean;
|
|
43
|
+
// The module is named "isArrayValue" since it
|
|
44
|
+
// is conflicting with a nested npm dependency.
|
|
45
|
+
// We may need to revisit this in the future.
|
|
46
|
+
declare function isArray(value: unknown): value is Array<unknown>;
|
|
47
|
+
declare function isBetween(value: number | string, min: number | string, max: number | string): boolean;
|
|
48
|
+
declare function isBlank(value: unknown): boolean;
|
|
49
|
+
declare function isBoolean(value: unknown): value is boolean;
|
|
50
|
+
declare function isEmpty(value: unknown): boolean;
|
|
51
|
+
declare function isNaN(value: unknown): boolean;
|
|
52
|
+
declare function isNegative(value: number | string): boolean;
|
|
53
|
+
declare function isNull(value: unknown): value is null;
|
|
54
|
+
declare function isNullish(value: any): value is null | undefined;
|
|
55
|
+
declare function isNumber(value: unknown): value is number;
|
|
56
|
+
declare function isNumeric(value: string | number): boolean;
|
|
57
|
+
declare function isStringValue(v: unknown): v is string;
|
|
58
|
+
declare function isTruthy(value: unknown): boolean;
|
|
59
|
+
declare function isUndefined(value?: unknown): boolean;
|
|
60
|
+
declare function lengthEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
61
|
+
declare function lessThan(value: string | number, lt: string | number): boolean;
|
|
62
|
+
declare function lessThanOrEquals(value: string | number, lte: string | number): boolean;
|
|
63
|
+
declare function longerThan(value: string | unknown[], arg1: string | number): boolean;
|
|
64
|
+
declare function longerThanOrEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
65
|
+
declare function matches(value: string, regex: RegExp | string): boolean;
|
|
66
|
+
declare function numberEquals(value: string | number, eq: string | number): boolean;
|
|
67
|
+
declare function shorterThan(value: string | unknown[], arg1: string | number): boolean;
|
|
68
|
+
declare function shorterThanOrEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
69
|
+
declare function startsWith(value: string, arg1: string): boolean;
|
|
70
|
+
declare const baseRules: {
|
|
71
|
+
condition: typeof condition;
|
|
72
|
+
doesNotEndWith: (value: string, arg1: string) => boolean;
|
|
73
|
+
doesNotStartWith: (value: string, arg1: string) => boolean;
|
|
74
|
+
endsWith: typeof endsWith;
|
|
75
|
+
equals: typeof equals;
|
|
76
|
+
greaterThan: typeof greaterThan;
|
|
77
|
+
greaterThanOrEquals: typeof greaterThanOrEquals;
|
|
78
|
+
gt: typeof greaterThan;
|
|
79
|
+
gte: typeof greaterThanOrEquals;
|
|
80
|
+
inside: typeof inside;
|
|
81
|
+
isArray: typeof isArray;
|
|
82
|
+
isBetween: typeof isBetween;
|
|
83
|
+
isBlank: typeof isBlank;
|
|
84
|
+
isBoolean: typeof isBoolean;
|
|
85
|
+
isEmpty: typeof isEmpty;
|
|
86
|
+
isEven: (value: any) => boolean;
|
|
87
|
+
isFalsy: (value: unknown) => boolean;
|
|
88
|
+
isNaN: typeof isNaN;
|
|
89
|
+
isNegative: typeof isNegative;
|
|
90
|
+
isNotArray: (value: unknown) => boolean;
|
|
91
|
+
isNotBetween: (value: string | number, min: string | number, max: string | number) => boolean;
|
|
92
|
+
isNotBlank: (value: unknown) => boolean;
|
|
93
|
+
isNotBoolean: (value: unknown) => boolean;
|
|
94
|
+
isNotEmpty: (value: unknown) => boolean;
|
|
95
|
+
isNotNaN: (value: unknown) => boolean;
|
|
96
|
+
isNotNull: (value: unknown) => boolean;
|
|
97
|
+
isNotNullish: (value: any) => boolean;
|
|
98
|
+
isNotNumber: (value: unknown) => boolean;
|
|
99
|
+
isNotNumeric: (value: string | number) => boolean;
|
|
100
|
+
isNotString: (v: unknown) => boolean;
|
|
101
|
+
isNotUndefined: (value?: unknown) => boolean;
|
|
102
|
+
isNull: typeof isNull;
|
|
103
|
+
isNullish: typeof isNullish;
|
|
104
|
+
isNumber: typeof isNumber;
|
|
105
|
+
isNumeric: typeof isNumeric;
|
|
106
|
+
isOdd: (value: any) => boolean;
|
|
107
|
+
isPositive: (value: string | number) => boolean;
|
|
108
|
+
isString: typeof isStringValue;
|
|
109
|
+
isTruthy: typeof isTruthy;
|
|
110
|
+
isUndefined: typeof isUndefined;
|
|
111
|
+
lengthEquals: typeof lengthEquals;
|
|
112
|
+
lengthNotEquals: (value: string | unknown[], arg1: string | number) => boolean;
|
|
113
|
+
lessThan: typeof lessThan;
|
|
114
|
+
lessThanOrEquals: typeof lessThanOrEquals;
|
|
115
|
+
longerThan: typeof longerThan;
|
|
116
|
+
longerThanOrEquals: typeof longerThanOrEquals;
|
|
117
|
+
lt: typeof lessThan;
|
|
118
|
+
lte: typeof lessThanOrEquals;
|
|
119
|
+
matches: typeof matches;
|
|
120
|
+
notEquals: (value: unknown, arg1: unknown) => boolean;
|
|
121
|
+
notInside: (value: unknown, arg1: string | unknown[]) => boolean;
|
|
122
|
+
notMatches: (value: string, regex: string | RegExp) => boolean;
|
|
123
|
+
numberEquals: typeof numberEquals;
|
|
124
|
+
numberNotEquals: (value: string | number, eq: string | number) => boolean;
|
|
125
|
+
shorterThan: typeof shorterThan;
|
|
126
|
+
shorterThanOrEquals: typeof shorterThanOrEquals;
|
|
127
|
+
startsWith: typeof startsWith;
|
|
128
|
+
};
|
|
129
|
+
type TRules<E = Record<string, unknown>> = n4s.EnforceCustomMatchers<TRules<E> & E> & Record<string, (...args: TArgs) => TRules<E> & E> & {
|
|
130
|
+
[P in KBaseRules]: (...args: DropFirst<Parameters<TBaseRules[P]>> | TArgs) => TRules<E> & E;
|
|
131
|
+
};
|
|
132
|
+
/* eslint-disable @typescript-eslint/no-namespace, @typescript-eslint/no-empty-interface */
|
|
133
|
+
declare global {
|
|
134
|
+
namespace n4s {
|
|
135
|
+
interface IRules<E> extends TRules<E> {
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
type IRules = n4s.IRules<Record<string, any>>;
|
|
140
|
+
declare function enforceEager(value: TRuleValue): IRules;
|
|
141
|
+
type TEnforceEager = typeof enforceEager;
|
|
142
|
+
type TLazyRules = n4s.IRules<TLazyRuleMethods>;
|
|
143
|
+
type TLazy = TLazyRules & TLazyRuleMethods &
|
|
144
|
+
// This is a "catch all" hack to make TS happy while not
|
|
145
|
+
// losing type hints
|
|
146
|
+
Record<string, (...args: any[]) => any>;
|
|
147
|
+
type TLazyRuleMethods = TLazyRuleRunners & {
|
|
148
|
+
message: (message: TLazyMessage) => TLazy;
|
|
149
|
+
};
|
|
150
|
+
type TLazyRuleRunners = {
|
|
151
|
+
test: (value: unknown) => boolean;
|
|
152
|
+
run: (value: unknown) => TRuleDetailedResult;
|
|
153
|
+
};
|
|
154
|
+
type TLazyMessage = string | ((value: unknown, originalMessage?: TStringable) => string);
|
|
155
|
+
declare const enforce: TEnforce;
|
|
156
|
+
type TEnforce = TEnforceMethods & TLazyRules & TEnforceEager;
|
|
157
|
+
type TEnforceMethods = {
|
|
158
|
+
context: () => TEnforceContext;
|
|
159
|
+
extend: (customRules: TRule) => void;
|
|
160
|
+
};
|
|
161
|
+
declare global {
|
|
162
|
+
namespace n4s {
|
|
163
|
+
interface EnforceCustomMatchers<R> {
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export { enforce, ctx };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
type DropFirst<T extends unknown[]> = T extends [
|
|
2
|
+
unknown,
|
|
3
|
+
...infer U
|
|
4
|
+
] ? U : never;
|
|
5
|
+
type TStringable = string | ((...args: any[]) => string);
|
|
6
|
+
type TRuleReturn = boolean | {
|
|
7
|
+
pass: boolean;
|
|
8
|
+
message?: TStringable;
|
|
9
|
+
};
|
|
10
|
+
type TRuleDetailedResult = {
|
|
11
|
+
pass: boolean;
|
|
12
|
+
message?: string;
|
|
13
|
+
};
|
|
14
|
+
type TArgs = any[];
|
|
15
|
+
type TBaseRules = typeof baseRules;
|
|
16
|
+
type KBaseRules = keyof TBaseRules;
|
|
17
|
+
declare function condition(value: any, callback: (value: any) => TRuleReturn): TRuleReturn;
|
|
18
|
+
declare function endsWith(value: string, arg1: string): boolean;
|
|
19
|
+
declare function equals(value: unknown, arg1: unknown): boolean;
|
|
20
|
+
declare function greaterThan(value: number | string, gt: number | string): boolean;
|
|
21
|
+
declare function greaterThanOrEquals(value: string | number, gte: string | number): boolean;
|
|
22
|
+
declare function inside(value: unknown, arg1: string | unknown[]): boolean;
|
|
23
|
+
// The module is named "isArrayValue" since it
|
|
24
|
+
// is conflicting with a nested npm dependency.
|
|
25
|
+
// We may need to revisit this in the future.
|
|
26
|
+
declare function isArray(value: unknown): value is Array<unknown>;
|
|
27
|
+
declare function isBetween(value: number | string, min: number | string, max: number | string): boolean;
|
|
28
|
+
declare function isBlank(value: unknown): boolean;
|
|
29
|
+
declare function isBoolean(value: unknown): value is boolean;
|
|
30
|
+
declare function isEmpty(value: unknown): boolean;
|
|
31
|
+
declare function isNaN(value: unknown): boolean;
|
|
32
|
+
declare function isNegative(value: number | string): boolean;
|
|
33
|
+
declare function isNull(value: unknown): value is null;
|
|
34
|
+
declare function isNullish(value: any): value is null | undefined;
|
|
35
|
+
declare function isNumber(value: unknown): value is number;
|
|
36
|
+
declare function isNumeric(value: string | number): boolean;
|
|
37
|
+
declare function isStringValue(v: unknown): v is string;
|
|
38
|
+
declare function isTruthy(value: unknown): boolean;
|
|
39
|
+
declare function isUndefined(value?: unknown): boolean;
|
|
40
|
+
declare function lengthEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
41
|
+
declare function lessThan(value: string | number, lt: string | number): boolean;
|
|
42
|
+
declare function lessThanOrEquals(value: string | number, lte: string | number): boolean;
|
|
43
|
+
declare function longerThan(value: string | unknown[], arg1: string | number): boolean;
|
|
44
|
+
declare function longerThanOrEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
45
|
+
declare function matches(value: string, regex: RegExp | string): boolean;
|
|
46
|
+
declare function numberEquals(value: string | number, eq: string | number): boolean;
|
|
47
|
+
declare function shorterThan(value: string | unknown[], arg1: string | number): boolean;
|
|
48
|
+
declare function shorterThanOrEquals(value: string | unknown[], arg1: string | number): boolean;
|
|
49
|
+
declare function startsWith(value: string, arg1: string): boolean;
|
|
50
|
+
declare const baseRules: {
|
|
51
|
+
condition: typeof condition;
|
|
52
|
+
doesNotEndWith: (value: string, arg1: string) => boolean;
|
|
53
|
+
doesNotStartWith: (value: string, arg1: string) => boolean;
|
|
54
|
+
endsWith: typeof endsWith;
|
|
55
|
+
equals: typeof equals;
|
|
56
|
+
greaterThan: typeof greaterThan;
|
|
57
|
+
greaterThanOrEquals: typeof greaterThanOrEquals;
|
|
58
|
+
gt: typeof greaterThan;
|
|
59
|
+
gte: typeof greaterThanOrEquals;
|
|
60
|
+
inside: typeof inside;
|
|
61
|
+
isArray: typeof isArray;
|
|
62
|
+
isBetween: typeof isBetween;
|
|
63
|
+
isBlank: typeof isBlank;
|
|
64
|
+
isBoolean: typeof isBoolean;
|
|
65
|
+
isEmpty: typeof isEmpty;
|
|
66
|
+
isEven: (value: any) => boolean;
|
|
67
|
+
isFalsy: (value: unknown) => boolean;
|
|
68
|
+
isNaN: typeof isNaN;
|
|
69
|
+
isNegative: typeof isNegative;
|
|
70
|
+
isNotArray: (value: unknown) => boolean;
|
|
71
|
+
isNotBetween: (value: string | number, min: string | number, max: string | number) => boolean;
|
|
72
|
+
isNotBlank: (value: unknown) => boolean;
|
|
73
|
+
isNotBoolean: (value: unknown) => boolean;
|
|
74
|
+
isNotEmpty: (value: unknown) => boolean;
|
|
75
|
+
isNotNaN: (value: unknown) => boolean;
|
|
76
|
+
isNotNull: (value: unknown) => boolean;
|
|
77
|
+
isNotNullish: (value: any) => boolean;
|
|
78
|
+
isNotNumber: (value: unknown) => boolean;
|
|
79
|
+
isNotNumeric: (value: string | number) => boolean;
|
|
80
|
+
isNotString: (v: unknown) => boolean;
|
|
81
|
+
isNotUndefined: (value?: unknown) => boolean;
|
|
82
|
+
isNull: typeof isNull;
|
|
83
|
+
isNullish: typeof isNullish;
|
|
84
|
+
isNumber: typeof isNumber;
|
|
85
|
+
isNumeric: typeof isNumeric;
|
|
86
|
+
isOdd: (value: any) => boolean;
|
|
87
|
+
isPositive: (value: string | number) => boolean;
|
|
88
|
+
isString: typeof isStringValue;
|
|
89
|
+
isTruthy: typeof isTruthy;
|
|
90
|
+
isUndefined: typeof isUndefined;
|
|
91
|
+
lengthEquals: typeof lengthEquals;
|
|
92
|
+
lengthNotEquals: (value: string | unknown[], arg1: string | number) => boolean;
|
|
93
|
+
lessThan: typeof lessThan;
|
|
94
|
+
lessThanOrEquals: typeof lessThanOrEquals;
|
|
95
|
+
longerThan: typeof longerThan;
|
|
96
|
+
longerThanOrEquals: typeof longerThanOrEquals;
|
|
97
|
+
lt: typeof lessThan;
|
|
98
|
+
lte: typeof lessThanOrEquals;
|
|
99
|
+
matches: typeof matches;
|
|
100
|
+
notEquals: (value: unknown, arg1: unknown) => boolean;
|
|
101
|
+
notInside: (value: unknown, arg1: string | unknown[]) => boolean;
|
|
102
|
+
notMatches: (value: string, regex: string | RegExp) => boolean;
|
|
103
|
+
numberEquals: typeof numberEquals;
|
|
104
|
+
numberNotEquals: (value: string | number, eq: string | number) => boolean;
|
|
105
|
+
shorterThan: typeof shorterThan;
|
|
106
|
+
shorterThanOrEquals: typeof shorterThanOrEquals;
|
|
107
|
+
startsWith: typeof startsWith;
|
|
108
|
+
};
|
|
109
|
+
type TRules<E = Record<string, unknown>> = n4s.EnforceCustomMatchers<TRules<E> & E> & Record<string, (...args: TArgs) => TRules<E> & E> & {
|
|
110
|
+
[P in KBaseRules]: (...args: DropFirst<Parameters<TBaseRules[P]>> | TArgs) => TRules<E> & E;
|
|
111
|
+
};
|
|
112
|
+
/* eslint-disable @typescript-eslint/no-namespace, @typescript-eslint/no-empty-interface */
|
|
113
|
+
declare global {
|
|
114
|
+
namespace n4s {
|
|
115
|
+
interface IRules<E> extends TRules<E> {
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
type TLazyRules = n4s.IRules<TLazyRuleMethods>;
|
|
120
|
+
type TLazy = TLazyRules & TLazyRuleMethods &
|
|
121
|
+
// This is a "catch all" hack to make TS happy while not
|
|
122
|
+
// losing type hints
|
|
123
|
+
Record<string, (...args: any[]) => any>;
|
|
124
|
+
interface IShapeObject extends Record<string, any>, Record<string, TLazyRuleRunners> {
|
|
125
|
+
}
|
|
126
|
+
type TLazyRuleMethods = TLazyRuleRunners & {
|
|
127
|
+
message: (message: TLazyMessage) => TLazy;
|
|
128
|
+
};
|
|
129
|
+
type TLazyRuleRunners = {
|
|
130
|
+
test: (value: unknown) => boolean;
|
|
131
|
+
run: (value: unknown) => TRuleDetailedResult;
|
|
132
|
+
};
|
|
133
|
+
type TLazyMessage = string | ((value: unknown, originalMessage?: TStringable) => string);
|
|
134
|
+
declare function isArrayOf(inputArray: any[], currentRule: TLazy): TRuleDetailedResult;
|
|
135
|
+
declare function loose(inputObject: Record<string, any>, shapeObject: IShapeObject): TRuleDetailedResult;
|
|
136
|
+
declare function optional(value: any, ruleChain: TLazy): TRuleDetailedResult;
|
|
137
|
+
declare function shape(inputObject: Record<string, any>, shapeObject: IShapeObject): TRuleDetailedResult;
|
|
138
|
+
// Help needed improving the typings of this file.
|
|
139
|
+
// Ideally, we'd be able to extend IShapeObject, but that's not possible.
|
|
140
|
+
declare function partial<T extends Record<any, any>>(shapeObject: T): T;
|
|
141
|
+
declare global {
|
|
142
|
+
namespace n4s {
|
|
143
|
+
interface EnforceCustomMatchers<R> {
|
|
144
|
+
isArrayOf: (...args: DropFirst<Parameters<typeof isArrayOf>>) => R;
|
|
145
|
+
loose: (...args: DropFirst<Parameters<typeof loose>>) => R;
|
|
146
|
+
shape: (...args: DropFirst<Parameters<typeof shape>>) => R;
|
|
147
|
+
optional: (...args: DropFirst<Parameters<typeof optional>>) => R;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
export { partial };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
expect.extend({
|
|
2
|
-
toPass: res => ({
|
|
3
|
-
pass: res.pass,
|
|
4
|
-
message: () => 'enforceResult.pass failed validation',
|
|
5
|
-
}),
|
|
6
|
-
toPassWith: (enforcement, value) => {
|
|
7
|
-
return {
|
|
8
|
-
pass:
|
|
9
|
-
enforcement.run(value).pass === true &&
|
|
10
|
-
enforcement.test(value) === true,
|
|
11
|
-
message: () => 'enforceResult.pass failed validation',
|
|
12
|
-
};
|
|
13
|
-
},
|
|
14
|
-
});
|
package/config/rollup/enforce.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
const genConfig = require('../../../../config/rollup/genConfig');
|
|
2
|
-
const { packageDist, packageNames } = require('../../../../util');
|
|
3
|
-
|
|
4
|
-
export default genConfig({
|
|
5
|
-
libraryName: packageNames.N4S,
|
|
6
|
-
distPath: packageDist(packageNames.N4S),
|
|
7
|
-
input: 'enforce.js',
|
|
8
|
-
});
|
package/docs/compound.md
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
# Shape and schema validation
|
|
2
|
-
|
|
3
|
-
Alongside the list of rules that only accept data provided by the user, enforce also supports compound rules - these are rules that accept other rules as their arguments. These rules let you validate more complex scenarios with the ergonomics of enforce.
|
|
4
|
-
|
|
5
|
-
- [enforce.anyOf() - either/or validations](#anyof)
|
|
6
|
-
- [enforce.allOf() - all/and validations](#allof)
|
|
7
|
-
- [enforce.shape() - Object's shape matching](#shape)
|
|
8
|
-
- [enforce.optional() - nullable keys](#optional)
|
|
9
|
-
- [enforec.loose() - loose shape matching](#loose)
|
|
10
|
-
- [enforce.isArrayOf() - array shape matching](#isarrayof)
|
|
11
|
-
|
|
12
|
-
## enforce.anyOf() - either/or validations :id=anyof
|
|
13
|
-
|
|
14
|
-
Sometimes a value has more than one valid possibilities, `any` lets us validate that a value passes _at least_ one of the supplied rules.
|
|
15
|
-
|
|
16
|
-
```js
|
|
17
|
-
enforce(value).anyOf(enforce.isString(), enforce.isArray()).isNotEmpty();
|
|
18
|
-
// A valid value would either an array or a string.
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## enforce.allOf() - all/and validations :id=allof
|
|
22
|
-
|
|
23
|
-
`allOf` lets us validate that a value passes _all_ of the supplied rules or templates.
|
|
24
|
-
|
|
25
|
-
enforce(value).allOf(
|
|
26
|
-
enforce.isArray(),
|
|
27
|
-
enforce.longerThan(2)
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
This can be even more useful when combined with shapes and templates:
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
const User = enforce.template(
|
|
34
|
-
enforce.loose({
|
|
35
|
-
id: enforce.isNumber()
|
|
36
|
-
name: enforce.shape({
|
|
37
|
-
first: enforce.isString(),
|
|
38
|
-
last: enforce.isString(),
|
|
39
|
-
middle: enforce.optional(enforce.isString()),
|
|
40
|
-
}),
|
|
41
|
-
})
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const DisabledAccount = enforce.template(
|
|
45
|
-
enforce.loose({
|
|
46
|
-
disabled: enforce.equals(true)
|
|
47
|
-
})
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
enforce(value).allOf(
|
|
51
|
-
User,
|
|
52
|
-
DisabledAccount
|
|
53
|
-
);
|
|
54
|
-
// A valid is string and longer then 5.
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## enforce.shape() - Lean schema validation. :id=shape
|
|
58
|
-
|
|
59
|
-
`enforce.shape()` validates the structure of an object.
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
enforce({
|
|
63
|
-
firstName: 'Rick',
|
|
64
|
-
lastName: 'Sanchez',
|
|
65
|
-
age: 70,
|
|
66
|
-
}).shape({
|
|
67
|
-
firstName: enforce.isString(),
|
|
68
|
-
lastName: enforce.isString(),
|
|
69
|
-
age: enforce.isNumber(),
|
|
70
|
-
});
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
You may also chain your validation rules:
|
|
74
|
-
|
|
75
|
-
```js
|
|
76
|
-
enforce({
|
|
77
|
-
age: 22,
|
|
78
|
-
}).shape({
|
|
79
|
-
age: enforce.isNumber().isBetween(0, 150),
|
|
80
|
-
});
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
You may also nest calls to shape in order to validate a deeply nested object.
|
|
84
|
-
|
|
85
|
-
```js
|
|
86
|
-
enforce({
|
|
87
|
-
user: {
|
|
88
|
-
name: {
|
|
89
|
-
first: 'Joseph',
|
|
90
|
-
last: 'Weil',
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
}).shape({
|
|
94
|
-
user: enforce.shape({
|
|
95
|
-
name: enforce.shape({
|
|
96
|
-
first: enforce.isString(),
|
|
97
|
-
last: enforce.isString(),
|
|
98
|
-
}),
|
|
99
|
-
}),
|
|
100
|
-
});
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### enforce.optional() - nullable keys :id=optional
|
|
104
|
-
|
|
105
|
-
-- Optional can only be used within enforce.shape().
|
|
106
|
-
|
|
107
|
-
In regular cases, a missing key in the data object would cause an error to be thrown. To prevent that from happening, mark your optional keys with `enforce.optional`.
|
|
108
|
-
|
|
109
|
-
enforce.optional will pass validations of a key that's either not defined, undefined or null.
|
|
110
|
-
|
|
111
|
-
`enforce.optional` takes as its arguments all the rules that the value must pass.
|
|
112
|
-
|
|
113
|
-
```js
|
|
114
|
-
enforce({
|
|
115
|
-
user: {
|
|
116
|
-
name: {
|
|
117
|
-
first: 'Joseph',
|
|
118
|
-
last: 'Weil',
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
}).shape({
|
|
122
|
-
user: enforce.shape({
|
|
123
|
-
name: enforce.shape({
|
|
124
|
-
first: enforce.isString(),
|
|
125
|
-
last: enforce.isString(),
|
|
126
|
-
middle: enforce.optional(enforce.isString(), enforce.longerThan(3)),
|
|
127
|
-
}),
|
|
128
|
-
}),
|
|
129
|
-
});
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## enforec.loose() - loose shape matching :id=loose
|
|
133
|
-
|
|
134
|
-
By default, shape will treat excess keys in your data object as validation errors. If you wish to allow support for excess keys in your object's shape, you can use `enforce.loose()` which is a shorthand to `enforce.shape(data, shape, { loose: true })`.
|
|
135
|
-
|
|
136
|
-
```js
|
|
137
|
-
enforce({ name: 'Laura', code: 'x23' }).shape({ name: enforce.isString() });
|
|
138
|
-
// 🚨 This will throw an error because `code` is not defined in the shape
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
```js
|
|
142
|
-
enforce({ name: 'Laura', code: 'x23' }).loose({ name: enforce.isString() });
|
|
143
|
-
// ✅ This will pass with `code` not being validated
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## enforce.isArrayOf() - array shape matching :id=isarrayof
|
|
147
|
-
|
|
148
|
-
enforce.isArrayOf can be used to determine the allowed types and values within an array. It will run against each element in the array, and will only pass if all items meet at least one of the validation rules.
|
|
149
|
-
|
|
150
|
-
```js
|
|
151
|
-
enforce([1, 2, 'hello!']).isArrayOf(enforce.isString(), enforce.isNumber());
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
You can also combine `isArrayOf` with other rules to validate other array properties:
|
|
155
|
-
|
|
156
|
-
```js
|
|
157
|
-
enforce(someArrayValue)
|
|
158
|
-
.isArrayOf(enforce.isString(), enforce.isNumber().lessThan(3))
|
|
159
|
-
.longerThan(2);
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
And as part of shape:
|
|
163
|
-
|
|
164
|
-
```js
|
|
165
|
-
enforce({ data: [1, 2, 3] }).shape({
|
|
166
|
-
data: enforce.isArrayOf(enforce.isNumber()),
|
|
167
|
-
});
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## enforce.oneOf()
|
|
171
|
-
|
|
172
|
-
enforce.oneOf can be used to determine if _exactly_ one of the rules applies. It will run against rule in the array, and will only pass if exactly one rule applies.
|
|
173
|
-
|
|
174
|
-
```js
|
|
175
|
-
enforce(value).oneOf(
|
|
176
|
-
enforce.isString(),
|
|
177
|
-
enforce.isNumber(),
|
|
178
|
-
enforce.longerThan(1)
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
/*
|
|
182
|
-
value = 1 -> ✅ (value is a number)
|
|
183
|
-
value = "1" -> ✅ (value is string)
|
|
184
|
-
value = [1, 2] -> ✅ (value is longer than 1)
|
|
185
|
-
value = "12" -> 🚨 (value is both a string and longer than 1)
|
|
186
|
-
*/
|
|
187
|
-
```
|