@graffiti-garden/implementation-decentralized 0.1.7 → 0.1.8

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.
@@ -25,7 +25,7 @@ import"./chunk-O4MIY67H.js";var e=`.graffiti-modal {
25
25
  top: 50%;
26
26
  left: 50%;
27
27
  transform: translate(-50%, -50%);
28
- display: flex;
28
+ display: none;
29
29
  flex-direction: column;
30
30
  justify-content: flex-start;
31
31
  align-items: center;
@@ -277,10 +277,19 @@ import"./chunk-O4MIY67H.js";var e=`.graffiti-modal {
277
277
  }
278
278
 
279
279
  .graffiti-modal[open] {
280
+ display: flex;
280
281
  pointer-events: inherit;
281
282
  opacity: 1;
282
283
  }
283
284
 
285
+ @media (prefers-reduced-motion: reduce) {
286
+ .graffiti-modal,
287
+ .graffiti-modal button,
288
+ .graffiti-modal input {
289
+ transition: none;
290
+ }
291
+ }
292
+
284
293
  .graffiti-modal::backdrop {
285
294
  background-color: black;
286
295
  opacity: 0.5;
@@ -302,4 +311,4 @@ import"./chunk-O4MIY67H.js";var e=`.graffiti-modal {
302
311
  overflow: hidden;
303
312
  }
304
313
  `;export{e as default};
305
- //# sourceMappingURL=style-BOBMBTYJ-2YZTO5FX.js.map
314
+ //# sourceMappingURL=style-EDM5B7ME-CSVOYXSW.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../utils/modal/src/style.css"],
4
- "sourcesContent": [".graffiti-modal {\n --back: rgba(26, 26, 26, 0.85);\n --halfback: rgba(80, 80, 80, 0.85);\n --halfback2: rgba(26, 26, 26, 0.85);\n --hover: rgba(202, 122, 204, 0.3);\n --frontfaded: rgba(190, 190, 190);\n --front: rgba(240, 240, 240);\n --emph: rgb(202, 122, 204);\n --blurpix: 3px;\n border-color: var(--emph);\n box-sizing: border-box;\n border-width: 2px;\n padding: 0;\n margin: 0;\n border-radius: 1rem;\n box-shadow: 0 0 2rem black;\n overflow: hidden;\n position: fixed;\n opacity: 0;\n transition: opacity 0.3s;\n pointer-events: none;\n min-width: 95dvw;\n min-height: 95dvh;\n height: 95dvh;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n font-family:\n Inter,\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n Roboto,\n Oxygen,\n Ubuntu,\n Cantarell,\n \"Fira Sans\",\n \"Droid Sans\",\n \"Helvetica Neue\",\n sans-serif;\n color: var(--front);\n font-size: 150%;\n\n * {\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n }\n\n ::selection {\n background: rgba(202, 122, 204, 0.3);\n }\n\n :focus {\n outline: 2px solid var(--front);\n }\n\n header {\n width: 100%;\n display: flex;\n justify-content: flex-end;\n }\n\n main {\n flex: 1;\n max-width: 600px;\n width: 100%;\n gap: 2em;\n padding-inline: clamp(1rem, 4dvw, 3rem);\n padding-block: clamp(1rem, 4dvh, 3rem);\n margin-inline: clamp(1rem, 4dvw, 3rem);\n margin-block: clamp(1rem, 4dvh, 3rem);\n background: var(--back);\n border-radius: 1rem;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n scrollbar-color: var(--emph) rgba(0, 0, 0, 0);\n }\n\n ul {\n list-style-type: none;\n display: flex;\n flex-direction: column;\n gap: 0.5em;\n align-items: stretch;\n justify-content: stretch;\n }\n\n aside {\n color: var(--frontfaded);\n }\n\n .secondary,\n a:not([type=\"button\"]) {\n color: var(--emph);\n }\n\n h1 {\n font-size: 120%;\n font-family:\n Rock Salt,\n cursive,\n sans-serif;\n letter-spacing: 0.1em;\n text-align: center;\n color: var(--front);\n line-height: 1.5em;\n }\n\n h1 a:not([type=\"button\"]) {\n color: inherit;\n }\n\n @media (hover: hover) and (pointer: fine) {\n h1 a:hover {\n background: none;\n color: inherit;\n }\n }\n\n @media (hover: none), (pointer: coarse) {\n h1 a:active {\n background: none;\n color: inherit;\n }\n }\n\n button,\n input[type=\"submit\"],\n input[type=\"text\"],\n a[type=\"button\"] {\n font-size: inherit;\n width: 100%;\n text-align: center;\n display: block;\n border-radius: 1rem;\n border: 2px solid var(--emph);\n padding: 1em;\n padding-top: 0.5em;\n padding-bottom: 0.5em;\n transition: 0.1s;\n text-overflow: ellipsis;\n background: none;\n line-height: 1.2em;\n }\n\n input[type=\"text\"] {\n font-weight: 500;\n background: var(--front);\n text-align: left;\n color: black;\n }\n\n header button {\n border-radius: 0 0 0 1rem;\n border-right: none;\n border-top: none;\n background-color: var(--halfback2);\n width: fit-content;\n position: relative;\n overflow: hidden;\n }\n\n header button::before {\n z-index: -1;\n top: 0;\n left: 0;\n height: 100%;\n position: absolute;\n width: 100%;\n content: \"\";\n background-color: var(--back);\n }\n\n @media (max-height: 600px) {\n main {\n gap: 1em;\n }\n\n h1 {\n font-size: 100%;\n }\n }\n\n @media (max-width: 600px) {\n main {\n border-radius: 0;\n margin: auto;\n overflow: auto;\n }\n\n header button {\n border-radius: 0;\n border-left: none;\n width: 100%;\n }\n\n html {\n justify-content: safe center;\n }\n }\n\n a {\n text-decoration: none;\n }\n\n @media (hover: hover) and (pointer: fine) {\n :is(button, ul a, input[type=\"submit\"]):hover {\n cursor: pointer;\n background: var(--hover);\n color: var(--front);\n }\n\n a:hover {\n text-decoration: underline;\n cursor: pointer;\n }\n }\n\n @media (hover: none), (pointer: coarse) {\n :is(button, ul a, input[type=\"submit\"]):active {\n cursor: pointer;\n background: var(--hover);\n color: var(--front);\n }\n\n a:active {\n text-decoration: underline;\n cursor: pointer;\n }\n }\n\n form {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: stretch;\n gap: 0.5em;\n }\n\n iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n :is(button, a[type=\"button\"], input[type=\"submit\"]).secondary {\n color: rgb(244, 213, 244);\n background: rgba(26, 26, 26, 0.6);\n }\n\n :is(button, a[type=\"button\"], input[type=\"submit\"]):not(.secondary) {\n background: var(--hover);\n color: white;\n }\n\n @media (hover: hover) and (pointer: fine) {\n :is(button, a[type=\"button\"], input[type=\"submit\"]):hover {\n background: rgba(202, 122, 204, 0.6);\n color: white;\n text-decoration: none;\n }\n }\n\n @media (hover: none), (pointer: coarse) {\n :is(button, a[type=\"button\"], input[type=\"submit\"]):active {\n background: rgba(202, 122, 204, 0.6);\n color: white;\n text-decoration: none;\n }\n }\n}\n\n.graffiti-modal[open] {\n pointer-events: inherit;\n opacity: 1;\n}\n\n.graffiti-modal::backdrop {\n background-color: black;\n opacity: 0.5;\n}\n\n.graffiti-modal::before {\n content: \"\";\n position: absolute;\n inset: calc(-1 * var(--blurpix));\n z-index: -1;\n background-image: url(graffiti.jpg);\n background-size: cover;\n background-repeat: no-repeat;\n background-position: 50% 50%;\n filter: blur(var(--blurpix));\n border-radius: inherit;\n pointer-events: none;\n transform: translateZ(0);\n overflow: hidden;\n}\n"],
5
- "mappings": "4BAAA,IAAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;",
4
+ "sourcesContent": [".graffiti-modal {\n --back: rgba(26, 26, 26, 0.85);\n --halfback: rgba(80, 80, 80, 0.85);\n --halfback2: rgba(26, 26, 26, 0.85);\n --hover: rgba(202, 122, 204, 0.3);\n --frontfaded: rgba(190, 190, 190);\n --front: rgba(240, 240, 240);\n --emph: rgb(202, 122, 204);\n --blurpix: 3px;\n border-color: var(--emph);\n box-sizing: border-box;\n border-width: 2px;\n padding: 0;\n margin: 0;\n border-radius: 1rem;\n box-shadow: 0 0 2rem black;\n overflow: hidden;\n position: fixed;\n opacity: 0;\n transition: opacity 0.3s;\n pointer-events: none;\n min-width: 95dvw;\n min-height: 95dvh;\n height: 95dvh;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: none;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n font-family:\n Inter,\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n Roboto,\n Oxygen,\n Ubuntu,\n Cantarell,\n \"Fira Sans\",\n \"Droid Sans\",\n \"Helvetica Neue\",\n sans-serif;\n color: var(--front);\n font-size: 150%;\n\n * {\n box-sizing: border-box;\n padding: 0;\n margin: 0;\n }\n\n ::selection {\n background: rgba(202, 122, 204, 0.3);\n }\n\n :focus {\n outline: 2px solid var(--front);\n }\n\n header {\n width: 100%;\n display: flex;\n justify-content: flex-end;\n }\n\n main {\n flex: 1;\n max-width: 600px;\n width: 100%;\n gap: 2em;\n padding-inline: clamp(1rem, 4dvw, 3rem);\n padding-block: clamp(1rem, 4dvh, 3rem);\n margin-inline: clamp(1rem, 4dvw, 3rem);\n margin-block: clamp(1rem, 4dvh, 3rem);\n background: var(--back);\n border-radius: 1rem;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n scrollbar-color: var(--emph) rgba(0, 0, 0, 0);\n }\n\n ul {\n list-style-type: none;\n display: flex;\n flex-direction: column;\n gap: 0.5em;\n align-items: stretch;\n justify-content: stretch;\n }\n\n aside {\n color: var(--frontfaded);\n }\n\n .secondary,\n a:not([type=\"button\"]) {\n color: var(--emph);\n }\n\n h1 {\n font-size: 120%;\n font-family:\n Rock Salt,\n cursive,\n sans-serif;\n letter-spacing: 0.1em;\n text-align: center;\n color: var(--front);\n line-height: 1.5em;\n }\n\n h1 a:not([type=\"button\"]) {\n color: inherit;\n }\n\n @media (hover: hover) and (pointer: fine) {\n h1 a:hover {\n background: none;\n color: inherit;\n }\n }\n\n @media (hover: none), (pointer: coarse) {\n h1 a:active {\n background: none;\n color: inherit;\n }\n }\n\n button,\n input[type=\"submit\"],\n input[type=\"text\"],\n a[type=\"button\"] {\n font-size: inherit;\n width: 100%;\n text-align: center;\n display: block;\n border-radius: 1rem;\n border: 2px solid var(--emph);\n padding: 1em;\n padding-top: 0.5em;\n padding-bottom: 0.5em;\n transition: 0.1s;\n text-overflow: ellipsis;\n background: none;\n line-height: 1.2em;\n }\n\n input[type=\"text\"] {\n font-weight: 500;\n background: var(--front);\n text-align: left;\n color: black;\n }\n\n header button {\n border-radius: 0 0 0 1rem;\n border-right: none;\n border-top: none;\n background-color: var(--halfback2);\n width: fit-content;\n position: relative;\n overflow: hidden;\n }\n\n header button::before {\n z-index: -1;\n top: 0;\n left: 0;\n height: 100%;\n position: absolute;\n width: 100%;\n content: \"\";\n background-color: var(--back);\n }\n\n @media (max-height: 600px) {\n main {\n gap: 1em;\n }\n\n h1 {\n font-size: 100%;\n }\n }\n\n @media (max-width: 600px) {\n main {\n border-radius: 0;\n margin: auto;\n overflow: auto;\n }\n\n header button {\n border-radius: 0;\n border-left: none;\n width: 100%;\n }\n\n html {\n justify-content: safe center;\n }\n }\n\n a {\n text-decoration: none;\n }\n\n @media (hover: hover) and (pointer: fine) {\n :is(button, ul a, input[type=\"submit\"]):hover {\n cursor: pointer;\n background: var(--hover);\n color: var(--front);\n }\n\n a:hover {\n text-decoration: underline;\n cursor: pointer;\n }\n }\n\n @media (hover: none), (pointer: coarse) {\n :is(button, ul a, input[type=\"submit\"]):active {\n cursor: pointer;\n background: var(--hover);\n color: var(--front);\n }\n\n a:active {\n text-decoration: underline;\n cursor: pointer;\n }\n }\n\n form {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: stretch;\n gap: 0.5em;\n }\n\n iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n :is(button, a[type=\"button\"], input[type=\"submit\"]).secondary {\n color: rgb(244, 213, 244);\n background: rgba(26, 26, 26, 0.6);\n }\n\n :is(button, a[type=\"button\"], input[type=\"submit\"]):not(.secondary) {\n background: var(--hover);\n color: white;\n }\n\n @media (hover: hover) and (pointer: fine) {\n :is(button, a[type=\"button\"], input[type=\"submit\"]):hover {\n background: rgba(202, 122, 204, 0.6);\n color: white;\n text-decoration: none;\n }\n }\n\n @media (hover: none), (pointer: coarse) {\n :is(button, a[type=\"button\"], input[type=\"submit\"]):active {\n background: rgba(202, 122, 204, 0.6);\n color: white;\n text-decoration: none;\n }\n }\n}\n\n.graffiti-modal[open] {\n display: flex;\n pointer-events: inherit;\n opacity: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .graffiti-modal,\n .graffiti-modal button,\n .graffiti-modal input {\n transition: none;\n }\n}\n\n.graffiti-modal::backdrop {\n background-color: black;\n opacity: 0.5;\n}\n\n.graffiti-modal::before {\n content: \"\";\n position: absolute;\n inset: calc(-1 * var(--blurpix));\n z-index: -1;\n background-image: url(graffiti.jpg);\n background-size: cover;\n background-repeat: no-repeat;\n background-position: 50% 50%;\n filter: blur(var(--blurpix));\n border-radius: inherit;\n pointer-events: none;\n transform: translateZ(0);\n overflow: hidden;\n}\n"],
5
+ "mappings": "4BAAA,IAAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;",
6
6
  "names": ["style_default"]
7
7
  }
