@fedify/vocab 2.0.29-dev.2107 → 2.0.29-dev.2139

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.
@@ -1,6 +1,6 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  globalThis.addEventListener = () => {};
3
- import { _ as PropertyValue, a as Create, b as Source, d as Note, f as Object$1, g as Place, h as Person, i as Collection, l as Hashtag, n as Announce, o as CryptographicKey, p as OrderedCollectionPage, s as Follow, t as Activity, u as Link, v as Question, x as vocab_exports } from "./vocab-C_YFgzlY.mjs";
3
+ import { _ as PropertyValue, a as Create, b as Source, d as Note, f as Object$1, g as Place, h as Person, i as Collection, l as Hashtag, n as Announce, o as CryptographicKey, p as OrderedCollectionPage, s as Follow, t as Activity, u as Link, v as Question, x as vocab_exports } from "./vocab-CLB8P-Fw.mjs";
4
4
  import { t as assertInstanceOf } from "./utils-CE8Dk5hm.mjs";
5
5
  import { mockDocumentLoader, test } from "@fedify/fixture";
6
6
  import { deepStrictEqual, notDeepStrictEqual, ok, rejects, throws } from "node:assert/strict";
@@ -351,6 +351,72 @@ test({
351
351
  deepStrictEqual(objects2[0].name, "Second object");
352
352
  }
353
353
  });
