@peerbit/document 15.0.14 → 15.0.16
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/README.md +25 -0
- package/dist/src/callback-detachment.d.ts +5 -0
- package/dist/src/callback-detachment.d.ts.map +1 -1
- package/dist/src/callback-detachment.js +377 -6
- package/dist/src/callback-detachment.js.map +1 -1
- package/dist/src/domain.d.ts.map +1 -1
- package/dist/src/domain.js +2 -2
- package/dist/src/domain.js.map +1 -1
- package/dist/src/program.d.ts +7 -0
- package/dist/src/program.d.ts.map +1 -1
- package/dist/src/program.js +312 -145
- package/dist/src/program.js.map +1 -1
- package/dist/src/search.d.ts +2 -0
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +36 -6
- package/dist/src/search.js.map +1 -1
- package/dist/src/transform.d.ts +2 -0
- package/dist/src/transform.d.ts.map +1 -1
- package/dist/src/transform.js +4 -0
- package/dist/src/transform.js.map +1 -1
- package/package.json +15 -15
- package/src/callback-detachment.ts +546 -6
- package/src/domain.ts +2 -3
- package/src/program.ts +682 -358
- package/src/search.ts +49 -5
- package/src/transform.ts +7 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PublicSignKey, SignatureWithKey } from "@peerbit/crypto";
|
|
1
2
|
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
2
3
|
import { Entry } from "@peerbit/log";
|
|
3
4
|
import {
|
|
@@ -8,6 +9,402 @@ import {
|
|
|
8
9
|
PutWithKeyOperation,
|
|
9
10
|
} from "./operation.js";
|
|
10
11
|
|
|
12
|
+
type LazyPropertyFactories = Map<PropertyKey, () => unknown>;
|
|
13
|
+
|
|
14
|
+
const isPromiseLike = (value: unknown): value is PromiseLike<unknown> =>
|
|
15
|
+
!!value &&
|
|
16
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
17
|
+
typeof (value as { then?: unknown }).then === "function";
|
|
18
|
+
|
|
19
|
+
const mapMaybePromise = (
|
|
20
|
+
value: unknown,
|
|
21
|
+
map: (value: any) => unknown,
|
|
22
|
+
): unknown => (isPromiseLike(value) ? value.then(map) : map(value));
|
|
23
|
+
|
|
24
|
+
const copyOptionalBytes = (
|
|
25
|
+
bytes: Uint8Array | undefined,
|
|
26
|
+
): Uint8Array | undefined =>
|
|
27
|
+
bytes == null ? undefined : new Uint8Array(bytes);
|
|
28
|
+
|
|
29
|
+
const preserveArrayIntegrity = <T>(source: readonly T[], copy: T[]): T[] => {
|
|
30
|
+
if (Object.isFrozen(source)) {
|
|
31
|
+
Object.freeze(copy);
|
|
32
|
+
} else if (Object.isSealed(source)) {
|
|
33
|
+
Object.seal(copy);
|
|
34
|
+
} else if (!Object.isExtensible(source)) {
|
|
35
|
+
Object.preventExtensions(copy);
|
|
36
|
+
}
|
|
37
|
+
return copy;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const detachArray = <T>(
|
|
41
|
+
values: readonly T[],
|
|
42
|
+
detach: (value: T) => T = (value) => value,
|
|
43
|
+
): T[] => preserveArrayIntegrity(values, values.map(detach));
|
|
44
|
+
|
|
45
|
+
const getInheritedPropertyDescriptor = (
|
|
46
|
+
value: object,
|
|
47
|
+
key: PropertyKey,
|
|
48
|
+
): PropertyDescriptor | undefined => {
|
|
49
|
+
let prototype = Object.getPrototypeOf(value) as object | null;
|
|
50
|
+
while (prototype) {
|
|
51
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(prototype, key);
|
|
52
|
+
if (descriptor) {
|
|
53
|
+
return descriptor;
|
|
54
|
+
}
|
|
55
|
+
prototype = Object.getPrototypeOf(prototype) as object | null;
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Clone an object without resolving selected nested values. For normal
|
|
62
|
+
* objects the selected fields become callback-local lazy accessors. The clone
|
|
63
|
+
* receives the source's frozen/sealed/non-extensible state only after those
|
|
64
|
+
* accessors are installed, so a no-touch callback never resolves lazy source
|
|
65
|
+
* fields.
|
|
66
|
+
*/
|
|
67
|
+
const cloneWithLazyProperties = <T extends object>(
|
|
68
|
+
value: T,
|
|
69
|
+
factories: LazyPropertyFactories,
|
|
70
|
+
): T => {
|
|
71
|
+
const descriptors = Object.getOwnPropertyDescriptors(value) as Record<
|
|
72
|
+
PropertyKey,
|
|
73
|
+
PropertyDescriptor
|
|
74
|
+
>;
|
|
75
|
+
const extensible = Object.isExtensible(value);
|
|
76
|
+
for (const [key, factory] of factories) {
|
|
77
|
+
const ownDescriptor = descriptors[key];
|
|
78
|
+
const descriptor =
|
|
79
|
+
ownDescriptor ?? getInheritedPropertyDescriptor(value, key);
|
|
80
|
+
let resolved = false;
|
|
81
|
+
let detachedValue: unknown;
|
|
82
|
+
const writable = descriptor
|
|
83
|
+
? (ownDescriptor != null || extensible) &&
|
|
84
|
+
("value" in descriptor
|
|
85
|
+
? descriptor.writable !== false
|
|
86
|
+
: descriptor.set != null)
|
|
87
|
+
: extensible;
|
|
88
|
+
descriptors[key] = {
|
|
89
|
+
configurable: descriptor?.configurable ?? true,
|
|
90
|
+
enumerable: descriptor?.enumerable ?? true,
|
|
91
|
+
get() {
|
|
92
|
+
if (!resolved) {
|
|
93
|
+
detachedValue = factory();
|
|
94
|
+
resolved = true;
|
|
95
|
+
}
|
|
96
|
+
return detachedValue;
|
|
97
|
+
},
|
|
98
|
+
...(writable
|
|
99
|
+
? {
|
|
100
|
+
set(nextValue: unknown) {
|
|
101
|
+
detachedValue = nextValue;
|
|
102
|
+
resolved = true;
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
: {}),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const clone = Object.create(Object.getPrototypeOf(value), descriptors) as T;
|
|
109
|
+
if (Object.isFrozen(value)) {
|
|
110
|
+
Object.freeze(clone);
|
|
111
|
+
} else if (Object.isSealed(value)) {
|
|
112
|
+
Object.seal(clone);
|
|
113
|
+
} else if (!Object.isExtensible(value)) {
|
|
114
|
+
Object.preventExtensions(clone);
|
|
115
|
+
}
|
|
116
|
+
return clone;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const addOwnByteFactories = (
|
|
120
|
+
value: object,
|
|
121
|
+
factories: LazyPropertyFactories,
|
|
122
|
+
): void => {
|
|
123
|
+
const descriptors = Object.getOwnPropertyDescriptors(value) as Record<
|
|
124
|
+
PropertyKey,
|
|
125
|
+
PropertyDescriptor
|
|
126
|
+
>;
|
|
127
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
128
|
+
const descriptor = descriptors[key];
|
|
129
|
+
if (descriptor && "value" in descriptor) {
|
|
130
|
+
const bytes = descriptor.value;
|
|
131
|
+
if (bytes instanceof Uint8Array) {
|
|
132
|
+
factories.set(key, () => new Uint8Array(bytes));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const addOwnArrayFactories = (
|
|
139
|
+
value: object,
|
|
140
|
+
factories: LazyPropertyFactories,
|
|
141
|
+
): void => {
|
|
142
|
+
const descriptors = Object.getOwnPropertyDescriptors(value) as Record<
|
|
143
|
+
PropertyKey,
|
|
144
|
+
PropertyDescriptor
|
|
145
|
+
>;
|
|
146
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
147
|
+
const descriptor = descriptors[key];
|
|
148
|
+
if (
|
|
149
|
+
descriptor &&
|
|
150
|
+
"value" in descriptor &&
|
|
151
|
+
Array.isArray(descriptor.value)
|
|
152
|
+
) {
|
|
153
|
+
const array = descriptor.value as unknown[];
|
|
154
|
+
factories.set(key, () =>
|
|
155
|
+
detachArray(array, (item) =>
|
|
156
|
+
item instanceof Uint8Array ? new Uint8Array(item) : item,
|
|
157
|
+
),
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const detachedCallbackEntryLikes = new WeakSet<object>();
|
|
164
|
+
|
|
165
|
+
const createEntryDetachmentContext = () => {
|
|
166
|
+
let metadata: WeakMap<object, object> | undefined;
|
|
167
|
+
let clocks: WeakMap<object, object> | undefined;
|
|
168
|
+
let timestamps: WeakMap<object, object> | undefined;
|
|
169
|
+
let signatures: WeakMap<object, object> | undefined;
|
|
170
|
+
let publicKeys: WeakMap<object, object> | undefined;
|
|
171
|
+
let entryLikes: WeakMap<object, object> | undefined;
|
|
172
|
+
let arrays: WeakMap<object, unknown[]> | undefined;
|
|
173
|
+
|
|
174
|
+
const detachValues = <T>(
|
|
175
|
+
values: readonly T[],
|
|
176
|
+
detach: (value: T) => T = (value) => value,
|
|
177
|
+
): T[] => {
|
|
178
|
+
const cached = arrays?.get(values);
|
|
179
|
+
if (cached) {
|
|
180
|
+
return cached as T[];
|
|
181
|
+
}
|
|
182
|
+
const clone = detachArray(values, detach);
|
|
183
|
+
(arrays ??= new WeakMap()).set(values, clone);
|
|
184
|
+
return clone;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const detachTimestamp = <T>(value: T): T => {
|
|
188
|
+
if (!value || typeof value !== "object") {
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
const cached = timestamps?.get(value);
|
|
192
|
+
if (cached) {
|
|
193
|
+
return cached as T;
|
|
194
|
+
}
|
|
195
|
+
const factories: LazyPropertyFactories = new Map();
|
|
196
|
+
addOwnByteFactories(value, factories);
|
|
197
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
198
|
+
(timestamps ??= new WeakMap()).set(value, clone);
|
|
199
|
+
return clone;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const detachClock = <T>(value: T): T => {
|
|
203
|
+
if (!value || typeof value !== "object") {
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
const cached = clocks?.get(value);
|
|
207
|
+
if (cached) {
|
|
208
|
+
return cached as T;
|
|
209
|
+
}
|
|
210
|
+
const factories: LazyPropertyFactories = new Map();
|
|
211
|
+
addOwnByteFactories(value, factories);
|
|
212
|
+
if (Reflect.has(value, "id") && !factories.has("id")) {
|
|
213
|
+
factories.set("id", () =>
|
|
214
|
+
copyOptionalBytes(
|
|
215
|
+
Reflect.get(value, "id", value) as Uint8Array | undefined,
|
|
216
|
+
),
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
if (Reflect.has(value, "timestamp")) {
|
|
220
|
+
factories.set("timestamp", () =>
|
|
221
|
+
detachTimestamp(Reflect.get(value, "timestamp", value)),
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
225
|
+
(clocks ??= new WeakMap()).set(value, clone);
|
|
226
|
+
return clone;
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const detachMeta = <T>(value: T): T => {
|
|
230
|
+
if (!value || typeof value !== "object") {
|
|
231
|
+
return value;
|
|
232
|
+
}
|
|
233
|
+
const cached = metadata?.get(value);
|
|
234
|
+
if (cached) {
|
|
235
|
+
return cached as T;
|
|
236
|
+
}
|
|
237
|
+
const factories: LazyPropertyFactories = new Map();
|
|
238
|
+
addOwnByteFactories(value, factories);
|
|
239
|
+
if (Reflect.has(value, "data") && !factories.has("data")) {
|
|
240
|
+
factories.set("data", () =>
|
|
241
|
+
copyOptionalBytes(
|
|
242
|
+
Reflect.get(value, "data", value) as Uint8Array | undefined,
|
|
243
|
+
),
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (Reflect.has(value, "clock")) {
|
|
247
|
+
factories.set("clock", () =>
|
|
248
|
+
detachClock(Reflect.get(value, "clock", value)),
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
if (Reflect.has(value, "next")) {
|
|
252
|
+
factories.set("next", () => {
|
|
253
|
+
const next = Reflect.get(value, "next", value);
|
|
254
|
+
return Array.isArray(next) ? detachValues(next) : next;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
258
|
+
(metadata ??= new WeakMap()).set(value, clone);
|
|
259
|
+
return clone;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const detachPublicKey = <T>(value: T): T => {
|
|
263
|
+
if (!value || typeof value !== "object") {
|
|
264
|
+
return value;
|
|
265
|
+
}
|
|
266
|
+
const cached = publicKeys?.get(value);
|
|
267
|
+
if (cached) {
|
|
268
|
+
return cached as T;
|
|
269
|
+
}
|
|
270
|
+
const factories: LazyPropertyFactories = new Map();
|
|
271
|
+
addOwnByteFactories(value, factories);
|
|
272
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
273
|
+
(publicKeys ??= new WeakMap()).set(value, clone);
|
|
274
|
+
return clone;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const detachSignature = <T>(value: T): T => {
|
|
278
|
+
if (!value || typeof value !== "object") {
|
|
279
|
+
return value;
|
|
280
|
+
}
|
|
281
|
+
const cached = signatures?.get(value);
|
|
282
|
+
if (cached) {
|
|
283
|
+
return cached as T;
|
|
284
|
+
}
|
|
285
|
+
const factories: LazyPropertyFactories = new Map();
|
|
286
|
+
addOwnByteFactories(value, factories);
|
|
287
|
+
if (Reflect.has(value, "publicKey")) {
|
|
288
|
+
factories.set("publicKey", () =>
|
|
289
|
+
detachPublicKey(Reflect.get(value, "publicKey", value)),
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
293
|
+
(signatures ??= new WeakMap()).set(value, clone);
|
|
294
|
+
return clone;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const detachSignatures = (
|
|
298
|
+
values: readonly SignatureWithKey[],
|
|
299
|
+
): SignatureWithKey[] => detachValues(values, detachSignature);
|
|
300
|
+
|
|
301
|
+
const detachPublicKeys = (
|
|
302
|
+
values: readonly PublicSignKey[],
|
|
303
|
+
): PublicSignKey[] => detachValues(values, detachPublicKey);
|
|
304
|
+
|
|
305
|
+
const detachEntryLike = <T extends object>(value: T): T => {
|
|
306
|
+
if (detachedCallbackEntryLikes.has(value)) {
|
|
307
|
+
return value;
|
|
308
|
+
}
|
|
309
|
+
const cached = entryLikes?.get(value);
|
|
310
|
+
if (cached) {
|
|
311
|
+
return cached as T;
|
|
312
|
+
}
|
|
313
|
+
const factories: LazyPropertyFactories = new Map();
|
|
314
|
+
addOwnByteFactories(value, factories);
|
|
315
|
+
addOwnArrayFactories(value, factories);
|
|
316
|
+
if (Reflect.has(value, "meta")) {
|
|
317
|
+
factories.set("meta", () =>
|
|
318
|
+
detachMeta(Reflect.get(value, "meta", value)),
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
for (const methodName of ["getMetaBytes", "getHashDigestBytes"] as const) {
|
|
322
|
+
const method = Reflect.get(value, methodName, value);
|
|
323
|
+
if (typeof method === "function") {
|
|
324
|
+
factories.set(
|
|
325
|
+
methodName,
|
|
326
|
+
() =>
|
|
327
|
+
(...args: unknown[]) =>
|
|
328
|
+
mapMaybePromise(
|
|
329
|
+
Reflect.apply(method, value, args),
|
|
330
|
+
copyOptionalBytes,
|
|
331
|
+
),
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const clone = cloneWithLazyProperties(value, factories);
|
|
336
|
+
(entryLikes ??= new WeakMap()).set(value, clone);
|
|
337
|
+
detachedCallbackEntryLikes.add(clone);
|
|
338
|
+
return clone;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
return {
|
|
342
|
+
detachArray: detachValues,
|
|
343
|
+
detachClock,
|
|
344
|
+
detachEntryLike,
|
|
345
|
+
detachMeta,
|
|
346
|
+
detachPublicKeys,
|
|
347
|
+
detachSignatures,
|
|
348
|
+
};
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
type EntryDetachmentContext = ReturnType<typeof createEntryDetachmentContext>;
|
|
352
|
+
type EntryDetachmentContextProvider = () => EntryDetachmentContext;
|
|
353
|
+
|
|
354
|
+
const detachPreparedAppendJoinFactsForCallback = (
|
|
355
|
+
facts: object,
|
|
356
|
+
canonicalEntry: Entry<any>,
|
|
357
|
+
callbackEntry: Entry<any>,
|
|
358
|
+
getContext: EntryDetachmentContextProvider,
|
|
359
|
+
): object => {
|
|
360
|
+
const factories: LazyPropertyFactories = new Map();
|
|
361
|
+
addOwnByteFactories(facts, factories);
|
|
362
|
+
if (Reflect.has(facts, "bytes")) {
|
|
363
|
+
factories.set("bytes", () =>
|
|
364
|
+
copyOptionalBytes(
|
|
365
|
+
Reflect.get(facts, "bytes", facts) as Uint8Array | undefined,
|
|
366
|
+
),
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
if (Reflect.has(facts, "meta")) {
|
|
370
|
+
factories.set("meta", () =>
|
|
371
|
+
getContext().detachMeta(Reflect.get(facts, "meta", facts)),
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
const getShallowEntry = Reflect.get(facts, "getShallowEntry", facts);
|
|
375
|
+
if (typeof getShallowEntry === "function") {
|
|
376
|
+
factories.set("getShallowEntry", () => (...args: unknown[]) => {
|
|
377
|
+
const shallow = Reflect.apply(getShallowEntry, facts, args) as unknown;
|
|
378
|
+
return shallow && typeof shallow === "object"
|
|
379
|
+
? getContext().detachEntryLike(shallow)
|
|
380
|
+
: shallow;
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
const materializeEntry = Reflect.get(facts, "materializeEntry", facts);
|
|
384
|
+
if (typeof materializeEntry === "function") {
|
|
385
|
+
factories.set(
|
|
386
|
+
"materializeEntry",
|
|
387
|
+
() =>
|
|
388
|
+
(...args: unknown[]) =>
|
|
389
|
+
mapMaybePromise(
|
|
390
|
+
Reflect.apply(materializeEntry, facts, args),
|
|
391
|
+
(materialized) =>
|
|
392
|
+
materialized === canonicalEntry
|
|
393
|
+
? callbackEntry
|
|
394
|
+
: materialized instanceof Entry
|
|
395
|
+
? detachEntryPayloadForCallbackWithContext(
|
|
396
|
+
materialized,
|
|
397
|
+
getContext,
|
|
398
|
+
)
|
|
399
|
+
: materialized && typeof materialized === "object"
|
|
400
|
+
? getContext().detachEntryLike(materialized)
|
|
401
|
+
: materialized,
|
|
402
|
+
),
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
return cloneWithLazyProperties(facts, factories);
|
|
406
|
+
};
|
|
407
|
+
|
|
11
408
|
/**
|
|
12
409
|
* Borsh byte fields are input-buffer views. Clone only fields that can expose
|
|
13
410
|
* verified operation bytes while retaining the operation's exact prototype,
|
|
@@ -176,13 +573,16 @@ export const detachCanPerformCallbackProperties = <
|
|
|
176
573
|
};
|
|
177
574
|
|
|
178
575
|
/**
|
|
179
|
-
* Return an Entry view whose public
|
|
180
|
-
*
|
|
181
|
-
* callbacks
|
|
576
|
+
* Return an Entry view whose public accessors cannot expose verified payload,
|
|
577
|
+
* metadata, signature, public-key, or hash-digest buffers to application
|
|
578
|
+
* callbacks. Nested copies remain lazy, including metadata byte fields.
|
|
182
579
|
*/
|
|
183
580
|
const detachedCallbackEntries = new WeakSet<object>();
|
|
184
581
|
|
|
185
|
-
|
|
582
|
+
const detachEntryPayloadForCallbackWithContext = <T>(
|
|
583
|
+
entry: Entry<T>,
|
|
584
|
+
getContext: EntryDetachmentContextProvider,
|
|
585
|
+
): Entry<T> => {
|
|
186
586
|
if (detachedCallbackEntries.has(entry)) {
|
|
187
587
|
return entry;
|
|
188
588
|
}
|
|
@@ -252,6 +652,23 @@ export const detachEntryPayloadForCallback = <T>(entry: Entry<T>): Entry<T> => {
|
|
|
252
652
|
if (property === "payload") {
|
|
253
653
|
return copyPayload(entry.payload);
|
|
254
654
|
}
|
|
655
|
+
if (property === "meta") {
|
|
656
|
+
return getContext().detachMeta(Reflect.get(target, property, target));
|
|
657
|
+
}
|
|
658
|
+
if (property === "next") {
|
|
659
|
+
const next = Reflect.get(target, property, target);
|
|
660
|
+
return Array.isArray(next) ? getContext().detachArray(next) : next;
|
|
661
|
+
}
|
|
662
|
+
if (property === "signatures") {
|
|
663
|
+
return getContext().detachSignatures(
|
|
664
|
+
Reflect.get(target, property, target),
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
if (property === "publicKeys") {
|
|
668
|
+
return getContext().detachPublicKeys(
|
|
669
|
+
Reflect.get(target, property, target),
|
|
670
|
+
);
|
|
671
|
+
}
|
|
255
672
|
if (
|
|
256
673
|
property === "getPayload" &&
|
|
257
674
|
typeof (entry as Entry<T> & { getPayload?: unknown }).getPayload ===
|
|
@@ -262,9 +679,83 @@ export const detachEntryPayloadForCallback = <T>(entry: Entry<T>): Entry<T> => {
|
|
|
262
679
|
if (property === "getPayloadValue") {
|
|
263
680
|
return getPayloadValue;
|
|
264
681
|
}
|
|
682
|
+
if (property === "getMeta") {
|
|
683
|
+
const getMeta = Reflect.get(target, property, target);
|
|
684
|
+
if (typeof getMeta === "function") {
|
|
685
|
+
return (...args: unknown[]) =>
|
|
686
|
+
mapMaybePromise(
|
|
687
|
+
Reflect.apply(getMeta, target, args),
|
|
688
|
+
getContext().detachMeta,
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
if (property === "getClock") {
|
|
693
|
+
const getClock = Reflect.get(target, property, target);
|
|
694
|
+
if (typeof getClock === "function") {
|
|
695
|
+
return (...args: unknown[]) =>
|
|
696
|
+
mapMaybePromise(
|
|
697
|
+
Reflect.apply(getClock, target, args),
|
|
698
|
+
getContext().detachClock,
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
if (property === "getNext") {
|
|
703
|
+
const getNext = Reflect.get(target, property, target);
|
|
704
|
+
if (typeof getNext === "function") {
|
|
705
|
+
return (...args: unknown[]) =>
|
|
706
|
+
mapMaybePromise(Reflect.apply(getNext, target, args), (next) =>
|
|
707
|
+
Array.isArray(next) ? getContext().detachArray(next) : next,
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
if (property === "getSignatures") {
|
|
712
|
+
const getSignatures = Reflect.get(target, property, target);
|
|
713
|
+
if (typeof getSignatures === "function") {
|
|
714
|
+
return (...args: unknown[]) =>
|
|
715
|
+
mapMaybePromise(
|
|
716
|
+
Reflect.apply(getSignatures, target, args),
|
|
717
|
+
getContext().detachSignatures,
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (property === "getPublicKeys") {
|
|
722
|
+
const getPublicKeys = Reflect.get(target, property, target);
|
|
723
|
+
if (typeof getPublicKeys === "function") {
|
|
724
|
+
return (...args: unknown[]) =>
|
|
725
|
+
mapMaybePromise(
|
|
726
|
+
Reflect.apply(getPublicKeys, target, args),
|
|
727
|
+
getContext().detachPublicKeys,
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (property === "getMetaBytes" || property === "getHashDigestBytes") {
|
|
732
|
+
const getBytes = Reflect.get(target, property, target);
|
|
733
|
+
if (typeof getBytes === "function") {
|
|
734
|
+
return (...args: unknown[]) =>
|
|
735
|
+
mapMaybePromise(
|
|
736
|
+
Reflect.apply(getBytes, target, args),
|
|
737
|
+
copyOptionalBytes,
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
if (property === "__peerbitNext") {
|
|
742
|
+
const next = Reflect.get(target, property, target);
|
|
743
|
+
return Array.isArray(next) ? getContext().detachArray(next) : next;
|
|
744
|
+
}
|
|
265
745
|
if (property === "getStorageBytes") {
|
|
266
746
|
return () => new Uint8Array(entry.getStorageBytes());
|
|
267
747
|
}
|
|
748
|
+
if (property === "toShallow") {
|
|
749
|
+
const toShallow = Reflect.get(target, property, target);
|
|
750
|
+
if (typeof toShallow === "function") {
|
|
751
|
+
return (...args: unknown[]) => {
|
|
752
|
+
const shallow = Reflect.apply(toShallow, target, args) as unknown;
|
|
753
|
+
return shallow && typeof shallow === "object"
|
|
754
|
+
? getContext().detachEntryLike(shallow)
|
|
755
|
+
: shallow;
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
}
|
|
268
759
|
if (property === "valueOf") {
|
|
269
760
|
return () => callbackEntry;
|
|
270
761
|
}
|
|
@@ -275,11 +766,35 @@ export const detachEntryPayloadForCallback = <T>(entry: Entry<T>): Entry<T> => {
|
|
|
275
766
|
return callbackEntry;
|
|
276
767
|
}
|
|
277
768
|
return (detachedMaterialized ??=
|
|
278
|
-
|
|
769
|
+
detachEntryPayloadForCallbackWithContext(materialized, getContext));
|
|
279
770
|
};
|
|
280
771
|
}
|
|
281
772
|
if (property === "toSignable") {
|
|
282
|
-
return () =>
|
|
773
|
+
return () =>
|
|
774
|
+
detachEntryPayloadForCallbackWithContext(
|
|
775
|
+
entry.toSignable(),
|
|
776
|
+
getContext,
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
if (property === "toPreparedAppendJoinFacts") {
|
|
780
|
+
const toPreparedAppendJoinFacts = Reflect.get(target, property, target);
|
|
781
|
+
if (typeof toPreparedAppendJoinFacts === "function") {
|
|
782
|
+
return (...args: unknown[]) => {
|
|
783
|
+
const facts = Reflect.apply(
|
|
784
|
+
toPreparedAppendJoinFacts,
|
|
785
|
+
target,
|
|
786
|
+
args,
|
|
787
|
+
) as unknown;
|
|
788
|
+
return facts && typeof facts === "object"
|
|
789
|
+
? detachPreparedAppendJoinFactsForCallback(
|
|
790
|
+
facts,
|
|
791
|
+
target,
|
|
792
|
+
callbackEntry,
|
|
793
|
+
getContext,
|
|
794
|
+
)
|
|
795
|
+
: facts;
|
|
796
|
+
};
|
|
797
|
+
}
|
|
283
798
|
}
|
|
284
799
|
if (property === "init") {
|
|
285
800
|
return (properties: Parameters<Entry<T>["init"]>[0]) => {
|
|
@@ -306,3 +821,28 @@ export const detachEntryPayloadForCallback = <T>(entry: Entry<T>): Entry<T> => {
|
|
|
306
821
|
detachedCallbackEntries.add(callbackEntry);
|
|
307
822
|
return callbackEntry;
|
|
308
823
|
};
|
|
824
|
+
|
|
825
|
+
export const detachEntryPayloadForCallback = <T>(entry: Entry<T>): Entry<T> => {
|
|
826
|
+
let context: EntryDetachmentContext | undefined;
|
|
827
|
+
return detachEntryPayloadForCallbackWithContext(
|
|
828
|
+
entry,
|
|
829
|
+
() => (context ??= createEntryDetachmentContext()),
|
|
830
|
+
);
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
/** Detach full, shallow, and replicated entries at document callback edges. */
|
|
834
|
+
export const detachEntryForCallback = <T>(entry: T): T => {
|
|
835
|
+
if (!entry || typeof entry !== "object") {
|
|
836
|
+
return entry;
|
|
837
|
+
}
|
|
838
|
+
return (
|
|
839
|
+
entry instanceof Entry
|
|
840
|
+
? detachEntryPayloadForCallback(entry)
|
|
841
|
+
: createEntryDetachmentContext().detachEntryLike(entry)
|
|
842
|
+
) as T;
|
|
843
|
+
};
|
|
844
|
+
|
|
845
|
+
/** Give arbitrary document transforms signer objects they cannot retain/mutate. */
|
|
846
|
+
export const detachPublicKeysForCallback = (
|
|
847
|
+
keys: readonly PublicSignKey[],
|
|
848
|
+
): PublicSignKey[] => createEntryDetachmentContext().detachPublicKeys(keys);
|
package/src/domain.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
type ReplicationDomain,
|
|
10
10
|
type SharedLog,
|
|
11
11
|
} from "@peerbit/shared-log";
|
|
12
|
-
import {
|
|
12
|
+
import { detachEntryForCallback } from "./callback-detachment.js";
|
|
13
13
|
import { type Operation, isPutOperation } from "./operation.js";
|
|
14
14
|
import type { DocumentIndex } from "./search.js";
|
|
15
15
|
|
|
@@ -96,8 +96,7 @@ export const createDocumentDomain =
|
|
|
96
96
|
let maxValue = args.resolution === "u32" ? MAX_U32 : MAX_U64;
|
|
97
97
|
const detachEntry = (
|
|
98
98
|
entry: ShallowEntry | Entry<Operation> | EntryReplicated<any>,
|
|
99
|
-
) =>
|
|
100
|
-
entry instanceof Entry ? detachEntryPayloadForCallback(entry) : entry;
|
|
99
|
+
) => detachEntryForCallback(entry);
|
|
101
100
|
let fromEntry = (args as FromEntry<InferR<DB>>).fromEntry
|
|
102
101
|
? (entry: ShallowEntry | Entry<Operation> | EntryReplicated<any>) =>
|
|
103
102
|
(args as FromEntry<InferR<DB>>).fromEntry!(detachEntry(entry))
|