@fedify/vocab 2.5.0-dev.2504 → 2.5.0-dev.2516
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/deno.json +1 -1
- package/dist/mod.cjs +13426 -2215
- package/dist/mod.d.cts +9001 -782
- package/dist/mod.d.ts +9001 -782
- package/dist/mod.js +13427 -2216
- package/dist-tests/{actor-BRLxkkip.mjs → actor-HAORUnb8.mjs} +2 -2
- package/dist-tests/actor.test.mjs +2 -2
- package/dist-tests/deep-clone.test.mjs +292 -0
- package/dist-tests/gateway.test.mjs +71 -4
- package/dist-tests/license.test.mjs +2 -2
- package/dist-tests/{lookup-C20BmzHy.mjs → lookup-B9VbSKaj.mjs} +2 -2
- package/dist-tests/lookup.test.mjs +2 -2
- package/dist-tests/portable-lookup.test.mjs +3 -3
- package/dist-tests/signed-representation.test.mjs +15 -1
- package/dist-tests/sparse-arrays.test.mjs +459 -0
- package/dist-tests/{src-CB6Qo4bK.mjs → src-sHf6TARh.mjs} +3 -3
- package/dist-tests/translation.test.mjs +2 -2
- package/dist-tests/type.test.mjs +1 -1
- package/dist-tests/{vocab-BmIsd6gR.mjs → vocab-CCAqTuHd.mjs} +13427 -2216
- package/dist-tests/vocab.test.mjs +2 -2
- package/package.json +4 -4
- package/src/deep-clone.test.ts +347 -0
- package/src/gateway.test.ts +81 -5
- package/src/signed-representation.test.ts +21 -0
- package/src/sparse-arrays.test.ts +507 -0
- package/src/vocab.bench.ts +63 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { t as getTypeId } from "./type-BMdjm4Eg.mjs";
|
|
4
|
-
import { F as
|
|
4
|
+
import { F as Organization, I as Person, W as Service, a as Application, x as Group } from "./vocab-CCAqTuHd.mjs";
|
|
5
5
|
import { canonicalizePortableUri, formatIri, fromCompatibleEf61Id, isGatewayUrl } from "@fedify/vocab-runtime";
|
|
6
6
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
7
7
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
8
8
|
import { domainToASCII, domainToUnicode } from "node:url";
|
|
9
9
|
//#region deno.json
|
|
10
10
|
var name = "@fedify/vocab";
|
|
11
|
-
var version = "2.5.0-dev.
|
|
11
|
+
var version = "2.5.0-dev.2516+42d3ed0b";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/actor.ts
|
|
14
14
|
const ACTOR_DISCOVERY_HISTOGRAM_BUCKETS = [
|
|
@@ -2,8 +2,8 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { n as __exportAll } from "./rolldown-runtime-BWJg4WE8.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-BIqRhjGA.mjs";
|
|
5
|
-
import { a as normalizeActorHandle, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-
|
|
6
|
-
import { F as
|
|
5
|
+
import { a as normalizeActorHandle, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-HAORUnb8.mjs";
|
|
6
|
+
import { F as Organization, I as Person, W as Service, a as Application, x as Group } from "./vocab-CCAqTuHd.mjs";
|
|
7
7
|
import { createTestMeterProvider, test } from "@fedify/fixture";
|
|
8
8
|
import { deepStrictEqual, ok, rejects, strictEqual, throws } from "node:assert/strict";
|
|
9
9
|
//#region ../../node_modules/.pnpm/fast-check@3.23.2/node_modules/fast-check/lib/esm/check/precondition/PreconditionFailure.js
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { Temporal } from "temporal-polyfill";
|
|
2
|
+
globalThis.addEventListener = () => {};
|
|
3
|
+
import { A as Note, D as Link, G as Source, H as QuoteRequest, I as Person, U as Reject, f as DataIntegrityProof, h as Endpoints, j as Object$1, t as Accept, u as Create } from "./vocab-CCAqTuHd.mjs";
|
|
4
|
+
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
5
|
+
import { deepStrictEqual, notStrictEqual, ok, strictEqual, throws } from "node:assert/strict";
|
|
6
|
+
import { LanguageString } from "@fedify/vocab-runtime";
|
|
7
|
+
import { Buffer } from "node:buffer";
|
|
8
|
+
//#region src/deep-clone.test.ts
|
|
9
|
+
const options = { contextLoader: mockDocumentLoader };
|
|
10
|
+
function personLoader(name, fetched = []) {
|
|
11
|
+
return async (url) => {
|
|
12
|
+
fetched.push(url);
|
|
13
|
+
return {
|
|
14
|
+
contextUrl: null,
|
|
15
|
+
documentUrl: url,
|
|
16
|
+
document: {
|
|
17
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
18
|
+
id: url,
|
|
19
|
+
type: "Person",
|
|
20
|
+
name
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
for (const hydrateOriginal of [false, true]) test(`deepClone() isolates embedded quote hydration (${hydrateOriginal})`, async () => {
|
|
26
|
+
const original = await QuoteRequest.fromJsonLd({
|
|
27
|
+
"@context": ["https://www.w3.org/ns/activitystreams", { QuoteRequest: "https://w3id.org/fep/044f#QuoteRequest" }],
|
|
28
|
+
id: "https://a.example/requests/1",
|
|
29
|
+
type: "QuoteRequest",
|
|
30
|
+
instrument: {
|
|
31
|
+
id: "https://a.example/notes/1",
|
|
32
|
+
type: "Note",
|
|
33
|
+
attributedTo: "https://a.example/alice",
|
|
34
|
+
content: "Quoted"
|
|
35
|
+
}
|
|
36
|
+
}, {
|
|
37
|
+
...options,
|
|
38
|
+
documentLoader: personLoader("Alice")
|
|
39
|
+
});
|
|
40
|
+
const copy = original.deepClone();
|
|
41
|
+
const sourceNote = await original.getInstrument();
|
|
42
|
+
const copyNote = await copy.getInstrument();
|
|
43
|
+
ok(sourceNote instanceof Note && copyNote instanceof Note);
|
|
44
|
+
notStrictEqual(copyNote, sourceNote);
|
|
45
|
+
strictEqual((await (hydrateOriginal ? sourceNote : copyNote).getAttribution())?.name, "Alice");
|
|
46
|
+
for (const Wrapper of [Accept, Reject]) strictEqual((await new Wrapper({ object: hydrateOriginal ? copy : original }).toJsonLd(options)).object.instrument.attributedTo, "https://a.example/alice");
|
|
47
|
+
strictEqual(await original.getInstrument(), sourceNote);
|
|
48
|
+
strictEqual(await copy.getInstrument(), copyNote);
|
|
49
|
+
});
|
|
50
|
+
test("deepClone() copies replacements and preserves graph aliases", async () => {
|
|
51
|
+
const id = new URL("https://example.com/notes/1");
|
|
52
|
+
const child = new Note({
|
|
53
|
+
id,
|
|
54
|
+
url: id,
|
|
55
|
+
content: "Child"
|
|
56
|
+
});
|
|
57
|
+
const source = new Create({
|
|
58
|
+
object: child,
|
|
59
|
+
attachments: [child]
|
|
60
|
+
});
|
|
61
|
+
const copy = source.deepClone({ objects: [child, child] });
|
|
62
|
+
const objects = await Array.fromAsync(copy.getObjects());
|
|
63
|
+
const attachment = (await Array.fromAsync(copy.getAttachments()))[0];
|
|
64
|
+
strictEqual(objects[0], objects[1]);
|
|
65
|
+
strictEqual(objects[0], attachment);
|
|
66
|
+
notStrictEqual(objects[0], child);
|
|
67
|
+
strictEqual(objects[0].id, objects[0].url);
|
|
68
|
+
notStrictEqual(objects[0].id, id);
|
|
69
|
+
objects[0].id.pathname = "/changed";
|
|
70
|
+
strictEqual(id.pathname, "/notes/1");
|
|
71
|
+
strictEqual(await source.getObject(), child);
|
|
72
|
+
const backReference = source.deepClone({ object: source });
|
|
73
|
+
const snapshot = await backReference.getObject();
|
|
74
|
+
ok(snapshot instanceof Create);
|
|
75
|
+
notStrictEqual(snapshot, source);
|
|
76
|
+
notStrictEqual(snapshot, backReference);
|
|
77
|
+
ok(await snapshot.getObject() instanceof Note);
|
|
78
|
+
await backReference.toJsonLd(options);
|
|
79
|
+
});
|
|
80
|
+
test("deepClone() copies non-entity vocabulary objects and standalone roots", () => {
|
|
81
|
+
const endpoint = new URL("https://example.com/inbox");
|
|
82
|
+
const endpoints = new Endpoints({ sharedInbox: endpoint });
|
|
83
|
+
const source = new Source({ content: "Markdown" });
|
|
84
|
+
const copy = new Person({
|
|
85
|
+
endpoints,
|
|
86
|
+
source
|
|
87
|
+
}).deepClone();
|
|
88
|
+
notStrictEqual(copy.endpoints, endpoints);
|
|
89
|
+
notStrictEqual(copy.source, source);
|
|
90
|
+
notStrictEqual(copy.endpoints.sharedInbox, endpoint);
|
|
91
|
+
copy.endpoints.sharedInbox.pathname = "/copied";
|
|
92
|
+
strictEqual(endpoint.pathname, "/inbox");
|
|
93
|
+
const link = new Link({ href: endpoint }).deepClone();
|
|
94
|
+
notStrictEqual(link.href, endpoint);
|
|
95
|
+
strictEqual(link.href.href, endpoint.href);
|
|
96
|
+
});
|
|
97
|
+
test("deepClone() copies byte arrays including Buffer storage", async () => {
|
|
98
|
+
for (const bytes of [new Uint8Array([
|
|
99
|
+
1,
|
|
100
|
+
2,
|
|
101
|
+
3
|
|
102
|
+
]), Buffer.from([
|
|
103
|
+
1,
|
|
104
|
+
2,
|
|
105
|
+
3
|
|
106
|
+
])]) {
|
|
107
|
+
const proof = new DataIntegrityProof({ proofValue: bytes });
|
|
108
|
+
const copiedProof = await new Note({ proof }).deepClone().getProof();
|
|
109
|
+
ok(copiedProof instanceof DataIntegrityProof);
|
|
110
|
+
notStrictEqual(copiedProof, proof);
|
|
111
|
+
notStrictEqual(copiedProof.proofValue, bytes);
|
|
112
|
+
copiedProof.proofValue[0] = 9;
|
|
113
|
+
strictEqual(bytes[0], 1);
|
|
114
|
+
bytes[1] = 8;
|
|
115
|
+
strictEqual(copiedProof.proofValue[1], 2);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
test("deepClone() shares immutable scalars and preserves sparse arrays", () => {
|
|
119
|
+
const content = new LanguageString("Hello", "en");
|
|
120
|
+
const published = Temporal.Instant.from("2026-10-27T00:00:00Z");
|
|
121
|
+
const names = new Array(3);
|
|
122
|
+
names[2] = "Kept";
|
|
123
|
+
const source = new Note({
|
|
124
|
+
names,
|
|
125
|
+
content,
|
|
126
|
+
published
|
|
127
|
+
});
|
|
128
|
+
const copy = source.deepClone();
|
|
129
|
+
strictEqual(copy.content, content);
|
|
130
|
+
strictEqual(copy.published, published);
|
|
131
|
+
deepStrictEqual(copy.names, source.names);
|
|
132
|
+
strictEqual(0 in copy.names, false);
|
|
133
|
+
copy.names.push("Copy only");
|
|
134
|
+
strictEqual(source.names.length, 3);
|
|
135
|
+
});
|
|
136
|
+
test("deepClone() retains node defaults and overrides only the root", async () => {
|
|
137
|
+
const fetched = [];
|
|
138
|
+
const [rootTracer, rootSpans] = createTestTracerProvider();
|
|
139
|
+
const [childTracer, childSpans] = createTestTracerProvider();
|
|
140
|
+
const child = new Note({ attribution: new URL("https://example.com/child-actor") }, {
|
|
141
|
+
...options,
|
|
142
|
+
documentLoader: personLoader("Child", fetched),
|
|
143
|
+
tracerProvider: childTracer
|
|
144
|
+
});
|
|
145
|
+
const source = new Create({
|
|
146
|
+
actor: new URL("https://example.com/root-actor"),
|
|
147
|
+
object: child
|
|
148
|
+
}, {
|
|
149
|
+
...options,
|
|
150
|
+
documentLoader: personLoader("Root", fetched),
|
|
151
|
+
tracerProvider: rootTracer
|
|
152
|
+
});
|
|
153
|
+
const copy = source.deepClone({}, { documentLoader: personLoader("Override") });
|
|
154
|
+
strictEqual((await copy.getActor())?.name, "Override");
|
|
155
|
+
const copiedChild = await copy.getObject();
|
|
156
|
+
ok(copiedChild instanceof Note);
|
|
157
|
+
strictEqual((await copiedChild.getAttribution())?.name, "Child");
|
|
158
|
+
strictEqual((await source.getActor())?.name, "Root");
|
|
159
|
+
deepStrictEqual(fetched, ["https://example.com/child-actor", "https://example.com/root-actor"]);
|
|
160
|
+
strictEqual(rootSpans.getSpans("activitypub.lookup_object").length, 2);
|
|
161
|
+
strictEqual(childSpans.getSpans("activitypub.lookup_object").length, 1);
|
|
162
|
+
});
|
|
163
|
+
test("deepClone() preserves origin checks and isolates hydrated trust", async () => {
|
|
164
|
+
let fetches = 0;
|
|
165
|
+
const original = await Create.fromJsonLd({
|
|
166
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
167
|
+
id: "https://a.example/create",
|
|
168
|
+
type: "Create",
|
|
169
|
+
object: {
|
|
170
|
+
id: "https://b.example/note",
|
|
171
|
+
type: "Note",
|
|
172
|
+
content: "Embedded"
|
|
173
|
+
}
|
|
174
|
+
}, {
|
|
175
|
+
...options,
|
|
176
|
+
documentLoader: async (url) => {
|
|
177
|
+
fetches++;
|
|
178
|
+
return {
|
|
179
|
+
contextUrl: null,
|
|
180
|
+
documentUrl: url,
|
|
181
|
+
document: {
|
|
182
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
183
|
+
id: url,
|
|
184
|
+
type: "Note",
|
|
185
|
+
content: "Fetched"
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
strictEqual((await original.deepClone().getObject())?.content, "Fetched");
|
|
191
|
+
strictEqual(fetches, 1);
|
|
192
|
+
strictEqual((await original.getObject({ crossOrigin: "trust" }))?.content, "Embedded");
|
|
193
|
+
strictEqual((await original.getObject())?.content, "Fetched");
|
|
194
|
+
strictEqual(fetches, 2);
|
|
195
|
+
});
|
|
196
|
+
test("deepClone() keeps base URLs and discards cached JSON-LD", async () => {
|
|
197
|
+
const source = await Note.fromJsonLd({
|
|
198
|
+
"@context": ["https://www.w3.org/ns/activitystreams", { extension: "https://example.com/extension" }],
|
|
199
|
+
type: "Note",
|
|
200
|
+
id: "./note",
|
|
201
|
+
attributedTo: "./alice",
|
|
202
|
+
extension: "received only"
|
|
203
|
+
}, {
|
|
204
|
+
...options,
|
|
205
|
+
baseUrl: new URL("https://example.com/posts/"),
|
|
206
|
+
documentLoader: personLoader("Alice")
|
|
207
|
+
});
|
|
208
|
+
const copy = source.deepClone({ content: "Copy" });
|
|
209
|
+
strictEqual(copy.id.href, "https://example.com/posts/note");
|
|
210
|
+
strictEqual((await copy.getAttribution())?.id?.href, "https://example.com/posts/alice");
|
|
211
|
+
const json = await copy.toJsonLd(options);
|
|
212
|
+
strictEqual(json.content, "Copy");
|
|
213
|
+
strictEqual(json.extension, void 0);
|
|
214
|
+
strictEqual((await source.toJsonLd()).extension, "received only");
|
|
215
|
+
});
|
|
216
|
+
test("deepClone() validates replacements through clone() only", () => {
|
|
217
|
+
const source = new Note({ content: "Source" });
|
|
218
|
+
for (const values of [
|
|
219
|
+
{ id: 42 },
|
|
220
|
+
{
|
|
221
|
+
name: "one",
|
|
222
|
+
names: ["two"]
|
|
223
|
+
},
|
|
224
|
+
{ names: [42] }
|
|
225
|
+
]) throws(() => source.deepClone(values), TypeError);
|
|
226
|
+
function values(counter) {
|
|
227
|
+
return Object.create({ get content() {
|
|
228
|
+
counter.reads++;
|
|
229
|
+
return "Inherited";
|
|
230
|
+
} });
|
|
231
|
+
}
|
|
232
|
+
const shallowReads = { reads: 0 };
|
|
233
|
+
const deepReads = { reads: 0 };
|
|
234
|
+
strictEqual(source.clone(values(shallowReads)).content, "Inherited");
|
|
235
|
+
strictEqual(source.deepClone(values(deepReads)).content, "Inherited");
|
|
236
|
+
strictEqual(deepReads.reads, shallowReads.reads);
|
|
237
|
+
});
|
|
238
|
+
test("deepClone() preserves user subclasses and handles deep graphs", async () => {
|
|
239
|
+
class CustomNote extends Note {}
|
|
240
|
+
const child = new CustomNote({ content: "Child" });
|
|
241
|
+
const copiedChild = await new Create({ object: child }).deepClone().getObject();
|
|
242
|
+
ok(copiedChild instanceof CustomNote);
|
|
243
|
+
notStrictEqual(copiedChild, child);
|
|
244
|
+
let source = new Note({ content: "End" });
|
|
245
|
+
for (let i = 0; i < 3e3; i++) source = new Note({ replyTarget: source });
|
|
246
|
+
let copy = source.deepClone();
|
|
247
|
+
for (let i = 0; i < 3e3; i++) {
|
|
248
|
+
const next = await copy.getReplyTarget();
|
|
249
|
+
ok(next instanceof Note);
|
|
250
|
+
copy = next;
|
|
251
|
+
}
|
|
252
|
+
strictEqual(copy.content, "End");
|
|
253
|
+
});
|
|
254
|
+
test("deepClone() rejects broken subclass clone results", () => {
|
|
255
|
+
class ReturnsSelf extends Note {
|
|
256
|
+
clone() {
|
|
257
|
+
return this;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const source = new ReturnsSelf({ id: new URL("https://example.com/note") });
|
|
261
|
+
const id = source.id;
|
|
262
|
+
throws(() => source.deepClone(), /fresh, compatible/);
|
|
263
|
+
strictEqual(source.id, id);
|
|
264
|
+
class Incompatible extends Note {
|
|
265
|
+
clone() {
|
|
266
|
+
return new Object$1({});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
throws(() => new Incompatible({}).deepClone(), /fresh, compatible/);
|
|
270
|
+
class ReusesCopy extends Note {
|
|
271
|
+
static copy;
|
|
272
|
+
clone() {
|
|
273
|
+
return ReusesCopy.copy ??= super.clone();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const first = new ReusesCopy({ content: "First" });
|
|
277
|
+
const second = new ReusesCopy({ content: "Second" });
|
|
278
|
+
throws(() => new Create({ objects: [first, second] }).deepClone(), /fresh, compatible/);
|
|
279
|
+
strictEqual(first.content, "First");
|
|
280
|
+
strictEqual(second.content, "Second");
|
|
281
|
+
class Throws extends Note {
|
|
282
|
+
clone() {
|
|
283
|
+
throw new Error("Copy failed");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const child = new Throws({ content: "Unchanged" });
|
|
287
|
+
const parent = new Create({ object: child });
|
|
288
|
+
throws(() => parent.deepClone(), /Copy failed/);
|
|
289
|
+
strictEqual(child.content, "Unchanged");
|
|
290
|
+
});
|
|
291
|
+
//#endregion
|
|
292
|
+
export {};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { t as esm_default } from "./esm-BIqRhjGA.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { r as traverseCollection, t as lookupObject } from "./lookup-
|
|
4
|
+
import { A as Note, C as Image, I as Person, N as OrderedCollection, c as CollectionPage, s as Collection, u as Create } from "./vocab-CCAqTuHd.mjs";
|
|
5
|
+
import { r as traverseCollection, t as lookupObject } from "./lookup-B9VbSKaj.mjs";
|
|
6
6
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
7
7
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
8
8
|
import { deepStrictEqual, ok, rejects } from "node:assert/strict";
|
|
9
|
-
import { FetchError, getDocumentLoader, parseIri, withGatewayHints } from "@fedify/vocab-runtime";
|
|
9
|
+
import { FetchError, formatIri, getDocumentLoader, parseIri, withGatewayHints } from "@fedify/vocab-runtime";
|
|
10
10
|
//#region src/gateway.test.ts
|
|
11
11
|
const did = "did:key:z6Mkabc";
|
|
12
12
|
const objectId = `ap+ef61://${did}/objects/1`;
|
|
@@ -724,6 +724,73 @@ test("getFirst() passes the referrer chain and collection context", async () =>
|
|
|
724
724
|
deepStrictEqual(referrer?.referrer?.referrer?.acceptance, "verified");
|
|
725
725
|
ok(referrer?.referrer?.referrer?.referrer?.object === create);
|
|
726
726
|
});
|
|
727
|
+
test("deepClone() preserves historical ancestry independently of replacements", async () => {
|
|
728
|
+
const context = Object.freeze({});
|
|
729
|
+
const documentLoader = createLoader({
|
|
730
|
+
[gatewayUrl("https://gw.example", "/actor/outbox")]: portableCollection("/actor/outbox", {
|
|
731
|
+
attributedTo: `ap://${did}/actor`,
|
|
732
|
+
first: {
|
|
733
|
+
id: `ap://${did}/actor/outbox?page=1`,
|
|
734
|
+
type: "OrderedCollectionPage",
|
|
735
|
+
partOf: `ap://${did}/other/outbox`,
|
|
736
|
+
next: `ap://${did}/actor/outbox?page=2`
|
|
737
|
+
}
|
|
738
|
+
}),
|
|
739
|
+
[gatewayUrl("https://gw.example", "/actor/outbox?page=2")]: {
|
|
740
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
741
|
+
id: `ap://${did}/actor/outbox?page=2`,
|
|
742
|
+
type: "OrderedCollectionPage"
|
|
743
|
+
},
|
|
744
|
+
[gatewayUrl("https://gw.example", "/actor")]: {
|
|
745
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
746
|
+
id: `ap://${did}/actor`,
|
|
747
|
+
type: "Person",
|
|
748
|
+
name: "Fetched actor"
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
const verifier = createRecordingVerifier(() => ({
|
|
752
|
+
verified: true,
|
|
753
|
+
collectionContext: context
|
|
754
|
+
}));
|
|
755
|
+
const options = {
|
|
756
|
+
documentLoader,
|
|
757
|
+
contextLoader: mockDocumentLoader,
|
|
758
|
+
gateways: ["https://gw.example"],
|
|
759
|
+
verifyPortableObject: verifier
|
|
760
|
+
};
|
|
761
|
+
const actor = await Person.fromJsonLd({
|
|
762
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
763
|
+
id: `ap://${did}/actor`,
|
|
764
|
+
type: "Person",
|
|
765
|
+
outbox: `ap://${did}/actor/outbox`
|
|
766
|
+
}, { contextLoader: mockDocumentLoader });
|
|
767
|
+
const outbox = await actor.getOutbox(options);
|
|
768
|
+
assertInstanceOf(outbox, OrderedCollection);
|
|
769
|
+
const first = await outbox.getFirst(options);
|
|
770
|
+
assertInstanceOf(first, CollectionPage);
|
|
771
|
+
const copy = outbox.deepClone({
|
|
772
|
+
id: parseIri(`ap://${did}/other/outbox`),
|
|
773
|
+
attribution: parseIri(`ap://${did}/different-actor`)
|
|
774
|
+
});
|
|
775
|
+
const copiedFirst = await copy.getFirst(options);
|
|
776
|
+
assertInstanceOf(copiedFirst, CollectionPage);
|
|
777
|
+
ok(copiedFirst !== first);
|
|
778
|
+
await copiedFirst.getNext(options);
|
|
779
|
+
const referrer = verifier.calls.at(-1).options.referrer;
|
|
780
|
+
ok(referrer?.object === copiedFirst);
|
|
781
|
+
const history = referrer.referrer;
|
|
782
|
+
ok(history?.object instanceof OrderedCollection);
|
|
783
|
+
ok(history.object !== copy && history.object !== outbox);
|
|
784
|
+
deepStrictEqual(history.id, outbox.id);
|
|
785
|
+
deepStrictEqual(history.acceptance, void 0);
|
|
786
|
+
deepStrictEqual(history.collectionContext, void 0);
|
|
787
|
+
deepStrictEqual(history.object.attributionId, outbox.attributionId);
|
|
788
|
+
deepStrictEqual(copiedFirst.partOfId, first.partOfId);
|
|
789
|
+
ok(copiedFirst.partOfId.href !== history.id.href);
|
|
790
|
+
ok(history.referrer?.object === actor);
|
|
791
|
+
await history.object.getAttribution(options);
|
|
792
|
+
deepStrictEqual((await outbox.toJsonLd()).attributedTo, formatIri(outbox.attributionId));
|
|
793
|
+
});
|
|
727
794
|
test("accessors do not trust objects embedded in unsecured collections", async () => {
|
|
728
795
|
const itemPath = "/objects/1";
|
|
729
796
|
const options = {
|
|
@@ -763,7 +830,7 @@ test("accessors do not trust objects embedded in unsecured collections", async (
|
|
|
763
830
|
}))).length, 1);
|
|
764
831
|
const outbox3 = await (await createPerson()).getOutbox(options);
|
|
765
832
|
assertInstanceOf(outbox3, Collection);
|
|
766
|
-
deepStrictEqual(await Array.fromAsync(
|
|
833
|
+
for (const copy of [outbox3.clone(), outbox3.deepClone()]) deepStrictEqual(await Array.fromAsync(copy.getItems({
|
|
767
834
|
...options,
|
|
768
835
|
documentLoader: createLoader({}),
|
|
769
836
|
suppressError: true
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
|
-
import {
|
|
4
|
-
import "./src-
|
|
3
|
+
import { A as Note, B as Question, C as Image, D as Link, F as Organization, I as Person, W as Service, Y as Video, a as Application, s as Collection, u as Create, x as Group } from "./vocab-CCAqTuHd.mjs";
|
|
4
|
+
import "./src-sHf6TARh.mjs";
|
|
5
5
|
import { test } from "@fedify/fixture";
|
|
6
6
|
import { deepStrictEqual, ok } from "node:assert/strict";
|
|
7
7
|
import { getDocumentLoader, preloadedContexts } from "@fedify/vocab-runtime";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
|
-
import { i as isActor, o as name, s as version } from "./actor-
|
|
3
|
+
import { i as isActor, o as name, s as version } from "./actor-HAORUnb8.mjs";
|
|
4
4
|
import { t as getTypeId } from "./type-BMdjm4Eg.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { j as Object$1 } from "./vocab-CCAqTuHd.mjs";
|
|
6
6
|
import { canonicalizePortableUri, formatIri, getDocumentLoader, haveSameFe34Origin, haveSameIriOrigin, parseIri } from "@fedify/vocab-runtime";
|
|
7
7
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
8
8
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { t as esm_default } from "./esm-BIqRhjGA.mjs";
|
|
4
|
-
import { A as
|
|
5
|
-
import { n as lookupObserver, r as traverseCollection, t as lookupObject } from "./lookup-
|
|
4
|
+
import { A as Note, I as Person, j as Object$1, s as Collection } from "./vocab-CCAqTuHd.mjs";
|
|
5
|
+
import { n as lookupObserver, r as traverseCollection, t as lookupObject } from "./lookup-B9VbSKaj.mjs";
|
|
6
6
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
7
7
|
import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
8
8
|
import { deepStrictEqual, equal, ok, rejects } from "node:assert/strict";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { t as esm_default } from "./esm-BIqRhjGA.mjs";
|
|
4
|
-
import { n as getActorHandle } from "./actor-
|
|
5
|
-
import {
|
|
6
|
-
import { t as lookupObject } from "./lookup-
|
|
4
|
+
import { n as getActorHandle } from "./actor-HAORUnb8.mjs";
|
|
5
|
+
import { I as Person } from "./vocab-CCAqTuHd.mjs";
|
|
6
|
+
import { t as lookupObject } from "./lookup-B9VbSKaj.mjs";
|
|
7
7
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
8
8
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
9
9
|
import { deepStrictEqual, equal, rejects } from "node:assert/strict";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
|
-
import {
|
|
3
|
+
import { A as Note, B as Question, N as OrderedCollection, Q as vocab_exports, i as Announce, u as Create } from "./vocab-CCAqTuHd.mjs";
|
|
4
4
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
5
5
|
import { deepStrictEqual, ok } from "node:assert/strict";
|
|
6
6
|
import { isMarkerSafeContext, retainSignedRepresentation } from "@fedify/vocab-runtime/internal/signed-representation";
|
|
@@ -135,6 +135,20 @@ test("a clone does not inherit a retained signed representation", async () => {
|
|
|
135
135
|
deepStrictEqual(embedded["@context"], void 0);
|
|
136
136
|
deepStrictEqual(embedded.content, "Changed");
|
|
137
137
|
});
|
|
138
|
+
test("deepClone() drops retained signed representations at every level", async () => {
|
|
139
|
+
const note = retainedNote();
|
|
140
|
+
const original = new Create({ object: note });
|
|
141
|
+
retainSignedRepresentation(original, {
|
|
142
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
143
|
+
type: "Create",
|
|
144
|
+
content: "Retained root only"
|
|
145
|
+
});
|
|
146
|
+
const json = await new Create({ object: original.deepClone() }).toJsonLd(options);
|
|
147
|
+
deepStrictEqual(json.object.content, void 0);
|
|
148
|
+
deepStrictEqual(json.object.object.content, "Hello");
|
|
149
|
+
deepStrictEqual(json.object.object.proof, void 0);
|
|
150
|
+
deepStrictEqual((await new Create({ object: note }).toJsonLd(options)).object, securedNote);
|
|
151
|
+
});
|
|
138
152
|
test("every generated default context keeps placeholders recoverable", async () => {
|
|
139
153
|
const classes = Object.values(vocab_exports).filter((value) => typeof value === "function" && value.typeId instanceof URL);
|
|
140
154
|
ok(classes.length > 0);
|