@@ -113,6 +113,7 @@ class GraffitiDecentralized {
113
113
  allowedAttestations: this.allowedAttestations
114
114
  });
115
115
  modal = typeof window === "undefined" ? void 0 : new import_modal.GraffitiModal({
116
+ ariaLabel: "Graffiti Log In",
116
117
  useTemplateHTML: () => import("./login-dialog.html").then(({ template }) => template),
117
118
  onManualClose: () => {
118
119
  const event = new CustomEvent("login", {
@@ -154,6 +155,7 @@ class GraffitiDecentralized {
154
155
  this.login_(handle2);
155
156
  return;
156
157
  }
158
+ this.modal?.close();
157
159
  const actor = detail.session.actor;
158
160
  let handle;
159
161
  try {
@@ -209,6 +211,7 @@ class GraffitiDecentralized {
209
211
  async login_(proposedHandle) {
210
212
  if (typeof window !== "undefined") {
211
213
  let template;
214
+ let focusAfterOpen = null;
212
215
  if (proposedHandle !== void 0) {
213
216
  template = await this.modal?.displayTemplate("graffiti-login-handle");
214
217
  const input = template?.querySelector(
@@ -217,7 +220,7 @@ class GraffitiDecentralized {
217
220
  const rememberedHandle = proposedHandle || this.getRememberedHandleFromBrowserStorage();
218
221
  if (input) input.value = rememberedHandle ?? "";
219
222
  input?.addEventListener("focus", () => input?.select());
220
- setTimeout(() => input?.focus(), 0);
223
+ focusAfterOpen = input;
221
224
  template?.querySelector("#graffiti-login-handle-form")?.addEventListener("submit", async (e) => {
222
225
  e.preventDefault();
223
226
  input?.setAttribute("disabled", "true");
@@ -262,12 +265,6 @@ class GraffitiDecentralized {
262
265
  e.preventDefault();
263
266
  this.login_("");
264
267
  });
265
- setTimeout(
266
- () => template?.querySelector(
267
- "#graffiti-login-new"
268
- )?.focus(),
269
- 0
270
- );
271
268
  }
272
269
  const createUrl = new URL(this.identityCreatorEndpoint);
273
270
  createUrl.searchParams.set(
@@ -278,6 +275,7 @@ class GraffitiDecentralized {
278
275
  "#graffiti-login-new"
279
276
  );
280
277
  createLink?.setAttribute("href", createUrl.toString());
278
+ if (proposedHandle === void 0) focusAfterOpen = createLink ?? null;
281
279
  if (this.replaceInitialLoginHistoryEntry) {
282
280
  createLink?.addEventListener("click", (event) => {
283
281
  if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
@@ -286,6 +284,7 @@ class GraffitiDecentralized {
286
284
  });
287
285
  }
288
286
  await this.modal?.open();
287
+ focusAfterOpen?.focus();
289
288
  } else {
290
289
  const readline = await import("readline").catch((e) => {
291
290
  throw new Error(
@@ -322,7 +321,6 @@ class GraffitiDecentralized {
322
321
  const provider = template?.querySelector("#graffiti-provider");
323
322
  if (provider) provider.value = defaultProvider.host;
324
323
  provider?.addEventListener("focus", () => provider.select());
325
- setTimeout(() => provider?.focus(), 0);
326
324
  template?.querySelector("#graffiti-login-provider-form")?.addEventListener("submit", (event) => {
327
325
  event.preventDefault();
328
326
  try {
@@ -345,6 +343,7 @@ class GraffitiDecentralized {
345
343
  void this.login_("");
346
344
  });
347
345
  await this.modal?.open();
346
+ provider?.focus();
348
347
  }
349
348
  rememberHandleInBrowserStorage(handle) {
350
349
  if (typeof window === "undefined") return;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/3-protocol/4-graffiti.ts"],
4
- "sourcesContent": ["import type { JSONSchema } from \"json-schema-to-ts\";\nimport {\n GraffitiErrorNotFound,\n maskGraffitiObject,\n type Graffiti,\n type GraffitiLoginEvent,\n type GraffitiObjectBase,\n type GraffitiSession,\n type GraffitiObject,\n unpackObjectUrl,\n compileGraffitiObjectSchema,\n GraffitiErrorSchemaMismatch,\n GraffitiErrorForbidden,\n GraffitiErrorTooLarge,\n isMediaAcceptable,\n GraffitiErrorNotAcceptable,\n GraffitiErrorCursorExpired,\n GraffitiErrorInvalidSchema,\n type GraffitiObjectStream,\n} from \"@graffiti-garden/api\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\nimport {\n encode as dagCborEncode,\n decode as dagCborDecode,\n} from \"@ipld/dag-cbor\";\n\nimport { DecentralizedIdentifiers } from \"../1-services/2-dids\";\nimport { Authorization } from \"../1-services/1-authorization\";\nimport { StorageBuckets } from \"../1-services/3-storage-buckets\";\nimport {\n Inboxes,\n LABELED_MESSAGE_LABEL_KEY,\n LABELED_MESSAGE_MESSAGE_KEY,\n MESSAGE_METADATA_KEY,\n MESSAGE_OBJECT_KEY,\n MESSAGE_TAGS_KEY,\n type LabeledMessage,\n type MessageStream,\n} from \"../1-services/4-inboxes\";\nimport { GraffitiErrorUnauthorized } from \"../1-services/utilities\";\n\nimport {\n StringEncoder,\n STRING_ENCODER_METHOD_BASE64URL,\n} from \"../2-primitives/1-string-encoding\";\nimport { ContentAddresses } from \"../2-primitives/2-content-addresses\";\nimport {\n CHANNEL_ATTESTATION_METHOD_SHA256_ED25519,\n ChannelAttestations,\n} from \"../2-primitives/3-channel-attestations\";\nimport { AllowedAttestations } from \"../2-primitives/4-allowed-attestations\";\n\nimport { Handles } from \"./2-handles\";\nimport {\n Sessions,\n DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX,\n DID_SERVICE_TYPE_GRAFFITI_INBOX,\n DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET,\n DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,\n} from \"./1-sessions\";\nimport {\n decodeObjectUrl,\n MAX_OBJECT_SIZE_BYTES,\n ObjectEncoding,\n} from \"./3-object-encoding\";\n\nimport { GraffitiModal } from \"@graffiti-garden/modal\";\nimport {\n type infer as infer_,\n custom,\n string,\n boolean,\n strictObject,\n array,\n int,\n nonnegative,\n optional,\n extend,\n union,\n record,\n url,\n} from \"zod/mini\";\n\nconst Uint8ArraySchema = custom<Uint8Array>(\n (v): v is Uint8Array => v instanceof Uint8Array,\n);\nconst MESSAGE_DATA_STORAGE_BUCKET_KEY = \"k\";\nconst MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY = \"t\";\nconst MessageMetadataBaseSchema = strictObject({\n [MESSAGE_DATA_STORAGE_BUCKET_KEY]: string(),\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: optional(string()),\n});\nconst MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY = \"id\";\nconst MESSAGE_DATA_ANNOUNCEMENT_ENDPOINT_KEY = \"e\";\nconst MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY = \"a\";\nconst MessageMetadataAnnouncementsSchema = array(\n strictObject({\n [MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]: string(),\n [MESSAGE_DATA_ANNOUNCEMENT_ENDPOINT_KEY]: optional(url()),\n [MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY]: optional(url()),\n }),\n);\nconst MESSAGE_DATA_ALLOWED_TICKETS_KEY = \"s\";\nconst MESSAGE_DATA_ANNOUNCEMENTS_KEY = \"n\";\nconst MessageMetaDataSelfSchema = extend(MessageMetadataBaseSchema, {\n [MESSAGE_DATA_ALLOWED_TICKETS_KEY]: optional(array(Uint8ArraySchema)),\n [MESSAGE_DATA_ANNOUNCEMENTS_KEY]: MessageMetadataAnnouncementsSchema,\n});\nconst MESSAGE_DATA_ALLOWED_TICKET_KEY = \"a\";\nconst MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY = \"i\";\nconst MessageMetadataPrivateSchema = extend(MessageMetadataBaseSchema, {\n [MESSAGE_DATA_ALLOWED_TICKET_KEY]: Uint8ArraySchema,\n [MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY]: int().check(nonnegative()),\n});\nconst MessageMetadataSchema = union([\n MessageMetadataBaseSchema,\n MessageMetaDataSelfSchema,\n MessageMetadataPrivateSchema,\n]);\ntype MessageMetadataBase = infer_<typeof MessageMetadataBaseSchema>;\ntype MessageMetadata = infer_<typeof MessageMetadataSchema>;\ntype MessageMetadataAnnouncements = infer_<\n typeof MessageMetadataAnnouncementsSchema\n>;\n\nconst MESSAGE_LABEL_UNLABELED = 0;\nconst MESSAGE_LABEL_VALID = 1;\nconst MESSAGE_LABEL_TRASH = 2;\nconst MESSAGE_LABEL_INVALID = 3;\n\nexport interface GraffitiDecentralizedOptions {\n identityCreatorEndpoint?: string;\n defaultInboxEndpoints?: string[];\n /** For login hosts that already have the application in the preceding history entry. */\n replaceInitialLoginHistoryEntry?: boolean;\n}\n\nconst CONCURRENCY = 128;\nconst LOCAL_STORAGE_REMEMBERED_HANDLE_KEY = \"graffiti-login-remembered-handle\";\n\nexport class GraffitiDecentralized implements Graffiti {\n protected readonly dids = new DecentralizedIdentifiers();\n protected readonly authorization = new Authorization();\n protected readonly storageBuckets = new StorageBuckets();\n protected readonly inboxes = new Inboxes();\n\n protected readonly stringEncoder = new StringEncoder();\n protected readonly contentAddresses = new ContentAddresses();\n protected readonly channelAttestations = new ChannelAttestations();\n protected readonly allowedAttestations = new AllowedAttestations();\n\n protected readonly sessions = new Sessions({\n dids: this.dids,\n authorization: this.authorization,\n storageBuckets: this.storageBuckets,\n inboxes: this.inboxes,\n });\n protected readonly handles = new Handles({ dids: this.dids });\n protected readonly objectEncoding = new ObjectEncoding({\n stringEncoder: this.stringEncoder,\n contentAddresses: this.contentAddresses,\n channelAttestations: this.channelAttestations,\n allowedAttestations: this.allowedAttestations,\n });\n\n protected readonly modal: GraffitiModal | undefined =\n typeof window === \"undefined\"\n ? undefined\n : new GraffitiModal({\n useTemplateHTML: () =>\n import(\"./login-dialog.html\").then(({ template }) => template),\n onManualClose: () => {\n const event = new CustomEvent(\"login\", {\n detail: {\n error: new Error(\"User cancelled login\"),\n manual: true,\n },\n });\n this.sessionEvents.dispatchEvent(event);\n },\n });\n\n protected readonly defaultInboxEndpoints: string[];\n protected readonly identityCreatorEndpoint: string;\n protected readonly replaceInitialLoginHistoryEntry: boolean;\n constructor(options?: GraffitiDecentralizedOptions) {\n this.replaceInitialLoginHistoryEntry =\n options?.replaceInitialLoginHistoryEntry ?? false;\n if (this.replaceInitialLoginHistoryEntry) {\n this.sessions.initialAuthorizationNavigation = \"replace\";\n }\n this.defaultInboxEndpoints = options?.defaultInboxEndpoints ?? [\n \"https://graffiti.actor/i/shared\",\n ];\n this.identityCreatorEndpoint =\n options?.identityCreatorEndpoint ?? \"https://graffiti.actor/create\";\n\n this.sessionEvents.addEventListener(\"login\", async (event) => {\n if (!(event instanceof CustomEvent)) return;\n const detail = event.detail as GraffitiLoginEvent[\"detail\"];\n\n if (detail.error !== undefined) {\n // If \"manual\", the window was closed by the user, nothing to do\n if (\"manual\" in detail && detail.manual) return;\n\n alert(\"Login failed: \" + detail.error.message);\n const actor = detail.session?.actor;\n let handle: string | undefined;\n if (actor) {\n try {\n handle = await this.actorToHandle(actor);\n } catch (error) {\n console.error(\"Failed to handle actor:\", error);\n }\n }\n // Open the login window again with the failed actor\n this.login_(handle);\n return;\n }\n\n const actor = detail.session.actor;\n\n let handle: string | undefined;\n try {\n handle = await this.actorToHandle(actor);\n } catch (error) {\n console.error(\"Failed to load handle from actor:\", error);\n }\n\n if (handle) {\n this.rememberHandleInBrowserStorage(handle);\n }\n });\n\n // If any methods throw an unauthorized error,\n // log out the used session\n for (const method of [\n \"post\",\n \"get\",\n \"delete\",\n \"postMedia\",\n \"getMedia\",\n \"deleteMedia\",\n ]) {\n const fn = (this as any)[method];\n (this as any)[method] = async (...args: unknown[]) => {\n try {\n return await fn(...args);\n } catch (e) {\n const session = args[args.length - 1] as any;\n await this.tryLogoutIfUnauthorized(e, session);\n throw e;\n }\n };\n }\n }\n\n readonly actorToHandle: Graffiti[\"actorToHandle\"] =\n this.handles.actorToHandle.bind(this.handles);\n readonly handleToActor: Graffiti[\"handleToActor\"] =\n this.handles.handleToActor.bind(this.handles);\n readonly sessionEvents: Graffiti[\"sessionEvents\"] =\n this.sessions.sessionEvents;\n\n login: Graffiti[\"login\"] = async (actor?: string) => {\n try {\n let proposedHandle: string | undefined;\n try {\n proposedHandle = actor ? await this.actorToHandle(actor) : undefined;\n } catch (error) {\n console.error(\"Error fetching handle for actor:\", error);\n }\n\n await this.login_(proposedHandle);\n } catch (e) {\n const loginError: GraffitiLoginEvent = new CustomEvent(\"login\", {\n detail: {\n error: e instanceof Error ? e : new Error(String(e)),\n },\n });\n this.sessionEvents.dispatchEvent(loginError);\n }\n };\n protected async login_(proposedHandle?: string) {\n if (typeof window !== \"undefined\") {\n let template: HTMLElement | undefined;\n if (proposedHandle !== undefined) {\n template = await this.modal?.displayTemplate(\"graffiti-login-handle\");\n const input = template?.querySelector(\n \"#username\",\n ) as HTMLInputElement | null;\n const rememberedHandle =\n proposedHandle || this.getRememberedHandleFromBrowserStorage();\n if (input) input.value = rememberedHandle ?? \"\";\n input?.addEventListener(\"focus\", () => input?.select());\n setTimeout(() => input?.focus(), 0);\n\n template\n ?.querySelector(\"#graffiti-login-handle-form\")\n ?.addEventListener(\"submit\", async (e) => {\n e.preventDefault();\n input?.setAttribute(\"disabled\", \"true\");\n const submitButton = template?.querySelector(\n \"#graffiti-login-handle-submit\",\n ) as HTMLButtonElement | null;\n submitButton?.setAttribute(\"disabled\", \"true\");\n submitButton && (submitButton.innerHTML = \"Logging in...\");\n\n if (!input?.value) {\n alert(\"No handle provided\");\n this.login_(\"\");\n return;\n }\n\n let handle = input.value;\n if (!handle.includes(\".\") && !handle.startsWith(\"localhost\")) {\n const defaultHost = new URL(this.identityCreatorEndpoint).host;\n handle = `${handle}.${defaultHost}`;\n }\n\n let actor: string;\n try {\n actor = await this.handleToActor(handle);\n } catch (e) {\n alert(\"Could not find an identity associated with that handle.\");\n this.login_(handle);\n return;\n }\n\n try {\n await this.sessions.login(actor);\n } catch (e) {\n alert(\"Error logging in.\");\n console.error(e);\n this.login_(handle);\n }\n });\n template\n ?.querySelector(\"#graffiti-login-forgot\")\n ?.addEventListener(\"click\", (e) => {\n e.preventDefault();\n void this.loginWithoutHandle();\n });\n } else {\n template = await this.modal?.displayTemplate(\"graffiti-login-welcome\");\n template\n ?.querySelector(\"#graffiti-login-existing\")\n ?.addEventListener(\"click\", (e) => {\n e.preventDefault();\n this.login_(\"\");\n });\n\n setTimeout(\n () =>\n (\n template?.querySelector(\n \"#graffiti-login-new\",\n ) as HTMLAnchorElement\n )?.focus(),\n 0,\n );\n }\n\n const createUrl = new URL(this.identityCreatorEndpoint);\n createUrl.searchParams.set(\n \"redirect_uri\",\n encodeURIComponent(window.location.toString()),\n );\n const createLink = template?.querySelector<HTMLAnchorElement>(\n \"#graffiti-login-new\",\n );\n createLink?.setAttribute(\"href\", createUrl.toString());\n if (this.replaceInitialLoginHistoryEntry) {\n createLink?.addEventListener(\"click\", (event) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n ) return;\n event.preventDefault();\n window.location.replace(createUrl.toString());\n });\n }\n\n await this.modal?.open();\n } else {\n // Node.js environment\n const readline = await import(\"readline\").catch((e) => {\n throw new Error(\n \"Unrecognized environment: neither window nor readline\",\n );\n });\n\n console.log(\n \"If you do not already have a Graffiti handle, you can create one here:\",\n );\n console.log(this.identityCreatorEndpoint);\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const handle: string | undefined = await new Promise((resolve) => {\n rl.question(\n `Please enter your handle${proposedHandle ? ` (default: ${proposedHandle})` : \"\"}: `,\n (input) => {\n rl.close();\n resolve(input || proposedHandle);\n },\n );\n });\n\n if (!handle) {\n throw new Error(\"No handle provided\");\n }\n\n // Convert the handle to an actor\n const actor = await this.handleToActor(handle);\n\n await this.sessions.login(actor);\n }\n }\n\n protected async loginWithoutHandle() {\n const template = await this.modal?.displayTemplate(\"graffiti-login-provider\");\n const defaultProvider = new URL(\"/\", this.identityCreatorEndpoint);\n const provider = template?.querySelector(\"#graffiti-provider\") as HTMLInputElement | null;\n if (provider) provider.value = defaultProvider.host;\n provider?.addEventListener(\"focus\", () => provider.select());\n setTimeout(() => provider?.focus(), 0);\n\n template\n ?.querySelector(\"#graffiti-login-provider-form\")\n ?.addEventListener(\"submit\", (event) => {\n event.preventDefault();\n try {\n const domain = provider?.value.trim() ?? \"\";\n const origin = domain === defaultProvider.host\n ? defaultProvider\n : new URL(`https://${domain}`);\n if (\n !origin.hostname || origin.username || origin.password ||\n origin.pathname !== \"/\" || origin.search || origin.hash\n ) throw new Error(\"Invalid provider domain\");\n\n const url = new URL(\"/forgot-handle\", origin);\n url.searchParams.set(\"redirect_uri\", window.location.toString());\n if (this.replaceInitialLoginHistoryEntry) {\n window.location.replace(url.toString());\n } else {\n window.location.assign(url.toString());\n }\n } catch {\n alert(\"Enter a valid provider domain.\");\n }\n });\n\n template\n ?.querySelector(\"#graffiti-login-provider-back\")\n ?.addEventListener(\"click\", (event) => {\n event.preventDefault();\n void this.login_(\"\");\n });\n\n await this.modal?.open();\n }\n\n protected rememberHandleInBrowserStorage(handle: string) {\n if (typeof window === \"undefined\") return;\n\n try {\n window.localStorage.setItem(LOCAL_STORAGE_REMEMBERED_HANDLE_KEY, handle);\n } catch (error) {\n console.error(\"Failed to remember handle in browser storage:\", error);\n }\n }\n\n protected getRememberedHandleFromBrowserStorage() {\n if (typeof window === \"undefined\") return undefined;\n\n try {\n return (\n window.localStorage.getItem(LOCAL_STORAGE_REMEMBERED_HANDLE_KEY) ??\n undefined\n );\n } catch (error) {\n console.error(\"Failed to load handle from browser storage:\", error);\n return undefined;\n }\n }\n\n logout: Graffiti[\"logout\"] = async (session) => {\n await this.sessions.logout(session.actor);\n };\n\n // @ts-ignore\n post: Graffiti[\"post\"] = async (...args) => {\n const [partialObject, session] = args;\n const resolvedSession = this.sessions.resolveSession(session);\n\n // Encode the object\n const { object, tags, objectBytes, allowedTickets } =\n await this.objectEncoding.encode<{}>(partialObject, session.actor);\n\n // Generate a random key under which to store the object\n // If the object is private, this means no one will be able to\n // fetch the object, even if they know its URL.\n // If the object is public but in some secret channel, the storage\n // location means the object can be moved around or \"rotated\"\n // without changing its URL.\n const storageBucketKeyBytes = randomBytes();\n const storageBucketKey = await this.stringEncoder.encode(\n STRING_ENCODER_METHOD_BASE64URL,\n storageBucketKeyBytes,\n );\n\n // Store the object at the random key\n await this.storageBuckets.put(\n resolvedSession.storageBucket.serviceEndpoint,\n storageBucketKey,\n objectBytes,\n resolvedSession.storageBucket.token,\n );\n\n // Announce the object, its key,\n // and other metadata to appropriate inboxes\n await this.announceObject(\n object,\n tags,\n allowedTickets,\n storageBucketKey,\n session,\n );\n\n return object;\n };\n\n get: Graffiti[\"get\"] = async (...args) => {\n const [url, schema, session] = args;\n let services: { token?: string; serviceEndpoint: string }[];\n const validator = await compileGraffitiObjectSchema(schema);\n\n if (session) {\n // If logged in, first search one's\n // personal inbox, then any shared inboxes\n const resolvedSession = this.sessions.resolveSession(session);\n services = [\n resolvedSession.personalInbox,\n ...resolvedSession.sharedInboxes,\n ];\n } else {\n // Otherwise, search the default inboxes\n services = this.defaultInboxEndpoints.map((s) => ({\n serviceEndpoint: s,\n }));\n }\n\n // Search the inboxes for all objects\n // matching the tag, object.url\n const objectUrl = unpackObjectUrl(url);\n const tags = [new TextEncoder().encode(objectUrl)];\n for (const service of services) {\n let object: GraffitiObjectBase | undefined = undefined;\n\n const iterator = this.querySingleEndpoint<{}>(\n service.serviceEndpoint,\n {\n tags,\n objectSchema: {},\n },\n service.token,\n session?.actor,\n );\n\n for await (const result of iterator) {\n if (result.object.url !== objectUrl) continue;\n if (result.tombstone) {\n object = undefined;\n } else {\n object = result.object;\n }\n }\n\n if (object) {\n if (!validator(object)) {\n throw new GraffitiErrorSchemaMismatch(\n \"Object exists but does not match the supplied schema\",\n );\n }\n\n return object;\n }\n }\n\n throw new GraffitiErrorNotFound(\"Object not found\");\n };\n\n delete: Graffiti[\"delete\"] = async (url, session) => {\n const resolvedSession = this.sessions.resolveSession(session);\n\n const objectUrl = unpackObjectUrl(url);\n\n const { actor } = decodeObjectUrl(objectUrl);\n if (actor !== session.actor) {\n throw new GraffitiErrorForbidden(\"Cannot delete someone else's actor\");\n }\n\n // Look in one's personal inbox for the object\n const iterator = this.querySingleEndpoint<{}>(\n resolvedSession.personalInbox.serviceEndpoint,\n {\n tags: [new TextEncoder().encode(objectUrl)],\n objectSchema: {},\n },\n resolvedSession.personalInbox.token,\n );\n let existing: SingleEndpointQueryResult<{}> | undefined;\n for await (const result of iterator) {\n if (result.object.url !== objectUrl) continue;\n if (result.tombstone) {\n existing = undefined;\n } else {\n existing = result;\n }\n }\n if (!existing) {\n throw new GraffitiErrorNotFound(`Object ${objectUrl} not found`);\n }\n const {\n object,\n storageBucketKey,\n tags,\n allowedTickets,\n announcements,\n messageId,\n } = existing;\n\n // Delete the object from the actor's own storage bucket\n await this.storageBuckets.delete(\n resolvedSession.storageBucket.serviceEndpoint,\n storageBucketKey,\n resolvedSession.storageBucket.token,\n );\n\n // Announce the deletion to all inboxes\n await this.announceObject(\n object,\n tags,\n allowedTickets,\n storageBucketKey,\n session,\n [\n ...(announcements ?? []),\n // Make sure we delete from our own inbox too\n {\n [MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY]: session.actor,\n [MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]: messageId,\n },\n ],\n );\n\n return object;\n };\n\n postMedia: Graffiti[\"postMedia\"] = async (...args) => {\n const [media, session] = args;\n\n const type = media.data.type;\n\n const resolvedSession = this.sessions.resolveSession(session);\n\n // Generate a random storage key\n const keyBytes = randomBytes();\n const key = await this.stringEncoder.encode(\n STRING_ENCODER_METHOD_BASE64URL,\n keyBytes,\n );\n\n // Store the media at that key\n await this.storageBuckets.put(\n resolvedSession.storageBucket.serviceEndpoint,\n key,\n new Uint8Array(await media.data.arrayBuffer()),\n resolvedSession.storageBucket.token,\n );\n\n // Create an object\n const { url } = await this.post<typeof MEDIA_OBJECT_SCHEMA>(\n {\n value: {\n key,\n type,\n size: media.data.size,\n },\n channels: [],\n allowed: media.allowed,\n },\n session,\n );\n\n return url;\n };\n\n getMedia: Graffiti[\"getMedia\"] = async (...args) => {\n const [mediaUrl, accept, session] = args;\n\n if (\n accept?.maxBytes !== undefined &&\n (!Number.isSafeInteger(accept.maxBytes) || accept.maxBytes < 0)\n ) {\n throw new TypeError(\"maxBytes must be a nonnegative safe integer\");\n }\n\n const object = await this.get<typeof MEDIA_OBJECT_SCHEMA>(\n mediaUrl,\n MEDIA_OBJECT_SCHEMA,\n session,\n );\n\n const { key, type, size } = object.value;\n\n if (accept?.maxBytes !== undefined && size > accept.maxBytes) {\n throw new GraffitiErrorTooLarge(\"File size exceeds limit\");\n }\n\n // Make sure it adheres to requirements.accept\n if (accept?.types) {\n if (!isMediaAcceptable(type, accept.types)) {\n throw new GraffitiErrorNotAcceptable(\n `Unacceptable media type, ${type}`,\n );\n }\n }\n\n // Get the actor's storage bucket endpoint\n const actorDocument = await this.dids.resolve(object.actor);\n const storageBucketService = actorDocument?.service?.find(\n (service) =>\n service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET &&\n service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,\n );\n if (!storageBucketService) {\n throw new GraffitiErrorNotFound(\n `Actor ${object.actor} has no storage bucket service`,\n );\n }\n if (typeof storageBucketService.serviceEndpoint !== \"string\") {\n throw new GraffitiErrorNotFound(\n `Actor ${object.actor} does not have a valid storage bucket endpoint`,\n );\n }\n const storageBucketEndpoint = storageBucketService.serviceEndpoint;\n\n const data = await this.storageBuckets.get(\n storageBucketEndpoint,\n key,\n size,\n );\n\n const blob = new Blob([data.slice()], { type });\n\n return {\n data: blob,\n actor: object.actor,\n allowed: object.allowed,\n };\n };\n\n deleteMedia: Graffiti[\"deleteMedia\"] = async (...args) => {\n const [mediaUrl, session] = args;\n\n const resolvedSession = this.sessions.resolveSession(session);\n\n const result = await this.delete(mediaUrl, session);\n\n if (!(\"key\" in result.value && typeof result.value.key === \"string\"))\n throw new Error(\n \"Deleted object was not media: \" + JSON.stringify(result, null, 2),\n );\n\n await this.storageBuckets.delete(\n resolvedSession.storageBucket.serviceEndpoint,\n result.value.key,\n resolvedSession.storageBucket.token,\n );\n };\n\n async *discoverMeta<Schema extends JSONSchema>(\n channels: string[],\n schema: Schema,\n cursors: {\n [endpoint: string]: string;\n },\n session?: GraffitiSession | null,\n ): GraffitiObjectStream<Schema> {\n const tombstones = new Map<string, boolean>();\n\n let allInboxes: { serviceEndpoint: string; token?: string }[];\n if (session) {\n const resolvedSession = this.sessions.resolveSession(session);\n allInboxes = [\n resolvedSession.personalInbox,\n ...resolvedSession.sharedInboxes,\n ];\n } else {\n allInboxes = this.defaultInboxEndpoints.map((e) => ({\n serviceEndpoint: e,\n }));\n }\n\n // Make sure all cursors are represented by an inbox\n for (const endpoint in cursors) {\n if (!allInboxes.some((i) => i.serviceEndpoint === endpoint)) {\n throw new GraffitiErrorForbidden(\n \"Cursor does not match actor's inboxes\",\n );\n }\n }\n\n // Turn the channels into tags\n const tags = await Promise.all(\n channels.map((c) =>\n this.channelAttestations.register(\n CHANNEL_ATTESTATION_METHOD_SHA256_ED25519,\n c,\n ),\n ),\n );\n\n const iterators: SingleEndpointQueryIterator<Schema>[] = allInboxes.map(\n (i) => {\n const cursor = cursors[i.serviceEndpoint];\n return this.querySingleEndpoint<Schema>(\n i.serviceEndpoint,\n cursor\n ? {\n cursor,\n }\n : {\n tags,\n objectSchema: schema,\n },\n i.token,\n session?.actor,\n );\n },\n );\n\n let indexedIteratorNexts = iterators.map<\n Promise<IndexedSingleEndpointQueryResult<Schema>>\n >(async (it, index) => indexedSingleEndpointQueryNext<Schema>(it, index));\n let active = indexedIteratorNexts.length;\n\n try {\n while (active > 0) {\n const next: IndexedSingleEndpointQueryResult<Schema> =\n await Promise.race<any>(indexedIteratorNexts);\n if (next.error !== undefined) {\n // Remove it from the race\n indexedIteratorNexts[next.index] = new Promise(() => {});\n active--;\n yield {\n error: next.error,\n origin: allInboxes[next.index].serviceEndpoint,\n };\n this.tryLogoutIfUnauthorized(next.error, session);\n } else if (next.result.done) {\n // Store the cursor for future use\n const inbox = allInboxes[next.index];\n cursors[inbox.serviceEndpoint] = next.result.value;\n // Remove it from the race\n indexedIteratorNexts[next.index] = new Promise(() => {});\n active--;\n } else {\n // Re-arm the iterator\n indexedIteratorNexts[next.index] =\n indexedSingleEndpointQueryNext<Schema>(\n iterators[next.index],\n next.index,\n );\n const { object, tombstone, tags: receivedTags } = next.result.value;\n if (tombstone) {\n if (tombstones.get(object.url) === true) continue;\n tombstones.set(object.url, true);\n yield {\n tombstone,\n object: { url: object.url },\n };\n } else {\n // Filter already seen\n if (tombstones.get(object.url) === false) continue;\n\n // Fill in the matched channels\n const matchedTagIndices = tags.reduce<number[]>(\n (acc, tag, tagIndex) => {\n for (const receivedTag of receivedTags) {\n if (\n tag.length === receivedTag.length &&\n tag.every((b, i) => receivedTag[i] === b)\n ) {\n acc.push(tagIndex);\n break;\n }\n }\n return acc;\n },\n [],\n );\n const matchedChannels = matchedTagIndices.map(\n (index) => channels[index],\n );\n if (matchedChannels.length === 0) {\n yield {\n error: new Error(\n \"Inbox returned object without matching channels\",\n ),\n origin: allInboxes[next.index].serviceEndpoint,\n };\n }\n tombstones.set(object.url, false);\n yield {\n object: {\n ...object,\n channels: matchedChannels,\n },\n };\n }\n }\n }\n } catch (e) {\n this.tryLogoutIfUnauthorized(e, session);\n throw e;\n } finally {\n await Promise.all(\n iterators.map<Promise<void>>(async (it) => {\n await it.return(\"\");\n }),\n );\n }\n\n return {\n cursor: JSON.stringify({\n channels,\n cursors,\n } satisfies infer_<typeof CursorSchema>),\n };\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const [channels, schema, session] = args;\n return this.discoverMeta<(typeof args)[1]>(channels, schema, {}, session);\n };\n\n // @ts-ignore\n continueDiscover: Graffiti[\"continueDiscover\"] = (...args) => {\n const [cursor, session] = args;\n // Extract the channels from the cursor\n let channels: string[];\n let cursors: { [endpoint: string]: string };\n try {\n const json = JSON.parse(cursor);\n const parsed = CursorSchema.parse(json);\n channels = parsed.channels;\n cursors = parsed.cursors;\n } catch (error) {\n return (async function* () {\n throw new GraffitiErrorCursorExpired(\"Invalid cursor\");\n })();\n }\n return this.discoverMeta<{}>(channels, {}, cursors, session);\n };\n\n protected async tryLogoutIfUnauthorized(\n e: unknown,\n session?: GraffitiSession | null,\n ) {\n if (e instanceof GraffitiErrorUnauthorized && session) {\n await this.sessions.logout(session.actor);\n }\n }\n\n async announceObject(\n object: GraffitiObjectBase,\n tags: Uint8Array[],\n allowedTickets: Uint8Array[] | undefined,\n storageBucketKey: string,\n session: GraffitiSession,\n priorAnnouncements?: MessageMetadataAnnouncements,\n ): Promise<void> {\n const resolvedSession = this.sessions.resolveSession(session);\n\n const metadataBase: MessageMetadataBase = {\n [MESSAGE_DATA_STORAGE_BUCKET_KEY]: storageBucketKey,\n };\n\n const announcements: MessageMetadataAnnouncements = [];\n const allowed = object.allowed;\n if (Array.isArray(allowed)) {\n if (!allowedTickets || allowedTickets.length !== allowed.length) {\n throw new Error(\n \"If allowed actors are specified, there must be a corresponding ticket for each allowed actor\",\n );\n }\n\n // Send the object to each allowed recipient's personal inbox\n const results = await Promise.allSettled(\n allowed.map(async (recipient, recipientIndex) => {\n // Mask the object to not include any channels\n // and only include the recipient actor on the allowed list\n const copy = JSON.parse(JSON.stringify(object)) as GraffitiObjectBase;\n const masked = maskGraffitiObject(copy, [], recipient);\n\n // Get the recipient's inbox\n const actorDocument = await this.dids.resolve(recipient);\n const personalInbox = actorDocument.service?.find(\n (service) =>\n service.type === DID_SERVICE_TYPE_GRAFFITI_INBOX &&\n service.id === DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX,\n );\n if (!personalInbox) {\n throw new Error(\n `Recipient ${recipient} does not have a personal inbox`,\n );\n }\n if (typeof personalInbox.serviceEndpoint !== \"string\") {\n throw new Error(\n `Recipient ${recipient} does not have a valid personal inbox endpoint`,\n );\n }\n\n const tombstonedMessageId = priorAnnouncements\n ? priorAnnouncements.find(\n (a) => a[MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY] === recipient,\n )?.[MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]\n : undefined;\n\n // Announce to the inbox\n const privateMetadata: MessageMetadata = {\n ...metadataBase,\n ...(tombstonedMessageId\n ? {\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n }\n : {}),\n [MESSAGE_DATA_ALLOWED_TICKET_KEY]: allowedTickets[recipientIndex],\n [MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY]: recipientIndex,\n };\n const messageId = await this.inboxes.send(\n personalInbox.serviceEndpoint,\n {\n [MESSAGE_TAGS_KEY]: tags,\n [MESSAGE_OBJECT_KEY]: masked,\n [MESSAGE_METADATA_KEY]: dagCborEncode(privateMetadata),\n },\n );\n\n announcements.push({\n [MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]: messageId,\n [MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY]: recipient,\n });\n }),\n );\n\n for (const [index, result] of results.entries()) {\n if (result.status === \"rejected\") {\n const recipient = allowed[index];\n console.error(\"Error sending to recipient:\", recipient);\n console.error(result.reason);\n }\n }\n } else {\n // Mask the object to not include any channels\n // and only include the recipient actor on the allowed list\n const copy = JSON.parse(JSON.stringify(object)) as GraffitiObjectBase;\n const masked = maskGraffitiObject(copy, []);\n\n // Send the object to each shared inbox\n const sharedInboxes = resolvedSession.sharedInboxes;\n const results = await Promise.allSettled(\n sharedInboxes.map(async (inbox) => {\n const tombstonedMessageId = priorAnnouncements\n ? priorAnnouncements.find(\n (a) =>\n a[MESSAGE_DATA_ANNOUNCEMENT_ENDPOINT_KEY] ===\n inbox.serviceEndpoint,\n )?.[MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]\n : undefined;\n const metadata: MessageMetadata = {\n ...metadataBase,\n ...(tombstonedMessageId\n ? {\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n }\n : {}),\n };\n\n const messageId = await this.inboxes.send(inbox.serviceEndpoint, {\n ...(tombstonedMessageId\n ? {\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n }\n : {}),\n [MESSAGE_TAGS_KEY]: tags,\n [MESSAGE_OBJECT_KEY]: masked,\n [MESSAGE_METADATA_KEY]: dagCborEncode(metadata),\n });\n announcements.push({\n [MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]: messageId,\n [MESSAGE_DATA_ANNOUNCEMENT_ENDPOINT_KEY]: inbox.serviceEndpoint,\n });\n }),\n );\n\n for (const [index, result] of results.entries()) {\n if (result.status === \"rejected\") {\n const inbox = sharedInboxes[index];\n console.error(\"Error sending to inbox:\", inbox);\n console.error(result.reason);\n }\n }\n }\n\n // Send the complete object to my own personal inbox\n // along with its key and allowed tickets\n const tombstonedMessageId = priorAnnouncements\n ? priorAnnouncements.find(\n (a) => a[MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY] === session.actor,\n )?.[MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]\n : undefined;\n const selfMetadata: MessageMetadata = {\n ...metadataBase,\n ...(allowedTickets\n ? {\n [MESSAGE_DATA_ALLOWED_TICKETS_KEY]: allowedTickets,\n }\n : {}),\n ...(tombstonedMessageId\n ? {\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n }\n : {}),\n [MESSAGE_DATA_ANNOUNCEMENTS_KEY]: announcements,\n };\n await this.inboxes.send(resolvedSession.personalInbox.serviceEndpoint, {\n [MESSAGE_TAGS_KEY]: tags,\n [MESSAGE_OBJECT_KEY]: object,\n [MESSAGE_METADATA_KEY]: dagCborEncode(selfMetadata),\n });\n }\n\n protected async *querySingleEndpoint<Schema extends JSONSchema>(\n inboxEndpoint: string,\n queryArguments:\n | {\n tags: Uint8Array[];\n objectSchema: Schema;\n }\n | {\n cursor: string;\n },\n inboxToken?: string | null,\n recipient?: string | null,\n ): SingleEndpointQueryIterator<Schema> {\n const iterator: MessageStream<Schema> =\n \"tags\" in queryArguments\n ? this.inboxes.query<Schema>(\n inboxEndpoint,\n queryArguments.tags,\n queryArguments.objectSchema,\n inboxToken,\n )\n : (this.inboxes.continueQuery(\n inboxEndpoint,\n queryArguments.cursor,\n inboxToken,\n ) as unknown as MessageStream<Schema>);\n\n const inFlight: Promise<SingleEndpointQueryResult<Schema> | void>[] = [];\n let doneValue: string | null = null;\n\n try {\n while (true) {\n while (doneValue === null && inFlight.length < CONCURRENCY) {\n const itResult = await iterator.next();\n if (itResult.done) {\n doneValue = itResult.value;\n break;\n }\n\n const processPromise = this.processOneLabeledMessage<Schema>(\n inboxEndpoint,\n itResult.value,\n inboxToken,\n recipient,\n ).catch((e) => {\n throw e;\n });\n\n inFlight.push(processPromise);\n }\n\n const nextProcessedPromise = inFlight.shift();\n\n if (!nextProcessedPromise) {\n if (doneValue !== null) return doneValue;\n\n throw new Error(\"Process queue empty but no return value\");\n }\n\n const processed = await nextProcessedPromise;\n if (processed) yield processed;\n }\n } finally {\n await iterator.return(\"\");\n }\n }\n\n // Labeling is advisory and should not hold up discovery, but its failure\n // must be handled even if the caller has already stopped reading the stream.\n protected labelInboxMessage(\n inboxEndpoint: string,\n messageId: string,\n label: number,\n inboxToken?: string | null,\n ): void {\n void this.inboxes.label(inboxEndpoint, messageId, label, inboxToken).catch(\n (error) => console.error(\"Could not label inbox message:\", error),\n );\n }\n\n protected async processOneLabeledMessage<Schema extends JSONSchema>(\n inboxEndpoint: string,\n result: LabeledMessage<Schema>,\n inboxToken?: string | null,\n recipient?: string | null,\n ): Promise<SingleEndpointQueryResult<Schema> | void> {\n const label = result.l;\n // Anything invalid or unexpected, we can skip\n if (\n label !== MESSAGE_LABEL_VALID &&\n label !== MESSAGE_LABEL_UNLABELED &&\n label !== MESSAGE_LABEL_TRASH\n )\n return;\n\n const messageId = result.id;\n const { o: object, m: metadataBytes, t: receivedTags } = result.m;\n\n let metadata: MessageMetadata;\n try {\n const metadataRaw = dagCborDecode(metadataBytes);\n metadata = MessageMetadataSchema.parse(metadataRaw);\n } catch (e) {\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_INVALID,\n inboxToken,\n );\n return;\n }\n\n const {\n [MESSAGE_DATA_STORAGE_BUCKET_KEY]: storageBucketKey,\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n } = metadata;\n\n const allowedTickets =\n MESSAGE_DATA_ALLOWED_TICKETS_KEY in metadata\n ? metadata[MESSAGE_DATA_ALLOWED_TICKETS_KEY]\n : undefined;\n const announcements =\n MESSAGE_DATA_ANNOUNCEMENTS_KEY in metadata\n ? metadata[MESSAGE_DATA_ANNOUNCEMENTS_KEY]\n : undefined;\n\n if (label === MESSAGE_LABEL_VALID) {\n return {\n messageId,\n object,\n storageBucketKey,\n allowedTickets,\n tags: receivedTags,\n announcements,\n };\n } else if (label === MESSAGE_LABEL_TRASH) {\n // If it is simply trash, just continue.\n if (!tombstonedMessageId) return;\n\n // Make sure the tombstone points to a real message\n const past = await this.inboxes.get(\n inboxEndpoint,\n tombstonedMessageId,\n inboxToken,\n );\n if (\n !past ||\n past[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url !== object.url\n )\n return;\n\n // If the referred to message isn't labeled as trash, trash it\n // This may happen if a trash message is processed on another\n // device and the device cache is out of date.\n if (past[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH) {\n // Label the message as trash\n this.labelInboxMessage(\n inboxEndpoint,\n tombstonedMessageId,\n MESSAGE_LABEL_TRASH,\n inboxToken,\n );\n }\n\n // Return the tombstone\n return {\n messageId,\n tombstone: true,\n object,\n storageBucketKey,\n allowedTickets,\n tags: receivedTags,\n announcements,\n };\n }\n\n // Otherwise, unlabeled: try to validate the object\n let validationError: unknown | undefined = undefined;\n try {\n const actor = object.actor;\n const actorDocument = await this.dids.resolve(actor);\n const storageBucketService = actorDocument?.service?.find(\n (service) =>\n service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET &&\n service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,\n );\n if (!storageBucketService) {\n throw new GraffitiErrorNotFound(\n `Actor ${actor} has no storage bucket service`,\n );\n }\n if (typeof storageBucketService.serviceEndpoint !== \"string\") {\n throw new GraffitiErrorNotFound(\n `Actor ${actor} does not have a valid storage bucket endpoint`,\n );\n }\n const storageBucketEndpoint = storageBucketService.serviceEndpoint;\n\n const objectBytes = await this.storageBuckets.get(\n storageBucketEndpoint,\n storageBucketKey,\n MAX_OBJECT_SIZE_BYTES,\n );\n\n if (MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata && !recipient) {\n throw new GraffitiErrorForbidden(\n `Recipient is required when allowed ticket is present`,\n );\n }\n const privateObjectInfo = allowedTickets\n ? { allowedTickets }\n : MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata\n ? {\n recipient: recipient ?? \"null\",\n allowedTicket: metadata[MESSAGE_DATA_ALLOWED_TICKET_KEY],\n allowedIndex: metadata[MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY],\n }\n : undefined;\n\n await this.objectEncoding.validate(\n object,\n receivedTags,\n objectBytes,\n privateObjectInfo,\n );\n } catch (e) {\n validationError = e;\n }\n\n if (tombstonedMessageId) {\n if (validationError instanceof GraffitiErrorNotFound) {\n // Not found == The tombstone is correct\n void this.inboxes\n // Get the referenced message\n .get(inboxEndpoint, tombstonedMessageId, inboxToken)\n .then((result) => {\n if (\n // Make sure that it actually references the object being deleted\n result &&\n result[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url ===\n object.url &&\n // And that the object is not already marked as trash\n result[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH\n ) {\n // If valid but not yet trash, label the message as trash\n this.labelInboxMessage(\n inboxEndpoint,\n tombstonedMessageId,\n MESSAGE_LABEL_TRASH,\n inboxToken,\n );\n }\n\n // Then, label the tombstone message as trash\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_TRASH,\n inboxToken,\n );\n })\n .catch((error) =>\n console.error(\"Could not inspect tombstone message:\", error),\n );\n\n return {\n messageId,\n tombstone: true,\n object,\n storageBucketKey,\n allowedTickets,\n tags: receivedTags,\n announcements,\n };\n } else {\n console.error(\"Recieved an incorrect tombstone object\");\n console.error(validationError);\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_INVALID,\n inboxToken,\n );\n }\n } else {\n if (validationError === undefined) {\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_VALID,\n inboxToken,\n );\n return {\n messageId,\n object,\n storageBucketKey,\n tags: receivedTags,\n allowedTickets,\n announcements,\n };\n } else if (validationError instanceof GraffitiErrorNotFound) {\n // Item was deleted before we got a chance to\n // validate it. Just label the message as trash.\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_TRASH,\n inboxToken,\n );\n } else {\n console.error(\"Recieved an incorrect object\");\n console.error(validationError);\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_INVALID,\n inboxToken,\n );\n }\n }\n }\n}\n\nconst MEDIA_OBJECT_SCHEMA = {\n properties: {\n value: {\n properties: {\n type: { type: \"string\" },\n size: { type: \"number\" },\n key: { type: \"string\" },\n },\n required: [\"type\", \"size\", \"key\"],\n },\n },\n} as const satisfies JSONSchema;\n\nconst CursorSchema = strictObject({\n cursors: record(url(), string()),\n channels: array(string()),\n});\n\ninterface SingleEndpointQueryResult<Schema extends JSONSchema> {\n messageId: string;\n object: GraffitiObject<Schema>;\n storageBucketKey: string;\n tags: Uint8Array[];\n allowedTickets: Uint8Array[] | undefined;\n tombstone?: boolean;\n announcements?: MessageMetadataAnnouncements | undefined;\n}\ninterface SingleEndpointQueryIterator<\n Schema extends JSONSchema,\n> extends AsyncGenerator<SingleEndpointQueryResult<Schema>, string> {}\ntype IndexedSingleEndpointQueryResult<Schema extends JSONSchema> =\n | {\n index: number;\n error?: undefined;\n result: IteratorResult<SingleEndpointQueryResult<Schema>, string>;\n }\n | {\n index: number;\n error: Error;\n result?: undefined;\n };\n\nasync function indexedSingleEndpointQueryNext<Schema extends JSONSchema>(\n it: SingleEndpointQueryIterator<Schema>,\n index: number,\n): Promise<IndexedSingleEndpointQueryResult<Schema>> {\n try {\n return {\n index: index,\n result: await it.next(),\n };\n } catch (e) {\n if (\n e instanceof GraffitiErrorCursorExpired ||\n e instanceof GraffitiErrorInvalidSchema\n ) {\n // Propogate these errors to the root\n throw e;\n }\n // Otherwise, silently pass them in the stream\n return {\n index,\n error: e instanceof Error ? e : new Error(String(e)),\n };\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { JSONSchema } from \"json-schema-to-ts\";\nimport {\n GraffitiErrorNotFound,\n maskGraffitiObject,\n type Graffiti,\n type GraffitiLoginEvent,\n type GraffitiObjectBase,\n type GraffitiSession,\n type GraffitiObject,\n unpackObjectUrl,\n compileGraffitiObjectSchema,\n GraffitiErrorSchemaMismatch,\n GraffitiErrorForbidden,\n GraffitiErrorTooLarge,\n isMediaAcceptable,\n GraffitiErrorNotAcceptable,\n GraffitiErrorCursorExpired,\n GraffitiErrorInvalidSchema,\n type GraffitiObjectStream,\n} from \"@graffiti-garden/api\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\nimport {\n encode as dagCborEncode,\n decode as dagCborDecode,\n} from \"@ipld/dag-cbor\";\n\nimport { DecentralizedIdentifiers } from \"../1-services/2-dids\";\nimport { Authorization } from \"../1-services/1-authorization\";\nimport { StorageBuckets } from \"../1-services/3-storage-buckets\";\nimport {\n Inboxes,\n LABELED_MESSAGE_LABEL_KEY,\n LABELED_MESSAGE_MESSAGE_KEY,\n MESSAGE_METADATA_KEY,\n MESSAGE_OBJECT_KEY,\n MESSAGE_TAGS_KEY,\n type LabeledMessage,\n type MessageStream,\n} from \"../1-services/4-inboxes\";\nimport { GraffitiErrorUnauthorized } from \"../1-services/utilities\";\n\nimport {\n StringEncoder,\n STRING_ENCODER_METHOD_BASE64URL,\n} from \"../2-primitives/1-string-encoding\";\nimport { ContentAddresses } from \"../2-primitives/2-content-addresses\";\nimport {\n CHANNEL_ATTESTATION_METHOD_SHA256_ED25519,\n ChannelAttestations,\n} from \"../2-primitives/3-channel-attestations\";\nimport { AllowedAttestations } from \"../2-primitives/4-allowed-attestations\";\n\nimport { Handles } from \"./2-handles\";\nimport {\n Sessions,\n DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX,\n DID_SERVICE_TYPE_GRAFFITI_INBOX,\n DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET,\n DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,\n} from \"./1-sessions\";\nimport {\n decodeObjectUrl,\n MAX_OBJECT_SIZE_BYTES,\n ObjectEncoding,\n} from \"./3-object-encoding\";\n\nimport { GraffitiModal } from \"@graffiti-garden/modal\";\nimport {\n type infer as infer_,\n custom,\n string,\n boolean,\n strictObject,\n array,\n int,\n nonnegative,\n optional,\n extend,\n union,\n record,\n url,\n} from \"zod/mini\";\n\nconst Uint8ArraySchema = custom<Uint8Array>(\n (v): v is Uint8Array => v instanceof Uint8Array,\n);\nconst MESSAGE_DATA_STORAGE_BUCKET_KEY = \"k\";\nconst MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY = \"t\";\nconst MessageMetadataBaseSchema = strictObject({\n [MESSAGE_DATA_STORAGE_BUCKET_KEY]: string(),\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: optional(string()),\n});\nconst MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY = \"id\";\nconst MESSAGE_DATA_ANNOUNCEMENT_ENDPOINT_KEY = \"e\";\nconst MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY = \"a\";\nconst MessageMetadataAnnouncementsSchema = array(\n strictObject({\n [MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]: string(),\n [MESSAGE_DATA_ANNOUNCEMENT_ENDPOINT_KEY]: optional(url()),\n [MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY]: optional(url()),\n }),\n);\nconst MESSAGE_DATA_ALLOWED_TICKETS_KEY = \"s\";\nconst MESSAGE_DATA_ANNOUNCEMENTS_KEY = \"n\";\nconst MessageMetaDataSelfSchema = extend(MessageMetadataBaseSchema, {\n [MESSAGE_DATA_ALLOWED_TICKETS_KEY]: optional(array(Uint8ArraySchema)),\n [MESSAGE_DATA_ANNOUNCEMENTS_KEY]: MessageMetadataAnnouncementsSchema,\n});\nconst MESSAGE_DATA_ALLOWED_TICKET_KEY = \"a\";\nconst MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY = \"i\";\nconst MessageMetadataPrivateSchema = extend(MessageMetadataBaseSchema, {\n [MESSAGE_DATA_ALLOWED_TICKET_KEY]: Uint8ArraySchema,\n [MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY]: int().check(nonnegative()),\n});\nconst MessageMetadataSchema = union([\n MessageMetadataBaseSchema,\n MessageMetaDataSelfSchema,\n MessageMetadataPrivateSchema,\n]);\ntype MessageMetadataBase = infer_<typeof MessageMetadataBaseSchema>;\ntype MessageMetadata = infer_<typeof MessageMetadataSchema>;\ntype MessageMetadataAnnouncements = infer_<\n typeof MessageMetadataAnnouncementsSchema\n>;\n\nconst MESSAGE_LABEL_UNLABELED = 0;\nconst MESSAGE_LABEL_VALID = 1;\nconst MESSAGE_LABEL_TRASH = 2;\nconst MESSAGE_LABEL_INVALID = 3;\n\nexport interface GraffitiDecentralizedOptions {\n identityCreatorEndpoint?: string;\n defaultInboxEndpoints?: string[];\n /** For login hosts that already have the application in the preceding history entry. */\n replaceInitialLoginHistoryEntry?: boolean;\n}\n\nconst CONCURRENCY = 128;\nconst LOCAL_STORAGE_REMEMBERED_HANDLE_KEY = \"graffiti-login-remembered-handle\";\n\nexport class GraffitiDecentralized implements Graffiti {\n protected readonly dids = new DecentralizedIdentifiers();\n protected readonly authorization = new Authorization();\n protected readonly storageBuckets = new StorageBuckets();\n protected readonly inboxes = new Inboxes();\n\n protected readonly stringEncoder = new StringEncoder();\n protected readonly contentAddresses = new ContentAddresses();\n protected readonly channelAttestations = new ChannelAttestations();\n protected readonly allowedAttestations = new AllowedAttestations();\n\n protected readonly sessions = new Sessions({\n dids: this.dids,\n authorization: this.authorization,\n storageBuckets: this.storageBuckets,\n inboxes: this.inboxes,\n });\n protected readonly handles = new Handles({ dids: this.dids });\n protected readonly objectEncoding = new ObjectEncoding({\n stringEncoder: this.stringEncoder,\n contentAddresses: this.contentAddresses,\n channelAttestations: this.channelAttestations,\n allowedAttestations: this.allowedAttestations,\n });\n\n protected readonly modal: GraffitiModal | undefined =\n typeof window === \"undefined\"\n ? undefined\n : new GraffitiModal({\n ariaLabel: \"Graffiti Log In\",\n useTemplateHTML: () =>\n import(\"./login-dialog.html\").then(({ template }) => template),\n onManualClose: () => {\n const event = new CustomEvent(\"login\", {\n detail: {\n error: new Error(\"User cancelled login\"),\n manual: true,\n },\n });\n this.sessionEvents.dispatchEvent(event);\n },\n });\n\n protected readonly defaultInboxEndpoints: string[];\n protected readonly identityCreatorEndpoint: string;\n protected readonly replaceInitialLoginHistoryEntry: boolean;\n constructor(options?: GraffitiDecentralizedOptions) {\n this.replaceInitialLoginHistoryEntry =\n options?.replaceInitialLoginHistoryEntry ?? false;\n if (this.replaceInitialLoginHistoryEntry) {\n this.sessions.initialAuthorizationNavigation = \"replace\";\n }\n this.defaultInboxEndpoints = options?.defaultInboxEndpoints ?? [\n \"https://graffiti.actor/i/shared\",\n ];\n this.identityCreatorEndpoint =\n options?.identityCreatorEndpoint ?? \"https://graffiti.actor/create\";\n\n this.sessionEvents.addEventListener(\"login\", async (event) => {\n if (!(event instanceof CustomEvent)) return;\n const detail = event.detail as GraffitiLoginEvent[\"detail\"];\n\n if (detail.error !== undefined) {\n // If \"manual\", the window was closed by the user, nothing to do\n if (\"manual\" in detail && detail.manual) return;\n\n alert(\"Login failed: \" + detail.error.message);\n const actor = detail.session?.actor;\n let handle: string | undefined;\n if (actor) {\n try {\n handle = await this.actorToHandle(actor);\n } catch (error) {\n console.error(\"Failed to handle actor:\", error);\n }\n }\n // Open the login window again with the failed actor\n this.login_(handle);\n return;\n }\n\n this.modal?.close();\n const actor = detail.session.actor;\n\n let handle: string | undefined;\n try {\n handle = await this.actorToHandle(actor);\n } catch (error) {\n console.error(\"Failed to load handle from actor:\", error);\n }\n\n if (handle) {\n this.rememberHandleInBrowserStorage(handle);\n }\n });\n\n // If any methods throw an unauthorized error,\n // log out the used session\n for (const method of [\n \"post\",\n \"get\",\n \"delete\",\n \"postMedia\",\n \"getMedia\",\n \"deleteMedia\",\n ]) {\n const fn = (this as any)[method];\n (this as any)[method] = async (...args: unknown[]) => {\n try {\n return await fn(...args);\n } catch (e) {\n const session = args[args.length - 1] as any;\n await this.tryLogoutIfUnauthorized(e, session);\n throw e;\n }\n };\n }\n }\n\n readonly actorToHandle: Graffiti[\"actorToHandle\"] =\n this.handles.actorToHandle.bind(this.handles);\n readonly handleToActor: Graffiti[\"handleToActor\"] =\n this.handles.handleToActor.bind(this.handles);\n readonly sessionEvents: Graffiti[\"sessionEvents\"] =\n this.sessions.sessionEvents;\n\n login: Graffiti[\"login\"] = async (actor?: string) => {\n try {\n let proposedHandle: string | undefined;\n try {\n proposedHandle = actor ? await this.actorToHandle(actor) : undefined;\n } catch (error) {\n console.error(\"Error fetching handle for actor:\", error);\n }\n\n await this.login_(proposedHandle);\n } catch (e) {\n const loginError: GraffitiLoginEvent = new CustomEvent(\"login\", {\n detail: {\n error: e instanceof Error ? e : new Error(String(e)),\n },\n });\n this.sessionEvents.dispatchEvent(loginError);\n }\n };\n protected async login_(proposedHandle?: string) {\n if (typeof window !== \"undefined\") {\n let template: HTMLElement | undefined;\n let focusAfterOpen: HTMLElement | null = null;\n if (proposedHandle !== undefined) {\n template = await this.modal?.displayTemplate(\"graffiti-login-handle\");\n const input = template?.querySelector(\n \"#username\",\n ) as HTMLInputElement | null;\n const rememberedHandle =\n proposedHandle || this.getRememberedHandleFromBrowserStorage();\n if (input) input.value = rememberedHandle ?? \"\";\n input?.addEventListener(\"focus\", () => input?.select());\n focusAfterOpen = input;\n\n template\n ?.querySelector(\"#graffiti-login-handle-form\")\n ?.addEventListener(\"submit\", async (e) => {\n e.preventDefault();\n input?.setAttribute(\"disabled\", \"true\");\n const submitButton = template?.querySelector(\n \"#graffiti-login-handle-submit\",\n ) as HTMLButtonElement | null;\n submitButton?.setAttribute(\"disabled\", \"true\");\n submitButton && (submitButton.innerHTML = \"Logging in...\");\n\n if (!input?.value) {\n alert(\"No handle provided\");\n this.login_(\"\");\n return;\n }\n\n let handle = input.value;\n if (!handle.includes(\".\") && !handle.startsWith(\"localhost\")) {\n const defaultHost = new URL(this.identityCreatorEndpoint).host;\n handle = `${handle}.${defaultHost}`;\n }\n\n let actor: string;\n try {\n actor = await this.handleToActor(handle);\n } catch (e) {\n alert(\"Could not find an identity associated with that handle.\");\n this.login_(handle);\n return;\n }\n\n try {\n await this.sessions.login(actor);\n } catch (e) {\n alert(\"Error logging in.\");\n console.error(e);\n this.login_(handle);\n }\n });\n template\n ?.querySelector(\"#graffiti-login-forgot\")\n ?.addEventListener(\"click\", (e) => {\n e.preventDefault();\n void this.loginWithoutHandle();\n });\n } else {\n template = await this.modal?.displayTemplate(\"graffiti-login-welcome\");\n template\n ?.querySelector(\"#graffiti-login-existing\")\n ?.addEventListener(\"click\", (e) => {\n e.preventDefault();\n this.login_(\"\");\n });\n }\n\n const createUrl = new URL(this.identityCreatorEndpoint);\n createUrl.searchParams.set(\n \"redirect_uri\",\n encodeURIComponent(window.location.toString()),\n );\n const createLink = template?.querySelector<HTMLAnchorElement>(\n \"#graffiti-login-new\",\n );\n createLink?.setAttribute(\"href\", createUrl.toString());\n if (proposedHandle === undefined) focusAfterOpen = createLink ?? null;\n if (this.replaceInitialLoginHistoryEntry) {\n createLink?.addEventListener(\"click\", (event) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n ) return;\n event.preventDefault();\n window.location.replace(createUrl.toString());\n });\n }\n\n await this.modal?.open();\n focusAfterOpen?.focus();\n } else {\n // Node.js environment\n const readline = await import(\"readline\").catch((e) => {\n throw new Error(\n \"Unrecognized environment: neither window nor readline\",\n );\n });\n\n console.log(\n \"If you do not already have a Graffiti handle, you can create one here:\",\n );\n console.log(this.identityCreatorEndpoint);\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const handle: string | undefined = await new Promise((resolve) => {\n rl.question(\n `Please enter your handle${proposedHandle ? ` (default: ${proposedHandle})` : \"\"}: `,\n (input) => {\n rl.close();\n resolve(input || proposedHandle);\n },\n );\n });\n\n if (!handle) {\n throw new Error(\"No handle provided\");\n }\n\n // Convert the handle to an actor\n const actor = await this.handleToActor(handle);\n\n await this.sessions.login(actor);\n }\n }\n\n protected async loginWithoutHandle() {\n const template = await this.modal?.displayTemplate(\"graffiti-login-provider\");\n const defaultProvider = new URL(\"/\", this.identityCreatorEndpoint);\n const provider = template?.querySelector(\"#graffiti-provider\") as HTMLInputElement | null;\n if (provider) provider.value = defaultProvider.host;\n provider?.addEventListener(\"focus\", () => provider.select());\n\n template\n ?.querySelector(\"#graffiti-login-provider-form\")\n ?.addEventListener(\"submit\", (event) => {\n event.preventDefault();\n try {\n const domain = provider?.value.trim() ?? \"\";\n const origin = domain === defaultProvider.host\n ? defaultProvider\n : new URL(`https://${domain}`);\n if (\n !origin.hostname || origin.username || origin.password ||\n origin.pathname !== \"/\" || origin.search || origin.hash\n ) throw new Error(\"Invalid provider domain\");\n\n const url = new URL(\"/forgot-handle\", origin);\n url.searchParams.set(\"redirect_uri\", window.location.toString());\n if (this.replaceInitialLoginHistoryEntry) {\n window.location.replace(url.toString());\n } else {\n window.location.assign(url.toString());\n }\n } catch {\n alert(\"Enter a valid provider domain.\");\n }\n });\n\n template\n ?.querySelector(\"#graffiti-login-provider-back\")\n ?.addEventListener(\"click\", (event) => {\n event.preventDefault();\n void this.login_(\"\");\n });\n\n await this.modal?.open();\n provider?.focus();\n }\n\n protected rememberHandleInBrowserStorage(handle: string) {\n if (typeof window === \"undefined\") return;\n\n try {\n window.localStorage.setItem(LOCAL_STORAGE_REMEMBERED_HANDLE_KEY, handle);\n } catch (error) {\n console.error(\"Failed to remember handle in browser storage:\", error);\n }\n }\n\n protected getRememberedHandleFromBrowserStorage() {\n if (typeof window === \"undefined\") return undefined;\n\n try {\n return (\n window.localStorage.getItem(LOCAL_STORAGE_REMEMBERED_HANDLE_KEY) ??\n undefined\n );\n } catch (error) {\n console.error(\"Failed to load handle from browser storage:\", error);\n return undefined;\n }\n }\n\n logout: Graffiti[\"logout\"] = async (session) => {\n await this.sessions.logout(session.actor);\n };\n\n // @ts-ignore\n post: Graffiti[\"post\"] = async (...args) => {\n const [partialObject, session] = args;\n const resolvedSession = this.sessions.resolveSession(session);\n\n // Encode the object\n const { object, tags, objectBytes, allowedTickets } =\n await this.objectEncoding.encode<{}>(partialObject, session.actor);\n\n // Generate a random key under which to store the object\n // If the object is private, this means no one will be able to\n // fetch the object, even if they know its URL.\n // If the object is public but in some secret channel, the storage\n // location means the object can be moved around or \"rotated\"\n // without changing its URL.\n const storageBucketKeyBytes = randomBytes();\n const storageBucketKey = await this.stringEncoder.encode(\n STRING_ENCODER_METHOD_BASE64URL,\n storageBucketKeyBytes,\n );\n\n // Store the object at the random key\n await this.storageBuckets.put(\n resolvedSession.storageBucket.serviceEndpoint,\n storageBucketKey,\n objectBytes,\n resolvedSession.storageBucket.token,\n );\n\n // Announce the object, its key,\n // and other metadata to appropriate inboxes\n await this.announceObject(\n object,\n tags,\n allowedTickets,\n storageBucketKey,\n session,\n );\n\n return object;\n };\n\n get: Graffiti[\"get\"] = async (...args) => {\n const [url, schema, session] = args;\n let services: { token?: string; serviceEndpoint: string }[];\n const validator = await compileGraffitiObjectSchema(schema);\n\n if (session) {\n // If logged in, first search one's\n // personal inbox, then any shared inboxes\n const resolvedSession = this.sessions.resolveSession(session);\n services = [\n resolvedSession.personalInbox,\n ...resolvedSession.sharedInboxes,\n ];\n } else {\n // Otherwise, search the default inboxes\n services = this.defaultInboxEndpoints.map((s) => ({\n serviceEndpoint: s,\n }));\n }\n\n // Search the inboxes for all objects\n // matching the tag, object.url\n const objectUrl = unpackObjectUrl(url);\n const tags = [new TextEncoder().encode(objectUrl)];\n for (const service of services) {\n let object: GraffitiObjectBase | undefined = undefined;\n\n const iterator = this.querySingleEndpoint<{}>(\n service.serviceEndpoint,\n {\n tags,\n objectSchema: {},\n },\n service.token,\n session?.actor,\n );\n\n for await (const result of iterator) {\n if (result.object.url !== objectUrl) continue;\n if (result.tombstone) {\n object = undefined;\n } else {\n object = result.object;\n }\n }\n\n if (object) {\n if (!validator(object)) {\n throw new GraffitiErrorSchemaMismatch(\n \"Object exists but does not match the supplied schema\",\n );\n }\n\n return object;\n }\n }\n\n throw new GraffitiErrorNotFound(\"Object not found\");\n };\n\n delete: Graffiti[\"delete\"] = async (url, session) => {\n const resolvedSession = this.sessions.resolveSession(session);\n\n const objectUrl = unpackObjectUrl(url);\n\n const { actor } = decodeObjectUrl(objectUrl);\n if (actor !== session.actor) {\n throw new GraffitiErrorForbidden(\"Cannot delete someone else's actor\");\n }\n\n // Look in one's personal inbox for the object\n const iterator = this.querySingleEndpoint<{}>(\n resolvedSession.personalInbox.serviceEndpoint,\n {\n tags: [new TextEncoder().encode(objectUrl)],\n objectSchema: {},\n },\n resolvedSession.personalInbox.token,\n );\n let existing: SingleEndpointQueryResult<{}> | undefined;\n for await (const result of iterator) {\n if (result.object.url !== objectUrl) continue;\n if (result.tombstone) {\n existing = undefined;\n } else {\n existing = result;\n }\n }\n if (!existing) {\n throw new GraffitiErrorNotFound(`Object ${objectUrl} not found`);\n }\n const {\n object,\n storageBucketKey,\n tags,\n allowedTickets,\n announcements,\n messageId,\n } = existing;\n\n // Delete the object from the actor's own storage bucket\n await this.storageBuckets.delete(\n resolvedSession.storageBucket.serviceEndpoint,\n storageBucketKey,\n resolvedSession.storageBucket.token,\n );\n\n // Announce the deletion to all inboxes\n await this.announceObject(\n object,\n tags,\n allowedTickets,\n storageBucketKey,\n session,\n [\n ...(announcements ?? []),\n // Make sure we delete from our own inbox too\n {\n [MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY]: session.actor,\n [MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]: messageId,\n },\n ],\n );\n\n return object;\n };\n\n postMedia: Graffiti[\"postMedia\"] = async (...args) => {\n const [media, session] = args;\n\n const type = media.data.type;\n\n const resolvedSession = this.sessions.resolveSession(session);\n\n // Generate a random storage key\n const keyBytes = randomBytes();\n const key = await this.stringEncoder.encode(\n STRING_ENCODER_METHOD_BASE64URL,\n keyBytes,\n );\n\n // Store the media at that key\n await this.storageBuckets.put(\n resolvedSession.storageBucket.serviceEndpoint,\n key,\n new Uint8Array(await media.data.arrayBuffer()),\n resolvedSession.storageBucket.token,\n );\n\n // Create an object\n const { url } = await this.post<typeof MEDIA_OBJECT_SCHEMA>(\n {\n value: {\n key,\n type,\n size: media.data.size,\n },\n channels: [],\n allowed: media.allowed,\n },\n session,\n );\n\n return url;\n };\n\n getMedia: Graffiti[\"getMedia\"] = async (...args) => {\n const [mediaUrl, accept, session] = args;\n\n if (\n accept?.maxBytes !== undefined &&\n (!Number.isSafeInteger(accept.maxBytes) || accept.maxBytes < 0)\n ) {\n throw new TypeError(\"maxBytes must be a nonnegative safe integer\");\n }\n\n const object = await this.get<typeof MEDIA_OBJECT_SCHEMA>(\n mediaUrl,\n MEDIA_OBJECT_SCHEMA,\n session,\n );\n\n const { key, type, size } = object.value;\n\n if (accept?.maxBytes !== undefined && size > accept.maxBytes) {\n throw new GraffitiErrorTooLarge(\"File size exceeds limit\");\n }\n\n // Make sure it adheres to requirements.accept\n if (accept?.types) {\n if (!isMediaAcceptable(type, accept.types)) {\n throw new GraffitiErrorNotAcceptable(\n `Unacceptable media type, ${type}`,\n );\n }\n }\n\n // Get the actor's storage bucket endpoint\n const actorDocument = await this.dids.resolve(object.actor);\n const storageBucketService = actorDocument?.service?.find(\n (service) =>\n service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET &&\n service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,\n );\n if (!storageBucketService) {\n throw new GraffitiErrorNotFound(\n `Actor ${object.actor} has no storage bucket service`,\n );\n }\n if (typeof storageBucketService.serviceEndpoint !== \"string\") {\n throw new GraffitiErrorNotFound(\n `Actor ${object.actor} does not have a valid storage bucket endpoint`,\n );\n }\n const storageBucketEndpoint = storageBucketService.serviceEndpoint;\n\n const data = await this.storageBuckets.get(\n storageBucketEndpoint,\n key,\n size,\n );\n\n const blob = new Blob([data.slice()], { type });\n\n return {\n data: blob,\n actor: object.actor,\n allowed: object.allowed,\n };\n };\n\n deleteMedia: Graffiti[\"deleteMedia\"] = async (...args) => {\n const [mediaUrl, session] = args;\n\n const resolvedSession = this.sessions.resolveSession(session);\n\n const result = await this.delete(mediaUrl, session);\n\n if (!(\"key\" in result.value && typeof result.value.key === \"string\"))\n throw new Error(\n \"Deleted object was not media: \" + JSON.stringify(result, null, 2),\n );\n\n await this.storageBuckets.delete(\n resolvedSession.storageBucket.serviceEndpoint,\n result.value.key,\n resolvedSession.storageBucket.token,\n );\n };\n\n async *discoverMeta<Schema extends JSONSchema>(\n channels: string[],\n schema: Schema,\n cursors: {\n [endpoint: string]: string;\n },\n session?: GraffitiSession | null,\n ): GraffitiObjectStream<Schema> {\n const tombstones = new Map<string, boolean>();\n\n let allInboxes: { serviceEndpoint: string; token?: string }[];\n if (session) {\n const resolvedSession = this.sessions.resolveSession(session);\n allInboxes = [\n resolvedSession.personalInbox,\n ...resolvedSession.sharedInboxes,\n ];\n } else {\n allInboxes = this.defaultInboxEndpoints.map((e) => ({\n serviceEndpoint: e,\n }));\n }\n\n // Make sure all cursors are represented by an inbox\n for (const endpoint in cursors) {\n if (!allInboxes.some((i) => i.serviceEndpoint === endpoint)) {\n throw new GraffitiErrorForbidden(\n \"Cursor does not match actor's inboxes\",\n );\n }\n }\n\n // Turn the channels into tags\n const tags = await Promise.all(\n channels.map((c) =>\n this.channelAttestations.register(\n CHANNEL_ATTESTATION_METHOD_SHA256_ED25519,\n c,\n ),\n ),\n );\n\n const iterators: SingleEndpointQueryIterator<Schema>[] = allInboxes.map(\n (i) => {\n const cursor = cursors[i.serviceEndpoint];\n return this.querySingleEndpoint<Schema>(\n i.serviceEndpoint,\n cursor\n ? {\n cursor,\n }\n : {\n tags,\n objectSchema: schema,\n },\n i.token,\n session?.actor,\n );\n },\n );\n\n let indexedIteratorNexts = iterators.map<\n Promise<IndexedSingleEndpointQueryResult<Schema>>\n >(async (it, index) => indexedSingleEndpointQueryNext<Schema>(it, index));\n let active = indexedIteratorNexts.length;\n\n try {\n while (active > 0) {\n const next: IndexedSingleEndpointQueryResult<Schema> =\n await Promise.race<any>(indexedIteratorNexts);\n if (next.error !== undefined) {\n // Remove it from the race\n indexedIteratorNexts[next.index] = new Promise(() => {});\n active--;\n yield {\n error: next.error,\n origin: allInboxes[next.index].serviceEndpoint,\n };\n this.tryLogoutIfUnauthorized(next.error, session);\n } else if (next.result.done) {\n // Store the cursor for future use\n const inbox = allInboxes[next.index];\n cursors[inbox.serviceEndpoint] = next.result.value;\n // Remove it from the race\n indexedIteratorNexts[next.index] = new Promise(() => {});\n active--;\n } else {\n // Re-arm the iterator\n indexedIteratorNexts[next.index] =\n indexedSingleEndpointQueryNext<Schema>(\n iterators[next.index],\n next.index,\n );\n const { object, tombstone, tags: receivedTags } = next.result.value;\n if (tombstone) {\n if (tombstones.get(object.url) === true) continue;\n tombstones.set(object.url, true);\n yield {\n tombstone,\n object: { url: object.url },\n };\n } else {\n // Filter already seen\n if (tombstones.get(object.url) === false) continue;\n\n // Fill in the matched channels\n const matchedTagIndices = tags.reduce<number[]>(\n (acc, tag, tagIndex) => {\n for (const receivedTag of receivedTags) {\n if (\n tag.length === receivedTag.length &&\n tag.every((b, i) => receivedTag[i] === b)\n ) {\n acc.push(tagIndex);\n break;\n }\n }\n return acc;\n },\n [],\n );\n const matchedChannels = matchedTagIndices.map(\n (index) => channels[index],\n );\n if (matchedChannels.length === 0) {\n yield {\n error: new Error(\n \"Inbox returned object without matching channels\",\n ),\n origin: allInboxes[next.index].serviceEndpoint,\n };\n }\n tombstones.set(object.url, false);\n yield {\n object: {\n ...object,\n channels: matchedChannels,\n },\n };\n }\n }\n }\n } catch (e) {\n this.tryLogoutIfUnauthorized(e, session);\n throw e;\n } finally {\n await Promise.all(\n iterators.map<Promise<void>>(async (it) => {\n await it.return(\"\");\n }),\n );\n }\n\n return {\n cursor: JSON.stringify({\n channels,\n cursors,\n } satisfies infer_<typeof CursorSchema>),\n };\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const [channels, schema, session] = args;\n return this.discoverMeta<(typeof args)[1]>(channels, schema, {}, session);\n };\n\n // @ts-ignore\n continueDiscover: Graffiti[\"continueDiscover\"] = (...args) => {\n const [cursor, session] = args;\n // Extract the channels from the cursor\n let channels: string[];\n let cursors: { [endpoint: string]: string };\n try {\n const json = JSON.parse(cursor);\n const parsed = CursorSchema.parse(json);\n channels = parsed.channels;\n cursors = parsed.cursors;\n } catch (error) {\n return (async function* () {\n throw new GraffitiErrorCursorExpired(\"Invalid cursor\");\n })();\n }\n return this.discoverMeta<{}>(channels, {}, cursors, session);\n };\n\n protected async tryLogoutIfUnauthorized(\n e: unknown,\n session?: GraffitiSession | null,\n ) {\n if (e instanceof GraffitiErrorUnauthorized && session) {\n await this.sessions.logout(session.actor);\n }\n }\n\n async announceObject(\n object: GraffitiObjectBase,\n tags: Uint8Array[],\n allowedTickets: Uint8Array[] | undefined,\n storageBucketKey: string,\n session: GraffitiSession,\n priorAnnouncements?: MessageMetadataAnnouncements,\n ): Promise<void> {\n const resolvedSession = this.sessions.resolveSession(session);\n\n const metadataBase: MessageMetadataBase = {\n [MESSAGE_DATA_STORAGE_BUCKET_KEY]: storageBucketKey,\n };\n\n const announcements: MessageMetadataAnnouncements = [];\n const allowed = object.allowed;\n if (Array.isArray(allowed)) {\n if (!allowedTickets || allowedTickets.length !== allowed.length) {\n throw new Error(\n \"If allowed actors are specified, there must be a corresponding ticket for each allowed actor\",\n );\n }\n\n // Send the object to each allowed recipient's personal inbox\n const results = await Promise.allSettled(\n allowed.map(async (recipient, recipientIndex) => {\n // Mask the object to not include any channels\n // and only include the recipient actor on the allowed list\n const copy = JSON.parse(JSON.stringify(object)) as GraffitiObjectBase;\n const masked = maskGraffitiObject(copy, [], recipient);\n\n // Get the recipient's inbox\n const actorDocument = await this.dids.resolve(recipient);\n const personalInbox = actorDocument.service?.find(\n (service) =>\n service.type === DID_SERVICE_TYPE_GRAFFITI_INBOX &&\n service.id === DID_SERVICE_ID_GRAFFITI_PERSONAL_INBOX,\n );\n if (!personalInbox) {\n throw new Error(\n `Recipient ${recipient} does not have a personal inbox`,\n );\n }\n if (typeof personalInbox.serviceEndpoint !== \"string\") {\n throw new Error(\n `Recipient ${recipient} does not have a valid personal inbox endpoint`,\n );\n }\n\n const tombstonedMessageId = priorAnnouncements\n ? priorAnnouncements.find(\n (a) => a[MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY] === recipient,\n )?.[MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]\n : undefined;\n\n // Announce to the inbox\n const privateMetadata: MessageMetadata = {\n ...metadataBase,\n ...(tombstonedMessageId\n ? {\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n }\n : {}),\n [MESSAGE_DATA_ALLOWED_TICKET_KEY]: allowedTickets[recipientIndex],\n [MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY]: recipientIndex,\n };\n const messageId = await this.inboxes.send(\n personalInbox.serviceEndpoint,\n {\n [MESSAGE_TAGS_KEY]: tags,\n [MESSAGE_OBJECT_KEY]: masked,\n [MESSAGE_METADATA_KEY]: dagCborEncode(privateMetadata),\n },\n );\n\n announcements.push({\n [MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]: messageId,\n [MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY]: recipient,\n });\n }),\n );\n\n for (const [index, result] of results.entries()) {\n if (result.status === \"rejected\") {\n const recipient = allowed[index];\n console.error(\"Error sending to recipient:\", recipient);\n console.error(result.reason);\n }\n }\n } else {\n // Mask the object to not include any channels\n // and only include the recipient actor on the allowed list\n const copy = JSON.parse(JSON.stringify(object)) as GraffitiObjectBase;\n const masked = maskGraffitiObject(copy, []);\n\n // Send the object to each shared inbox\n const sharedInboxes = resolvedSession.sharedInboxes;\n const results = await Promise.allSettled(\n sharedInboxes.map(async (inbox) => {\n const tombstonedMessageId = priorAnnouncements\n ? priorAnnouncements.find(\n (a) =>\n a[MESSAGE_DATA_ANNOUNCEMENT_ENDPOINT_KEY] ===\n inbox.serviceEndpoint,\n )?.[MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]\n : undefined;\n const metadata: MessageMetadata = {\n ...metadataBase,\n ...(tombstonedMessageId\n ? {\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n }\n : {}),\n };\n\n const messageId = await this.inboxes.send(inbox.serviceEndpoint, {\n ...(tombstonedMessageId\n ? {\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n }\n : {}),\n [MESSAGE_TAGS_KEY]: tags,\n [MESSAGE_OBJECT_KEY]: masked,\n [MESSAGE_METADATA_KEY]: dagCborEncode(metadata),\n });\n announcements.push({\n [MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]: messageId,\n [MESSAGE_DATA_ANNOUNCEMENT_ENDPOINT_KEY]: inbox.serviceEndpoint,\n });\n }),\n );\n\n for (const [index, result] of results.entries()) {\n if (result.status === \"rejected\") {\n const inbox = sharedInboxes[index];\n console.error(\"Error sending to inbox:\", inbox);\n console.error(result.reason);\n }\n }\n }\n\n // Send the complete object to my own personal inbox\n // along with its key and allowed tickets\n const tombstonedMessageId = priorAnnouncements\n ? priorAnnouncements.find(\n (a) => a[MESSAGE_DATA_ANNOUNCEMENT_ACTOR_KEY] === session.actor,\n )?.[MESSAGE_DATA_ANNOUNCEMENT_MESSAGE_ID_KEY]\n : undefined;\n const selfMetadata: MessageMetadata = {\n ...metadataBase,\n ...(allowedTickets\n ? {\n [MESSAGE_DATA_ALLOWED_TICKETS_KEY]: allowedTickets,\n }\n : {}),\n ...(tombstonedMessageId\n ? {\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n }\n : {}),\n [MESSAGE_DATA_ANNOUNCEMENTS_KEY]: announcements,\n };\n await this.inboxes.send(resolvedSession.personalInbox.serviceEndpoint, {\n [MESSAGE_TAGS_KEY]: tags,\n [MESSAGE_OBJECT_KEY]: object,\n [MESSAGE_METADATA_KEY]: dagCborEncode(selfMetadata),\n });\n }\n\n protected async *querySingleEndpoint<Schema extends JSONSchema>(\n inboxEndpoint: string,\n queryArguments:\n | {\n tags: Uint8Array[];\n objectSchema: Schema;\n }\n | {\n cursor: string;\n },\n inboxToken?: string | null,\n recipient?: string | null,\n ): SingleEndpointQueryIterator<Schema> {\n const iterator: MessageStream<Schema> =\n \"tags\" in queryArguments\n ? this.inboxes.query<Schema>(\n inboxEndpoint,\n queryArguments.tags,\n queryArguments.objectSchema,\n inboxToken,\n )\n : (this.inboxes.continueQuery(\n inboxEndpoint,\n queryArguments.cursor,\n inboxToken,\n ) as unknown as MessageStream<Schema>);\n\n const inFlight: Promise<SingleEndpointQueryResult<Schema> | void>[] = [];\n let doneValue: string | null = null;\n\n try {\n while (true) {\n while (doneValue === null && inFlight.length < CONCURRENCY) {\n const itResult = await iterator.next();\n if (itResult.done) {\n doneValue = itResult.value;\n break;\n }\n\n const processPromise = this.processOneLabeledMessage<Schema>(\n inboxEndpoint,\n itResult.value,\n inboxToken,\n recipient,\n ).catch((e) => {\n throw e;\n });\n\n inFlight.push(processPromise);\n }\n\n const nextProcessedPromise = inFlight.shift();\n\n if (!nextProcessedPromise) {\n if (doneValue !== null) return doneValue;\n\n throw new Error(\"Process queue empty but no return value\");\n }\n\n const processed = await nextProcessedPromise;\n if (processed) yield processed;\n }\n } finally {\n await iterator.return(\"\");\n }\n }\n\n // Labeling is advisory and should not hold up discovery, but its failure\n // must be handled even if the caller has already stopped reading the stream.\n protected labelInboxMessage(\n inboxEndpoint: string,\n messageId: string,\n label: number,\n inboxToken?: string | null,\n ): void {\n void this.inboxes.label(inboxEndpoint, messageId, label, inboxToken).catch(\n (error) => console.error(\"Could not label inbox message:\", error),\n );\n }\n\n protected async processOneLabeledMessage<Schema extends JSONSchema>(\n inboxEndpoint: string,\n result: LabeledMessage<Schema>,\n inboxToken?: string | null,\n recipient?: string | null,\n ): Promise<SingleEndpointQueryResult<Schema> | void> {\n const label = result.l;\n // Anything invalid or unexpected, we can skip\n if (\n label !== MESSAGE_LABEL_VALID &&\n label !== MESSAGE_LABEL_UNLABELED &&\n label !== MESSAGE_LABEL_TRASH\n )\n return;\n\n const messageId = result.id;\n const { o: object, m: metadataBytes, t: receivedTags } = result.m;\n\n let metadata: MessageMetadata;\n try {\n const metadataRaw = dagCborDecode(metadataBytes);\n metadata = MessageMetadataSchema.parse(metadataRaw);\n } catch (e) {\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_INVALID,\n inboxToken,\n );\n return;\n }\n\n const {\n [MESSAGE_DATA_STORAGE_BUCKET_KEY]: storageBucketKey,\n [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId,\n } = metadata;\n\n const allowedTickets =\n MESSAGE_DATA_ALLOWED_TICKETS_KEY in metadata\n ? metadata[MESSAGE_DATA_ALLOWED_TICKETS_KEY]\n : undefined;\n const announcements =\n MESSAGE_DATA_ANNOUNCEMENTS_KEY in metadata\n ? metadata[MESSAGE_DATA_ANNOUNCEMENTS_KEY]\n : undefined;\n\n if (label === MESSAGE_LABEL_VALID) {\n return {\n messageId,\n object,\n storageBucketKey,\n allowedTickets,\n tags: receivedTags,\n announcements,\n };\n } else if (label === MESSAGE_LABEL_TRASH) {\n // If it is simply trash, just continue.\n if (!tombstonedMessageId) return;\n\n // Make sure the tombstone points to a real message\n const past = await this.inboxes.get(\n inboxEndpoint,\n tombstonedMessageId,\n inboxToken,\n );\n if (\n !past ||\n past[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url !== object.url\n )\n return;\n\n // If the referred to message isn't labeled as trash, trash it\n // This may happen if a trash message is processed on another\n // device and the device cache is out of date.\n if (past[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH) {\n // Label the message as trash\n this.labelInboxMessage(\n inboxEndpoint,\n tombstonedMessageId,\n MESSAGE_LABEL_TRASH,\n inboxToken,\n );\n }\n\n // Return the tombstone\n return {\n messageId,\n tombstone: true,\n object,\n storageBucketKey,\n allowedTickets,\n tags: receivedTags,\n announcements,\n };\n }\n\n // Otherwise, unlabeled: try to validate the object\n let validationError: unknown | undefined = undefined;\n try {\n const actor = object.actor;\n const actorDocument = await this.dids.resolve(actor);\n const storageBucketService = actorDocument?.service?.find(\n (service) =>\n service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET &&\n service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET,\n );\n if (!storageBucketService) {\n throw new GraffitiErrorNotFound(\n `Actor ${actor} has no storage bucket service`,\n );\n }\n if (typeof storageBucketService.serviceEndpoint !== \"string\") {\n throw new GraffitiErrorNotFound(\n `Actor ${actor} does not have a valid storage bucket endpoint`,\n );\n }\n const storageBucketEndpoint = storageBucketService.serviceEndpoint;\n\n const objectBytes = await this.storageBuckets.get(\n storageBucketEndpoint,\n storageBucketKey,\n MAX_OBJECT_SIZE_BYTES,\n );\n\n if (MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata && !recipient) {\n throw new GraffitiErrorForbidden(\n `Recipient is required when allowed ticket is present`,\n );\n }\n const privateObjectInfo = allowedTickets\n ? { allowedTickets }\n : MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata\n ? {\n recipient: recipient ?? \"null\",\n allowedTicket: metadata[MESSAGE_DATA_ALLOWED_TICKET_KEY],\n allowedIndex: metadata[MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY],\n }\n : undefined;\n\n await this.objectEncoding.validate(\n object,\n receivedTags,\n objectBytes,\n privateObjectInfo,\n );\n } catch (e) {\n validationError = e;\n }\n\n if (tombstonedMessageId) {\n if (validationError instanceof GraffitiErrorNotFound) {\n // Not found == The tombstone is correct\n void this.inboxes\n // Get the referenced message\n .get(inboxEndpoint, tombstonedMessageId, inboxToken)\n .then((result) => {\n if (\n // Make sure that it actually references the object being deleted\n result &&\n result[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url ===\n object.url &&\n // And that the object is not already marked as trash\n result[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH\n ) {\n // If valid but not yet trash, label the message as trash\n this.labelInboxMessage(\n inboxEndpoint,\n tombstonedMessageId,\n MESSAGE_LABEL_TRASH,\n inboxToken,\n );\n }\n\n // Then, label the tombstone message as trash\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_TRASH,\n inboxToken,\n );\n })\n .catch((error) =>\n console.error(\"Could not inspect tombstone message:\", error),\n );\n\n return {\n messageId,\n tombstone: true,\n object,\n storageBucketKey,\n allowedTickets,\n tags: receivedTags,\n announcements,\n };\n } else {\n console.error(\"Recieved an incorrect tombstone object\");\n console.error(validationError);\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_INVALID,\n inboxToken,\n );\n }\n } else {\n if (validationError === undefined) {\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_VALID,\n inboxToken,\n );\n return {\n messageId,\n object,\n storageBucketKey,\n tags: receivedTags,\n allowedTickets,\n announcements,\n };\n } else if (validationError instanceof GraffitiErrorNotFound) {\n // Item was deleted before we got a chance to\n // validate it. Just label the message as trash.\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_TRASH,\n inboxToken,\n );\n } else {\n console.error(\"Recieved an incorrect object\");\n console.error(validationError);\n this.labelInboxMessage(\n inboxEndpoint,\n messageId,\n MESSAGE_LABEL_INVALID,\n inboxToken,\n );\n }\n }\n }\n}\n\nconst MEDIA_OBJECT_SCHEMA = {\n properties: {\n value: {\n properties: {\n type: { type: \"string\" },\n size: { type: \"number\" },\n key: { type: \"string\" },\n },\n required: [\"type\", \"size\", \"key\"],\n },\n },\n} as const satisfies JSONSchema;\n\nconst CursorSchema = strictObject({\n cursors: record(url(), string()),\n channels: array(string()),\n});\n\ninterface SingleEndpointQueryResult<Schema extends JSONSchema> {\n messageId: string;\n object: GraffitiObject<Schema>;\n storageBucketKey: string;\n tags: Uint8Array[];\n allowedTickets: Uint8Array[] | undefined;\n tombstone?: boolean;\n announcements?: MessageMetadataAnnouncements | undefined;\n}\ninterface SingleEndpointQueryIterator<\n Schema extends JSONSchema,\n> extends AsyncGenerator<SingleEndpointQueryResult<Schema>, string> {}\ntype IndexedSingleEndpointQueryResult<Schema extends JSONSchema> =\n | {\n index: number;\n error?: undefined;\n result: IteratorResult<SingleEndpointQueryResult<Schema>, string>;\n }\n | {\n index: number;\n error: Error;\n result?: undefined;\n };\n\nasync function indexedSingleEndpointQueryNext<Schema extends JSONSchema>(\n it: SingleEndpointQueryIterator<Schema>,\n index: number,\n): Promise<IndexedSingleEndpointQueryResult<Schema>> {\n try {\n return {\n index: index,\n result: await it.next(),\n };\n } catch (e) {\n if (\n e instanceof GraffitiErrorCursorExpired ||\n e instanceof GraffitiErrorInvalidSchema\n ) {\n // Propogate these errors to the root\n throw e;\n }\n // Otherwise, silently pass them in the stream\n return {\n index,\n error: e instanceof Error ? e : new Error(String(e)),\n };\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["actor", "handle", "e", "url", "tombstonedMessageId", "dagCborEncode", "dagCborDecode", "result"]
7
7
  }
@@ -131,6 +131,7 @@ class GraffitiDecentralized {
131
131
  allowedAttestations: this.allowedAttestations
132
132
  });
133
133
  modal = typeof window === "undefined" ? void 0 : new GraffitiModal({
134
+ ariaLabel: "Graffiti Log In",
134
135
  useTemplateHTML: () => import("./login-dialog.html").then(({ template }) => template),
135
136
  onManualClose: () => {
136
137
  const event = new CustomEvent("login", {
@@ -172,6 +173,7 @@ class GraffitiDecentralized {
172
173
  this.login_(handle2);
173
174
  return;
174
175
  }
176
+ this.modal?.close();
175
177
  const actor = detail.session.actor;
176
178
  let handle;
177
179
  try {
@@ -227,6 +229,7 @@ class GraffitiDecentralized {
227
229
  async login_(proposedHandle) {
228
230
  if (typeof window !== "undefined") {
229
231
  let template;
232
+ let focusAfterOpen = null;
230
233
  if (proposedHandle !== void 0) {
231
234
  template = await this.modal?.displayTemplate("graffiti-login-handle");
232
235
  const input = template?.querySelector(
@@ -235,7 +238,7 @@ class GraffitiDecentralized {
235
238
  const rememberedHandle = proposedHandle || this.getRememberedHandleFromBrowserStorage();
236
239
  if (input) input.value = rememberedHandle ?? "";
237
240
  input?.addEventListener("focus", () => input?.select());
238
- setTimeout(() => input?.focus(), 0);
241
+ focusAfterOpen = input;
239
242
  template?.querySelector("#graffiti-login-handle-form")?.addEventListener("submit", async (e) => {
240
243
  e.preventDefault();
241
244
  input?.setAttribute("disabled", "true");
@@ -280,12 +283,6 @@ class GraffitiDecentralized {
280
283
  e.preventDefault();
281
284
  this.login_("");
282
285
  });
283
- setTimeout(
284
- () => template?.querySelector(
285
- "#graffiti-login-new"
286
- )?.focus(),
287
- 0
288
- );
289
286
  }
290
287
  const createUrl = new URL(this.identityCreatorEndpoint);
291
288
  createUrl.searchParams.set(
@@ -296,6 +293,7 @@ class GraffitiDecentralized {
296
293
  "#graffiti-login-new"
297
294
  );
298
295
  createLink?.setAttribute("href", createUrl.toString());
296
+ if (proposedHandle === void 0) focusAfterOpen = createLink ?? null;
299
297
  if (this.replaceInitialLoginHistoryEntry) {
300
298
  createLink?.addEventListener("click", (event) => {
301
299
  if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
@@ -304,6 +302,7 @@ class GraffitiDecentralized {
304
302
  });
305
303
  }
306
304
  await this.modal?.open();
305
+ focusAfterOpen?.focus();
307
306
  } else {
308
307
  const readline = await import("readline").catch((e) => {
309
308
  throw new Error(
@@ -340,7 +339,6 @@ class GraffitiDecentralized {
340
339
  const provider = template?.querySelector("#graffiti-provider");
341
340
  if (provider) provider.value = defaultProvider.host;
342
341
  provider?.addEventListener("focus", () => provider.select());
343
- setTimeout(() => provider?.focus(), 0);
344
342
  template?.querySelector("#graffiti-login-provider-form")?.addEventListener("submit", (event) => {
345
343
  event.preventDefault();
346
344
  try {
@@ -363,6 +361,7 @@ class GraffitiDecentralized {
363
361
  void this.login_("");
364
362
  });
365
363
  await this.modal?.open();
364
+ provider?.focus();
366
365
  }
367
366
  rememberHandleInBrowserStorage(handle) {
368
367
  if (typeof window === "undefined") return;