@clementine-solutions/jane-io 1.0.1 → 1.0.2
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/core/analysis/diff.js +88 -0
- package/dist/core/analysis/explain.js +117 -0
- package/dist/core/analysis/index.js +26 -0
- package/dist/core/analysis/replay.js +68 -0
- package/dist/core/analysis/telemetry.js +123 -0
- package/dist/core/boundary-rules/at-most-one.js +38 -0
- package/dist/core/boundary-rules/conditionally-required.js +44 -0
- package/dist/core/boundary-rules/date-range.js +39 -0
- package/dist/core/boundary-rules/index.js +21 -0
- package/dist/core/boundary-rules/mutually-exclusive.js +38 -0
- package/dist/core/boundary-rules/no-unknown-fields.js +39 -0
- package/dist/core/boundary-rules/require-all.js +39 -0
- package/dist/core/boundary-rules/require-one.js +41 -0
- package/dist/core/common/events.js +82 -0
- package/dist/core/common/fluent.js +429 -0
- package/dist/core/common/index.js +31 -0
- package/dist/core/common/policy.js +550 -0
- package/dist/core/common/utilities.js +177 -0
- package/dist/core/common/wildcard.js +63 -0
- package/dist/core/field-path/construct.js +189 -0
- package/dist/core/field-path/format.js +154 -0
- package/dist/core/field-path/index.js +26 -0
- package/dist/core/field-path/utilities.js +138 -0
- package/dist/core/field-path/walk.js +80 -0
- package/dist/core/fluent-registry.js +151 -0
- package/dist/core/normalizers/array/compact-sparse-array.js +40 -0
- package/dist/core/normalizers/array/flatten-one-level.js +45 -0
- package/dist/core/normalizers/array/remove-empty-string-items.js +34 -0
- package/dist/core/normalizers/array/remove-null-items.js +34 -0
- package/dist/core/normalizers/array/remove-undefined-items.js +34 -0
- package/dist/core/normalizers/date/invalid-date-to-undefined.js +35 -0
- package/dist/core/normalizers/index.js +46 -0
- package/dist/core/normalizers/normalizer-register.js +41 -0
- package/dist/core/normalizers/number/infinity-to-undefined.js +35 -0
- package/dist/core/normalizers/number/nan-to-undefined.js +34 -0
- package/dist/core/normalizers/number/normalize-negative-zero.js +33 -0
- package/dist/core/normalizers/object/remove-empty-array-keys.js +38 -0
- package/dist/core/normalizers/object/remove-empty-object-keys.js +42 -0
- package/dist/core/normalizers/object/remove-empty-string-keys.js +37 -0
- package/dist/core/normalizers/object/remove-null-keys.js +37 -0
- package/dist/core/normalizers/object/remove-undefined-keys.js +37 -0
- package/dist/core/normalizers/string/collapse-whitespace.js +35 -0
- package/dist/core/normalizers/string/empty-to-undefined.js +33 -0
- package/dist/core/normalizers/string/trim.js +34 -0
- package/dist/core/parsers/index.js +43 -0
- package/dist/core/parsers/parse-array-string.js +36 -0
- package/dist/core/parsers/parse-bigint-string.js +33 -0
- package/dist/core/parsers/parse-binary-string.js +33 -0
- package/dist/core/parsers/parse-boolean-string.js +27 -0
- package/dist/core/parsers/parse-date-string.js +30 -0
- package/dist/core/parsers/parse-duration-string.js +37 -0
- package/dist/core/parsers/parse-hex-string.js +29 -0
- package/dist/core/parsers/parse-integer-string.js +30 -0
- package/dist/core/parsers/parse-json-string.js +35 -0
- package/dist/core/parsers/parse-numeric-string.js +29 -0
- package/dist/core/parsers/parse-object-string.js +36 -0
- package/dist/core/parsers/parse-octal-string.js +33 -0
- package/dist/core/parsers/parse-scientific-notation-string.js +30 -0
- package/dist/core/parsers/parse-url-string.js +36 -0
- package/dist/core/pipeline/boundary.js +256 -0
- package/dist/core/pipeline/contain.js +339 -0
- package/dist/core/pipeline/index.js +37 -0
- package/dist/core/pipeline/normalize.js +76 -0
- package/dist/core/pipeline/parse.js +91 -0
- package/dist/core/pipeline/pipeline.js +418 -0
- package/dist/core/pipeline/scan.js +115 -0
- package/dist/core/pipeline/validate.js +74 -0
- package/dist/core/scanners/any/scan-for-sentinels.js +35 -0
- package/dist/core/scanners/array/array-is-deep.js +38 -0
- package/dist/core/scanners/array/array-is-heterogenous.js +39 -0
- package/dist/core/scanners/array/array-is-large.js +32 -0
- package/dist/core/scanners/bigint/bigint-is-large.js +34 -0
- package/dist/core/scanners/bigint/bigint-not-safe.js +34 -0
- package/dist/core/scanners/date/date-is-before-epoch.js +32 -0
- package/dist/core/scanners/date/date-is-far-future.js +32 -0
- package/dist/core/scanners/date/date-is-invalid.js +31 -0
- package/dist/core/scanners/index.js +58 -0
- package/dist/core/scanners/number/number-is-infinite.js +31 -0
- package/dist/core/scanners/number/number-is-nan.js +31 -0
- package/dist/core/scanners/number/number-is-too-large.js +33 -0
- package/dist/core/scanners/number/number-is-unsafe-integer.js +31 -0
- package/dist/core/scanners/object/object-has-circular-references.js +43 -0
- package/dist/core/scanners/object/object-has-many-keys.js +33 -0
- package/dist/core/scanners/object/object-is-deep.js +38 -0
- package/dist/core/scanners/scanner-registry.js +36 -0
- package/dist/core/scanners/string/string-has-unsafe-unicode.js +32 -0
- package/dist/core/scanners/string/string-has-whitespace-edges.js +31 -0
- package/dist/core/scanners/string/string-is-long.js +32 -0
- package/dist/core/scanners/unknown/unknown-not-scannable.js +34 -0
- package/dist/core/shapes/analysis.js +11 -0
- package/dist/core/shapes/boundary.js +11 -0
- package/dist/core/shapes/events.js +10 -0
- package/dist/core/shapes/field-path.js +10 -0
- package/dist/core/shapes/index.js +11 -0
- package/dist/core/shapes/normalize.js +11 -0
- package/dist/core/shapes/parse.js +11 -0
- package/dist/core/shapes/pipeline.js +11 -0
- package/dist/core/shapes/policy.js +11 -0
- package/dist/core/shapes/public.js +10 -0
- package/dist/core/shapes/scan.js +11 -0
- package/dist/core/shapes/validate.js +11 -0
- package/dist/core/validators/array/array-max-items.js +42 -0
- package/dist/core/validators/array/array-min-items.js +42 -0
- package/dist/core/validators/array/array.js +34 -0
- package/dist/core/validators/array/excludes.js +47 -0
- package/dist/core/validators/array/has-unique-items.js +46 -0
- package/dist/core/validators/array/includes.js +46 -0
- package/dist/core/validators/array/items-equal.js +42 -0
- package/dist/core/validators/array/no-empty-string-items.js +46 -0
- package/dist/core/validators/array/no-null-items.js +46 -0
- package/dist/core/validators/array/no-undefined-items.js +45 -0
- package/dist/core/validators/array/non-empty-array.js +45 -0
- package/dist/core/validators/array/not-sparse.js +44 -0
- package/dist/core/validators/bigint/bigint-equals.js +57 -0
- package/dist/core/validators/bigint/bigint-max.js +63 -0
- package/dist/core/validators/bigint/bigint-min.js +87 -0
- package/dist/core/validators/bigint/bigint-negative.js +73 -0
- package/dist/core/validators/bigint/bigint-non-negative.js +72 -0
- package/dist/core/validators/bigint/bigint-non-positive.js +72 -0
- package/dist/core/validators/bigint/bigint-positive.js +72 -0
- package/dist/core/validators/bigint/bigint-safe.js +75 -0
- package/dist/core/validators/bigint/bigint.js +38 -0
- package/dist/core/validators/boolean/boolean.js +39 -0
- package/dist/core/validators/boolean/is-false.js +48 -0
- package/dist/core/validators/boolean/is-true.js +48 -0
- package/dist/core/validators/common/is-country-code.js +36 -0
- package/dist/core/validators/common/is-currency-code.js +36 -0
- package/dist/core/validators/common/is-email-strict.js +36 -0
- package/dist/core/validators/common/is-email.js +36 -0
- package/dist/core/validators/common/is-ip.js +37 -0
- package/dist/core/validators/common/is-phone-strict.js +36 -0
- package/dist/core/validators/common/is-phone.js +36 -0
- package/dist/core/validators/common/is-port.js +35 -0
- package/dist/core/validators/common/is-postal-code.js +36 -0
- package/dist/core/validators/common/is-url.js +38 -0
- package/dist/core/validators/common/is-uuid.js +36 -0
- package/dist/core/validators/date/before-epoch.js +56 -0
- package/dist/core/validators/date/date-now-required.js +48 -0
- package/dist/core/validators/date/is-date.js +47 -0
- package/dist/core/validators/date/is-far-future.js +46 -0
- package/dist/core/validators/date/is-future.js +59 -0
- package/dist/core/validators/date/is-past.js +59 -0
- package/dist/core/validators/date/not-after.js +66 -0
- package/dist/core/validators/date/not-before.js +66 -0
- package/dist/core/validators/date/same-day.js +60 -0
- package/dist/core/validators/date/same-month.js +59 -0
- package/dist/core/validators/date/same-year.js +56 -0
- package/dist/core/validators/date/too-early.js +57 -0
- package/dist/core/validators/date/too-late.js +57 -0
- package/dist/core/validators/date/weekday.js +65 -0
- package/dist/core/validators/date/weekend.js +56 -0
- package/dist/core/validators/index.js +139 -0
- package/dist/core/validators/nullish/is-null-or-undefined.js +40 -0
- package/dist/core/validators/nullish/is-null.js +39 -0
- package/dist/core/validators/nullish/is-undefined.js +39 -0
- package/dist/core/validators/number/finite.js +40 -0
- package/dist/core/validators/number/integer.js +40 -0
- package/dist/core/validators/number/less-than.js +39 -0
- package/dist/core/validators/number/max.js +39 -0
- package/dist/core/validators/number/min.js +39 -0
- package/dist/core/validators/number/more-than.js +39 -0
- package/dist/core/validators/number/negative.js +38 -0
- package/dist/core/validators/number/non-negative.js +37 -0
- package/dist/core/validators/number/non-positive.js +37 -0
- package/dist/core/validators/number/number.js +31 -0
- package/dist/core/validators/number/positive.js +38 -0
- package/dist/core/validators/number/safe-integer.js +42 -0
- package/dist/core/validators/object/deep-equals.js +47 -0
- package/dist/core/validators/object/has-key.js +42 -0
- package/dist/core/validators/object/has-value.js +59 -0
- package/dist/core/validators/object/keys-equal.js +47 -0
- package/dist/core/validators/object/max-keys.js +43 -0
- package/dist/core/validators/object/min-keys.js +43 -0
- package/dist/core/validators/object/missing-key.js +42 -0
- package/dist/core/validators/object/no-empty-array-values.js +44 -0
- package/dist/core/validators/object/no-empty-object-values.js +44 -0
- package/dist/core/validators/object/no-null-values.js +44 -0
- package/dist/core/validators/object/no-undefined-values.js +44 -0
- package/dist/core/validators/object/non-empty-object.js +40 -0
- package/dist/core/validators/object/only-keys.js +43 -0
- package/dist/core/validators/object/plain-object.js +35 -0
- package/dist/core/validators/string/alpha-num.js +50 -0
- package/dist/core/validators/string/alpha.js +51 -0
- package/dist/core/validators/string/chars-equal.js +49 -0
- package/dist/core/validators/string/ends-with.js +50 -0
- package/dist/core/validators/string/is-ascii.js +53 -0
- package/dist/core/validators/string/is-printable.js +53 -0
- package/dist/core/validators/string/matches.js +50 -0
- package/dist/core/validators/string/max-length.js +50 -0
- package/dist/core/validators/string/min-length.js +50 -0
- package/dist/core/validators/string/no-lead-space.js +50 -0
- package/dist/core/validators/string/no-repeat-space.js +52 -0
- package/dist/core/validators/string/no-space.js +51 -0
- package/dist/core/validators/string/no-trail-space.js +50 -0
- package/dist/core/validators/string/non-empty.js +48 -0
- package/dist/core/validators/string/not-one-of.js +51 -0
- package/dist/core/validators/string/num-string.js +50 -0
- package/dist/core/validators/string/one-of.js +50 -0
- package/dist/core/validators/string/starts-with.js +50 -0
- package/dist/core/validators/string/string.js +39 -0
- package/dist/core/validators/string/trimmed.js +51 -0
- package/dist/index.js +26 -0
- package/dist/test.js +12 -0
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Same Year
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Ensures the input is a Date instance representing a date in
|
|
7
|
+
* the same calendar year as the provided `other` date.
|
|
8
|
+
* @see https://jane-io.com
|
|
9
|
+
* ----------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
import { validationEvent } from '../../pipeline';
|
|
12
|
+
import { safeStringify } from '../../common';
|
|
13
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
14
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
15
|
+
|* Implementation *|
|
|
16
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
17
|
+
/**
|
|
18
|
+
* Ensures the input is a Date instance representing a date in the
|
|
19
|
+
* same calendar year as the provided `other` date.
|
|
20
|
+
*
|
|
21
|
+
* - Non-Date values emit `date.not.date`.
|
|
22
|
+
* - Invalid Date instances emit `date.is.invalid`.
|
|
23
|
+
* - Dates not matching the same year emit `date.not.same-year`.
|
|
24
|
+
*
|
|
25
|
+
* This rule is pure, total, async-compatible, and preserves the
|
|
26
|
+
* provided path. It supports userMessage overrides applied at the
|
|
27
|
+
* pipeline level.
|
|
28
|
+
*/
|
|
29
|
+
export const sameYear = (other) => {
|
|
30
|
+
const rule = async (value, path) => {
|
|
31
|
+
const structuralType = detectStructuralType(value);
|
|
32
|
+
if (!(value instanceof Date)) {
|
|
33
|
+
return [
|
|
34
|
+
validationEvent('error', 'date.not.date', path, `Expected 'Date' but received '${structuralType}'.`, `Please provide a valid date.`, { value, expected: 'Date', actual: structuralType }),
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
if (isNaN(value.getTime())) {
|
|
38
|
+
return [
|
|
39
|
+
validationEvent('error', 'date.is.invalid', path, `Date value is invalid.`, `Please provide a valid date.`, { value, expected: 'valid Date', actual: value }),
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
if (value.getUTCFullYear() !== other.getUTCFullYear()) {
|
|
43
|
+
return [
|
|
44
|
+
validationEvent('error', 'date.not.same-year', path, `${safeStringify(value)} must be in the same year as ${other.toISOString()}.`, `Please provide a date in the correct year.`, {
|
|
45
|
+
value,
|
|
46
|
+
expected: other.toISOString().slice(0, 4),
|
|
47
|
+
actual: value.toISOString().slice(0, 4),
|
|
48
|
+
}),
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
};
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
rule.__janeFactory = true;
|
|
55
|
+
return rule;
|
|
56
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Too Early
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Ensures the input is a Date instance that is not earlier
|
|
7
|
+
* than the provided `min` boundary.
|
|
8
|
+
* @see https://jane-io.com
|
|
9
|
+
* ----------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
import { validationEvent } from '../../pipeline';
|
|
12
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
13
|
+
import { safeStringify } from '../../common';
|
|
14
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
15
|
+
|* Implementation *|
|
|
16
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
17
|
+
/**
|
|
18
|
+
* Ensures the input is a Date instance that is not earlier than the
|
|
19
|
+
* provided `min` boundary. The comparison is inclusive: value must be
|
|
20
|
+
* ≥ min.
|
|
21
|
+
*
|
|
22
|
+
* - Non-Date values emit `date.not.date`.
|
|
23
|
+
* - Invalid Date instances emit `date.is.invalid`.
|
|
24
|
+
* - Dates < min emit `date.too.early`.
|
|
25
|
+
*
|
|
26
|
+
* This rule is pure, total, async-compatible, and preserves the
|
|
27
|
+
* provided path. It supports userMessage overrides applied at the
|
|
28
|
+
* pipeline level.
|
|
29
|
+
*/
|
|
30
|
+
export const tooEarly = (min) => {
|
|
31
|
+
const rule = async (value, path) => {
|
|
32
|
+
const structuralType = detectStructuralType(value);
|
|
33
|
+
if (!(value instanceof Date)) {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'date.not.date', path, `Expected 'Date' but received '${structuralType}'.`, `Please provide a valid date.`, { value, expected: 'Date', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
if (isNaN(value.getTime())) {
|
|
39
|
+
return [
|
|
40
|
+
validationEvent('error', 'date.is.invalid', path, `Date value is invalid.`, `Please provide a valid date.`, { value, expected: 'valid Date', actual: value }),
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
if (value.getTime() < min.getTime()) {
|
|
44
|
+
return [
|
|
45
|
+
validationEvent('error', 'date.too.early', path, `${safeStringify(value)} must not be earlier than ${min.toISOString()}.`, `Please provide a later date.`, {
|
|
46
|
+
value: value.toISOString(),
|
|
47
|
+
expected: `>= ${min.toISOString()}`,
|
|
48
|
+
actual: value.toISOString(),
|
|
49
|
+
}),
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
return [];
|
|
53
|
+
};
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
rule.__janeFactory = true;
|
|
56
|
+
return rule;
|
|
57
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Too Early
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Ensures the input is a Date instance that is not later than
|
|
7
|
+
* the provided `max` boundary.
|
|
8
|
+
* @see https://jane-io.com
|
|
9
|
+
* ----------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
import { validationEvent } from '../../pipeline';
|
|
12
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
13
|
+
import { safeStringify } from '../../common';
|
|
14
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
15
|
+
|* Implementation *|
|
|
16
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
17
|
+
/**
|
|
18
|
+
* Ensures the input is a Date instance that is not later than the
|
|
19
|
+
* provided `max` boundary. The comparison is inclusive: value must be
|
|
20
|
+
* ≤ max.
|
|
21
|
+
*
|
|
22
|
+
* - Non-Date values emit `date.not.date`.
|
|
23
|
+
* - Invalid Date instances emit `date.is.invalid`.
|
|
24
|
+
* - Dates > max emit `date.too.late`.
|
|
25
|
+
*
|
|
26
|
+
* This rule is pure, total, async-compatible, and preserves the
|
|
27
|
+
* provided path. It supports userMessage overrides applied at the
|
|
28
|
+
* pipeline level.
|
|
29
|
+
*/
|
|
30
|
+
export const tooLate = (max) => {
|
|
31
|
+
const rule = async (value, path) => {
|
|
32
|
+
const structuralType = detectStructuralType(value);
|
|
33
|
+
if (!(value instanceof Date)) {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'date.not.date', path, `Expected 'Date' but received '${structuralType}'.`, `Please provide a valid date.`, { value, expected: 'Date', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
if (isNaN(value.getTime())) {
|
|
39
|
+
return [
|
|
40
|
+
validationEvent('error', 'date.is.invalid', path, `Date value is invalid.`, `Please provide a valid date.`, { value, expected: 'valid Date', actual: value }),
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
if (value.getTime() > max.getTime()) {
|
|
44
|
+
return [
|
|
45
|
+
validationEvent('error', 'date.too.late', path, `${safeStringify(value)} must not be later than ${max.toISOString()}.`, `Please provide an earlier date.`, {
|
|
46
|
+
value: value.toISOString(),
|
|
47
|
+
expected: `<= ${max.toISOString()}`,
|
|
48
|
+
actual: value.toISOString(),
|
|
49
|
+
}),
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
return [];
|
|
53
|
+
};
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
rule.__janeFactory = true;
|
|
56
|
+
return rule;
|
|
57
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Weekday
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Ensures the input is a Date instance whose weekday (0–6)
|
|
7
|
+
* matches the required weekday.
|
|
8
|
+
* @see https://jane-io.com
|
|
9
|
+
* ----------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
import { validationEvent } from '../../pipeline';
|
|
12
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
13
|
+
import { safeStringify } from '../../common';
|
|
14
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
15
|
+
|* Implementation *|
|
|
16
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
17
|
+
/**
|
|
18
|
+
* Ensures the input is a Date instance whose weekday (0–6) matches
|
|
19
|
+
* the required weekday. JavaScript uses:
|
|
20
|
+
*
|
|
21
|
+
* 0 = Sunday
|
|
22
|
+
* 1 = Monday
|
|
23
|
+
* 2 = Tuesday
|
|
24
|
+
* 3 = Wednesday
|
|
25
|
+
* 4 = Thursday
|
|
26
|
+
* 5 = Friday
|
|
27
|
+
* 6 = Saturday
|
|
28
|
+
*
|
|
29
|
+
* - Non-Date values emit `date.not.date`.
|
|
30
|
+
* - Invalid Date instances emit `date.is.invalid`.
|
|
31
|
+
* - Mismatched weekdays emit `date.not.weekday`.
|
|
32
|
+
*
|
|
33
|
+
* This rule is pure, total, async-compatible, and preserves the
|
|
34
|
+
* provided path. It supports userMessage overrides applied at the
|
|
35
|
+
* pipeline level.
|
|
36
|
+
*/
|
|
37
|
+
export const weekday = (required) => {
|
|
38
|
+
const rule = async (value, path) => {
|
|
39
|
+
const structuralType = detectStructuralType(value);
|
|
40
|
+
if (!(value instanceof Date)) {
|
|
41
|
+
return [
|
|
42
|
+
validationEvent('error', 'date.not.date', path, `Expected 'Date' but received '${structuralType}'.`, `Please provide a valid date.`, { value, expected: 'Date', actual: structuralType }),
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
if (isNaN(value.getTime())) {
|
|
46
|
+
return [
|
|
47
|
+
validationEvent('error', 'date.is.invalid', path, `Date value is invalid.`, `Please provide a valid date.`, { value, expected: 'valid Date', actual: value }),
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
const actualWeekday = value.getUTCDay();
|
|
51
|
+
if (actualWeekday !== required) {
|
|
52
|
+
return [
|
|
53
|
+
validationEvent('error', 'date.not.weekday', path, `${safeStringify(value)} must fall on weekday ${required}.`, `Please provide a date on the correct weekday.`, {
|
|
54
|
+
value: value.toISOString(),
|
|
55
|
+
expected: required,
|
|
56
|
+
actual: actualWeekday,
|
|
57
|
+
}),
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
return [];
|
|
61
|
+
};
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
|
+
rule.__janeFactory = true;
|
|
64
|
+
return rule;
|
|
65
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Weekend
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Ensures the input is a Date instance that falls on a
|
|
7
|
+
* weekend.
|
|
8
|
+
* @see https://jane-io.com
|
|
9
|
+
* ----------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
import { validationEvent } from '../../pipeline';
|
|
12
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
13
|
+
import { safeStringify } from '../../common';
|
|
14
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
15
|
+
|* Implementation *|
|
|
16
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
17
|
+
/**
|
|
18
|
+
* Ensures the input is a Date instance that falls on a weekend.
|
|
19
|
+
*
|
|
20
|
+
* JavaScript weekday values:
|
|
21
|
+
* 0 = Sunday
|
|
22
|
+
* 6 = Saturday
|
|
23
|
+
*
|
|
24
|
+
* - Non-Date values emit `date.not.date`.
|
|
25
|
+
* - Invalid Date instances emit `date.is.invalid`.
|
|
26
|
+
* - Weekdays (1–5) emit `date.not.weekend`.
|
|
27
|
+
*
|
|
28
|
+
* This rule is pure, total, async-compatible, and preserves the
|
|
29
|
+
* provided path. It supports userMessage overrides applied at the
|
|
30
|
+
* pipeline level.
|
|
31
|
+
*/
|
|
32
|
+
export const weekend = async (value, path) => {
|
|
33
|
+
const structuralType = detectStructuralType(value);
|
|
34
|
+
if (!(value instanceof Date)) {
|
|
35
|
+
return [
|
|
36
|
+
validationEvent('error', 'date.not.date', path, `Expected 'Date' but received '${structuralType}'.`, `Please provide a valid date.`, { value, expected: 'Date', actual: structuralType }),
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
if (isNaN(value.getTime())) {
|
|
40
|
+
return [
|
|
41
|
+
validationEvent('error', 'date.is.invalid', path, `Date value is invalid.`, `Please provide a valid date.`, { value, expected: 'valid Date', actual: value }),
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
const weekday = value.getUTCDay();
|
|
45
|
+
const isWeekend = weekday === 0 || weekday === 6;
|
|
46
|
+
if (!isWeekend) {
|
|
47
|
+
return [
|
|
48
|
+
validationEvent('error', 'date.not.weekend', path, `${safeStringify(value)} must fall on a weekend.`, `Please provide a Saturday or Sunday date.`, {
|
|
49
|
+
value: value.toISOString(),
|
|
50
|
+
expected: 'weekend',
|
|
51
|
+
actual: weekday,
|
|
52
|
+
}),
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Barrel File
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Re‑exports all built‑in validation rules, providing a single
|
|
7
|
+
* cohesive entry point for Jane’s validation subsystem. This
|
|
8
|
+
* keeps contributor onboarding simple and ensures consistent,
|
|
9
|
+
* predictable resolution of validator names across the
|
|
10
|
+
* framework.
|
|
11
|
+
* @see https://jane-io.com
|
|
12
|
+
* ----------------------------------------------------------------------------
|
|
13
|
+
*/
|
|
14
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
15
|
+
|* Array Values *|
|
|
16
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
17
|
+
export { array } from './array/array';
|
|
18
|
+
export { arrayMaxItems } from './array/array-max-items';
|
|
19
|
+
export { arrayMinItems } from './array/array-min-items';
|
|
20
|
+
export { excludes } from './array/excludes';
|
|
21
|
+
export { hasUniqueItems } from './array/has-unique-items';
|
|
22
|
+
export { includes } from './array/includes';
|
|
23
|
+
export { itemsEqual } from './array/items-equal';
|
|
24
|
+
export { noEmptyStringItems } from './array/no-empty-string-items';
|
|
25
|
+
export { noNullItems } from './array/no-null-items';
|
|
26
|
+
export { noUndefinedItems } from './array/no-undefined-items';
|
|
27
|
+
export { nonEmptyArray } from './array/non-empty-array';
|
|
28
|
+
export { notSparse } from './array/not-sparse';
|
|
29
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
30
|
+
|* Bigint Values *|
|
|
31
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
32
|
+
export { bigint } from './bigint/bigint';
|
|
33
|
+
export { bigintEquals } from './bigint/bigint-equals';
|
|
34
|
+
export { bigintMax } from './bigint/bigint-max';
|
|
35
|
+
export { bigintMin } from './bigint/bigint-min';
|
|
36
|
+
export { bigintNegative } from './bigint/bigint-negative';
|
|
37
|
+
export { bigintNonNegative } from './bigint/bigint-non-negative';
|
|
38
|
+
export { bigintNonPositive } from './bigint/bigint-non-positive';
|
|
39
|
+
export { bigintPositive } from './bigint/bigint-positive';
|
|
40
|
+
export { bigintSafe } from './bigint/bigint-safe';
|
|
41
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
42
|
+
|* Boolean Values *|
|
|
43
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
44
|
+
export { boolean } from './boolean/boolean';
|
|
45
|
+
export { isFalse } from './boolean/is-false';
|
|
46
|
+
export { isTrue } from './boolean/is-true';
|
|
47
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
48
|
+
|* Common Values *|
|
|
49
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
50
|
+
export { isCountryCode } from './common/is-country-code';
|
|
51
|
+
export { isCurrencyCode } from './common/is-currency-code';
|
|
52
|
+
export { isEmail } from './common/is-email';
|
|
53
|
+
export { isEmailStrict } from './common/is-email-strict';
|
|
54
|
+
export { isIp } from './common/is-ip';
|
|
55
|
+
export { isPhone } from './common/is-phone';
|
|
56
|
+
export { isPhoneStrict } from './common/is-phone-strict';
|
|
57
|
+
export { isPort } from './common/is-port';
|
|
58
|
+
export { isPostalCode } from './common/is-postal-code';
|
|
59
|
+
export { isUrl } from './common/is-url';
|
|
60
|
+
export { isUuid } from './common/is-uuid';
|
|
61
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
62
|
+
|* Date Values *|
|
|
63
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
64
|
+
export { beforeEpoch } from './date/before-epoch';
|
|
65
|
+
export { dateNowRequired } from './date/date-now-required';
|
|
66
|
+
export { isDate } from './date/is-date';
|
|
67
|
+
export { isFarFuture } from './date/is-far-future';
|
|
68
|
+
export { isFuture } from './date/is-future';
|
|
69
|
+
export { isPast } from './date/is-past';
|
|
70
|
+
export { notAfter } from './date/not-after';
|
|
71
|
+
export { notBefore } from './date/not-before';
|
|
72
|
+
export { sameDay } from './date/same-day';
|
|
73
|
+
export { sameMonth } from './date/same-month';
|
|
74
|
+
export { sameYear } from './date/same-year';
|
|
75
|
+
export { tooEarly } from './date/too-early';
|
|
76
|
+
export { tooLate } from './date/too-late';
|
|
77
|
+
export { weekday } from './date/weekday';
|
|
78
|
+
export { weekend } from './date/weekend';
|
|
79
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
80
|
+
|* Nullish Values *|
|
|
81
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
82
|
+
export { isNull } from './nullish/is-null';
|
|
83
|
+
export { isNullOrUndefined } from './nullish/is-null-or-undefined';
|
|
84
|
+
export { isUndefined } from './nullish/is-undefined';
|
|
85
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
86
|
+
|* Number Values *|
|
|
87
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
88
|
+
export { finite } from './number/finite';
|
|
89
|
+
export { integer } from './number/integer';
|
|
90
|
+
export { lessThan } from './number/less-than';
|
|
91
|
+
export { max } from './number/max';
|
|
92
|
+
export { min } from './number/min';
|
|
93
|
+
export { moreThan } from './number/more-than';
|
|
94
|
+
export { negative } from './number/negative';
|
|
95
|
+
export { nonNegative } from './number/non-negative';
|
|
96
|
+
export { nonPositive } from './number/non-positive';
|
|
97
|
+
export { number } from './number/number';
|
|
98
|
+
export { positive } from './number/positive';
|
|
99
|
+
export { safeInteger } from './number/safe-integer';
|
|
100
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
101
|
+
|* Object Values *|
|
|
102
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
103
|
+
export { deepEquals } from './object/deep-equals';
|
|
104
|
+
export { hasKey } from './object/has-key';
|
|
105
|
+
export { hasValue } from './object/has-value';
|
|
106
|
+
export { keysEqual } from './object/keys-equal';
|
|
107
|
+
export { maxKeys } from './object/max-keys';
|
|
108
|
+
export { minKeys } from './object/min-keys';
|
|
109
|
+
export { missingKey } from './object/missing-key';
|
|
110
|
+
export { noEmptyArrayValues } from './object/no-empty-array-values';
|
|
111
|
+
export { noEmptyObjectValues } from './object/no-empty-object-values';
|
|
112
|
+
export { noNullValues } from './object/no-null-values';
|
|
113
|
+
export { noUndefinedValues } from './object/no-undefined-values';
|
|
114
|
+
export { nonEmptyObject } from './object/non-empty-object';
|
|
115
|
+
export { plainObject } from './object/plain-object';
|
|
116
|
+
export { onlyKeys } from './object/only-keys';
|
|
117
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
118
|
+
|* String Values *|
|
|
119
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
120
|
+
export { alpha } from './string/alpha';
|
|
121
|
+
export { alphaNum } from './string/alpha-num';
|
|
122
|
+
export { charsEqual } from './string/chars-equal';
|
|
123
|
+
export { endsWith } from './string/ends-with';
|
|
124
|
+
export { isAscii } from './string/is-ascii';
|
|
125
|
+
export { isPrintable } from './string/is-printable';
|
|
126
|
+
export { matches } from './string/matches';
|
|
127
|
+
export { maxLength } from './string/max-length';
|
|
128
|
+
export { minLength } from './string/min-length';
|
|
129
|
+
export { noLeadSpace } from './string/no-lead-space';
|
|
130
|
+
export { noRepeatSpace } from './string/no-repeat-space';
|
|
131
|
+
export { noSpace } from './string/no-space';
|
|
132
|
+
export { noTrailSpace } from './string/no-trail-space';
|
|
133
|
+
export { nonEmpty } from './string/non-empty';
|
|
134
|
+
export { notOneOf } from './string/not-one-of';
|
|
135
|
+
export { numString } from './string/num-string';
|
|
136
|
+
export { oneOf } from './string/one-of';
|
|
137
|
+
export { startsWith } from './string/starts-with';
|
|
138
|
+
export { string } from './string/string';
|
|
139
|
+
export { trimmed } from './string/trimmed';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Is Null Or Undefined
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is either `null` or `undefined`.
|
|
7
|
+
* @see https://jane-io.com
|
|
8
|
+
* ----------------------------------------------------------------------------
|
|
9
|
+
*/
|
|
10
|
+
import { validationEvent } from '../../pipeline';
|
|
11
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
12
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
13
|
+
|* Implementation *|
|
|
14
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
15
|
+
/**
|
|
16
|
+
* Validates that the value is either `null` or `undefined`.
|
|
17
|
+
*
|
|
18
|
+
* - Any value other than `null` or `undefined` emits
|
|
19
|
+
* `value.not.null-or-undefined`.
|
|
20
|
+
* - Returns an empty array when the value is valid.
|
|
21
|
+
*
|
|
22
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
23
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
24
|
+
* overrides applied at the pipeline level.
|
|
25
|
+
*/
|
|
26
|
+
export const isNullOrUndefined = async (value, path) => {
|
|
27
|
+
const structuralType = detectStructuralType(value);
|
|
28
|
+
// ------------------------------------------------------------
|
|
29
|
+
// Nullish check
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
if (value !== null && value !== undefined) {
|
|
32
|
+
return [
|
|
33
|
+
validationEvent('error', 'value.not.null-or-undefined', path, `Value must be null or undefined.`, `Please provide a null or undefined value.`, { value, expected: 'null | undefined', actual: structuralType }),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
// ------------------------------------------------------------
|
|
37
|
+
// Valid
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
return [];
|
|
40
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Is Null
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is exactly `null`.
|
|
7
|
+
* @see https://jane-io.com
|
|
8
|
+
* ----------------------------------------------------------------------------
|
|
9
|
+
*/
|
|
10
|
+
import { validationEvent } from '../../pipeline';
|
|
11
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
12
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
13
|
+
|* Implementation *|
|
|
14
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
15
|
+
/**
|
|
16
|
+
* Validates that the value is exactly `null`.
|
|
17
|
+
*
|
|
18
|
+
* - Any value other than `null` emits `value.not.null`.
|
|
19
|
+
* - Returns an empty array when the value is valid.
|
|
20
|
+
*
|
|
21
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
22
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
23
|
+
* overrides applied at the pipeline level.
|
|
24
|
+
*/
|
|
25
|
+
export const isNull = async (value, path) => {
|
|
26
|
+
const structuralType = detectStructuralType(value);
|
|
27
|
+
// ------------------------------------------------------------
|
|
28
|
+
// Null check
|
|
29
|
+
// ------------------------------------------------------------
|
|
30
|
+
if (value !== null) {
|
|
31
|
+
return [
|
|
32
|
+
validationEvent('error', 'value.not.null', path, `Value must be null.`, `Please provide a null value.`, { value, expected: 'null', actual: structuralType }),
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
// ------------------------------------------------------------
|
|
36
|
+
// Valid
|
|
37
|
+
// ------------------------------------------------------------
|
|
38
|
+
return [];
|
|
39
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Is Undefined
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is exactly `undefined`.
|
|
7
|
+
* @see https://jane-io.com
|
|
8
|
+
* ----------------------------------------------------------------------------
|
|
9
|
+
*/
|
|
10
|
+
import { validationEvent } from '../../pipeline';
|
|
11
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
12
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
13
|
+
|* Implementation *|
|
|
14
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
15
|
+
/**
|
|
16
|
+
* Validates that the value is exactly `undefined`.
|
|
17
|
+
*
|
|
18
|
+
* - Any value other than `undefined` emits `value.not.undefined`.
|
|
19
|
+
* - Returns an empty array when the value is valid.
|
|
20
|
+
*
|
|
21
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
22
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
23
|
+
* overrides applied at the pipeline level.
|
|
24
|
+
*/
|
|
25
|
+
export const isUndefined = async (value, path) => {
|
|
26
|
+
const structuralType = detectStructuralType(value);
|
|
27
|
+
// ------------------------------------------------------------
|
|
28
|
+
// Undefined check
|
|
29
|
+
// ------------------------------------------------------------
|
|
30
|
+
if (value !== undefined) {
|
|
31
|
+
return [
|
|
32
|
+
validationEvent('error', 'value.not.undefined', path, `Value must be undefined.`, `Please provide an undefined value.`, { value, expected: 'undefined', actual: structuralType }),
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
// ------------------------------------------------------------
|
|
36
|
+
// Valid
|
|
37
|
+
// ------------------------------------------------------------
|
|
38
|
+
return [];
|
|
39
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Finite
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validate that the value is a finite number.
|
|
7
|
+
* @see https://jane-io.com
|
|
8
|
+
* ----------------------------------------------------------------------------
|
|
9
|
+
*/
|
|
10
|
+
import { validationEvent } from '../../pipeline';
|
|
11
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
12
|
+
import { safeStringify } from '../../common';
|
|
13
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
14
|
+
|* Implementation *|
|
|
15
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
16
|
+
/**
|
|
17
|
+
* Validate that the value is a finite number.
|
|
18
|
+
*
|
|
19
|
+
* This rule accepts only JavaScript numbers that are both numeric and finite.
|
|
20
|
+
* Non-number values, NaN, Infinity, and -Infinity are rejected.
|
|
21
|
+
*
|
|
22
|
+
* If the value is not a number, a type.not.valid event is emitted.
|
|
23
|
+
* If the value is a number but not finite, a number.not.finite event is emitted.
|
|
24
|
+
*
|
|
25
|
+
* The rule is async-compatible and returns a readonly array of JaneEvent objects.
|
|
26
|
+
*/
|
|
27
|
+
export const finite = async (value, path) => {
|
|
28
|
+
const structuralType = detectStructuralType(value);
|
|
29
|
+
if (typeof value !== 'number') {
|
|
30
|
+
return [
|
|
31
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'number' but received '${structuralType}'.`, `Please enter a valid number.`, { expected: 'number', actual: structuralType }),
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
if (!Number.isFinite(value)) {
|
|
35
|
+
return [
|
|
36
|
+
validationEvent('error', 'number.not.finite', path, `${safeStringify(value)} must be a valid, bounded number.`, `Please enter a valid number.`, { expected: 'finite number', actual: value }),
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
return [];
|
|
40
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Integer
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validate that the value is an integer.
|
|
7
|
+
* @see https://jane-io.com
|
|
8
|
+
* ----------------------------------------------------------------------------
|
|
9
|
+
*/
|
|
10
|
+
import { validationEvent } from '../../pipeline';
|
|
11
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
12
|
+
import { safeStringify } from '../../common';
|
|
13
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
14
|
+
|* Implementation *|
|
|
15
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
16
|
+
/**
|
|
17
|
+
* Validate that the value is an integer.
|
|
18
|
+
*
|
|
19
|
+
* This rule accepts only JavaScript numbers that are both numeric and integer‑valued.
|
|
20
|
+
* Non-number values and non-integer numbers are rejected.
|
|
21
|
+
*
|
|
22
|
+
* If the value is not a number, a type.not.valid event is emitted.
|
|
23
|
+
* If the value is a number but not an integer, a number.not.integer event is emitted.
|
|
24
|
+
*
|
|
25
|
+
* The rule is async-compatible and returns a readonly array of JaneEvent objects.
|
|
26
|
+
*/
|
|
27
|
+
export const integer = async (value, path) => {
|
|
28
|
+
const structuralType = detectStructuralType(value);
|
|
29
|
+
if (typeof value !== 'number') {
|
|
30
|
+
return [
|
|
31
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'number' but received '${structuralType}'.`, `Please enter a valid number.`, { expected: 'number', actual: structuralType }),
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
if (!Number.isInteger(value)) {
|
|
35
|
+
return [
|
|
36
|
+
validationEvent('error', 'number.not.integer', path, `${safeStringify(value)} must be an integer-based number.`, `Please enter a valid number.`, { expected: 'integer', actual: value }),
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
return [];
|
|
40
|
+
};
|