@atproto/lex-schema 0.0.18 → 0.0.20
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 +15 -0
- package/dist/core/string-format.d.ts +10 -16
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +21 -11
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-issue.js +1 -1
- package/dist/core/validation-issue.js.map +1 -1
- package/package.json +2 -2
- package/src/core/string-format.ts +24 -20
- package/src/core/validation-issue.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @atproto/lex-schema
|
|
2
2
|
|
|
3
|
+
## 0.0.20
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#4925](https://github.com/bluesky-social/atproto/pull/4925) [`2fd8d62`](https://github.com/bluesky-social/atproto/commit/2fd8d62708dc23de6ed21cbcccfebab68b19f588) Thanks [@rafaeleyng](https://github.com/rafaeleyng)! - Increase string preview validation error
|
|
8
|
+
|
|
9
|
+
## 0.0.19
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#4806](https://github.com/bluesky-social/atproto/pull/4806) [`26d793a`](https://github.com/bluesky-social/atproto/commit/26d793af95a6fb3a50f9b2a97187d8ac4fecf676) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Export `AtUriString` utilities from `@atproto/syntax`
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [[`26d793a`](https://github.com/bluesky-social/atproto/commit/26d793af95a6fb3a50f9b2a97187d8ac4fecf676), [`26d793a`](https://github.com/bluesky-social/atproto/commit/26d793af95a6fb3a50f9b2a97187d8ac4fecf676), [`26d793a`](https://github.com/bluesky-social/atproto/commit/26d793af95a6fb3a50f9b2a97187d8ac4fecf676), [`55d06de`](https://github.com/bluesky-social/atproto/commit/55d06de80a1506908a04ed5c0834986cb5783797), [`26d793a`](https://github.com/bluesky-social/atproto/commit/26d793af95a6fb3a50f9b2a97187d8ac4fecf676)]:
|
|
16
|
+
- @atproto/syntax@0.5.4
|
|
17
|
+
|
|
3
18
|
## 0.0.18
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
import { AtIdentifierString, AtUriString, DatetimeString, DidString, HandleString, NsidString, RecordKeyString, TidString, UriString } from '@atproto/syntax';
|
|
2
2
|
import { CheckFn } from '../util/assertion-util.js';
|
|
3
|
-
export { type AtIdentifierString, asAtIdentifierString, ifAtIdentifierString, isAtIdentifierString, } from '@atproto/syntax';
|
|
3
|
+
export { type AtIdentifierString, asAtIdentifierString, assertAtIdentifierString, ifAtIdentifierString, isAtIdentifierString, } from '@atproto/syntax';
|
|
4
4
|
export { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax';
|
|
5
|
-
export { type DatetimeString, asDatetimeString, ifDatetimeString, isDatetimeString, } from '@atproto/syntax';
|
|
5
|
+
export { type DatetimeString, asDatetimeString, assertDatetimeString, ifDatetimeString, isDatetimeString, } from '@atproto/syntax';
|
|
6
6
|
/**
|
|
7
7
|
* Matches any ISO-ish datetime string. This is a more lenient check than
|
|
8
8
|
* the strict {@link isDatetimeString} guard, which only allows datetimes that
|
|
9
9
|
* fully conform to the AT Protocol specification (e.g. must include timezone).
|
|
10
10
|
*/
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function isDatetimeStringLenient<I>(input: I): input is I & DatetimeString;
|
|
12
12
|
export { currentDatetimeString, toDatetimeString } from '@atproto/syntax';
|
|
13
|
+
export { type AtUriString, asAtUriString, assertAtUriString, ifAtUriString, isAtUriString, } from '@atproto/syntax';
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
+
* Lenient version of {@link isAtUriString} that does not enforce the validity
|
|
16
|
+
* of the record key (rkey) path component (if present).
|
|
15
17
|
*
|
|
16
|
-
* @
|
|
17
|
-
* @returns `true` if the value is a valid AT URI
|
|
18
|
-
*/
|
|
19
|
-
export declare const isAtUriString: CheckFn<AtUriString>;
|
|
20
|
-
export type {
|
|
21
|
-
/**
|
|
22
|
-
* An AT URI string pointing to a resource in the AT Protocol network.
|
|
23
|
-
*
|
|
24
|
-
* @example `"at://did:plc:1234.../app.bsky.feed.post/3k2..."`
|
|
18
|
+
* @see {@link isAtUriString}
|
|
25
19
|
*/
|
|
26
|
-
AtUriString
|
|
20
|
+
export declare function isAtUriStringLenient<I>(input: I): input is I & AtUriString;
|
|
27
21
|
/**
|
|
28
22
|
* Type guard that checks if a value is a valid CID string.
|
|
29
23
|
*
|
|
@@ -161,8 +155,8 @@ type StringFormats = {
|
|
|
161
155
|
export type StringFormat = Extract<keyof StringFormats, string>;
|
|
162
156
|
export type StringFormatValidationOptions = {
|
|
163
157
|
/**
|
|
164
|
-
* Allows to be more lenient in validation by using a "
|
|
165
|
-
* function, if available. The behavior of the
|
|
158
|
+
* Allows to be more lenient in validation by using a "lenient" verification
|
|
159
|
+
* function, if available. The behavior of the lenient verifier depends on the
|
|
166
160
|
* specific format, but generally it may allow for a wider range of valid
|
|
167
161
|
* inputs, including values that are not compliant with the AT Protocol
|
|
168
162
|
* specification.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string-format.d.ts","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,SAAS,EACT,YAAY,EACZ,UAAU,EACV,eAAe,EACf,SAAS,EACT,SAAS,EAWV,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAWnD,OAAO,EACL,KAAK,kBAAkB,EACvB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAErE,OAAO,EACL,KAAK,cAAc,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AAExB;;;;GAIG;AACH,wBAAgB,
|
|
1
|
+
{"version":3,"file":"string-format.d.ts","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.STRING_FORMATS = exports.isUriString = exports.isTidString = exports.isRecordKeyString = exports.isNsidString = exports.isLanguageString = exports.isHandleString = exports.isDidString = exports.isCidString = exports.isAtUriString = exports.toDatetimeString = exports.currentDatetimeString = exports.isDatetimeString = exports.ifDatetimeString = exports.asDatetimeString = exports.isHandleIdentifier = exports.isDidIdentifier = exports.isAtIdentifierString = exports.ifAtIdentifierString = exports.asAtIdentifierString = void 0;
|
|
4
|
-
exports.
|
|
3
|
+
exports.STRING_FORMATS = exports.isUriString = exports.isTidString = exports.isRecordKeyString = exports.isNsidString = exports.isLanguageString = exports.isHandleString = exports.isDidString = exports.isCidString = exports.isAtUriString = exports.ifAtUriString = exports.assertAtUriString = exports.asAtUriString = exports.toDatetimeString = exports.currentDatetimeString = exports.isDatetimeString = exports.ifDatetimeString = exports.assertDatetimeString = exports.asDatetimeString = exports.isHandleIdentifier = exports.isDidIdentifier = exports.isAtIdentifierString = exports.ifAtIdentifierString = exports.assertAtIdentifierString = exports.asAtIdentifierString = void 0;
|
|
4
|
+
exports.isDatetimeStringLenient = isDatetimeStringLenient;
|
|
5
|
+
exports.isAtUriStringLenient = isAtUriStringLenient;
|
|
5
6
|
exports.isStringFormat = isStringFormat;
|
|
6
7
|
exports.assertStringFormat = assertStringFormat;
|
|
7
8
|
exports.asStringFormat = asStringFormat;
|
|
@@ -18,6 +19,7 @@ const syntax_1 = require("@atproto/syntax");
|
|
|
18
19
|
// and re-export here, e.g. language tags, NSIDs, record keys, etc.
|
|
19
20
|
var syntax_2 = require("@atproto/syntax");
|
|
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; } });
|
|
21
23
|
Object.defineProperty(exports, "ifAtIdentifierString", { enumerable: true, get: function () { return syntax_2.ifAtIdentifierString; } });
|
|
22
24
|
Object.defineProperty(exports, "isAtIdentifierString", { enumerable: true, get: function () { return syntax_2.isAtIdentifierString; } });
|
|
23
25
|
// AtIdentifierString utilities
|
|
@@ -26,6 +28,7 @@ Object.defineProperty(exports, "isDidIdentifier", { enumerable: true, get: funct
|
|
|
26
28
|
Object.defineProperty(exports, "isHandleIdentifier", { enumerable: true, get: function () { return syntax_3.isHandleIdentifier; } });
|
|
27
29
|
var syntax_4 = require("@atproto/syntax");
|
|
28
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; } });
|
|
29
32
|
Object.defineProperty(exports, "ifDatetimeString", { enumerable: true, get: function () { return syntax_4.ifDatetimeString; } });
|
|
30
33
|
Object.defineProperty(exports, "isDatetimeString", { enumerable: true, get: function () { return syntax_4.isDatetimeString; } });
|
|
31
34
|
/**
|
|
@@ -33,7 +36,7 @@ Object.defineProperty(exports, "isDatetimeString", { enumerable: true, get: func
|
|
|
33
36
|
* the strict {@link isDatetimeString} guard, which only allows datetimes that
|
|
34
37
|
* fully conform to the AT Protocol specification (e.g. must include timezone).
|
|
35
38
|
*/
|
|
36
|
-
function
|
|
39
|
+
function isDatetimeStringLenient(input) {
|
|
37
40
|
// @NOTE the returned type assertion is inaccurate wrt. the DatetimeString
|
|
38
41
|
// type definition. A more accurate solution would be to use a branded type
|
|
39
42
|
// instead of a template literal for the "datetime" format
|
|
@@ -51,13 +54,20 @@ function isDatetimeStringLoose(input) {
|
|
|
51
54
|
var syntax_5 = require("@atproto/syntax");
|
|
52
55
|
Object.defineProperty(exports, "currentDatetimeString", { enumerable: true, get: function () { return syntax_5.currentDatetimeString; } });
|
|
53
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; } });
|
|
54
62
|
/**
|
|
55
|
-
*
|
|
63
|
+
* Lenient version of {@link isAtUriString} that does not enforce the validity
|
|
64
|
+
* of the record key (rkey) path component (if present).
|
|
56
65
|
*
|
|
57
|
-
* @
|
|
58
|
-
* @returns `true` if the value is a valid AT URI
|
|
66
|
+
* @see {@link isAtUriString}
|
|
59
67
|
*/
|
|
60
|
-
|
|
68
|
+
function isAtUriStringLenient(input) {
|
|
69
|
+
return (0, syntax_1.isAtUriString)(input, { strict: false });
|
|
70
|
+
}
|
|
61
71
|
/**
|
|
62
72
|
* Type guard that checks if a value is a valid CID string.
|
|
63
73
|
*
|
|
@@ -117,9 +127,9 @@ exports.isUriString = syntax_1.isValidUri;
|
|
|
117
127
|
const stringFormatVerifiers = /*#__PURE__*/ Object.freeze({
|
|
118
128
|
__proto__: null,
|
|
119
129
|
'at-identifier': [syntax_1.isAtIdentifierString],
|
|
120
|
-
'at-uri': [
|
|
130
|
+
'at-uri': [syntax_1.isAtUriString, isAtUriStringLenient],
|
|
121
131
|
cid: [exports.isCidString],
|
|
122
|
-
datetime: [syntax_1.isDatetimeString,
|
|
132
|
+
datetime: [syntax_1.isDatetimeString, isDatetimeStringLenient],
|
|
123
133
|
did: [exports.isDidString],
|
|
124
134
|
handle: [exports.isHandleString],
|
|
125
135
|
language: [exports.isLanguageString],
|
|
@@ -152,8 +162,8 @@ function isStringFormat(input, format, options) {
|
|
|
152
162
|
// Fool-proof
|
|
153
163
|
if (!formatVerifier)
|
|
154
164
|
throw new TypeError(`Unknown string format: ${format}`);
|
|
155
|
-
const check = options?.strict === false
|
|
156
|
-
? formatVerifier[1]
|
|
165
|
+
const check = options?.strict === false && formatVerifier.length > 1
|
|
166
|
+
? formatVerifier[1]
|
|
157
167
|
: formatVerifier[0];
|
|
158
168
|
return check(input);
|
|
159
169
|
}
|
|
@@ -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 isDatetimeString,\n isValidAtUri,\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 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 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 isDatetimeStringLoose<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\n/**\n * Type guard that checks if a value is a valid AT URI.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid AT URI\n */\nexport const isAtUriString: CheckFn<AtUriString> = isValidAtUri\nexport type {\n /**\n * An AT URI string pointing to a resource in the AT Protocol network.\n *\n * @example `\"at://did:plc:1234.../app.bsky.feed.post/3k2...\"`\n */\n AtUriString,\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 loose?: CheckFn<StringFormats[K]>,\n ]\n} = /*#__PURE__*/ Object.freeze({\n __proto__: null,\n\n 'at-identifier': [isAtIdentifierString],\n 'at-uri': [isAtUriString],\n cid: [isCidString],\n datetime: [isDatetimeString, isDatetimeStringLoose],\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 \"loose\" verification\n * function, if available. The behavior of the loose 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\n ? formatVerifier[1] ?? formatVerifier[0]\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 { 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"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.IssueTooSmall = exports.IssueTooBig = exports.IssueRequiredKey = exports.IssueInvalidValue = exports.IssueInvalidType = exports.IssueInvalidFormat = exports.IssueCustom = exports.Issue = void 0;
|
|
4
4
|
const lex_data_1 = require("@atproto/lex-data");
|
|
5
|
-
const STRING_PREVIEW_MAX_LENGTH =
|
|
5
|
+
const STRING_PREVIEW_MAX_LENGTH = 256;
|
|
6
6
|
const STRING_PREVIEW_TRUNCATED_SUFFIX = '…';
|
|
7
7
|
/**
|
|
8
8
|
* Abstract base class for all validation issues.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-issue.js","sourceRoot":"","sources":["../../src/core/validation-issue.ts"],"names":[],"mappings":"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","sourcesContent":["import { ifCid, isLegacyBlobRef, isPlainObject } from '@atproto/lex-data'\n\nconst STRING_PREVIEW_MAX_LENGTH = 48\nconst STRING_PREVIEW_TRUNCATED_SUFFIX = '…'\n\n/**\n * Abstract base class for all validation issues.\n *\n * An issue represents a single validation failure, containing:\n * - A code identifying the type of issue\n * - The path to the invalid value in the data structure\n * - The actual input value that failed validation\n *\n * Subclasses add specific properties relevant to each issue type and implement\n * the {@link message} property for human-readable error messages (that don't\n * contain the error path)\n */\nexport abstract class Issue {\n abstract readonly message: string\n\n constructor(\n readonly code: string,\n readonly path: readonly PropertyKey[],\n readonly input: unknown,\n ) {}\n\n /**\n * Returns a human-readable description of the validation issue.\n */\n toString() {\n return `${this.message}${stringifyPath(this.path)}`\n }\n\n /**\n * Converts the issue to a JSON-serializable object.\n *\n * @returns An object containing the issue code, path, and message\n */\n toJSON() {\n return {\n code: this.code,\n path: this.path,\n message: this.message,\n }\n }\n}\n\n/**\n * A custom validation issue with a user-defined message.\n *\n * Use this for validation rules that don't fit into the standard issue categories.\n */\nexport class IssueCustom extends Issue {\n constructor(\n readonly path: readonly PropertyKey[],\n readonly input: unknown,\n readonly message: string,\n ) {\n super('custom', path, input)\n }\n}\n\n/**\n * Issue for string values that don't match an expected format.\n *\n * Used for AT Protocol specific formats like DID, handle, NSID, AT-URI, etc.\n */\nexport class IssueInvalidFormat extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly format: string,\n readonly detail?: string,\n ) {\n super('invalid_format', path, input)\n }\n\n override get message(): string {\n return `Invalid ${this.formatDescription}${this.detail ? ` (${this.detail}, ` : ' ('}got ${stringifyValue(this.input)})`\n }\n\n /** Returns a human-readable description of the expected format. */\n get formatDescription(): string {\n switch (this.format) {\n case 'at-identifier':\n return `AT identifier`\n case 'did':\n return `DID`\n case 'nsid':\n return `NSID`\n case 'cid':\n return `CID string`\n case 'tid':\n return `TID string`\n case 'record-key':\n return `record key`\n default:\n return this.format\n }\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n format: this.format,\n }\n }\n}\n\n/**\n * Issue for values that have an unexpected type.\n *\n * This is one of the most common validation issues, occurring when the\n * runtime type of a value doesn't match the expected schema type.\n */\nexport class IssueInvalidType extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly expected: readonly string[],\n ) {\n super('invalid_type', path, input)\n }\n\n override get message(): string {\n return `Expected ${oneOf(this.expected.map(stringifyExpectedType))} value type (got ${stringifyValue(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n expected: this.expected,\n }\n }\n}\n\n/**\n * Issue for values that don't match any of the expected literal values.\n *\n * Used when a value must be one of a specific set of allowed values\n * (e.g., enum-like constraints).\n */\nexport class IssueInvalidValue extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly values: readonly unknown[],\n ) {\n super('invalid_value', path, input)\n }\n\n override get message(): string {\n return `Expected ${oneOf(this.values.map(stringifyValue))} (got ${stringifyValue(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n values: this.values,\n }\n }\n}\n\n/**\n * Issue for missing required object properties.\n */\nexport class IssueRequiredKey extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly key: PropertyKey,\n ) {\n super('required_key', path, input)\n }\n\n override get message(): string {\n return `Missing required key \"${String(this.key)}\"`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n key: this.key,\n }\n }\n}\n\n/**\n * The type of measurement for size constraint issues.\n *\n * - `'array'` - Array length\n * - `'string'` - String length in characters\n * - `'integer'` - Numeric value\n * - `'grapheme'` - String length in grapheme clusters\n * - `'bytes'` - Byte length\n * - `'blob'` - Blob size\n */\nexport type MeasurableType =\n | 'array'\n | 'string'\n | 'integer'\n | 'grapheme'\n | 'bytes'\n | 'blob'\n\n/**\n * Issue for values that exceed a maximum constraint.\n */\nexport class IssueTooBig extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly maximum: number,\n readonly type: MeasurableType,\n readonly actual: number,\n ) {\n super('too_big', path, input)\n }\n\n override get message(): string {\n return `${this.type} too big (maximum ${this.maximum}, got ${this.actual})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n type: this.type,\n maximum: this.maximum,\n }\n }\n}\n\n/**\n * Issue for values that are below a minimum constraint.\n */\nexport class IssueTooSmall extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly minimum: number,\n readonly type: MeasurableType,\n readonly actual: number,\n ) {\n super('too_small', path, input)\n }\n\n override get message(): string {\n return `${this.type} too small (minimum ${this.minimum}, got ${this.actual})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n type: this.type,\n minimum: this.minimum,\n }\n }\n}\n\n// -----------------------------------------------------------------------------\n// Helper functions for formatting error messages\n// -----------------------------------------------------------------------------\n\nfunction stringifyExpectedType(expected: string): string {\n if (expected === '$typed') {\n return 'an object which includes the \"$type\" property'\n }\n return expected\n}\n\nfunction stringifyPath(path: readonly PropertyKey[]) {\n return ` at ${buildJsonPath(path)}`\n}\n\nfunction buildJsonPath(path: readonly PropertyKey[]): string {\n return `$${path.map(toJsonPathSegment).join('')}`\n}\n\nfunction toJsonPathSegment(segment: PropertyKey): string {\n if (typeof segment === 'number' || typeof segment === 'symbol') {\n return `[${String(segment)}]`\n } else if (/^[a-zA-Z_$][a-zA-Z0-9_]*$/.test(segment)) {\n return `.${segment}`\n } else {\n return `[${JSON.stringify(segment)}]`\n }\n}\n\nfunction oneOf(arr: readonly string[]): string {\n if (arr.length === 0) return ''\n if (arr.length === 1) return arr[0]\n return `one of ${arr.slice(0, -1).join(', ')} or ${arr.at(-1)}`\n}\n\nfunction stringifyValue(value: unknown): string {\n switch (typeof value) {\n case 'bigint':\n return `${value}n`\n case 'number':\n case 'boolean':\n return String(value)\n case 'string':\n return JSON.stringify(\n value.length < STRING_PREVIEW_MAX_LENGTH\n ? value\n : `${value.slice(0, STRING_PREVIEW_MAX_LENGTH - STRING_PREVIEW_TRUNCATED_SUFFIX.length)}${STRING_PREVIEW_TRUNCATED_SUFFIX}`,\n )\n case 'object':\n if (value === null) return 'null'\n if (Array.isArray(value)) {\n return `[${stringifyArray(value, stringifyValue)}]`\n }\n if (isPlainObject(value)) {\n return `{${stringifyArray(Object.entries(value), stringifyObjectEntry)}}`\n }\n if (ifCid(value)) return 'cid'\n if (isLegacyBlobRef(value)) return 'legacy-blob'\n if (value instanceof Date) return 'date'\n if (value instanceof RegExp) return 'regexp'\n if (value instanceof Map) return 'map'\n if (value instanceof Set) return 'set'\n return 'object'\n default:\n return typeof value\n }\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringifyObjectEntry([key, _value]: [PropertyKey, unknown]): string {\n return `${JSON.stringify(key)}: ...`\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringifyArray<T>(\n arr: readonly T[],\n fn: (item: T) => string,\n n = 2,\n): string {\n return arr.slice(0, n).map(fn).join(', ') + (arr.length > n ? ', ...' : '')\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validation-issue.js","sourceRoot":"","sources":["../../src/core/validation-issue.ts"],"names":[],"mappings":"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","sourcesContent":["import { ifCid, isLegacyBlobRef, isPlainObject } from '@atproto/lex-data'\n\nconst STRING_PREVIEW_MAX_LENGTH = 256\nconst STRING_PREVIEW_TRUNCATED_SUFFIX = '…'\n\n/**\n * Abstract base class for all validation issues.\n *\n * An issue represents a single validation failure, containing:\n * - A code identifying the type of issue\n * - The path to the invalid value in the data structure\n * - The actual input value that failed validation\n *\n * Subclasses add specific properties relevant to each issue type and implement\n * the {@link message} property for human-readable error messages (that don't\n * contain the error path)\n */\nexport abstract class Issue {\n abstract readonly message: string\n\n constructor(\n readonly code: string,\n readonly path: readonly PropertyKey[],\n readonly input: unknown,\n ) {}\n\n /**\n * Returns a human-readable description of the validation issue.\n */\n toString() {\n return `${this.message}${stringifyPath(this.path)}`\n }\n\n /**\n * Converts the issue to a JSON-serializable object.\n *\n * @returns An object containing the issue code, path, and message\n */\n toJSON() {\n return {\n code: this.code,\n path: this.path,\n message: this.message,\n }\n }\n}\n\n/**\n * A custom validation issue with a user-defined message.\n *\n * Use this for validation rules that don't fit into the standard issue categories.\n */\nexport class IssueCustom extends Issue {\n constructor(\n readonly path: readonly PropertyKey[],\n readonly input: unknown,\n readonly message: string,\n ) {\n super('custom', path, input)\n }\n}\n\n/**\n * Issue for string values that don't match an expected format.\n *\n * Used for AT Protocol specific formats like DID, handle, NSID, AT-URI, etc.\n */\nexport class IssueInvalidFormat extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly format: string,\n readonly detail?: string,\n ) {\n super('invalid_format', path, input)\n }\n\n override get message(): string {\n return `Invalid ${this.formatDescription}${this.detail ? ` (${this.detail}, ` : ' ('}got ${stringifyValue(this.input)})`\n }\n\n /** Returns a human-readable description of the expected format. */\n get formatDescription(): string {\n switch (this.format) {\n case 'at-identifier':\n return `AT identifier`\n case 'did':\n return `DID`\n case 'nsid':\n return `NSID`\n case 'cid':\n return `CID string`\n case 'tid':\n return `TID string`\n case 'record-key':\n return `record key`\n default:\n return this.format\n }\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n format: this.format,\n }\n }\n}\n\n/**\n * Issue for values that have an unexpected type.\n *\n * This is one of the most common validation issues, occurring when the\n * runtime type of a value doesn't match the expected schema type.\n */\nexport class IssueInvalidType extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly expected: readonly string[],\n ) {\n super('invalid_type', path, input)\n }\n\n override get message(): string {\n return `Expected ${oneOf(this.expected.map(stringifyExpectedType))} value type (got ${stringifyValue(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n expected: this.expected,\n }\n }\n}\n\n/**\n * Issue for values that don't match any of the expected literal values.\n *\n * Used when a value must be one of a specific set of allowed values\n * (e.g., enum-like constraints).\n */\nexport class IssueInvalidValue extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly values: readonly unknown[],\n ) {\n super('invalid_value', path, input)\n }\n\n override get message(): string {\n return `Expected ${oneOf(this.values.map(stringifyValue))} (got ${stringifyValue(this.input)})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n values: this.values,\n }\n }\n}\n\n/**\n * Issue for missing required object properties.\n */\nexport class IssueRequiredKey extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly key: PropertyKey,\n ) {\n super('required_key', path, input)\n }\n\n override get message(): string {\n return `Missing required key \"${String(this.key)}\"`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n key: this.key,\n }\n }\n}\n\n/**\n * The type of measurement for size constraint issues.\n *\n * - `'array'` - Array length\n * - `'string'` - String length in characters\n * - `'integer'` - Numeric value\n * - `'grapheme'` - String length in grapheme clusters\n * - `'bytes'` - Byte length\n * - `'blob'` - Blob size\n */\nexport type MeasurableType =\n | 'array'\n | 'string'\n | 'integer'\n | 'grapheme'\n | 'bytes'\n | 'blob'\n\n/**\n * Issue for values that exceed a maximum constraint.\n */\nexport class IssueTooBig extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly maximum: number,\n readonly type: MeasurableType,\n readonly actual: number,\n ) {\n super('too_big', path, input)\n }\n\n override get message(): string {\n return `${this.type} too big (maximum ${this.maximum}, got ${this.actual})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n type: this.type,\n maximum: this.maximum,\n }\n }\n}\n\n/**\n * Issue for values that are below a minimum constraint.\n */\nexport class IssueTooSmall extends Issue {\n constructor(\n path: readonly PropertyKey[],\n input: unknown,\n readonly minimum: number,\n readonly type: MeasurableType,\n readonly actual: number,\n ) {\n super('too_small', path, input)\n }\n\n override get message(): string {\n return `${this.type} too small (minimum ${this.minimum}, got ${this.actual})`\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n type: this.type,\n minimum: this.minimum,\n }\n }\n}\n\n// -----------------------------------------------------------------------------\n// Helper functions for formatting error messages\n// -----------------------------------------------------------------------------\n\nfunction stringifyExpectedType(expected: string): string {\n if (expected === '$typed') {\n return 'an object which includes the \"$type\" property'\n }\n return expected\n}\n\nfunction stringifyPath(path: readonly PropertyKey[]) {\n return ` at ${buildJsonPath(path)}`\n}\n\nfunction buildJsonPath(path: readonly PropertyKey[]): string {\n return `$${path.map(toJsonPathSegment).join('')}`\n}\n\nfunction toJsonPathSegment(segment: PropertyKey): string {\n if (typeof segment === 'number' || typeof segment === 'symbol') {\n return `[${String(segment)}]`\n } else if (/^[a-zA-Z_$][a-zA-Z0-9_]*$/.test(segment)) {\n return `.${segment}`\n } else {\n return `[${JSON.stringify(segment)}]`\n }\n}\n\nfunction oneOf(arr: readonly string[]): string {\n if (arr.length === 0) return ''\n if (arr.length === 1) return arr[0]\n return `one of ${arr.slice(0, -1).join(', ')} or ${arr.at(-1)}`\n}\n\nfunction stringifyValue(value: unknown): string {\n switch (typeof value) {\n case 'bigint':\n return `${value}n`\n case 'number':\n case 'boolean':\n return String(value)\n case 'string':\n return JSON.stringify(\n value.length < STRING_PREVIEW_MAX_LENGTH\n ? value\n : `${value.slice(0, STRING_PREVIEW_MAX_LENGTH - STRING_PREVIEW_TRUNCATED_SUFFIX.length)}${STRING_PREVIEW_TRUNCATED_SUFFIX}`,\n )\n case 'object':\n if (value === null) return 'null'\n if (Array.isArray(value)) {\n return `[${stringifyArray(value, stringifyValue)}]`\n }\n if (isPlainObject(value)) {\n return `{${stringifyArray(Object.entries(value), stringifyObjectEntry)}}`\n }\n if (ifCid(value)) return 'cid'\n if (isLegacyBlobRef(value)) return 'legacy-blob'\n if (value instanceof Date) return 'date'\n if (value instanceof RegExp) return 'regexp'\n if (value instanceof Map) return 'map'\n if (value instanceof Set) return 'set'\n return 'object'\n default:\n return typeof value\n }\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringifyObjectEntry([key, _value]: [PropertyKey, unknown]): string {\n return `${JSON.stringify(key)}: ...`\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction stringifyArray<T>(\n arr: readonly T[],\n fn: (item: T) => string,\n n = 2,\n): string {\n return arr.slice(0, n).map(fn).join(', ') + (arr.length > n ? ', ...' : '')\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/lex-schema",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Lexicon schema system for AT Lexicons",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@standard-schema/spec": "^1.1.0",
|
|
39
39
|
"iso-datestring-validator": "^2.2.2",
|
|
40
40
|
"tslib": "^2.8.1",
|
|
41
|
-
"@atproto/syntax": "^0.5.
|
|
41
|
+
"@atproto/syntax": "^0.5.4",
|
|
42
42
|
"@atproto/lex-data": "^0.0.15"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
TidString,
|
|
12
12
|
UriString,
|
|
13
13
|
isAtIdentifierString,
|
|
14
|
+
isAtUriString,
|
|
14
15
|
isDatetimeString,
|
|
15
|
-
isValidAtUri,
|
|
16
16
|
isValidDid,
|
|
17
17
|
isValidHandle,
|
|
18
18
|
isValidLanguage,
|
|
@@ -35,6 +35,7 @@ import { CheckFn } from '../util/assertion-util.js'
|
|
|
35
35
|
export {
|
|
36
36
|
type AtIdentifierString,
|
|
37
37
|
asAtIdentifierString,
|
|
38
|
+
assertAtIdentifierString,
|
|
38
39
|
ifAtIdentifierString,
|
|
39
40
|
isAtIdentifierString,
|
|
40
41
|
} from '@atproto/syntax'
|
|
@@ -45,6 +46,7 @@ export { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax'
|
|
|
45
46
|
export {
|
|
46
47
|
type DatetimeString,
|
|
47
48
|
asDatetimeString,
|
|
49
|
+
assertDatetimeString,
|
|
48
50
|
ifDatetimeString,
|
|
49
51
|
isDatetimeString,
|
|
50
52
|
} from '@atproto/syntax'
|
|
@@ -54,7 +56,7 @@ export {
|
|
|
54
56
|
* the strict {@link isDatetimeString} guard, which only allows datetimes that
|
|
55
57
|
* fully conform to the AT Protocol specification (e.g. must include timezone).
|
|
56
58
|
*/
|
|
57
|
-
export function
|
|
59
|
+
export function isDatetimeStringLenient<I>(
|
|
58
60
|
input: I,
|
|
59
61
|
): input is I & DatetimeString {
|
|
60
62
|
// @NOTE the returned type assertion is inaccurate wrt. the DatetimeString
|
|
@@ -72,20 +74,22 @@ export function isDatetimeStringLoose<I>(
|
|
|
72
74
|
// DatetimeString utilities
|
|
73
75
|
export { currentDatetimeString, toDatetimeString } from '@atproto/syntax'
|
|
74
76
|
|
|
77
|
+
export {
|
|
78
|
+
type AtUriString,
|
|
79
|
+
asAtUriString,
|
|
80
|
+
assertAtUriString,
|
|
81
|
+
ifAtUriString,
|
|
82
|
+
isAtUriString,
|
|
83
|
+
} from '@atproto/syntax'
|
|
84
|
+
|
|
75
85
|
/**
|
|
76
|
-
*
|
|
86
|
+
* Lenient version of {@link isAtUriString} that does not enforce the validity
|
|
87
|
+
* of the record key (rkey) path component (if present).
|
|
77
88
|
*
|
|
78
|
-
* @
|
|
79
|
-
* @returns `true` if the value is a valid AT URI
|
|
89
|
+
* @see {@link isAtUriString}
|
|
80
90
|
*/
|
|
81
|
-
export
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* An AT URI string pointing to a resource in the AT Protocol network.
|
|
85
|
-
*
|
|
86
|
-
* @example `"at://did:plc:1234.../app.bsky.feed.post/3k2..."`
|
|
87
|
-
*/
|
|
88
|
-
AtUriString,
|
|
91
|
+
export function isAtUriStringLenient<I>(input: I): input is I & AtUriString {
|
|
92
|
+
return isAtUriString(input, { strict: false })
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
/**
|
|
@@ -246,15 +250,15 @@ export type StringFormat = Extract<keyof StringFormats, string>
|
|
|
246
250
|
const stringFormatVerifiers: {
|
|
247
251
|
readonly [K in StringFormat]: readonly [
|
|
248
252
|
strict: CheckFn<StringFormats[K]>,
|
|
249
|
-
|
|
253
|
+
lenient?: CheckFn<StringFormats[K]>,
|
|
250
254
|
]
|
|
251
255
|
} = /*#__PURE__*/ Object.freeze({
|
|
252
256
|
__proto__: null,
|
|
253
257
|
|
|
254
258
|
'at-identifier': [isAtIdentifierString],
|
|
255
|
-
'at-uri': [isAtUriString],
|
|
259
|
+
'at-uri': [isAtUriString, isAtUriStringLenient],
|
|
256
260
|
cid: [isCidString],
|
|
257
|
-
datetime: [isDatetimeString,
|
|
261
|
+
datetime: [isDatetimeString, isDatetimeStringLenient],
|
|
258
262
|
did: [isDidString],
|
|
259
263
|
handle: [isHandleString],
|
|
260
264
|
language: [isLanguageString],
|
|
@@ -266,8 +270,8 @@ const stringFormatVerifiers: {
|
|
|
266
270
|
|
|
267
271
|
export type StringFormatValidationOptions = {
|
|
268
272
|
/**
|
|
269
|
-
* Allows to be more lenient in validation by using a "
|
|
270
|
-
* function, if available. The behavior of the
|
|
273
|
+
* Allows to be more lenient in validation by using a "lenient" verification
|
|
274
|
+
* function, if available. The behavior of the lenient verifier depends on the
|
|
271
275
|
* specific format, but generally it may allow for a wider range of valid
|
|
272
276
|
* inputs, including values that are not compliant with the AT Protocol
|
|
273
277
|
* specification.
|
|
@@ -321,8 +325,8 @@ export function isStringFormat<I extends string, F extends StringFormat>(
|
|
|
321
325
|
if (!formatVerifier) throw new TypeError(`Unknown string format: ${format}`)
|
|
322
326
|
|
|
323
327
|
const check: CheckFn<StringFormats[F]> =
|
|
324
|
-
options?.strict === false
|
|
325
|
-
? formatVerifier[1]
|
|
328
|
+
options?.strict === false && formatVerifier.length > 1
|
|
329
|
+
? formatVerifier[1]!
|
|
326
330
|
: formatVerifier[0]
|
|
327
331
|
|
|
328
332
|
return check(input)
|