@fedify/vocab-runtime 2.4.0-pr.936.41 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/deno.json +4 -2
  2. package/dist/{tests/docloader-Ck8bcBir.mjs → contexts-B09jb9Pi.cjs} +173 -274
  3. package/dist/{tests/docloader-S_gQZ2tt.cjs → contexts-DWrj4AGR.js} +169 -293
  4. package/dist/{docloader-C_dir7Xb.d.ts → docloader-BMHljyYb.d.cts} +68 -2
  5. package/dist/{docloader-D2DTRiyA.d.cts → docloader-BMHljyYb.d.ts} +68 -2
  6. package/dist/internal/jsonld-cache.cjs +70 -1
  7. package/dist/internal/jsonld-cache.d.cts +35 -2
  8. package/dist/internal/jsonld-cache.d.ts +35 -2
  9. package/dist/internal/jsonld-cache.js +67 -2
  10. package/dist/internal/portable-dereference.cjs +721 -0
  11. package/dist/internal/portable-dereference.d.cts +349 -0
  12. package/dist/internal/portable-dereference.d.ts +349 -0
  13. package/dist/internal/portable-dereference.js +702 -0
  14. package/dist/internal/signed-representation.cjs +378 -0
  15. package/dist/internal/signed-representation.d.cts +144 -0
  16. package/dist/internal/signed-representation.d.ts +144 -0
  17. package/dist/internal/signed-representation.js +371 -0
  18. package/dist/jsonld.cjs +2 -2
  19. package/dist/mod.cjs +762 -4529
  20. package/dist/mod.d.cts +427 -9
  21. package/dist/mod.d.ts +427 -10
  22. package/dist/mod.js +742 -4524
  23. package/dist/portable-6Aj-7dZJ.d.cts +160 -0
  24. package/dist/portable-nkTiqH0w.d.ts +160 -0
  25. package/dist/tests/body-DpC9p-iG.mjs +130 -0
  26. package/dist/tests/body-cKLBprYm.cjs +153 -0
  27. package/dist/tests/body.test.cjs +89 -0
  28. package/dist/tests/body.test.d.cts +1 -0
  29. package/dist/tests/body.test.d.mts +1 -0
  30. package/dist/tests/body.test.mjs +90 -0
  31. package/dist/tests/contexts-C9Lj11SC.cjs +4533 -0
  32. package/dist/tests/contexts-duRA_dDC.mjs +4522 -0
  33. package/dist/tests/decimal.test.cjs +9 -7
  34. package/dist/tests/decimal.test.mjs +9 -6
  35. package/dist/tests/digest-3FeH2Y-Q.cjs +176 -0
  36. package/dist/tests/digest-COC7xDiQ.mjs +141 -0
  37. package/dist/tests/digest.test.cjs +102 -0
  38. package/dist/tests/digest.test.d.cts +1 -0
  39. package/dist/tests/digest.test.d.mts +1 -0
  40. package/dist/tests/digest.test.mjs +103 -0
  41. package/dist/tests/docloader-DyZ1JGIl.cjs +398 -0
  42. package/dist/tests/docloader-tUmMeXjU.mjs +375 -0
  43. package/dist/tests/docloader.test.cjs +816 -39
  44. package/dist/tests/docloader.test.mjs +810 -34
  45. package/dist/tests/internal/multicodec.test.cjs +2 -3
  46. package/dist/tests/internal/multicodec.test.mjs +2 -2
  47. package/dist/tests/internal/portable-dereference.test.cjs +172 -0
  48. package/dist/tests/internal/portable-dereference.test.d.cts +1 -0
  49. package/dist/tests/internal/portable-dereference.test.d.mts +1 -0
  50. package/dist/tests/internal/portable-dereference.test.mjs +173 -0
  51. package/dist/tests/jsonld-CmDhHNTx.cjs +12 -0
  52. package/dist/tests/jsonld-DweIJ07b.mjs +5 -0
  53. package/dist/tests/jsonld-cache-BEXiiM-V.cjs +386 -0
  54. package/dist/tests/jsonld-cache-DFnWsLuZ.mjs +339 -0
  55. package/dist/tests/jsonld-cache.test.cjs +102 -298
  56. package/dist/tests/jsonld-cache.test.mjs +95 -289
  57. package/dist/tests/{key-_wXwomh_.cjs → key-C-AYkdJJ.cjs} +11 -4
  58. package/dist/tests/{key-CDGDH_vC.mjs → key-C2Db_TAJ.mjs} +11 -3
  59. package/dist/tests/key.test.cjs +6 -5
  60. package/dist/tests/key.test.mjs +6 -4
  61. package/dist/tests/{langstr-Di5AvKpB.mjs → langstr-DYRmJqFn.mjs} +5 -2
  62. package/dist/tests/{langstr-CbAxaeEZ.cjs → langstr-_PqsL1ae.cjs} +5 -2
  63. package/dist/tests/langstr.test.cjs +11 -4
  64. package/dist/tests/langstr.test.mjs +9 -2
  65. package/dist/tests/langtag-CUppHs_s.mjs +45 -0
  66. package/dist/tests/langtag-Czjvxfzx.cjs +50 -0
  67. package/dist/tests/langtag.test.cjs +45 -0
  68. package/dist/tests/langtag.test.d.cts +1 -0
  69. package/dist/tests/langtag.test.d.mts +1 -0
  70. package/dist/tests/langtag.test.mjs +46 -0
  71. package/dist/tests/link.test.cjs +2 -3
  72. package/dist/tests/link.test.mjs +2 -2
  73. package/dist/tests/multibase/multibase.test.cjs +8 -9
  74. package/dist/tests/multibase/multibase.test.mjs +6 -6
  75. package/dist/tests/{multibase-Bz_UUDtL.cjs → multibase-B5Mea7Ip.cjs} +19 -2
  76. package/dist/tests/{multibase-B4bvakyA.mjs → multibase-BPnF_L4e.mjs} +12 -1
  77. package/dist/tests/portable-dereference-DmTYDy2p.mjs +250 -0
  78. package/dist/tests/portable-dereference-qTLMqe2_.cjs +279 -0
  79. package/dist/tests/portable-media-5p8azal0.cjs +153 -0
  80. package/dist/tests/portable-media-B_lt9MMA.mjs +148 -0
  81. package/dist/tests/portable-media.test.cjs +222 -0
  82. package/dist/tests/portable-media.test.d.cts +1 -0
  83. package/dist/tests/portable-media.test.d.mts +1 -0
  84. package/dist/tests/portable-media.test.mjs +223 -0
  85. package/dist/tests/portable-workers.test.cjs +36 -0
  86. package/dist/tests/portable-workers.test.d.cts +2 -0
  87. package/dist/tests/portable-workers.test.d.mts +2 -0
  88. package/dist/tests/portable-workers.test.mjs +35 -0
  89. package/dist/tests/{request-uk51rkhO.cjs → request-BgjA9wyl.cjs} +10 -4
  90. package/dist/tests/{request-C8CaGwtt.mjs → request-DodZNukP.mjs} +8 -2
  91. package/dist/tests/request.test.cjs +7 -4
  92. package/dist/tests/request.test.mjs +5 -2
  93. package/dist/tests/signed-representation.test.cjs +588 -0
  94. package/dist/tests/signed-representation.test.d.cts +1 -0
  95. package/dist/tests/signed-representation.test.d.mts +1 -0
  96. package/dist/tests/signed-representation.test.mjs +589 -0
  97. package/dist/tests/temporal.test.cjs +1 -2
  98. package/dist/tests/temporal.test.mjs +1 -1
  99. package/dist/tests/url-BNakuZ8k.cjs +998 -0
  100. package/dist/tests/url-DMxmp7ZG.mjs +859 -0
  101. package/dist/tests/url.test.cjs +489 -6
  102. package/dist/tests/url.test.mjs +489 -5
  103. package/dist/url-DrGTR8yv.cjs +993 -0
  104. package/dist/url-Dzyp-NsC.js +860 -0
  105. package/package.json +27 -4
  106. package/scripts/test-bun.mjs +17 -0
  107. package/src/body.test.ts +125 -0
  108. package/src/body.ts +152 -0
  109. package/src/contexts/cid-v1.json +114 -0
  110. package/src/contexts/fep-22cd.json +21 -0
  111. package/src/contexts/fep-6757.json +12 -0
  112. package/src/contexts/joinmastodon.json +1 -1
  113. package/src/contexts/miscellany.json +17 -0
  114. package/src/contexts.ts +47 -1
  115. package/src/digest.test.ts +220 -0
  116. package/src/digest.ts +229 -0
  117. package/src/docloader.test.ts +1066 -27
  118. package/src/docloader.ts +322 -105
  119. package/src/internal/jsonld-cache.ts +97 -1
  120. package/src/internal/portable-dereference.test.ts +254 -0
  121. package/src/internal/portable-dereference.ts +1000 -0
  122. package/src/internal/signed-representation.ts +565 -0
  123. package/src/jsonld-cache.test.ts +89 -0
  124. package/src/key.test.ts +9 -0
  125. package/src/key.ts +11 -1
  126. package/src/langstr.test.ts +18 -1
  127. package/src/langstr.ts +6 -2
  128. package/src/langtag.test.ts +53 -0
  129. package/src/langtag.ts +76 -0
  130. package/src/mod.ts +29 -0
  131. package/src/multibase/multibase.test.ts +5 -5
  132. package/src/portable-media.test.ts +293 -0
  133. package/src/portable-media.ts +264 -0
  134. package/src/portable-workers.test.ts +81 -0
  135. package/src/portable.ts +180 -0
  136. package/src/preprocessor.ts +7 -0
  137. package/src/request.test.ts +10 -1
  138. package/src/request.ts +9 -1
  139. package/src/signed-representation.test.ts +338 -0
  140. package/src/url.test.ts +823 -3
  141. package/src/url.ts +700 -23
  142. package/tsdown.config.ts +2 -0
  143. package/dist/tests/url-CsOV_B_P.cjs +0 -482
  144. package/dist/tests/url-Du7RQQgP.mjs +0 -392
  145. package/dist/url-DD4F0ULf.cjs +0 -483
  146. package/dist/url-DGVbSVVi.js +0 -393
  147. /package/dist/{chunk-M78iaK0I.cjs → rolldown-runtime-B7lfambq.cjs} +0 -0
  148. /package/dist/tests/{link-NUUWCdnK.mjs → link-Cevmc87v.mjs} +0 -0
  149. /package/dist/tests/{link-FguCydMA.cjs → link-DlKm8bEr.cjs} +0 -0
  150. /package/dist/tests/{multicodec-CxGVGa91.cjs → multicodec-CLRPeW4N.cjs} +0 -0
  151. /package/dist/tests/{multicodec-CyFp54fI.mjs → multicodec-CRIj_05H.mjs} +0 -0
  152. /package/dist/tests/{chunk-C2EiDwsr.cjs → rolldown-runtime-emK7D4bc.cjs} +0 -0
