@clementine-solutions/jane-io 1.0.1 → 1.0.3
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/package.json +28 -3
- package/dist/test.d.ts +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Is Printable
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string containing only
|
|
7
|
+
* printable ASCII characters (code points 0x20–0x7E).
|
|
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
|
+
* Validates that the value is a string containing only printable ASCII
|
|
19
|
+
* characters (code points 0x20–0x7E).
|
|
20
|
+
*
|
|
21
|
+
* - Non‑string values emit `string.not.string`.
|
|
22
|
+
* - Strings containing characters outside the printable ASCII range emit
|
|
23
|
+
* `string.not.printable`.
|
|
24
|
+
* - Returns an empty array when the value is valid.
|
|
25
|
+
*
|
|
26
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
27
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
28
|
+
* overrides applied at the pipeline level.
|
|
29
|
+
*/
|
|
30
|
+
export const isPrintable = async (value, path) => {
|
|
31
|
+
const structuralType = detectStructuralType(value);
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
// Type check
|
|
34
|
+
// ------------------------------------------------------------
|
|
35
|
+
if (typeof value !== 'string') {
|
|
36
|
+
return [
|
|
37
|
+
validationEvent('error', 'string.not.string', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
// Printable ASCII check
|
|
42
|
+
// ------------------------------------------------------------
|
|
43
|
+
const printablePattern = /^[\x20-\x7E]+$/;
|
|
44
|
+
if (!printablePattern.test(value)) {
|
|
45
|
+
return [
|
|
46
|
+
validationEvent('error', 'string.not.printable', path, `${safeStringify(value)} must contain only printable ASCII characters.`, `Please use only printable characters.`, { value, expected: 'printable ASCII', actual: value }),
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
// ------------------------------------------------------------
|
|
50
|
+
// Valid
|
|
51
|
+
// ------------------------------------------------------------
|
|
52
|
+
return [];
|
|
53
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Matches
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string matching the provided
|
|
7
|
+
* regular expression.
|
|
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
|
+
* Validates that the value is a string matching the provided regular expression.
|
|
19
|
+
*
|
|
20
|
+
* - Non‑string values emit `string.not.string`.
|
|
21
|
+
* - Strings that do not satisfy the pattern emit `string.is.not-match`.
|
|
22
|
+
* - Returns an empty array when the value is valid.
|
|
23
|
+
*
|
|
24
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
25
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
26
|
+
* overrides applied at the pipeline level.
|
|
27
|
+
*/
|
|
28
|
+
export const matches = (pattern) => async (value, path) => {
|
|
29
|
+
const structuralType = detectStructuralType(value);
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
// Type check
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
if (typeof value !== 'string') {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'string.not.string', path, `Expected 'string' but received '${structuralType}'.`, `Please provide a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
// Pattern match check
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
if (!pattern.test(value)) {
|
|
42
|
+
return [
|
|
43
|
+
validationEvent('error', 'string.is.not-match', path, `${safeStringify(value)} must match pattern ${pattern}.`, `Please provide a value matching the required format.`, { value, expected: pattern.toString(), actual: value }),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
// ------------------------------------------------------------
|
|
47
|
+
// Valid
|
|
48
|
+
// ------------------------------------------------------------
|
|
49
|
+
return [];
|
|
50
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Maximum Length (Max Length)
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string whose length is less
|
|
7
|
+
* than or equal to the provided `max` value.
|
|
8
|
+
* @see https://jane-io.com
|
|
9
|
+
* ----------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
import { validationEvent } from '../../pipeline';
|
|
12
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
13
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
14
|
+
|* Implementation *|
|
|
15
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
16
|
+
/**
|
|
17
|
+
* Validates that the value is a string whose length is less than or equal to
|
|
18
|
+
* the provided `max` value.
|
|
19
|
+
*
|
|
20
|
+
* - Non‑string values emit `type.not.valid`.
|
|
21
|
+
* - Strings longer than `max` emit `string.too.long`.
|
|
22
|
+
* - Returns an empty array when the value is valid.
|
|
23
|
+
*
|
|
24
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
25
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
26
|
+
* overrides applied at the pipeline level.
|
|
27
|
+
*/
|
|
28
|
+
export const maxLength = (max) => async (value, path) => {
|
|
29
|
+
const structuralType = detectStructuralType(value);
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
// Type check
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
if (typeof value !== 'string') {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
// Maximum-length check
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
if (value.length > max) {
|
|
42
|
+
return [
|
|
43
|
+
validationEvent('error', 'string.too.long', path, `String length ${value.length} must be ≤ ${max}.`, `Please enter no more than ${max} characters.`, { value, expected: `≤ ${max}`, actual: value.length }),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
// ------------------------------------------------------------
|
|
47
|
+
// Valid
|
|
48
|
+
// ------------------------------------------------------------
|
|
49
|
+
return [];
|
|
50
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Minimum Length (Min Length)
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string whose length is greater
|
|
7
|
+
* than or equal to the provided `min` value.
|
|
8
|
+
* @see https://jane-io.com
|
|
9
|
+
* ----------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
import { validationEvent } from '../../pipeline';
|
|
12
|
+
import { detectStructuralType } from '../../pipeline/scan';
|
|
13
|
+
/* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— *\
|
|
14
|
+
|* Implementation *|
|
|
15
|
+
\* ——— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ————— * ——— */
|
|
16
|
+
/**
|
|
17
|
+
* Validates that the value is a string whose length is greater than or equal to
|
|
18
|
+
* the provided `min` value.
|
|
19
|
+
*
|
|
20
|
+
* - Non‑string values emit `type.not.valid`.
|
|
21
|
+
* - Strings shorter than `min` emit `string.too.short`.
|
|
22
|
+
* - Returns an empty array when the value is valid.
|
|
23
|
+
*
|
|
24
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
25
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
26
|
+
* overrides applied at the pipeline level.
|
|
27
|
+
*/
|
|
28
|
+
export const minLength = (min) => async (value, path) => {
|
|
29
|
+
const structuralType = detectStructuralType(value);
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
// Type check
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
if (typeof value !== 'string') {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
// Minimum-length check
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
if (value.length < min) {
|
|
42
|
+
return [
|
|
43
|
+
validationEvent('error', 'string.too.short', path, `String length ${value.length} must be ≥ ${min}.`, `Please enter at least ${min} characters.`, { value, expected: `≥ ${min}`, actual: value.length }),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
// ------------------------------------------------------------
|
|
47
|
+
// Valid
|
|
48
|
+
// ------------------------------------------------------------
|
|
49
|
+
return [];
|
|
50
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | No Leading Whitespace (No Lead Space)
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string that does not begin
|
|
7
|
+
* with whitespace.
|
|
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
|
+
* Validates that the value is a string that does not begin with whitespace.
|
|
19
|
+
*
|
|
20
|
+
* - Non‑string values emit `type.not.valid`.
|
|
21
|
+
* - Strings beginning with whitespace emit `string.has.leading-whitespace`.
|
|
22
|
+
* - Returns an empty array when the value is valid.
|
|
23
|
+
*
|
|
24
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
25
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
26
|
+
* overrides applied at the pipeline level.
|
|
27
|
+
*/
|
|
28
|
+
export const noLeadSpace = async (value, path) => {
|
|
29
|
+
const structuralType = detectStructuralType(value);
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
// Type check
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
if (typeof value !== 'string') {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
// Leading whitespace check
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
if (/^\s/.test(value)) {
|
|
42
|
+
return [
|
|
43
|
+
validationEvent('error', 'string.has.leading-whitespace', path, `${safeStringify(value)} must not start with whitespace.`, `Please remove leading spaces.`, { value, expected: 'no leading space', actual: value }),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
// ------------------------------------------------------------
|
|
47
|
+
// Valid
|
|
48
|
+
// ------------------------------------------------------------
|
|
49
|
+
return [];
|
|
50
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | No Repeated Whitespace (No Repeat Space)
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string that does not contain
|
|
7
|
+
* repeated consecutive space characters.
|
|
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
|
+
* Validates that the value is a string that does not contain repeated
|
|
19
|
+
* consecutive space characters.
|
|
20
|
+
*
|
|
21
|
+
* - Non‑string values emit `type.not.valid`.
|
|
22
|
+
* - Strings containing `" "` (two or more consecutive spaces) emit
|
|
23
|
+
* `string.has.repeating-whitespace`.
|
|
24
|
+
* - Returns an empty array when the value is valid.
|
|
25
|
+
*
|
|
26
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
27
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
28
|
+
* overrides applied at the pipeline level.
|
|
29
|
+
*/
|
|
30
|
+
export const noRepeatSpace = async (value, path) => {
|
|
31
|
+
const structuralType = detectStructuralType(value);
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
// Type check
|
|
34
|
+
// ------------------------------------------------------------
|
|
35
|
+
if (typeof value !== 'string') {
|
|
36
|
+
return [
|
|
37
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
// Repeated-space check
|
|
42
|
+
// ------------------------------------------------------------
|
|
43
|
+
if (/ {2,}/.test(value)) {
|
|
44
|
+
return [
|
|
45
|
+
validationEvent('error', 'string.has.repeating-whitespace', path, `${safeStringify(value)} must not contain repeated spaces.`, `Please remove extra spaces.`, { value, expected: 'no repeated spaces', actual: value }),
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
// ------------------------------------------------------------
|
|
49
|
+
// Valid
|
|
50
|
+
// ------------------------------------------------------------
|
|
51
|
+
return [];
|
|
52
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | No Whitespace (No Space)
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string containing no
|
|
7
|
+
* whitespace characters.
|
|
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
|
+
* Validates that the value is a string containing no whitespace characters.
|
|
19
|
+
*
|
|
20
|
+
* - Non‑string values emit `type.not.valid`.
|
|
21
|
+
* - Strings containing any whitespace (spaces, tabs, newlines, etc.) emit
|
|
22
|
+
* `string.has.whitespace`.
|
|
23
|
+
* - Returns an empty array when the value is valid.
|
|
24
|
+
*
|
|
25
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
26
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
27
|
+
* overrides applied at the pipeline level.
|
|
28
|
+
*/
|
|
29
|
+
export const noSpace = async (value, path) => {
|
|
30
|
+
const structuralType = detectStructuralType(value);
|
|
31
|
+
// ------------------------------------------------------------
|
|
32
|
+
// Type check
|
|
33
|
+
// ------------------------------------------------------------
|
|
34
|
+
if (typeof value !== 'string') {
|
|
35
|
+
return [
|
|
36
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
// ------------------------------------------------------------
|
|
40
|
+
// Whitespace check
|
|
41
|
+
// ------------------------------------------------------------
|
|
42
|
+
if (/\s/.test(value)) {
|
|
43
|
+
return [
|
|
44
|
+
validationEvent('error', 'string.has.whitespace', path, `${safeStringify(value)} must not contain whitespace.`, `Please remove spaces.`, { value, expected: 'no whitespace', actual: value }),
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
// ------------------------------------------------------------
|
|
48
|
+
// Valid
|
|
49
|
+
// ------------------------------------------------------------
|
|
50
|
+
return [];
|
|
51
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | No Trailing Whitespace (No Trail Space)
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string that does not end with
|
|
7
|
+
* whitespace.
|
|
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
|
+
* Validates that the value is a string that does not end with whitespace.
|
|
19
|
+
*
|
|
20
|
+
* - Non‑string values emit `type.not.valid`.
|
|
21
|
+
* - Strings ending with whitespace emit `string.has.trailing-whitespace`.
|
|
22
|
+
* - Returns an empty array when the value is valid.
|
|
23
|
+
*
|
|
24
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
25
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
26
|
+
* overrides applied at the pipeline level.
|
|
27
|
+
*/
|
|
28
|
+
export const noTrailSpace = async (value, path) => {
|
|
29
|
+
const structuralType = detectStructuralType(value);
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
// Type check
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
if (typeof value !== 'string') {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
// Trailing whitespace check
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
if (/\s$/.test(value)) {
|
|
42
|
+
return [
|
|
43
|
+
validationEvent('error', 'string.has.trailing-whitespace', path, `${safeStringify(value)} must not end with whitespace.`, `Please remove trailing spaces.`, { value, expected: 'no trailing space', actual: value }),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
// ------------------------------------------------------------
|
|
47
|
+
// Valid
|
|
48
|
+
// ------------------------------------------------------------
|
|
49
|
+
return [];
|
|
50
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Non-Empty
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a non-empty string.
|
|
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 a non-empty string.
|
|
17
|
+
*
|
|
18
|
+
* - Non‑string values emit `string.not.string`.
|
|
19
|
+
* - Empty strings emit `string.is.empty`.
|
|
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 nonEmpty = async (value, path) => {
|
|
27
|
+
const structuralType = detectStructuralType(value);
|
|
28
|
+
// ------------------------------------------------------------
|
|
29
|
+
// Type check
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
if (typeof value !== 'string') {
|
|
32
|
+
return [
|
|
33
|
+
validationEvent('error', 'string.not.string', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
// ------------------------------------------------------------
|
|
37
|
+
// Non-empty check
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
if (value.length === 0) {
|
|
40
|
+
return [
|
|
41
|
+
validationEvent('error', 'string.is.empty', path, `String must not be empty.`, `Please enter a non-empty string.`, { value, expected: 'non-empty', actual: value }),
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
// ------------------------------------------------------------
|
|
45
|
+
// Valid
|
|
46
|
+
// ------------------------------------------------------------
|
|
47
|
+
return [];
|
|
48
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Not One Of
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string that is *not* included
|
|
7
|
+
* in the provided `disallowed` list.
|
|
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
|
+
* Validates that the value is a string that is *not* included in the provided
|
|
19
|
+
* `disallowed` list.
|
|
20
|
+
*
|
|
21
|
+
* - Non‑string values emit `type.not.valid`.
|
|
22
|
+
* - Strings that appear in the disallowed list emit `string.is.disallowed`.
|
|
23
|
+
* - Returns an empty array when the value is valid.
|
|
24
|
+
*
|
|
25
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
26
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
27
|
+
* overrides applied at the pipeline level.
|
|
28
|
+
*/
|
|
29
|
+
export const notOneOf = (disallowed) => async (value, path) => {
|
|
30
|
+
const structuralType = detectStructuralType(value);
|
|
31
|
+
// ------------------------------------------------------------
|
|
32
|
+
// Type check
|
|
33
|
+
// ------------------------------------------------------------
|
|
34
|
+
if (typeof value !== 'string') {
|
|
35
|
+
return [
|
|
36
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
// ------------------------------------------------------------
|
|
40
|
+
// Disallowed membership check
|
|
41
|
+
// ------------------------------------------------------------
|
|
42
|
+
if (disallowed.includes(value)) {
|
|
43
|
+
return [
|
|
44
|
+
validationEvent('error', 'string.is.disallowed', path, `${safeStringify(value)} must not be one of: ${disallowed.join(', ')}.`, `Please enter a different value.`, { value, expected: `not in ${disallowed}`, actual: value }),
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
// ------------------------------------------------------------
|
|
48
|
+
// Valid
|
|
49
|
+
// ------------------------------------------------------------
|
|
50
|
+
return [];
|
|
51
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | Number String (Num String)
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string containing only ASCII
|
|
7
|
+
* digits (`0–9`).
|
|
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
|
+
* Validates that the value is a string containing only ASCII digits (`0–9`).
|
|
19
|
+
*
|
|
20
|
+
* - Non‑string values emit `type.not.valid`.
|
|
21
|
+
* - Strings containing any non-digit character emit `string.not.numeric`.
|
|
22
|
+
* - Returns an empty array when the value is valid.
|
|
23
|
+
*
|
|
24
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
25
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
26
|
+
* overrides applied at the pipeline level.
|
|
27
|
+
*/
|
|
28
|
+
export const numString = async (value, path) => {
|
|
29
|
+
const structuralType = detectStructuralType(value);
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
// Type check
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
if (typeof value !== 'string') {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
// Digit-only check
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
if (!/^[0-9]+$/.test(value)) {
|
|
42
|
+
return [
|
|
43
|
+
validationEvent('error', 'string.not.numeric', path, `${safeStringify(value)} must contain only digits.`, `Please use only numbers.`, { value, expected: '0-9', actual: value }),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
// ------------------------------------------------------------
|
|
47
|
+
// Valid
|
|
48
|
+
// ------------------------------------------------------------
|
|
49
|
+
return [];
|
|
50
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ----------------------------------------------------------------------------
|
|
3
|
+
* Validators | One Of
|
|
4
|
+
* ----------------------------------------------------------------------------
|
|
5
|
+
* @package @clementine-solutions/jane
|
|
6
|
+
* @description Validates that the value is a string included in the
|
|
7
|
+
* provided `allowed` list.
|
|
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
|
+
* Validates that the value is a string included in the provided `allowed` list.
|
|
19
|
+
*
|
|
20
|
+
* - Non‑string values emit `type.not.valid`.
|
|
21
|
+
* - Strings not present in the allowed list emit `string.not.allowed`.
|
|
22
|
+
* - Returns an empty array when the value is valid.
|
|
23
|
+
*
|
|
24
|
+
* This rule is pure, total, async‑compatible, and returns a readonly array of
|
|
25
|
+
* JaneEvent objects. It preserves the provided path and supports userMessage
|
|
26
|
+
* overrides applied at the pipeline level.
|
|
27
|
+
*/
|
|
28
|
+
export const oneOf = (allowed) => async (value, path) => {
|
|
29
|
+
const structuralType = detectStructuralType(value);
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
// Type check
|
|
32
|
+
// ------------------------------------------------------------
|
|
33
|
+
if (typeof value !== 'string') {
|
|
34
|
+
return [
|
|
35
|
+
validationEvent('error', 'type.not.valid', path, `Expected 'string' but received '${structuralType}'.`, `Please enter a valid string.`, { value, expected: 'string', actual: structuralType }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
// ------------------------------------------------------------
|
|
39
|
+
// Allowed membership check
|
|
40
|
+
// ------------------------------------------------------------
|
|
41
|
+
if (!allowed.includes(value)) {
|
|
42
|
+
return [
|
|
43
|
+
validationEvent('error', 'string.not.allowed', path, `${safeStringify(value)} must be one of: ${allowed.join(', ')}.`, `Please enter one of the allowed values.`, { value, expected: allowed, actual: value }),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
// ------------------------------------------------------------
|
|
47
|
+
// Valid
|
|
48
|
+
// ------------------------------------------------------------
|
|
49
|
+
return [];
|
|
50
|
+
};
|