@atproto/did 0.1.0
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 +7 -0
- package/LICENSE.txt +7 -0
- package/dist/did-document.d.ts +335 -0
- package/dist/did-document.d.ts.map +1 -0
- package/dist/did-document.js +135 -0
- package/dist/did-document.js.map +1 -0
- package/dist/did-error.d.ts +16 -0
- package/dist/did-error.d.ts.map +1 -0
- package/dist/did-error.js +58 -0
- package/dist/did-error.js.map +1 -0
- package/dist/did.d.ts +56 -0
- package/dist/did.d.ts.map +1 -0
- package/dist/did.js +148 -0
- package/dist/did.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/methods/plc.d.ts +6 -0
- package/dist/methods/plc.d.ts.map +1 -0
- package/dist/methods/plc.js +38 -0
- package/dist/methods/plc.js.map +1 -0
- package/dist/methods/web.d.ts +16 -0
- package/dist/methods/web.d.ts.map +1 -0
- package/dist/methods/web.js +74 -0
- package/dist/methods/web.js.map +1 -0
- package/dist/methods.d.ts +3 -0
- package/dist/methods.d.ts.map +1 -0
- package/dist/methods.js +19 -0
- package/dist/methods.js.map +1 -0
- package/package.json +36 -0
- package/src/did-document.ts +151 -0
- package/src/did-error.ts +49 -0
- package/src/did.ts +258 -0
- package/src/index.ts +4 -0
- package/src/methods/plc.ts +40 -0
- package/src/methods/web.ts +78 -0
- package/src/methods.ts +2 -0
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +4 -0
package/dist/did.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.didSchema = exports.isDid = exports.checkDid = exports.checkDidMsid = exports.extractDidMethod = exports.checkDidMethod = exports.DID_PREFIX = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const did_error_js_1 = require("./did-error.js");
|
|
6
|
+
const DID_PREFIX = 'did:';
|
|
7
|
+
exports.DID_PREFIX = DID_PREFIX;
|
|
8
|
+
const DID_PREFIX_LENGTH = DID_PREFIX.length;
|
|
9
|
+
/**
|
|
10
|
+
* DID Method-name check function.
|
|
11
|
+
*
|
|
12
|
+
* Check if the input is a valid DID method name, at the position between
|
|
13
|
+
* `start` (inclusive) and `end` (exclusive).
|
|
14
|
+
*/
|
|
15
|
+
function checkDidMethod(input, start = 0, end = input.length) {
|
|
16
|
+
if (!Number.isFinite(end) ||
|
|
17
|
+
!Number.isFinite(start) ||
|
|
18
|
+
end < start ||
|
|
19
|
+
end > input.length) {
|
|
20
|
+
throw new TypeError('Invalid start or end position');
|
|
21
|
+
}
|
|
22
|
+
if (end === start) {
|
|
23
|
+
throw new did_error_js_1.InvalidDidError(input, `Empty method name`);
|
|
24
|
+
}
|
|
25
|
+
let c;
|
|
26
|
+
for (let i = start; i < end; i++) {
|
|
27
|
+
c = input.charCodeAt(i);
|
|
28
|
+
if ((c < 0x61 || c > 0x7a) && // a-z
|
|
29
|
+
(c < 0x30 || c > 0x39) // 0-9
|
|
30
|
+
) {
|
|
31
|
+
throw new did_error_js_1.InvalidDidError(input, `Invalid character at position ${i} in DID method name`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.checkDidMethod = checkDidMethod;
|
|
36
|
+
/**
|
|
37
|
+
* This method assumes the input is a valid Did
|
|
38
|
+
*/
|
|
39
|
+
function extractDidMethod(did) {
|
|
40
|
+
const msidSep = did.indexOf(':', DID_PREFIX_LENGTH);
|
|
41
|
+
const method = did.slice(DID_PREFIX_LENGTH, msidSep);
|
|
42
|
+
return method;
|
|
43
|
+
}
|
|
44
|
+
exports.extractDidMethod = extractDidMethod;
|
|
45
|
+
/**
|
|
46
|
+
* DID Method-specific identifier check function.
|
|
47
|
+
*
|
|
48
|
+
* Check if the input is a valid DID method-specific identifier, at the position
|
|
49
|
+
* between `start` (inclusive) and `end` (exclusive).
|
|
50
|
+
*/
|
|
51
|
+
function checkDidMsid(input, start = 0, end = input.length) {
|
|
52
|
+
if (!Number.isFinite(end) ||
|
|
53
|
+
!Number.isFinite(start) ||
|
|
54
|
+
end < start ||
|
|
55
|
+
end > input.length) {
|
|
56
|
+
throw new TypeError('Invalid start or end position');
|
|
57
|
+
}
|
|
58
|
+
if (end === start) {
|
|
59
|
+
throw new did_error_js_1.InvalidDidError(input, `DID method-specific id must not be empty`);
|
|
60
|
+
}
|
|
61
|
+
let c;
|
|
62
|
+
for (let i = start; i < end; i++) {
|
|
63
|
+
c = input.charCodeAt(i);
|
|
64
|
+
// Check for frequent chars first
|
|
65
|
+
if ((c < 0x61 || c > 0x7a) && // a-z
|
|
66
|
+
(c < 0x41 || c > 0x5a) && // A-Z
|
|
67
|
+
(c < 0x30 || c > 0x39) && // 0-9
|
|
68
|
+
c !== 0x2e && // .
|
|
69
|
+
c !== 0x2d && // -
|
|
70
|
+
c !== 0x5f // _
|
|
71
|
+
) {
|
|
72
|
+
// Less frequent chars are checked here
|
|
73
|
+
// ":"
|
|
74
|
+
if (c === 0x3a) {
|
|
75
|
+
if (i === end - 1) {
|
|
76
|
+
throw new did_error_js_1.InvalidDidError(input, `DID cannot end with ":"`);
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
// pct-encoded
|
|
81
|
+
if (c === 0x25) {
|
|
82
|
+
c = input.charCodeAt(++i);
|
|
83
|
+
if ((c < 0x30 || c > 0x39) && (c < 0x41 || c > 0x46)) {
|
|
84
|
+
throw new did_error_js_1.InvalidDidError(input, `Invalid pct-encoded character at position ${i}`);
|
|
85
|
+
}
|
|
86
|
+
c = input.charCodeAt(++i);
|
|
87
|
+
if ((c < 0x30 || c > 0x39) && (c < 0x41 || c > 0x46)) {
|
|
88
|
+
throw new did_error_js_1.InvalidDidError(input, `Invalid pct-encoded character at position ${i}`);
|
|
89
|
+
}
|
|
90
|
+
// There must always be 2 HEXDIG after a "%"
|
|
91
|
+
if (i >= end) {
|
|
92
|
+
throw new did_error_js_1.InvalidDidError(input, `Incomplete pct-encoded character at position ${i - 2}`);
|
|
93
|
+
}
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
throw new did_error_js_1.InvalidDidError(input, `Disallowed character in DID at position ${i}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.checkDidMsid = checkDidMsid;
|
|
101
|
+
function checkDid(input) {
|
|
102
|
+
if (typeof input !== 'string') {
|
|
103
|
+
throw new did_error_js_1.InvalidDidError(typeof input, `DID must be a string`);
|
|
104
|
+
}
|
|
105
|
+
const { length } = input;
|
|
106
|
+
if (length > 2048) {
|
|
107
|
+
throw new did_error_js_1.InvalidDidError(input, `DID is too long (2048 chars max)`);
|
|
108
|
+
}
|
|
109
|
+
if (!input.startsWith(DID_PREFIX)) {
|
|
110
|
+
throw new did_error_js_1.InvalidDidError(input, `DID requires "${DID_PREFIX}" prefix`);
|
|
111
|
+
}
|
|
112
|
+
const idSep = input.indexOf(':', DID_PREFIX_LENGTH);
|
|
113
|
+
if (idSep === -1) {
|
|
114
|
+
throw new did_error_js_1.InvalidDidError(input, `Missing colon after method name`);
|
|
115
|
+
}
|
|
116
|
+
checkDidMethod(input, DID_PREFIX_LENGTH, idSep);
|
|
117
|
+
checkDidMsid(input, idSep + 1, length);
|
|
118
|
+
}
|
|
119
|
+
exports.checkDid = checkDid;
|
|
120
|
+
function isDid(input) {
|
|
121
|
+
try {
|
|
122
|
+
checkDid(input);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
if (err instanceof did_error_js_1.DidError) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.isDid = isDid;
|
|
133
|
+
exports.didSchema = zod_1.z
|
|
134
|
+
.string()
|
|
135
|
+
.superRefine((value, ctx) => {
|
|
136
|
+
try {
|
|
137
|
+
checkDid(value);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
ctx.addIssue({
|
|
142
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
143
|
+
message: err instanceof Error ? err.message : 'Unexpected error',
|
|
144
|
+
});
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=did.js.map
|
package/dist/did.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did.js","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,cAAc,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./did-document.js"), exports);
|
|
18
|
+
__exportStar(require("./did-error.js"), exports);
|
|
19
|
+
__exportStar(require("./did.js"), exports);
|
|
20
|
+
__exportStar(require("./methods.js"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAiC;AACjC,iDAA8B;AAC9B,2CAAwB;AACxB,+CAA4B"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Did } from '../did.js';
|
|
2
|
+
declare const DID_PLC_PREFIX = "did:plc:";
|
|
3
|
+
export { DID_PLC_PREFIX };
|
|
4
|
+
export declare function isDidPlc(input: unknown): input is Did<'plc'>;
|
|
5
|
+
export declare function checkDidPlc(input: string): asserts input is Did<'plc'>;
|
|
6
|
+
//# sourceMappingURL=plc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plc.d.ts","sourceRoot":"","sources":["../../src/methods/plc.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAE/B,QAAA,MAAM,cAAc,aAAa,CAAA;AAIjC,OAAO,EAAE,cAAc,EAAE,CAAA;AAEzB,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,CAQ5D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,CAoBtE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkDidPlc = exports.isDidPlc = exports.DID_PLC_PREFIX = void 0;
|
|
4
|
+
const did_error_js_1 = require("../did-error.js");
|
|
5
|
+
const DID_PLC_PREFIX = `did:plc:`;
|
|
6
|
+
exports.DID_PLC_PREFIX = DID_PLC_PREFIX;
|
|
7
|
+
const DID_PLC_PREFIX_LENGTH = DID_PLC_PREFIX.length;
|
|
8
|
+
const DID_PLC_LENGTH = 32;
|
|
9
|
+
function isDidPlc(input) {
|
|
10
|
+
if (typeof input !== 'string')
|
|
11
|
+
return false;
|
|
12
|
+
try {
|
|
13
|
+
checkDidPlc(input);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.isDidPlc = isDidPlc;
|
|
21
|
+
function checkDidPlc(input) {
|
|
22
|
+
if (input.length !== DID_PLC_LENGTH) {
|
|
23
|
+
throw new did_error_js_1.InvalidDidError(input, `did:plc must be ${DID_PLC_LENGTH} characters long`);
|
|
24
|
+
}
|
|
25
|
+
if (!input.startsWith(DID_PLC_PREFIX)) {
|
|
26
|
+
throw new did_error_js_1.InvalidDidError(input, `Invalid did:plc prefix`);
|
|
27
|
+
}
|
|
28
|
+
let c;
|
|
29
|
+
for (let i = DID_PLC_PREFIX_LENGTH; i < DID_PLC_LENGTH; i++) {
|
|
30
|
+
c = input.charCodeAt(i);
|
|
31
|
+
// Base32 encoding ([a-z2-7])
|
|
32
|
+
if ((c < 0x61 || c > 0x7a) && (c < 0x32 || c > 0x37)) {
|
|
33
|
+
throw new did_error_js_1.InvalidDidError(input, `Invalid character at position ${i}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.checkDidPlc = checkDidPlc;
|
|
38
|
+
//# sourceMappingURL=plc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plc.js","sourceRoot":"","sources":["../../src/methods/plc.ts"],"names":[],"mappings":";;;AAAA,kDAAiD;AAGjD,MAAM,cAAc,GAAG,UAAU,CAAA;AAIxB,wCAAc;AAHvB,MAAM,qBAAqB,GAAG,cAAc,CAAC,MAAM,CAAA;AACnD,MAAM,cAAc,GAAG,EAAE,CAAA;AAIzB,SAAgB,QAAQ,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3C,IAAI,CAAC;QACH,WAAW,CAAC,KAAK,CAAC,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AARD,4BAQC;AAED,SAAgB,WAAW,CAAC,KAAa;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACpC,MAAM,IAAI,8BAAe,CACvB,KAAK,EACL,mBAAmB,cAAc,kBAAkB,CACpD,CAAA;IACH,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,8BAAe,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,CAAS,CAAA;IACb,KAAK,IAAI,CAAC,GAAG,qBAAqB,EAAE,CAAC,GAAG,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5D,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QACvB,6BAA6B;QAC7B,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,8BAAe,CAAC,KAAK,EAAE,iCAAiC,CAAC,EAAE,CAAC,CAAA;QACxE,CAAC;IACH,CAAC;AACH,CAAC;AApBD,kCAoBC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Did } from '../did.js';
|
|
2
|
+
export declare const DID_WEB_PREFIX = "did:web:";
|
|
3
|
+
/**
|
|
4
|
+
* This function checks if the input is a valid Web DID, as per DID spec.
|
|
5
|
+
* ATPROTO adds additional constraints to allowed DID values for the `did:web`
|
|
6
|
+
* method. Use {@link isAtprotoDidWeb} if that's what you need.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isDidWeb(input: unknown): input is Did<'web'>;
|
|
9
|
+
/**
|
|
10
|
+
* @see {@link https://atproto.com/specs/did#blessed-did-methods}
|
|
11
|
+
*/
|
|
12
|
+
export declare function isAtprotoDidWeb(input: unknown): input is Did<'web'>;
|
|
13
|
+
export declare function checkDidWeb(input: string): asserts input is Did<'web'>;
|
|
14
|
+
export declare function didWebToUrl(did: string): URL;
|
|
15
|
+
export declare function urlToDidWeb(url: URL): Did<'web'>;
|
|
16
|
+
//# sourceMappingURL=web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/methods/web.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAgB,MAAM,WAAW,CAAA;AAE7C,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,CAQ5D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,CAoBnE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,CAEtE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAmB5C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAOhD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.urlToDidWeb = exports.didWebToUrl = exports.checkDidWeb = exports.isAtprotoDidWeb = exports.isDidWeb = exports.DID_WEB_PREFIX = void 0;
|
|
4
|
+
const did_error_js_1 = require("../did-error.js");
|
|
5
|
+
const did_js_1 = require("../did.js");
|
|
6
|
+
exports.DID_WEB_PREFIX = `did:web:`;
|
|
7
|
+
/**
|
|
8
|
+
* This function checks if the input is a valid Web DID, as per DID spec.
|
|
9
|
+
* ATPROTO adds additional constraints to allowed DID values for the `did:web`
|
|
10
|
+
* method. Use {@link isAtprotoDidWeb} if that's what you need.
|
|
11
|
+
*/
|
|
12
|
+
function isDidWeb(input) {
|
|
13
|
+
if (typeof input !== 'string')
|
|
14
|
+
return false;
|
|
15
|
+
try {
|
|
16
|
+
didWebToUrl(input);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.isDidWeb = isDidWeb;
|
|
24
|
+
/**
|
|
25
|
+
* @see {@link https://atproto.com/specs/did#blessed-did-methods}
|
|
26
|
+
*/
|
|
27
|
+
function isAtprotoDidWeb(input) {
|
|
28
|
+
// Optimization: make cheap checks first
|
|
29
|
+
if (typeof input !== 'string') {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
// Path are not allowed
|
|
33
|
+
if (input.includes(':', exports.DID_WEB_PREFIX.length)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// Port numbers are not allowed, except for localhost
|
|
37
|
+
if (input.includes('%3A', exports.DID_WEB_PREFIX.length) &&
|
|
38
|
+
!input.startsWith('did:web:localhost%3A')) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return isDidWeb(input);
|
|
42
|
+
}
|
|
43
|
+
exports.isAtprotoDidWeb = isAtprotoDidWeb;
|
|
44
|
+
function checkDidWeb(input) {
|
|
45
|
+
didWebToUrl(input);
|
|
46
|
+
}
|
|
47
|
+
exports.checkDidWeb = checkDidWeb;
|
|
48
|
+
function didWebToUrl(did) {
|
|
49
|
+
if (!did.startsWith(exports.DID_WEB_PREFIX)) {
|
|
50
|
+
throw new did_error_js_1.InvalidDidError(did, `did:web must start with ${exports.DID_WEB_PREFIX}`);
|
|
51
|
+
}
|
|
52
|
+
if (did.charAt(exports.DID_WEB_PREFIX.length) === ':') {
|
|
53
|
+
throw new did_error_js_1.InvalidDidError(did, 'did:web MSID must not start with a colon');
|
|
54
|
+
}
|
|
55
|
+
// Make sure every char is valid (per DID spec)
|
|
56
|
+
(0, did_js_1.checkDidMsid)(did, exports.DID_WEB_PREFIX.length);
|
|
57
|
+
try {
|
|
58
|
+
const msid = did.slice(exports.DID_WEB_PREFIX.length);
|
|
59
|
+
const parts = msid.split(':').map(decodeURIComponent);
|
|
60
|
+
return new URL(`https://${parts.join('/')}`);
|
|
61
|
+
}
|
|
62
|
+
catch (cause) {
|
|
63
|
+
throw new did_error_js_1.InvalidDidError(did, 'Invalid Web DID', cause);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.didWebToUrl = didWebToUrl;
|
|
67
|
+
function urlToDidWeb(url) {
|
|
68
|
+
const path = url.pathname === '/'
|
|
69
|
+
? ''
|
|
70
|
+
: url.pathname.slice(1).split('/').map(encodeURIComponent).join(':');
|
|
71
|
+
return `did:web:${encodeURIComponent(url.host)}${path ? `:${path}` : ''}`;
|
|
72
|
+
}
|
|
73
|
+
exports.urlToDidWeb = urlToDidWeb;
|
|
74
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/methods/web.ts"],"names":[],"mappings":";;;AAAA,kDAAiD;AACjD,sCAA6C;AAEhC,QAAA,cAAc,GAAG,UAAU,CAAA;AAExC;;;;GAIG;AACH,SAAgB,QAAQ,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3C,IAAI,CAAC;QACH,WAAW,CAAC,KAAK,CAAC,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AARD,4BAQC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,KAAc;IAC5C,wCAAwC;IACxC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,uBAAuB;IACvB,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,sBAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,qDAAqD;IACrD,IACE,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,sBAAc,CAAC,MAAM,CAAC;QAC5C,CAAC,KAAK,CAAC,UAAU,CAAC,sBAAsB,CAAC,EACzC,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC;AApBD,0CAoBC;AAED,SAAgB,WAAW,CAAC,KAAa;IACvC,WAAW,CAAC,KAAK,CAAC,CAAA;AACpB,CAAC;AAFD,kCAEC;AAED,SAAgB,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,sBAAc,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,8BAAe,CAAC,GAAG,EAAE,2BAA2B,sBAAc,EAAE,CAAC,CAAA;IAC7E,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,CAAC,sBAAc,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;QAC9C,MAAM,IAAI,8BAAe,CAAC,GAAG,EAAE,0CAA0C,CAAC,CAAA;IAC5E,CAAC;IAED,+CAA+C;IAC/C,IAAA,qBAAY,EAAC,GAAG,EAAE,sBAAc,CAAC,MAAM,CAAC,CAAA;IAExC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,sBAAc,CAAC,MAAM,CAAC,CAAA;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;QACrD,OAAO,IAAI,GAAG,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,8BAAe,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,CAAC,CAAA;IAC1D,CAAC;AACH,CAAC;AAnBD,kCAmBC;AAED,SAAgB,WAAW,CAAC,GAAQ;IAClC,MAAM,IAAI,GACR,GAAG,CAAC,QAAQ,KAAK,GAAG;QAClB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAExE,OAAO,WAAW,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;AAC3E,CAAC;AAPD,kCAOC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.d.ts","sourceRoot":"","sources":["../src/methods.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA"}
|
package/dist/methods.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./methods/plc.js"), exports);
|
|
18
|
+
__exportStar(require("./methods/web.js"), exports);
|
|
19
|
+
//# sourceMappingURL=methods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.js","sourceRoot":"","sources":["../src/methods.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAgC;AAChC,mDAAgC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atproto/did",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "DID resolution and verification library",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"atproto",
|
|
8
|
+
"did",
|
|
9
|
+
"validation",
|
|
10
|
+
"types"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://atproto.com",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/bluesky-social/atproto",
|
|
16
|
+
"directory": "packages/did"
|
|
17
|
+
},
|
|
18
|
+
"type": "commonjs",
|
|
19
|
+
"main": "dist/index.js",
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"default": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"zod": "^3.23.8"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"typescript": "^5.3.3"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc --build tsconfig.build.json"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { Did, didSchema } from './did.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* RFC3968 compliant URI
|
|
7
|
+
*
|
|
8
|
+
* @see {@link https://www.rfc-editor.org/rfc/rfc3986}
|
|
9
|
+
*/
|
|
10
|
+
const rfc3968UriSchema = z.string().refine((data) => {
|
|
11
|
+
try {
|
|
12
|
+
new URL(data)
|
|
13
|
+
return true
|
|
14
|
+
} catch {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
}, 'RFC3968 compliant URI')
|
|
18
|
+
|
|
19
|
+
const didControllerSchema = z.union([didSchema, z.array(didSchema)])
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @note this schema might be too permissive
|
|
23
|
+
*/
|
|
24
|
+
const didRelativeUriSchema = z.union([
|
|
25
|
+
rfc3968UriSchema,
|
|
26
|
+
z.string().regex(/^#[^#]+$/),
|
|
27
|
+
])
|
|
28
|
+
|
|
29
|
+
const didVerificationMethodSchema = z.object({
|
|
30
|
+
id: didRelativeUriSchema,
|
|
31
|
+
type: z.string().min(1),
|
|
32
|
+
controller: didControllerSchema,
|
|
33
|
+
publicKeyJwk: z.record(z.string(), z.unknown()).optional(),
|
|
34
|
+
publicKeyMultibase: z.string().optional(),
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The value of the id property MUST be a URI conforming to [RFC3986]. A
|
|
39
|
+
* conforming producer MUST NOT produce multiple service entries with the same
|
|
40
|
+
* id. A conforming consumer MUST produce an error if it detects multiple
|
|
41
|
+
* service entries with the same id.
|
|
42
|
+
*
|
|
43
|
+
* @note Normally, only rfc3968UriSchema should be allowed here. However, the
|
|
44
|
+
* did:plc uses relative URI. For this reason, we also allow relative URIs
|
|
45
|
+
* here.
|
|
46
|
+
*/
|
|
47
|
+
const didServiceIdSchema = didRelativeUriSchema
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The value of the type property MUST be a string or a set of strings. In order
|
|
51
|
+
* to maximize interoperability, the service type and its associated properties
|
|
52
|
+
* SHOULD be registered in the DID Specification Registries
|
|
53
|
+
* [DID-SPEC-REGISTRIES].
|
|
54
|
+
*/
|
|
55
|
+
const didServiceTypeSchema = z.union([z.string(), z.array(z.string())])
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The value of the serviceEndpoint property MUST be a string, a map, or a set
|
|
59
|
+
* composed of one or more strings and/or maps. All string values MUST be valid
|
|
60
|
+
* URIs conforming to [RFC3986] and normalized according to the Normalization
|
|
61
|
+
* and Comparison rules in RFC3986 and to any normalization rules in its
|
|
62
|
+
* applicable URI scheme specification.
|
|
63
|
+
*/
|
|
64
|
+
const didServiceEndpointSchema = z.union([
|
|
65
|
+
rfc3968UriSchema,
|
|
66
|
+
z.record(z.string(), rfc3968UriSchema),
|
|
67
|
+
z
|
|
68
|
+
.array(z.union([rfc3968UriSchema, z.record(z.string(), rfc3968UriSchema)]))
|
|
69
|
+
.nonempty(),
|
|
70
|
+
])
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Each service map MUST contain id, type, and serviceEndpoint properties.
|
|
74
|
+
* @see {@link https://www.w3.org/TR/did-core/#services}
|
|
75
|
+
*/
|
|
76
|
+
const didServiceSchema = z.object({
|
|
77
|
+
id: didServiceIdSchema,
|
|
78
|
+
type: didServiceTypeSchema,
|
|
79
|
+
serviceEndpoint: didServiceEndpointSchema,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
export type DidService = z.infer<typeof didServiceSchema>
|
|
83
|
+
|
|
84
|
+
const didAuthenticationSchema = z.union([
|
|
85
|
+
//
|
|
86
|
+
didRelativeUriSchema,
|
|
87
|
+
didVerificationMethodSchema,
|
|
88
|
+
])
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @note This schema is incomplete
|
|
92
|
+
* @see {@link https://www.w3.org/TR/did-core/#production-0}
|
|
93
|
+
*/
|
|
94
|
+
export const didDocumentSchema = z.object({
|
|
95
|
+
'@context': z.union([
|
|
96
|
+
z.literal('https://www.w3.org/ns/did/v1'),
|
|
97
|
+
z
|
|
98
|
+
.array(z.string().url())
|
|
99
|
+
.nonempty()
|
|
100
|
+
.refine((data) => data[0] === 'https://www.w3.org/ns/did/v1', {
|
|
101
|
+
message: 'First @context must be https://www.w3.org/ns/did/v1',
|
|
102
|
+
}),
|
|
103
|
+
]),
|
|
104
|
+
id: didSchema,
|
|
105
|
+
controller: didControllerSchema.optional(),
|
|
106
|
+
alsoKnownAs: z.array(rfc3968UriSchema).optional(),
|
|
107
|
+
service: z.array(didServiceSchema).optional(),
|
|
108
|
+
authentication: z.array(didAuthenticationSchema).optional(),
|
|
109
|
+
verificationMethod: z
|
|
110
|
+
.array(z.union([didVerificationMethodSchema, didRelativeUriSchema]))
|
|
111
|
+
.optional(),
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
export type DidDocument<Method extends string = string> = z.infer<
|
|
115
|
+
typeof didDocumentSchema
|
|
116
|
+
> & { id: Did<Method> }
|
|
117
|
+
|
|
118
|
+
// @TODO: add other refinements ?
|
|
119
|
+
export const didDocumentValidator = didDocumentSchema
|
|
120
|
+
.superRefine((data, ctx) => {
|
|
121
|
+
if (data.service) {
|
|
122
|
+
for (let i = 0; i < data.service.length; i++) {
|
|
123
|
+
if (data.service[i].id === data.id) {
|
|
124
|
+
ctx.addIssue({
|
|
125
|
+
code: z.ZodIssueCode.custom,
|
|
126
|
+
message: `Service id must be different from the document id`,
|
|
127
|
+
path: ['service', i, 'id'],
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
.superRefine((data, ctx) => {
|
|
134
|
+
if (data.service) {
|
|
135
|
+
const normalizedIds = data.service.map((s) =>
|
|
136
|
+
s.id?.startsWith('#') ? `${data.id}${s.id}` : s.id,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
for (let i = 0; i < normalizedIds.length; i++) {
|
|
140
|
+
for (let j = i + 1; j < normalizedIds.length; j++) {
|
|
141
|
+
if (normalizedIds[i] === normalizedIds[j]) {
|
|
142
|
+
ctx.addIssue({
|
|
143
|
+
code: z.ZodIssueCode.custom,
|
|
144
|
+
message: `Duplicate service id (${normalizedIds[j]}) found in the document`,
|
|
145
|
+
path: ['service', j, 'id'],
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
})
|
package/src/did-error.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export class DidError extends Error {
|
|
2
|
+
constructor(
|
|
3
|
+
public readonly did: string,
|
|
4
|
+
message: string,
|
|
5
|
+
public readonly code: string,
|
|
6
|
+
public readonly status = 400,
|
|
7
|
+
cause?: unknown,
|
|
8
|
+
) {
|
|
9
|
+
super(message, { cause })
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* For compatibility with error handlers in common HTTP frameworks.
|
|
14
|
+
*/
|
|
15
|
+
get statusCode() {
|
|
16
|
+
return this.status
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override toString() {
|
|
20
|
+
return `${this.constructor.name} ${this.code} (${this.did}): ${this.message}`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static from(cause: unknown, did: string): DidError {
|
|
24
|
+
if (cause instanceof DidError) {
|
|
25
|
+
return cause
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const message =
|
|
29
|
+
cause instanceof Error
|
|
30
|
+
? cause.message
|
|
31
|
+
: typeof cause === 'string'
|
|
32
|
+
? cause
|
|
33
|
+
: 'An unknown error occurred'
|
|
34
|
+
|
|
35
|
+
const status =
|
|
36
|
+
(typeof cause?.['statusCode'] === 'number'
|
|
37
|
+
? cause['statusCode']
|
|
38
|
+
: undefined) ??
|
|
39
|
+
(typeof cause?.['status'] === 'number' ? cause['status'] : undefined)
|
|
40
|
+
|
|
41
|
+
return new DidError(did, message, 'did-unknown-error', status, cause)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class InvalidDidError extends DidError {
|
|
46
|
+
constructor(did: string, message: string, cause?: unknown) {
|
|
47
|
+
super(did, message, 'did-invalid', 400, cause)
|
|
48
|
+
}
|
|
49
|
+
}
|