package/dist/mod.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { a as DocumentLoaderOptions, c as getDocumentLoader, d as FetchError, f as GetUserAgentOptions, h as logRequest, i as DocumentLoaderFactoryOptions, l as getRemoteDocument, m as getUserAgent, n as DocumentLoader, o as GetDocumentLoaderOptions, p as createActivityPubRequest, r as DocumentLoaderFactory, s as RemoteDocument, t as AuthenticatedDocumentLoaderFactory, u as CreateRequestOptions } from "./docloader-C_dir7Xb.js";
2
+ import { _ as logRequest, a as DocumentLoaderOptions, c as getDocumentLoader, d as withDocumentLoaderTimeout, f as CreateRequestOptions, g as getUserAgent, h as createActivityPubRequest, i as DocumentLoaderFactoryOptions, l as getRemoteDocument, m as GetUserAgentOptions, n as DocumentLoader, o as GetDocumentLoaderOptions, p as FetchError, r as DocumentLoaderFactory, s as RemoteDocument, t as AuthenticatedDocumentLoaderFactory, u as resolveDocumentLoaderTimeout } from "./docloader-BMHljyYb.js";
3
+ import { i as PortableObjectVerifierOptions, n as PortableObjectVerification, r as PortableObjectVerifier, t as PortableObjectReferrer } from "./portable-nkTiqH0w.js";
3
4
  import { TracerProvider } from "@opentelemetry/api";
