@azure-net/node-kit 0.0.0-stage → 0.1.1
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 +11 -0
- package/LICENSE +21 -0
- package/README.md +301 -2
- package/VALIDATION.md +866 -0
- package/dist/delivery/http/ResponseBuilder.d.ts +44 -0
- package/dist/delivery/http/ResponseBuilder.js +135 -0
- package/dist/delivery/http/index.d.ts +1 -0
- package/dist/delivery/http/index.js +1 -0
- package/dist/delivery/index.d.ts +1 -0
- package/dist/delivery/index.js +1 -0
- package/dist/domain/Ensure.d.ts +2 -0
- package/dist/domain/Ensure.js +7 -0
- package/dist/domain/EnsureError.d.ts +4 -0
- package/dist/domain/EnsureError.js +7 -0
- package/dist/domain/index.d.ts +2 -0
- package/dist/domain/index.js +2 -0
- package/dist/infrastructure/background/BackgroundTask.d.ts +12 -0
- package/dist/infrastructure/background/BackgroundTask.js +41 -0
- package/dist/infrastructure/background/index.d.ts +1 -0
- package/dist/infrastructure/background/index.js +1 -0
- package/dist/infrastructure/environment/Env.d.ts +19 -0
- package/dist/infrastructure/environment/Env.js +33 -0
- package/dist/infrastructure/environment/index.d.ts +1 -0
- package/dist/infrastructure/environment/index.js +1 -0
- package/dist/infrastructure/index.d.ts +2 -0
- package/dist/infrastructure/index.js +2 -0
- package/dist/tools/DateHelper.d.ts +13 -0
- package/dist/tools/DateHelper.js +77 -0
- package/dist/tools/DurationHelper.d.ts +6 -0
- package/dist/tools/DurationHelper.js +31 -0
- package/dist/tools/EnumHelper.d.ts +26 -0
- package/dist/tools/EnumHelper.js +40 -0
- package/dist/tools/ErrorHelper.d.ts +3 -0
- package/dist/tools/ErrorHelper.js +31 -0
- package/dist/tools/NumberHelper.d.ts +19 -0
- package/dist/tools/NumberHelper.js +49 -0
- package/dist/tools/ObjectHelper.d.ts +28 -0
- package/dist/tools/ObjectHelper.js +90 -0
- package/dist/tools/PromiseHelper.d.ts +3 -0
- package/dist/tools/PromiseHelper.js +7 -0
- package/dist/tools/StringHelper.d.ts +75 -0
- package/dist/tools/StringHelper.js +127 -0
- package/dist/tools/UidHelper.d.ts +56 -0
- package/dist/tools/UidHelper.js +132 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.js +9 -0
- package/dist/validation/Engine.d.ts +6 -0
- package/dist/validation/Engine.js +406 -0
- package/dist/validation/Result.d.ts +31 -0
- package/dist/validation/Result.js +264 -0
- package/dist/validation/Symbols.d.ts +1 -0
- package/dist/validation/Symbols.js +1 -0
- package/dist/validation/Types.d.ts +105 -0
- package/dist/validation/Types.js +1 -0
- package/dist/validation/Validator.d.ts +26 -0
- package/dist/validation/Validator.js +95 -0
- package/dist/validation/index.d.ts +5 -0
- package/dist/validation/index.js +5 -0
- package/dist/validation/messages/En.d.ts +3 -0
- package/dist/validation/messages/En.js +118 -0
- package/dist/validation/messages/Ru.d.ts +3 -0
- package/dist/validation/messages/Ru.js +118 -0
- package/dist/validation/messages/index.d.ts +7 -0
- package/dist/validation/messages/index.js +7 -0
- package/dist/validation/rules/CustomRules.d.ts +8 -0
- package/dist/validation/rules/CustomRules.js +64 -0
- package/dist/validation/rules/Factory.d.ts +4 -0
- package/dist/validation/rules/Factory.js +21 -0
- package/dist/validation/rules/StringRules.d.ts +105 -0
- package/dist/validation/rules/StringRules.js +481 -0
- package/dist/validation/rules/StructureRules.d.ts +30 -0
- package/dist/validation/rules/StructureRules.js +145 -0
- package/dist/validation/rules/ValueRules.d.ts +82 -0
- package/dist/validation/rules/ValueRules.js +365 -0
- package/dist/validation/rules/index.d.ts +151 -0
- package/dist/validation/rules/index.js +19 -0
- package/package.json +77 -3
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Blob, File } from "node:buffer";
|
|
2
|
+
import type { RuleOptions } from "../Types.js";
|
|
3
|
+
type Literal = string | number | bigint | boolean | null;
|
|
4
|
+
type Numeric = number | bigint;
|
|
5
|
+
type Comparable = Numeric | Date;
|
|
6
|
+
type EnumValue<T> = T extends readonly (infer V)[] ? V : T[keyof T];
|
|
7
|
+
export interface ValueRangeOptions extends RuleOptions {
|
|
8
|
+
readonly inclusive?: boolean;
|
|
9
|
+
readonly minInclusive?: boolean;
|
|
10
|
+
readonly maxInclusive?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ValueClockOptions extends RuleOptions {
|
|
13
|
+
/** Evaluated for each validation, not when constructing the rule. */
|
|
14
|
+
readonly clock?: () => Date | number;
|
|
15
|
+
}
|
|
16
|
+
export interface ValueFileOptions extends RuleOptions {
|
|
17
|
+
readonly minSize?: number;
|
|
18
|
+
readonly maxSize?: number;
|
|
19
|
+
/** Matches Blob.type's type/subtype, ignoring parameters (e.g. charset). Metadata only, not byte verification. */
|
|
20
|
+
readonly mimeTypes?: readonly string[];
|
|
21
|
+
/** Case-insensitive suffixes, with or without a leading dot. */
|
|
22
|
+
readonly extensions?: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
export declare const valueRules: Readonly<{
|
|
25
|
+
number: (options?: RuleOptions) => import("../Types.js").BuiltinRule<number, unknown, unknown>;
|
|
26
|
+
finite: (options?: RuleOptions) => import("../Types.js").BuiltinRule<number, unknown, unknown>;
|
|
27
|
+
bigint: (options?: RuleOptions) => import("../Types.js").BuiltinRule<bigint, unknown, unknown>;
|
|
28
|
+
boolean: (options?: RuleOptions) => import("../Types.js").BuiltinRule<boolean, unknown, unknown>;
|
|
29
|
+
date: (options?: RuleOptions) => import("../Types.js").BuiltinRule<Date, unknown, unknown>;
|
|
30
|
+
symbol: (options?: RuleOptions) => import("../Types.js").BuiltinRule<symbol, unknown, unknown>;
|
|
31
|
+
literal<const T extends Literal>(expected: T, options?: RuleOptions): import("../Types.js").BuiltinRule<T, unknown, unknown>;
|
|
32
|
+
enum<const T extends readonly Literal[] | Readonly<Record<string, string | number>>>(enumeration: T, options?: RuleOptions): import("../Types.js").BuiltinRule<EnumValue<T>, unknown, unknown>;
|
|
33
|
+
enumName<const T extends Readonly<Record<string, string | number>>>(enumeration: T, options?: RuleOptions): import("../Types.js").BuiltinRule<Extract<keyof T, string>, unknown, unknown>;
|
|
34
|
+
integer: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
35
|
+
int32: (options?: RuleOptions) => import("../Types.js").BuiltinRule<number, unknown, unknown>;
|
|
36
|
+
uint32: (options?: RuleOptions) => import("../Types.js").BuiltinRule<number, unknown, unknown>;
|
|
37
|
+
/** Like Zod's float32: finite range only, not exact Math.fround representability; no rounding. */
|
|
38
|
+
float32: (options?: RuleOptions) => import("../Types.js").BuiltinRule<number, unknown, unknown>;
|
|
39
|
+
/** 64-bit formats require bigint: JS numbers cannot represent their full ranges safely. */
|
|
40
|
+
int64: (options?: RuleOptions) => import("../Types.js").BuiltinRule<bigint, unknown, unknown>;
|
|
41
|
+
uint64: (options?: RuleOptions) => import("../Types.js").BuiltinRule<bigint, unknown, unknown>;
|
|
42
|
+
safeInteger: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
43
|
+
positive: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
44
|
+
negative: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
45
|
+
nonNegative: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
46
|
+
nonPositive: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
47
|
+
min(min: Comparable, options?: ValueRangeOptions): import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
48
|
+
max(max: Comparable, options?: ValueRangeOptions): import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
49
|
+
lessThan(max: Comparable, options?: ValueRangeOptions): import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
50
|
+
greaterThan(min: Comparable, options?: ValueRangeOptions): import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
51
|
+
lessThanOrEqual: (max: Comparable, options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
52
|
+
greaterThanOrEqual: (min: Comparable, options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
53
|
+
between(min: Comparable, max: Comparable, options?: ValueRangeOptions): import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
54
|
+
multipleOf(divisor: Numeric, options?: RuleOptions): import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
55
|
+
/** Decimal notation up to 4096 characters; optionally limit fractional places after exponent expansion. */
|
|
56
|
+
decimal(places?: number, options?: RuleOptions): import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
57
|
+
/** SQL-style precision/scale: at most precision-scale integer and scale fractional digits; 4096-character input limit. */
|
|
58
|
+
precisionScale(precision: number, scale: number, options?: RuleOptions): import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
59
|
+
/** Equality uses Node's isDeepStrictEqual, including Object.is semantics for primitives. */
|
|
60
|
+
equal: (expected: unknown, options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
61
|
+
notEqual: (expected: unknown, options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
62
|
+
notNull: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
63
|
+
required: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
64
|
+
notEmpty: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
65
|
+
empty: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
66
|
+
unknown: (options?: RuleOptions) => import("../Types.js").BuiltinRule<unknown, unknown, unknown>;
|
|
67
|
+
never: (options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
68
|
+
null: (options?: RuleOptions) => import("../Types.js").BuiltinRule<null, unknown, unknown>;
|
|
69
|
+
undefined: (options?: RuleOptions) => import("../Types.js").BuiltinRule<undefined, unknown, unknown>;
|
|
70
|
+
nan: (options?: RuleOptions) => import("../Types.js").BuiltinRule<number, unknown, unknown>;
|
|
71
|
+
instanceOf<T>(constructor: abstract new (...args: any[]) => T, options?: RuleOptions): import("../Types.js").BuiltinRule<T, unknown, unknown>;
|
|
72
|
+
/** Real File instances only; metadata validation never reads or verifies content bytes. */
|
|
73
|
+
file: (options?: ValueFileOptions) => import("../Types.js").BuiltinRule<File, unknown, unknown>;
|
|
74
|
+
/** Blob or File instances; extension constraints require a real File name. Metadata only. */
|
|
75
|
+
blob: (options?: ValueFileOptions) => import("../Types.js").BuiltinRule<Blob, unknown, unknown>;
|
|
76
|
+
before: (target: Date, options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
77
|
+
after: (target: Date, options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
78
|
+
same: (target: Date, options?: RuleOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
79
|
+
isPast: (options?: ValueClockOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
80
|
+
isFuture: (options?: ValueClockOptions) => import("../Types.js").BuiltinRule<never, unknown, unknown>;
|
|
81
|
+
}>;
|
|
82
|
+
export {};
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { Blob, File } from "node:buffer";
|
|
2
|
+
import { isDeepStrictEqual } from "node:util";
|
|
3
|
+
import { sizeOption, testRule } from "./Factory.js";
|
|
4
|
+
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
5
|
+
const numeric = (value) => finite(value) || typeof value === "bigint";
|
|
6
|
+
const dateTime = (value) => Date.prototype.getTime.call(value);
|
|
7
|
+
const validDate = (value) => {
|
|
8
|
+
if (!(value instanceof Date))
|
|
9
|
+
return false;
|
|
10
|
+
try {
|
|
11
|
+
return Number.isFinite(dateTime(value));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const literalValue = (value) => value === null ||
|
|
18
|
+
typeof value === "string" ||
|
|
19
|
+
typeof value === "bigint" ||
|
|
20
|
+
typeof value === "boolean" ||
|
|
21
|
+
finite(value);
|
|
22
|
+
function numericConfig(value) {
|
|
23
|
+
if (!numeric(value))
|
|
24
|
+
throw new TypeError("Expected a finite number or bigint.");
|
|
25
|
+
}
|
|
26
|
+
function inclusivity(options) {
|
|
27
|
+
for (const key of ["inclusive", "minInclusive", "maxInclusive"]) {
|
|
28
|
+
if (options[key] !== undefined && typeof options[key] !== "boolean")
|
|
29
|
+
throw new TypeError(`${key} must be boolean.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const MAX_DECIMAL_LENGTH = 4096;
|
|
33
|
+
const blobSize = Object.getOwnPropertyDescriptor(Blob.prototype, "size").get;
|
|
34
|
+
const fileName = Object.getOwnPropertyDescriptor(File.prototype, "name").get;
|
|
35
|
+
const blobType = Object.getOwnPropertyDescriptor(Blob.prototype, "type").get;
|
|
36
|
+
// Normalize decimal notation without floating-point arithmetic or exponent-sized allocations.
|
|
37
|
+
// Numbers use their shortest round-trip decimal representation; strings preserve exact digits.
|
|
38
|
+
function decimalParts(value) {
|
|
39
|
+
if (typeof value !== "string" && !finite(value))
|
|
40
|
+
return undefined;
|
|
41
|
+
const text = String(value);
|
|
42
|
+
if (text.length > MAX_DECIMAL_LENGTH)
|
|
43
|
+
return undefined;
|
|
44
|
+
const match = /^([+-]?)(?:(\d+)(?:\.(\d*))?|\.(\d+))(?:[eE]([+-]?\d+))?$/.exec(text);
|
|
45
|
+
if (!match || match[0] !== text)
|
|
46
|
+
return undefined;
|
|
47
|
+
const fraction = match[3] ?? match[4] ?? "";
|
|
48
|
+
let digits = ((match[2] ?? "") + fraction).replace(/^0+/, "");
|
|
49
|
+
if (!digits)
|
|
50
|
+
return { digits: "0", power: 0n };
|
|
51
|
+
let end = digits.length;
|
|
52
|
+
while (digits[end - 1] === "0")
|
|
53
|
+
end--;
|
|
54
|
+
const exponent = match[5] ?? "0";
|
|
55
|
+
const negative = exponent[0] === "-";
|
|
56
|
+
const significant = exponent.replace(/^[+-]?0*/, "");
|
|
57
|
+
// Saturation is exact for our comparisons: even after digit offsets, these exponents
|
|
58
|
+
// exceed every permitted safe-integer precision/scale. Never parse an unbounded BigInt.
|
|
59
|
+
const magnitude = significant.length > 16
|
|
60
|
+
? BigInt(Number.MAX_SAFE_INTEGER) + BigInt(MAX_DECIMAL_LENGTH) + 1n
|
|
61
|
+
: BigInt(significant || "0");
|
|
62
|
+
const power = (negative ? -magnitude : magnitude) -
|
|
63
|
+
BigInt(fraction.length) +
|
|
64
|
+
BigInt(digits.length - end);
|
|
65
|
+
digits = digits.slice(0, end);
|
|
66
|
+
return { digits, power };
|
|
67
|
+
}
|
|
68
|
+
function exactMultiple(value, divisor) {
|
|
69
|
+
const a = decimalParts(value);
|
|
70
|
+
const b = decimalParts(divisor);
|
|
71
|
+
if (a.digits === "0")
|
|
72
|
+
return true;
|
|
73
|
+
const difference = a.power - b.power;
|
|
74
|
+
// Finite binary64 decimal powers range from -324 through 308. Enforce this bound
|
|
75
|
+
// before exponentiation, even if this helper's callers change in the future.
|
|
76
|
+
if (difference < -632n || difference > 632n)
|
|
77
|
+
return false;
|
|
78
|
+
return difference >= 0n
|
|
79
|
+
? (BigInt(a.digits) * 10n ** difference) % BigInt(b.digits) === 0n
|
|
80
|
+
: BigInt(a.digits) % (BigInt(b.digits) * 10n ** -difference) === 0n;
|
|
81
|
+
}
|
|
82
|
+
function comparisonBound(bound) {
|
|
83
|
+
if (validDate(bound))
|
|
84
|
+
return { kind: "date", value: dateTime(bound) };
|
|
85
|
+
numericConfig(bound);
|
|
86
|
+
return { kind: typeof bound, value: bound };
|
|
87
|
+
}
|
|
88
|
+
function comparableValue(value, kind) {
|
|
89
|
+
if (kind === "date")
|
|
90
|
+
return validDate(value) ? dateTime(value) : undefined;
|
|
91
|
+
return typeof value === kind && numeric(value) ? value : undefined;
|
|
92
|
+
}
|
|
93
|
+
function comparisonRule(code, bound, greater, inclusive, options) {
|
|
94
|
+
const target = comparisonBound(bound);
|
|
95
|
+
return testRule(code, (value) => {
|
|
96
|
+
const actual = comparableValue(value, target.kind);
|
|
97
|
+
return (actual !== undefined &&
|
|
98
|
+
(greater
|
|
99
|
+
? inclusive
|
|
100
|
+
? actual >= target.value
|
|
101
|
+
: actual > target.value
|
|
102
|
+
: inclusive
|
|
103
|
+
? actual <= target.value
|
|
104
|
+
: actual < target.value));
|
|
105
|
+
}, options, { [greater ? "min" : "max"]: target.value, inclusive });
|
|
106
|
+
}
|
|
107
|
+
function enumEntries(value) {
|
|
108
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
109
|
+
throw new TypeError("Expected an enum object.");
|
|
110
|
+
const entries = Object.entries(value);
|
|
111
|
+
if (!entries.length ||
|
|
112
|
+
entries.some(([, item]) => typeof item !== "string" && !finite(item)))
|
|
113
|
+
throw new TypeError("Enum values must be strings or finite numbers.");
|
|
114
|
+
return entries.filter(([key, item]) => !(typeof item === "string" &&
|
|
115
|
+
Object.hasOwn(value, item) &&
|
|
116
|
+
typeof value[item] === "number" &&
|
|
117
|
+
String(value[item]) === key));
|
|
118
|
+
}
|
|
119
|
+
function emptyValue(value) {
|
|
120
|
+
return (value === null ||
|
|
121
|
+
value === undefined ||
|
|
122
|
+
(typeof value === "string" && value.trim() === "") ||
|
|
123
|
+
(Array.isArray(value) && value.length === 0) ||
|
|
124
|
+
((value instanceof Map || value instanceof Set) && value.size === 0) ||
|
|
125
|
+
(value instanceof Blob && value.size === 0) ||
|
|
126
|
+
(value !== null &&
|
|
127
|
+
typeof value === "object" &&
|
|
128
|
+
(Object.getPrototypeOf(value) === Object.prototype ||
|
|
129
|
+
Object.getPrototypeOf(value) === null) &&
|
|
130
|
+
Reflect.ownKeys(value).length === 0));
|
|
131
|
+
}
|
|
132
|
+
function dateComparison(code, target, compare, options) {
|
|
133
|
+
if (!validDate(target))
|
|
134
|
+
throw new TypeError("Expected a valid Date.");
|
|
135
|
+
const timestamp = dateTime(target);
|
|
136
|
+
return testRule(code, (value) => validDate(value) && compare(dateTime(value), timestamp), options, { timestamp });
|
|
137
|
+
}
|
|
138
|
+
function relativeDate(code, future, options) {
|
|
139
|
+
if (options.clock !== undefined && typeof options.clock !== "function")
|
|
140
|
+
throw new TypeError("clock must be a function.");
|
|
141
|
+
const clock = options.clock ?? (() => Date.now());
|
|
142
|
+
return testRule(code, (value) => {
|
|
143
|
+
if (!validDate(value))
|
|
144
|
+
return false;
|
|
145
|
+
const now = clock();
|
|
146
|
+
const timestamp = validDate(now) ? dateTime(now) : now;
|
|
147
|
+
if (!finite(timestamp))
|
|
148
|
+
throw new TypeError("clock must return a finite timestamp or valid Date.");
|
|
149
|
+
return future ? dateTime(value) > timestamp : dateTime(value) < timestamp;
|
|
150
|
+
}, options);
|
|
151
|
+
}
|
|
152
|
+
function binaryRule(code, options) {
|
|
153
|
+
const { minSize, maxSize } = options;
|
|
154
|
+
if (minSize !== undefined)
|
|
155
|
+
sizeOption(minSize, "minSize");
|
|
156
|
+
if (maxSize !== undefined)
|
|
157
|
+
sizeOption(maxSize, "maxSize");
|
|
158
|
+
if (minSize !== undefined && maxSize !== undefined && minSize > maxSize)
|
|
159
|
+
throw new RangeError("minSize must not exceed maxSize.");
|
|
160
|
+
for (const key of ["mimeTypes", "extensions"]) {
|
|
161
|
+
const list = options[key];
|
|
162
|
+
if (list !== undefined &&
|
|
163
|
+
(!Array.isArray(list) ||
|
|
164
|
+
Array.from(list).some((item) => typeof item !== "string" || !item || item.trim() !== item)))
|
|
165
|
+
throw new TypeError(`${key} must be an array of non-empty, unpadded strings.`);
|
|
166
|
+
}
|
|
167
|
+
const mimeTypes = options.mimeTypes &&
|
|
168
|
+
Object.freeze(options.mimeTypes.map((item) => item.toLowerCase()));
|
|
169
|
+
if (mimeTypes?.some((item) => !/^[\w!#$&^.+-]+\/(?:[\w!#$&^.+-]+|\*)$/.test(item)))
|
|
170
|
+
throw new TypeError("Invalid MIME type.");
|
|
171
|
+
const extensions = options.extensions &&
|
|
172
|
+
Object.freeze(options.extensions.map((item) => item.replace(/^\./, "").toLowerCase()));
|
|
173
|
+
if (extensions?.some((item) => !/^[a-z0-9_-]+(?:\.[a-z0-9_-]+)*$/.test(item)))
|
|
174
|
+
throw new TypeError("Invalid extension.");
|
|
175
|
+
return testRule(code, (value) => {
|
|
176
|
+
if (!(value instanceof Blob))
|
|
177
|
+
return false;
|
|
178
|
+
let size;
|
|
179
|
+
let mime;
|
|
180
|
+
let name;
|
|
181
|
+
try {
|
|
182
|
+
size = blobSize.call(value);
|
|
183
|
+
mime = blobType.call(value);
|
|
184
|
+
if (code === "file" || extensions) {
|
|
185
|
+
if (!(value instanceof File))
|
|
186
|
+
return false;
|
|
187
|
+
name = fileName.call(value);
|
|
188
|
+
if (typeof name !== "string")
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
if ((minSize !== undefined && size < minSize) ||
|
|
196
|
+
(maxSize !== undefined && size > maxSize))
|
|
197
|
+
return false;
|
|
198
|
+
if (mimeTypes) {
|
|
199
|
+
// Bun may add charset metadata where Node does not. Compare the MIME essence,
|
|
200
|
+
// not its parameters, while still rejecting malformed types before wildcard matching.
|
|
201
|
+
const essence = mime.split(";", 1)[0].trim().toLowerCase();
|
|
202
|
+
if (!/^[\w!#$&^.+-]+\/[\w!#$&^.+-]+$/.test(essence) ||
|
|
203
|
+
!mimeTypes.some((type) => type.endsWith("/*")
|
|
204
|
+
? essence.startsWith(type.slice(0, -1))
|
|
205
|
+
: essence === type))
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
if (extensions) {
|
|
209
|
+
if (!extensions.some((extension) => name.toLowerCase().endsWith(`.${extension}`)))
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
}, options, { minSize, maxSize, mimeTypes, extensions }, true);
|
|
214
|
+
}
|
|
215
|
+
export const valueRules = Object.freeze({
|
|
216
|
+
number: (options = {}) => testRule("number", finite, options, {}, true),
|
|
217
|
+
finite: (options = {}) => testRule("finite", finite, options, {}, true),
|
|
218
|
+
bigint: (options = {}) => testRule("bigint", (value) => typeof value === "bigint", options, {}, true),
|
|
219
|
+
boolean: (options = {}) => testRule("boolean", (value) => typeof value === "boolean", options, {}, true),
|
|
220
|
+
date: (options = {}) => testRule("date", validDate, options, {}, true),
|
|
221
|
+
symbol: (options = {}) => testRule("symbol", (value) => typeof value === "symbol", options, {}, true),
|
|
222
|
+
literal(expected, options = {}) {
|
|
223
|
+
if (!literalValue(expected))
|
|
224
|
+
throw new TypeError("Expected a string, finite number, bigint, boolean or null literal.");
|
|
225
|
+
return testRule("literal", (value) => Object.is(value, expected), options, { expected }, true);
|
|
226
|
+
},
|
|
227
|
+
enum(enumeration, options = {}) {
|
|
228
|
+
let allowed;
|
|
229
|
+
if (Array.isArray(enumeration)) {
|
|
230
|
+
allowed = Array.from(enumeration);
|
|
231
|
+
if (!allowed.length || !allowed.every(literalValue))
|
|
232
|
+
throw new TypeError("Enum members must be strings, finite numbers, bigints, booleans or null.");
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
allowed = enumEntries(enumeration).map(([, value]) => value);
|
|
236
|
+
}
|
|
237
|
+
const values = Object.freeze(allowed);
|
|
238
|
+
return testRule("enum", (value) => values.some((item) => Object.is(item, value)), options, { values }, true);
|
|
239
|
+
},
|
|
240
|
+
enumName(enumeration, options = {}) {
|
|
241
|
+
const names = Object.freeze(enumEntries(enumeration).map(([name]) => name));
|
|
242
|
+
return testRule("enumName", (value) => typeof value === "string" && names.includes(value), options, { names }, true);
|
|
243
|
+
},
|
|
244
|
+
integer: (options = {}) => testRule("integer", (value) => typeof value === "bigint" || (finite(value) && Number.isInteger(value)), options),
|
|
245
|
+
int32: (options = {}) => testRule("int32", (value) => finite(value) &&
|
|
246
|
+
Number.isSafeInteger(value) &&
|
|
247
|
+
value >= -2147483648 &&
|
|
248
|
+
value <= 2147483647, options, {}, true),
|
|
249
|
+
uint32: (options = {}) => testRule("uint32", (value) => finite(value) &&
|
|
250
|
+
Number.isSafeInteger(value) &&
|
|
251
|
+
value >= 0 &&
|
|
252
|
+
value <= 4294967295, options, {}, true),
|
|
253
|
+
/** Like Zod's float32: finite range only, not exact Math.fround representability; no rounding. */
|
|
254
|
+
float32: (options = {}) => testRule("float32", (value) => finite(value) && Math.abs(value) <= 3.4028234663852886e38, options, {}, true),
|
|
255
|
+
/** 64-bit formats require bigint: JS numbers cannot represent their full ranges safely. */
|
|
256
|
+
int64: (options = {}) => testRule("int64", (value) => typeof value === "bigint" &&
|
|
257
|
+
value >= -9223372036854775808n &&
|
|
258
|
+
value <= 9223372036854775807n, options, {}, true),
|
|
259
|
+
uint64: (options = {}) => testRule("uint64", (value) => typeof value === "bigint" &&
|
|
260
|
+
value >= 0n &&
|
|
261
|
+
value <= 18446744073709551615n, options, {}, true),
|
|
262
|
+
safeInteger: (options = {}) => testRule("safeInteger", (value) => typeof value === "bigint"
|
|
263
|
+
? value >= BigInt(Number.MIN_SAFE_INTEGER) &&
|
|
264
|
+
value <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
265
|
+
: finite(value) && Number.isSafeInteger(value), options),
|
|
266
|
+
positive: (options = {}) => testRule("positive", (value) => numeric(value) && value > 0, options),
|
|
267
|
+
negative: (options = {}) => testRule("negative", (value) => numeric(value) && value < 0, options),
|
|
268
|
+
nonNegative: (options = {}) => testRule("nonNegative", (value) => numeric(value) && value >= 0, options),
|
|
269
|
+
nonPositive: (options = {}) => testRule("nonPositive", (value) => numeric(value) && value <= 0, options),
|
|
270
|
+
min(min, options = {}) {
|
|
271
|
+
inclusivity(options);
|
|
272
|
+
return comparisonRule("min", min, true, options.inclusive !== false, options);
|
|
273
|
+
},
|
|
274
|
+
max(max, options = {}) {
|
|
275
|
+
inclusivity(options);
|
|
276
|
+
return comparisonRule("max", max, false, options.inclusive !== false, options);
|
|
277
|
+
},
|
|
278
|
+
lessThan(max, options = {}) {
|
|
279
|
+
inclusivity(options);
|
|
280
|
+
return comparisonRule("lessThan", max, false, options.inclusive ?? false, options);
|
|
281
|
+
},
|
|
282
|
+
greaterThan(min, options = {}) {
|
|
283
|
+
inclusivity(options);
|
|
284
|
+
return comparisonRule("greaterThan", min, true, options.inclusive ?? false, options);
|
|
285
|
+
},
|
|
286
|
+
lessThanOrEqual: (max, options = {}) => comparisonRule("lessThanOrEqual", max, false, true, options),
|
|
287
|
+
greaterThanOrEqual: (min, options = {}) => comparisonRule("greaterThanOrEqual", min, true, true, options),
|
|
288
|
+
between(min, max, options = {}) {
|
|
289
|
+
const lower = comparisonBound(min);
|
|
290
|
+
const upper = comparisonBound(max);
|
|
291
|
+
inclusivity(options);
|
|
292
|
+
if (lower.kind !== upper.kind || lower.value > upper.value)
|
|
293
|
+
throw new RangeError("Bounds must have the same type and min must not exceed max.");
|
|
294
|
+
const minInclusive = options.minInclusive ?? options.inclusive ?? true;
|
|
295
|
+
const maxInclusive = options.maxInclusive ?? options.inclusive ?? true;
|
|
296
|
+
return testRule("between", (value) => {
|
|
297
|
+
const actual = comparableValue(value, lower.kind);
|
|
298
|
+
return (actual !== undefined &&
|
|
299
|
+
(minInclusive ? actual >= lower.value : actual > lower.value) &&
|
|
300
|
+
(maxInclusive ? actual <= upper.value : actual < upper.value));
|
|
301
|
+
}, options, { min: lower.value, max: upper.value, minInclusive, maxInclusive });
|
|
302
|
+
},
|
|
303
|
+
multipleOf(divisor, options = {}) {
|
|
304
|
+
numericConfig(divisor);
|
|
305
|
+
if (divisor === 0 || divisor === 0n)
|
|
306
|
+
throw new RangeError("divisor must not be zero.");
|
|
307
|
+
return testRule("multipleOf", (value) => typeof divisor === "bigint"
|
|
308
|
+
? typeof value === "bigint" && value % divisor === 0n
|
|
309
|
+
: finite(value) && exactMultiple(value, divisor), options, { divisor });
|
|
310
|
+
},
|
|
311
|
+
/** Decimal notation up to 4096 characters; optionally limit fractional places after exponent expansion. */
|
|
312
|
+
decimal(places, options = {}) {
|
|
313
|
+
if (places !== undefined)
|
|
314
|
+
sizeOption(places, "places");
|
|
315
|
+
return testRule("decimal", (value) => {
|
|
316
|
+
const parts = decimalParts(value);
|
|
317
|
+
return (parts !== undefined &&
|
|
318
|
+
(places === undefined || parts.power >= -BigInt(places)));
|
|
319
|
+
}, options, places === undefined ? {} : { places });
|
|
320
|
+
},
|
|
321
|
+
/** SQL-style precision/scale: at most precision-scale integer and scale fractional digits; 4096-character input limit. */
|
|
322
|
+
precisionScale(precision, scale, options = {}) {
|
|
323
|
+
sizeOption(precision, "precision");
|
|
324
|
+
sizeOption(scale, "scale");
|
|
325
|
+
if (precision === 0 || scale > precision)
|
|
326
|
+
throw new RangeError("Require precision > 0 and scale <= precision.");
|
|
327
|
+
return testRule("precisionScale", (value) => {
|
|
328
|
+
const parts = decimalParts(value);
|
|
329
|
+
if (!parts)
|
|
330
|
+
return false;
|
|
331
|
+
if (parts.digits === "0")
|
|
332
|
+
return true;
|
|
333
|
+
return (parts.power >= -BigInt(scale) &&
|
|
334
|
+
BigInt(parts.digits.length) + parts.power <= BigInt(precision - scale));
|
|
335
|
+
}, options, { precision, scale });
|
|
336
|
+
},
|
|
337
|
+
/** Equality uses Node's isDeepStrictEqual, including Object.is semantics for primitives. */
|
|
338
|
+
equal: (expected, options = {}) => testRule("equal", (value) => isDeepStrictEqual(value, expected), options, {
|
|
339
|
+
expected,
|
|
340
|
+
}),
|
|
341
|
+
notEqual: (expected, options = {}) => testRule("notEqual", (value) => !isDeepStrictEqual(value, expected), options, { expected }),
|
|
342
|
+
notNull: (options = {}) => testRule("notNull", (value) => value !== null, options),
|
|
343
|
+
required: (options = {}) => testRule("required", (value) => value !== null && value !== undefined, options),
|
|
344
|
+
notEmpty: (options = {}) => testRule("notEmpty", (value) => !emptyValue(value), options),
|
|
345
|
+
empty: (options = {}) => testRule("empty", emptyValue, options),
|
|
346
|
+
unknown: (options = {}) => testRule("unknown", () => true, options, {}, true),
|
|
347
|
+
never: (options = {}) => testRule("never", () => false, options, {}, true),
|
|
348
|
+
null: (options = {}) => testRule("null", (value) => value === null, options, {}, true),
|
|
349
|
+
undefined: (options = {}) => testRule("undefined", (value) => value === undefined, options, {}, true),
|
|
350
|
+
nan: (options = {}) => testRule("nan", (value) => typeof value === "number" && Number.isNaN(value), options, {}, true),
|
|
351
|
+
instanceOf(constructor, options = {}) {
|
|
352
|
+
if (typeof constructor !== "function" || !constructor.prototype)
|
|
353
|
+
throw new TypeError("Expected a constructor.");
|
|
354
|
+
return testRule("instanceOf", (value) => value instanceof constructor, options, { name: constructor.name }, true);
|
|
355
|
+
},
|
|
356
|
+
/** Real File instances only; metadata validation never reads or verifies content bytes. */
|
|
357
|
+
file: (options = {}) => binaryRule("file", options),
|
|
358
|
+
/** Blob or File instances; extension constraints require a real File name. Metadata only. */
|
|
359
|
+
blob: (options = {}) => binaryRule("blob", options),
|
|
360
|
+
before: (target, options = {}) => dateComparison("before", target, (a, b) => a < b, options),
|
|
361
|
+
after: (target, options = {}) => dateComparison("after", target, (a, b) => a > b, options),
|
|
362
|
+
same: (target, options = {}) => dateComparison("same", target, (a, b) => a === b, options),
|
|
363
|
+
isPast: (options = {}) => relativeDate("isPast", false, options),
|
|
364
|
+
isFuture: (options = {}) => relativeDate("isFuture", true, options),
|
|
365
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { RuleOptions, BuiltinRule, FieldRule, ValidationRules } from "../Types.js";
|
|
2
|
+
import { validatorDefinition } from "../Symbols.js";
|
|
3
|
+
export type { LengthOptions, UuidOptions, UrlOptions, NanoidOptions, JwtOptions, MacOptions, HashOptions, IsoTimeOptions, IsoDateTimeOptions, HashAlgorithm, } from "./StringRules.js";
|
|
4
|
+
export type { ValueRangeOptions, ValueClockOptions, ValueFileOptions, } from "./ValueRules.js";
|
|
5
|
+
export declare const rules: Readonly<{
|
|
6
|
+
when<T, D = unknown, R = D, C = unknown>(condition: (context: import("../Types.js").RuleContext<T, D, R, C>) => boolean, checks: readonly FieldRule<T, D, R, C>[]): import("../Types.js").ValidationRule<T, D, R, C>;
|
|
7
|
+
contains(expected: unknown, options?: RuleOptions): BuiltinRule<never>;
|
|
8
|
+
some<T>(predicate: (value: T, index: number) => boolean, options?: RuleOptions): import("../Types.js").ValidationRule<T[]>;
|
|
9
|
+
every<T>(predicate: (value: T, index: number) => boolean, options?: RuleOptions): import("../Types.js").ValidationRule<T[]>;
|
|
10
|
+
optional: () => BuiltinRule<undefined>;
|
|
11
|
+
nullable: () => BuiltinRule<null>;
|
|
12
|
+
nullish: () => BuiltinRule<null | undefined>;
|
|
13
|
+
object<T extends object, TRoot = unknown, C = unknown>(shape: ValidationRules<T, TRoot, C>, options?: RuleOptions & {
|
|
14
|
+
unknownKeys?: "reject" | "allow";
|
|
15
|
+
}): BuiltinRule<T, C, TRoot>;
|
|
16
|
+
array<T, TRoot = unknown, C = unknown>(items: readonly FieldRule<T, T[], TRoot, C>[], options?: RuleOptions): BuiltinRule<T[], C, TRoot>;
|
|
17
|
+
tuple<T extends readonly unknown[], TRoot = unknown, C = unknown>(items: { readonly [K in keyof T]: readonly FieldRule<T[K], T, TRoot, C>[]; }, options?: RuleOptions): BuiltinRule<T, C, TRoot>;
|
|
18
|
+
record<T, TRoot = unknown, C = unknown>(items: readonly FieldRule<T, Record<string, T>, TRoot, C>[], options?: RuleOptions, keys?: readonly FieldRule<string, Record<string, T>, TRoot, C>[]): BuiltinRule<Record<string, T>, C, TRoot>;
|
|
19
|
+
map<K, V, TRoot = unknown, C = unknown>(keys: readonly FieldRule<K, Map<K, V>, TRoot, C>[], items: readonly FieldRule<V, Map<K, V>, TRoot, C>[], options?: RuleOptions): BuiltinRule<Map<K, V>, C, TRoot>;
|
|
20
|
+
set<T, TRoot = unknown, C = unknown>(items: readonly FieldRule<T, Set<T>, TRoot, C>[], options?: RuleOptions): BuiltinRule<Set<T>, C, TRoot>;
|
|
21
|
+
union<T, D = unknown, TRoot = unknown, C = unknown>(alternatives: readonly (readonly FieldRule<T, D, TRoot, C>[])[], options?: RuleOptions): BuiltinRule<T, C, TRoot>;
|
|
22
|
+
discriminatedUnion<T, D = unknown, TRoot = unknown, C = unknown>(key: string, variants: Readonly<Record<string, readonly FieldRule<T, D, TRoot, C>[]>>, options?: RuleOptions): BuiltinRule<T, C, TRoot>;
|
|
23
|
+
intersection<A extends object, B extends object, TRoot = unknown, C = unknown>(left: ValidationRules<A, TRoot, C>, right: ValidationRules<B, TRoot, C>, options?: RuleOptions): BuiltinRule<A & B, C, TRoot>;
|
|
24
|
+
validator<T extends object, C>(validator: (new () => import("../Validator.js").Validator<T, C>) & {
|
|
25
|
+
[validatorDefinition](): Readonly<Record<string, readonly import("../Types.js").AnyRule[]>>;
|
|
26
|
+
readonly configuration: {
|
|
27
|
+
readonly unknownKeys?: "reject" | "allow";
|
|
28
|
+
};
|
|
29
|
+
}, options?: RuleOptions): BuiltinRule<T, C>;
|
|
30
|
+
lazy<T, D = unknown, TRoot = unknown, C = unknown>(resolve: () => readonly FieldRule<T, D, TRoot, C>[], options?: RuleOptions): BuiltinRule<T, C, TRoot>;
|
|
31
|
+
unique(options?: RuleOptions): BuiltinRule<never>;
|
|
32
|
+
uniqueBy<T>(key: keyof T, options?: RuleOptions): BuiltinRule<never>;
|
|
33
|
+
sameAs(key: string, options?: RuleOptions): BuiltinRule<never>;
|
|
34
|
+
notSameAs(key: string, options?: RuleOptions): BuiltinRule<never>;
|
|
35
|
+
string(options?: RuleOptions): BuiltinRule<string>;
|
|
36
|
+
length(length: number, options?: import("./StringRules.js").LengthOptions): BuiltinRule<never>;
|
|
37
|
+
minLength(minLength: number, options?: import("./StringRules.js").LengthOptions): BuiltinRule<never>;
|
|
38
|
+
maxLength(maxLength: number, options?: import("./StringRules.js").LengthOptions): BuiltinRule<never>;
|
|
39
|
+
matches(regex: RegExp, options?: RuleOptions): BuiltinRule<string>;
|
|
40
|
+
includes(substring: string, options?: RuleOptions): BuiltinRule<string>;
|
|
41
|
+
startsWith(prefix: string, options?: RuleOptions): BuiltinRule<string>;
|
|
42
|
+
endsWith(suffix: string, options?: RuleOptions): BuiltinRule<string>;
|
|
43
|
+
lowercase(options?: RuleOptions): BuiltinRule<string>;
|
|
44
|
+
uppercase(options?: RuleOptions): BuiltinRule<string>;
|
|
45
|
+
email(options?: RuleOptions): BuiltinRule<string>;
|
|
46
|
+
uuid(options?: import("./StringRules.js").UuidOptions): BuiltinRule<string>;
|
|
47
|
+
guid(options?: RuleOptions): BuiltinRule<string>;
|
|
48
|
+
url(options?: import("./StringRules.js").UrlOptions): BuiltinRule<string>;
|
|
49
|
+
httpUrl(options?: import("./StringRules.js").UrlOptions): BuiltinRule<string>;
|
|
50
|
+
hostname(options?: RuleOptions): BuiltinRule<string>;
|
|
51
|
+
e164(options?: RuleOptions): BuiltinRule<string>;
|
|
52
|
+
emoji(options?: RuleOptions): BuiltinRule<string>;
|
|
53
|
+
base64(options?: RuleOptions): BuiltinRule<string>;
|
|
54
|
+
base64url(options?: RuleOptions): BuiltinRule<string>;
|
|
55
|
+
hex(options?: RuleOptions): BuiltinRule<string>;
|
|
56
|
+
jwt(options?: import("./StringRules.js").JwtOptions): BuiltinRule<string>;
|
|
57
|
+
nanoid(options?: import("./StringRules.js").NanoidOptions): BuiltinRule<string>;
|
|
58
|
+
cuid(options?: RuleOptions): BuiltinRule<string>;
|
|
59
|
+
cuid2(options?: RuleOptions): BuiltinRule<string>;
|
|
60
|
+
ulid(options?: RuleOptions): BuiltinRule<string>;
|
|
61
|
+
xid(options?: RuleOptions): BuiltinRule<string>;
|
|
62
|
+
ksuid(options?: RuleOptions): BuiltinRule<string>;
|
|
63
|
+
ip(options?: RuleOptions): BuiltinRule<string>;
|
|
64
|
+
ipv4(options?: RuleOptions): BuiltinRule<string>;
|
|
65
|
+
ipv6(options?: RuleOptions): BuiltinRule<string>;
|
|
66
|
+
cidr(options?: RuleOptions): BuiltinRule<string>;
|
|
67
|
+
cidrv4(options?: RuleOptions): BuiltinRule<string>;
|
|
68
|
+
cidrv6(options?: RuleOptions): BuiltinRule<string>;
|
|
69
|
+
mac(options?: import("./StringRules.js").MacOptions): BuiltinRule<string>;
|
|
70
|
+
creditCard(options?: RuleOptions): BuiltinRule<string>;
|
|
71
|
+
iban(options?: RuleOptions): BuiltinRule<string>;
|
|
72
|
+
currencyCode(options?: RuleOptions): BuiltinRule<string>;
|
|
73
|
+
hash(algorithm: import("./StringRules.js").HashAlgorithm, options?: import("./StringRules.js").HashOptions): BuiltinRule<string>;
|
|
74
|
+
isoDate(options?: RuleOptions): BuiltinRule<string>;
|
|
75
|
+
isoTime(options?: import("./StringRules.js").IsoTimeOptions): BuiltinRule<string>;
|
|
76
|
+
isoDateTime(options?: import("./StringRules.js").IsoDateTimeOptions): BuiltinRule<string>;
|
|
77
|
+
isoDuration(options?: RuleOptions): BuiltinRule<string>;
|
|
78
|
+
number: (options?: RuleOptions) => BuiltinRule<number, unknown, unknown>;
|
|
79
|
+
finite: (options?: RuleOptions) => BuiltinRule<number, unknown, unknown>;
|
|
80
|
+
bigint: (options?: RuleOptions) => BuiltinRule<bigint, unknown, unknown>;
|
|
81
|
+
boolean: (options?: RuleOptions) => BuiltinRule<boolean, unknown, unknown>;
|
|
82
|
+
date: (options?: RuleOptions) => BuiltinRule<Date, unknown, unknown>;
|
|
83
|
+
symbol: (options?: RuleOptions) => BuiltinRule<symbol, unknown, unknown>;
|
|
84
|
+
literal: <const T extends string | number | bigint | boolean | null>(expected: T, options?: RuleOptions) => BuiltinRule<T, unknown, unknown>;
|
|
85
|
+
enum: <const T extends readonly (string | number | bigint | boolean | null)[] | Readonly<Record<string, string | number>>>(enumeration: T, options?: RuleOptions) => BuiltinRule<T extends readonly (infer V)[] ? V : T[keyof T], unknown, unknown>;
|
|
86
|
+
enumName: <const T extends Readonly<Record<string, string | number>>>(enumeration: T, options?: RuleOptions) => BuiltinRule<Extract<keyof T, string>, unknown, unknown>;
|
|
87
|
+
integer: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
88
|
+
int32: (options?: RuleOptions) => BuiltinRule<number, unknown, unknown>;
|
|
89
|
+
uint32: (options?: RuleOptions) => BuiltinRule<number, unknown, unknown>;
|
|
90
|
+
float32: (options?: RuleOptions) => BuiltinRule<number, unknown, unknown>;
|
|
91
|
+
int64: (options?: RuleOptions) => BuiltinRule<bigint, unknown, unknown>;
|
|
92
|
+
uint64: (options?: RuleOptions) => BuiltinRule<bigint, unknown, unknown>;
|
|
93
|
+
safeInteger: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
94
|
+
positive: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
95
|
+
negative: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
96
|
+
nonNegative: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
97
|
+
nonPositive: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
98
|
+
min: (min: Date | (number | bigint), options?: import("./ValueRules.js").ValueRangeOptions) => BuiltinRule<never, unknown, unknown>;
|
|
99
|
+
max: (max: Date | (number | bigint), options?: import("./ValueRules.js").ValueRangeOptions) => BuiltinRule<never, unknown, unknown>;
|
|
100
|
+
lessThan: (max: Date | (number | bigint), options?: import("./ValueRules.js").ValueRangeOptions) => BuiltinRule<never, unknown, unknown>;
|
|
101
|
+
greaterThan: (min: Date | (number | bigint), options?: import("./ValueRules.js").ValueRangeOptions) => BuiltinRule<never, unknown, unknown>;
|
|
102
|
+
lessThanOrEqual: (max: Date | (number | bigint), options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
103
|
+
greaterThanOrEqual: (min: Date | (number | bigint), options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
104
|
+
between: (min: Date | (number | bigint), max: Date | (number | bigint), options?: import("./ValueRules.js").ValueRangeOptions) => BuiltinRule<never, unknown, unknown>;
|
|
105
|
+
multipleOf: (divisor: number | bigint, options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
106
|
+
decimal: (places?: number, options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
107
|
+
precisionScale: (precision: number, scale: number, options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
108
|
+
equal: (expected: unknown, options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
109
|
+
notEqual: (expected: unknown, options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
110
|
+
notNull: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
111
|
+
required: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
112
|
+
notEmpty: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
113
|
+
empty: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
114
|
+
unknown: (options?: RuleOptions) => BuiltinRule<unknown, unknown, unknown>;
|
|
115
|
+
never: (options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
116
|
+
null: (options?: RuleOptions) => BuiltinRule<null, unknown, unknown>;
|
|
117
|
+
undefined: (options?: RuleOptions) => BuiltinRule<undefined, unknown, unknown>;
|
|
118
|
+
nan: (options?: RuleOptions) => BuiltinRule<number, unknown, unknown>;
|
|
119
|
+
instanceOf: <T>(constructor: abstract new (...args: any[]) => T, options?: RuleOptions) => BuiltinRule<T, unknown, unknown>;
|
|
120
|
+
file: (options?: import("./ValueRules.js").ValueFileOptions) => BuiltinRule<import("buffer").File, unknown, unknown>;
|
|
121
|
+
blob: (options?: import("./ValueRules.js").ValueFileOptions) => BuiltinRule<import("buffer").Blob, unknown, unknown>;
|
|
122
|
+
before: (target: Date, options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
123
|
+
after: (target: Date, options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
124
|
+
same: (target: Date, options?: RuleOptions) => BuiltinRule<never, unknown, unknown>;
|
|
125
|
+
isPast: (options?: import("./ValueRules.js").ValueClockOptions) => BuiltinRule<never, unknown, unknown>;
|
|
126
|
+
isFuture: (options?: import("./ValueRules.js").ValueClockOptions) => BuiltinRule<never, unknown, unknown>;
|
|
127
|
+
}>;
|
|
128
|
+
export type TypedRules<T extends object, C = unknown> = Omit<typeof rules, "sameAs" | "notSameAs" | "object" | "array" | "record" | "map" | "set" | "tuple"> & {
|
|
129
|
+
sameAs(key: keyof T & string, options?: RuleOptions): BuiltinRule<never>;
|
|
130
|
+
notSameAs(key: keyof T & string, options?: RuleOptions): BuiltinRule<never>;
|
|
131
|
+
object<V extends object>(shape: {
|
|
132
|
+
[K in keyof V]: K extends string | number ? readonly [
|
|
133
|
+
BuiltinRule<V[K], C, T>,
|
|
134
|
+
...FieldRule<V[K], NoInfer<V>, T, C>[]
|
|
135
|
+
] : never;
|
|
136
|
+
}, options?: RuleOptions & {
|
|
137
|
+
unknownKeys?: "reject" | "allow";
|
|
138
|
+
}): BuiltinRule<V, C, T>;
|
|
139
|
+
object<V extends object>(shape: ValidationRules<V, T, C>, options?: RuleOptions & {
|
|
140
|
+
unknownKeys?: "reject" | "allow";
|
|
141
|
+
}): BuiltinRule<V, C, T>;
|
|
142
|
+
array<V>(items: readonly FieldRule<V, V[], T, C>[], options?: RuleOptions): BuiltinRule<V[], C, T>;
|
|
143
|
+
record<V>(items: readonly FieldRule<V, Record<string, V>, T, C>[], options?: RuleOptions, keys?: readonly FieldRule<string, Record<string, V>, T, C>[]): BuiltinRule<Record<string, V>, C, T>;
|
|
144
|
+
map<K, V>(keys: readonly FieldRule<K, Map<K, V>, T, C>[], items: readonly FieldRule<V, Map<K, V>, T, C>[], options?: RuleOptions): BuiltinRule<Map<K, V>, C, T>;
|
|
145
|
+
set<V>(items: readonly FieldRule<V, Set<V>, T, C>[], options?: RuleOptions): BuiltinRule<Set<V>, C, T>;
|
|
146
|
+
tuple<V extends readonly unknown[]>(items: {
|
|
147
|
+
readonly [K in keyof V]: readonly FieldRule<V[K], V, T, C>[];
|
|
148
|
+
}, options?: RuleOptions): BuiltinRule<V, C, T>;
|
|
149
|
+
};
|
|
150
|
+
/** Binds root/context types for nested callbacks and sibling keys for comparisons. */
|
|
151
|
+
export declare function createRules<T extends object, C = unknown>(): TypedRules<T, C>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { structureRules } from "./StructureRules.js";
|
|
2
|
+
import { stringRules } from "./StringRules.js";
|
|
3
|
+
import { valueRules } from "./ValueRules.js";
|
|
4
|
+
import { customRules } from "./CustomRules.js";
|
|
5
|
+
import { validatorDefinition } from "../Symbols.js";
|
|
6
|
+
export const rules = Object.freeze({
|
|
7
|
+
...valueRules,
|
|
8
|
+
...stringRules,
|
|
9
|
+
...structureRules,
|
|
10
|
+
...customRules,
|
|
11
|
+
});
|
|
12
|
+
/** Binds root/context types for nested callbacks and sibling keys for comparisons. */
|
|
13
|
+
export function createRules() {
|
|
14
|
+
return Object.freeze({
|
|
15
|
+
...rules,
|
|
16
|
+
sameAs: (key, options) => structureRules.sameAs(key, options),
|
|
17
|
+
notSameAs: (key, options) => structureRules.notSameAs(key, options),
|
|
18
|
+
});
|
|
19
|
+
}
|