354
+ function embeddedPropertyDocument(property) {
355
+ const context = "https://www.w3.org/ns/activitystreams";
356
+ return {
357
+ "@context": [context, { CustomImage: `${context}#Image` }],
358
+ type: property === "attachment" ? "Note" : "Create",
359
+ [property]: [
360
+ {
361
+ "@context": [context, { "@vocab": "https://example.com/" }],
362
+ type: "CustomImage",
363
+ name: "Malformed when reparsed"
364
+ },
365
+ {
366
+ "@context": context,
367
+ type: "Image",
368
+ name: "Cached image"
369
+ },
370
+ {
371
+ type: "Image",
372
+ name: "Decoded image"
373
+ }
374
+ ]
375
+ };
376
+ }
377
+ for (const suppressError of [
378
+ void 0,
379
+ false,
380
+ true
381
+ ]) {
382
+ test(`Note.getAttachments() cached parse failure (suppressError: ${suppressError})`, async () => {
383
+ const jsonLd = embeddedPropertyDocument("attachment");
384
+ const note = await Note.fromJsonLd(jsonLd);
385
+ if (suppressError) {
386
+ for (let i = 0; i < 2; i++) deepStrictEqual((await Array.fromAsync(note.getAttachments({ suppressError }))).map((attachment) => attachment.name), ["Cached image", "Decoded image"]);
387
+ await rejects(() => Array.fromAsync(note.getAttachments()), TypeError);
388
+ } else await rejects(() => Array.fromAsync(note.getAttachments({ suppressError })), TypeError);
389
+ deepStrictEqual(await note.toJsonLd(), jsonLd);
390
+ });
391
+ test(`Activity.getObject() cached parse failure (suppressError: ${suppressError})`, async () => {
392
+ const jsonLd = embeddedPropertyDocument("object");
393
+ const activity = await Activity.fromJsonLd(jsonLd);
394
+ if (suppressError) {
395
+ deepStrictEqual(await activity.getObject({ suppressError }), null);
396
+ deepStrictEqual(await activity.getObject({ suppressError }), null);
397
+ await rejects(() => activity.getObject(), TypeError);
398
+ } else await rejects(() => activity.getObject({ suppressError }), TypeError);
399
+ deepStrictEqual(await activity.toJsonLd(), jsonLd);
400
+ });
401
+ }
402
+ test("Note.getAttachments() suppresses cached context loader failures", async () => {
403
+ const note = await Note.fromJsonLd(embeddedPropertyDocument("attachment"));
404
+ const contextLoader = () => Promise.reject(/* @__PURE__ */ new Error("Context loader failed"));
405
+ await rejects(() => Array.fromAsync(note.getAttachments({ contextLoader })), (error) => error instanceof Error && !(error instanceof TypeError));
406
+ deepStrictEqual((await Array.fromAsync(note.getAttachments({
407
+ contextLoader,
408
+ suppressError: true
409
+ }))).map((attachment) => attachment.name), ["Decoded image"]);
410
+ });
411
+ test("Activity.getObject() suppresses cached context loader failures", async () => {
412
+ const activity = await Activity.fromJsonLd(embeddedPropertyDocument("object"));
413
+ const contextLoader = () => Promise.reject(/* @__PURE__ */ new Error("Context loader failed"));
414
+ await rejects(() => activity.getObject({ contextLoader }), (error) => error instanceof Error && !(error instanceof TypeError));
415
+ deepStrictEqual(await activity.getObject({
416
+ contextLoader,
417
+ suppressError: true
418
+ }), null);
419
+ });
354
420
  test("Activity.clone()", async () => {
355
421
  const activity = new Activity({
356
422
  actor: new Person({ name: "John Doe" }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/vocab",
3
- "version": "2.0.29-dev.2107+5ab4c99b",
3
+ "version": "2.0.29-dev.2139+7e5d091d",
4
4
  "homepage": "https://fedify.dev/",
5
5
  "repository": {
6
6
  "type": "git",
@@ -46,9 +46,9 @@
46
46
  "es-toolkit": "1.43.0",
47
47
  "jsonld": "^9.0.0",
48
48
  "pkijs": "^3.3.3",
49
- "@fedify/webfinger": "2.0.29-dev.2107+5ab4c99b",
50
- "@fedify/vocab-tools": "2.0.29-dev.2107+5ab4c99b",
51
- "@fedify/vocab-runtime": "2.0.29-dev.2107+5ab4c99b"
49
+ "@fedify/vocab-tools": "2.0.29-dev.2139+7e5d091d",
50
+ "@fedify/webfinger": "2.0.29-dev.2139+7e5d091d",
51
+ "@fedify/vocab-runtime": "2.0.29-dev.2139+7e5d091d"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "^22.17.0",
package/src/vocab.test.ts CHANGED
@@ -538,6 +538,104 @@ test({
538
538
  },
539
539
  });
540
540
 
541
+ // The alias is inherited during initial expansion, but is unavailable when
542
+ // an embedded value is reparsed standalone from the cached JSON-LD.
543
+ function embeddedPropertyDocument(property: "attachment" | "object") {
544
+ const context = "https://www.w3.org/ns/activitystreams";
545
+ return {
546
+ "@context": [context, { CustomImage: `${context}#Image` }],
547
+ type: property === "attachment" ? "Note" : "Create",
548
+ [property]: [
549
+ {
550
+ "@context": [context, { "@vocab": "https://example.com/" }],
551
+ type: "CustomImage",
552
+ name: "Malformed when reparsed",
553
+ },
554
+ { "@context": context, type: "Image", name: "Cached image" },
555
+ { type: "Image", name: "Decoded image" },
556
+ ],
557
+ };
558
+ }
559
+
560
+ for (const suppressError of [undefined, false, true]) {
561
+ test(
562
+ `Note.getAttachments() cached parse failure (suppressError: ${suppressError})`,
563
+ async () => {
564
+ const jsonLd = embeddedPropertyDocument("attachment");
565
+ const note = await Note.fromJsonLd(jsonLd);
566
+ if (suppressError) {
567
+ for (let i = 0; i < 2; i++) {
568
+ const attachments: (Object | Link | PropertyValue)[] = await Array
569
+ .fromAsync(
570
+ note.getAttachments({ suppressError }),
571
+ );
572
+ deepStrictEqual(
573
+ attachments.map((attachment) => attachment.name),
574
+ ["Cached image", "Decoded image"],
575
+ );
576
+ }
577
+ // Suppression must not remove or replace the cached malformed value.
578
+ await rejects(() => Array.fromAsync(note.getAttachments()), TypeError);
579
+ } else {
580
+ await rejects(
581
+ () => Array.fromAsync(note.getAttachments({ suppressError })),
582
+ TypeError,
583
+ );
584
+ }
585
+ deepStrictEqual(await note.toJsonLd(), jsonLd);
586
+ },
587
+ );
588
+
589
+ test(
590
+ `Activity.getObject() cached parse failure (suppressError: ${suppressError})`,
591
+ async () => {
592
+ const jsonLd = embeddedPropertyDocument("object");
593
+ const activity = await Activity.fromJsonLd(jsonLd);
594
+ if (suppressError) {
595
+ deepStrictEqual(await activity.getObject({ suppressError }), null);
596
+ deepStrictEqual(await activity.getObject({ suppressError }), null);
597
+ await rejects(() => activity.getObject(), TypeError);
598
+ } else {
599
+ await rejects(() => activity.getObject({ suppressError }), TypeError);
600
+ }
601
+ deepStrictEqual(await activity.toJsonLd(), jsonLd);
602
+ },
603
+ );
604
+ }
605
+
606
+ test("Note.getAttachments() suppresses cached context loader failures", async () => {
607
+ const note = await Note.fromJsonLd(embeddedPropertyDocument("attachment"));
608
+ const contextLoader = () =>
609
+ Promise.reject(new Error("Context loader failed"));
610
+ await rejects(
611
+ () => Array.fromAsync(note.getAttachments({ contextLoader })),
612
+ (error: unknown) => error instanceof Error && !(error instanceof TypeError),
613
+ );
614
+ // Both cached values need the failing loader; the decoded value remains usable.
615
+ const attachments: (Object | Link | PropertyValue)[] = await Array.fromAsync(
616
+ note.getAttachments({ contextLoader, suppressError: true }),
617
+ );
618
+ deepStrictEqual(attachments.map((attachment) => attachment.name), [
619
+ "Decoded image",
620
+ ]);
621
+ });
622
+
623
+ test("Activity.getObject() suppresses cached context loader failures", async () => {
624
+ const activity = await Activity.fromJsonLd(
625
+ embeddedPropertyDocument("object"),
626
+ );
627
+ const contextLoader = () =>
628
+ Promise.reject(new Error("Context loader failed"));
629
+ await rejects(
630
+ () => activity.getObject({ contextLoader }),
631
+ (error: unknown) => error instanceof Error && !(error instanceof TypeError),
632
+ );
633
+ deepStrictEqual(
634
+ await activity.getObject({ contextLoader, suppressError: true }),
635
+ null,
636
+ );
637
+ });
638
+
541
639
  test("Activity.clone()", async () => {
542
640
  const activity = new Activity({
543
641
  actor: new Person({