@atproto/syntax 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/LICENSE.txt +1 -1
- package/dist/at-identifier.d.ts +6 -0
- package/dist/at-identifier.d.ts.map +1 -0
- package/dist/at-identifier.js +28 -0
- package/dist/at-identifier.js.map +1 -0
- package/dist/aturi.d.ts +8 -6
- package/dist/aturi.d.ts.map +1 -1
- package/dist/aturi.js +41 -83
- package/dist/aturi.js.map +1 -1
- package/dist/aturi_validation.d.ts +6 -2
- package/dist/aturi_validation.d.ts.map +1 -1
- package/dist/aturi_validation.js +66 -60
- package/dist/aturi_validation.js.map +1 -1
- package/dist/datetime.d.ts +11 -4
- package/dist/datetime.d.ts.map +1 -1
- package/dist/datetime.js +22 -25
- package/dist/datetime.js.map +1 -1
- package/dist/did.d.ts +4 -2
- package/dist/did.d.ts.map +1 -1
- package/dist/did.js +24 -19
- package/dist/did.js.map +1 -1
- package/dist/handle.d.ts +7 -6
- package/dist/handle.d.ts.map +1 -1
- package/dist/handle.js +32 -35
- package/dist/handle.js.map +1 -1
- package/dist/index.d.ts +10 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -21
- package/dist/index.js.map +1 -1
- package/dist/language.d.ts +18 -0
- package/dist/language.d.ts.map +1 -0
- package/dist/language.js +30 -0
- package/dist/language.js.map +1 -0
- package/dist/nsid.d.ts +6 -5
- package/dist/nsid.d.ts.map +1 -1
- package/dist/nsid.js +6 -11
- package/dist/nsid.js.map +1 -1
- package/dist/recordkey.d.ts +3 -2
- package/dist/recordkey.d.ts.map +1 -1
- package/dist/recordkey.js +33 -22
- package/dist/recordkey.js.map +1 -1
- package/dist/tid.d.ts +3 -2
- package/dist/tid.d.ts.map +1 -1
- package/dist/tid.js +10 -10
- package/dist/tid.js.map +1 -1
- package/dist/uri.d.ts +3 -0
- package/dist/uri.d.ts.map +1 -0
- package/dist/uri.js +7 -0
- package/dist/uri.js.map +1 -0
- package/package.json +7 -4
- package/src/at-identifier.ts +33 -0
- package/src/aturi.ts +59 -46
- package/src/aturi_validation.ts +78 -51
- package/src/datetime.ts +26 -14
- package/src/did.ts +28 -15
- package/src/handle.ts +29 -26
- package/src/index.ts +10 -7
- package/src/language.ts +39 -0
- package/src/nsid.ts +14 -8
- package/src/recordkey.ts +42 -17
- package/src/tid.ts +9 -5
- package/src/uri.ts +5 -0
- package/tests/aturi.test.ts +3 -2
- package/tests/datetime.test.ts +1 -0
- package/tests/did.test.ts +1 -0
- package/tests/handle.test.ts +1 -0
- package/tests/language.test.ts +88 -0
- package/tests/nsid.test.ts +1 -0
- package/tests/recordkey.test.ts +1 -0
- package/tests/tid.test.ts +1 -0
- package/tsconfig.build.json +6 -2
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.tests.json +6 -4
- package/vitest.config.ts +5 -0
- package/jest.config.js +0 -7
- package/tsconfig.tests.tsbuildinfo +0 -1
package/dist/datetime.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InvalidDatetimeError = exports.normalizeDatetimeAlways =
|
|
3
|
+
exports.InvalidDatetimeError = exports.normalizeDatetimeAlways = void 0;
|
|
4
|
+
exports.ensureValidDatetime = ensureValidDatetime;
|
|
5
|
+
exports.isValidDatetime = isValidDatetime;
|
|
6
|
+
exports.normalizeDatetime = normalizeDatetime;
|
|
4
7
|
/* Validates datetime string against atproto Lexicon 'datetime' format.
|
|
5
8
|
* Syntax is described at: https://atproto.com/specs/lexicon#datetime
|
|
6
9
|
*/
|
|
7
|
-
|
|
8
|
-
const date = new Date(
|
|
10
|
+
function ensureValidDatetime(input) {
|
|
11
|
+
const date = new Date(input);
|
|
9
12
|
// must parse as ISO 8601; this also verifies semantics like month is not 13 or 00
|
|
10
13
|
if (isNaN(date.getTime())) {
|
|
11
14
|
throw new InvalidDatetimeError('datetime did not parse as ISO 8601');
|
|
@@ -14,35 +17,30 @@ const ensureValidDatetime = (dtStr) => {
|
|
|
14
17
|
throw new InvalidDatetimeError('datetime normalized to a negative time');
|
|
15
18
|
}
|
|
16
19
|
// regex and other checks for RFC-3339
|
|
17
|
-
if (!/^[0-9]{4}-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9]:[0-6][0-9](.[0-9]{1,20})?(Z|([+-][0-2][0-9]:[0-5][0-9]))$/.test(
|
|
20
|
+
if (!/^[0-9]{4}-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9]:[0-6][0-9](.[0-9]{1,20})?(Z|([+-][0-2][0-9]:[0-5][0-9]))$/.test(input)) {
|
|
18
21
|
throw new InvalidDatetimeError("datetime didn't validate via regex");
|
|
19
22
|
}
|
|
20
|
-
if (
|
|
23
|
+
if (input.length > 64) {
|
|
21
24
|
throw new InvalidDatetimeError('datetime is too long (64 chars max)');
|
|
22
25
|
}
|
|
23
|
-
if (
|
|
26
|
+
if (input.endsWith('-00:00')) {
|
|
24
27
|
throw new InvalidDatetimeError('datetime can not use "-00:00" for UTC timezone');
|
|
25
28
|
}
|
|
26
|
-
if (
|
|
29
|
+
if (input.startsWith('000')) {
|
|
27
30
|
throw new InvalidDatetimeError('datetime so close to year zero not allowed');
|
|
28
31
|
}
|
|
29
|
-
}
|
|
30
|
-
exports.ensureValidDatetime = ensureValidDatetime;
|
|
32
|
+
}
|
|
31
33
|
/* Same logic as ensureValidDatetime(), but returns a boolean instead of throwing an exception.
|
|
32
34
|
*/
|
|
33
|
-
|
|
35
|
+
function isValidDatetime(input) {
|
|
34
36
|
try {
|
|
35
|
-
|
|
37
|
+
ensureValidDatetime(input);
|
|
36
38
|
}
|
|
37
39
|
catch (err) {
|
|
38
|
-
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
throw err;
|
|
40
|
+
return false;
|
|
42
41
|
}
|
|
43
42
|
return true;
|
|
44
|
-
}
|
|
45
|
-
exports.isValidDatetime = isValidDatetime;
|
|
43
|
+
}
|
|
46
44
|
/* Takes a flexible datetime string and normalizes representation.
|
|
47
45
|
*
|
|
48
46
|
* This function will work with any valid atproto datetime (eg, anything which isValidDatetime() is true for). It *additionally* is more flexible about accepting datetimes that don't comply to RFC 3339, or are missing timezone information, and normalizing them to a valid datetime.
|
|
@@ -53,10 +51,10 @@ exports.isValidDatetime = isValidDatetime;
|
|
|
53
51
|
*
|
|
54
52
|
* Expected output format: YYYY-MM-DDTHH:mm:ss.sssZ
|
|
55
53
|
*/
|
|
56
|
-
|
|
57
|
-
if (
|
|
54
|
+
function normalizeDatetime(dtStr) {
|
|
55
|
+
if (isValidDatetime(dtStr)) {
|
|
58
56
|
const outStr = new Date(dtStr).toISOString();
|
|
59
|
-
if (
|
|
57
|
+
if (isValidDatetime(outStr)) {
|
|
60
58
|
return outStr;
|
|
61
59
|
}
|
|
62
60
|
}
|
|
@@ -65,7 +63,7 @@ const normalizeDatetime = (dtStr) => {
|
|
|
65
63
|
const date = new Date(dtStr + 'Z');
|
|
66
64
|
if (!isNaN(date.getTime())) {
|
|
67
65
|
const tzStr = date.toISOString();
|
|
68
|
-
if (
|
|
66
|
+
if (isValidDatetime(tzStr)) {
|
|
69
67
|
return tzStr;
|
|
70
68
|
}
|
|
71
69
|
}
|
|
@@ -76,21 +74,20 @@ const normalizeDatetime = (dtStr) => {
|
|
|
76
74
|
throw new InvalidDatetimeError('datetime did not parse as any timestamp format');
|
|
77
75
|
}
|
|
78
76
|
const isoStr = date.toISOString();
|
|
79
|
-
if (
|
|
77
|
+
if (isValidDatetime(isoStr)) {
|
|
80
78
|
return isoStr;
|
|
81
79
|
}
|
|
82
80
|
else {
|
|
83
81
|
throw new InvalidDatetimeError('datetime normalized to invalid timestamp string');
|
|
84
82
|
}
|
|
85
|
-
}
|
|
86
|
-
exports.normalizeDatetime = normalizeDatetime;
|
|
83
|
+
}
|
|
87
84
|
/* Variant of normalizeDatetime() which always returns a valid datetime strings.
|
|
88
85
|
*
|
|
89
86
|
* If a InvalidDatetimeError is encountered, returns the UNIX epoch time as a UTC datetime (1970-01-01T00:00:00.000Z).
|
|
90
87
|
*/
|
|
91
88
|
const normalizeDatetimeAlways = (dtStr) => {
|
|
92
89
|
try {
|
|
93
|
-
return
|
|
90
|
+
return normalizeDatetime(dtStr);
|
|
94
91
|
}
|
|
95
92
|
catch (err) {
|
|
96
93
|
if (err instanceof InvalidDatetimeError) {
|
package/dist/datetime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datetime.js","sourceRoot":"","sources":["../src/datetime.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"datetime.js","sourceRoot":"","sources":["../src/datetime.ts"],"names":[],"mappings":"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","sourcesContent":["/** An ISO 8601 formatted datetime string (YYYY-MM-DDTHH:mm:ss.sssZ) */\nexport type DatetimeString =\n `${string}-${string}-${string}T${string}:${string}:${string}${'Z' | `+${string}` | `-${string}`}`\n\n// Allow date.toISOString() to be used where datetime format is expected\ndeclare global {\n interface Date {\n toISOString(): `${string}-${string}-${string}T${string}:${string}:${string}Z`\n }\n}\n\n/* Validates datetime string against atproto Lexicon 'datetime' format.\n * Syntax is described at: https://atproto.com/specs/lexicon#datetime\n */\nexport function ensureValidDatetime<I extends string>(\n input: I,\n): asserts input is I & DatetimeString {\n const date = new Date(input)\n // must parse as ISO 8601; this also verifies semantics like month is not 13 or 00\n if (isNaN(date.getTime())) {\n throw new InvalidDatetimeError('datetime did not parse as ISO 8601')\n }\n if (date.toISOString().startsWith('-')) {\n throw new InvalidDatetimeError('datetime normalized to a negative time')\n }\n // regex and other checks for RFC-3339\n if (\n !/^[0-9]{4}-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-6][0-9]:[0-6][0-9](.[0-9]{1,20})?(Z|([+-][0-2][0-9]:[0-5][0-9]))$/.test(\n input,\n )\n ) {\n throw new InvalidDatetimeError(\"datetime didn't validate via regex\")\n }\n if (input.length > 64) {\n throw new InvalidDatetimeError('datetime is too long (64 chars max)')\n }\n if (input.endsWith('-00:00')) {\n throw new InvalidDatetimeError(\n 'datetime can not use \"-00:00\" for UTC timezone',\n )\n }\n if (input.startsWith('000')) {\n throw new InvalidDatetimeError('datetime so close to year zero not allowed')\n }\n}\n\n/* Same logic as ensureValidDatetime(), but returns a boolean instead of throwing an exception.\n */\nexport function isValidDatetime<I extends string>(\n input: I,\n): input is I & DatetimeString {\n try {\n ensureValidDatetime(input)\n } catch (err) {\n return false\n }\n\n return true\n}\n\n/* Takes a flexible datetime string and normalizes representation.\n *\n * This function will work with any valid atproto datetime (eg, anything which isValidDatetime() is true for). It *additionally* is more flexible about accepting datetimes that don't comply to RFC 3339, or are missing timezone information, and normalizing them to a valid datetime.\n *\n * One use-case is a consistent, sortable string. Another is to work with older invalid createdAt datetimes.\n *\n * Successful output will be a valid atproto datetime with millisecond precision (3 sub-second digits) and UTC timezone with trailing 'Z' syntax. Throws `InvalidDatetimeError` if the input string could not be parsed as a datetime, even with permissive parsing.\n *\n * Expected output format: YYYY-MM-DDTHH:mm:ss.sssZ\n */\nexport function normalizeDatetime(dtStr: string): DatetimeString {\n if (isValidDatetime(dtStr)) {\n const outStr = new Date(dtStr).toISOString()\n if (isValidDatetime(outStr)) {\n return outStr\n }\n }\n\n // check if this permissive datetime is missing a timezone\n if (!/.*(([+-]\\d\\d:?\\d\\d)|[a-zA-Z])$/.test(dtStr)) {\n const date = new Date(dtStr + 'Z')\n if (!isNaN(date.getTime())) {\n const tzStr = date.toISOString()\n if (isValidDatetime(tzStr)) {\n return tzStr\n }\n }\n }\n\n // finally try parsing as simple datetime\n const date = new Date(dtStr)\n if (isNaN(date.getTime())) {\n throw new InvalidDatetimeError(\n 'datetime did not parse as any timestamp format',\n )\n }\n const isoStr = date.toISOString()\n if (isValidDatetime(isoStr)) {\n return isoStr\n } else {\n throw new InvalidDatetimeError(\n 'datetime normalized to invalid timestamp string',\n )\n }\n}\n\n/* Variant of normalizeDatetime() which always returns a valid datetime strings.\n *\n * If a InvalidDatetimeError is encountered, returns the UNIX epoch time as a UTC datetime (1970-01-01T00:00:00.000Z).\n */\nexport const normalizeDatetimeAlways = (dtStr: string): DatetimeString => {\n try {\n return normalizeDatetime(dtStr)\n } catch (err) {\n if (err instanceof InvalidDatetimeError) {\n return new Date(0).toISOString()\n }\n throw err\n }\n}\n\n/* Indicates a datetime string did not pass full atproto Lexicon datetime string format checks.\n */\nexport class InvalidDatetimeError extends Error {}\n"]}
|
package/dist/did.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
export declare
|
|
1
|
+
export type DidString<M extends string = string> = `did:${M}:${string}`;
|
|
2
|
+
export declare function ensureValidDid<I extends string>(input: I): asserts input is I & DidString;
|
|
3
|
+
export declare function ensureValidDidRegex<I extends string>(input: I): asserts input is I & DidString;
|
|
4
|
+
export declare function isValidDid<I extends string>(input: I): input is I & DidString;
|
|
3
5
|
export declare class InvalidDidError extends Error {
|
|
4
6
|
}
|
|
5
7
|
//# sourceMappingURL=did.d.ts.map
|
package/dist/did.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"did.d.ts","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"did.d.ts","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,OAAO,CAAC,IAAI,MAAM,EAAE,CAAA;AAEvE,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CA8BhC;AAID,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAUhC;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,SAAS,CAE7E;AAED,qBAAa,eAAgB,SAAQ,KAAK;CAAG"}
|
package/dist/did.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InvalidDidError = exports.ensureValidDidRegex = exports.ensureValidDid = void 0;
|
|
4
2
|
// Human-readable constraints:
|
|
5
3
|
// - valid W3C DID (https://www.w3.org/TR/did-core/#did-syntax)
|
|
6
4
|
// - entire URI is ASCII: [a-zA-Z0-9._:%-]
|
|
@@ -14,40 +12,47 @@ exports.InvalidDidError = exports.ensureValidDidRegex = exports.ensureValidDid =
|
|
|
14
12
|
// - in current atproto, only allowing did:plc and did:web. But not *forcing* this at lexicon layer
|
|
15
13
|
// - hard length limit of 8KBytes
|
|
16
14
|
// - not going to validate "percent encoding" here
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.InvalidDidError = void 0;
|
|
17
|
+
exports.ensureValidDid = ensureValidDid;
|
|
18
|
+
exports.ensureValidDidRegex = ensureValidDidRegex;
|
|
19
|
+
exports.isValidDid = isValidDid;
|
|
20
|
+
function ensureValidDid(input) {
|
|
21
|
+
if (!input.startsWith('did:')) {
|
|
19
22
|
throw new InvalidDidError('DID requires "did:" prefix');
|
|
20
23
|
}
|
|
24
|
+
if (input.length > 2048) {
|
|
25
|
+
throw new InvalidDidError('DID is too long (2048 chars max)');
|
|
26
|
+
}
|
|
27
|
+
if (input.endsWith(':') || input.endsWith('%')) {
|
|
28
|
+
throw new InvalidDidError('DID can not end with ":" or "%"');
|
|
29
|
+
}
|
|
21
30
|
// check that all chars are boring ASCII
|
|
22
|
-
if (!/^[a-zA-Z0-9._:%-]*$/.test(
|
|
31
|
+
if (!/^[a-zA-Z0-9._:%-]*$/.test(input)) {
|
|
23
32
|
throw new InvalidDidError('Disallowed characters in DID (ASCII letters, digits, and a couple other characters only)');
|
|
24
33
|
}
|
|
25
|
-
const { length, 1: method } =
|
|
34
|
+
const { length, 1: method } = input.split(':');
|
|
26
35
|
if (length < 3) {
|
|
27
36
|
throw new InvalidDidError('DID requires prefix, method, and method-specific content');
|
|
28
37
|
}
|
|
29
38
|
if (!/^[a-z]+$/.test(method)) {
|
|
30
39
|
throw new InvalidDidError('DID method must be lower-case letters');
|
|
31
40
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (did.length > 2 * 1024) {
|
|
36
|
-
throw new InvalidDidError('DID is too long (2048 chars max)');
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
exports.ensureValidDid = ensureValidDid;
|
|
40
|
-
const ensureValidDidRegex = (did) => {
|
|
41
|
+
}
|
|
42
|
+
const DID_REGEX = /^did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]$/;
|
|
43
|
+
function ensureValidDidRegex(input) {
|
|
41
44
|
// simple regex to enforce most constraints via just regex and length.
|
|
42
45
|
// hand wrote this regex based on above constraints
|
|
43
|
-
if (
|
|
46
|
+
if (!DID_REGEX.test(input)) {
|
|
44
47
|
throw new InvalidDidError("DID didn't validate via regex");
|
|
45
48
|
}
|
|
46
|
-
if (
|
|
49
|
+
if (input.length > 2048) {
|
|
47
50
|
throw new InvalidDidError('DID is too long (2048 chars max)');
|
|
48
51
|
}
|
|
49
|
-
}
|
|
50
|
-
|
|
52
|
+
}
|
|
53
|
+
function isValidDid(input) {
|
|
54
|
+
return input.length <= 2048 && DID_REGEX.test(input);
|
|
55
|
+
}
|
|
51
56
|
class InvalidDidError extends Error {
|
|
52
57
|
}
|
|
53
58
|
exports.InvalidDidError = InvalidDidError;
|
package/dist/did.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"did.js","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"did.js","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":";AAAA,8BAA8B;AAC9B,iEAAiE;AACjE,+CAA+C;AAC/C,2CAA2C;AAC3C,wEAAwE;AACxE,sFAAsF;AACtF,qFAAqF;AACrF,wHAAwH;AACxH,8GAA8G;AAC9G,6FAA6F;AAC7F,qGAAqG;AACrG,mCAAmC;AACnC,oDAAoD;;;AAIpD,wCAgCC;AAID,kDAYC;AAED,gCAEC;AApDD,SAAgB,cAAc,CAC5B,KAAQ;IAER,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,eAAe,CAAC,4BAA4B,CAAC,CAAA;IACzD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,eAAe,CAAC,kCAAkC,CAAC,CAAA;IAC/D,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,eAAe,CAAC,iCAAiC,CAAC,CAAA;IAC9D,CAAC;IAED,wCAAwC;IACxC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,eAAe,CACvB,0FAA0F,CAC3F,CAAA;IACH,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC9C,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,eAAe,CACvB,0DAA0D,CAC3D,CAAA;IACH,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,eAAe,CAAC,uCAAuC,CAAC,CAAA;IACpE,CAAC;AACH,CAAC;AAED,MAAM,SAAS,GAAG,8CAA8C,CAAA;AAEhE,SAAgB,mBAAmB,CACjC,KAAQ;IAER,sEAAsE;IACtE,mDAAmD;IACnD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,eAAe,CAAC,+BAA+B,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,eAAe,CAAC,kCAAkC,CAAC,CAAA;IAC/D,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAmB,KAAQ;IACnD,OAAO,KAAK,CAAC,MAAM,IAAI,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACtD,CAAC;AAED,MAAa,eAAgB,SAAQ,KAAK;CAAG;AAA7C,0CAA6C","sourcesContent":["// Human-readable constraints:\n// - valid W3C DID (https://www.w3.org/TR/did-core/#did-syntax)\n// - entire URI is ASCII: [a-zA-Z0-9._:%-]\n// - always starts \"did:\" (lower-case)\n// - method name is one or more lower-case letters, followed by \":\"\n// - remaining identifier can have any of the above chars, but can not end in \":\"\n// - it seems that a bunch of \":\" can be included, and don't need spaces between\n// - \"%\" is used only for \"percent encoding\" and must be followed by two hex characters (and thus can't end in \"%\")\n// - query (\"?\") and fragment (\"#\") stuff is defined for \"DID URIs\", but not as part of identifier itself\n// - \"The current specification does not take a position on the maximum length of a DID\"\n// - in current atproto, only allowing did:plc and did:web. But not *forcing* this at lexicon layer\n// - hard length limit of 8KBytes\n// - not going to validate \"percent encoding\" here\n\nexport type DidString<M extends string = string> = `did:${M}:${string}`\n\nexport function ensureValidDid<I extends string>(\n input: I,\n): asserts input is I & DidString {\n if (!input.startsWith('did:')) {\n throw new InvalidDidError('DID requires \"did:\" prefix')\n }\n\n if (input.length > 2048) {\n throw new InvalidDidError('DID is too long (2048 chars max)')\n }\n\n if (input.endsWith(':') || input.endsWith('%')) {\n throw new InvalidDidError('DID can not end with \":\" or \"%\"')\n }\n\n // check that all chars are boring ASCII\n if (!/^[a-zA-Z0-9._:%-]*$/.test(input)) {\n throw new InvalidDidError(\n 'Disallowed characters in DID (ASCII letters, digits, and a couple other characters only)',\n )\n }\n\n const { length, 1: method } = input.split(':')\n if (length < 3) {\n throw new InvalidDidError(\n 'DID requires prefix, method, and method-specific content',\n )\n }\n\n if (!/^[a-z]+$/.test(method)) {\n throw new InvalidDidError('DID method must be lower-case letters')\n }\n}\n\nconst DID_REGEX = /^did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]$/\n\nexport function ensureValidDidRegex<I extends string>(\n input: I,\n): asserts input is I & DidString {\n // simple regex to enforce most constraints via just regex and length.\n // hand wrote this regex based on above constraints\n if (!DID_REGEX.test(input)) {\n throw new InvalidDidError(\"DID didn't validate via regex\")\n }\n\n if (input.length > 2048) {\n throw new InvalidDidError('DID is too long (2048 chars max)')\n }\n}\n\nexport function isValidDid<I extends string>(input: I): input is I & DidString {\n return input.length <= 2048 && DID_REGEX.test(input)\n}\n\nexport class InvalidDidError extends Error {}\n"]}
|
package/dist/handle.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export declare const INVALID_HANDLE = "handle.invalid";
|
|
2
|
+
export type HandleString = `${string}.${string}`;
|
|
2
3
|
export declare const DISALLOWED_TLDS: string[];
|
|
3
|
-
export declare
|
|
4
|
-
export declare
|
|
5
|
-
export declare
|
|
6
|
-
export declare
|
|
7
|
-
export declare
|
|
8
|
-
export declare
|
|
4
|
+
export declare function ensureValidHandle<I extends string>(input: I): asserts input is I & HandleString;
|
|
5
|
+
export declare function ensureValidHandleRegex<I extends string>(input: I): asserts input is I & HandleString;
|
|
6
|
+
export declare function normalizeHandle(handle: string): string;
|
|
7
|
+
export declare function normalizeAndEnsureValidHandle(handle: string): HandleString;
|
|
8
|
+
export declare function isValidHandle<I extends string>(input: I): input is I & HandleString;
|
|
9
|
+
export declare function isValidTld(handle: string): boolean;
|
|
9
10
|
export declare class InvalidHandleError extends Error {
|
|
10
11
|
}
|
|
11
12
|
/** @deprecated Never used */
|
package/dist/handle.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle.d.ts","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"handle.d.ts","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,mBAAmB,CAAA;AAE9C,MAAM,MAAM,YAAY,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAA;AAMhD,eAAO,MAAM,eAAe,UAY3B,CAAA;AAqBD,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,YAAY,CAkCnC;AAMD,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EACrD,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,YAAY,CAOnC;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAI1E;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAC5C,KAAK,EAAE,CAAC,GACP,KAAK,IAAI,CAAC,GAAG,YAAY,CAE3B;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED,qBAAa,kBAAmB,SAAQ,KAAK;CAAG;AAChD,6BAA6B;AAC7B,qBAAa,mBAAoB,SAAQ,KAAK;CAAG;AACjD,6BAA6B;AAC7B,qBAAa,sBAAuB,SAAQ,KAAK;CAAG;AACpD,6BAA6B;AAC7B,qBAAa,qBAAsB,SAAQ,KAAK;CAAG"}
|
package/dist/handle.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DisallowedDomainError = exports.UnsupportedDomainError = exports.ReservedHandleError = exports.InvalidHandleError = exports.
|
|
3
|
+
exports.DisallowedDomainError = exports.UnsupportedDomainError = exports.ReservedHandleError = exports.InvalidHandleError = exports.DISALLOWED_TLDS = exports.INVALID_HANDLE = void 0;
|
|
4
|
+
exports.ensureValidHandle = ensureValidHandle;
|
|
5
|
+
exports.ensureValidHandleRegex = ensureValidHandleRegex;
|
|
6
|
+
exports.normalizeHandle = normalizeHandle;
|
|
7
|
+
exports.normalizeAndEnsureValidHandle = normalizeAndEnsureValidHandle;
|
|
8
|
+
exports.isValidHandle = isValidHandle;
|
|
9
|
+
exports.isValidTld = isValidTld;
|
|
4
10
|
exports.INVALID_HANDLE = 'handle.invalid';
|
|
5
11
|
// Currently these are registration-time restrictions, not protocol-level
|
|
6
12
|
// restrictions. We have a couple accounts in the wild that we need to clean up
|
|
@@ -38,15 +44,15 @@ exports.DISALLOWED_TLDS = [
|
|
|
38
44
|
// - does not validate whether domain or TLD exists, or is a reserved or
|
|
39
45
|
// special TLD (eg, .onion or .local)
|
|
40
46
|
// - does not validate punycode
|
|
41
|
-
|
|
47
|
+
function ensureValidHandle(input) {
|
|
42
48
|
// check that all chars are boring ASCII
|
|
43
|
-
if (!/^[a-zA-Z0-9.-]*$/.test(
|
|
49
|
+
if (!/^[a-zA-Z0-9.-]*$/.test(input)) {
|
|
44
50
|
throw new InvalidHandleError('Disallowed characters in handle (ASCII letters, digits, dashes, periods only)');
|
|
45
51
|
}
|
|
46
|
-
if (
|
|
52
|
+
if (input.length > 253) {
|
|
47
53
|
throw new InvalidHandleError('Handle is too long (253 chars max)');
|
|
48
54
|
}
|
|
49
|
-
const labels =
|
|
55
|
+
const labels = input.split('.');
|
|
50
56
|
if (labels.length < 2) {
|
|
51
57
|
throw new InvalidHandleError('Handle domain needs at least two parts');
|
|
52
58
|
}
|
|
@@ -65,45 +71,36 @@ const ensureValidHandle = (handle) => {
|
|
|
65
71
|
throw new InvalidHandleError('Handle final component (TLD) must start with ASCII letter');
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
|
-
}
|
|
69
|
-
exports.ensureValidHandle = ensureValidHandle;
|
|
74
|
+
}
|
|
70
75
|
// simple regex translation of above constraints
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
if (handle.length > 253) {
|
|
76
|
+
const HANDLE_REGEX = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
|
|
77
|
+
function ensureValidHandleRegex(input) {
|
|
78
|
+
if (input.length > 253) {
|
|
76
79
|
throw new InvalidHandleError('Handle is too long (253 chars max)');
|
|
77
80
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
if (!HANDLE_REGEX.test(input)) {
|
|
82
|
+
throw new InvalidHandleError("Handle didn't validate via regex");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function normalizeHandle(handle) {
|
|
81
86
|
return handle.toLowerCase();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
(0, exports.ensureValidHandle)(normalized);
|
|
87
|
+
}
|
|
88
|
+
function normalizeAndEnsureValidHandle(handle) {
|
|
89
|
+
const normalized = normalizeHandle(handle);
|
|
90
|
+
ensureValidHandle(normalized);
|
|
87
91
|
return normalized;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (err instanceof InvalidHandleError) {
|
|
92
|
+
}
|
|
93
|
+
function isValidHandle(input) {
|
|
94
|
+
return input.length <= 253 && HANDLE_REGEX.test(input);
|
|
95
|
+
}
|
|
96
|
+
function isValidTld(handle) {
|
|
97
|
+
for (const tld of exports.DISALLOWED_TLDS) {
|
|
98
|
+
if (handle.endsWith(tld)) {
|
|
96
99
|
return false;
|
|
97
100
|
}
|
|
98
|
-
throw err;
|
|
99
101
|
}
|
|
100
102
|
return true;
|
|
101
|
-
}
|
|
102
|
-
exports.isValidHandle = isValidHandle;
|
|
103
|
-
const isValidTld = (handle) => {
|
|
104
|
-
return !exports.DISALLOWED_TLDS.some((domain) => handle.endsWith(domain));
|
|
105
|
-
};
|
|
106
|
-
exports.isValidTld = isValidTld;
|
|
103
|
+
}
|
|
107
104
|
class InvalidHandleError extends Error {
|
|
108
105
|
}
|
|
109
106
|
exports.InvalidHandleError = InvalidHandleError;
|
package/dist/handle.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle.js","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"handle.js","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"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","sourcesContent":["export const INVALID_HANDLE = 'handle.invalid'\n\nexport type HandleString = `${string}.${string}`\n\n// Currently these are registration-time restrictions, not protocol-level\n// restrictions. We have a couple accounts in the wild that we need to clean up\n// before hard-disallow.\n// See also: https://en.wikipedia.org/wiki/Top-level_domain#Reserved_domains\nexport const DISALLOWED_TLDS = [\n '.local',\n '.arpa',\n '.invalid',\n '.localhost',\n '.internal',\n '.example',\n '.alt',\n // policy could concievably change on \".onion\" some day\n '.onion',\n // NOTE: .test is allowed in testing and devopment. In practical terms\n // \"should\" \"never\" actually resolve and get registered in production\n]\n\n// Handle constraints, in English:\n// - must be a possible domain name\n// - RFC-1035 is commonly referenced, but has been updated. eg, RFC-3696,\n// section 2. and RFC-3986, section 3. can now have leading numbers (eg,\n// 4chan.org)\n// - \"labels\" (sub-names) are made of ASCII letters, digits, hyphens\n// - can not start or end with a hyphen\n// - TLD (last component) should not start with a digit\n// - can't end with a hyphen (can end with digit)\n// - each segment must be between 1 and 63 characters (not including any periods)\n// - overall length can't be more than 253 characters\n// - separated by (ASCII) periods; does not start or end with period\n// - case insensitive\n// - domains (handles) are equal if they are the same lower-case\n// - punycode allowed for internationalization\n// - no whitespace, null bytes, joining chars, etc\n// - does not validate whether domain or TLD exists, or is a reserved or\n// special TLD (eg, .onion or .local)\n// - does not validate punycode\nexport function ensureValidHandle<I extends string>(\n input: I,\n): asserts input is I & HandleString {\n // check that all chars are boring ASCII\n if (!/^[a-zA-Z0-9.-]*$/.test(input)) {\n throw new InvalidHandleError(\n 'Disallowed characters in handle (ASCII letters, digits, dashes, periods only)',\n )\n }\n\n if (input.length > 253) {\n throw new InvalidHandleError('Handle is too long (253 chars max)')\n }\n const labels = input.split('.')\n if (labels.length < 2) {\n throw new InvalidHandleError('Handle domain needs at least two parts')\n }\n for (let i = 0; i < labels.length; i++) {\n const l = labels[i]\n if (l.length < 1) {\n throw new InvalidHandleError('Handle parts can not be empty')\n }\n if (l.length > 63) {\n throw new InvalidHandleError('Handle part too long (max 63 chars)')\n }\n if (l.endsWith('-') || l.startsWith('-')) {\n throw new InvalidHandleError(\n 'Handle parts can not start or end with hyphens',\n )\n }\n if (i + 1 === labels.length && !/^[a-zA-Z]/.test(l)) {\n throw new InvalidHandleError(\n 'Handle final component (TLD) must start with ASCII letter',\n )\n }\n }\n}\n\n// simple regex translation of above constraints\nconst HANDLE_REGEX =\n /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/\n\nexport function ensureValidHandleRegex<I extends string>(\n input: I,\n): asserts input is I & HandleString {\n if (input.length > 253) {\n throw new InvalidHandleError('Handle is too long (253 chars max)')\n }\n if (!HANDLE_REGEX.test(input)) {\n throw new InvalidHandleError(\"Handle didn't validate via regex\")\n }\n}\n\nexport function normalizeHandle(handle: string): string {\n return handle.toLowerCase()\n}\n\nexport function normalizeAndEnsureValidHandle(handle: string): HandleString {\n const normalized = normalizeHandle(handle)\n ensureValidHandle(normalized)\n return normalized\n}\n\nexport function isValidHandle<I extends string>(\n input: I,\n): input is I & HandleString {\n return input.length <= 253 && HANDLE_REGEX.test(input)\n}\n\nexport function isValidTld(handle: string): boolean {\n for (const tld of DISALLOWED_TLDS) {\n if (handle.endsWith(tld)) {\n return false\n }\n }\n return true\n}\n\nexport class InvalidHandleError extends Error {}\n/** @deprecated Never used */\nexport class ReservedHandleError extends Error {}\n/** @deprecated Never used */\nexport class UnsupportedDomainError extends Error {}\n/** @deprecated Never used */\nexport class DisallowedDomainError extends Error {}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
1
|
+
export * from './at-identifier.js';
|
|
2
|
+
export * from './aturi.js';
|
|
3
|
+
export * from './datetime.js';
|
|
4
|
+
export * from './did.js';
|
|
5
|
+
export * from './handle.js';
|
|
6
|
+
export * from './nsid.js';
|
|
7
|
+
export * from './language.js';
|
|
8
|
+
export * from './recordkey.js';
|
|
9
|
+
export * from './tid.js';
|
|
10
|
+
export * from './uri.js';
|
|
8
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,24 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
|
|
18
|
-
__exportStar(require("./
|
|
19
|
-
__exportStar(require("./
|
|
20
|
-
__exportStar(require("./
|
|
21
|
-
__exportStar(require("./
|
|
22
|
-
__exportStar(require("./
|
|
23
|
-
__exportStar(require("./
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./at-identifier.js"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./aturi.js"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./datetime.js"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./did.js"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./handle.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./nsid.js"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./language.js"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./recordkey.js"), exports);
|
|
12
|
+
tslib_1.__exportStar(require("./tid.js"), exports);
|
|
13
|
+
tslib_1.__exportStar(require("./uri.js"), exports);
|
|
24
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,6DAAkC;AAClC,qDAA0B;AAC1B,wDAA6B;AAC7B,mDAAwB;AACxB,sDAA2B;AAC3B,oDAAyB;AACzB,wDAA6B;AAC7B,yDAA8B;AAC9B,mDAAwB;AACxB,mDAAwB","sourcesContent":["export * from './at-identifier.js'\nexport * from './aturi.js'\nexport * from './datetime.js'\nexport * from './did.js'\nexport * from './handle.js'\nexport * from './nsid.js'\nexport * from './language.js'\nexport * from './recordkey.js'\nexport * from './tid.js'\nexport * from './uri.js'\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type LanguageTag = {
|
|
2
|
+
grandfathered?: string;
|
|
3
|
+
language?: string;
|
|
4
|
+
extlang?: string;
|
|
5
|
+
script?: string;
|
|
6
|
+
region?: string;
|
|
7
|
+
variant?: string;
|
|
8
|
+
extension?: string;
|
|
9
|
+
privateUse?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function parseLanguageString(input: string): LanguageTag | null;
|
|
12
|
+
/**
|
|
13
|
+
* Validates well-formed BCP 47 syntax
|
|
14
|
+
*
|
|
15
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc5646.html#section-2.1}
|
|
16
|
+
*/
|
|
17
|
+
export declare function isValidLanguage(input: string): boolean;
|
|
18
|
+
//# sourceMappingURL=language.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../src/language.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GAAG;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAerE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD"}
|
package/dist/language.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseLanguageString = parseLanguageString;
|
|
4
|
+
exports.isValidLanguage = isValidLanguage;
|
|
5
|
+
const BCP47_REGEXP = /^((?<grandfathered>(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?<language>([A-Za-z]{2,3}(-(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-(?<script>[A-Za-z]{4}))?(-(?<region>[A-Za-z]{2}|[0-9]{3}))?(-(?<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-(?<extension>[0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(?<privateUseA>x(-[A-Za-z0-9]{1,8})+))?)|(?<privateUseB>x(-[A-Za-z0-9]{1,8})+))$/;
|
|
6
|
+
function parseLanguageString(input) {
|
|
7
|
+
const parsed = input.match(BCP47_REGEXP);
|
|
8
|
+
if (!parsed?.groups)
|
|
9
|
+
return null;
|
|
10
|
+
const { groups } = parsed;
|
|
11
|
+
return {
|
|
12
|
+
grandfathered: groups.grandfathered,
|
|
13
|
+
language: groups.language,
|
|
14
|
+
extlang: groups.extlang,
|
|
15
|
+
script: groups.script,
|
|
16
|
+
region: groups.region,
|
|
17
|
+
variant: groups.variant,
|
|
18
|
+
extension: groups.extension,
|
|
19
|
+
privateUse: groups.privateUseA || groups.privateUseB,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Validates well-formed BCP 47 syntax
|
|
24
|
+
*
|
|
25
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc5646.html#section-2.1}
|
|
26
|
+
*/
|
|
27
|
+
function isValidLanguage(input) {
|
|
28
|
+
return BCP47_REGEXP.test(input);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=language.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.js","sourceRoot":"","sources":["../src/language.ts"],"names":[],"mappings":";;AAcA,kDAeC;AAOD,0CAEC;AAtCD,MAAM,YAAY,GAChB,mlBAAmlB,CAAA;AAarlB,SAAgB,mBAAmB,CAAC,KAAa;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IACxC,IAAI,CAAC,MAAM,EAAE,MAAM;QAAE,OAAO,IAAI,CAAA;IAEhC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;IACzB,OAAO;QACL,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,UAAU,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW;KACrD,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,eAAe,CAAC,KAAa;IAC3C,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACjC,CAAC","sourcesContent":["const BCP47_REGEXP =\n /^((?<grandfathered>(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?<language>([A-Za-z]{2,3}(-(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-(?<script>[A-Za-z]{4}))?(-(?<region>[A-Za-z]{2}|[0-9]{3}))?(-(?<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-(?<extension>[0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(?<privateUseA>x(-[A-Za-z0-9]{1,8})+))?)|(?<privateUseB>x(-[A-Za-z0-9]{1,8})+))$/\n\nexport type LanguageTag = {\n grandfathered?: string\n language?: string\n extlang?: string\n script?: string\n region?: string\n variant?: string\n extension?: string\n privateUse?: string\n}\n\nexport function parseLanguageString(input: string): LanguageTag | null {\n const parsed = input.match(BCP47_REGEXP)\n if (!parsed?.groups) return null\n\n const { groups } = parsed\n return {\n grandfathered: groups.grandfathered,\n language: groups.language,\n extlang: groups.extlang,\n script: groups.script,\n region: groups.region,\n variant: groups.variant,\n extension: groups.extension,\n privateUse: groups.privateUseA || groups.privateUseB,\n }\n}\n\n/**\n * Validates well-formed BCP 47 syntax\n *\n * @see {@link https://www.rfc-editor.org/rfc/rfc5646.html#section-2.1}\n */\nexport function isValidLanguage(input: string): boolean {\n return BCP47_REGEXP.test(input)\n}\n"]}
|
package/dist/nsid.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
export type NsidString = `${string}.${string}.${string}`;
|
|
1
2
|
export declare class NSID {
|
|
2
3
|
readonly segments: readonly string[];
|
|
3
4
|
static parse(input: string): NSID;
|
|
4
5
|
static create(authority: string, name: string): NSID;
|
|
5
|
-
static isValid(nsid: string):
|
|
6
|
+
static isValid(nsid: string): nsid is `${string}.${string}.${string}`;
|
|
6
7
|
static from(input: {
|
|
7
8
|
toString: () => string;
|
|
8
9
|
}): NSID;
|
|
@@ -11,9 +12,9 @@ export declare class NSID {
|
|
|
11
12
|
get name(): string | undefined;
|
|
12
13
|
toString(): string;
|
|
13
14
|
}
|
|
14
|
-
export declare function ensureValidNsid(
|
|
15
|
+
export declare function ensureValidNsid<I extends string>(input: I): asserts input is I & NsidString;
|
|
15
16
|
export declare function parseNsid(nsid: string): string[];
|
|
16
|
-
export declare function isValidNsid(
|
|
17
|
+
export declare function isValidNsid<I extends string>(input: I): input is I & NsidString;
|
|
17
18
|
type ValidateResult<T> = {
|
|
18
19
|
success: true;
|
|
19
20
|
value: T;
|
|
@@ -27,12 +28,12 @@ export declare function validateNsid(input: string): ValidateResult<string[]>;
|
|
|
27
28
|
* {@link parseNsid}/{@link NSID.parse} if you need the parsed segments, or
|
|
28
29
|
* {@link isValidNsid} if you just want a boolean.
|
|
29
30
|
*/
|
|
30
|
-
export declare function ensureValidNsidRegex(nsid: string):
|
|
31
|
+
export declare function ensureValidNsidRegex(nsid: string): asserts nsid is NsidString;
|
|
31
32
|
/**
|
|
32
33
|
* Regexp based validation that behaves identically to the previous code but
|
|
33
34
|
* provides less detailed error messages (while being 20% to 50% faster).
|
|
34
35
|
*/
|
|
35
|
-
export declare function validateNsidRegex(value: string): ValidateResult<
|
|
36
|
+
export declare function validateNsidRegex(value: string): ValidateResult<NsidString>;
|
|
36
37
|
export declare class InvalidNsidError extends Error {
|
|
37
38
|
}
|
|
38
39
|
export {};
|
package/dist/nsid.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nsid.d.ts","sourceRoot":"","sources":["../src/nsid.ts"],"names":[],"mappings":"AAaA,qBAAa,IAAI;IACf,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAEpC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIjC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKpD,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM;IAI3B,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;KAAE,GAAG,IAAI;gBAWxC,IAAI,EAAE,MAAM;IAIxB,IAAI,SAAS,WAKZ;IAED,IAAI,IAAI,uBAEP;IAED,QAAQ;CAGT;AAED,wBAAgB,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"nsid.d.ts","sourceRoot":"","sources":["../src/nsid.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,UAAU,GAAG,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,CAAA;AAExD,qBAAa,IAAI;IACf,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAEpC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIjC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAKpD,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM;IAI3B,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;KAAE,GAAG,IAAI;gBAWxC,IAAI,EAAE,MAAM;IAIxB,IAAI,SAAS,WAKZ;IAED,IAAI,IAAI,uBAEP;IAED,QAAQ;CAGT;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC9C,KAAK,EAAE,CAAC,GACP,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,UAAU,CAGjC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAIhD;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC1C,KAAK,EAAE,CAAC,GACP,KAAK,IAAI,CAAC,GAAG,UAAU,CAIzB;AAED,KAAK,cAAc,CAAC,CAAC,IACjB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAC3B;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAKvC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,CA0DpE;AA4BD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,IAAI,UAAU,CAG7E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAuB3E;AAED,qBAAa,gBAAiB,SAAQ,KAAK;CAAG"}
|