4
-
5
5
  //#region src/contexts.d.ts
6
6
  declare const preloadedContexts: Record<string, unknown>;
7
7
  //#endregion
@@ -73,9 +73,16 @@ declare function importDidKey(did: string | URL): Promise<CryptoKey>;
73
73
  /**
74
74
  * Exports an Ed25519 public key as a `did:key` DID.
75
75
  *
76
+ * The DID is encoded in base58-btc with the Ed25519 multicodec prefix, e.g.,
77
+ * `did:key:z6Mk...`, as [FEP-ef61] requires for the DIDs of portable
78
+ * objects.
79
+ *
80
+ * [FEP-ef61]: https://w3id.org/fep/ef61
81
+ *
76
82
  * @param key The Ed25519 public key.
77
83
  * @returns The `did:key` DID.
78
- * @throws {TypeError} If the key is invalid or unsupported.
84
+ * @throws {TypeError} If the key is invalid or unsupported, or it is not
85
+ * a public key.
79
86
  * @since 2.4.0
80
87
  */
81
88
  declare function exportDidKey(key: CryptoKey): Promise<string>;
@@ -204,6 +211,87 @@ declare function canParseDecimal(value: string): boolean;
204
211
  */
205
212
  declare function parseDecimal(value: string): Decimal;
206
213
  //#endregion
214
+ //#region src/digest.d.ts
215
+ /**
216
+ * A parsed SHA-256 resource digest.
217
+ *
218
+ * @since 2.4.0
219
+ */
220
+ interface ParsedDigestMultibase {
221
+ /** The multihash algorithm represented by the digest. */
222
+ readonly algorithm: "sha2-256";
223
+ /** The raw 32-byte SHA-256 digest. */
224
+ readonly digest: Uint8Array;
225
+ }
226
+ /**
227
+ * A parsed simple hashlink.
228
+ *
229
+ * @since 2.4.0
230
+ */
231
+ interface ParsedHashlink {
232
+ /** The multibase-encoded multihash carried by the hashlink. */
233
+ readonly digestMultibase: string;
234
+ }
235
+ /**
236
+ * Computes the SHA-256 digest of a byte sequence and encodes it as a
237
+ * base58-btc multibase multihash suitable for FEP-ef61's
238
+ * `digestMultibase` property.
239
+ *
240
+ * @param bytes The bytes to digest.
241
+ * @returns The base58-btc multibase-encoded SHA-256 multihash.
242
+ * @since 2.4.0
243
+ */
244
+ declare function computeDigestMultibase(bytes: Uint8Array): Promise<string>;
245
+ /**
246
+ * Parses and validates a SHA-256 `digestMultibase` value.
247
+ *
248
+ * @param value The multibase-encoded multihash to parse.
249
+ * @returns The digest algorithm and raw digest bytes.
250
+ * @throws {TypeError} If the value is malformed or uses an unsupported hash
251
+ * algorithm.
252
+ * @since 2.4.0
253
+ */
254
+ declare function parseDigestMultibase(value: string): ParsedDigestMultibase;
255
+ /**
256
+ * Parses a metadata-free `hl:` hashlink and validates its resource digest.
257
+ *
258
+ * @param value The simple hashlink to parse.
259
+ * @returns The `digestMultibase` value carried by the hashlink.
260
+ * @throws {TypeError} If the hashlink is malformed, contains metadata, or
261
+ * carries an invalid or unsupported digest.
262
+ * @since 2.4.0
263
+ */
264
+ declare function parseHashlink(value: string | URL): ParsedHashlink;
265
+ /**
266
+ * Creates a metadata-free `hl:` hashlink from a `digestMultibase` value.
267
+ *
268
+ * @param digestMultibase The SHA-256 multibase multihash to embed.
269
+ * @returns The simple hashlink.
270
+ * @throws {TypeError} If the digest is malformed or unsupported.
271
+ * @since 2.4.0
272
+ */
273
+ declare function createHashlink(digestMultibase: string): string;
274
+ /**
275
+ * Verifies that bytes match a SHA-256 `digestMultibase` value.
276
+ *
277
+ * @param bytes The bytes to verify.
278
+ * @param digestMultibase The expected digest.
279
+ * @returns Whether the bytes match the digest.
280
+ * @throws {TypeError} If the digest is malformed or unsupported.
281
+ * @since 2.4.0
282
+ */
283
+ declare function verifyDigestMultibase(bytes: Uint8Array, digestMultibase: string): Promise<boolean>;
284
+ /**
285
+ * Verifies that bytes match the resource digest in a simple hashlink.
286
+ *
287
+ * @param bytes The bytes to verify.
288
+ * @param hashlink The simple hashlink containing the expected digest.
289
+ * @returns Whether the bytes match the hashlink digest.
290
+ * @throws {TypeError} If the hashlink or digest is malformed or unsupported.
291
+ * @since 2.4.0
292
+ */
293
+ declare function verifyHashlink(bytes: Uint8Array, hashlink: string | URL): Promise<boolean>;
294
+ //#endregion
207
295
  //#region src/langstr.d.ts
