@atproto/lex-schema 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/core/result.d.ts +1 -125
- package/dist/core/result.d.ts.map +1 -1
- package/dist/core/result.js +1 -128
- package/dist/core/result.js.map +1 -1
- package/dist/core/string-format.d.ts +1 -7
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +2 -23
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-error.d.ts +0 -18
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +0 -30
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validator.d.ts +8 -15
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +3 -14
- package/dist/core/validator.js.map +1 -1
- package/dist/schema/array.d.ts +1 -1
- package/dist/schema/blob.d.ts +1 -1
- package/dist/schema/boolean.d.ts +1 -1
- package/dist/schema/bytes.d.ts +1 -1
- package/dist/schema/cid.d.ts +1 -1
- package/dist/schema/custom.d.ts +1 -1
- package/dist/schema/dict.d.ts +1 -1
- package/dist/schema/enum.d.ts +1 -1
- package/dist/schema/integer.d.ts +1 -1
- package/dist/schema/intersection.d.ts +1 -1
- package/dist/schema/lex-map.d.ts +1 -1
- package/dist/schema/lex-value.d.ts +1 -1
- package/dist/schema/literal.d.ts +1 -1
- package/dist/schema/null.d.ts +1 -1
- package/dist/schema/nullable.d.ts +1 -1
- package/dist/schema/object.d.ts +1 -1
- package/dist/schema/optional.d.ts +1 -1
- package/dist/schema/params.d.ts +2 -2
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/regexp.d.ts +1 -1
- package/dist/schema/string.d.ts +1 -1
- package/dist/schema/token.d.ts +2 -1
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +6 -1
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-union.d.ts +1 -1
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +3 -3
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown.d.ts +1 -1
- package/package.json +3 -4
- package/src/core/result.ts +8 -155
- package/src/core/string-format.ts +2 -22
- package/src/core/validation-error.ts +1 -33
- package/src/core/validator.ts +10 -21
- package/src/schema/token.ts +9 -1
- package/src/schema/union.ts +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atproto/lex-schema
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#5006](https://github.com/bluesky-social/atproto/pull/5006) [`60721e6`](https://github.com/bluesky-social/atproto/commit/60721e69c8db193eb817c4238ac447505ac855bc) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add `$token` accessor for `token` lexicon values schemas
|
|
8
|
+
|
|
9
|
+
## 0.1.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#4955](https://github.com/bluesky-social/atproto/pull/4955) [`20c5cc1`](https://github.com/bluesky-social/atproto/commit/20c5cc187aab538435c669c6e19a2d2f658af5f8) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Fixes a bug that would reject valid `datetime` atproto strings in non-strict validation
|
|
14
|
+
|
|
15
|
+
- [#4955](https://github.com/bluesky-social/atproto/pull/4955) [`20c5cc1`](https://github.com/bluesky-social/atproto/commit/20c5cc187aab538435c669c6e19a2d2f658af5f8) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Use datetime validation utility from `@atproto/syntax`
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [[`20c5cc1`](https://github.com/bluesky-social/atproto/commit/20c5cc187aab538435c669c6e19a2d2f658af5f8)]:
|
|
18
|
+
- @atproto/syntax@0.6.1
|
|
19
|
+
|
|
3
20
|
## 0.1.0
|
|
4
21
|
|
|
5
22
|
### Minor Changes
|
package/dist/core/result.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type ResultSuccess<V = any> = {
|
|
2
2
|
success: true;
|
|
3
3
|
value: V;
|
|
4
|
+
reason?: undefined;
|
|
4
5
|
};
|
|
5
6
|
/**
|
|
6
7
|
* Represents a failed result containing an error reason.
|
|
@@ -11,129 +12,4 @@ export type ResultFailure<E = Error> = {
|
|
|
11
12
|
success: false;
|
|
12
13
|
reason: E;
|
|
13
14
|
};
|
|
14
|
-
/**
|
|
15
|
-
* A discriminated union type representing either a success or failure outcome.
|
|
16
|
-
*
|
|
17
|
-
* Check the `success` property to determine the outcome and access the
|
|
18
|
-
* appropriate property (`value` for success, `reason` for failure).
|
|
19
|
-
*
|
|
20
|
-
* @typeParam V - The type of the success value
|
|
21
|
-
* @typeParam E - The type of the error reason
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```typescript
|
|
25
|
-
* function parseJson(text: string): Result<unknown, SyntaxError> {
|
|
26
|
-
* try {
|
|
27
|
-
* return success(JSON.parse(text))
|
|
28
|
-
* } catch (e) {
|
|
29
|
-
* return failure(e as SyntaxError)
|
|
30
|
-
* }
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
export type Result<V = any, E = Error> = ResultSuccess<V> | ResultFailure<E>;
|
|
35
|
-
/**
|
|
36
|
-
* Creates a successful result wrapping the given value.
|
|
37
|
-
*
|
|
38
|
-
* @typeParam V - The type of the value
|
|
39
|
-
* @param value - The success value to wrap
|
|
40
|
-
* @returns {ResultSuccess} A success result containing the value
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```typescript
|
|
44
|
-
* const result = success(42)
|
|
45
|
-
* console.log(result.success) // true
|
|
46
|
-
* console.log(result.value) // 42
|
|
47
|
-
* ```
|
|
48
|
-
*/
|
|
49
|
-
export declare function success<V>(value: V): ResultSuccess<V>;
|
|
50
|
-
/**
|
|
51
|
-
* Creates a failed result wrapping the given error reason.
|
|
52
|
-
*
|
|
53
|
-
* @typeParam E - The type of the error reason
|
|
54
|
-
* @param reason - The error reason to wrap
|
|
55
|
-
* @returns {ResultFailure} A failure result containing the error
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```typescript
|
|
59
|
-
* const result = failure(new Error('Something went wrong'))
|
|
60
|
-
* console.log(result.success) // false
|
|
61
|
-
* console.log(result.reason.message) // "Something went wrong"
|
|
62
|
-
* ```
|
|
63
|
-
*/
|
|
64
|
-
export declare function failure<E>(reason: E): ResultFailure<E>;
|
|
65
|
-
/**
|
|
66
|
-
* Extracts the error reason from a failure result.
|
|
67
|
-
*
|
|
68
|
-
* @typeParam T - The type of the error reason
|
|
69
|
-
* @param result - A failure result
|
|
70
|
-
* @returns {T} The error reason
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```typescript
|
|
74
|
-
* const result = failure(new Error('oops'))
|
|
75
|
-
* const error = failureReason(result)
|
|
76
|
-
* console.log(error.message) // "oops"
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
export declare function failureReason<T>(result: ResultFailure<T>): T;
|
|
80
|
-
/**
|
|
81
|
-
* Extracts the value from a success result.
|
|
82
|
-
*
|
|
83
|
-
* @typeParam T - The type of the success value
|
|
84
|
-
* @param result - A success result
|
|
85
|
-
* @returns {T} The success value
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* ```typescript
|
|
89
|
-
* const result = success(42)
|
|
90
|
-
* const value = successValue(result)
|
|
91
|
-
* console.log(value) // 42
|
|
92
|
-
* ```
|
|
93
|
-
*/
|
|
94
|
-
export declare function successValue<T>(result: ResultSuccess<T>): T;
|
|
95
|
-
/**
|
|
96
|
-
* Catches any error and wraps it in a {@link ResultFailure<Error>}.
|
|
97
|
-
*
|
|
98
|
-
* @param err - The error to catch.
|
|
99
|
-
* @returns {ResultFailure} A failure result containing the error.
|
|
100
|
-
* @example
|
|
101
|
-
*
|
|
102
|
-
* ```ts
|
|
103
|
-
* declare function someFunction(): Promise<string>
|
|
104
|
-
*
|
|
105
|
-
* const result = await someFunction().then(success, catchall)
|
|
106
|
-
* if (result.success) {
|
|
107
|
-
* console.log(result.value) // string
|
|
108
|
-
* } else {
|
|
109
|
-
* console.error(result.reason instanceof Error) // true
|
|
110
|
-
* console.error(result.reason.message) // string
|
|
111
|
-
* }
|
|
112
|
-
* ```
|
|
113
|
-
*/
|
|
114
|
-
export declare function catchall(err: unknown): ResultFailure<Error>;
|
|
115
|
-
/**
|
|
116
|
-
* Creates a catcher function for the given constructor that wraps caught errors
|
|
117
|
-
* in a {@link ResultFailure}.
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
*
|
|
121
|
-
* ```ts
|
|
122
|
-
* class FooError extends Error {}
|
|
123
|
-
* class BarError extends Error {}
|
|
124
|
-
*
|
|
125
|
-
* declare function someFunction(): Promise<string>
|
|
126
|
-
*
|
|
127
|
-
* const result = await someFunction()
|
|
128
|
-
* .then(success)
|
|
129
|
-
* .catch(createCatcher(FooError))
|
|
130
|
-
* .catch(createCatcher(BarError))
|
|
131
|
-
*
|
|
132
|
-
* if (result.success) {
|
|
133
|
-
* console.log(result.value) // string
|
|
134
|
-
* } else {
|
|
135
|
-
* console.error(result.reason) // FooError | BarError
|
|
136
|
-
* }
|
|
137
|
-
*/
|
|
138
|
-
export declare function createCatcher<T>(Ctor: new (...args: any[]) => T): (err: unknown) => ResultFailure<T>;
|
|
139
15
|
//# sourceMappingURL=result.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/core/result.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/core/result.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,GAAG,IAAI;IACnC,OAAO,EAAE,IAAI,CAAA;IACb,KAAK,EAAE,CAAC,CAAA;IACR,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,KAAK,IAAI;IACrC,OAAO,EAAE,KAAK,CAAA;IACd,MAAM,EAAE,CAAC,CAAA;CACV,CAAA"}
|
package/dist/core/result.js
CHANGED
|
@@ -1,129 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* Creates a successful result wrapping the given value.
|
|
3
|
-
*
|
|
4
|
-
* @typeParam V - The type of the value
|
|
5
|
-
* @param value - The success value to wrap
|
|
6
|
-
* @returns {ResultSuccess} A success result containing the value
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```typescript
|
|
10
|
-
* const result = success(42)
|
|
11
|
-
* console.log(result.success) // true
|
|
12
|
-
* console.log(result.value) // 42
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
/*@__NO_SIDE_EFFECTS__*/
|
|
16
|
-
export function success(value) {
|
|
17
|
-
return { success: true, value };
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Creates a failed result wrapping the given error reason.
|
|
21
|
-
*
|
|
22
|
-
* @typeParam E - The type of the error reason
|
|
23
|
-
* @param reason - The error reason to wrap
|
|
24
|
-
* @returns {ResultFailure} A failure result containing the error
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```typescript
|
|
28
|
-
* const result = failure(new Error('Something went wrong'))
|
|
29
|
-
* console.log(result.success) // false
|
|
30
|
-
* console.log(result.reason.message) // "Something went wrong"
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
/*@__NO_SIDE_EFFECTS__*/
|
|
34
|
-
export function failure(reason) {
|
|
35
|
-
return { success: false, reason };
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Extracts the error reason from a failure result.
|
|
39
|
-
*
|
|
40
|
-
* @typeParam T - The type of the error reason
|
|
41
|
-
* @param result - A failure result
|
|
42
|
-
* @returns {T} The error reason
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* ```typescript
|
|
46
|
-
* const result = failure(new Error('oops'))
|
|
47
|
-
* const error = failureReason(result)
|
|
48
|
-
* console.log(error.message) // "oops"
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
/*@__NO_SIDE_EFFECTS__*/
|
|
52
|
-
export function failureReason(result) {
|
|
53
|
-
return result.reason;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Extracts the value from a success result.
|
|
57
|
-
*
|
|
58
|
-
* @typeParam T - The type of the success value
|
|
59
|
-
* @param result - A success result
|
|
60
|
-
* @returns {T} The success value
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```typescript
|
|
64
|
-
* const result = success(42)
|
|
65
|
-
* const value = successValue(result)
|
|
66
|
-
* console.log(value) // 42
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
/*@__NO_SIDE_EFFECTS__*/
|
|
70
|
-
export function successValue(result) {
|
|
71
|
-
return result.value;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Catches any error and wraps it in a {@link ResultFailure<Error>}.
|
|
75
|
-
*
|
|
76
|
-
* @param err - The error to catch.
|
|
77
|
-
* @returns {ResultFailure} A failure result containing the error.
|
|
78
|
-
* @example
|
|
79
|
-
*
|
|
80
|
-
* ```ts
|
|
81
|
-
* declare function someFunction(): Promise<string>
|
|
82
|
-
*
|
|
83
|
-
* const result = await someFunction().then(success, catchall)
|
|
84
|
-
* if (result.success) {
|
|
85
|
-
* console.log(result.value) // string
|
|
86
|
-
* } else {
|
|
87
|
-
* console.error(result.reason instanceof Error) // true
|
|
88
|
-
* console.error(result.reason.message) // string
|
|
89
|
-
* }
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
/*@__NO_SIDE_EFFECTS__*/
|
|
93
|
-
export function catchall(err) {
|
|
94
|
-
if (err instanceof Error)
|
|
95
|
-
return failure(err);
|
|
96
|
-
return failure(new Error('Unknown error', { cause: err }));
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Creates a catcher function for the given constructor that wraps caught errors
|
|
100
|
-
* in a {@link ResultFailure}.
|
|
101
|
-
*
|
|
102
|
-
* @example
|
|
103
|
-
*
|
|
104
|
-
* ```ts
|
|
105
|
-
* class FooError extends Error {}
|
|
106
|
-
* class BarError extends Error {}
|
|
107
|
-
*
|
|
108
|
-
* declare function someFunction(): Promise<string>
|
|
109
|
-
*
|
|
110
|
-
* const result = await someFunction()
|
|
111
|
-
* .then(success)
|
|
112
|
-
* .catch(createCatcher(FooError))
|
|
113
|
-
* .catch(createCatcher(BarError))
|
|
114
|
-
*
|
|
115
|
-
* if (result.success) {
|
|
116
|
-
* console.log(result.value) // string
|
|
117
|
-
* } else {
|
|
118
|
-
* console.error(result.reason) // FooError | BarError
|
|
119
|
-
* }
|
|
120
|
-
*/
|
|
121
|
-
/*@__NO_SIDE_EFFECTS__*/
|
|
122
|
-
export function createCatcher(Ctor) {
|
|
123
|
-
return (err) => {
|
|
124
|
-
if (err instanceof Ctor)
|
|
125
|
-
return failure(err);
|
|
126
|
-
throw err;
|
|
127
|
-
};
|
|
128
|
-
}
|
|
1
|
+
export {};
|
|
129
2
|
//# sourceMappingURL=result.js.map
|
package/dist/core/result.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/core/result.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/core/result.ts"],"names":[],"mappings":"","sourcesContent":["export type ResultSuccess<V = any> = {\n success: true\n value: V\n reason?: undefined\n}\n\n/**\n * Represents a failed result containing an error reason.\n *\n * @typeParam E - The type of the error reason\n */\nexport type ResultFailure<E = Error> = {\n success: false\n reason: E\n}\n"]}
|
|
@@ -2,13 +2,7 @@ import { AtIdentifierString, AtUriString, DatetimeString, DidString, HandleStrin
|
|
|
2
2
|
import { CheckFn } from '../util/assertion-util.js';
|
|
3
3
|
export { type AtIdentifierString, asAtIdentifierString, assertAtIdentifierString, ifAtIdentifierString, isAtIdentifierString, } from '@atproto/syntax';
|
|
4
4
|
export { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax';
|
|
5
|
-
export { type DatetimeString, asDatetimeString, assertDatetimeString, ifDatetimeString, isDatetimeString, } from '@atproto/syntax';
|
|
6
|
-
/**
|
|
7
|
-
* Matches any ISO-ish datetime string. This is a more lenient check than
|
|
8
|
-
* the strict {@link isDatetimeString} guard, which only allows datetimes that
|
|
9
|
-
* fully conform to the AT Protocol specification (e.g. must include timezone).
|
|
10
|
-
*/
|
|
11
|
-
export declare function isDatetimeStringLenient<I>(input: I): input is I & DatetimeString;
|
|
5
|
+
export { type DatetimeString, asDatetimeString, assertDatetimeString, ifDatetimeString, isDatetimeString, isDatetimeStringLenient, } from '@atproto/syntax';
|
|
12
6
|
export { currentDatetimeString, toDatetimeString } from '@atproto/syntax';
|
|
13
7
|
export { type AtUriString, asAtUriString, assertAtUriString, ifAtUriString, isAtUriString, } from '@atproto/syntax';
|
|
14
8
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string-format.d.ts","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"string-format.d.ts","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import isoDatestringValidator from 'iso-datestring-validator';
|
|
2
|
-
const { isValidISODateString } = isoDatestringValidator;
|
|
3
1
|
import { validateCidString } from '@atproto/lex-data';
|
|
4
|
-
import { isAtIdentifierString, isAtUriString, isDatetimeString, isValidDid, isValidHandle, isValidLanguage, isValidNsid, isValidRecordKey, isValidTid, isValidUri, } from '@atproto/syntax';
|
|
2
|
+
import { isAtIdentifierString, isAtUriString, isDatetimeString, isDatetimeStringLenient, isValidDid, isValidHandle, isValidLanguage, isValidNsid, isValidRecordKey, isValidTid, isValidUri, } from '@atproto/syntax';
|
|
5
3
|
// -----------------------------------------------------------------------------
|
|
6
4
|
// Individual string format types and type guards
|
|
7
5
|
// -----------------------------------------------------------------------------
|
|
@@ -12,26 +10,7 @@ import { isAtIdentifierString, isAtUriString, isDatetimeString, isValidDid, isVa
|
|
|
12
10
|
export { asAtIdentifierString, assertAtIdentifierString, ifAtIdentifierString, isAtIdentifierString, } from '@atproto/syntax';
|
|
13
11
|
// AtIdentifierString utilities
|
|
14
12
|
export { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax';
|
|
15
|
-
export { asDatetimeString, assertDatetimeString, ifDatetimeString, isDatetimeString, } from '@atproto/syntax';
|
|
16
|
-
/**
|
|
17
|
-
* Matches any ISO-ish datetime string. This is a more lenient check than
|
|
18
|
-
* the strict {@link isDatetimeString} guard, which only allows datetimes that
|
|
19
|
-
* fully conform to the AT Protocol specification (e.g. must include timezone).
|
|
20
|
-
*/
|
|
21
|
-
export function isDatetimeStringLenient(input) {
|
|
22
|
-
// @NOTE the returned type assertion is inaccurate wrt. the DatetimeString
|
|
23
|
-
// type definition. A more accurate solution would be to use a branded type
|
|
24
|
-
// instead of a template literal for the "datetime" format
|
|
25
|
-
if (typeof input !== 'string')
|
|
26
|
-
return false;
|
|
27
|
-
try {
|
|
28
|
-
return isValidISODateString(input);
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
// @NOTE isValidISODateString throws on some inputs
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
13
|
+
export { asDatetimeString, assertDatetimeString, ifDatetimeString, isDatetimeString, isDatetimeStringLenient, } from '@atproto/syntax';
|
|
35
14
|
// DatetimeString utilities
|
|
36
15
|
export { currentDatetimeString, toDatetimeString } from '@atproto/syntax';
|
|
37
16
|
export { asAtUriString, assertAtUriString, ifAtUriString, isAtUriString, } from '@atproto/syntax';
|
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
1
|
+
{"version":3,"file":"string-format.js","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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","sourcesContent":["import { 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 isDatetimeStringLenient,\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 isDatetimeStringLenient,\n} from '@atproto/syntax'\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"]}
|
|
@@ -65,23 +65,5 @@ export declare class LexValidationError extends LexError<'InvalidRequest'> imple
|
|
|
65
65
|
error: import("@atproto/lex-data").LexErrorCode;
|
|
66
66
|
message?: string;
|
|
67
67
|
};
|
|
68
|
-
/**
|
|
69
|
-
* Creates a validation error by combining multiple validation failures.
|
|
70
|
-
*
|
|
71
|
-
* This is useful when validating against multiple possible schemas (e.g., unions)
|
|
72
|
-
* and all branches fail. The resulting error contains issues from all failures.
|
|
73
|
-
*
|
|
74
|
-
* @param failures - The validation failures to combine
|
|
75
|
-
* @returns A single validation error containing all issues from the failures
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* ```typescript
|
|
79
|
-
* const failures = schemas.map(s => s.safeValidate(data)).filter(r => !r.success)
|
|
80
|
-
* if (failures.length === schemas.length) {
|
|
81
|
-
* throw LexValidationError.fromFailures(failures)
|
|
82
|
-
* }
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
85
|
-
static fromFailures(failures: readonly ResultFailure<LexValidationError>[]): LexValidationError;
|
|
86
68
|
}
|
|
87
69
|
//# sourceMappingURL=validation-error.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-error.d.ts","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"validation-error.d.ts","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EACL,KAAK,EAGN,MAAM,uBAAuB,CAAA;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,kBACX,SAAQ,QAAQ,CAAC,gBAAgB,CACjC,YAAW,aAAa,CAAC,kBAAkB,CAAC;IAE5C,IAAI,SAAuB;IAE3B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;IAEjC;;;;;;;;OAQG;gBACS,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY;IAMnD,mCAAmC;IACnC,QAAQ,CAAC,OAAO,EAAG,KAAK,CAAS;IAEjC,kCAAkC;IAClC,IAAI,MAAM,SAET;IAED;;;;OAIG;IACM,MAAM;;;;;;;;;CAMhB"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { LexError } from '@atproto/lex-data';
|
|
2
2
|
import { arrayAgg } from '../util/array-agg.js';
|
|
3
|
-
import { failureReason } from './result.js';
|
|
4
3
|
import { IssueInvalidType, IssueInvalidValue, } from './validation-issue.js';
|
|
5
4
|
/**
|
|
6
5
|
* Error thrown when validation fails.
|
|
@@ -62,35 +61,6 @@ export class LexValidationError extends LexError {
|
|
|
62
61
|
issues: this.issues.map((issue) => issue.toJSON()),
|
|
63
62
|
};
|
|
64
63
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Creates a validation error by combining multiple validation failures.
|
|
67
|
-
*
|
|
68
|
-
* This is useful when validating against multiple possible schemas (e.g., unions)
|
|
69
|
-
* and all branches fail. The resulting error contains issues from all failures.
|
|
70
|
-
*
|
|
71
|
-
* @param failures - The validation failures to combine
|
|
72
|
-
* @returns A single validation error containing all issues from the failures
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```typescript
|
|
76
|
-
* const failures = schemas.map(s => s.safeValidate(data)).filter(r => !r.success)
|
|
77
|
-
* if (failures.length === schemas.length) {
|
|
78
|
-
* throw LexValidationError.fromFailures(failures)
|
|
79
|
-
* }
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
static fromFailures(failures) {
|
|
83
|
-
if (failures.length === 1)
|
|
84
|
-
return failureReason(failures[0]);
|
|
85
|
-
const issues = failures.flatMap(extractFailureIssues);
|
|
86
|
-
return new LexValidationError(issues, {
|
|
87
|
-
// Keep the original errors as the cause chain
|
|
88
|
-
cause: failures.map(failureReason),
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function extractFailureIssues(result) {
|
|
93
|
-
return result.reason.issues;
|
|
94
64
|
}
|
|
95
65
|
function aggregateIssues(issues) {
|
|
96
66
|
// Quick path for common cases
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-error.js","sourceRoot":"","sources":["../../src/core/validation-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;
|
|
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 } 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\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"]}
|
package/dist/core/validator.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type * as Result from './result.js';
|
|
2
2
|
import { LexValidationError } from './validation-error.js';
|
|
3
3
|
import { Issue, MeasurableType } from './validation-issue.js';
|
|
4
4
|
/**
|
|
5
5
|
* Represents a successful validation result.
|
|
6
6
|
*
|
|
7
|
-
* @typeParam
|
|
7
|
+
* @typeParam TValue - The type of the validated value
|
|
8
|
+
* @extends Result.ResultSuccess<TValue>
|
|
8
9
|
*/
|
|
9
|
-
export type ValidationSuccess<
|
|
10
|
+
export type ValidationSuccess<TValue = unknown> = Result.ResultSuccess<TValue>;
|
|
10
11
|
/**
|
|
11
12
|
* Represents a failed validation result containing a {@link LexValidationError}.
|
|
12
13
|
*
|
|
13
|
-
* @extends ResultFailure<LexValidationError>
|
|
14
|
-
* @see {@link ResultFailure}
|
|
15
14
|
* @see {@link LexValidationError}
|
|
15
|
+
* @extends Result.ResultFailure<LexValidationError>
|
|
16
16
|
*/
|
|
17
17
|
export type ValidationFailure = LexValidationError;
|
|
18
18
|
/**
|
|
@@ -307,20 +307,13 @@ export declare class ValidationContext {
|
|
|
307
307
|
*/
|
|
308
308
|
addIssue(issue: Issue): void;
|
|
309
309
|
/**
|
|
310
|
-
*
|
|
310
|
+
* Helper method to create a successful validation result.
|
|
311
311
|
*
|
|
312
312
|
* @typeParam V - The value type
|
|
313
313
|
* @param value - The validated value
|
|
314
314
|
* @returns A successful validation result
|
|
315
315
|
*/
|
|
316
|
-
success<V>(value: V):
|
|
317
|
-
/**
|
|
318
|
-
* Creates a failed validation result with the given error.
|
|
319
|
-
*
|
|
320
|
-
* @param reason - The validation error
|
|
321
|
-
* @returns A failed validation result
|
|
322
|
-
*/
|
|
323
|
-
failure(reason: LexValidationError): ValidationFailure;
|
|
316
|
+
success<V>(value: V): ValidationSuccess<V>;
|
|
324
317
|
/**
|
|
325
318
|
* Creates a failed validation result from a single issue.
|
|
326
319
|
*
|
|
@@ -329,7 +322,7 @@ export declare class ValidationContext {
|
|
|
329
322
|
* @param issue - The validation issue that caused the failure
|
|
330
323
|
* @returns A failed validation result
|
|
331
324
|
*/
|
|
332
|
-
issue(issue: Issue):
|
|
325
|
+
issue(issue: Issue): ValidationFailure;
|
|
333
326
|
/**
|
|
334
327
|
* Creates a failure for an invalid value that doesn't match expected values.
|
|
335
328
|
*
|