@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
@@ -0,0 +1,254 @@
1
+ import { deepStrictEqual, ok, throws } from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import type { DocumentLoader } from "../docloader.ts";
4
+ import { parseIri, withGatewayHints } from "../url.ts";
5
+ import { createScopedContextLoader } from "./jsonld-cache.ts";
6
+ import {
7
+ createSnapshotContextLoader,
8
+ getPortableGatewayCandidates,
9
+ getReferrerGateways,
10
+ isPortableIri,
11
+ recordPortableReferrer,
12
+ } from "./portable-dereference.ts";
13
+
14
+ const hrefs = (urls: URL[]) => urls.map((url) => url.href);
15
+
16
+ test("isPortableIri()", () => {
17
+ ok(isPortableIri(parseIri("ap://did:key:z6Mkabc/actor")));
18
+ ok(isPortableIri(parseIri("ap+ef61://did:key:z6Mkabc/actor")));
19
+ ok(isPortableIri(new URL("ap://did%3Akey%3Az6Mkabc/actor")));
20
+ ok(!isPortableIri(new URL("https://example.com/actor")));
21
+ ok(!isPortableIri(new URL("did:key:z6Mkabc")));
22
+ });
23
+
24
+ test("getPortableGatewayCandidates() uses explicit gateways", () => {
25
+ const url = parseIri(
26
+ "ap://did:key:z6Mkabc/actor?@gateway=https%3A%2F%2Fhint.example",
27
+ );
28
+ deepStrictEqual(
29
+ hrefs(getPortableGatewayCandidates(url, [
30
+ "https://b.example",
31
+ new URL("https://a.example/"),
32
+ "https://b.example/",
33
+ "http://c.example:8080",
34
+ ])),
35
+ ["https://b.example/", "https://a.example/", "http://c.example:8080/"],
36
+ );
37
+ deepStrictEqual(getPortableGatewayCandidates(url, []), []);
38
+ for (
39
+ const gateway of [
40
+ "https://a.example/path",
41
+ "https://a.example/?",
42
+ "https://a.example/#",
43
+ "https://user:pass@a.example",
44
+ "ftp://a.example",
45
+ "a.example",
46
+ ]
47
+ ) {
48
+ throws(() => getPortableGatewayCandidates(url, [gateway]), TypeError);
49
+ }
50
+ });
51
+
52
+ test("getPortableGatewayCandidates() reads @gateway hints", () => {
53
+ deepStrictEqual(
54
+ hrefs(getPortableGatewayCandidates(parseIri(
55
+ "ap://did:key:z6Mkabc/actor?page=1" +
56
+ "&@gateway=https%3A%2F%2Fa.example" +
57
+ "&gateways=https%3A%2F%2Flegacy.example" +
58
+ "&@gateway=not%20a%20URL" +
59
+ "&@gateway=https%3A%2F%2Fb.example%2Fpath" +
60
+ "&@gateway=https%3A%2F%2Fquery.example%2F%3F" +
61
+ "&@gateway=https%3A%2F%2Ffragment.example%2F%23" +
62
+ "&%40gateway=https%3A%2F%2Fb.example" +
63
+ "&@gateway=https%3A%2F%2Fa.example%2F",
64
+ ))),
65
+ ["https://a.example/", "https://b.example/"],
66
+ );
67
+ deepStrictEqual(
68
+ getPortableGatewayCandidates(parseIri("ap://did:key:z6Mkabc/actor")),
69
+ [],
70
+ );
71
+ const hints = Array.from(
72
+ { length: 7 },
73
+ (_, i) => `@gateway=https%3A%2F%2Fg${i}.example`,
74
+ );
75
+ deepStrictEqual(
76
+ hrefs(getPortableGatewayCandidates(
77
+ parseIri(`ap://did:key:z6Mkabc/actor?${hints.join("&")}`),
78
+ )),
79
+ [0, 1, 2, 3, 4].map((i) => `https://g${i}.example/`),
80
+ );
81
+ });
82
+
83
+ test("getPortableGatewayCandidates() reads hints from withGatewayHints()", () => {
84
+ const gateways = Array.from(
85
+ { length: 7 },
86
+ (_, i) => `https://g${i}.example`,
87
+ );
88
+ deepStrictEqual(
89
+ hrefs(getPortableGatewayCandidates(
90
+ withGatewayHints("ap://did:key:z6Mkabc/actor?page=1", gateways),
91
+ )),
92
+ [0, 1, 2, 3, 4].map((i) => `https://g${i}.example/`),
93
+ );
94
+ });
95
+
96
+ test("getReferrerGateways() takes gateways from the owner", () => {
97
+ const actor = {
98
+ id: parseIri("ap://did:key:z6Mkabc/actor"),
99
+ gateways: [
100
+ new URL("https://a.example"),
101
+ new URL("https://a.example/"),
102
+ new URL("https://b.example/path"),
103
+ new URL("https://c.example"),
104
+ ],
105
+ };
106
+ const outbox = { id: parseIri("ap://did:key:z6Mkabc/actor/outbox") };
107
+ recordPortableReferrer(actor, outbox, "outbox");
108
+ const page = parseIri("ap://did:key:z6Mkabc/actor/outbox?cursor=1");
109
+
110
+ // From the actor itself, and from an object obtained from it; duplicate and
111
+ // invalid gateways are dropped:
112
+ deepStrictEqual(
113
+ hrefs(getReferrerGateways(actor, outbox.id) ?? []),
114
+ ["https://a.example/", "https://c.example/"],
115
+ );
116
+ deepStrictEqual(
117
+ hrefs(getReferrerGateways(outbox, page) ?? []),
118
+ ["https://a.example/", "https://c.example/"],
119
+ );
120
+
121
+ // Location hints take precedence:
122
+ deepStrictEqual(
123
+ getReferrerGateways(
124
+ outbox,
125
+ withGatewayHints(page, [new URL("https://hint.example")]),
126
+ ),
127
+ undefined,
128
+ );
129
+
130
+ // A reference under another DID does not belong to the actor:
131
+ deepStrictEqual(
132
+ getReferrerGateways(outbox, parseIri("ap://did:key:z6Mkdef/notes/1")),
133
+ undefined,
134
+ );
135
+
136
+ // An actor with a compatible identifier works the same way:
137
+ const compatible = {
138
+ id: new URL(
139
+ "https://a.example/.well-known/apgateway/did:key:z6Mkabc/actor",
140
+ ),
141
+ gateways: [new URL("https://a.example")],
142
+ };
143
+ deepStrictEqual(
144
+ hrefs(getReferrerGateways(compatible, outbox.id) ?? []),
145
+ ["https://a.example/"],
146
+ );
147
+
148
+ // Objects that no portable actor leads to have no gateways to offer:
149
+ deepStrictEqual(getReferrerGateways({}, page), undefined);
150
+ deepStrictEqual(
151
+ getReferrerGateways({ id: actor.id, gateways: [] }, page),
152
+ undefined,
153
+ );
154
+ });
155
+
156
+ test("createSnapshotContextLoader() does not nest released snapshots", async () => {
157
+ const calls: string[] = [];
158
+ const base: DocumentLoader = (url) => {
159
+ calls.push(url);
160
+ return Promise.resolve({
161
+ contextUrl: null,
162
+ documentUrl: url,
163
+ document: { "@context": {} },
164
+ });
165
+ };
166
+ let loader = base;
167
+ for (let i = 0; i < 10000; i++) {
168
+ const snapshot = createSnapshotContextLoader(loader);
169
+ snapshot.release();
170
+ loader = snapshot.loader;
171
+ }
172
+ // A deep chain of wrappers would overflow the stack here:
173
+ await loader("https://example.com/context");
174
+ deepStrictEqual(calls, ["https://example.com/context"]);
175
+
176
+ // Snapshots still in use are kept, so a nested snapshot sees their cache:
177
+ const outer = createSnapshotContextLoader(base);
178
+ await outer.loader("https://example.com/context");
179
+ const inner = createSnapshotContextLoader(outer.loader);
180
+ await inner.loader("https://example.com/context");
181
+ deepStrictEqual(calls.length, 2);
182
+ inner.release();
183
+ outer.release();
184
+ });
185
+
186
+ test("context loaders unwrap mixed released wrappers", async () => {
187
+ const calls: string[] = [];
188
+ const base: DocumentLoader = (url) => {
189
+ calls.push(url);
190
+ return Promise.resolve({
191
+ contextUrl: null,
192
+ documentUrl: url,
193
+ document: { "@context": {} },
194
+ });
195
+ };
196
+ for (const snapshotFirst of [false, true]) {
197
+ let loader = base;
198
+ for (let i = 0; i < 10000; i++) {
199
+ const wrapper = (i % 2 === 0) === snapshotFirst
200
+ ? createSnapshotContextLoader(loader, true)
201
+ : createScopedContextLoader(loader, true);
202
+ wrapper.release();
203
+ loader = wrapper.loader;
204
+ }
205
+ const unwrapped = createScopedContextLoader(loader, false).loader;
206
+ deepStrictEqual(unwrapped, base);
207
+ await unwrapped("https://example.com/context");
208
+ }
209
+ deepStrictEqual(calls, [
210
+ "https://example.com/context",
211
+ "https://example.com/context",
212
+ ]);
213
+ });
214
+
215
+ test("mixed context wrappers preserve active suppression and snapshots", async () => {
216
+ for (const activeSnapshot of [false, true]) {
217
+ const calls: Parameters<DocumentLoader>[1][] = [];
218
+ const base: DocumentLoader = (url, options) => {
219
+ calls.push(options);
220
+ return Promise.resolve({
221
+ contextUrl: null,
222
+ documentUrl: url,
223
+ document: { "@context": {} },
224
+ });
225
+ };
226
+ const active = activeSnapshot
227
+ ? createSnapshotContextLoader(base, true)
228
+ : createScopedContextLoader(base, true);
229
+ let loader = active.loader;
230
+ for (let i = 0; i < 4; i++) {
231
+ const wrapper = i % 2 === 0
232
+ ? createScopedContextLoader(loader, true)
233
+ : createSnapshotContextLoader(loader, true);
234
+ wrapper.release();
235
+ loader = wrapper.loader;
236
+ }
237
+ const unwrapped = createScopedContextLoader(loader, false).loader;
238
+ deepStrictEqual(unwrapped, active.loader);
239
+ const options = { signal: new AbortController().signal };
240
+ const first = await unwrapped("https://example.com/context", options);
241
+ ok(first.document != null && typeof first.document === "object");
242
+ Reflect.set(first.document, "changed", true);
243
+ const second = await unwrapped("https://example.com/context", options);
244
+ deepStrictEqual(second.document, { "@context": {} });
245
+ deepStrictEqual(calls.length, activeSnapshot ? 1 : 2);
246
+ for (const call of calls) {
247
+ deepStrictEqual(call, { ...options, suppressError: true });
248
+ }
249
+ active.release();
250
+ deepStrictEqual(createScopedContextLoader(loader, false).loader, base);
251
+ await unwrapped("https://example.com/context", options);
252
+ deepStrictEqual(calls.at(-1), options);
253
+ }
254
+ });