@graffiti-garden/implementation-decentralized 0.0.1
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/LICENSE +674 -0
- package/dist/1-services/1-authorization.d.ts +37 -0
- package/dist/1-services/1-authorization.d.ts.map +1 -0
- package/dist/1-services/2-dids-tests.d.ts +2 -0
- package/dist/1-services/2-dids-tests.d.ts.map +1 -0
- package/dist/1-services/2-dids.d.ts +9 -0
- package/dist/1-services/2-dids.d.ts.map +1 -0
- package/dist/1-services/3-storage-buckets-tests.d.ts +2 -0
- package/dist/1-services/3-storage-buckets-tests.d.ts.map +1 -0
- package/dist/1-services/3-storage-buckets.d.ts +11 -0
- package/dist/1-services/3-storage-buckets.d.ts.map +1 -0
- package/dist/1-services/4-inboxes-tests.d.ts +2 -0
- package/dist/1-services/4-inboxes-tests.d.ts.map +1 -0
- package/dist/1-services/4-inboxes.d.ts +87 -0
- package/dist/1-services/4-inboxes.d.ts.map +1 -0
- package/dist/1-services/utilities.d.ts +7 -0
- package/dist/1-services/utilities.d.ts.map +1 -0
- package/dist/2-primitives/1-string-encoding-tests.d.ts +2 -0
- package/dist/2-primitives/1-string-encoding-tests.d.ts.map +1 -0
- package/dist/2-primitives/1-string-encoding.d.ts +6 -0
- package/dist/2-primitives/1-string-encoding.d.ts.map +1 -0
- package/dist/2-primitives/2-content-addresses-tests.d.ts +2 -0
- package/dist/2-primitives/2-content-addresses-tests.d.ts.map +1 -0
- package/dist/2-primitives/2-content-addresses.d.ts +8 -0
- package/dist/2-primitives/2-content-addresses.d.ts.map +1 -0
- package/dist/2-primitives/3-channel-attestations-tests.d.ts +2 -0
- package/dist/2-primitives/3-channel-attestations-tests.d.ts.map +1 -0
- package/dist/2-primitives/3-channel-attestations.d.ts +13 -0
- package/dist/2-primitives/3-channel-attestations.d.ts.map +1 -0
- package/dist/2-primitives/4-allowed-attestations-tests.d.ts +2 -0
- package/dist/2-primitives/4-allowed-attestations-tests.d.ts.map +1 -0
- package/dist/2-primitives/4-allowed-attestations.d.ts +9 -0
- package/dist/2-primitives/4-allowed-attestations.d.ts.map +1 -0
- package/dist/3-protocol/1-sessions.d.ts +81 -0
- package/dist/3-protocol/1-sessions.d.ts.map +1 -0
- package/dist/3-protocol/2-handles-tests.d.ts +2 -0
- package/dist/3-protocol/2-handles-tests.d.ts.map +1 -0
- package/dist/3-protocol/2-handles.d.ts +13 -0
- package/dist/3-protocol/2-handles.d.ts.map +1 -0
- package/dist/3-protocol/3-object-encoding-tests.d.ts +2 -0
- package/dist/3-protocol/3-object-encoding-tests.d.ts.map +1 -0
- package/dist/3-protocol/3-object-encoding.d.ts +43 -0
- package/dist/3-protocol/3-object-encoding.d.ts.map +1 -0
- package/dist/3-protocol/4-graffiti.d.ts +79 -0
- package/dist/3-protocol/4-graffiti.d.ts.map +1 -0
- package/dist/3-protocol/login-dialog.html.d.ts +2 -0
- package/dist/3-protocol/login-dialog.html.d.ts.map +1 -0
- package/dist/browser/ajv-QBSREQSI.js +9 -0
- package/dist/browser/ajv-QBSREQSI.js.map +7 -0
- package/dist/browser/build-BXWPS7VK.js +2 -0
- package/dist/browser/build-BXWPS7VK.js.map +7 -0
- package/dist/browser/chunk-RFBBAUMM.js +2 -0
- package/dist/browser/chunk-RFBBAUMM.js.map +7 -0
- package/dist/browser/graffiti-KV3G3O72-URO7SJIJ.js +2 -0
- package/dist/browser/graffiti-KV3G3O72-URO7SJIJ.js.map +7 -0
- package/dist/browser/index.js +16 -0
- package/dist/browser/index.js.map +7 -0
- package/dist/browser/login-dialog.html-XUWYDNNI.js +44 -0
- package/dist/browser/login-dialog.html-XUWYDNNI.js.map +7 -0
- package/dist/browser/rock-salt-LI7DAH66-KPFEBIBO.js +2 -0
- package/dist/browser/rock-salt-LI7DAH66-KPFEBIBO.js.map +7 -0
- package/dist/browser/style-YUTCEBZV-RWYJV575.js +287 -0
- package/dist/browser/style-YUTCEBZV-RWYJV575.js.map +7 -0
- package/dist/cjs/1-services/1-authorization.js +317 -0
- package/dist/cjs/1-services/1-authorization.js.map +7 -0
- package/dist/cjs/1-services/2-dids-tests.js +44 -0
- package/dist/cjs/1-services/2-dids-tests.js.map +7 -0
- package/dist/cjs/1-services/2-dids.js +47 -0
- package/dist/cjs/1-services/2-dids.js.map +7 -0
- package/dist/cjs/1-services/3-storage-buckets-tests.js +123 -0
- package/dist/cjs/1-services/3-storage-buckets-tests.js.map +7 -0
- package/dist/cjs/1-services/3-storage-buckets.js +148 -0
- package/dist/cjs/1-services/3-storage-buckets.js.map +7 -0
- package/dist/cjs/1-services/4-inboxes-tests.js +145 -0
- package/dist/cjs/1-services/4-inboxes-tests.js.map +7 -0
- package/dist/cjs/1-services/4-inboxes.js +539 -0
- package/dist/cjs/1-services/4-inboxes.js.map +7 -0
- package/dist/cjs/1-services/utilities.js +75 -0
- package/dist/cjs/1-services/utilities.js.map +7 -0
- package/dist/cjs/2-primitives/1-string-encoding-tests.js +50 -0
- package/dist/cjs/2-primitives/1-string-encoding-tests.js.map +7 -0
- package/dist/cjs/2-primitives/1-string-encoding.js +46 -0
- package/dist/cjs/2-primitives/1-string-encoding.js.map +7 -0
- package/dist/cjs/2-primitives/2-content-addresses-tests.js +62 -0
- package/dist/cjs/2-primitives/2-content-addresses-tests.js.map +7 -0
- package/dist/cjs/2-primitives/2-content-addresses.js +53 -0
- package/dist/cjs/2-primitives/2-content-addresses.js.map +7 -0
- package/dist/cjs/2-primitives/3-channel-attestations-tests.js +130 -0
- package/dist/cjs/2-primitives/3-channel-attestations-tests.js.map +7 -0
- package/dist/cjs/2-primitives/3-channel-attestations.js +84 -0
- package/dist/cjs/2-primitives/3-channel-attestations.js.map +7 -0
- package/dist/cjs/2-primitives/4-allowed-attestations-tests.js +96 -0
- package/dist/cjs/2-primitives/4-allowed-attestations-tests.js.map +7 -0
- package/dist/cjs/2-primitives/4-allowed-attestations.js +68 -0
- package/dist/cjs/2-primitives/4-allowed-attestations.js.map +7 -0
- package/dist/cjs/3-protocol/1-sessions.js +473 -0
- package/dist/cjs/3-protocol/1-sessions.js.map +7 -0
- package/dist/cjs/3-protocol/2-handles-tests.js +39 -0
- package/dist/cjs/3-protocol/2-handles-tests.js.map +7 -0
- package/dist/cjs/3-protocol/2-handles.js +65 -0
- package/dist/cjs/3-protocol/2-handles.js.map +7 -0
- package/dist/cjs/3-protocol/3-object-encoding-tests.js +253 -0
- package/dist/cjs/3-protocol/3-object-encoding-tests.js.map +7 -0
- package/dist/cjs/3-protocol/3-object-encoding.js +287 -0
- package/dist/cjs/3-protocol/3-object-encoding.js.map +7 -0
- package/dist/cjs/3-protocol/4-graffiti.js +937 -0
- package/dist/cjs/3-protocol/4-graffiti.js.map +7 -0
- package/dist/cjs/3-protocol/login-dialog.html.js +67 -0
- package/dist/cjs/3-protocol/login-dialog.html.js.map +7 -0
- package/dist/cjs/index.js +32 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/index.spec.js +130 -0
- package/dist/cjs/index.spec.js.map +7 -0
- package/dist/esm/1-services/1-authorization.js +304 -0
- package/dist/esm/1-services/1-authorization.js.map +7 -0
- package/dist/esm/1-services/2-dids-tests.js +24 -0
- package/dist/esm/1-services/2-dids-tests.js.map +7 -0
- package/dist/esm/1-services/2-dids.js +27 -0
- package/dist/esm/1-services/2-dids.js.map +7 -0
- package/dist/esm/1-services/3-storage-buckets-tests.js +103 -0
- package/dist/esm/1-services/3-storage-buckets-tests.js.map +7 -0
- package/dist/esm/1-services/3-storage-buckets.js +132 -0
- package/dist/esm/1-services/3-storage-buckets.js.map +7 -0
- package/dist/esm/1-services/4-inboxes-tests.js +125 -0
- package/dist/esm/1-services/4-inboxes-tests.js.map +7 -0
- package/dist/esm/1-services/4-inboxes.js +533 -0
- package/dist/esm/1-services/4-inboxes.js.map +7 -0
- package/dist/esm/1-services/utilities.js +60 -0
- package/dist/esm/1-services/utilities.js.map +7 -0
- package/dist/esm/2-primitives/1-string-encoding-tests.js +33 -0
- package/dist/esm/2-primitives/1-string-encoding-tests.js.map +7 -0
- package/dist/esm/2-primitives/1-string-encoding.js +26 -0
- package/dist/esm/2-primitives/1-string-encoding.js.map +7 -0
- package/dist/esm/2-primitives/2-content-addresses-tests.js +45 -0
- package/dist/esm/2-primitives/2-content-addresses-tests.js.map +7 -0
- package/dist/esm/2-primitives/2-content-addresses.js +33 -0
- package/dist/esm/2-primitives/2-content-addresses.js.map +7 -0
- package/dist/esm/2-primitives/3-channel-attestations-tests.js +116 -0
- package/dist/esm/2-primitives/3-channel-attestations-tests.js.map +7 -0
- package/dist/esm/2-primitives/3-channel-attestations.js +69 -0
- package/dist/esm/2-primitives/3-channel-attestations.js.map +7 -0
- package/dist/esm/2-primitives/4-allowed-attestations-tests.js +82 -0
- package/dist/esm/2-primitives/4-allowed-attestations-tests.js.map +7 -0
- package/dist/esm/2-primitives/4-allowed-attestations.js +51 -0
- package/dist/esm/2-primitives/4-allowed-attestations.js.map +7 -0
- package/dist/esm/3-protocol/1-sessions.js +465 -0
- package/dist/esm/3-protocol/1-sessions.js.map +7 -0
- package/dist/esm/3-protocol/2-handles-tests.js +19 -0
- package/dist/esm/3-protocol/2-handles-tests.js.map +7 -0
- package/dist/esm/3-protocol/2-handles.js +45 -0
- package/dist/esm/3-protocol/2-handles.js.map +7 -0
- package/dist/esm/3-protocol/3-object-encoding-tests.js +248 -0
- package/dist/esm/3-protocol/3-object-encoding-tests.js.map +7 -0
- package/dist/esm/3-protocol/3-object-encoding.js +280 -0
- package/dist/esm/3-protocol/3-object-encoding.js.map +7 -0
- package/dist/esm/3-protocol/4-graffiti.js +957 -0
- package/dist/esm/3-protocol/4-graffiti.js.map +7 -0
- package/dist/esm/3-protocol/login-dialog.html.js +47 -0
- package/dist/esm/3-protocol/login-dialog.html.js.map +7 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/esm/index.spec.js +133 -0
- package/dist/esm/index.spec.js.map +7 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.spec.d.ts +2 -0
- package/dist/index.spec.d.ts.map +1 -0
- package/package.json +62 -0
- package/src/1-services/1-authorization.ts +399 -0
- package/src/1-services/2-dids-tests.ts +24 -0
- package/src/1-services/2-dids.ts +30 -0
- package/src/1-services/3-storage-buckets-tests.ts +121 -0
- package/src/1-services/3-storage-buckets.ts +183 -0
- package/src/1-services/4-inboxes-tests.ts +154 -0
- package/src/1-services/4-inboxes.ts +722 -0
- package/src/1-services/utilities.ts +65 -0
- package/src/2-primitives/1-string-encoding-tests.ts +33 -0
- package/src/2-primitives/1-string-encoding.ts +33 -0
- package/src/2-primitives/2-content-addresses-tests.ts +46 -0
- package/src/2-primitives/2-content-addresses.ts +42 -0
- package/src/2-primitives/3-channel-attestations-tests.ts +125 -0
- package/src/2-primitives/3-channel-attestations.ts +95 -0
- package/src/2-primitives/4-allowed-attestations-tests.ts +86 -0
- package/src/2-primitives/4-allowed-attestations.ts +69 -0
- package/src/3-protocol/1-sessions.ts +601 -0
- package/src/3-protocol/2-handles-tests.ts +17 -0
- package/src/3-protocol/2-handles.ts +60 -0
- package/src/3-protocol/3-object-encoding-tests.ts +269 -0
- package/src/3-protocol/3-object-encoding.ts +396 -0
- package/src/3-protocol/4-graffiti.ts +1265 -0
- package/src/3-protocol/login-dialog.html.ts +43 -0
- package/src/index.spec.ts +158 -0
- package/src/index.ts +16 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var allowed_attestations_exports = {};
|
|
20
|
+
__export(allowed_attestations_exports, {
|
|
21
|
+
ALLOWED_ATTESTATION_METHOD_HMAC_SHA256: () => ALLOWED_ATTESTATION_METHOD_HMAC_SHA256,
|
|
22
|
+
AllowedAttestations: () => AllowedAttestations
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(allowed_attestations_exports);
|
|
25
|
+
var import_webcrypto = require("@noble/hashes/webcrypto.js");
|
|
26
|
+
var import_utils = require("@noble/hashes/utils.js");
|
|
27
|
+
var import_content_addresses = require("./2-content-addresses");
|
|
28
|
+
const ALLOWED_ATTESTATION_METHOD_HMAC_SHA256 = "hmac:sha2-256";
|
|
29
|
+
const ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC = 0;
|
|
30
|
+
class AllowedAttestations {
|
|
31
|
+
async attest(allowedAttestationMethod, actor) {
|
|
32
|
+
if (allowedAttestationMethod !== ALLOWED_ATTESTATION_METHOD_HMAC_SHA256) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Unsupported allowed attestation method: ${allowedAttestationMethod}`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
const ticket = (0, import_utils.randomBytes)();
|
|
38
|
+
const attestation = await (0, import_webcrypto.hmac)(
|
|
39
|
+
import_webcrypto.sha256,
|
|
40
|
+
ticket,
|
|
41
|
+
new TextEncoder().encode(actor)
|
|
42
|
+
);
|
|
43
|
+
const prefixedTicket = new Uint8Array(ticket.length + 3);
|
|
44
|
+
prefixedTicket[0] = ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC;
|
|
45
|
+
prefixedTicket[1] = import_content_addresses.MULTIHASH_CODE_SHA256;
|
|
46
|
+
prefixedTicket[2] = import_content_addresses.MULTIHASH_LENGTH_SHA256;
|
|
47
|
+
prefixedTicket.set(ticket, 3);
|
|
48
|
+
return { attestation, ticket: prefixedTicket };
|
|
49
|
+
}
|
|
50
|
+
async validate(attestation, actor, ticket) {
|
|
51
|
+
const typePrefix = ticket[0];
|
|
52
|
+
const hashPrefix = ticket[1];
|
|
53
|
+
const lengthPrefix = ticket[2];
|
|
54
|
+
if (typePrefix !== ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC || hashPrefix !== import_content_addresses.MULTIHASH_CODE_SHA256 || lengthPrefix !== import_content_addresses.MULTIHASH_LENGTH_SHA256) {
|
|
55
|
+
throw new Error(`Unrecognized allowed ticket format`);
|
|
56
|
+
}
|
|
57
|
+
const expected = await (0, import_webcrypto.hmac)(
|
|
58
|
+
import_webcrypto.sha256,
|
|
59
|
+
ticket.slice(3),
|
|
60
|
+
new TextEncoder().encode(actor)
|
|
61
|
+
);
|
|
62
|
+
if (attestation.length !== expected.length) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return expected.every((b, i) => attestation[i] === b);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=4-allowed-attestations.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/2-primitives/4-allowed-attestations.ts"],
|
|
4
|
+
"sourcesContent": ["import { sha256, hmac } from \"@noble/hashes/webcrypto.js\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\nimport {\n MULTIHASH_CODE_SHA256,\n MULTIHASH_LENGTH_SHA256,\n} from \"./2-content-addresses\";\n\nexport const ALLOWED_ATTESTATION_METHOD_HMAC_SHA256 = \"hmac:sha2-256\";\nconst ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC = 0;\n\nexport class AllowedAttestations {\n async attest(\n allowedAttestationMethod: string,\n actor: string,\n ): Promise<{\n attestation: Uint8Array;\n ticket: Uint8Array;\n }> {\n if (allowedAttestationMethod !== ALLOWED_ATTESTATION_METHOD_HMAC_SHA256) {\n throw new Error(\n `Unsupported allowed attestation method: ${allowedAttestationMethod}`,\n );\n }\n\n const ticket = randomBytes();\n const attestation = await hmac(\n sha256,\n ticket,\n new TextEncoder().encode(actor),\n );\n\n const prefixedTicket = new Uint8Array(ticket.length + 3);\n prefixedTicket[0] = ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC;\n prefixedTicket[1] = MULTIHASH_CODE_SHA256;\n prefixedTicket[2] = MULTIHASH_LENGTH_SHA256;\n prefixedTicket.set(ticket, 3);\n\n return { attestation, ticket: prefixedTicket };\n }\n\n async validate(\n attestation: Uint8Array,\n actor: string,\n ticket: Uint8Array,\n ): Promise<boolean> {\n const typePrefix = ticket[0];\n const hashPrefix = ticket[1];\n const lengthPrefix = ticket[2];\n if (\n typePrefix !== ALLOWED_ATTESTATION_METHOD_PREFIX_HMAC ||\n hashPrefix !== MULTIHASH_CODE_SHA256 ||\n lengthPrefix !== MULTIHASH_LENGTH_SHA256\n ) {\n throw new Error(`Unrecognized allowed ticket format`);\n }\n\n const expected = await hmac(\n sha256,\n ticket.slice(3),\n new TextEncoder().encode(actor),\n );\n\n // Make sure the bytes are exactly equal\n if (attestation.length !== expected.length) {\n return false;\n }\n return expected.every((b, i) => attestation[i] === b);\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAA6B;AAC7B,mBAA4B;AAC5B,+BAGO;AAEA,MAAM,yCAAyC;AACtD,MAAM,yCAAyC;AAExC,MAAM,oBAAoB;AAAA,EAC/B,MAAM,OACJ,0BACA,OAIC;AACD,QAAI,6BAA6B,wCAAwC;AACvE,YAAM,IAAI;AAAA,QACR,2CAA2C,wBAAwB;AAAA,MACrE;AAAA,IACF;AAEA,UAAM,aAAS,0BAAY;AAC3B,UAAM,cAAc,UAAM;AAAA,MACxB;AAAA,MACA;AAAA,MACA,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,IAChC;AAEA,UAAM,iBAAiB,IAAI,WAAW,OAAO,SAAS,CAAC;AACvD,mBAAe,CAAC,IAAI;AACpB,mBAAe,CAAC,IAAI;AACpB,mBAAe,CAAC,IAAI;AACpB,mBAAe,IAAI,QAAQ,CAAC;AAE5B,WAAO,EAAE,aAAa,QAAQ,eAAe;AAAA,EAC/C;AAAA,EAEA,MAAM,SACJ,aACA,OACA,QACkB;AAClB,UAAM,aAAa,OAAO,CAAC;AAC3B,UAAM,aAAa,OAAO,CAAC;AAC3B,UAAM,eAAe,OAAO,CAAC;AAC7B,QACE,eAAe,0CACf,eAAe,kDACf,iBAAiB,kDACjB;AACA,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AAEA,UAAM,WAAW,UAAM;AAAA,MACrB;AAAA,MACA,OAAO,MAAM,CAAC;AAAA,MACd,IAAI,YAAY,EAAE,OAAO,KAAK;AAAA,IAChC;AAGA,QAAI,YAAY,WAAW,SAAS,QAAQ;AAC1C,aAAO;AAAA,IACT;AACA,WAAO,SAAS,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC;AAAA,EACtD;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var sessions_exports = {};
|
|
20
|
+
__export(sessions_exports, {
|
|
21
|
+
DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX: () => DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX,
|
|
22
|
+
DID_SERVICE_ID_GRAFFITI_SHARED_INBOX_PREFIX: () => DID_SERVICE_ID_GRAFFITI_SHARED_INBOX_PREFIX,
|
|
23
|
+
DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET: () => DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET,
|
|
24
|
+
DID_SERVICE_TYPE_GRAFFITI_INBOX: () => DID_SERVICE_TYPE_GRAFFITI_INBOX,
|
|
25
|
+
DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET: () => DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,
|
|
26
|
+
Sessions: () => Sessions
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(sessions_exports);
|
|
29
|
+
var import_dids = require("../1-services/2-dids");
|
|
30
|
+
var import_authorization = require("../1-services/1-authorization");
|
|
31
|
+
var import_storage_buckets = require("../1-services/3-storage-buckets");
|
|
32
|
+
var import_mini = require("zod/mini");
|
|
33
|
+
const DID_SERVICE_TYPE_GRAFFITI_INBOX = "GraffitiInbox";
|
|
34
|
+
const DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET = "GraffitiStorageBucket";
|
|
35
|
+
const DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX = "#graffitiPersonalInbox";
|
|
36
|
+
const DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET = "#graffitiStorageBucket";
|
|
37
|
+
const DID_SERVICE_ID_GRAFFITI_SHARED_INBOX_PREFIX = "#graffitiSharedInbox_";
|
|
38
|
+
class Sessions {
|
|
39
|
+
constructor(services) {
|
|
40
|
+
this.services = services;
|
|
41
|
+
const initializedPromise = new Promise((resolve) => {
|
|
42
|
+
this.services.authorization.eventTarget.addEventListener(
|
|
43
|
+
"initialized",
|
|
44
|
+
(e) => {
|
|
45
|
+
if (!(e instanceof CustomEvent)) return;
|
|
46
|
+
const parsed = import_authorization.InitializedEventDetailSchema.safeParse(e.detail);
|
|
47
|
+
if (!parsed.success) return;
|
|
48
|
+
const error = parsed.data?.error;
|
|
49
|
+
if (error) console.log(error);
|
|
50
|
+
resolve();
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
this.services.authorization.eventTarget.addEventListener(
|
|
55
|
+
"login",
|
|
56
|
+
this.onLogin.bind(this)
|
|
57
|
+
);
|
|
58
|
+
this.services.authorization.eventTarget.addEventListener(
|
|
59
|
+
"logout",
|
|
60
|
+
this.onLogout.bind(this)
|
|
61
|
+
);
|
|
62
|
+
let loginPromise;
|
|
63
|
+
if (typeof window !== "undefined") {
|
|
64
|
+
const actorEncoded = new URLSearchParams(window.location.search).get(
|
|
65
|
+
"actor"
|
|
66
|
+
);
|
|
67
|
+
if (actorEncoded) {
|
|
68
|
+
try {
|
|
69
|
+
const actor = decodeURIComponent(actorEncoded);
|
|
70
|
+
const url2 = new URL(window.location.toString());
|
|
71
|
+
url2.searchParams.delete("actor");
|
|
72
|
+
window.history.replaceState({}, "", url2.toString());
|
|
73
|
+
loginPromise = this.login(actor);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error("Error decoding actor:", error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
(async () => {
|
|
80
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
81
|
+
await loginPromise;
|
|
82
|
+
for (const session of this.loggedInSessions) {
|
|
83
|
+
const loginEvent = new CustomEvent("login", {
|
|
84
|
+
detail: { session: { actor: session.actor } }
|
|
85
|
+
});
|
|
86
|
+
this.sessionEvents.dispatchEvent(loginEvent);
|
|
87
|
+
}
|
|
88
|
+
await initializedPromise;
|
|
89
|
+
const initializedEvent = new CustomEvent(
|
|
90
|
+
"initialized"
|
|
91
|
+
);
|
|
92
|
+
this.sessionEvents.dispatchEvent(initializedEvent);
|
|
93
|
+
})();
|
|
94
|
+
}
|
|
95
|
+
sessionEvents = new EventTarget();
|
|
96
|
+
inProgressLogin = void 0;
|
|
97
|
+
inProgressLogout = void 0;
|
|
98
|
+
async login(actor) {
|
|
99
|
+
try {
|
|
100
|
+
await this.login_(actor);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
const loginEvent = new CustomEvent("login", {
|
|
103
|
+
detail: {
|
|
104
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
105
|
+
session: { actor }
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
this.sessionEvents.dispatchEvent(loginEvent);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async login_(actor) {
|
|
112
|
+
const existingSession = this.loggedInSessions.find(
|
|
113
|
+
(session2) => session2.actor === actor
|
|
114
|
+
);
|
|
115
|
+
if (existingSession) {
|
|
116
|
+
this.sessionEvents.dispatchEvent(
|
|
117
|
+
new CustomEvent("login", { detail: { session: { actor } } })
|
|
118
|
+
);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const actorDocument = await this.services.dids.resolve(actor);
|
|
122
|
+
const services = actorDocument.service;
|
|
123
|
+
if (!services) {
|
|
124
|
+
throw new Error(`No services found in actor document for ${actor}`);
|
|
125
|
+
}
|
|
126
|
+
const storageBucketService = services.find(
|
|
127
|
+
(service) => service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET && service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET
|
|
128
|
+
);
|
|
129
|
+
const personalInboxService = services.find(
|
|
130
|
+
(service) => service.id === DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX && service.type === DID_SERVICE_TYPE_GRAFFITI_INBOX
|
|
131
|
+
);
|
|
132
|
+
const sharedInboxServices = services.filter(
|
|
133
|
+
(service) => service.id.match(
|
|
134
|
+
new RegExp(`^${DID_SERVICE_ID_GRAFFITI_SHARED_INBOX_PREFIX}\\d+$`)
|
|
135
|
+
) && service.type === DID_SERVICE_TYPE_GRAFFITI_INBOX
|
|
136
|
+
);
|
|
137
|
+
if (!personalInboxService || !storageBucketService || sharedInboxServices.length === 0) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
`Required services not found in actor document for ${actor}`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
const storageBucketEndpoint = serviceToEndpoint(storageBucketService);
|
|
143
|
+
const personalInboxEndpoint = serviceToEndpoint(personalInboxService);
|
|
144
|
+
const sharedInboxEndpoints = sharedInboxServices.map(serviceToEndpoint);
|
|
145
|
+
const servicesWithTypes = [
|
|
146
|
+
{ endpoint: storageBucketEndpoint, type: "bucket" },
|
|
147
|
+
{ endpoint: personalInboxEndpoint, type: "personal-inbox" },
|
|
148
|
+
...sharedInboxEndpoints.map(
|
|
149
|
+
(endpoint) => ({
|
|
150
|
+
endpoint,
|
|
151
|
+
type: "shared-inbox"
|
|
152
|
+
})
|
|
153
|
+
)
|
|
154
|
+
];
|
|
155
|
+
const servicesWithAuthorizationEndpoints = await Promise.all(
|
|
156
|
+
servicesWithTypes.map(async ({ endpoint, type }) => {
|
|
157
|
+
const authorizationEndpoint = await (type === "bucket" ? this.services.storageBuckets.getAuthorizationEndpoint(endpoint) : this.services.inboxes.getAuthorizationEndpoint(endpoint));
|
|
158
|
+
return { endpoint, authorizationEndpoint, type };
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
const servicesByAuthorizationMap = /* @__PURE__ */ new Map();
|
|
162
|
+
servicesWithAuthorizationEndpoints.forEach(
|
|
163
|
+
({ authorizationEndpoint, endpoint, type }) => {
|
|
164
|
+
if (!servicesByAuthorizationMap.has(authorizationEndpoint)) {
|
|
165
|
+
servicesByAuthorizationMap.set(authorizationEndpoint, []);
|
|
166
|
+
}
|
|
167
|
+
servicesByAuthorizationMap.get(authorizationEndpoint).push({ endpoint, type });
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
const servicesByAuthorization = [...servicesByAuthorizationMap.entries()];
|
|
171
|
+
const session = { actor };
|
|
172
|
+
const inProgressLogin = {
|
|
173
|
+
...session,
|
|
174
|
+
tokens: [],
|
|
175
|
+
servicesByAuthorization
|
|
176
|
+
};
|
|
177
|
+
if (typeof window !== "undefined") {
|
|
178
|
+
window.localStorage.setItem(
|
|
179
|
+
LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY,
|
|
180
|
+
JSON.stringify(inProgressLogin)
|
|
181
|
+
);
|
|
182
|
+
} else {
|
|
183
|
+
this.inProgressLogin = inProgressLogin;
|
|
184
|
+
}
|
|
185
|
+
const [firstAuthorizationEndpoint, firstServices] = servicesByAuthorization[0];
|
|
186
|
+
await this.services.authorization.login(
|
|
187
|
+
firstAuthorizationEndpoint,
|
|
188
|
+
actor,
|
|
189
|
+
firstServices.map((s) => s.endpoint)
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
async onLogin(event) {
|
|
193
|
+
if (!(event instanceof CustomEvent)) return;
|
|
194
|
+
const parsed = import_authorization.LoginEventDetailSchema.safeParse(event.detail);
|
|
195
|
+
if (!parsed.success) return;
|
|
196
|
+
const actor = parsed.data.loginId;
|
|
197
|
+
try {
|
|
198
|
+
await this.onLogin_(parsed.data);
|
|
199
|
+
} catch (e) {
|
|
200
|
+
const LoginEvent = new CustomEvent("login", {
|
|
201
|
+
detail: {
|
|
202
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
203
|
+
session: { actor }
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
this.sessionEvents.dispatchEvent(LoginEvent);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async onLogin_(loginDetail) {
|
|
210
|
+
if (loginDetail.error) throw loginDetail.error;
|
|
211
|
+
const token = loginDetail.token;
|
|
212
|
+
const actor = loginDetail.loginId;
|
|
213
|
+
let inProgressLogin;
|
|
214
|
+
if (typeof window !== "undefined") {
|
|
215
|
+
const inProgressLoginString = window.localStorage.getItem(
|
|
216
|
+
LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY
|
|
217
|
+
);
|
|
218
|
+
if (!inProgressLoginString) {
|
|
219
|
+
throw new Error("No in-progress login found");
|
|
220
|
+
}
|
|
221
|
+
const json = JSON.parse(inProgressLoginString);
|
|
222
|
+
inProgressLogin = InProgressSchema.parse(json);
|
|
223
|
+
} else {
|
|
224
|
+
if (!this.inProgressLogin) {
|
|
225
|
+
throw new Error("No in-progress login found");
|
|
226
|
+
}
|
|
227
|
+
inProgressLogin = this.inProgressLogin;
|
|
228
|
+
}
|
|
229
|
+
if (inProgressLogin.actor !== actor) {
|
|
230
|
+
throw new Error("Actor mismatch in login response - concurrent logins?");
|
|
231
|
+
}
|
|
232
|
+
inProgressLogin.tokens.push(token);
|
|
233
|
+
if (inProgressLogin.tokens.length === inProgressLogin.servicesByAuthorization.length) {
|
|
234
|
+
if (typeof window === "undefined") {
|
|
235
|
+
this.inProgressLogin = void 0;
|
|
236
|
+
} else {
|
|
237
|
+
window.localStorage.removeItem(LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY);
|
|
238
|
+
}
|
|
239
|
+
const services = inProgressLogin.servicesByAuthorization.flatMap(
|
|
240
|
+
([authorizationEndpoint, services2], index) => services2.map((service) => ({
|
|
241
|
+
token: inProgressLogin.tokens[index],
|
|
242
|
+
serviceEndpoint: service.endpoint,
|
|
243
|
+
authorizationEndpoint,
|
|
244
|
+
type: service.type
|
|
245
|
+
}))
|
|
246
|
+
);
|
|
247
|
+
const session = {
|
|
248
|
+
...inProgressLogin,
|
|
249
|
+
storageBucket: services.find((s) => s.type === "bucket"),
|
|
250
|
+
personalInbox: services.find((s) => s.type === "personal-inbox"),
|
|
251
|
+
sharedInboxes: services.filter((s) => s.type === "shared-inbox")
|
|
252
|
+
};
|
|
253
|
+
const sessions = this.loggedInSessions;
|
|
254
|
+
sessions.push(session);
|
|
255
|
+
this.loggedInSessions = sessions;
|
|
256
|
+
const loginEvent = new CustomEvent("login", {
|
|
257
|
+
detail: { session: { actor } }
|
|
258
|
+
});
|
|
259
|
+
this.sessionEvents.dispatchEvent(loginEvent);
|
|
260
|
+
} else {
|
|
261
|
+
if (typeof window !== "undefined") {
|
|
262
|
+
window.localStorage.setItem(
|
|
263
|
+
LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY,
|
|
264
|
+
JSON.stringify(inProgressLogin)
|
|
265
|
+
);
|
|
266
|
+
} else {
|
|
267
|
+
this.inProgressLogin = inProgressLogin;
|
|
268
|
+
}
|
|
269
|
+
const [authorizationEndpoint, services] = inProgressLogin.servicesByAuthorization[inProgressLogin.tokens.length];
|
|
270
|
+
await this.services.authorization.login(
|
|
271
|
+
authorizationEndpoint,
|
|
272
|
+
actor,
|
|
273
|
+
services.map((s) => s.endpoint)
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
async logout(actor) {
|
|
278
|
+
try {
|
|
279
|
+
await this.logout_(actor);
|
|
280
|
+
} catch (e) {
|
|
281
|
+
const logoutEvent = new CustomEvent("logout", {
|
|
282
|
+
detail: {
|
|
283
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
284
|
+
actor
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
this.sessionEvents.dispatchEvent(logoutEvent);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async logout_(actor) {
|
|
291
|
+
const session = this.loggedInSessions.find(
|
|
292
|
+
(session2) => session2.actor === actor
|
|
293
|
+
);
|
|
294
|
+
if (!session) {
|
|
295
|
+
throw new Error(`No session found for actor ${actor}`);
|
|
296
|
+
}
|
|
297
|
+
this.loggedInSessions = this.loggedInSessions.filter(
|
|
298
|
+
(session2) => session2.actor !== actor
|
|
299
|
+
);
|
|
300
|
+
const token = session.tokens.pop();
|
|
301
|
+
if (!token) {
|
|
302
|
+
throw new Error("No tokens found in session");
|
|
303
|
+
}
|
|
304
|
+
if (typeof window !== "undefined") {
|
|
305
|
+
window.localStorage.setItem(
|
|
306
|
+
LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY,
|
|
307
|
+
JSON.stringify(session)
|
|
308
|
+
);
|
|
309
|
+
} else {
|
|
310
|
+
this.inProgressLogout = session;
|
|
311
|
+
}
|
|
312
|
+
const [authorizationEndpoint, _] = session.servicesByAuthorization[session.tokens.length];
|
|
313
|
+
await this.services.authorization.logout(
|
|
314
|
+
authorizationEndpoint,
|
|
315
|
+
actor,
|
|
316
|
+
token
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
async onLogout(event) {
|
|
320
|
+
if (!(event instanceof CustomEvent)) return;
|
|
321
|
+
const parsed = import_authorization.LogoutEventDetailSchema.safeParse(event.detail);
|
|
322
|
+
if (!parsed.success) return;
|
|
323
|
+
const actor = parsed.data.logoutId;
|
|
324
|
+
try {
|
|
325
|
+
await this.onLogout_(parsed.data);
|
|
326
|
+
} catch (e) {
|
|
327
|
+
const logoutEvent = new CustomEvent("logout", {
|
|
328
|
+
detail: {
|
|
329
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
330
|
+
actor
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
this.sessionEvents.dispatchEvent(logoutEvent);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
async onLogout_(logoutDetail) {
|
|
337
|
+
if (logoutDetail.error) throw logoutDetail.error;
|
|
338
|
+
const actor = logoutDetail.logoutId;
|
|
339
|
+
let inProgressLogout;
|
|
340
|
+
if (typeof window !== "undefined") {
|
|
341
|
+
const inProgressLogoutString = window.localStorage.getItem(
|
|
342
|
+
LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY
|
|
343
|
+
);
|
|
344
|
+
if (!inProgressLogoutString) {
|
|
345
|
+
throw new Error("No in-progress logout found");
|
|
346
|
+
}
|
|
347
|
+
const json = JSON.parse(inProgressLogoutString);
|
|
348
|
+
inProgressLogout = InProgressSchema.parse(json);
|
|
349
|
+
} else {
|
|
350
|
+
if (!this.inProgressLogout) {
|
|
351
|
+
throw new Error("No in-progress logout found");
|
|
352
|
+
}
|
|
353
|
+
inProgressLogout = this.inProgressLogout;
|
|
354
|
+
}
|
|
355
|
+
if (inProgressLogout.actor !== actor) {
|
|
356
|
+
throw new Error(
|
|
357
|
+
"Actor mismatch in logout response - concurrent logouts?"
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
const token = inProgressLogout.tokens.pop();
|
|
361
|
+
if (!token) {
|
|
362
|
+
if (typeof window === "undefined") {
|
|
363
|
+
this.inProgressLogout = void 0;
|
|
364
|
+
} else {
|
|
365
|
+
window.localStorage.removeItem(LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY);
|
|
366
|
+
}
|
|
367
|
+
const logoutEvent = new CustomEvent("logout", {
|
|
368
|
+
detail: { actor }
|
|
369
|
+
});
|
|
370
|
+
this.sessionEvents.dispatchEvent(logoutEvent);
|
|
371
|
+
} else {
|
|
372
|
+
if (typeof window !== "undefined") {
|
|
373
|
+
window.localStorage.setItem(
|
|
374
|
+
LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY,
|
|
375
|
+
JSON.stringify(inProgressLogout)
|
|
376
|
+
);
|
|
377
|
+
} else {
|
|
378
|
+
this.inProgressLogout = inProgressLogout;
|
|
379
|
+
}
|
|
380
|
+
const [authorizationEndpoint, _] = inProgressLogout.servicesByAuthorization[inProgressLogout.tokens.length];
|
|
381
|
+
await this.services.authorization.logout(
|
|
382
|
+
authorizationEndpoint,
|
|
383
|
+
actor,
|
|
384
|
+
token
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
get loggedInSessions() {
|
|
389
|
+
if (typeof window === "undefined") return loggedInSessions_;
|
|
390
|
+
const data = window.localStorage.getItem(
|
|
391
|
+
LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY
|
|
392
|
+
);
|
|
393
|
+
if (!data) return [];
|
|
394
|
+
let json;
|
|
395
|
+
try {
|
|
396
|
+
json = JSON.parse(data);
|
|
397
|
+
} catch {
|
|
398
|
+
console.error("Error parsing stored session data");
|
|
399
|
+
window.localStorage.removeItem(LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY);
|
|
400
|
+
return [];
|
|
401
|
+
}
|
|
402
|
+
const parsed = (0, import_mini.array)(StoredSessionSchema).safeParse(json);
|
|
403
|
+
if (!parsed.success) {
|
|
404
|
+
console.error("Stored session data is invalid");
|
|
405
|
+
window.localStorage.removeItem(LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY);
|
|
406
|
+
return [];
|
|
407
|
+
}
|
|
408
|
+
return parsed.data;
|
|
409
|
+
}
|
|
410
|
+
set loggedInSessions(sessions) {
|
|
411
|
+
if (typeof window === "undefined") {
|
|
412
|
+
loggedInSessions_ = sessions;
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
window.localStorage.setItem(
|
|
416
|
+
LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY,
|
|
417
|
+
JSON.stringify(sessions)
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
resolveSession(session) {
|
|
421
|
+
const resolvedSession = this.loggedInSessions.find(
|
|
422
|
+
(s) => s.actor === session.actor
|
|
423
|
+
);
|
|
424
|
+
if (!resolvedSession) {
|
|
425
|
+
const logoutEvent = new CustomEvent("logout", {
|
|
426
|
+
detail: { actor: session.actor }
|
|
427
|
+
});
|
|
428
|
+
this.sessionEvents.dispatchEvent(logoutEvent);
|
|
429
|
+
throw new Error("Not logged in");
|
|
430
|
+
}
|
|
431
|
+
return resolvedSession;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
let loggedInSessions_ = [];
|
|
435
|
+
const LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY = "graffiti-login-in-progress";
|
|
436
|
+
const LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY = "graffiti-logout-in-progress";
|
|
437
|
+
const LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY = "graffiti-sessions-logged-in";
|
|
438
|
+
const GraffitiSessionSchema = (0, import_mini.object)({
|
|
439
|
+
actor: (0, import_mini.url)()
|
|
440
|
+
});
|
|
441
|
+
const ServiceSessionSchema = (0, import_mini.object)({
|
|
442
|
+
token: (0, import_mini.string)(),
|
|
443
|
+
serviceEndpoint: (0, import_mini.url)(),
|
|
444
|
+
authorizationEndpoint: (0, import_mini.url)()
|
|
445
|
+
});
|
|
446
|
+
const ServicesByAuthorizationSchema = (0, import_mini.array)(
|
|
447
|
+
(0, import_mini.tuple)([
|
|
448
|
+
(0, import_mini.url)(),
|
|
449
|
+
// Authorization endpoint
|
|
450
|
+
(0, import_mini.array)(
|
|
451
|
+
(0, import_mini.object)({
|
|
452
|
+
endpoint: (0, import_mini.url)(),
|
|
453
|
+
// Service endpoint
|
|
454
|
+
type: (0, import_mini.enum)(["bucket", "personal-inbox", "shared-inbox"])
|
|
455
|
+
})
|
|
456
|
+
)
|
|
457
|
+
])
|
|
458
|
+
);
|
|
459
|
+
const InProgressSchema = (0, import_mini.extend)(GraffitiSessionSchema, {
|
|
460
|
+
tokens: (0, import_mini.array)((0, import_mini.string)()),
|
|
461
|
+
servicesByAuthorization: ServicesByAuthorizationSchema
|
|
462
|
+
});
|
|
463
|
+
const StoredSessionSchema = (0, import_mini.extend)(InProgressSchema, {
|
|
464
|
+
storageBucket: ServiceSessionSchema,
|
|
465
|
+
personalInbox: ServiceSessionSchema,
|
|
466
|
+
sharedInboxes: (0, import_mini.array)(ServiceSessionSchema)
|
|
467
|
+
});
|
|
468
|
+
function serviceToEndpoint(service) {
|
|
469
|
+
if (typeof service.serviceEndpoint === "string")
|
|
470
|
+
return service.serviceEndpoint;
|
|
471
|
+
throw new Error(`Service endpoint for ${service.id} is not a string`);
|
|
472
|
+
}
|
|
473
|
+
//# sourceMappingURL=1-sessions.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/3-protocol/1-sessions.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n Graffiti,\n GraffitiLoginEvent,\n GraffitiLogoutEvent,\n GraffitiSession,\n GraffitiSessionInitializedEvent,\n} from \"@graffiti-garden/api\";\nimport { DecentralizedIdentifiers } from \"../1-services/2-dids\";\nimport {\n InitializedEventDetailSchema,\n LoginEventDetailSchema,\n LogoutEventDetailSchema,\n type Authorization,\n} from \"../1-services/1-authorization\";\nimport { StorageBuckets } from \"../1-services/3-storage-buckets\";\nimport type { Inboxes } from \"../1-services/4-inboxes\";\nimport type { Service } from \"did-resolver\";\nimport {\n type infer as infer_,\n extend,\n array,\n string,\n object,\n url,\n tuple,\n enum as enum_,\n} from \"zod/mini\";\n\nexport const DID_SERVICE_TYPE_GRAFFITI_INBOX = \"GraffitiInbox\";\nexport const DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET = \"GraffitiStorageBucket\";\nexport const DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX = \"#graffitiPersonalInbox\";\nexport const DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET = \"#graffitiStorageBucket\";\nexport const DID_SERVICE_ID_GRAFFITI_SHARED_INBOX_PREFIX =\n \"#graffitiSharedInbox_\";\n\nexport class Sessions {\n sessionEvents: Graffiti[\"sessionEvents\"] = new EventTarget();\n\n constructor(\n protected readonly services: {\n readonly dids: DecentralizedIdentifiers;\n readonly authorization: Authorization;\n readonly storageBuckets: StorageBuckets;\n readonly inboxes: Inboxes;\n },\n ) {\n const initializedPromise = new Promise<void>((resolve) => {\n this.services.authorization.eventTarget.addEventListener(\n \"initialized\",\n (e) => {\n if (!(e instanceof CustomEvent)) return;\n const parsed = InitializedEventDetailSchema.safeParse(e.detail);\n if (!parsed.success) return;\n const error = parsed.data?.error;\n if (error) console.log(error);\n resolve();\n },\n );\n });\n this.services.authorization.eventTarget.addEventListener(\n \"login\",\n this.onLogin.bind(this),\n );\n this.services.authorization.eventTarget.addEventListener(\n \"logout\",\n this.onLogout.bind(this),\n );\n\n // Handle account registration redirect immediately,\n // to prevent SPA routers from hijacking the URL too soon\n let loginPromise: Promise<void> | undefined;\n if (typeof window !== \"undefined\") {\n const actorEncoded = new URLSearchParams(window.location.search).get(\n \"actor\",\n );\n if (actorEncoded) {\n try {\n // Get the actor\n const actor = decodeURIComponent(actorEncoded);\n // Strip it from the URL\n const url = new URL(window.location.toString());\n url.searchParams.delete(\"actor\");\n window.history.replaceState({}, \"\", url.toString());\n // Complete the login\n loginPromise = this.login(actor);\n } catch (error) {\n console.error(\"Error decoding actor:\", error);\n }\n }\n }\n\n (async () => {\n // Allow listeners to be added before dispatching events\n await new Promise((resolve) => setTimeout(resolve, 0));\n\n // Wait for login to complete, if there\n await loginPromise;\n\n for (const session of this.loggedInSessions) {\n const loginEvent: GraffitiLoginEvent = new CustomEvent(\"login\", {\n detail: { session: { actor: session.actor } },\n });\n this.sessionEvents.dispatchEvent(loginEvent);\n }\n\n await initializedPromise;\n\n // Send own initialized event\n const initializedEvent: GraffitiSessionInitializedEvent = new CustomEvent(\n \"initialized\",\n );\n this.sessionEvents.dispatchEvent(initializedEvent);\n })();\n }\n\n protected inProgressLogin: infer_<typeof InProgressSchema> | undefined =\n undefined;\n protected inProgressLogout: infer_<typeof InProgressSchema> | undefined =\n undefined;\n\n async login(actor: string) {\n try {\n await this.login_(actor);\n } catch (e) {\n const loginEvent: GraffitiLoginEvent = new CustomEvent(\"login\", {\n detail: {\n error: e instanceof Error ? e : new Error(String(e)),\n session: { actor },\n },\n });\n this.sessionEvents.dispatchEvent(loginEvent);\n }\n }\n protected async login_(actor: string) {\n // First look to see if we're already logged in\n const existingSession = this.loggedInSessions.find(\n (session) => session.actor === actor,\n );\n if (existingSession) {\n this.sessionEvents.dispatchEvent(\n new CustomEvent(\"login\", { detail: { session: { actor } } }),\n );\n return;\n }\n\n const actorDocument = await this.services.dids.resolve(actor);\n\n const services = actorDocument.service;\n if (!services) {\n throw new Error(`No services found in actor document for ${actor}`);\n }\n\n const storageBucketService = services.find(\n (service) =>\n service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET &&\n service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,\n );\n const personalInboxService = services.find(\n (service) =>\n service.id === DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX &&\n service.type === DID_SERVICE_TYPE_GRAFFITI_INBOX,\n );\n const sharedInboxServices = services.filter(\n (service) =>\n service.id.match(\n new RegExp(`^${DID_SERVICE_ID_GRAFFITI_SHARED_INBOX_PREFIX}\\\\d+$`),\n ) && service.type === DID_SERVICE_TYPE_GRAFFITI_INBOX,\n );\n\n if (\n !personalInboxService ||\n !storageBucketService ||\n sharedInboxServices.length === 0\n ) {\n throw new Error(\n `Required services not found in actor document for ${actor}`,\n );\n }\n\n // Massage the services into a list of endpoints with types\n const storageBucketEndpoint: string =\n serviceToEndpoint(storageBucketService);\n const personalInboxEndpoint: string =\n serviceToEndpoint(personalInboxService);\n const sharedInboxEndpoints: string[] =\n sharedInboxServices.map(serviceToEndpoint);\n const servicesWithTypes = [\n { endpoint: storageBucketEndpoint, type: \"bucket\" } as const,\n { endpoint: personalInboxEndpoint, type: \"personal-inbox\" } as const,\n ...sharedInboxEndpoints.map(\n (endpoint) =>\n ({\n endpoint,\n type: \"shared-inbox\",\n }) as const,\n ),\n ];\n\n // Fetch the authorization endpoints for each service\n const servicesWithAuthorizationEndpoints = await Promise.all(\n servicesWithTypes.map(async ({ endpoint, type }) => {\n const authorizationEndpoint = await (type === \"bucket\"\n ? this.services.storageBuckets.getAuthorizationEndpoint(endpoint)\n : this.services.inboxes.getAuthorizationEndpoint(endpoint));\n return { endpoint, authorizationEndpoint, type };\n }),\n );\n\n // Group the endpoints according to their authorization endpoints\n const servicesByAuthorizationMap: Map<\n string,\n {\n endpoint: string;\n type: \"bucket\" | \"personal-inbox\" | \"shared-inbox\";\n }[]\n > = new Map();\n servicesWithAuthorizationEndpoints.forEach(\n ({ authorizationEndpoint, endpoint, type }) => {\n if (!servicesByAuthorizationMap.has(authorizationEndpoint)) {\n servicesByAuthorizationMap.set(authorizationEndpoint, []);\n }\n servicesByAuthorizationMap\n .get(authorizationEndpoint)!\n .push({ endpoint, type });\n },\n );\n const servicesByAuthorization = [...servicesByAuthorizationMap.entries()];\n\n const session: GraffitiSession = { actor };\n\n const inProgressLogin: infer_<typeof InProgressSchema> = {\n ...session,\n tokens: [],\n servicesByAuthorization,\n };\n\n if (typeof window !== \"undefined\") {\n // Store the in-progress session in localStorage\n window.localStorage.setItem(\n LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY,\n JSON.stringify(inProgressLogin),\n );\n } else {\n this.inProgressLogin = inProgressLogin;\n }\n\n // Start the login process with the first endpoint\n const [firstAuthorizationEndpoint, firstServices] =\n servicesByAuthorization[0];\n await this.services.authorization.login(\n firstAuthorizationEndpoint,\n actor,\n firstServices.map((s) => s.endpoint),\n );\n }\n\n protected async onLogin(event: unknown) {\n if (!(event instanceof CustomEvent)) return;\n const parsed = LoginEventDetailSchema.safeParse(event.detail);\n if (!parsed.success) return;\n\n const actor = parsed.data.loginId;\n\n try {\n await this.onLogin_(parsed.data);\n } catch (e) {\n const LoginEvent: GraffitiLoginEvent = new CustomEvent(\"login\", {\n detail: {\n error: e instanceof Error ? e : new Error(String(e)),\n session: { actor },\n },\n });\n this.sessionEvents.dispatchEvent(LoginEvent);\n }\n }\n protected async onLogin_(loginDetail: infer_<typeof LoginEventDetailSchema>) {\n if (loginDetail.error) throw loginDetail.error;\n\n const token = loginDetail.token;\n const actor = loginDetail.loginId;\n\n // Lookup the in-progress session\n let inProgressLogin: infer_<typeof InProgressSchema>;\n if (typeof window !== \"undefined\") {\n const inProgressLoginString = window.localStorage.getItem(\n LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY,\n );\n if (!inProgressLoginString) {\n throw new Error(\"No in-progress login found\");\n }\n\n const json = JSON.parse(inProgressLoginString);\n inProgressLogin = InProgressSchema.parse(json);\n } else {\n if (!this.inProgressLogin) {\n throw new Error(\"No in-progress login found\");\n }\n inProgressLogin = this.inProgressLogin;\n }\n\n if (inProgressLogin.actor !== actor) {\n throw new Error(\"Actor mismatch in login response - concurrent logins?\");\n }\n\n inProgressLogin.tokens.push(token);\n\n if (\n inProgressLogin.tokens.length ===\n inProgressLogin.servicesByAuthorization.length\n ) {\n // Login complete!\n if (typeof window === \"undefined\") {\n this.inProgressLogin = undefined;\n } else {\n window.localStorage.removeItem(LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY);\n }\n\n // Build the completed session\n const services = inProgressLogin.servicesByAuthorization.flatMap(\n ([authorizationEndpoint, services], index) =>\n services.map((service) => ({\n token: inProgressLogin.tokens[index],\n serviceEndpoint: service.endpoint,\n authorizationEndpoint,\n type: service.type,\n })),\n );\n\n const session: StoredSession = {\n ...inProgressLogin,\n storageBucket: services.find((s) => s.type === \"bucket\")!,\n personalInbox: services.find((s) => s.type === \"personal-inbox\")!,\n sharedInboxes: services.filter((s) => s.type === \"shared-inbox\")!,\n };\n\n // Store the completed session\n const sessions = this.loggedInSessions;\n sessions.push(session);\n this.loggedInSessions = sessions;\n\n // Return the completed session\n const loginEvent: GraffitiLoginEvent = new CustomEvent(\"login\", {\n detail: { session: { actor } },\n });\n this.sessionEvents.dispatchEvent(loginEvent);\n } else {\n // Store the in progress and continue\n if (typeof window !== \"undefined\") {\n window.localStorage.setItem(\n LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY,\n JSON.stringify(inProgressLogin),\n );\n } else {\n this.inProgressLogin = inProgressLogin;\n }\n\n // Continue to the next authorization endpoint\n const [authorizationEndpoint, services] =\n inProgressLogin.servicesByAuthorization[inProgressLogin.tokens.length];\n await this.services.authorization.login(\n authorizationEndpoint,\n actor,\n services.map((s) => s.endpoint),\n );\n }\n }\n\n async logout(actor: string) {\n try {\n await this.logout_(actor);\n } catch (e) {\n const logoutEvent: GraffitiLogoutEvent = new CustomEvent(\"logout\", {\n detail: {\n error: e instanceof Error ? e : new Error(String(e)),\n actor,\n },\n });\n this.sessionEvents.dispatchEvent(logoutEvent);\n }\n }\n protected async logout_(actor: string) {\n const session = this.loggedInSessions.find(\n (session) => session.actor === actor,\n );\n if (!session) {\n throw new Error(`No session found for actor ${actor}`);\n }\n\n // Remove the session(s)\n this.loggedInSessions = this.loggedInSessions.filter(\n (session) => session.actor !== actor,\n );\n\n // Begin the logout\n const token = session.tokens.pop();\n if (!token) {\n throw new Error(\"No tokens found in session\");\n }\n // Store the in progress logout\n if (typeof window !== \"undefined\") {\n window.localStorage.setItem(\n LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY,\n JSON.stringify(session),\n );\n } else {\n this.inProgressLogout = session;\n }\n const [authorizationEndpoint, _] =\n session.servicesByAuthorization[session.tokens.length];\n await this.services.authorization.logout(\n authorizationEndpoint,\n actor,\n token,\n );\n }\n\n protected async onLogout(event: unknown) {\n if (!(event instanceof CustomEvent)) return;\n const parsed = LogoutEventDetailSchema.safeParse(event.detail);\n if (!parsed.success) return;\n\n const actor = parsed.data.logoutId;\n\n try {\n await this.onLogout_(parsed.data);\n } catch (e) {\n const logoutEvent: GraffitiLogoutEvent = new CustomEvent(\"logout\", {\n detail: {\n error: e instanceof Error ? e : new Error(String(e)),\n actor,\n },\n });\n this.sessionEvents.dispatchEvent(logoutEvent);\n }\n }\n protected async onLogout_(\n logoutDetail: infer_<typeof LogoutEventDetailSchema>,\n ) {\n if (logoutDetail.error) throw logoutDetail.error;\n\n const actor = logoutDetail.logoutId;\n\n // Lookup the in-progress session\n let inProgressLogout: infer_<typeof InProgressSchema>;\n if (typeof window !== \"undefined\") {\n const inProgressLogoutString = window.localStorage.getItem(\n LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY,\n );\n if (!inProgressLogoutString) {\n throw new Error(\"No in-progress logout found\");\n }\n\n const json = JSON.parse(inProgressLogoutString);\n inProgressLogout = InProgressSchema.parse(json);\n } else {\n if (!this.inProgressLogout) {\n throw new Error(\"No in-progress logout found\");\n }\n inProgressLogout = this.inProgressLogout;\n }\n\n if (inProgressLogout.actor !== actor) {\n throw new Error(\n \"Actor mismatch in logout response - concurrent logouts?\",\n );\n }\n\n const token = inProgressLogout.tokens.pop();\n if (!token) {\n // Logout complete\n if (typeof window === \"undefined\") {\n this.inProgressLogout = undefined;\n } else {\n window.localStorage.removeItem(LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY);\n }\n\n const logoutEvent: GraffitiLogoutEvent = new CustomEvent(\"logout\", {\n detail: { actor },\n });\n this.sessionEvents.dispatchEvent(logoutEvent);\n } else {\n // Store the in progress and continue\n if (typeof window !== \"undefined\") {\n window.localStorage.setItem(\n LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY,\n JSON.stringify(inProgressLogout),\n );\n } else {\n this.inProgressLogout = inProgressLogout;\n }\n\n // Continue to the next authorization endpoint\n const [authorizationEndpoint, _] =\n inProgressLogout.servicesByAuthorization[\n inProgressLogout.tokens.length\n ];\n await this.services.authorization.logout(\n authorizationEndpoint,\n actor,\n token,\n );\n }\n }\n\n protected get loggedInSessions(): StoredSession[] {\n if (typeof window === \"undefined\") return loggedInSessions_;\n\n const data = window.localStorage.getItem(\n LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY,\n );\n if (!data) return [];\n\n let json: unknown;\n try {\n json = JSON.parse(data);\n } catch {\n console.error(\"Error parsing stored session data\");\n window.localStorage.removeItem(LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY);\n return [];\n }\n\n const parsed = array(StoredSessionSchema).safeParse(json);\n if (!parsed.success) {\n console.error(\"Stored session data is invalid\");\n window.localStorage.removeItem(LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY);\n return [];\n }\n return parsed.data;\n }\n protected set loggedInSessions(sessions: StoredSession[]) {\n if (typeof window === \"undefined\") {\n loggedInSessions_ = sessions;\n return;\n }\n\n window.localStorage.setItem(\n LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY,\n JSON.stringify(sessions),\n );\n }\n\n resolveSession(session: GraffitiSession): StoredSession {\n const resolvedSession = this.loggedInSessions.find(\n (s) => s.actor === session.actor,\n );\n if (!resolvedSession) {\n const logoutEvent: GraffitiLogoutEvent = new CustomEvent(\"logout\", {\n detail: { actor: session.actor },\n });\n this.sessionEvents.dispatchEvent(logoutEvent);\n throw new Error(\"Not logged in\");\n }\n return resolvedSession;\n }\n}\nlet loggedInSessions_: StoredSession[] = [];\n\nconst LOCAL_STORAGE_IN_PROGRESS_LOGIN_KEY = \"graffiti-login-in-progress\";\nconst LOCAL_STORAGE_IN_PROGRESS_LOGOUT_KEY = \"graffiti-logout-in-progress\";\nconst LOCAL_STORAGE_LOGGED_IN_SESSIONS_KEY = \"graffiti-sessions-logged-in\";\n\nconst GraffitiSessionSchema = object({\n actor: url(),\n});\n\nconst ServiceSessionSchema = object({\n token: string(),\n serviceEndpoint: url(),\n authorizationEndpoint: url(),\n});\n\nconst ServicesByAuthorizationSchema = array(\n tuple([\n url(), // Authorization endpoint\n array(\n object({\n endpoint: url(), // Service endpoint\n type: enum_([\"bucket\", \"personal-inbox\", \"shared-inbox\"]),\n }),\n ),\n ]),\n);\n\nconst InProgressSchema = extend(GraffitiSessionSchema, {\n tokens: array(string()),\n servicesByAuthorization: ServicesByAuthorizationSchema,\n});\n\nconst StoredSessionSchema = extend(InProgressSchema, {\n storageBucket: ServiceSessionSchema,\n personalInbox: ServiceSessionSchema,\n sharedInboxes: array(ServiceSessionSchema),\n});\n\ntype StoredSession = infer_<typeof StoredSessionSchema>;\n\nfunction serviceToEndpoint(service: Service): string {\n if (typeof service.serviceEndpoint === \"string\")\n return service.serviceEndpoint;\n throw new Error(`Service endpoint for ${service.id} is not a string`);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["url", "session", "services", "enum_"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var handles_tests_exports = {};
|
|
20
|
+
__export(handles_tests_exports, {
|
|
21
|
+
handleTests: () => handleTests
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(handles_tests_exports);
|
|
24
|
+
var import_vitest = require("vitest");
|
|
25
|
+
var import_handles = require("./2-handles");
|
|
26
|
+
var import_dids = require("../1-services/2-dids");
|
|
27
|
+
function handleTests(handle) {
|
|
28
|
+
(0, import_vitest.describe)("Handles", async () => {
|
|
29
|
+
const handles = new import_handles.Handles({
|
|
30
|
+
dids: new import_dids.DecentralizedIdentifiers()
|
|
31
|
+
});
|
|
32
|
+
(0, import_vitest.test)("handleToActor and actorToHandle", async () => {
|
|
33
|
+
const actor = await handles.handleToActor(handle);
|
|
34
|
+
const resolvedHandle = await handles.actorToHandle(actor);
|
|
35
|
+
(0, import_vitest.expect)(resolvedHandle).toBe(handle);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=2-handles-tests.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/3-protocol/2-handles-tests.ts"],
|
|
4
|
+
"sourcesContent": ["import { describe, expect, test } from \"vitest\";\nimport { Handles } from \"./2-handles\";\nimport { DecentralizedIdentifiers } from \"../1-services/2-dids\";\n\nexport function handleTests(handle: string) {\n describe(\"Handles\", async () => {\n const handles = new Handles({\n dids: new DecentralizedIdentifiers(),\n });\n\n test(\"handleToActor and actorToHandle\", async () => {\n const actor = await handles.handleToActor(handle);\n const resolvedHandle = await handles.actorToHandle(actor);\n expect(resolvedHandle).toBe(handle);\n });\n });\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAuC;AACvC,qBAAwB;AACxB,kBAAyC;AAElC,SAAS,YAAY,QAAgB;AAC1C,8BAAS,WAAW,YAAY;AAC9B,UAAM,UAAU,IAAI,uBAAQ;AAAA,MAC1B,MAAM,IAAI,qCAAyB;AAAA,IACrC,CAAC;AAED,4BAAK,mCAAmC,YAAY;AAClD,YAAM,QAAQ,MAAM,QAAQ,cAAc,MAAM;AAChD,YAAM,iBAAiB,MAAM,QAAQ,cAAc,KAAK;AACxD,gCAAO,cAAc,EAAE,KAAK,MAAM;AAAA,IACpC,CAAC;AAAA,EACH,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|