@fedify/vocab 2.4.0-dev.1583 → 2.4.0-dev.1618

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mod.d.cts CHANGED
@@ -10269,6 +10269,7 @@ declare class Endpoints {
10269
10269
  provideClientKey?: URL | null;
10270
10270
  signClientKey?: URL | null;
10271
10271
  sharedInbox?: URL | null;
10272
+ uploadMedia?: URL | null;
10272
10273
  }, options?: {
10273
10274
  documentLoader?: DocumentLoader$1;
10274
10275
  contextLoader?: DocumentLoader$1;
@@ -10288,6 +10289,7 @@ declare class Endpoints {
10288
10289
  provideClientKey?: URL | null;
10289
10290
  signClientKey?: URL | null;
10290
10291
  sharedInbox?: URL | null;
10292
+ uploadMedia?: URL | null;
10291
10293
  }, options?: {
10292
10294
  documentLoader?: DocumentLoader$1;
10293
10295
  contextLoader?: DocumentLoader$1;
@@ -10333,6 +10335,14 @@ declare class Endpoints {
10333
10335
  * objects which are not addressed to the `Public`` endpoint.
10334
10336
  */
10335
10337
  get sharedInbox(): URL | null;
10338
+ /** Upload endpoint URI for this user for binary data, such as an image or
10339
+ * video, as described in the [ActivityPub Media
10340
+ * Upload](https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload) extension.
10341
+ * Clients `POST` a `multipart/form-data` request containing a `file` part
10342
+ * (the binary payload) and an `object` part (an ActivityStreams object shell)
10343
+ * to this endpoint.
10344
+ */
10345
+ get uploadMedia(): URL | null;
10336
10346
  /**
10337
10347
  * Converts this object to a JSON-LD structure.
10338
10348
  * @param options The options to use.
package/dist/mod.d.ts CHANGED
@@ -10269,6 +10269,7 @@ declare class Endpoints {
10269
10269
  provideClientKey?: URL | null;
10270
10270
  signClientKey?: URL | null;
10271
10271
  sharedInbox?: URL | null;
10272
+ uploadMedia?: URL | null;
10272
10273
  }, options?: {
10273
10274
  documentLoader?: DocumentLoader$1;
10274
10275
  contextLoader?: DocumentLoader$1;
@@ -10288,6 +10289,7 @@ declare class Endpoints {
10288
10289
  provideClientKey?: URL | null;
10289
10290
  signClientKey?: URL | null;
10290
10291
  sharedInbox?: URL | null;
10292
+ uploadMedia?: URL | null;
10291
10293
  }, options?: {
10292
10294
  documentLoader?: DocumentLoader$1;
10293
10295
  contextLoader?: DocumentLoader$1;
@@ -10333,6 +10335,14 @@ declare class Endpoints {
10333
10335
  * objects which are not addressed to the `Public`` endpoint.
10334
10336
  */
10335
10337
  get sharedInbox(): URL | null;
10338
+ /** Upload endpoint URI for this user for binary data, such as an image or
10339
+ * video, as described in the [ActivityPub Media
10340
+ * Upload](https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload) extension.
10341
+ * Clients `POST` a `multipart/form-data` request containing a `file` part
10342
+ * (the binary payload) and an `object` part (an ActivityStreams object shell)
10343
+ * to this endpoint.
10344
+ */
10345
+ get uploadMedia(): URL | null;
10336
10346
  /**
10337
10347
  * Converts this object to a JSON-LD structure.
10338
10348
  * @param options The options to use.
package/dist/mod.js CHANGED
@@ -1,16 +1,16 @@
1
- import { Temporal } from "@js-temporal/polyfill";
1
+ import { Temporal } from "temporal-polyfill";
2
2
  import { lookupWebFinger } from "@fedify/webfinger";
3
3
  import { SpanStatusCode, trace } from "@opentelemetry/api";
4
4
  import { domainToASCII, domainToUnicode } from "node:url";
5
5
  import jsonld from "@fedify/vocab-runtime/jsonld";
6
6
  import { getLogger } from "@logtape/logtape";
7
- import { LanguageString, LanguageString as LanguageString$1, decodeMultibase, encodeMultibase, exportMultibaseKey, exportSpki, formatIri, getDocumentLoader, haveSameIriOrigin, importMultibaseKey, importPem, isDecimal, parseDecimal, parseIri, parseJsonLdId } from "@fedify/vocab-runtime";
7
+ import { LanguageString, LanguageString as LanguageString$1, decodeMultibase, encodeMultibase, exportMultibaseKey, exportSpki, formatIri, getDocumentLoader, haveSameFe34Origin, haveSameIriOrigin, importMultibaseKey, importPem, isDecimal, parseDecimal, parseIri, parseJsonLdId } from "@fedify/vocab-runtime";
8
8
  import { compactJsonLdCache, isTrustedIriOrigin, normalizeJsonLdIris } from "@fedify/vocab-runtime/internal/jsonld-cache";
9
9
  import { isTemporalDuration, isTemporalInstant } from "@fedify/vocab-runtime/temporal";
10
10
  import { delay } from "es-toolkit";
11
11
  //#region deno.json
12
12
  var name = "@fedify/vocab";
13
- var version = "2.4.0-dev.1583+1a6f31cb";
13
+ var version = "2.4.0-dev.1618+58858243";
14
14
  //#endregion
15
15
  //#region src/type.ts
16
16
  function getTypeId(object) {
@@ -172,6 +172,7 @@ const PORTABLE_IRI_KEYS = new Set([
172
172
  "https://www.w3.org/ns/activitystreams#target",
173
173
  "https://www.w3.org/ns/activitystreams#to",
174
174
  "https://www.w3.org/ns/activitystreams#units",
175
+ "https://www.w3.org/ns/activitystreams#uploadMedia",
175
176
  "https://www.w3.org/ns/activitystreams#url",
176
177
  "https://www.w3.org/ns/did#service",
177
178
  "https://www.w3.org/ns/did#serviceEndpoint",
@@ -233,6 +234,7 @@ const PORTABLE_IRI_KEYS = new Set([
233
234
  "target",
234
235
  "to",
235
236
  "units",
237
+ "uploadMedia",
236
238
  "url"
237
239
  ]);
238
240
  /** Describes an object of any kind. The Object type serves as the base type for
@@ -28625,6 +28627,7 @@ var Endpoints = class {
28625
28627
  #_8Bx9qN8oU7Bpt2xi6khaxWp1gMr_provideClientKey = [];
28626
28628
  #_3dU7PMVQZJpsCpo2F4RQXxBXdPmS_signClientKey = [];
28627
28629
  #_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = [];
28630
+ #_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = [];
28628
28631
  /**
28629
28632
  * Constructs a new instance of Endpoints with the given values.
28630
28633
  * @param values The values to initialize the instance with.
@@ -28651,6 +28654,8 @@ var Endpoints = class {
28651
28654
  else throw new TypeError("The signClientKey must be of type URL.");
28652
28655
  if ("sharedInbox" in values && values.sharedInbox != null) if (values.sharedInbox instanceof URL) this.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = [values.sharedInbox];
28653
28656
  else throw new TypeError("The sharedInbox must be of type URL.");
28657
+ if ("uploadMedia" in values && values.uploadMedia != null) if (values.uploadMedia instanceof URL) this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = [values.uploadMedia];
28658
+ else throw new TypeError("The uploadMedia must be of type URL.");
28654
28659
  }
28655
28660
  /**
28656
28661
  * Clones this instance, optionally updating it with the given values.
@@ -28685,6 +28690,9 @@ var Endpoints = class {
28685
28690
  clone.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = this.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox;
28686
28691
  if ("sharedInbox" in values && values.sharedInbox != null) if (values.sharedInbox instanceof URL) clone.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = [values.sharedInbox];
28687
28692
  else throw new TypeError("The sharedInbox must be of type URL.");
28693
+ clone.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia;
28694
+ if ("uploadMedia" in values && values.uploadMedia != null) if (values.uploadMedia instanceof URL) clone.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = [values.uploadMedia];
28695
+ else throw new TypeError("The uploadMedia must be of type URL.");
28688
28696
  return clone;
28689
28697
  }
28690
28698
  /** Endpoint URI so this actor's clients may access remote ActivityStreams
@@ -28752,6 +28760,18 @@ var Endpoints = class {
28752
28760
  if (this.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox.length < 1) return null;
28753
28761
  return this.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox[0];
28754
28762
  }
28763
+ /** Upload endpoint URI for this user for binary data, such as an image or
28764
+ * video, as described in the [ActivityPub Media
28765
+ * Upload](https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload) extension.
28766
+ * Clients `POST` a `multipart/form-data` request containing a `file` part
28767
+ * (the binary payload) and an `object` part (an ActivityStreams object shell)
28768
+ * to this endpoint.
28769
+ */
28770
+ get uploadMedia() {
28771
+ if (this._warning != null) getLogger(this._warning.category).warn(this._warning.message, this._warning.values);
28772
+ if (this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia.length < 1) return null;
28773
+ return this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia[0];
28774
+ }
28755
28775
  /**
28756
28776
  * Converts this object to a JSON-LD structure.
28757
28777
  * @param options The options to use.
@@ -28807,6 +28827,12 @@ var Endpoints = class {
28807
28827
  compactItems.push(item);
28808
28828
  }
28809
28829
  if (compactItems.length > 0) result["sharedInbox"] = compactItems.length > 1 ? compactItems : compactItems[0];
28830
+ compactItems = [];
28831
+ for (const v of this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia) {
28832
+ const item = formatIri(v);
28833
+ compactItems.push(item);
28834
+ }
28835
+ if (compactItems.length > 0) result["uploadMedia"] = compactItems.length > 1 ? compactItems : compactItems[0];
28810
28836
  if (this.id != null) result["id"] = formatIri(this.id);
28811
28837
  result["@context"] = "https://www.w3.org/ns/activitystreams";
28812
28838
  return result;
@@ -28849,6 +28875,12 @@ var Endpoints = class {
28849
28875
  array.push(element);
28850
28876
  }
28851
28877
  if (array.length > 0) values["https://www.w3.org/ns/activitystreams#sharedInbox"] = array;
28878
+ array = [];
28879
+ for (const v of this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia) {
28880
+ const element = { "@id": formatIri(v) };
28881
+ array.push(element);
28882
+ }
28883
+ if (array.length > 0) values["https://www.w3.org/ns/activitystreams#uploadMedia"] = array;
28852
28884
  if (this.id != null) values["@id"] = formatIri(this.id);
28853
28885
  if (options.format === "expand") return await jsonld.expand(values, { documentLoader: options.contextLoader });
28854
28886
  const docContext = options.context ?? "https://www.w3.org/ns/activitystreams";
@@ -28974,6 +29006,15 @@ var Endpoints = class {
28974
29006
  _3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox.push(decoded);
28975
29007
  }
28976
29008
  instance.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = _3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox;
29009
+ const _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = [];
29010
+ let _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array = values["https://www.w3.org/ns/activitystreams#uploadMedia"];
29011
+ for (const v of _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array == null ? [] : _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array.length === 1 && "@list" in _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array[0] ? _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array[0]["@list"] : _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array) {
29012
+ if (v == null) continue;
29013
+ const decoded = parseIri(v["@id"], options.baseUrl);
29014
+ if (typeof decoded === "undefined") continue;
29015
+ _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia.push(decoded);
29016
+ }
29017
+ instance.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia;
28977
29018
  if (!("_fromSubclass" in options) || !options._fromSubclass) try {
28978
29019
  if (cacheJsonLd != null && cacheJsonLd !== expanded) {
28979
29020
  const compactArray = Array.isArray(json) && json.length === 1;
@@ -29022,6 +29063,11 @@ var Endpoints = class {
29022
29063
  [Symbol.for("nodejs.util.inspect.custom")]: (_depth, options, inspect) => "URL " + inspect(v.href, options)
29023
29064
  } : v);
29024
29065
  if (_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox.length == 1) proxy.sharedInbox = _3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox[0];
29066
+ const _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia.map((v) => v instanceof URL ? {
29067
+ [Symbol.for("Deno.customInspect")]: (inspect, options) => "URL " + inspect(v.href, options),
29068
+ [Symbol.for("nodejs.util.inspect.custom")]: (_depth, options, inspect) => "URL " + inspect(v.href, options)
29069
+ } : v);
29070
+ if (_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia.length == 1) proxy.uploadMedia = _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia[0];
29025
29071
  return proxy;
29026
29072
  }
29027
29073
  };
@@ -53203,7 +53249,7 @@ async function lookupObjectInternal(identifier, options = {}) {
53203
53249
  }
53204
53250
  throw error;
53205
53251
  }
53206
- if (options.crossOrigin !== "trust" && object.id != null && !haveSameIriOrigin(object.id, documentUrl)) {
53252
+ if (options.crossOrigin !== "trust" && object.id != null && !haveSameIriOrigin(object.id, documentUrl) && !haveSameFe34Origin(object.id, documentUrl)) {
53207
53253
  if (options.crossOrigin === "throw") throw new Error(`The object's @id (${object.id.href}) has a different origin than the document URL (${remoteDoc.documentUrl}); refusing to return the object. If you want to bypass this check and are aware of the security implications, set the crossOrigin option to "trust".`);
53208
53254
  logger.warn("The object's @id ({objectId}) has a different origin than the document URL ({documentUrl}); refusing to return the object. If you want to bypass this check and are aware of the security implications, set the crossOrigin option to \"trust\".", {
53209
53255
  ...remoteDoc,
@@ -1,7 +1,7 @@
1
- import "@js-temporal/polyfill";
1
+ import "temporal-polyfill";
2
2
  globalThis.addEventListener = () => {};
3
- import { A as Person, G as __toESM, L as Service, U as __commonJSMin, a as Application, k as Organization, v as Group } from "./vocab-DOHLQ4UQ.mjs";
4
- import { t as getTypeId } from "./type-Cf-vxmre.mjs";
3
+ import { A as Organization, K as __toESM, R as Service, W as __commonJSMin, a as Application, j as Person, v as Group } from "./vocab-OU5GYbNg.mjs";
4
+ import { t as getTypeId } from "./type-_BlsfT3S.mjs";
5
5
  import { lookupWebFinger } from "@fedify/webfinger";
6
6
  import { SpanStatusCode, trace } from "@opentelemetry/api";
7
7
  import { domainToASCII, domainToUnicode } from "node:url";
@@ -1206,7 +1206,7 @@ var esm_default = new class FetchMock {
1206
1206
  //#endregion
1207
1207
  //#region deno.json
1208
1208
  var name = "@fedify/vocab";
1209
- var version = "2.4.0-dev.1583+1a6f31cb";
1209
+ var version = "2.4.0-dev.1618+58858243";
1210
1210
  //#endregion
1211
1211
  //#region src/actor.ts
1212
1212
  const ACTOR_DISCOVERY_HISTOGRAM_BUCKETS = [
@@ -1,7 +1,7 @@
1
- import "@js-temporal/polyfill";
1
+ import "temporal-polyfill";
2
2
  globalThis.addEventListener = () => {};
3
- import { A as Person, L as Service, W as __exportAll, a as Application, k as Organization, v as Group } from "./vocab-DOHLQ4UQ.mjs";
4
- import { a as normalizeActorHandle, c as esm_default, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-Br5HgxUd.mjs";
3
+ import { A as Organization, G as __exportAll, R as Service, a as Application, j as Person, v as Group } from "./vocab-OU5GYbNg.mjs";
4
+ import { a as normalizeActorHandle, c as esm_default, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-COnJgcOw.mjs";
5
5
  import { createTestMeterProvider, test } from "@fedify/fixture";
6
6
  import { deepStrictEqual, ok, rejects, strictEqual, throws } from "node:assert/strict";
7
7
  //#region ../../node_modules/.pnpm/fast-check@3.23.2/node_modules/fast-check/lib/esm/check/precondition/PreconditionFailure.js
@@ -0,0 +1,28 @@
1
+ import "temporal-polyfill";
2
+ globalThis.addEventListener = () => {};
3
+ import { createRequire } from "node:module";
4
+ import { mockDocumentLoader, test } from "@fedify/fixture";
5
+ import { ok, strictEqual, throws } from "node:assert";
6
+ //#region src/cjs.test.ts
7
+ test("CommonJS entry bundles temporal-polyfill internally", { ignore: "Deno" in globalThis }, async () => {
8
+ const originalTemporal = globalThis.Temporal;
9
+ const require = createRequire(import.meta.url);
10
+ throws(() => require("temporal-polyfill"), (error) => {
11
+ if (error == null || typeof error !== "object") return false;
12
+ const { code } = error;
13
+ return code === "ERR_PACKAGE_PATH_NOT_EXPORTED" || code === "MODULE_NOT_FOUND";
14
+ });
15
+ const obj = await require("../dist/mod.cjs").Object.fromJsonLd({
16
+ "@context": "https://www.w3.org/ns/activitystreams",
17
+ type: "Object",
18
+ published: "2025-01-01T12:34:56Z"
19
+ }, {
20
+ documentLoader: mockDocumentLoader,
21
+ contextLoader: mockDocumentLoader
22
+ });
23
+ ok(obj.published != null);
24
+ strictEqual(obj.published.toString(), "2025-01-01T12:34:56Z");
25
+ strictEqual(globalThis.Temporal, originalTemporal);
26
+ });
27
+ //#endregion
28
+ export {};
@@ -84,3 +84,17 @@ properties:
84
84
  objects which are not addressed to the `Public`` endpoint.
85
85
  range:
86
86
  - "http://www.w3.org/2001/XMLSchema#anyURI"
87
+
88
+ - singularName: uploadMedia
89
+ functional: true
90
+ compactName: uploadMedia
91
+ uri: "https://www.w3.org/ns/activitystreams#uploadMedia"
92
+ description: |
93
+ Upload endpoint URI for this user for binary data, such as an image or
94
+ video, as described in the [ActivityPub Media
95
+ Upload](https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload) extension.
96
+ Clients `POST` a `multipart/form-data` request containing a `file` part
97
+ (the binary payload) and an `object` part (an ActivityStreams object shell)
98
+ to this endpoint.
99
+ range:
100
+ - "http://www.w3.org/2001/XMLSchema#anyURI"
@@ -1,15 +1,15 @@
1
- import { Temporal } from "@js-temporal/polyfill";
1
+ import { Temporal } from "temporal-polyfill";
2
2
  globalThis.addEventListener = () => {};
3
- import { A as Person, E as Object$1, T as Note, o as Collection } from "./vocab-DOHLQ4UQ.mjs";
4
- import { c as esm_default, i as isActor, o as name, s as version } from "./actor-Br5HgxUd.mjs";
5
- import { t as getTypeId } from "./type-Cf-vxmre.mjs";
6
- import { t as assertInstanceOf } from "./utils-CE8Dk5hm.mjs";
3
+ import { D as Object$1, E as Note, j as Person, o as Collection } from "./vocab-OU5GYbNg.mjs";
4
+ import { c as esm_default, i as isActor, o as name, s as version } from "./actor-COnJgcOw.mjs";
5
+ import { t as getTypeId } from "./type-_BlsfT3S.mjs";
6
+ import { t as assertInstanceOf } from "./utils-CQjrpUkt.mjs";
7
7
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
8
8
  import { deepStrictEqual, equal, ok, rejects } from "node:assert/strict";
9
9
  import { lookupWebFinger } from "@fedify/webfinger";
10
10
  import { SpanStatusCode, trace } from "@opentelemetry/api";
11
11
  import { getLogger } from "@logtape/logtape";
12
- import { getDocumentLoader, haveSameIriOrigin, parseIri } from "@fedify/vocab-runtime";
12
+ import { getDocumentLoader, haveSameFe34Origin, haveSameIriOrigin, parseIri } from "@fedify/vocab-runtime";
13
13
  import { delay } from "es-toolkit";
14
14
  //#region src/handle.ts
15
15
  /**
@@ -223,7 +223,7 @@ async function lookupObjectInternal(identifier, options = {}) {
223
223
  }
224
224
  throw error;
225
225
  }
226
- if (options.crossOrigin !== "trust" && object.id != null && !haveSameIriOrigin(object.id, documentUrl)) {
226
+ if (options.crossOrigin !== "trust" && object.id != null && !haveSameIriOrigin(object.id, documentUrl) && !haveSameFe34Origin(object.id, documentUrl)) {
227
227
  if (options.crossOrigin === "throw") throw new Error(`The object's @id (${object.id.href}) has a different origin than the document URL (${remoteDoc.documentUrl}); refusing to return the object. If you want to bypass this check and are aware of the security implications, set the crossOrigin option to "trust".`);
228
228
  logger.warn("The object's @id ({objectId}) has a different origin than the document URL ({documentUrl}); refusing to return the object. If you want to bypass this check and are aware of the security implications, set the crossOrigin option to \"trust\".", {
229
229
  ...remoteDoc,
@@ -538,6 +538,73 @@ test("FEP-fe34: lookupObject() cross-origin security", {
538
538
  deepStrictEqual(result.id, new URL("https://example.com/note"));
539
539
  deepStrictEqual(result.content, "This is a legitimate note from the same origin");
540
540
  });
541
+ await t.step("same-authority non-FE34 IRIs are still trusted", async () => {
542
+ const atProtoDocumentLoader = async (url) => {
543
+ if (url === "https://gateway.example/at-item") return {
544
+ documentUrl: "at://did%3Aplc%3Aexample/collection/item",
545
+ contextUrl: null,
546
+ document: {
547
+ "@context": "https://www.w3.org/ns/activitystreams",
548
+ type: "Note",
549
+ id: "at://did:plc:example/collection/reply",
550
+ content: "AT Protocol note"
551
+ }
552
+ };
553
+ throw new Error(`Unexpected URL: ${url}`);
554
+ };
555
+ const result = await lookupObject("https://gateway.example/at-item", {
556
+ documentLoader: atProtoDocumentLoader,
557
+ contextLoader: mockDocumentLoader
558
+ });
559
+ assertInstanceOf(result, Note);
560
+ deepStrictEqual(result.id, new URL("at://did%3Aplc%3Aexample/collection/reply"));
561
+ deepStrictEqual(result.content, "AT Protocol note");
562
+ });
563
+ await t.step("portable object IDs are trusted by DID cryptographic origin", async () => {
564
+ const portableDocumentLoader = async (url) => {
565
+ if (url === "https://gateway.example/.well-known/apgateway/did:key:z6Mkabc/note") return {
566
+ documentUrl: "ap+ef61://did:key:z6Mkabc/note",
567
+ contextUrl: null,
568
+ document: {
569
+ "@context": "https://www.w3.org/ns/activitystreams",
570
+ type: "Note",
571
+ id: "ap://did:key:z6Mkabc/note",
572
+ content: "Portable note"
573
+ }
574
+ };
575
+ throw new Error(`Unexpected URL: ${url}`);
576
+ };
577
+ const result = await lookupObject("https://gateway.example/.well-known/apgateway/did:key:z6Mkabc/note", {
578
+ documentLoader: portableDocumentLoader,
579
+ contextLoader: mockDocumentLoader
580
+ });
581
+ assertInstanceOf(result, Note);
582
+ deepStrictEqual(result.content, "Portable note");
583
+ });
584
+ await t.step("portable object IDs reject mismatched cryptographic origins", async () => {
585
+ const portableDocumentLoader = async (url) => {
586
+ if (url === "https://gateway.example/.well-known/apgateway/did:key:z6Mkabc/note") return {
587
+ documentUrl: "ap+ef61://did:key:z6Mkabc/note",
588
+ contextUrl: null,
589
+ document: {
590
+ "@context": "https://www.w3.org/ns/activitystreams",
591
+ type: "Note",
592
+ id: "ap://did:key:z6Mkdef/note",
593
+ content: "Spoofed portable note"
594
+ }
595
+ };
596
+ throw new Error(`Unexpected URL: ${url}`);
597
+ };
598
+ deepStrictEqual(await lookupObject("https://gateway.example/.well-known/apgateway/did:key:z6Mkabc/note", {
599
+ documentLoader: portableDocumentLoader,
600
+ contextLoader: mockDocumentLoader
601
+ }), null);
602
+ await rejects(() => lookupObject("https://gateway.example/.well-known/apgateway/did:key:z6Mkabc/note", {
603
+ documentLoader: portableDocumentLoader,
604
+ contextLoader: mockDocumentLoader,
605
+ crossOrigin: "throw"
606
+ }), Error, "The object's @id (ap+ef61://did%3Akey%3Az6Mkdef/note) has a different origin than the document URL (ap+ef61://did:key:z6Mkabc/note)");
607
+ });
541
608
  await t.step("objects without @id are trusted", async () => {
542
609
  const noIdDocumentLoader = async (url) => {
543
610
  if (url === "https://example.com/note") return {
@@ -1,4 +1,4 @@
1
- import "@js-temporal/polyfill";
1
+ import "temporal-polyfill";
2
2
  globalThis.addEventListener = () => {};
3
3
  //#region src/type.ts
4
4
  function getTypeId(object) {
@@ -1,7 +1,7 @@
1
- import "@js-temporal/polyfill";
1
+ import "temporal-polyfill";
2
2
  globalThis.addEventListener = () => {};
3
- import { A as Person, B as getEntityTypeById, C as Link, V as isEntityType } from "./vocab-DOHLQ4UQ.mjs";
4
- import { t as getTypeId } from "./type-Cf-vxmre.mjs";
3
+ import { C as Link, H as isEntityType, V as getEntityTypeById, j as Person } from "./vocab-OU5GYbNg.mjs";
4
+ import { t as getTypeId } from "./type-_BlsfT3S.mjs";
5
5
  import { test } from "@fedify/fixture";
6
6
  import { deepStrictEqual } from "node:assert/strict";
7
7
  //#region src/type.test.ts
@@ -1,4 +1,4 @@
1
- import "@js-temporal/polyfill";
1
+ import "temporal-polyfill";
2
2
  globalThis.addEventListener = () => {};
3
3
  import { ok } from "node:assert";
4
4
  //#region src/utils.ts
@@ -1,5 +1,6 @@
1
- import { Temporal } from "@js-temporal/polyfill";
1
+ import { Temporal } from "temporal-polyfill";
2
2
  globalThis.addEventListener = () => {};
3
+ import "node:module";
3
4
  import { SpanStatusCode, trace } from "@opentelemetry/api";
4
5
  import jsonld from "@fedify/vocab-runtime/jsonld";
5
6
  import { getLogger } from "@logtape/logtape";
@@ -281,6 +282,7 @@ const PORTABLE_IRI_KEYS = new Set([
281
282
  "https://www.w3.org/ns/activitystreams#target",
282
283
  "https://www.w3.org/ns/activitystreams#to",
283
284
  "https://www.w3.org/ns/activitystreams#units",
285
+ "https://www.w3.org/ns/activitystreams#uploadMedia",
284
286
  "https://www.w3.org/ns/activitystreams#url",
285
287
  "https://www.w3.org/ns/did#service",
286
288
  "https://www.w3.org/ns/did#serviceEndpoint",
@@ -342,6 +344,7 @@ const PORTABLE_IRI_KEYS = new Set([
342
344
  "target",
343
345
  "to",
344
346
  "units",
347
+ "uploadMedia",
345
348
  "url"
346
349
  ]);
347
350
  /** Describes an object of any kind. The Object type serves as the base type for
@@ -28734,6 +28737,7 @@ var Endpoints = class {
28734
28737
  #_8Bx9qN8oU7Bpt2xi6khaxWp1gMr_provideClientKey = [];
28735
28738
  #_3dU7PMVQZJpsCpo2F4RQXxBXdPmS_signClientKey = [];
28736
28739
  #_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = [];
28740
+ #_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = [];
28737
28741
  /**
28738
28742
  * Constructs a new instance of Endpoints with the given values.
28739
28743
  * @param values The values to initialize the instance with.
@@ -28760,6 +28764,8 @@ var Endpoints = class {
28760
28764
  else throw new TypeError("The signClientKey must be of type URL.");
28761
28765
  if ("sharedInbox" in values && values.sharedInbox != null) if (values.sharedInbox instanceof URL) this.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = [values.sharedInbox];
28762
28766
  else throw new TypeError("The sharedInbox must be of type URL.");
28767
+ if ("uploadMedia" in values && values.uploadMedia != null) if (values.uploadMedia instanceof URL) this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = [values.uploadMedia];
28768
+ else throw new TypeError("The uploadMedia must be of type URL.");
28763
28769
  }
28764
28770
  /**
28765
28771
  * Clones this instance, optionally updating it with the given values.
@@ -28794,6 +28800,9 @@ var Endpoints = class {
28794
28800
  clone.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = this.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox;
28795
28801
  if ("sharedInbox" in values && values.sharedInbox != null) if (values.sharedInbox instanceof URL) clone.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = [values.sharedInbox];
28796
28802
  else throw new TypeError("The sharedInbox must be of type URL.");
28803
+ clone.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia;
28804
+ if ("uploadMedia" in values && values.uploadMedia != null) if (values.uploadMedia instanceof URL) clone.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = [values.uploadMedia];
28805
+ else throw new TypeError("The uploadMedia must be of type URL.");
28797
28806
  return clone;
28798
28807
  }
28799
28808
  /** Endpoint URI so this actor's clients may access remote ActivityStreams
@@ -28861,6 +28870,18 @@ var Endpoints = class {
28861
28870
  if (this.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox.length < 1) return null;
28862
28871
  return this.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox[0];
28863
28872
  }
28873
+ /** Upload endpoint URI for this user for binary data, such as an image or
28874
+ * video, as described in the [ActivityPub Media
28875
+ * Upload](https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload) extension.
28876
+ * Clients `POST` a `multipart/form-data` request containing a `file` part
28877
+ * (the binary payload) and an `object` part (an ActivityStreams object shell)
28878
+ * to this endpoint.
28879
+ */
28880
+ get uploadMedia() {
28881
+ if (this._warning != null) getLogger(this._warning.category).warn(this._warning.message, this._warning.values);
28882
+ if (this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia.length < 1) return null;
28883
+ return this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia[0];
28884
+ }
28864
28885
  /**
28865
28886
  * Converts this object to a JSON-LD structure.
28866
28887
  * @param options The options to use.
@@ -28916,6 +28937,12 @@ var Endpoints = class {
28916
28937
  compactItems.push(item);
28917
28938
  }
28918
28939
  if (compactItems.length > 0) result["sharedInbox"] = compactItems.length > 1 ? compactItems : compactItems[0];
28940
+ compactItems = [];
28941
+ for (const v of this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia) {
28942
+ const item = formatIri(v);
28943
+ compactItems.push(item);
28944
+ }
28945
+ if (compactItems.length > 0) result["uploadMedia"] = compactItems.length > 1 ? compactItems : compactItems[0];
28919
28946
  if (this.id != null) result["id"] = formatIri(this.id);
28920
28947
  result["@context"] = "https://www.w3.org/ns/activitystreams";
28921
28948
  return result;
@@ -28958,6 +28985,12 @@ var Endpoints = class {
28958
28985
  array.push(element);
28959
28986
  }
28960
28987
  if (array.length > 0) values["https://www.w3.org/ns/activitystreams#sharedInbox"] = array;
28988
+ array = [];
28989
+ for (const v of this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia) {
28990
+ const element = { "@id": formatIri(v) };
28991
+ array.push(element);
28992
+ }
28993
+ if (array.length > 0) values["https://www.w3.org/ns/activitystreams#uploadMedia"] = array;
28961
28994
  if (this.id != null) values["@id"] = formatIri(this.id);
28962
28995
  if (options.format === "expand") return await jsonld.expand(values, { documentLoader: options.contextLoader });
28963
28996
  const docContext = options.context ?? "https://www.w3.org/ns/activitystreams";
@@ -29083,6 +29116,15 @@ var Endpoints = class {
29083
29116
  _3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox.push(decoded);
29084
29117
  }
29085
29118
  instance.#_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox = _3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox;
29119
+ const _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = [];
29120
+ let _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array = values["https://www.w3.org/ns/activitystreams#uploadMedia"];
29121
+ for (const v of _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array == null ? [] : _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array.length === 1 && "@list" in _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array[0] ? _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array[0]["@list"] : _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia__array) {
29122
+ if (v == null) continue;
29123
+ const decoded = parseIri(v["@id"], options.baseUrl);
29124
+ if (typeof decoded === "undefined") continue;
29125
+ _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia.push(decoded);
29126
+ }
29127
+ instance.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia;
29086
29128
  if (!("_fromSubclass" in options) || !options._fromSubclass) try {
29087
29129
  if (cacheJsonLd != null && cacheJsonLd !== expanded) {
29088
29130
  const compactArray = Array.isArray(json) && json.length === 1;
@@ -29131,6 +29173,11 @@ var Endpoints = class {
29131
29173
  [Symbol.for("nodejs.util.inspect.custom")]: (_depth, options, inspect) => "URL " + inspect(v.href, options)
29132
29174
  } : v);
29133
29175
  if (_3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox.length == 1) proxy.sharedInbox = _3JprUSDLVqqX4dwHRi37qGZZCRCc_sharedInbox[0];
29176
+ const _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia = this.#_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia.map((v) => v instanceof URL ? {
29177
+ [Symbol.for("Deno.customInspect")]: (inspect, options) => "URL " + inspect(v.href, options),
29178
+ [Symbol.for("nodejs.util.inspect.custom")]: (_depth, options, inspect) => "URL " + inspect(v.href, options)
29179
+ } : v);
29180
+ if (_KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia.length == 1) proxy.uploadMedia = _KukVKGqFRETxAxXA15YCYAA7XAT_uploadMedia[0];
29134
29181
  return proxy;
29135
29182
  }
29136
29183
  };
@@ -52873,4 +52920,4 @@ function getEntityTypeById(id) {
52873
52920
  return entityTypeIds.get(typeof id === "string" ? id : id?.href);
52874
52921
  }
52875
52922
  //#endregion
52876
- export { Person as A, getEntityTypeById as B, Link as C, Offer as D, Object$1 as E, QuoteRequest as F, __toESM as G, vocab_exports as H, Reject as I, Service as L, Proposal as M, Question as N, OrderedCollectionPage as O, QuoteAuthorization as P, Source as R, InteractionRule as S, Note as T, __commonJSMin as U, isEntityType as V, __exportAll as W, Follow as _, Application as a, Intent as b, Create as c, Document as d, Endpoints as f, FeaturedItem as g, FeaturedCollection as h, Announce as i, Place as j, Organization as k, CryptographicKey as l, FeatureRequest as m, Activity as n, Collection as o, FeatureAuthorization as p, Agreement as r, Commitment as s, Accept as t, Delete as u, Group as v, Measure as w, InteractionPolicy as x, Hashtag as y, Tombstone as z };
52923
+ export { Organization as A, Tombstone as B, Link as C, Object$1 as D, Note as E, QuoteAuthorization as F, __exportAll as G, isEntityType as H, QuoteRequest as I, __toESM as K, Reject as L, Place as M, Proposal as N, Offer as O, Question as P, Service as R, InteractionRule as S, Multikey as T, vocab_exports as U, getEntityTypeById as V, __commonJSMin as W, Follow as _, Application as a, Intent as b, Create as c, Document as d, Endpoints as f, FeaturedItem as g, FeaturedCollection as h, Announce as i, Person as j, OrderedCollectionPage as k, CryptographicKey as l, FeatureRequest as m, Activity as n, Collection as o, FeatureAuthorization as p, Agreement as r, Commitment as s, Accept as t, Delete as u, Group as v, Measure as w, InteractionPolicy as x, Hashtag as y, Source as z };