@atproto/syntax 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/LICENSE.txt +1 -1
- package/benchmark.js +208 -0
- package/dist/at-identifier.d.ts +5 -0
- package/dist/at-identifier.d.ts.map +1 -0
- package/dist/at-identifier.js +19 -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 +36 -45
- package/dist/aturi.js.map +1 -1
- package/dist/aturi_validation.d.ts +5 -2
- package/dist/aturi_validation.d.ts.map +1 -1
- package/dist/aturi_validation.js +54 -66
- 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 +16 -16
- package/dist/datetime.js.map +1 -1
- package/dist/did.d.ts +3 -2
- package/dist/did.d.ts.map +1 -1
- package/dist/did.js +8 -8
- 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 +28 -31
- package/dist/handle.js.map +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/nsid.d.ts +30 -5
- package/dist/nsid.d.ts.map +1 -1
- package/dist/nsid.js +137 -47
- 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 +7 -7
- package/dist/tid.js.map +1 -1
- package/package.json +1 -1
- package/src/at-identifier.ts +22 -0
- package/src/aturi.ts +59 -46
- package/src/aturi_validation.ts +62 -57
- package/src/datetime.ts +17 -4
- package/src/did.ts +5 -2
- package/src/handle.ts +23 -22
- package/src/index.ts +8 -7
- package/src/nsid.ts +146 -47
- package/src/recordkey.ts +40 -17
- package/src/tid.ts +4 -2
- package/tests/nsid.test.ts +117 -77
- package/tsconfig.build.json +1 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.tests.tsbuildinfo +1 -1
package/dist/index.js
CHANGED
|
@@ -14,11 +14,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./handle"), exports);
|
|
18
|
-
__exportStar(require("./did"), exports);
|
|
19
|
-
__exportStar(require("./nsid"), exports);
|
|
20
|
-
__exportStar(require("./aturi"), exports);
|
|
21
|
-
__exportStar(require("./
|
|
22
|
-
__exportStar(require("./
|
|
23
|
-
__exportStar(require("./
|
|
17
|
+
__exportStar(require("./handle.js"), exports);
|
|
18
|
+
__exportStar(require("./did.js"), exports);
|
|
19
|
+
__exportStar(require("./nsid.js"), exports);
|
|
20
|
+
__exportStar(require("./aturi.js"), exports);
|
|
21
|
+
__exportStar(require("./at-identifier.js"), exports);
|
|
22
|
+
__exportStar(require("./tid.js"), exports);
|
|
23
|
+
__exportStar(require("./recordkey.js"), exports);
|
|
24
|
+
__exportStar(require("./datetime.js"), exports);
|
|
24
25
|
//# 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":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,2CAAwB;AACxB,4CAAyB;AACzB,6CAA0B;AAC1B,qDAAkC;AAClC,2CAAwB;AACxB,iDAA8B;AAC9B,gDAA6B","sourcesContent":["export * from './handle.js'\nexport * from './did.js'\nexport * from './nsid.js'\nexport * from './aturi.js'\nexport * from './at-identifier.js'\nexport * from './tid.js'\nexport * from './recordkey.js'\nexport * from './datetime.js'\n"]}
|
package/dist/nsid.d.ts
CHANGED
|
@@ -1,15 +1,40 @@
|
|
|
1
|
+
export type NsidString = `${string}.${string}.${string}`;
|
|
1
2
|
export declare class NSID {
|
|
2
|
-
segments: string[];
|
|
3
|
-
static parse(
|
|
3
|
+
readonly segments: readonly string[];
|
|
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}`;
|
|
7
|
+
static from(input: {
|
|
8
|
+
toString: () => string;
|
|
9
|
+
}): NSID;
|
|
6
10
|
constructor(nsid: string);
|
|
7
11
|
get authority(): string;
|
|
8
12
|
get name(): string | undefined;
|
|
9
13
|
toString(): string;
|
|
10
14
|
}
|
|
11
|
-
export declare
|
|
12
|
-
export declare
|
|
15
|
+
export declare function ensureValidNsid(nsid: string): asserts nsid is NsidString;
|
|
16
|
+
export declare function parseNsid(nsid: string): string[];
|
|
17
|
+
export declare function isValidNsid(nsid: string): nsid is NsidString;
|
|
18
|
+
type ValidateResult<T> = {
|
|
19
|
+
success: true;
|
|
20
|
+
value: T;
|
|
21
|
+
} | {
|
|
22
|
+
success: false;
|
|
23
|
+
message: string;
|
|
24
|
+
};
|
|
25
|
+
export declare function validateNsid(input: string): ValidateResult<string[]>;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated Use {@link ensureValidNsid} if you care about error details,
|
|
28
|
+
* {@link parseNsid}/{@link NSID.parse} if you need the parsed segments, or
|
|
29
|
+
* {@link isValidNsid} if you just want a boolean.
|
|
30
|
+
*/
|
|
31
|
+
export declare function ensureValidNsidRegex(nsid: string): asserts nsid is NsidString;
|
|
32
|
+
/**
|
|
33
|
+
* Regexp based validation that behaves identically to the previous code but
|
|
34
|
+
* provides less detailed error messages (while being 20% to 50% faster).
|
|
35
|
+
*/
|
|
36
|
+
export declare function validateNsidRegex(value: string): ValidateResult<NsidString>;
|
|
13
37
|
export declare class InvalidNsidError extends Error {
|
|
14
38
|
}
|
|
39
|
+
export {};
|
|
15
40
|
//# sourceMappingURL=nsid.d.ts.map
|
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,EAAE,MAAM,EAAE,
|
|
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,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,IAAI,UAAU,CAGxE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAIhD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,UAAU,CAI5D;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"}
|
package/dist/nsid.js
CHANGED
|
@@ -7,38 +7,47 @@ number = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "0"
|
|
|
7
7
|
delim = "."
|
|
8
8
|
segment = alpha *( alpha / number / "-" )
|
|
9
9
|
authority = segment *( delim segment )
|
|
10
|
-
name = alpha *( alpha )
|
|
10
|
+
name = alpha *( alpha / number )
|
|
11
11
|
nsid = authority delim name
|
|
12
12
|
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.InvalidNsidError = exports.
|
|
15
|
+
exports.InvalidNsidError = exports.NSID = void 0;
|
|
16
|
+
exports.ensureValidNsid = ensureValidNsid;
|
|
17
|
+
exports.parseNsid = parseNsid;
|
|
18
|
+
exports.isValidNsid = isValidNsid;
|
|
19
|
+
exports.validateNsid = validateNsid;
|
|
20
|
+
exports.ensureValidNsidRegex = ensureValidNsidRegex;
|
|
21
|
+
exports.validateNsidRegex = validateNsidRegex;
|
|
16
22
|
class NSID {
|
|
17
|
-
static parse(
|
|
18
|
-
return new NSID(
|
|
23
|
+
static parse(input) {
|
|
24
|
+
return new NSID(input);
|
|
19
25
|
}
|
|
20
26
|
static create(authority, name) {
|
|
21
|
-
const
|
|
22
|
-
return new NSID(
|
|
27
|
+
const input = [...authority.split('.').reverse(), name].join('.');
|
|
28
|
+
return new NSID(input);
|
|
23
29
|
}
|
|
24
30
|
static isValid(nsid) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
return isValidNsid(nsid);
|
|
32
|
+
}
|
|
33
|
+
static from(input) {
|
|
34
|
+
if (input instanceof NSID) {
|
|
35
|
+
// No need to clone, NSID is immutable
|
|
36
|
+
return input;
|
|
28
37
|
}
|
|
29
|
-
|
|
30
|
-
return
|
|
38
|
+
if (Array.isArray(input)) {
|
|
39
|
+
return new NSID(input.join('.'));
|
|
31
40
|
}
|
|
41
|
+
return new NSID(String(input));
|
|
32
42
|
}
|
|
33
43
|
constructor(nsid) {
|
|
34
44
|
Object.defineProperty(this, "segments", {
|
|
35
45
|
enumerable: true,
|
|
36
46
|
configurable: true,
|
|
37
47
|
writable: true,
|
|
38
|
-
value:
|
|
48
|
+
value: void 0
|
|
39
49
|
});
|
|
40
|
-
|
|
41
|
-
this.segments = nsid.split('.');
|
|
50
|
+
this.segments = parseNsid(nsid);
|
|
42
51
|
}
|
|
43
52
|
get authority() {
|
|
44
53
|
return this.segments
|
|
@@ -54,53 +63,134 @@ class NSID {
|
|
|
54
63
|
}
|
|
55
64
|
}
|
|
56
65
|
exports.NSID = NSID;
|
|
66
|
+
function ensureValidNsid(nsid) {
|
|
67
|
+
const result = validateNsid(nsid);
|
|
68
|
+
if (!result.success)
|
|
69
|
+
throw new InvalidNsidError(result.message);
|
|
70
|
+
}
|
|
71
|
+
function parseNsid(nsid) {
|
|
72
|
+
const result = validateNsid(nsid);
|
|
73
|
+
if (!result.success)
|
|
74
|
+
throw new InvalidNsidError(result.message);
|
|
75
|
+
return result.value;
|
|
76
|
+
}
|
|
77
|
+
function isValidNsid(nsid) {
|
|
78
|
+
// Since the regex version is more performant for valid NSIDs, we use it when
|
|
79
|
+
// we don't care about error details.
|
|
80
|
+
return validateNsidRegex(nsid).success;
|
|
81
|
+
}
|
|
57
82
|
// Human readable constraints on NSID:
|
|
58
83
|
// - a valid domain in reversed notation
|
|
59
84
|
// - followed by an additional period-separated name, which is camel-case letters
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
function validateNsid(input) {
|
|
86
|
+
if (input.length > 253 + 1 + 63) {
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
message: 'NSID is too long (317 chars max)',
|
|
90
|
+
};
|
|
65
91
|
}
|
|
66
|
-
if (
|
|
67
|
-
|
|
92
|
+
if (hasDisallowedCharacters(input)) {
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
message: 'Disallowed characters in NSID (ASCII letters, digits, dashes, periods only)',
|
|
96
|
+
};
|
|
68
97
|
}
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
71
|
-
|
|
98
|
+
const segments = input.split('.');
|
|
99
|
+
if (segments.length < 3) {
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
message: 'NSID needs at least three parts',
|
|
103
|
+
};
|
|
72
104
|
}
|
|
73
|
-
for (
|
|
74
|
-
const l = labels[i];
|
|
105
|
+
for (const l of segments) {
|
|
75
106
|
if (l.length < 1) {
|
|
76
|
-
|
|
107
|
+
return {
|
|
108
|
+
success: false,
|
|
109
|
+
message: 'NSID parts can not be empty',
|
|
110
|
+
};
|
|
77
111
|
}
|
|
78
112
|
if (l.length > 63) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
if (/^[0-9]/.test(l) && i === 0) {
|
|
85
|
-
throw new InvalidNsidError('NSID first part may not start with a digit');
|
|
113
|
+
return {
|
|
114
|
+
success: false,
|
|
115
|
+
message: 'NSID part too long (max 63 chars)',
|
|
116
|
+
};
|
|
86
117
|
}
|
|
87
|
-
if (
|
|
88
|
-
|
|
118
|
+
if (startsWithHyphen(l) || endsWithHyphen(l)) {
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
message: 'NSID parts can not start or end with hyphen',
|
|
122
|
+
};
|
|
89
123
|
}
|
|
90
124
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (!/^[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(\.[a-zA-Z]([a-zA-Z0-9]{0,62})?)$/.test(nsid)) {
|
|
97
|
-
throw new InvalidNsidError("NSID didn't validate via regex");
|
|
125
|
+
if (startsWithNumber(segments[0])) {
|
|
126
|
+
return {
|
|
127
|
+
success: false,
|
|
128
|
+
message: 'NSID first part may not start with a digit',
|
|
129
|
+
};
|
|
98
130
|
}
|
|
99
|
-
if (
|
|
100
|
-
|
|
131
|
+
if (!isValidIdentifier(segments[segments.length - 1])) {
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
message: 'NSID name part must be only letters and digits (and no leading digit)',
|
|
135
|
+
};
|
|
101
136
|
}
|
|
102
|
-
|
|
103
|
-
|
|
137
|
+
return {
|
|
138
|
+
success: true,
|
|
139
|
+
value: segments,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function hasDisallowedCharacters(v) {
|
|
143
|
+
return !/^[a-zA-Z0-9.-]*$/.test(v);
|
|
144
|
+
}
|
|
145
|
+
function startsWithNumber(v) {
|
|
146
|
+
const charCode = v.charCodeAt(0);
|
|
147
|
+
return charCode >= 48 && charCode <= 57;
|
|
148
|
+
}
|
|
149
|
+
function startsWithHyphen(v) {
|
|
150
|
+
return v.charCodeAt(0) === 45; /* - */
|
|
151
|
+
}
|
|
152
|
+
function endsWithHyphen(v) {
|
|
153
|
+
return v.charCodeAt(v.length - 1) === 45; /* - */
|
|
154
|
+
}
|
|
155
|
+
function isValidIdentifier(v) {
|
|
156
|
+
// Note, since we already know that "v" only contains [a-zA-Z0-9-], we can
|
|
157
|
+
// simplify the following regex by checking only the first char and presence
|
|
158
|
+
// of "-".
|
|
159
|
+
// return /^[a-zA-Z][a-zA-Z0-9]*$/.test(v)
|
|
160
|
+
return !startsWithNumber(v) && !v.includes('-');
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* @deprecated Use {@link ensureValidNsid} if you care about error details,
|
|
164
|
+
* {@link parseNsid}/{@link NSID.parse} if you need the parsed segments, or
|
|
165
|
+
* {@link isValidNsid} if you just want a boolean.
|
|
166
|
+
*/
|
|
167
|
+
function ensureValidNsidRegex(nsid) {
|
|
168
|
+
const result = validateNsidRegex(nsid);
|
|
169
|
+
if (!result.success)
|
|
170
|
+
throw new InvalidNsidError(result.message);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Regexp based validation that behaves identically to the previous code but
|
|
174
|
+
* provides less detailed error messages (while being 20% to 50% faster).
|
|
175
|
+
*/
|
|
176
|
+
function validateNsidRegex(value) {
|
|
177
|
+
if (value.length > 253 + 1 + 63) {
|
|
178
|
+
return {
|
|
179
|
+
success: false,
|
|
180
|
+
message: 'NSID is too long (317 chars max)',
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (!/^[a-zA-Z](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?:\.[a-zA-Z](?:[a-zA-Z0-9]{0,62})?)$/.test(value)) {
|
|
184
|
+
return {
|
|
185
|
+
success: false,
|
|
186
|
+
message: "NSID didn't validate via regex",
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
success: true,
|
|
191
|
+
value: value,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
104
194
|
class InvalidNsidError extends Error {
|
|
105
195
|
}
|
|
106
196
|
exports.InvalidNsidError = InvalidNsidError;
|
package/dist/nsid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nsid.js","sourceRoot":"","sources":["../src/nsid.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nsid.js","sourceRoot":"","sources":["../src/nsid.ts"],"names":[],"mappings":"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","sourcesContent":["/*\nGrammar:\n\nalpha = \"a\" / \"b\" / \"c\" / \"d\" / \"e\" / \"f\" / \"g\" / \"h\" / \"i\" / \"j\" / \"k\" / \"l\" / \"m\" / \"n\" / \"o\" / \"p\" / \"q\" / \"r\" / \"s\" / \"t\" / \"u\" / \"v\" / \"w\" / \"x\" / \"y\" / \"z\" / \"A\" / \"B\" / \"C\" / \"D\" / \"E\" / \"F\" / \"G\" / \"H\" / \"I\" / \"J\" / \"K\" / \"L\" / \"M\" / \"N\" / \"O\" / \"P\" / \"Q\" / \"R\" / \"S\" / \"T\" / \"U\" / \"V\" / \"W\" / \"X\" / \"Y\" / \"Z\"\nnumber = \"1\" / \"2\" / \"3\" / \"4\" / \"5\" / \"6\" / \"7\" / \"8\" / \"9\" / \"0\"\ndelim = \".\"\nsegment = alpha *( alpha / number / \"-\" )\nauthority = segment *( delim segment )\nname = alpha *( alpha / number )\nnsid = authority delim name\n\n*/\n\nexport type NsidString = `${string}.${string}.${string}`\n\nexport class NSID {\n readonly segments: readonly string[]\n\n static parse(input: string): NSID {\n return new NSID(input)\n }\n\n static create(authority: string, name: string): NSID {\n const input = [...authority.split('.').reverse(), name].join('.')\n return new NSID(input)\n }\n\n static isValid(nsid: string) {\n return isValidNsid(nsid)\n }\n\n static from(input: { toString: () => string }): NSID {\n if (input instanceof NSID) {\n // No need to clone, NSID is immutable\n return input\n }\n if (Array.isArray(input)) {\n return new NSID((input as string[]).join('.'))\n }\n return new NSID(String(input))\n }\n\n constructor(nsid: string) {\n this.segments = parseNsid(nsid)\n }\n\n get authority() {\n return this.segments\n .slice(0, this.segments.length - 1)\n .reverse()\n .join('.')\n }\n\n get name() {\n return this.segments.at(this.segments.length - 1)\n }\n\n toString() {\n return this.segments.join('.')\n }\n}\n\nexport function ensureValidNsid(nsid: string): asserts nsid is NsidString {\n const result = validateNsid(nsid)\n if (!result.success) throw new InvalidNsidError(result.message)\n}\n\nexport function parseNsid(nsid: string): string[] {\n const result = validateNsid(nsid)\n if (!result.success) throw new InvalidNsidError(result.message)\n return result.value\n}\n\nexport function isValidNsid(nsid: string): nsid is NsidString {\n // Since the regex version is more performant for valid NSIDs, we use it when\n // we don't care about error details.\n return validateNsidRegex(nsid).success\n}\n\ntype ValidateResult<T> =\n | { success: true; value: T }\n | { success: false; message: string }\n\n// Human readable constraints on NSID:\n// - a valid domain in reversed notation\n// - followed by an additional period-separated name, which is camel-case letters\nexport function validateNsid(input: string): ValidateResult<string[]> {\n if (input.length > 253 + 1 + 63) {\n return {\n success: false,\n message: 'NSID is too long (317 chars max)',\n }\n }\n if (hasDisallowedCharacters(input)) {\n return {\n success: false,\n message:\n 'Disallowed characters in NSID (ASCII letters, digits, dashes, periods only)',\n }\n }\n const segments = input.split('.')\n if (segments.length < 3) {\n return {\n success: false,\n message: 'NSID needs at least three parts',\n }\n }\n for (const l of segments) {\n if (l.length < 1) {\n return {\n success: false,\n message: 'NSID parts can not be empty',\n }\n }\n if (l.length > 63) {\n return {\n success: false,\n message: 'NSID part too long (max 63 chars)',\n }\n }\n if (startsWithHyphen(l) || endsWithHyphen(l)) {\n return {\n success: false,\n message: 'NSID parts can not start or end with hyphen',\n }\n }\n }\n if (startsWithNumber(segments[0])) {\n return {\n success: false,\n message: 'NSID first part may not start with a digit',\n }\n }\n if (!isValidIdentifier(segments[segments.length - 1])) {\n return {\n success: false,\n message:\n 'NSID name part must be only letters and digits (and no leading digit)',\n }\n }\n return {\n success: true,\n value: segments,\n }\n}\n\nfunction hasDisallowedCharacters(v: string) {\n return !/^[a-zA-Z0-9.-]*$/.test(v)\n}\n\nfunction startsWithNumber(v: string) {\n const charCode = v.charCodeAt(0)\n return charCode >= 48 && charCode <= 57\n}\n\nfunction startsWithHyphen(v: string) {\n return v.charCodeAt(0) === 45 /* - */\n}\n\nfunction endsWithHyphen(v: string) {\n return v.charCodeAt(v.length - 1) === 45 /* - */\n}\n\nfunction isValidIdentifier(v: string) {\n // Note, since we already know that \"v\" only contains [a-zA-Z0-9-], we can\n // simplify the following regex by checking only the first char and presence\n // of \"-\".\n\n // return /^[a-zA-Z][a-zA-Z0-9]*$/.test(v)\n return !startsWithNumber(v) && !v.includes('-')\n}\n\n/**\n * @deprecated Use {@link ensureValidNsid} if you care about error details,\n * {@link parseNsid}/{@link NSID.parse} if you need the parsed segments, or\n * {@link isValidNsid} if you just want a boolean.\n */\nexport function ensureValidNsidRegex(nsid: string): asserts nsid is NsidString {\n const result = validateNsidRegex(nsid)\n if (!result.success) throw new InvalidNsidError(result.message)\n}\n\n/**\n * Regexp based validation that behaves identically to the previous code but\n * provides less detailed error messages (while being 20% to 50% faster).\n */\nexport function validateNsidRegex(value: string): ValidateResult<NsidString> {\n if (value.length > 253 + 1 + 63) {\n return {\n success: false,\n message: 'NSID is too long (317 chars max)',\n }\n }\n\n if (\n !/^[a-zA-Z](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?:\\.[a-zA-Z](?:[a-zA-Z0-9]{0,62})?)$/.test(\n value,\n )\n ) {\n return {\n success: false,\n message: \"NSID didn't validate via regex\",\n }\n }\n\n return {\n success: true,\n value: value as NsidString,\n }\n}\n\nexport class InvalidNsidError extends Error {}\n"]}
|
package/dist/recordkey.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
export declare
|
|
1
|
+
export type RecordKeyString = string;
|
|
2
|
+
export declare function ensureValidRecordKey(rkey: string): asserts rkey is RecordKeyString;
|
|
3
|
+
export declare function isValidRecordKey(rkey: string): rkey is RecordKeyString;
|
|
3
4
|
export declare class InvalidRecordKeyError extends Error {
|
|
4
5
|
}
|
|
5
6
|
//# sourceMappingURL=recordkey.d.ts.map
|
package/dist/recordkey.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordkey.d.ts","sourceRoot":"","sources":["../src/recordkey.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"recordkey.d.ts","sourceRoot":"","sources":["../src/recordkey.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,CAAA;AAmBpC,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,IAAI,eAAe,CAgBjC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,eAAe,CAOtE;AAED,qBAAa,qBAAsB,SAAQ,KAAK;CAAG"}
|
package/dist/recordkey.js
CHANGED
|
@@ -1,31 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InvalidRecordKeyError =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
exports.InvalidRecordKeyError = void 0;
|
|
4
|
+
exports.ensureValidRecordKey = ensureValidRecordKey;
|
|
5
|
+
exports.isValidRecordKey = isValidRecordKey;
|
|
6
|
+
const RECORD_KEY_MAX_LENGTH = 512;
|
|
7
|
+
const RECORD_KEY_MIN_LENGTH = 1;
|
|
8
|
+
const RECORD_KEY_INVALID_VALUES = new Set(['.', '..']);
|
|
9
|
+
const RECORD_KEY_REGEX = /^[a-zA-Z0-9_~.:-]{1,512}$/;
|
|
10
|
+
// https://atproto.com/specs/record-key#record-key-syntax
|
|
11
|
+
// Regardless of the type, Record Keys must fulfill some baseline syntax constraints:
|
|
12
|
+
// - restricted to a subset of ASCII characters -- the allowed characters are
|
|
13
|
+
// alphanumeric (A-Za-z0-9), period, dash, underscore, colon, or tilde (.-_:~)
|
|
14
|
+
// - must have at least 1 and at most 512 characters
|
|
15
|
+
// - the specific record key values . and .. are not allowed
|
|
16
|
+
// - must be a permissible part of repository MST path string (the above
|
|
17
|
+
// constraints satisfy this condition)
|
|
18
|
+
// - must be permissible to include in a path component of a URI (following
|
|
19
|
+
// RFC-3986, section 3.3). The above constraints satisfy this condition, by
|
|
20
|
+
// matching the "unreserved" characters allowed in generic URI paths.
|
|
21
|
+
function ensureValidRecordKey(rkey) {
|
|
22
|
+
if (rkey.length > RECORD_KEY_MAX_LENGTH ||
|
|
23
|
+
rkey.length < RECORD_KEY_MIN_LENGTH) {
|
|
24
|
+
throw new InvalidRecordKeyError(`record key must be ${RECORD_KEY_MIN_LENGTH} to ${RECORD_KEY_MAX_LENGTH} characters`);
|
|
11
25
|
}
|
|
12
|
-
if (
|
|
26
|
+
if (RECORD_KEY_INVALID_VALUES.has(rkey)) {
|
|
13
27
|
throw new InvalidRecordKeyError('record key can not be "." or ".."');
|
|
14
|
-
};
|
|
15
|
-
exports.ensureValidRecordKey = ensureValidRecordKey;
|
|
16
|
-
const isValidRecordKey = (rkey) => {
|
|
17
|
-
try {
|
|
18
|
-
(0, exports.ensureValidRecordKey)(rkey);
|
|
19
28
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
throw err;
|
|
29
|
+
// simple regex to enforce most constraints via just regex and length.
|
|
30
|
+
if (!RECORD_KEY_REGEX.test(rkey)) {
|
|
31
|
+
throw new InvalidRecordKeyError('record key syntax not valid (regex)');
|
|
25
32
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
}
|
|
34
|
+
function isValidRecordKey(rkey) {
|
|
35
|
+
return (rkey.length >= RECORD_KEY_MIN_LENGTH &&
|
|
36
|
+
rkey.length <= RECORD_KEY_MAX_LENGTH &&
|
|
37
|
+
RECORD_KEY_REGEX.test(rkey) &&
|
|
38
|
+
!RECORD_KEY_INVALID_VALUES.has(rkey));
|
|
39
|
+
}
|
|
29
40
|
class InvalidRecordKeyError extends Error {
|
|
30
41
|
}
|
|
31
42
|
exports.InvalidRecordKeyError = InvalidRecordKeyError;
|
package/dist/recordkey.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordkey.js","sourceRoot":"","sources":["../src/recordkey.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"recordkey.js","sourceRoot":"","sources":["../src/recordkey.ts"],"names":[],"mappings":";;;AAmBA,oDAkBC;AAED,4CAOC;AA5CD,MAAM,qBAAqB,GAAG,GAAG,CAAA;AACjC,MAAM,qBAAqB,GAAG,CAAC,CAAA;AAC/B,MAAM,yBAAyB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAA;AACtD,MAAM,gBAAgB,GAAG,2BAA2B,CAAA;AAEpD,yDAAyD;AACzD,qFAAqF;AACrF,6EAA6E;AAC7E,gFAAgF;AAChF,oDAAoD;AACpD,4DAA4D;AAC5D,wEAAwE;AACxE,wCAAwC;AACxC,2EAA2E;AAC3E,6EAA6E;AAC7E,uEAAuE;AAEvE,SAAgB,oBAAoB,CAClC,IAAY;IAEZ,IACE,IAAI,CAAC,MAAM,GAAG,qBAAqB;QACnC,IAAI,CAAC,MAAM,GAAG,qBAAqB,EACnC,CAAC;QACD,MAAM,IAAI,qBAAqB,CAC7B,sBAAsB,qBAAqB,OAAO,qBAAqB,aAAa,CACrF,CAAA;IACH,CAAC;IACD,IAAI,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,qBAAqB,CAAC,mCAAmC,CAAC,CAAA;IACtE,CAAC;IACD,sEAAsE;IACtE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,qBAAqB,CAAC,qCAAqC,CAAC,CAAA;IACxE,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,OAAO,CACL,IAAI,CAAC,MAAM,IAAI,qBAAqB;QACpC,IAAI,CAAC,MAAM,IAAI,qBAAqB;QACpC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;QAC3B,CAAC,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC,CACrC,CAAA;AACH,CAAC;AAED,MAAa,qBAAsB,SAAQ,KAAK;CAAG;AAAnD,sDAAmD","sourcesContent":["export type RecordKeyString = string\n\nconst RECORD_KEY_MAX_LENGTH = 512\nconst RECORD_KEY_MIN_LENGTH = 1\nconst RECORD_KEY_INVALID_VALUES = new Set(['.', '..'])\nconst RECORD_KEY_REGEX = /^[a-zA-Z0-9_~.:-]{1,512}$/\n\n// https://atproto.com/specs/record-key#record-key-syntax\n// Regardless of the type, Record Keys must fulfill some baseline syntax constraints:\n// - restricted to a subset of ASCII characters -- the allowed characters are\n// alphanumeric (A-Za-z0-9), period, dash, underscore, colon, or tilde (.-_:~)\n// - must have at least 1 and at most 512 characters\n// - the specific record key values . and .. are not allowed\n// - must be a permissible part of repository MST path string (the above\n// constraints satisfy this condition)\n// - must be permissible to include in a path component of a URI (following\n// RFC-3986, section 3.3). The above constraints satisfy this condition, by\n// matching the \"unreserved\" characters allowed in generic URI paths.\n\nexport function ensureValidRecordKey(\n rkey: string,\n): asserts rkey is RecordKeyString {\n if (\n rkey.length > RECORD_KEY_MAX_LENGTH ||\n rkey.length < RECORD_KEY_MIN_LENGTH\n ) {\n throw new InvalidRecordKeyError(\n `record key must be ${RECORD_KEY_MIN_LENGTH} to ${RECORD_KEY_MAX_LENGTH} characters`,\n )\n }\n if (RECORD_KEY_INVALID_VALUES.has(rkey)) {\n throw new InvalidRecordKeyError('record key can not be \".\" or \"..\"')\n }\n // simple regex to enforce most constraints via just regex and length.\n if (!RECORD_KEY_REGEX.test(rkey)) {\n throw new InvalidRecordKeyError('record key syntax not valid (regex)')\n }\n}\n\nexport function isValidRecordKey(rkey: string): rkey is RecordKeyString {\n return (\n rkey.length >= RECORD_KEY_MIN_LENGTH &&\n rkey.length <= RECORD_KEY_MAX_LENGTH &&\n RECORD_KEY_REGEX.test(rkey) &&\n !RECORD_KEY_INVALID_VALUES.has(rkey)\n )\n}\n\nexport class InvalidRecordKeyError extends Error {}\n"]}
|
package/dist/tid.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
export declare
|
|
1
|
+
export type TidString = string;
|
|
2
|
+
export declare function ensureValidTid(tid: string): asserts tid is TidString;
|
|
3
|
+
export declare function isValidTid(tid: string): tid is TidString;
|
|
3
4
|
export declare class InvalidTidError extends Error {
|
|
4
5
|
}
|
|
5
6
|
//# sourceMappingURL=tid.d.ts.map
|
package/dist/tid.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tid.d.ts","sourceRoot":"","sources":["../src/tid.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tid.d.ts","sourceRoot":"","sources":["../src/tid.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,CAAA;AAK9B,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,SAAS,CAQpE;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,SAAS,CAExD;AAED,qBAAa,eAAgB,SAAQ,KAAK;CAAG"}
|
package/dist/tid.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InvalidTidError =
|
|
3
|
+
exports.InvalidTidError = void 0;
|
|
4
|
+
exports.ensureValidTid = ensureValidTid;
|
|
5
|
+
exports.isValidTid = isValidTid;
|
|
4
6
|
const TID_LENGTH = 13;
|
|
5
7
|
const TID_REGEX = /^[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}$/;
|
|
6
|
-
|
|
8
|
+
function ensureValidTid(tid) {
|
|
7
9
|
if (tid.length !== TID_LENGTH) {
|
|
8
10
|
throw new InvalidTidError(`TID must be ${TID_LENGTH} characters`);
|
|
9
11
|
}
|
|
@@ -11,12 +13,10 @@ const ensureValidTid = (tid) => {
|
|
|
11
13
|
if (!TID_REGEX.test(tid)) {
|
|
12
14
|
throw new InvalidTidError('TID syntax not valid (regex)');
|
|
13
15
|
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const isValidTid = (tid) => {
|
|
16
|
+
}
|
|
17
|
+
function isValidTid(tid) {
|
|
17
18
|
return tid.length === TID_LENGTH && TID_REGEX.test(tid);
|
|
18
|
-
}
|
|
19
|
-
exports.isValidTid = isValidTid;
|
|
19
|
+
}
|
|
20
20
|
class InvalidTidError extends Error {
|
|
21
21
|
}
|
|
22
22
|
exports.InvalidTidError = InvalidTidError;
|
package/dist/tid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tid.js","sourceRoot":"","sources":["../src/tid.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"tid.js","sourceRoot":"","sources":["../src/tid.ts"],"names":[],"mappings":";;;AAKA,wCAQC;AAED,gCAEC;AAfD,MAAM,UAAU,GAAG,EAAE,CAAA;AACrB,MAAM,SAAS,GAAG,4DAA4D,CAAA;AAE9E,SAAgB,cAAc,CAAC,GAAW;IACxC,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,eAAe,CAAC,eAAe,UAAU,aAAa,CAAC,CAAA;IACnE,CAAC;IACD,sEAAsE;IACtE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,eAAe,CAAC,8BAA8B,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAC,GAAW;IACpC,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACzD,CAAC;AAED,MAAa,eAAgB,SAAQ,KAAK;CAAG;AAA7C,0CAA6C","sourcesContent":["export type TidString = string\n\nconst TID_LENGTH = 13\nconst TID_REGEX = /^[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}$/\n\nexport function ensureValidTid(tid: string): asserts tid is TidString {\n if (tid.length !== TID_LENGTH) {\n throw new InvalidTidError(`TID must be ${TID_LENGTH} characters`)\n }\n // simple regex to enforce most constraints via just regex and length.\n if (!TID_REGEX.test(tid)) {\n throw new InvalidTidError('TID syntax not valid (regex)')\n }\n}\n\nexport function isValidTid(tid: string): tid is TidString {\n return tid.length === TID_LENGTH && TID_REGEX.test(tid)\n}\n\nexport class InvalidTidError extends Error {}\n"]}
|
package/package.json
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DidString, ensureValidDidRegex } from './did.js'
|
|
2
|
+
import {
|
|
3
|
+
HandleString,
|
|
4
|
+
InvalidHandleError,
|
|
5
|
+
ensureValidHandleRegex,
|
|
6
|
+
} from './handle.js'
|
|
7
|
+
|
|
8
|
+
export type AtIdentifierString = DidString | HandleString
|
|
9
|
+
|
|
10
|
+
export function ensureValidAtIdentifier(
|
|
11
|
+
input: string,
|
|
12
|
+
): asserts input is AtIdentifierString {
|
|
13
|
+
try {
|
|
14
|
+
if (input.startsWith('did:')) {
|
|
15
|
+
ensureValidDidRegex(input)
|
|
16
|
+
} else {
|
|
17
|
+
ensureValidHandleRegex(input)
|
|
18
|
+
}
|
|
19
|
+
} catch (cause) {
|
|
20
|
+
throw new InvalidHandleError('Invalid DID or handle', { cause })
|
|
21
|
+
}
|
|
22
|
+
}
|