+82
src/user.ts
+82
src/user.ts
···
23
23
web: new WebDidDocumentResolver(),
24
24
},
25
25
});
26
+
27
+
/**
28
+
* given a valid url path string containing
29
+
* - `/` for seperating characters
30
+
* - a-zA-Z0-9 `-._~` as unreserved
31
+
* - `!$&'()*+,;=` as reserved but valid in paths
32
+
* - `:@` as neither reserved or unreserved but valid in paths
33
+
* - %XX where X are hex digits for percent encoding
34
+
*
35
+
* we need to consistently and bidirectionally convert it into a string containing the characters A-Z, a-z, 0-9, `.-_:~` for an atproto rkey
36
+
* A-Z a-z 0-9 are covered easily
37
+
* we can also take -._~ as they are also unreserved
38
+
* leaving : as a valid rkey character which looks nice for encoding
39
+
* the uppercase versions MUST be used to prevent ambiguity
40
+
* a colon which isnt followed by a valid character is an invalid rkey and should be ignored
41
+
* - `/` `::`
42
+
* - `%` `:~`
43
+
* - `!` `:21`
44
+
* - `$` `:24`
45
+
* - `&` `:26`
46
+
* - `'` `:27`
47
+
* - `(` `:28`
48
+
* - `)` `:29`
49
+
* - `*` `:2A`
50
+
* - `+` `:2B`
51
+
* - `,` `:2C`
52
+
* - `:` `:3A`
53
+
* - `;` `:3B`
54
+
* - `=` `:3D`
55
+
* - `@` `:40`
56
+
* @returns {string | undefined} undefined when input is invalid
57
+
*/
58
+
function urlToRkey(url: string): string | undefined {
59
+
// contains 0-9A-Za-z + special valid chars and / seperator. also can contain %XX with XX being hex
60
+
if (!url.match(/^([a-zA-Z0-9/\-._~!$&'()*+,;=:@]|(%[0-9a-fA-F]{2}))*$/gm))
61
+
return;
62
+
return (
63
+
url
64
+
// : replace is hoisted so it doesnt replace colons from elsewhere
65
+
.replaceAll(":", ":3A")
66
+
.replaceAll("/", "::")
67
+
.replaceAll("%", ":~")
68
+
.replaceAll("!", ":21")
69
+
.replaceAll("$", ":24")
70
+
.replaceAll("&", ":26")
71
+
.replaceAll("'", ":27")
72
+
.replaceAll("(", ":28")
73
+
.replaceAll(")", ":29")
74
+
.replaceAll("*", ":2A")
75
+
.replaceAll("+", ":2B")
76
+
.replaceAll(",", ":2C")
77
+
.replaceAll(";", ":3B")
78
+
.replaceAll("=", ":3D")
79
+
.replaceAll("@", ":40")
80
+
);
81
+
}
82
+
83
+
/**
84
+
* @see {@link urlToRkey} for rkey <=> url conversion syntax
85
+
* @returns {string | undefined} undefined when input is invalid
86
+
*/
87
+
function rkeyToUrl(rkey: string): string | undefined {
88
+
// contains 0-9A-Za-z .-_:~
89
+
if (!rkey.match(/^[A-Za-z0-9.\-_:~]*$/gm)) return;
90
+
return rkey
91
+
.replaceAll("::", "/")
92
+
.replaceAll(":~", "%")
93
+
.replaceAll(":21", "!")
94
+
.replaceAll(":24", "$")
95
+
.replaceAll(":26", "&")
96
+
.replaceAll(":27", "'")
97
+
.replaceAll(":28", "(")
98
+
.replaceAll(":29", ")")
99
+
.replaceAll(":2A", "*")
100
+
.replaceAll(":2B", "+")
101
+
.replaceAll(":2C", ",")
102
+
.replaceAll(":3A", ":")
103
+
.replaceAll(":3B", ";")
104
+
.replaceAll(":3D", "=")
105
+
.replaceAll(":40", "@");
106
+
}
107
+
26
108
async function getRoute(
27
109
did: `did:${"plc" | "web"}:${string}`,
28
110
pds: string,