@loomcli/validators 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bounds.d.ts +5 -3
- package/dist/bounds.js +22 -12
- package/dist/codes.d.ts +78 -0
- package/dist/codes.js +134 -0
- package/dist/create.d.ts +3 -1
- package/dist/create.js +35 -13
- package/dist/date.js +3 -1
- package/dist/faults.d.ts +18 -3
- package/dist/faults.js +17 -5
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/integer.js +4 -3
- package/dist/issue-code.d.ts +24 -0
- package/dist/issue-code.js +183 -0
- package/dist/issues.d.ts +2 -2
- package/dist/issues.js +3 -3
- package/dist/number.js +5 -4
- package/dist/one-of.js +46 -14
- package/dist/params.d.ts +54 -0
- package/dist/params.js +68 -0
- package/dist/path.js +25 -22
- package/dist/port.js +3 -3
- package/dist/rules.d.ts +32 -0
- package/dist/rules.js +86 -0
- package/dist/text.d.ts +12 -4
- package/dist/text.js +71 -32
- package/dist/url.js +23 -12
- package/dist/uuid.js +3 -3
- package/package.json +2 -2
package/dist/rules.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { diagnosticRule } from '@loomcli/core';
|
|
2
|
+
/*
|
|
3
|
+
* The catalog's rules for the declaration faults its factories raise. Each is declared once here
|
|
4
|
+
* through the public diagnosticRule(), under the package's own name, as any third-party validator
|
|
5
|
+
* package declares its rules, and shared by every site that raises it.
|
|
6
|
+
*/
|
|
7
|
+
/** One rule of this package, named under the package as its issue codes are. */
|
|
8
|
+
function catalogRule(name, definition) {
|
|
9
|
+
return diagnosticRule(`@loomcli/validators/${name}`, definition);
|
|
10
|
+
}
|
|
11
|
+
/** A factory's options that are not a plain object. */
|
|
12
|
+
const factoryOptions = catalogRule('factory-options', {
|
|
13
|
+
explanation: 'A catalog factory reads its settings from one options object, so a value of any other kind leaves it no settings to read.',
|
|
14
|
+
headline: 'Options not an object',
|
|
15
|
+
});
|
|
16
|
+
/** A `oneOf()` list that is not a list of distinct nonempty strings. */
|
|
17
|
+
const oneOfValues = catalogRule('one-of-values', {
|
|
18
|
+
explanation: 'oneOf() accepts a token equal to one of its values, and help, completion, and the published schema offer each value as a choice, so the list holds at least one value, each a distinct nonempty string.',
|
|
19
|
+
headline: 'Invalid oneOf values',
|
|
20
|
+
});
|
|
21
|
+
/** A bound that is not a number of the kind its validator reads. */
|
|
22
|
+
const boundValue = catalogRule('bound-value', {
|
|
23
|
+
explanation: "A bound limits the values or the length a validator accepts, and the published schema carries it, so it is a number of the kind the validator reads: a safe integer for integer(), a finite number for number(), and a non-negative safe integer for text()'s lengths.",
|
|
24
|
+
headline: 'Invalid bound',
|
|
25
|
+
});
|
|
26
|
+
/** A lower bound above its upper bound. */
|
|
27
|
+
const boundsOrder = catalogRule('bounds-order', {
|
|
28
|
+
explanation: 'A validator accepts what lies between its lower and its upper bound, both inclusive, so a lower bound above the upper one would reject every token.',
|
|
29
|
+
headline: 'Bounds out of order',
|
|
30
|
+
});
|
|
31
|
+
/** A `url()` protocols list that is not a list of scheme names. */
|
|
32
|
+
const urlProtocols = catalogRule('url-protocols', {
|
|
33
|
+
explanation: 'url() accepts a URL whose scheme the list names and publishes the list as a pattern, so it holds at least one scheme name: a letter followed by letters, digits, +, -, or ., with no trailing colon.',
|
|
34
|
+
headline: 'Invalid url protocols',
|
|
35
|
+
});
|
|
36
|
+
/** A `path()` access or kind outside its set, or a kind with no access to narrow. */
|
|
37
|
+
const pathCheck = catalogRule('path-check', {
|
|
38
|
+
explanation: 'path() reads the file system only to check an access, read or write, and kind narrows that check to a file, a directory, or any entry, so kind has no meaning without access.',
|
|
39
|
+
headline: 'Invalid path check',
|
|
40
|
+
});
|
|
41
|
+
/** A `text()` pattern that JSON Schema cannot read as it is. */
|
|
42
|
+
const textPattern = catalogRule('invalid-pattern', {
|
|
43
|
+
explanation: 'text() publishes its pattern in the JSON Schema it serves, which reads a pattern under the u flag alone, so the pattern is a regular expression that compiles under u and carries no other flag.',
|
|
44
|
+
headline: 'Invalid pattern',
|
|
45
|
+
});
|
|
46
|
+
/** A `text()` pattern without its sentence, or a sentence without a pattern. */
|
|
47
|
+
const patternMessage = catalogRule('pattern-message', {
|
|
48
|
+
explanation: 'Only the author can say what a pattern accepts, so text() takes a pattern together with one sentence that states it, and prints that sentence when a token does not match.',
|
|
49
|
+
headline: 'Pattern and message apart',
|
|
50
|
+
});
|
|
51
|
+
/** An issue code outside the `<package>[/<subpath>...]/<kebab-case-rule>` grammar. */
|
|
52
|
+
const issueCodeName = catalogRule('issue-code-name', {
|
|
53
|
+
explanation: 'An issue code names the package that declares it and the one sentence it prints, so a view rewords that sentence by its code. It is a package name, any kebab-case subpath segments, and a kebab-case rule name, joined by /.',
|
|
54
|
+
headline: 'Invalid issue code',
|
|
55
|
+
});
|
|
56
|
+
/** An `issueCode()` config without a Standard Schema and a message function. */
|
|
57
|
+
const issueCodeConfig = catalogRule('issue-code-config', {
|
|
58
|
+
explanation: "An issue code checks each issue's parameters with its schema and builds the issue's sentence from them with its message function, so its config holds both.",
|
|
59
|
+
headline: 'Invalid issue code config',
|
|
60
|
+
});
|
|
61
|
+
/** An issue code schema that answers with a promise, throws, or answers with no result. */
|
|
62
|
+
const issueCodeSchema = catalogRule('issue-code-schema', {
|
|
63
|
+
explanation: "issue() and read() check an issue's parameters with the code's schema synchronously, while a validator builds the issue or a view reads it, so the schema returns its value or its issues, and neither throws nor answers with a promise.",
|
|
64
|
+
headline: 'Broken issue code schema',
|
|
65
|
+
});
|
|
66
|
+
/** Parameters an issue code's schema rejects. */
|
|
67
|
+
const issueParameters = catalogRule('issue-parameters', {
|
|
68
|
+
explanation: "An issue carries parameters its code's schema accepts, so every view that reads them through read() gets the shape the code declares.",
|
|
69
|
+
headline: 'Issue parameters rejected',
|
|
70
|
+
});
|
|
71
|
+
/** A `createValidator()` definition without a parse function. */
|
|
72
|
+
const validatorDefinition = catalogRule('validator-definition', {
|
|
73
|
+
explanation: 'createValidator() builds a Standard Schema value around one parse function that validates a raw string, so its definition is an object that holds that function.',
|
|
74
|
+
headline: 'Invalid validator definition',
|
|
75
|
+
});
|
|
76
|
+
/** A `createValidator()` input schema that is not a plain object, or declares its own dialect. */
|
|
77
|
+
const inputSchema = catalogRule('input-schema', {
|
|
78
|
+
explanation: 'createValidator() publishes its input schema as draft 2020-12 JSON Schema and adds the $schema dialect itself, so inputSchema is a plain object with no $schema of its own.',
|
|
79
|
+
headline: 'Invalid input schema',
|
|
80
|
+
});
|
|
81
|
+
/** A validator that read the validation context outside a Loom run. */
|
|
82
|
+
const contextOutsideRun = catalogRule('context-outside-run', {
|
|
83
|
+
explanation: 'Core attaches the validation context to each call it makes to a validator. A call from anywhere else, such as a unit test, carries none, so a validator that reads it runs inside an Application run.',
|
|
84
|
+
headline: 'Context outside a run',
|
|
85
|
+
});
|
|
86
|
+
export { boundsOrder, boundValue, contextOutsideRun, factoryOptions, inputSchema, issueCodeConfig, issueCodeName, issueCodeSchema, issueParameters, oneOfValues, pathCheck, patternMessage, textPattern, urlProtocols, validatorDefinition, };
|
package/dist/text.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type { Validator } from './create.js';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* The bounds on a token's length, and a pattern with the author's sentence for what it accepts.
|
|
4
|
+
* Only the author can say what a pattern accepts, so `message` comes with `pattern` or not at all.
|
|
5
|
+
*/
|
|
6
|
+
type TextOptions = {
|
|
3
7
|
minLength?: number;
|
|
4
8
|
maxLength?: number;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
} & ({
|
|
10
|
+
pattern?: undefined;
|
|
11
|
+
message?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
pattern: RegExp;
|
|
14
|
+
message: string;
|
|
15
|
+
});
|
|
8
16
|
/** A string whose code-point length is within bounds and which the pattern matches, if any. */
|
|
9
17
|
declare function text(options?: TextOptions): Validator<string>;
|
|
10
18
|
export { text };
|
package/dist/text.js
CHANGED
|
@@ -1,77 +1,111 @@
|
|
|
1
|
+
import { textExactLengthIssue, textLengthRangeIssue, textMaxLengthIssue, textMinLengthIssue, textNonemptyIssue, textPatternIssue, } from './codes.js';
|
|
1
2
|
import { createValidator } from './create.js';
|
|
2
3
|
import { fault, readOptions } from './faults.js';
|
|
3
4
|
import { reject } from './issues.js';
|
|
5
|
+
import { boundsOrder, boundValue, patternMessage, textPattern } from './rules.js';
|
|
4
6
|
const noLength = 0;
|
|
5
7
|
const oneCharacter = 1;
|
|
6
8
|
const defaultMinLength = 1;
|
|
7
|
-
|
|
9
|
+
/** The `text()` call a fault marks one key of. */
|
|
10
|
+
function textAt(call, key) {
|
|
11
|
+
return { ...call, mark: `0.${key}` };
|
|
12
|
+
}
|
|
13
|
+
function lengthOf(call, name, value) {
|
|
8
14
|
if (value === undefined) {
|
|
9
15
|
return undefined;
|
|
10
16
|
}
|
|
11
17
|
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < noLength) {
|
|
12
|
-
throw fault(
|
|
18
|
+
throw fault(boundValue, textAt(call, name), {
|
|
19
|
+
correction: 'Supply a whole number of 0 or more.',
|
|
20
|
+
sentence: `text() ${name} is not a non-negative safe integer.`,
|
|
21
|
+
});
|
|
13
22
|
}
|
|
14
23
|
return value;
|
|
15
24
|
}
|
|
16
25
|
/** Faults on a pattern flag other than `u`, which JSON Schema has no way to state. */
|
|
17
|
-
function checkFlags(pattern) {
|
|
26
|
+
function checkFlags(call, pattern) {
|
|
18
27
|
const others = pattern.flags.replace('u', '');
|
|
19
28
|
if (others !== '') {
|
|
20
29
|
const noun = others.length === oneCharacter ? 'flag' : 'flags';
|
|
21
|
-
throw fault(
|
|
30
|
+
throw fault(textPattern, textAt(call, 'pattern'), {
|
|
31
|
+
correction: 'Supply a pattern with no flag other than u.',
|
|
32
|
+
sentence: `text() pattern carries the ${noun} ${others}.`,
|
|
33
|
+
});
|
|
22
34
|
}
|
|
23
35
|
}
|
|
24
36
|
/** The author's pattern recompiled under the `u` flag, as JSON Schema reads a `pattern`. */
|
|
25
|
-
function patternOf(value) {
|
|
37
|
+
function patternOf(call, value) {
|
|
26
38
|
if (value === undefined) {
|
|
27
39
|
return undefined;
|
|
28
40
|
}
|
|
29
41
|
if (!(value instanceof RegExp)) {
|
|
30
|
-
throw fault(
|
|
42
|
+
throw fault(textPattern, textAt(call, 'pattern'), {
|
|
43
|
+
correction: 'Supply a regular expression literal.',
|
|
44
|
+
sentence: 'text() pattern is not a RegExp.',
|
|
45
|
+
});
|
|
31
46
|
}
|
|
32
|
-
checkFlags(value);
|
|
47
|
+
checkFlags(call, value);
|
|
33
48
|
try {
|
|
34
49
|
return new RegExp(value.source, 'u');
|
|
35
50
|
}
|
|
36
51
|
catch {
|
|
37
|
-
throw fault(
|
|
52
|
+
throw fault(textPattern, textAt(call, 'pattern'), {
|
|
53
|
+
correction: 'Supply a pattern that is valid with the u flag.',
|
|
54
|
+
sentence: 'text() pattern does not compile under the u flag.',
|
|
55
|
+
});
|
|
38
56
|
}
|
|
39
57
|
}
|
|
40
|
-
function messageOf(
|
|
58
|
+
function messageOf(call, value) {
|
|
41
59
|
if (value === undefined) {
|
|
42
60
|
return undefined;
|
|
43
61
|
}
|
|
44
62
|
if (typeof value !== 'string' || value === '') {
|
|
45
|
-
throw fault(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
63
|
+
throw fault(patternMessage, textAt(call, 'message'), {
|
|
64
|
+
correction: 'Supply one sentence that states the expectation.',
|
|
65
|
+
sentence: 'text() message is not a nonempty string.',
|
|
66
|
+
});
|
|
49
67
|
}
|
|
50
68
|
return value;
|
|
51
69
|
}
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
/** The pattern rule, or undefined without a pattern; a pattern and a message each need the other. */
|
|
71
|
+
function patternRule(call, pattern, message) {
|
|
72
|
+
if (pattern === undefined) {
|
|
73
|
+
if (message !== undefined) {
|
|
74
|
+
throw fault(patternMessage, textAt(call, 'message'), {
|
|
75
|
+
correction: 'Supply a pattern or leave out message.',
|
|
76
|
+
sentence: 'text() message has no pattern to describe.',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
if (message === undefined) {
|
|
82
|
+
throw fault(patternMessage, textAt(call, 'pattern'), {
|
|
83
|
+
correction: 'Supply a message that states what the pattern accepts.',
|
|
84
|
+
sentence: 'text() pattern has no message to describe it.',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return { issue: textPatternIssue.issue({ message }), pattern };
|
|
54
88
|
}
|
|
55
|
-
/** The
|
|
56
|
-
function
|
|
89
|
+
/** The issue for bounds with a `maxLength`, where `min` is `minLength` after its default. */
|
|
90
|
+
function boundedIssue(min, max) {
|
|
57
91
|
if (min === max) {
|
|
58
|
-
return
|
|
92
|
+
return textExactLengthIssue.issue({ length: min });
|
|
59
93
|
}
|
|
60
94
|
if (min === noLength) {
|
|
61
|
-
return
|
|
95
|
+
return textMaxLengthIssue.issue({ max });
|
|
62
96
|
}
|
|
63
|
-
return
|
|
97
|
+
return textLengthRangeIssue.issue({ max, min });
|
|
64
98
|
}
|
|
65
99
|
/** The length rule for the effective bounds, or undefined when every length passes. */
|
|
66
100
|
function lengthRule(min, max) {
|
|
67
101
|
if (max !== undefined) {
|
|
68
|
-
return { fits: (count) => count >= min && count <= max,
|
|
102
|
+
return { fits: (count) => count >= min && count <= max, issue: boundedIssue(min, max) };
|
|
69
103
|
}
|
|
70
104
|
if (min === noLength) {
|
|
71
105
|
return undefined;
|
|
72
106
|
}
|
|
73
|
-
const
|
|
74
|
-
return { fits: (count) => count >= min,
|
|
107
|
+
const issue = min === oneCharacter ? textNonemptyIssue.issue({}) : textMinLengthIssue.issue({ min });
|
|
108
|
+
return { fits: (count) => count >= min, issue };
|
|
75
109
|
}
|
|
76
110
|
/**
|
|
77
111
|
* The token's length in Unicode code points, as JSON Schema counts it.
|
|
@@ -84,27 +118,32 @@ function codePoints(raw) {
|
|
|
84
118
|
/** A string whose code-point length is within bounds and which the pattern matches, if any. */
|
|
85
119
|
function text(options) {
|
|
86
120
|
const declared = readOptions('text', options);
|
|
87
|
-
const
|
|
88
|
-
const
|
|
121
|
+
const call = { arguments: [options], factory: 'text' };
|
|
122
|
+
const minLength = lengthOf(call, 'minLength', declared.minLength) ?? defaultMinLength;
|
|
123
|
+
const maxLength = lengthOf(call, 'maxLength', declared.maxLength);
|
|
89
124
|
if (maxLength !== undefined && minLength > maxLength) {
|
|
90
|
-
|
|
125
|
+
// A minLength left to its default has no key to mark, so the maxLength below it is marked.
|
|
126
|
+
const key = declared.minLength === undefined ? 'maxLength' : 'minLength';
|
|
127
|
+
throw fault(boundsOrder, textAt(call, key), {
|
|
128
|
+
correction: 'Supply a minLength at or below maxLength.',
|
|
129
|
+
sentence: `text() minLength ${minLength} is above maxLength ${maxLength}.`,
|
|
130
|
+
});
|
|
91
131
|
}
|
|
92
|
-
const
|
|
93
|
-
const patternSentence = messageOf(declared.message, pattern) ?? 'Expected a value that matches the required pattern.';
|
|
132
|
+
const matching = patternRule(call, patternOf(call, declared.pattern), messageOf(call, declared.message));
|
|
94
133
|
const length = lengthRule(minLength, maxLength);
|
|
95
134
|
return createValidator({
|
|
96
135
|
inputSchema: {
|
|
97
136
|
type: 'string',
|
|
98
137
|
minLength,
|
|
99
138
|
...(maxLength === undefined ? {} : { maxLength }),
|
|
100
|
-
...(
|
|
139
|
+
...(matching === undefined ? {} : { pattern: matching.pattern.source }),
|
|
101
140
|
},
|
|
102
141
|
parse: (raw) => {
|
|
103
142
|
if (length !== undefined && !length.fits(codePoints(raw))) {
|
|
104
|
-
return reject(length.
|
|
143
|
+
return reject(length.issue);
|
|
105
144
|
}
|
|
106
|
-
if (
|
|
107
|
-
return reject(
|
|
145
|
+
if (matching !== undefined && !matching.pattern.test(raw)) {
|
|
146
|
+
return reject(matching.issue);
|
|
108
147
|
}
|
|
109
148
|
return { value: raw };
|
|
110
149
|
},
|
package/dist/url.js
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
|
+
import { urlIssue, urlSchemeIssue } from './codes.js';
|
|
1
2
|
import { createValidator } from './create.js';
|
|
2
3
|
import { fault, quote, readOptions } from './faults.js';
|
|
3
|
-
import {
|
|
4
|
+
import { reject } from './issues.js';
|
|
5
|
+
import { urlProtocols } from './rules.js';
|
|
4
6
|
import { schemePattern, uriPattern } from './uri-grammar.js';
|
|
5
7
|
const empty = 0;
|
|
6
|
-
|
|
8
|
+
/** The `protocols` a `url()` call declares, checked, and each fault marks it or one entry. */
|
|
9
|
+
function protocolsOf(options, value) {
|
|
7
10
|
if (value === undefined) {
|
|
8
11
|
return undefined;
|
|
9
12
|
}
|
|
13
|
+
const at = (mark) => ({ arguments: [options], factory: 'url', mark });
|
|
10
14
|
if (!Array.isArray(value)) {
|
|
11
|
-
throw fault('
|
|
15
|
+
throw fault(urlProtocols, at('0.protocols'), {
|
|
16
|
+
correction: 'Supply an array of scheme names.',
|
|
17
|
+
sentence: 'url() protocols is not an array.',
|
|
18
|
+
});
|
|
12
19
|
}
|
|
13
20
|
const items = value;
|
|
14
21
|
if (items.length === empty) {
|
|
15
|
-
throw fault(
|
|
22
|
+
throw fault(urlProtocols, at('0.protocols'), {
|
|
23
|
+
correction: 'List at least one scheme.',
|
|
24
|
+
sentence: 'url() protocols is empty.',
|
|
25
|
+
});
|
|
16
26
|
}
|
|
17
27
|
// `Array.from` reads a hole as `undefined`, so a sparse list faults instead of skipping it.
|
|
18
|
-
return Array.from(items, (item) => {
|
|
28
|
+
return Array.from(items, (item, index) => {
|
|
19
29
|
if (typeof item !== 'string' || !schemePattern.test(item)) {
|
|
20
|
-
throw fault(`
|
|
30
|
+
throw fault(urlProtocols, at(`0.protocols.${String(index)}`), {
|
|
31
|
+
correction: 'List a letter followed by letters, digits, +, -, or ., with no trailing colon.',
|
|
32
|
+
sentence: `url() protocols lists ${quote(item)}, which is not a scheme name.`,
|
|
33
|
+
});
|
|
21
34
|
}
|
|
22
35
|
return item;
|
|
23
36
|
});
|
|
@@ -37,12 +50,10 @@ function schemesPattern(protocols) {
|
|
|
37
50
|
}
|
|
38
51
|
/** An absolute RFC 3986 URI that the WHATWG parser also reads, optionally with a listed scheme. */
|
|
39
52
|
function url(options) {
|
|
40
|
-
const protocols = protocolsOf(readOptions('url', options).protocols);
|
|
53
|
+
const protocols = protocolsOf(options, readOptions('url', options).protocols);
|
|
41
54
|
// The WHATWG parser lowercases the scheme and ends `protocol` with a colon.
|
|
42
55
|
const listed = new Set(protocols?.map((protocol) => `${protocol.toLowerCase()}:`));
|
|
43
|
-
const
|
|
44
|
-
? 'Expected an absolute URL, such as https://example.com.'
|
|
45
|
-
: `Expected an absolute URL with the scheme ${listing(protocols)}.`;
|
|
56
|
+
const issue = protocols === undefined ? urlIssue.issue({}) : urlSchemeIssue.issue({ protocols });
|
|
46
57
|
return createValidator({
|
|
47
58
|
inputSchema: {
|
|
48
59
|
type: 'string',
|
|
@@ -51,12 +62,12 @@ function url(options) {
|
|
|
51
62
|
},
|
|
52
63
|
parse: (raw) => {
|
|
53
64
|
if (!uriPattern.test(raw) || !URL.canParse(raw)) {
|
|
54
|
-
return reject(
|
|
65
|
+
return reject(issue);
|
|
55
66
|
}
|
|
56
67
|
const parsed = new URL(raw);
|
|
57
68
|
return protocols === undefined || listed.has(parsed.protocol)
|
|
58
69
|
? { value: parsed }
|
|
59
|
-
: reject(
|
|
70
|
+
: reject(issue);
|
|
60
71
|
},
|
|
61
72
|
});
|
|
62
73
|
}
|
package/dist/uuid.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { uuidIssue } from './codes.js';
|
|
1
2
|
import { createValidator } from './create.js';
|
|
2
3
|
import { reject } from './issues.js';
|
|
3
4
|
const grouped = /^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/u;
|
|
4
5
|
/** A UUID of any version in any letter case, read as lowercase so two spellings compare equal. */
|
|
5
6
|
function uuid() {
|
|
7
|
+
const issue = uuidIssue.issue({});
|
|
6
8
|
return createValidator({
|
|
7
9
|
inputSchema: { type: 'string', format: 'uuid' },
|
|
8
|
-
parse: (raw) => grouped.test(raw)
|
|
9
|
-
? { value: raw.toLowerCase() }
|
|
10
|
-
: reject('Expected a UUID, such as 123e4567-e89b-12d3-a456-426614174000.'),
|
|
10
|
+
parse: (raw) => grouped.test(raw) ? { value: raw.toLowerCase() } : reject(issue),
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
13
|
export { uuid };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomcli/validators",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "The Loom CLI validator catalog. Ships Standard Schema values for common command-line input shapes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"ajv-formats": "^3.0.1"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@loomcli/core": "0.
|
|
26
|
+
"@loomcli/core": "0.6.0"
|
|
27
27
|
},
|
|
28
28
|
"engines": {
|
|
29
29
|
"bun": ">=1.4.0",
|