208
296
  /**
209
297
  * A language-tagged string which corresponds to the `rdf:langString` type.
@@ -218,11 +306,81 @@ declare class LanguageString extends String {
218
306
  * Constructs a new `LanguageString`.
219
307
  * @param value A string value written in the given language.
220
308
  * @param language The language of the string. If a string is given, it will
221
- * be parsed as a `Intl.Locale` object.
309
+ * be parsed as a `Intl.Locale` object. Extended language
310
+ * subtags are normalized first, e.g., `zh-yue` is parsed as
311
+ * `yue`.
222
312
  */
223
313
  constructor(value: string, language: Intl.Locale | string);
224
314
  }
225
315
  //#endregion
316
+ //#region src/langtag.d.ts
317
+ /**
318
+ * Normalizes a BCP 47 language tag that has an extended language subtag
319
+ * (extlang), such as `zh-yue`, into its canonical form, such as `yue`, as
320
+ * described in [RFC 5646, Section 4.5][1]. `Intl.Locale` rejects extlang
321
+ * tags, so tags should be normalized before being passed to it.
322
+ *
323
+ * Only registered extlangs that follow their registered prefix are removed;
324
+ * any other tag is returned unchanged, so the result still needs to be
325
+ * validated, e.g., by `Intl.Locale`.
326
+ *
327
+ * NOTE: This function is marked as internal in the 2.0.x–2.4.x patch
328
+ * releases. When merging it into the *main* branch, remove the `@internal`
329
+ * tag, formalize it as a public API (`@since 2.5.0`), and add it to
330
+ * the changelog fragment.
331
+ *
332
+ * [1]: https://www.rfc-editor.org/rfc/rfc5646.html#section-4.5
333
+ *
334
+ * @param tag The BCP 47 language tag to normalize.
335
+ * @returns The normalized language tag.
336
+ * @internal
337
+ */
338
+ declare function normalizeLanguageTag(tag: string): string;
339
+ //#endregion
340
+ //#region src/portable-media.d.ts
341
+ /** A link or document with an external resource and its integrity digest. */
342
+ interface PortableMedia {
343
+ readonly href?: URL | null;
344
+ readonly url?: URL | {
345
+ readonly href: URL | null;
346
+ readonly digestMultibase?: string | null;
347
+ } | null;
348
+ readonly digestMultibase?: string | null;
349
+ }
350
+ /** Options for {@link fetchPortableMedia}. */
351
+ interface FetchPortableMediaOptions {
352
+ /** Ordered FEP-ef61 gateway origins used for `hl:` resources. */
353
+ readonly gateways?: Iterable<string | URL>;
354
+ /** Expected digest when the first argument is a URL or string. */
355
+ readonly digestMultibase?: string;
356
+ /** Maximum decoded response size in bytes. Defaults to 16 MiB. */
357
+ readonly maxBytes?: number;
358
+ /** Whether private network addresses may be fetched. Defaults to `false`. */
359
+ readonly allowPrivateAddress?: boolean;
360
+ /** The HTTP `User-Agent` value or its components. */
361
+ readonly userAgent?: string | GetUserAgentOptions;
362
+ /** Cancels the entire retrieval and all gateway attempts. */
363
+ readonly signal?: AbortSignal;
364
+ /** Overall timeout in milliseconds. Defaults to 10 seconds; `null` disables it. */
365
+ readonly timeout?: number | null;
366
+ /** Timeout per gateway in milliseconds. Defaults to 3 seconds. */
367
+ readonly gatewayTimeout?: number | null;
368
+ }
369
+ /**
370
+ * Fetches a portable object's external media and returns it only after its
371
+ * SHA-256 `digestMultibase` has been verified. `hl:` resources are tried at
372
+ * the supplied gateways in order. The result contains verified body bytes;
373
+ * its `Content-Type` is unverified metadata supplied by the server.
374
+ *
375
+ * @param media A Link, Image, Document, or URL with an external resource.
376
+ * @param options Retrieval, integrity, and network policy options.
377
+ * @returns A response containing only verified bytes.
378
+ * @throws {TypeError} If the media reference or digest is invalid.
379
+ * @throws {Error} If no source supplies a matching bounded resource.
380
+ * @since 2.4.0
381
+ */
382
+ declare function fetchPortableMedia(media: string | URL | PortableMedia, options?: FetchPortableMediaOptions): Promise<Response>;
383
+ //#endregion
226
384
  //#region src/multibase/types.d.ts
