@atproto/lex-schema 0.0.20 → 0.1.0-next.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/CHANGELOG.md +20 -0
- package/dist/core/$type.js +2 -6
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.js +4 -8
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/result.js +6 -14
- package/dist/core/result.js.map +1 -1
- package/dist/core/schema.js +16 -20
- package/dist/core/schema.js.map +1 -1
- package/dist/core/standard-schema.js +5 -10
- package/dist/core/standard-schema.js.map +1 -1
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +37 -61
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/types.js +1 -2
- package/dist/core/validation-error.js +14 -25
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validation-issue.js +12 -40
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.js +19 -28
- package/dist/core/validator.js.map +1 -1
- package/dist/core.js +9 -12
- package/dist/core.js.map +1 -1
- package/dist/external.js +3 -6
- package/dist/external.js.map +1 -1
- package/dist/helpers.js +5 -9
- package/dist/helpers.js.map +1 -1
- package/dist/index.js +3 -7
- package/dist/index.js.map +1 -1
- package/dist/schema/array.js +5 -11
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.js +10 -17
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.js +8 -9
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.js +7 -12
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.js +7 -12
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.js +5 -13
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.js +6 -13
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.js +10 -18
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.js +6 -11
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.js +5 -10
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.js +4 -11
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/lex-map.js +13 -14
- package/dist/schema/lex-map.js.map +1 -1
- package/dist/schema/lex-value.js +11 -12
- package/dist/schema/lex-value.js.map +1 -1
- package/dist/schema/literal.js +4 -10
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.js +8 -9
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.js +9 -10
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.js +5 -10
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.js +8 -14
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.js +5 -10
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.js +39 -44
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.js +5 -13
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.js +2 -10
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.js +2 -9
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.js +3 -13
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.js +3 -12
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.js +15 -24
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.js +4 -9
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.js +3 -6
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.js +4 -11
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.js +15 -26
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.js +3 -12
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.js +5 -11
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.js +11 -18
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.js +4 -9
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.js +8 -15
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.js +5 -11
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown.js +8 -9
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.js +4 -11
- package/dist/schema/with-default.js.map +1 -1
- package/dist/schema.js +38 -41
- package/dist/schema.js.map +1 -1
- package/dist/util/array-agg.js +1 -4
- package/dist/util/array-agg.js.map +1 -1
- package/dist/util/assertion-util.js +1 -2
- package/dist/util/if-any.js +1 -2
- package/dist/util/lazy-property.js +1 -4
- package/dist/util/lazy-property.js.map +1 -1
- package/dist/util/memoize.js +2 -6
- package/dist/util/memoize.js.map +1 -1
- package/package.json +7 -8
- package/src/core/string-format.ts +2 -1
- package/src/helpers.test.ts +52 -52
- package/src/schema/record.test.ts +2 -2
- package/src/schema/ref.test.ts +1 -1
- package/src/schema/string.test.ts +6 -6
- package/src/schema/subscription.test.ts +4 -4
- package/src/schema/typed-object.test.ts +2 -2
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.isAtUriStringLenient = isAtUriStringLenient;
|
|
6
|
-
exports.isStringFormat = isStringFormat;
|
|
7
|
-
exports.assertStringFormat = assertStringFormat;
|
|
8
|
-
exports.asStringFormat = asStringFormat;
|
|
9
|
-
exports.ifStringFormat = ifStringFormat;
|
|
10
|
-
const iso_datestring_validator_1 = require("iso-datestring-validator");
|
|
11
|
-
const lex_data_1 = require("@atproto/lex-data");
|
|
12
|
-
const syntax_1 = require("@atproto/syntax");
|
|
1
|
+
import isoDatestringValidator from 'iso-datestring-validator';
|
|
2
|
+
const { isValidISODateString } = isoDatestringValidator;
|
|
3
|
+
import { validateCidString } from '@atproto/lex-data';
|
|
4
|
+
import { isAtIdentifierString, isAtUriString, isDatetimeString, isValidDid, isValidHandle, isValidLanguage, isValidNsid, isValidRecordKey, isValidTid, isValidUri, } from '@atproto/syntax';
|
|
13
5
|
// -----------------------------------------------------------------------------
|
|
14
6
|
// Individual string format types and type guards
|
|
15
7
|
// -----------------------------------------------------------------------------
|
|
@@ -17,33 +9,23 @@ const syntax_1 = require("@atproto/syntax");
|
|
|
17
9
|
// documentation for types and utilities that are already well-defined there.
|
|
18
10
|
// @TODO rework other string formats in @atproto/syntax to follow this pattern
|
|
19
11
|
// and re-export here, e.g. language tags, NSIDs, record keys, etc.
|
|
20
|
-
|
|
21
|
-
Object.defineProperty(exports, "asAtIdentifierString", { enumerable: true, get: function () { return syntax_2.asAtIdentifierString; } });
|
|
22
|
-
Object.defineProperty(exports, "assertAtIdentifierString", { enumerable: true, get: function () { return syntax_2.assertAtIdentifierString; } });
|
|
23
|
-
Object.defineProperty(exports, "ifAtIdentifierString", { enumerable: true, get: function () { return syntax_2.ifAtIdentifierString; } });
|
|
24
|
-
Object.defineProperty(exports, "isAtIdentifierString", { enumerable: true, get: function () { return syntax_2.isAtIdentifierString; } });
|
|
12
|
+
export { asAtIdentifierString, assertAtIdentifierString, ifAtIdentifierString, isAtIdentifierString, } from '@atproto/syntax';
|
|
25
13
|
// AtIdentifierString utilities
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Object.defineProperty(exports, "isHandleIdentifier", { enumerable: true, get: function () { return syntax_3.isHandleIdentifier; } });
|
|
29
|
-
var syntax_4 = require("@atproto/syntax");
|
|
30
|
-
Object.defineProperty(exports, "asDatetimeString", { enumerable: true, get: function () { return syntax_4.asDatetimeString; } });
|
|
31
|
-
Object.defineProperty(exports, "assertDatetimeString", { enumerable: true, get: function () { return syntax_4.assertDatetimeString; } });
|
|
32
|
-
Object.defineProperty(exports, "ifDatetimeString", { enumerable: true, get: function () { return syntax_4.ifDatetimeString; } });
|
|
33
|
-
Object.defineProperty(exports, "isDatetimeString", { enumerable: true, get: function () { return syntax_4.isDatetimeString; } });
|
|
14
|
+
export { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax';
|
|
15
|
+
export { asDatetimeString, assertDatetimeString, ifDatetimeString, isDatetimeString, } from '@atproto/syntax';
|
|
34
16
|
/**
|
|
35
17
|
* Matches any ISO-ish datetime string. This is a more lenient check than
|
|
36
18
|
* the strict {@link isDatetimeString} guard, which only allows datetimes that
|
|
37
19
|
* fully conform to the AT Protocol specification (e.g. must include timezone).
|
|
38
20
|
*/
|
|
39
|
-
function isDatetimeStringLenient(input) {
|
|
21
|
+
export function isDatetimeStringLenient(input) {
|
|
40
22
|
// @NOTE the returned type assertion is inaccurate wrt. the DatetimeString
|
|
41
23
|
// type definition. A more accurate solution would be to use a branded type
|
|
42
24
|
// instead of a template literal for the "datetime" format
|
|
43
25
|
if (typeof input !== 'string')
|
|
44
26
|
return false;
|
|
45
27
|
try {
|
|
46
|
-
return
|
|
28
|
+
return isValidISODateString(input);
|
|
47
29
|
}
|
|
48
30
|
catch {
|
|
49
31
|
// @NOTE isValidISODateString throws on some inputs
|
|
@@ -51,22 +33,16 @@ function isDatetimeStringLenient(input) {
|
|
|
51
33
|
}
|
|
52
34
|
}
|
|
53
35
|
// DatetimeString utilities
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Object.defineProperty(exports, "toDatetimeString", { enumerable: true, get: function () { return syntax_5.toDatetimeString; } });
|
|
57
|
-
var syntax_6 = require("@atproto/syntax");
|
|
58
|
-
Object.defineProperty(exports, "asAtUriString", { enumerable: true, get: function () { return syntax_6.asAtUriString; } });
|
|
59
|
-
Object.defineProperty(exports, "assertAtUriString", { enumerable: true, get: function () { return syntax_6.assertAtUriString; } });
|
|
60
|
-
Object.defineProperty(exports, "ifAtUriString", { enumerable: true, get: function () { return syntax_6.ifAtUriString; } });
|
|
61
|
-
Object.defineProperty(exports, "isAtUriString", { enumerable: true, get: function () { return syntax_6.isAtUriString; } });
|
|
36
|
+
export { currentDatetimeString, toDatetimeString } from '@atproto/syntax';
|
|
37
|
+
export { asAtUriString, assertAtUriString, ifAtUriString, isAtUriString, } from '@atproto/syntax';
|
|
62
38
|
/**
|
|
63
39
|
* Lenient version of {@link isAtUriString} that does not enforce the validity
|
|
64
40
|
* of the record key (rkey) path component (if present).
|
|
65
41
|
*
|
|
66
42
|
* @see {@link isAtUriString}
|
|
67
43
|
*/
|
|
68
|
-
function isAtUriStringLenient(input) {
|
|
69
|
-
return
|
|
44
|
+
export function isAtUriStringLenient(input) {
|
|
45
|
+
return isAtUriString(input, { strict: false });
|
|
70
46
|
}
|
|
71
47
|
/**
|
|
72
48
|
* Type guard that checks if a value is a valid CID string.
|
|
@@ -74,69 +50,69 @@ function isAtUriStringLenient(input) {
|
|
|
74
50
|
* @param value - The value to check
|
|
75
51
|
* @returns `true` if the value is a valid CID string
|
|
76
52
|
*/
|
|
77
|
-
|
|
53
|
+
export const isCidString = ((v) => validateCidString(v));
|
|
78
54
|
/**
|
|
79
55
|
* Type guard that checks if a value is a valid DID string.
|
|
80
56
|
*
|
|
81
57
|
* @param value - The value to check
|
|
82
58
|
* @returns `true` if the value is a valid DID string
|
|
83
59
|
*/
|
|
84
|
-
|
|
60
|
+
export const isDidString = isValidDid;
|
|
85
61
|
/**
|
|
86
62
|
* Type guard that checks if a value is a valid handle string.
|
|
87
63
|
*
|
|
88
64
|
* @param value - The value to check
|
|
89
65
|
* @returns `true` if the value is a valid handle string
|
|
90
66
|
*/
|
|
91
|
-
|
|
67
|
+
export const isHandleString = isValidHandle;
|
|
92
68
|
/**
|
|
93
69
|
* Type guard that checks if a value is a valid BCP-47 language tag.
|
|
94
70
|
*
|
|
95
71
|
* @param value - The value to check
|
|
96
72
|
* @returns `true` if the value is a valid language string
|
|
97
73
|
*/
|
|
98
|
-
|
|
74
|
+
export const isLanguageString = isValidLanguage;
|
|
99
75
|
/**
|
|
100
76
|
* Type guard that checks if a value is a valid NSID string.
|
|
101
77
|
*
|
|
102
78
|
* @param value - The value to check
|
|
103
79
|
* @returns `true` if the value is a valid NSID string
|
|
104
80
|
*/
|
|
105
|
-
|
|
81
|
+
export const isNsidString = isValidNsid;
|
|
106
82
|
/**
|
|
107
83
|
* Type guard that checks if a value is a valid record key string.
|
|
108
84
|
*
|
|
109
85
|
* @param value - The value to check
|
|
110
86
|
* @returns `true` if the value is a valid record key string
|
|
111
87
|
*/
|
|
112
|
-
|
|
88
|
+
export const isRecordKeyString = isValidRecordKey;
|
|
113
89
|
/**
|
|
114
90
|
* Type guard that checks if a value is a valid TID string.
|
|
115
91
|
*
|
|
116
92
|
* @param value - The value to check
|
|
117
93
|
* @returns `true` if the value is a valid TID string
|
|
118
94
|
*/
|
|
119
|
-
|
|
95
|
+
export const isTidString = isValidTid;
|
|
120
96
|
/**
|
|
121
97
|
* Type guard that checks if a value is a valid URI string.
|
|
122
98
|
*
|
|
123
99
|
* @param value - The value to check
|
|
124
100
|
* @returns `true` if the value is a valid URI string
|
|
125
101
|
*/
|
|
126
|
-
|
|
102
|
+
export const isUriString = isValidUri;
|
|
127
103
|
const stringFormatVerifiers = /*#__PURE__*/ Object.freeze({
|
|
128
104
|
__proto__: null,
|
|
129
|
-
'at-identifier': [
|
|
130
|
-
'at-uri': [
|
|
131
|
-
cid: [
|
|
132
|
-
datetime: [
|
|
133
|
-
did: [
|
|
134
|
-
handle: [
|
|
135
|
-
language: [
|
|
136
|
-
nsid: [
|
|
137
|
-
'record-key': [
|
|
138
|
-
tid: [
|
|
139
|
-
uri: [
|
|
105
|
+
'at-identifier': [isAtIdentifierString],
|
|
106
|
+
'at-uri': [isAtUriString, isAtUriStringLenient],
|
|
107
|
+
cid: [isCidString],
|
|
108
|
+
datetime: [isDatetimeString, isDatetimeStringLenient],
|
|
109
|
+
did: [isDidString],
|
|
110
|
+
handle: [isHandleString],
|
|
111
|
+
language: [isLanguageString],
|
|
112
|
+
nsid: [isNsidString],
|
|
113
|
+
'record-key': [isRecordKeyString],
|
|
114
|
+
tid: [isTidString],
|
|
115
|
+
uri: [isUriString],
|
|
140
116
|
});
|
|
141
117
|
/**
|
|
142
118
|
* Type guard that checks if a string matches a specific format.
|
|
@@ -157,7 +133,7 @@ const stringFormatVerifiers = /*#__PURE__*/ Object.freeze({
|
|
|
157
133
|
* ```
|
|
158
134
|
*/
|
|
159
135
|
/*@__NO_SIDE_EFFECTS__*/
|
|
160
|
-
function isStringFormat(input, format, options) {
|
|
136
|
+
export function isStringFormat(input, format, options) {
|
|
161
137
|
const formatVerifier = stringFormatVerifiers[format];
|
|
162
138
|
// Fool-proof
|
|
163
139
|
if (!formatVerifier)
|
|
@@ -183,7 +159,7 @@ function isStringFormat(input, format, options) {
|
|
|
183
159
|
* ```
|
|
184
160
|
*/
|
|
185
161
|
/*@__NO_SIDE_EFFECTS__*/
|
|
186
|
-
function assertStringFormat(input, format, options) {
|
|
162
|
+
export function assertStringFormat(input, format, options) {
|
|
187
163
|
if (!isStringFormat(input, format, options)) {
|
|
188
164
|
throw new TypeError(`Invalid string format (${format}): ${input}`);
|
|
189
165
|
}
|
|
@@ -207,7 +183,7 @@ function assertStringFormat(input, format, options) {
|
|
|
207
183
|
* ```
|
|
208
184
|
*/
|
|
209
185
|
/*@__NO_SIDE_EFFECTS__*/
|
|
210
|
-
function asStringFormat(input, format, options) {
|
|
186
|
+
export function asStringFormat(input, format, options) {
|
|
211
187
|
assertStringFormat(input, format, options);
|
|
212
188
|
return input;
|
|
213
189
|
}
|
|
@@ -232,7 +208,7 @@ function asStringFormat(input, format, options) {
|
|
|
232
208
|
* ```
|
|
233
209
|
*/
|
|
234
210
|
/*@__NO_SIDE_EFFECTS__*/
|
|
235
|
-
function ifStringFormat(input, format, options) {
|
|
211
|
+
export function ifStringFormat(input, format, options) {
|
|
236
212
|
return isStringFormat(input, format, options) ? input : undefined;
|
|
237
213
|
}
|
|
238
214
|
/**
|
|
@@ -245,6 +221,6 @@ function ifStringFormat(input, format, options) {
|
|
|
245
221
|
* }
|
|
246
222
|
* ```
|
|
247
223
|
*/
|
|
248
|
-
|
|
224
|
+
export const STRING_FORMATS = /*#__PURE__*/ Object.freeze(
|
|
249
225
|
/*#__PURE__*/ Object.keys(stringFormatVerifiers));
|
|
250
226
|
//# sourceMappingURL=string-format.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string-format.js","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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","sourcesContent":["import { isValidISODateString } from 'iso-datestring-validator'\nimport { validateCidString } from '@atproto/lex-data'\nimport {\n AtIdentifierString,\n AtUriString,\n DatetimeString,\n DidString,\n HandleString,\n NsidString,\n RecordKeyString,\n TidString,\n UriString,\n isAtIdentifierString,\n isAtUriString,\n isDatetimeString,\n isValidDid,\n isValidHandle,\n isValidLanguage,\n isValidNsid,\n isValidRecordKey,\n isValidTid,\n isValidUri,\n} from '@atproto/syntax'\nimport { CheckFn } from '../util/assertion-util.js'\n\n// -----------------------------------------------------------------------------\n// Individual string format types and type guards\n// -----------------------------------------------------------------------------\n\n// Re-exporting from @atproto/syntax without modification to preserve types and\n// documentation for types and utilities that are already well-defined there.\n// @TODO rework other string formats in @atproto/syntax to follow this pattern\n// and re-export here, e.g. language tags, NSIDs, record keys, etc.\n\nexport {\n type AtIdentifierString,\n asAtIdentifierString,\n assertAtIdentifierString,\n ifAtIdentifierString,\n isAtIdentifierString,\n} from '@atproto/syntax'\n\n// AtIdentifierString utilities\nexport { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax'\n\nexport {\n type DatetimeString,\n asDatetimeString,\n assertDatetimeString,\n ifDatetimeString,\n isDatetimeString,\n} from '@atproto/syntax'\n\n/**\n * Matches any ISO-ish datetime string. This is a more lenient check than\n * the strict {@link isDatetimeString} guard, which only allows datetimes that\n * fully conform to the AT Protocol specification (e.g. must include timezone).\n */\nexport function isDatetimeStringLenient<I>(\n input: I,\n): input is I & DatetimeString {\n // @NOTE the returned type assertion is inaccurate wrt. the DatetimeString\n // type definition. A more accurate solution would be to use a branded type\n // instead of a template literal for the \"datetime\" format\n if (typeof input !== 'string') return false\n try {\n return isValidISODateString(input)\n } catch {\n // @NOTE isValidISODateString throws on some inputs\n return false\n }\n}\n\n// DatetimeString utilities\nexport { currentDatetimeString, toDatetimeString } from '@atproto/syntax'\n\nexport {\n type AtUriString,\n asAtUriString,\n assertAtUriString,\n ifAtUriString,\n isAtUriString,\n} from '@atproto/syntax'\n\n/**\n * Lenient version of {@link isAtUriString} that does not enforce the validity\n * of the record key (rkey) path component (if present).\n *\n * @see {@link isAtUriString}\n */\nexport function isAtUriStringLenient<I>(input: I): input is I & AtUriString {\n return isAtUriString(input, { strict: false })\n}\n\n/**\n * Type guard that checks if a value is a valid CID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid CID string\n */\nexport const isCidString = ((v) => validateCidString(v)) as CheckFn<CidString>\n/**\n * A Content Identifier (CID) string.\n *\n * CIDs are self-describing content addresses used to identify data by its hash.\n *\n * @example `\"bafyreig...\"`\n */\nexport type CidString = string\n\n/**\n * Type guard that checks if a value is a valid DID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid DID string\n */\nexport const isDidString: CheckFn<DidString> = isValidDid\nexport type {\n /**\n * A Decentralized Identifier (DID) string.\n *\n * DIDs are globally unique identifiers that don't require a central authority.\n *\n * @example `\"did:plc:1234abcd...\"` or `\"did:web:example.com\"`\n */\n DidString,\n}\n\n/**\n * Type guard that checks if a value is a valid handle string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid handle string\n */\nexport const isHandleString: CheckFn<HandleString> = isValidHandle\nexport type {\n /**\n * A handle string - a human-readable identifier for users.\n *\n * @example `\"alice.bsky.social\"` or `\"bob.example.com\"`\n */\n HandleString,\n}\n\n/**\n * Type guard that checks if a value is a valid BCP-47 language tag.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid language string\n */\nexport const isLanguageString = isValidLanguage as CheckFn<LanguageString>\n/**\n * A BCP-47 language tag string.\n *\n * @example `\"en\"`, `\"en-US\"`, `\"zh-Hans\"`\n */\nexport type LanguageString = string\n\n/**\n * Type guard that checks if a value is a valid NSID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid NSID string\n */\nexport const isNsidString: CheckFn<NsidString> = isValidNsid\nexport type {\n /**\n * A Namespaced Identifier (NSID) string identifying a lexicon.\n *\n * NSIDs use reverse-domain notation to identify schemas.\n *\n * @example `\"app.bsky.feed.post\"`, `\"com.atproto.repo.createRecord\"`\n */\n NsidString,\n}\n\n/**\n * Type guard that checks if a value is a valid record key string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid record key string\n */\nexport const isRecordKeyString: CheckFn<RecordKeyString> = isValidRecordKey\nexport type {\n /**\n * A record key string identifying a record within a collection.\n *\n * @example `\"3k2...\"` (TID format) or `\"self\"` (literal key)\n */\n RecordKeyString,\n}\n\n/**\n * Type guard that checks if a value is a valid TID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid TID string\n */\nexport const isTidString: CheckFn<TidString> = isValidTid\nexport type {\n /**\n * A Timestamp Identifier (TID) string.\n *\n * TIDs are time-based identifiers used for record keys.\n *\n * @example `\"3k2...\"`\n */\n TidString,\n}\n\n/**\n * Type guard that checks if a value is a valid URI string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid URI string\n */\nexport const isUriString: CheckFn<UriString> = isValidUri\nexport type {\n /**\n * A standard URI string.\n *\n * @example `\"https://example.com/path\"`\n */\n UriString,\n}\n\n// -----------------------------------------------------------------------------\n// String format registry\n// -----------------------------------------------------------------------------\n\ntype StringFormats = {\n 'at-identifier': AtIdentifierString\n 'at-uri': AtUriString\n cid: CidString\n datetime: DatetimeString\n did: DidString\n handle: HandleString\n language: LanguageString\n nsid: NsidString\n 'record-key': RecordKeyString\n tid: TidString\n uri: UriString\n}\n\n/**\n * Union type of all valid string format names.\n */\nexport type StringFormat = Extract<keyof StringFormats, string>\n\nconst stringFormatVerifiers: {\n readonly [K in StringFormat]: readonly [\n strict: CheckFn<StringFormats[K]>,\n lenient?: CheckFn<StringFormats[K]>,\n ]\n} = /*#__PURE__*/ Object.freeze({\n __proto__: null,\n\n 'at-identifier': [isAtIdentifierString],\n 'at-uri': [isAtUriString, isAtUriStringLenient],\n cid: [isCidString],\n datetime: [isDatetimeString, isDatetimeStringLenient],\n did: [isDidString],\n handle: [isHandleString],\n language: [isLanguageString],\n nsid: [isNsidString],\n 'record-key': [isRecordKeyString],\n tid: [isTidString],\n uri: [isUriString],\n})\n\nexport type StringFormatValidationOptions = {\n /**\n * Allows to be more lenient in validation by using a \"lenient\" verification\n * function, if available. The behavior of the lenient verifier depends on the\n * specific format, but generally it may allow for a wider range of valid\n * inputs, including values that are not compliant with the AT Protocol\n * specification.\n *\n * @default true\n */\n strict?: boolean\n}\n\n/**\n * Infers the string type for a given format name.\n *\n * @typeParam F - The format name\n *\n * @example\n * ```typescript\n * type Did = InferStringFormat<'did'>\n * // Result: DidString\n * ```\n */\nexport type InferStringFormat<F extends StringFormat> = F extends StringFormat\n ? StringFormats[F]\n : never\n\n/**\n * Type guard that checks if a string matches a specific format.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to check\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns `true` if the string matches the format\n *\n * @example\n * ```typescript\n * const value: string = 'did:plc:1234...'\n * if (isStringFormat(value, 'did')) {\n * // value is typed as DidString\n * console.log('Valid DID:', value)\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): input is I & StringFormats[F] {\n const formatVerifier = stringFormatVerifiers[format]\n // Fool-proof\n if (!formatVerifier) throw new TypeError(`Unknown string format: ${format}`)\n\n const check: CheckFn<StringFormats[F]> =\n options?.strict === false && formatVerifier.length > 1\n ? formatVerifier[1]!\n : formatVerifier[0]\n\n return check(input)\n}\n\n/**\n * Asserts that a string matches a specific format, throwing if invalid.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to check\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @throws {TypeError} If the string doesn't match the format\n *\n * @example\n * ```typescript\n * assertStringFormat(value, 'handle')\n * // value is now typed as HandleString\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function assertStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): asserts input is I & StringFormats[F] {\n if (!isStringFormat(input, format, options)) {\n throw new TypeError(`Invalid string format (${format}): ${input}`)\n }\n}\n\n/**\n * Validates and returns a string as the specified format type, throwing if invalid.\n *\n * This is useful when you need to convert a string to a format type in an expression.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to validate against\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns The input typed as the format type\n * @throws {TypeError} If the string doesn't match the format\n *\n * @example\n * ```typescript\n * const did = asStringFormat(userInput, 'did')\n * // did is typed as DidString\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function asStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): I & StringFormats[F] {\n assertStringFormat(input, format, options)\n return input\n}\n\n/**\n * Returns the string as the format type if valid, otherwise returns `undefined`.\n *\n * This is useful for optional validation where you want to handle invalid values\n * without throwing.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to validate against\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns The typed string if valid, otherwise `undefined`\n *\n * @example\n * ```typescript\n * const did = ifStringFormat(maybeInvalid, 'did')\n * if (did) {\n * // did is typed as DidString\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function ifStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): undefined | (I & StringFormats[F]) {\n return isStringFormat(input, format, options) ? input : undefined\n}\n\n/**\n * Array of all valid string format names.\n *\n * @example\n * ```typescript\n * for (const format of STRING_FORMATS) {\n * console.log(format) // 'at-identifier', 'at-uri', 'cid', ...\n * }\n * ```\n */\nexport const STRING_FORMATS = /*#__PURE__*/ Object.freeze(\n /*#__PURE__*/ Object.keys(stringFormatVerifiers),\n) as readonly StringFormat[]\n"]}
|
|
1
|
+
{"version":3,"file":"string-format.js","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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","sourcesContent":["import isoDatestringValidator from 'iso-datestring-validator'\nconst { isValidISODateString } = isoDatestringValidator\nimport { validateCidString } from '@atproto/lex-data'\nimport {\n AtIdentifierString,\n AtUriString,\n DatetimeString,\n DidString,\n HandleString,\n NsidString,\n RecordKeyString,\n TidString,\n UriString,\n isAtIdentifierString,\n isAtUriString,\n isDatetimeString,\n isValidDid,\n isValidHandle,\n isValidLanguage,\n isValidNsid,\n isValidRecordKey,\n isValidTid,\n isValidUri,\n} from '@atproto/syntax'\nimport { CheckFn } from '../util/assertion-util.js'\n\n// -----------------------------------------------------------------------------\n// Individual string format types and type guards\n// -----------------------------------------------------------------------------\n\n// Re-exporting from @atproto/syntax without modification to preserve types and\n// documentation for types and utilities that are already well-defined there.\n// @TODO rework other string formats in @atproto/syntax to follow this pattern\n// and re-export here, e.g. language tags, NSIDs, record keys, etc.\n\nexport {\n type AtIdentifierString,\n asAtIdentifierString,\n assertAtIdentifierString,\n ifAtIdentifierString,\n isAtIdentifierString,\n} from '@atproto/syntax'\n\n// AtIdentifierString utilities\nexport { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax'\n\nexport {\n type DatetimeString,\n asDatetimeString,\n assertDatetimeString,\n ifDatetimeString,\n isDatetimeString,\n} from '@atproto/syntax'\n\n/**\n * Matches any ISO-ish datetime string. This is a more lenient check than\n * the strict {@link isDatetimeString} guard, which only allows datetimes that\n * fully conform to the AT Protocol specification (e.g. must include timezone).\n */\nexport function isDatetimeStringLenient<I>(\n input: I,\n): input is I & DatetimeString {\n // @NOTE the returned type assertion is inaccurate wrt. the DatetimeString\n // type definition. A more accurate solution would be to use a branded type\n // instead of a template literal for the \"datetime\" format\n if (typeof input !== 'string') return false\n try {\n return isValidISODateString(input)\n } catch {\n // @NOTE isValidISODateString throws on some inputs\n return false\n }\n}\n\n// DatetimeString utilities\nexport { currentDatetimeString, toDatetimeString } from '@atproto/syntax'\n\nexport {\n type AtUriString,\n asAtUriString,\n assertAtUriString,\n ifAtUriString,\n isAtUriString,\n} from '@atproto/syntax'\n\n/**\n * Lenient version of {@link isAtUriString} that does not enforce the validity\n * of the record key (rkey) path component (if present).\n *\n * @see {@link isAtUriString}\n */\nexport function isAtUriStringLenient<I>(input: I): input is I & AtUriString {\n return isAtUriString(input, { strict: false })\n}\n\n/**\n * Type guard that checks if a value is a valid CID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid CID string\n */\nexport const isCidString = ((v) => validateCidString(v)) as CheckFn<CidString>\n/**\n * A Content Identifier (CID) string.\n *\n * CIDs are self-describing content addresses used to identify data by its hash.\n *\n * @example `\"bafyreig...\"`\n */\nexport type CidString = string\n\n/**\n * Type guard that checks if a value is a valid DID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid DID string\n */\nexport const isDidString: CheckFn<DidString> = isValidDid\nexport type {\n /**\n * A Decentralized Identifier (DID) string.\n *\n * DIDs are globally unique identifiers that don't require a central authority.\n *\n * @example `\"did:plc:1234abcd...\"` or `\"did:web:example.com\"`\n */\n DidString,\n}\n\n/**\n * Type guard that checks if a value is a valid handle string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid handle string\n */\nexport const isHandleString: CheckFn<HandleString> = isValidHandle\nexport type {\n /**\n * A handle string - a human-readable identifier for users.\n *\n * @example `\"alice.bsky.social\"` or `\"bob.example.com\"`\n */\n HandleString,\n}\n\n/**\n * Type guard that checks if a value is a valid BCP-47 language tag.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid language string\n */\nexport const isLanguageString = isValidLanguage as CheckFn<LanguageString>\n/**\n * A BCP-47 language tag string.\n *\n * @example `\"en\"`, `\"en-US\"`, `\"zh-Hans\"`\n */\nexport type LanguageString = string\n\n/**\n * Type guard that checks if a value is a valid NSID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid NSID string\n */\nexport const isNsidString: CheckFn<NsidString> = isValidNsid\nexport type {\n /**\n * A Namespaced Identifier (NSID) string identifying a lexicon.\n *\n * NSIDs use reverse-domain notation to identify schemas.\n *\n * @example `\"app.bsky.feed.post\"`, `\"com.atproto.repo.createRecord\"`\n */\n NsidString,\n}\n\n/**\n * Type guard that checks if a value is a valid record key string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid record key string\n */\nexport const isRecordKeyString: CheckFn<RecordKeyString> = isValidRecordKey\nexport type {\n /**\n * A record key string identifying a record within a collection.\n *\n * @example `\"3k2...\"` (TID format) or `\"self\"` (literal key)\n */\n RecordKeyString,\n}\n\n/**\n * Type guard that checks if a value is a valid TID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid TID string\n */\nexport const isTidString: CheckFn<TidString> = isValidTid\nexport type {\n /**\n * A Timestamp Identifier (TID) string.\n *\n * TIDs are time-based identifiers used for record keys.\n *\n * @example `\"3k2...\"`\n */\n TidString,\n}\n\n/**\n * Type guard that checks if a value is a valid URI string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid URI string\n */\nexport const isUriString: CheckFn<UriString> = isValidUri\nexport type {\n /**\n * A standard URI string.\n *\n * @example `\"https://example.com/path\"`\n */\n UriString,\n}\n\n// -----------------------------------------------------------------------------\n// String format registry\n// -----------------------------------------------------------------------------\n\ntype StringFormats = {\n 'at-identifier': AtIdentifierString\n 'at-uri': AtUriString\n cid: CidString\n datetime: DatetimeString\n did: DidString\n handle: HandleString\n language: LanguageString\n nsid: NsidString\n 'record-key': RecordKeyString\n tid: TidString\n uri: UriString\n}\n\n/**\n * Union type of all valid string format names.\n */\nexport type StringFormat = Extract<keyof StringFormats, string>\n\nconst stringFormatVerifiers: {\n readonly [K in StringFormat]: readonly [\n strict: CheckFn<StringFormats[K]>,\n lenient?: CheckFn<StringFormats[K]>,\n ]\n} = /*#__PURE__*/ Object.freeze({\n __proto__: null,\n\n 'at-identifier': [isAtIdentifierString],\n 'at-uri': [isAtUriString, isAtUriStringLenient],\n cid: [isCidString],\n datetime: [isDatetimeString, isDatetimeStringLenient],\n did: [isDidString],\n handle: [isHandleString],\n language: [isLanguageString],\n nsid: [isNsidString],\n 'record-key': [isRecordKeyString],\n tid: [isTidString],\n uri: [isUriString],\n})\n\nexport type StringFormatValidationOptions = {\n /**\n * Allows to be more lenient in validation by using a \"lenient\" verification\n * function, if available. The behavior of the lenient verifier depends on the\n * specific format, but generally it may allow for a wider range of valid\n * inputs, including values that are not compliant with the AT Protocol\n * specification.\n *\n * @default true\n */\n strict?: boolean\n}\n\n/**\n * Infers the string type for a given format name.\n *\n * @typeParam F - The format name\n *\n * @example\n * ```typescript\n * type Did = InferStringFormat<'did'>\n * // Result: DidString\n * ```\n */\nexport type InferStringFormat<F extends StringFormat> = F extends StringFormat\n ? StringFormats[F]\n : never\n\n/**\n * Type guard that checks if a string matches a specific format.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to check\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns `true` if the string matches the format\n *\n * @example\n * ```typescript\n * const value: string = 'did:plc:1234...'\n * if (isStringFormat(value, 'did')) {\n * // value is typed as DidString\n * console.log('Valid DID:', value)\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): input is I & StringFormats[F] {\n const formatVerifier = stringFormatVerifiers[format]\n // Fool-proof\n if (!formatVerifier) throw new TypeError(`Unknown string format: ${format}`)\n\n const check: CheckFn<StringFormats[F]> =\n options?.strict === false && formatVerifier.length > 1\n ? formatVerifier[1]!\n : formatVerifier[0]\n\n return check(input)\n}\n\n/**\n * Asserts that a string matches a specific format, throwing if invalid.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to check\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @throws {TypeError} If the string doesn't match the format\n *\n * @example\n * ```typescript\n * assertStringFormat(value, 'handle')\n * // value is now typed as HandleString\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function assertStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): asserts input is I & StringFormats[F] {\n if (!isStringFormat(input, format, options)) {\n throw new TypeError(`Invalid string format (${format}): ${input}`)\n }\n}\n\n/**\n * Validates and returns a string as the specified format type, throwing if invalid.\n *\n * This is useful when you need to convert a string to a format type in an expression.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to validate against\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns The input typed as the format type\n * @throws {TypeError} If the string doesn't match the format\n *\n * @example\n * ```typescript\n * const did = asStringFormat(userInput, 'did')\n * // did is typed as DidString\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function asStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): I & StringFormats[F] {\n assertStringFormat(input, format, options)\n return input\n}\n\n/**\n * Returns the string as the format type if valid, otherwise returns `undefined`.\n *\n * This is useful for optional validation where you want to handle invalid values\n * without throwing.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to validate against\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns The typed string if valid, otherwise `undefined`\n *\n * @example\n * ```typescript\n * const did = ifStringFormat(maybeInvalid, 'did')\n * if (did) {\n * // did is typed as DidString\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function ifStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): undefined | (I & StringFormats[F]) {\n return isStringFormat(input, format, options) ? input : undefined\n}\n\n/**\n * Array of all valid string format names.\n *\n * @example\n * ```typescript\n * for (const format of STRING_FORMATS) {\n * console.log(format) // 'at-identifier', 'at-uri', 'cid', ...\n * }\n * ```\n */\nexport const STRING_FORMATS = /*#__PURE__*/ Object.freeze(\n /*#__PURE__*/ Object.keys(stringFormatVerifiers),\n) as readonly StringFormat[]\n"]}
|
package/dist/core/types.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const array_agg_js_1 = require("../util/array-agg.js");
|
|
6
|
-
const result_js_1 = require("./result.js");
|
|
7
|
-
const validation_issue_js_1 = require("./validation-issue.js");
|
|
1
|
+
import { LexError } from '@atproto/lex-data';
|
|
2
|
+
import { arrayAgg } from '../util/array-agg.js';
|
|
3
|
+
import { failureReason } from './result.js';
|
|
4
|
+
import { IssueInvalidType, IssueInvalidValue, } from './validation-issue.js';
|
|
8
5
|
/**
|
|
9
6
|
* Error thrown when validation fails.
|
|
10
7
|
*
|
|
@@ -32,15 +29,7 @@ const validation_issue_js_1 = require("./validation-issue.js");
|
|
|
32
29
|
* directly as a failure reason in validation results, avoiding the need for
|
|
33
30
|
* wrapping it in an additional object.
|
|
34
31
|
*/
|
|
35
|
-
class LexValidationError extends
|
|
36
|
-
name = 'LexValidationError';
|
|
37
|
-
/**
|
|
38
|
-
* The list of validation issues that caused this error.
|
|
39
|
-
*
|
|
40
|
-
* Issues are aggregated when possible (e.g., multiple invalid type issues
|
|
41
|
-
* at the same path are combined into a single issue listing all expected types).
|
|
42
|
-
*/
|
|
43
|
-
issues;
|
|
32
|
+
export class LexValidationError extends LexError {
|
|
44
33
|
/**
|
|
45
34
|
* Creates a new validation error from a list of issues.
|
|
46
35
|
*
|
|
@@ -53,10 +42,11 @@ class LexValidationError extends lex_data_1.LexError {
|
|
|
53
42
|
constructor(issues, options) {
|
|
54
43
|
const issuesAgg = aggregateIssues(issues);
|
|
55
44
|
super('InvalidRequest', issuesAgg.join(', '), options);
|
|
45
|
+
this.name = 'LexValidationError';
|
|
46
|
+
/** @see {ResultFailure.success} */
|
|
47
|
+
this.success = false;
|
|
56
48
|
this.issues = issuesAgg;
|
|
57
49
|
}
|
|
58
|
-
/** @see {ResultFailure.success} */
|
|
59
|
-
success = false;
|
|
60
50
|
/** @see {ResultFailure.reason} */
|
|
61
51
|
get reason() {
|
|
62
52
|
return this;
|
|
@@ -91,15 +81,14 @@ class LexValidationError extends lex_data_1.LexError {
|
|
|
91
81
|
*/
|
|
92
82
|
static fromFailures(failures) {
|
|
93
83
|
if (failures.length === 1)
|
|
94
|
-
return
|
|
84
|
+
return failureReason(failures[0]);
|
|
95
85
|
const issues = failures.flatMap(extractFailureIssues);
|
|
96
86
|
return new LexValidationError(issues, {
|
|
97
87
|
// Keep the original errors as the cause chain
|
|
98
|
-
cause: failures.map(
|
|
88
|
+
cause: failures.map(failureReason),
|
|
99
89
|
});
|
|
100
90
|
}
|
|
101
91
|
}
|
|
102
|
-
exports.LexValidationError = LexValidationError;
|
|
103
92
|
function extractFailureIssues(result) {
|
|
104
93
|
return result.reason.issues;
|
|
105
94
|
}
|
|
@@ -111,12 +100,12 @@ function aggregateIssues(issues) {
|
|
|
111
100
|
return issues;
|
|
112
101
|
return [
|
|
113
102
|
// Aggregate invalid_type with identical paths
|
|
114
|
-
...
|
|
103
|
+
...arrayAgg(issues.filter((issue) => issue instanceof IssueInvalidType), (a, b) => comparePropertyPaths(a.path, b.path), (issues) => new IssueInvalidType(issues[0].path, issues[0].input, Array.from(new Set(issues.flatMap((iss) => iss.expected))))),
|
|
115
104
|
// Aggregate invalid_value with identical paths
|
|
116
|
-
...
|
|
105
|
+
...arrayAgg(issues.filter((issue) => issue instanceof IssueInvalidValue), (a, b) => comparePropertyPaths(a.path, b.path), (issues) => new IssueInvalidValue(issues[0].path, issues[0].input, Array.from(new Set(issues.flatMap((iss) => iss.values))))),
|
|
117
106
|
// Pass through other issues
|
|
118
|
-
...issues.filter((issue) => !(issue instanceof
|
|
119
|
-
!(issue instanceof
|
|
107
|
+
...issues.filter((issue) => !(issue instanceof IssueInvalidType) &&
|
|
108
|
+
!(issue instanceof IssueInvalidValue)),
|
|
120
109
|
];
|
|
121
110
|
}
|
|
122
111
|
/*@__NO_SIDE_EFFECTS__*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-error.js","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validation-error.js","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexError } from '@atproto/lex-data'\nimport { arrayAgg } from '../util/array-agg.js'\nimport { ResultFailure, failureReason } from './result.js'\nimport {\n Issue,\n IssueInvalidType,\n IssueInvalidValue,\n} from './validation-issue.js'\n\n/**\n * Error thrown when validation fails.\n *\n * Contains detailed information about all validation issues encountered,\n * including the path to each invalid value and descriptions of what was\n * expected vs what was received.\n *\n * Extends {@link LexError} with the error name \"InvalidRequest\" for\n * consistency with the AT Protocol error handling conventions.\n *\n * @example\n * ```typescript\n * const error = new LexValidationError([\n * new IssueInvalidType(['user', 'age'], 'hello', ['number'])\n * ])\n * console.log(error.message)\n * // \"Expected integer value type (got \"some-string\") at $.user.age\"\n *\n * console.log(error.issues.length) // 1\n * console.log(error.toJSON())\n * // { error: 'InvalidRequest', message: '...', issues: [...] }\n * ```\n *\n * @note this class implements {@link ResultFailure} to allow it to be used\n * directly as a failure reason in validation results, avoiding the need for\n * wrapping it in an additional object.\n */\nexport class LexValidationError\n extends LexError<'InvalidRequest'>\n implements ResultFailure<LexValidationError>\n{\n name = 'LexValidationError'\n\n /**\n * The list of validation issues that caused this error.\n *\n * Issues are aggregated when possible (e.g., multiple invalid type issues\n * at the same path are combined into a single issue listing all expected types).\n */\n readonly issues: readonly Issue[]\n\n /**\n * Creates a new validation error from a list of issues.\n *\n * Issues are automatically aggregated to combine related issues at the same\n * path (e.g., multiple type expectations from a union schema).\n *\n * @param issues - The validation issues that caused this error\n * @param options - Standard Error options (e.g., `cause`)\n */\n constructor(issues: Issue[], options?: ErrorOptions) {\n const issuesAgg = aggregateIssues(issues)\n super('InvalidRequest', issuesAgg.join(', '), options)\n this.issues = issuesAgg\n }\n\n /** @see {ResultFailure.success} */\n readonly success = false as const\n\n /** @see {ResultFailure.reason} */\n get reason() {\n return this\n }\n\n /**\n * Converts the error to a JSON-serializable object.\n *\n * @returns An object containing the error details and issues details\n */\n override toJSON() {\n return {\n ...super.toJSON(),\n issues: this.issues.map((issue) => issue.toJSON()),\n }\n }\n\n /**\n * Creates a validation error by combining multiple validation failures.\n *\n * This is useful when validating against multiple possible schemas (e.g., unions)\n * and all branches fail. The resulting error contains issues from all failures.\n *\n * @param failures - The validation failures to combine\n * @returns A single validation error containing all issues from the failures\n *\n * @example\n * ```typescript\n * const failures = schemas.map(s => s.safeValidate(data)).filter(r => !r.success)\n * if (failures.length === schemas.length) {\n * throw LexValidationError.fromFailures(failures)\n * }\n * ```\n */\n static fromFailures(\n failures: readonly ResultFailure<LexValidationError>[],\n ): LexValidationError {\n if (failures.length === 1) return failureReason(failures[0])\n const issues = failures.flatMap(extractFailureIssues)\n return new LexValidationError(issues, {\n // Keep the original errors as the cause chain\n cause: failures.map(failureReason),\n })\n }\n}\n\nfunction extractFailureIssues(result: ResultFailure<LexValidationError>) {\n return result.reason.issues\n}\n\nfunction aggregateIssues(issues: Issue[]): Issue[] {\n // Quick path for common cases\n if (issues.length <= 1) return issues\n if (issues.length === 2 && issues[0].code !== issues[1].code) return issues\n\n return [\n // Aggregate invalid_type with identical paths\n ...arrayAgg(\n issues.filter((issue) => issue instanceof IssueInvalidType),\n (a, b) => comparePropertyPaths(a.path, b.path),\n (issues) =>\n new IssueInvalidType(\n issues[0].path,\n issues[0].input,\n Array.from(new Set(issues.flatMap((iss) => iss.expected))),\n ),\n ),\n // Aggregate invalid_value with identical paths\n ...arrayAgg(\n issues.filter((issue) => issue instanceof IssueInvalidValue),\n (a, b) => comparePropertyPaths(a.path, b.path),\n (issues) =>\n new IssueInvalidValue(\n issues[0].path,\n issues[0].input,\n Array.from(new Set(issues.flatMap((iss) => iss.values))),\n ),\n ),\n // Pass through other issues\n ...issues.filter(\n (issue) =>\n !(issue instanceof IssueInvalidType) &&\n !(issue instanceof IssueInvalidValue),\n ),\n ]\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction comparePropertyPaths(\n a: readonly PropertyKey[],\n b: readonly PropertyKey[],\n) {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false\n }\n return true\n}\n"]}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IssueTooSmall = exports.IssueTooBig = exports.IssueRequiredKey = exports.IssueInvalidValue = exports.IssueInvalidType = exports.IssueInvalidFormat = exports.IssueCustom = exports.Issue = void 0;
|
|
4
|
-
const lex_data_1 = require("@atproto/lex-data");
|
|
1
|
+
import { ifCid, isLegacyBlobRef, isPlainObject } from '@atproto/lex-data';
|
|
5
2
|
const STRING_PREVIEW_MAX_LENGTH = 256;
|
|
6
3
|
const STRING_PREVIEW_TRUNCATED_SUFFIX = '…';
|
|
7
4
|
/**
|
|
@@ -16,10 +13,7 @@ const STRING_PREVIEW_TRUNCATED_SUFFIX = '…';
|
|
|
16
13
|
* the {@link message} property for human-readable error messages (that don't
|
|
17
14
|
* contain the error path)
|
|
18
15
|
*/
|
|
19
|
-
class Issue {
|
|
20
|
-
code;
|
|
21
|
-
path;
|
|
22
|
-
input;
|
|
16
|
+
export class Issue {
|
|
23
17
|
constructor(code, path, input) {
|
|
24
18
|
this.code = code;
|
|
25
19
|
this.path = path;
|
|
@@ -44,16 +38,12 @@ class Issue {
|
|
|
44
38
|
};
|
|
45
39
|
}
|
|
46
40
|
}
|
|
47
|
-
exports.Issue = Issue;
|
|
48
41
|
/**
|
|
49
42
|
* A custom validation issue with a user-defined message.
|
|
50
43
|
*
|
|
51
44
|
* Use this for validation rules that don't fit into the standard issue categories.
|
|
52
45
|
*/
|
|
53
|
-
class IssueCustom extends Issue {
|
|
54
|
-
path;
|
|
55
|
-
input;
|
|
56
|
-
message;
|
|
46
|
+
export class IssueCustom extends Issue {
|
|
57
47
|
constructor(path, input, message) {
|
|
58
48
|
super('custom', path, input);
|
|
59
49
|
this.path = path;
|
|
@@ -61,15 +51,12 @@ class IssueCustom extends Issue {
|
|
|
61
51
|
this.message = message;
|
|
62
52
|
}
|
|
63
53
|
}
|
|
64
|
-
exports.IssueCustom = IssueCustom;
|
|
65
54
|
/**
|
|
66
55
|
* Issue for string values that don't match an expected format.
|
|
67
56
|
*
|
|
68
57
|
* Used for AT Protocol specific formats like DID, handle, NSID, AT-URI, etc.
|
|
69
58
|
*/
|
|
70
|
-
class IssueInvalidFormat extends Issue {
|
|
71
|
-
format;
|
|
72
|
-
detail;
|
|
59
|
+
export class IssueInvalidFormat extends Issue {
|
|
73
60
|
constructor(path, input, format, detail) {
|
|
74
61
|
super('invalid_format', path, input);
|
|
75
62
|
this.format = format;
|
|
@@ -104,15 +91,13 @@ class IssueInvalidFormat extends Issue {
|
|
|
104
91
|
};
|
|
105
92
|
}
|
|
106
93
|
}
|
|
107
|
-
exports.IssueInvalidFormat = IssueInvalidFormat;
|
|
108
94
|
/**
|
|
109
95
|
* Issue for values that have an unexpected type.
|
|
110
96
|
*
|
|
111
97
|
* This is one of the most common validation issues, occurring when the
|
|
112
98
|
* runtime type of a value doesn't match the expected schema type.
|
|
113
99
|
*/
|
|
114
|
-
class IssueInvalidType extends Issue {
|
|
115
|
-
expected;
|
|
100
|
+
export class IssueInvalidType extends Issue {
|
|
116
101
|
constructor(path, input, expected) {
|
|
117
102
|
super('invalid_type', path, input);
|
|
118
103
|
this.expected = expected;
|
|
@@ -127,15 +112,13 @@ class IssueInvalidType extends Issue {
|
|
|
127
112
|
};
|
|
128
113
|
}
|
|
129
114
|
}
|
|
130
|
-
exports.IssueInvalidType = IssueInvalidType;
|
|
131
115
|
/**
|
|
132
116
|
* Issue for values that don't match any of the expected literal values.
|
|
133
117
|
*
|
|
134
118
|
* Used when a value must be one of a specific set of allowed values
|
|
135
119
|
* (e.g., enum-like constraints).
|
|
136
120
|
*/
|
|
137
|
-
class IssueInvalidValue extends Issue {
|
|
138
|
-
values;
|
|
121
|
+
export class IssueInvalidValue extends Issue {
|
|
139
122
|
constructor(path, input, values) {
|
|
140
123
|
super('invalid_value', path, input);
|
|
141
124
|
this.values = values;
|
|
@@ -150,12 +133,10 @@ class IssueInvalidValue extends Issue {
|
|
|
150
133
|
};
|
|
151
134
|
}
|
|
152
135
|
}
|
|
153
|
-
exports.IssueInvalidValue = IssueInvalidValue;
|
|
154
136
|
/**
|
|
155
137
|
* Issue for missing required object properties.
|
|
156
138
|
*/
|
|
157
|
-
class IssueRequiredKey extends Issue {
|
|
158
|
-
key;
|
|
139
|
+
export class IssueRequiredKey extends Issue {
|
|
159
140
|
constructor(path, input, key) {
|
|
160
141
|
super('required_key', path, input);
|
|
161
142
|
this.key = key;
|
|
@@ -170,14 +151,10 @@ class IssueRequiredKey extends Issue {
|
|
|
170
151
|
};
|
|
171
152
|
}
|
|
172
153
|
}
|
|
173
|
-
exports.IssueRequiredKey = IssueRequiredKey;
|
|
174
154
|
/**
|
|
175
155
|
* Issue for values that exceed a maximum constraint.
|
|
176
156
|
*/
|
|
177
|
-
class IssueTooBig extends Issue {
|
|
178
|
-
maximum;
|
|
179
|
-
type;
|
|
180
|
-
actual;
|
|
157
|
+
export class IssueTooBig extends Issue {
|
|
181
158
|
constructor(path, input, maximum, type, actual) {
|
|
182
159
|
super('too_big', path, input);
|
|
183
160
|
this.maximum = maximum;
|
|
@@ -195,14 +172,10 @@ class IssueTooBig extends Issue {
|
|
|
195
172
|
};
|
|
196
173
|
}
|
|
197
174
|
}
|
|
198
|
-
exports.IssueTooBig = IssueTooBig;
|
|
199
175
|
/**
|
|
200
176
|
* Issue for values that are below a minimum constraint.
|
|
201
177
|
*/
|
|
202
|
-
class IssueTooSmall extends Issue {
|
|
203
|
-
minimum;
|
|
204
|
-
type;
|
|
205
|
-
actual;
|
|
178
|
+
export class IssueTooSmall extends Issue {
|
|
206
179
|
constructor(path, input, minimum, type, actual) {
|
|
207
180
|
super('too_small', path, input);
|
|
208
181
|
this.minimum = minimum;
|
|
@@ -220,7 +193,6 @@ class IssueTooSmall extends Issue {
|
|
|
220
193
|
};
|
|
221
194
|
}
|
|
222
195
|
}
|
|
223
|
-
exports.IssueTooSmall = IssueTooSmall;
|
|
224
196
|
// -----------------------------------------------------------------------------
|
|
225
197
|
// Helper functions for formatting error messages
|
|
226
198
|
// -----------------------------------------------------------------------------
|
|
@@ -271,12 +243,12 @@ function stringifyValue(value) {
|
|
|
271
243
|
if (Array.isArray(value)) {
|
|
272
244
|
return `[${stringifyArray(value, stringifyValue)}]`;
|
|
273
245
|
}
|
|
274
|
-
if (
|
|
246
|
+
if (isPlainObject(value)) {
|
|
275
247
|
return `{${stringifyArray(Object.entries(value), stringifyObjectEntry)}}`;
|
|
276
248
|
}
|
|
277
|
-
if (
|
|
249
|
+
if (ifCid(value))
|
|
278
250
|
return 'cid';
|
|
279
|
-
if (
|
|
251
|
+
if (isLegacyBlobRef(value))
|
|
280
252
|
return 'legacy-blob';
|
|
281
253
|
if (value instanceof Date)
|
|
282
254
|
return 'date';
|