227
385
  type BaseCode = "\x00" | "0" | "7" | "9" | "f" | "F" | "v" | "V" | "t" | "T" | "b" | "B" | "c" | "C" | "h" | "k" | "K" | "z" | "Z" | "m" | "M" | "u" | "U";
228
386
  /**
@@ -295,6 +453,12 @@ interface PropertyPreprocessorContext {
295
453
  contextLoader?: DocumentLoader;
296
454
  /** OpenTelemetry tracer provider for instrumentation. */
297
455
  tracerProvider?: TracerProvider;
456
+ /**
457
+ * The default FEP-ef61 portable object verifier that objects returned by
458
+ * the preprocessor should use for their property accessors.
459
+ * @since 2.4.0
460
+ */
461
+ verifyPortableObject?: PortableObjectVerifier;
298
462
  /** Base URL for resolving relative references. */
299
463
  baseUrl?: URL;
300
464
  }
@@ -311,18 +475,66 @@ type PropertyPreprocessor<T = unknown> = (value: Json, context: PropertyPreproce
311
475
  //#endregion
312
476
  //#region src/url.d.ts
313
477
  declare class UrlError extends Error {
314
- constructor(message: string);
478
+ /**
479
+ * The failure category. Defaults to `"disallowed"`.
480
+ * `"dns"` includes lookup errors and results with no usable IP addresses.
481
+ * @since 2.0.29
482
+ */
483
+ readonly reason: "dns" | "disallowed";
484
+ constructor(message: string, options?: {
485
+ cause?: unknown;
486
+ reason?: "dns" | "disallowed";
487
+ });
315
488
  }
316
489
  /**
317
- * Parses a JSON-LD `@id` value as an IRI.
490
+ * Parses a JSON-LD `@id` value as an IRI, including FEP-ef61 portable
491
+ * ActivityPub IRIs. See {@link parseIri} for how IRIs are parsed.
492
+ * @param id The `@id` value.
493
+ * @param base The base IRI to resolve a relative `@id` against.
494
+ * @returns The parsed IRI, or `undefined` if `id` is missing or a blank node
495
+ * identifier.
496
+ * @throws {TypeError} If `id` is not a valid IRI.
497
+ * @since 2.4.0
318
498
  */
319
499
  declare function parseJsonLdId(id: string | undefined, base?: string | URL): URL | undefined;
320
500
  /**
321
501
  * Parses an IRI as a URL, including FEP-ef61 portable ActivityPub IRIs.
502
+ * Portable URI and FEP-ef61 compatible identifier strings whose path contains
503
+ * a `.` or `..` segment, including percent-encoded spellings, throw a
504
+ * `TypeError`: JavaScript `URL` would otherwise identify a different object.
505
+ * This also applies to compatible identifier strings used as relative bases.
506
+ * A `URL` argument may already have lost such segments before this function
507
+ * receives it.
508
+ *
509
+ * Portable IRIs, e.g., `ap://did:key:z6Mk.../actor`, cannot be represented by
510
+ * JavaScript `URL` as they are, so the returned `URL` keeps the DID authority
511
+ * percent-encoded, e.g., `ap+ef61://did%3Akey%3Az6Mk.../actor`. Use
512
+ * {@link formatIri} to get the canonical string back.
513
+ * @param iri The IRI to parse.
514
+ * @param base The base IRI to resolve a relative IRI against.
515
+ * @returns The parsed IRI.
516
+ * @throws {TypeError} If the IRI is malformed.
517
+ * @since 2.4.0
322
518
  */
323
519
  declare function parseIri(iri: string | URL, base?: string | URL): URL;
324
520
  /**
325
521
  * Formats a URL as an IRI, including FEP-ef61 portable ActivityPub IRIs.
522
+ * Portable URI and FEP-ef61 compatible identifier strings with dot segments
523
+ * throw a `TypeError` because their paths cannot be represented by JavaScript
524
+ * `URL` without normalization.
525
+ *
526
+ * Portable IRIs are formatted with the `ap+ef61:` scheme and a decoded DID
527
+ * authority, even if they were parsed from `ap:` IRIs. FEP-ef61 currently
528
+ * recommends the `ap:` scheme, so a future major version of Fedify may change
529
+ * the scheme this function produces. Do not compare its results as strings to
530
+ * tell whether two portable IRIs identify the same object; use
531
+ * `arePortableUrisEqual()` instead.
532
+ * @param iri The IRI to format.
533
+ * @returns The formatted IRI. A string that cannot be parsed as a URL at all
534
+ * is returned unchanged.
535
+ * @throws {TypeError} If the IRI is a malformed portable IRI or FEP-ef61
536
+ * compatible identifier, e.g., one with dot segments.
537
+ * @since 2.4.0
326
538
  */
327
539
  declare function formatIri(iri: string | URL): string;
328
540
  /**
@@ -334,6 +546,12 @@ declare function formatIri(iri: string | URL): string;
334
546
  * string, not a `URL` object, because JavaScript `URL` normalizes opaque path
335
547
  * segments before Fedify can compare them.
336
548
  *
549
+ * The `ap+ef61:` scheme of the result is a choice of Fedify's, whereas
550
+ * FEP-ef61 currently canonicalizes portable URIs with the `ap:` scheme.
551
+ * A future major version of Fedify may change the scheme of the result, so
552
+ * do not persist the result as the only copy of an identifier; keep the
553
+ * original URI, and canonicalize it again when comparing.
554
+ *
337
555
  * @param input The raw portable ActivityPub URI string to canonicalize.
338
556
  * @returns The canonical portable ActivityPub URI string.
339
557
  * @throws {TypeError} If the input is not a valid portable ActivityPub IRI.
@@ -371,18 +589,217 @@ declare function getFe34Origin(input: string | URL): string;
371
589
  */
372
590
  declare function haveSameFe34Origin(left: string | URL, right: string | URL): boolean;
373
591
  /**
374
- * Checks whether two IRIs have the same origin.
592
+ * Checks whether two IRIs have the same origin. Unlike comparing
593
+ * `URL.origin`, which is `"null"` for URLs with non-special schemes, this
594
+ * compares FEP-ef61 portable ActivityPub IRIs by their schemes and DIDs, so
595
+ * that `ap:` and `ap+ef61:` IRIs of the same DID with decoded or
596
+ * percent-encoded authorities have the same origin. Other IRIs with
597
+ * a non-special scheme and a host are compared by their schemes and hosts.
598
+ *
599
+ * This is not an FEP-fe34 origin check: an `ap+ef61:` IRI and the `did:key`
600
+ * verification method of the same DID have different origins here. Use
601
+ * {@link haveSameFe34Origin} for that.
602
+ * @param left The first IRI.
603
+ * @param right The second IRI.
604
+ * @returns `true` if the IRIs have the same origin.
605
+ * @since 2.4.0
375
606
  */
376
607
  declare function haveSameIriOrigin(left: URL, right: URL): boolean;
377
608
  /**
378
- * Checks whether the URL is an FEP-ef61 gateway base URI.
609
+ * Checks whether the URL is an FEP-ef61 gateway base URI, i.e., an HTTP(S)
610
+ * URI with no credentials, path, query, or fragment, such as
611
+ * `https://example.com/`. FEP-ef61 requires every item of a portable actor's
612
+ * `gateways` to be such a URI. A URI with an empty query or fragment
613
+ * delimiter, such as `https://example.com/?`, is not a gateway base URI.
614
+ *
615
+ * Note that the `URL` class normalizes `https://example.com` to
616
+ * `https://example.com/`, so both are gateway base URIs.
617
+ * @param url The URL to check.
618
+ * @returns `true` if the URL is an FEP-ef61 gateway base URI.
619
+ * @since 2.4.0
379
620
  */
380
621
  declare function isGatewayUrl(url: URL): boolean;
381
622
  /**
382
- * Parses and validates an FEP-ef61 gateway base URI.
623
+ * Parses and validates an FEP-ef61 gateway base URI, i.e., an HTTP(S) URI with
624
+ * no credentials, path, query, or fragment, such as `https://example.com`.
625
+ * See {@link isGatewayUrl} for the rules.
626
+ * @param url The gateway base URI to parse.
627
+ * @returns The parsed gateway base URI, whose path is `/`.
628
+ * @throws {TypeError} If the URI is malformed, or is not an HTTP(S) base URI
629
+ * with no credentials, path, query, or fragment. In the
630
+ * latter case, the message starts with
631
+ * `Invalid FEP-ef61 gateway:`.
632
+ * @since 2.4.0
383
633
  */
384
634
  declare function parseGatewayUrl(url: string): URL;
385
635
  /**
636
+ * Converts an [FEP-ef61] compatible identifier into a portable ActivityPub
637
+ * URI.
638
+ *
639
+ * A compatible identifier is an HTTP(S) URL under a gateway's fixed
640
+ * `/.well-known/apgateway/` path, such as
641
+ * `https://server.example/.well-known/apgateway/did:key:z6Mk.../objects/1`.
642
+ * This function removes the gateway part and returns the corresponding
643
+ * portable URI, e.g., `ap+ef61://did:key:z6Mk.../objects/1`, in the same
644
+ * internal `URL` form that {@link parseIri} produces. The path, query, and
645
+ * fragment are preserved, so the result is a portable URI, not a comparison
646
+ * form; pass its `href` to {@link canonicalizePortableUri} or
647
+ * {@link arePortableUrisEqual} to compare it with other portable URIs.
648
+ *
649
+ * The conversion only reveals the *claimed* portable identifier. Anyone can
650
+ * publish a compatible identifier for any DID on their own server, so the
651
+ * gateway that served it is neither the object's origin nor authorized to act
652
+ * for the DID. Callers must still verify the retrieved document's Object
653
+ * Integrity Proof against the DID, as FEP-ef61 requires, and should keep the
654
+ * original URL if they need the gateway as a retrieval hint.
655
+ *
656
+ * Arbitrary gateway paths are not supported.
657
+ *
658
+ * [FEP-ef61]: https://w3id.org/fep/ef61
659
+ *
660
+ * @param input The URL to convert.
661
+ * @returns The portable ActivityPub URI, or `null` if the input is not an
662
+ * HTTP(S) URL whose path starts with `/.well-known/apgateway/did:`.
663
+ * Other gateway routes, such as the gateway discovery endpoint and
664
+ * hashlink media URLs, also yield `null`.
665
+ * @throws {TypeError} If the input looks like a compatible identifier but is
666
+ * malformed, e.g., it has an invalid DID, no object path,
667
+ * invalid percent-encoding, credentials, or location
668
+ * hints (`@gateway` query parameters, or the legacy
669
+ * `gateways` parameter), or its raw string path would
670
+ * change during URL parsing. Already-parsed `URL`
671
+ * arguments cannot reveal segments lost by their parser.
672
+ * @since 2.4.0
673
+ */
674
+ declare function fromCompatibleEf61Id(input: string | URL): URL | null;
675
+ /**
676
+ * Converts a portable ActivityPub URI into an [FEP-ef61] compatible
677
+ * identifier, which is an HTTP(S) URL under the gateway's fixed
678
+ * `/.well-known/apgateway/` path.
679
+ *
680
+ * For example, `ap+ef61://did:key:z6Mk.../objects/1` and
681
+ * `https://server.example` yield
682
+ * `https://server.example/.well-known/apgateway/did:key:z6Mk.../objects/1`.
683
+ * Both `ap:` and `ap+ef61:` URIs with decoded or percent-encoded DID
684
+ * authorities are accepted. Publishers should use the first gateway in the
685
+ * actor's `gateways` list, as FEP-ef61 requires.
686
+ *
687
+ * The path and fragment are preserved, with characters that are not allowed
688
+ * in HTTP(S) URLs percent-encoded the same way as
689
+ * {@link canonicalizePortableUri} does. FEP-ef61 location hints (`@gateway`
690
+ * query parameters, and the legacy `gateways` parameter) are removed, since
691
+ * compatible identifiers must not have them; other query parameters are kept
692
+ * in order.
693
+ *
694
+ * Arbitrary gateway paths are not supported.
695
+ *
696
+ * [FEP-ef61]: https://w3id.org/fep/ef61
697
+ *
698
+ * @param portableId The `ap:` or `ap+ef61:` URI to convert.
699
+ * @param gateway The gateway's HTTP(S) origin, e.g., `https://server.example`.
700
+ * @returns The compatible identifier.
701
+ * @throws {TypeError} If the portable ID is not a valid `ap:` or `ap+ef61:`
702
+ * URI, if its path has `.` or `..` segments (which
703
+ * HTTP(S) URLs cannot represent without changing the
704
+ * identified object), or if the gateway is
705
+ * not an HTTP(S) origin with no credentials, path, query,
706
+ * or fragment.
707
+ * @since 2.4.0
708
+ */
709
+ declare function toCompatibleEf61Id(portableId: string | URL, gateway: string | URL): URL;
710
+ /**
711
+ * Returns a copy of an [FEP-ef61] portable ActivityPub URI with `@gateway`
712
+ * location hints for the given gateways, which tell consumers where they can
713
+ * retrieve the object. Put hints on *references* to portable actors, e.g.,
714
+ * in `actor`, `attributedTo`, `to`, or `cc`, when constructing an object, as
715
+ * FEP-ef61 recommends:
716
+ *
717
+ * ~~~~ typescript
718
+ * withGatewayHints("ap://did:key:z6Mk.../actor", [
719
+ * "https://server1.example",
720
+ * "https://server2.example",
721
+ * ]);
722
+ * // ap+ef61://did:key:z6Mk.../actor?@gateway=https%3A%2F%2Fserver1.example&@gateway=https%3A%2F%2Fserver2.example
723
+ * ~~~~
724
+ *
725
+ * Do not put hints on an object's own `id`. Hints do not change the
726
+ * identity of a portable URI, since FEP-ef61 drops the query when comparing
727
+ * portable URIs, but implementations that do not canonicalize portable URIs
728
+ * would take a hinted ID for another object. Add hints before signing the
729
+ * object, since its Object Integrity Proof covers its references too.
730
+ *
731
+ * The hints that the URI already has, including the legacy `gateways`
732
+ * parameter, are replaced. Each gateway becomes a `@gateway` query
733
+ * parameter whose value is its URI-encoded origin, e.g.,
734
+ * `@gateway=https%3A%2F%2Fserver1.example`, in the given order after the
735
+ * other query parameters. Duplicate gateways are dropped, and an empty list
736
+ * removes the hints as {@link withoutGatewayHints} does. The other query
737
+ * parameters, their order, and the fragment are kept, but percent-encoding
738
+ * is normalized the same way as {@link canonicalizePortableUri} does it.
739
+ *
740
+ * Fedify follows at most five hints when dereferencing a portable URI
741
+ * (three for the key ID of an HTTP Signature), so list the preferred
742
+ * gateways first; there is no limit on the number of hints added here.
743
+ *
744
+ * [FEP-ef61]: https://w3id.org/fep/ef61
745
+ *
746
+ * @param portableId The `ap:` or `ap+ef61:` URI. Pass the raw string rather
747
+ * than a `URL` if its path may have `.` or `..` segments,
748
+ * because the `URL` class resolves them.
749
+ * @param gateways The gateways, e.g., the `gateways` of the actor that the
750
+ * URI refers to. Each has to be an HTTP(S) origin with no
751
+ * credentials, path, query, or fragment.
752
+ * @returns The portable URI with the hints, in the same internal `URL` form
753
+ * as {@link parseIri} returns. Use {@link formatIri} to get its
754
+ * canonical string.
755
+ * @throws {TypeError} If the portable ID is not a valid `ap:` or `ap+ef61:`
756
+ * URI, e.g., it is a compatible identifier, which must
757
+ * not have location hints; if its path has `.` or `..`
758
+ * segments, which the `URL` class cannot represent; or
759
+ * if a gateway is invalid.
760
+ * @since 2.4.0
761
+ */
762
+ declare function withGatewayHints(portableId: string | URL, gateways: Iterable<string | URL>): URL;
763
+ /**
764
+ * Returns a copy of an [FEP-ef61] portable ActivityPub URI without its
765
+ * location hints, i.e., `@gateway` query parameters and the legacy
766
+ * `gateways` parameter. The other query parameters, their order, and the
767
+ * fragment are kept, but percent-encoding is normalized the same way as
768
+ * {@link canonicalizePortableUri} does it.
769
+ *
770
+ * [FEP-ef61]: https://w3id.org/fep/ef61
771
+ *
772
+ * @param portableId The `ap:` or `ap+ef61:` URI. Pass the raw string rather
773
+ * than a `URL` if its path may have `.` or `..` segments,
774
+ * because the `URL` class resolves them.
775
+ * @returns The portable URI without the hints, in the same internal `URL`
776
+ * form as {@link parseIri} returns.
777
+ * @throws {TypeError} If the portable ID is not a valid `ap:` or `ap+ef61:`
778
+ * URI, or if its path has `.` or `..` segments, which
779
+ * the `URL` class cannot represent.
780
+ * @since 2.4.0
781
+ */
782
+ declare function withoutGatewayHints(portableId: string | URL): URL;
783
+ /**
784
+ * Gets the gateways in the `@gateway` location hints of an [FEP-ef61]
785
+ * portable ActivityPub URI, in order. Hints that are not valid gateways,
786
+ * i.e., HTTP(S) origins with no credentials, path, query, or fragment, are
787
+ * skipped, and so are duplicates. The legacy `gateways` parameter is not
788
+ * read.
789
+ *
790
+ * Unlike Fedify's dereferencing, which follows at most five hints, this
791
+ * returns all of them.
792
+ *
793
+ * [FEP-ef61]: https://w3id.org/fep/ef61
794
+ *
795
+ * @param portableId The `ap:` or `ap+ef61:` URI.
796
+ * @returns The gateways, e.g., `https://server1.example/`.
797
+ * @throws {TypeError} If the portable ID is not a valid `ap:` or `ap+ef61:`
798
+ * URI.
799
+ * @since 2.4.0
800
+ */
801
+ declare function getGatewayHints(portableId: string | URL): URL[];
802
+ /**
386
803
  * Validates a URL to prevent SSRF attacks.
387
804
  */
388
805
  declare function validatePublicUrl(url: string): Promise<void>;
@@ -390,4 +807,4 @@ declare function isValidPublicIPv4Address(address: string): boolean;
390
807
  declare function isValidPublicIPv6Address(address: string): boolean;
391
808
  declare function expandIPv6Address(address: string): string;
392
809
  //#endregion
393
- export { type AuthenticatedDocumentLoaderFactory, type CreateRequestOptions, type Decimal, type DidKeyVerificationMethod, type DocumentLoader, type DocumentLoaderFactory, type DocumentLoaderFactoryOptions, type DocumentLoaderOptions, FetchError, type GetDocumentLoaderOptions, type GetUserAgentOptions, type Json, LanguageString, type PropertyPreprocessor, type PropertyPreprocessorContext, type RemoteDocument, UrlError, arePortableUrisEqual, canParseDecimal, canonicalizePortableUri, createActivityPubRequest, decodeMultibase, encodeMultibase, encodingFromBaseData, expandIPv6Address, exportDidKey, exportMultibaseKey, exportSpki, formatIri, getDocumentLoader, getFe34Origin, getRemoteDocument, getUserAgent, haveSameFe34Origin, haveSameIriOrigin, importDidKey, importMultibaseKey, importPem, importPkcs1, importSpki, isDecimal, isGatewayUrl, isValidPublicIPv4Address, isValidPublicIPv6Address, logRequest, parseDecimal, parseDidKeyVerificationMethod, parseGatewayUrl, parseIri, parseJsonLdId, preloadedContexts, validatePublicUrl };
810
+ export { type AuthenticatedDocumentLoaderFactory, type CreateRequestOptions, type Decimal, type DidKeyVerificationMethod, type DocumentLoader, type DocumentLoaderFactory, type DocumentLoaderFactoryOptions, type DocumentLoaderOptions, FetchError, type FetchPortableMediaOptions, type GetDocumentLoaderOptions, type GetUserAgentOptions, type Json, LanguageString, type ParsedDigestMultibase, type ParsedHashlink, type PortableMedia, type PortableObjectReferrer, type PortableObjectVerification, type PortableObjectVerifier, type PortableObjectVerifierOptions, type PropertyPreprocessor, type PropertyPreprocessorContext, type RemoteDocument, UrlError, arePortableUrisEqual, canParseDecimal, canonicalizePortableUri, computeDigestMultibase, createActivityPubRequest, createHashlink, decodeMultibase, encodeMultibase, encodingFromBaseData, expandIPv6Address, exportDidKey, exportMultibaseKey, exportSpki, fetchPortableMedia, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, getGatewayHints, getRemoteDocument, getUserAgent, haveSameFe34Origin, haveSameIriOrigin, importDidKey, importMultibaseKey, importPem, importPkcs1, importSpki, isDecimal, isGatewayUrl, isValidPublicIPv4Address, isValidPublicIPv6Address, logRequest, normalizeLanguageTag, parseDecimal, parseDidKeyVerificationMethod, parseDigestMultibase, parseGatewayUrl, parseHashlink, parseIri, parseJsonLdId, preloadedContexts, resolveDocumentLoaderTimeout, toCompatibleEf61Id, validatePublicUrl, verifyDigestMultibase, verifyHashlink, withDocumentLoaderTimeout, withGatewayHints, withoutGatewayHints };