loro-repo 0.3.0 → 0.4.0
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 +18 -17
- package/dist/index.cjs +54 -85
- package/dist/index.cjs.map +1 -1
- package/dist/{index-DsCaL9JX.d.cts → index.d.cts} +3 -3
- package/dist/{index-tq65q3qY.d.ts → index.d.ts} +4 -3
- package/dist/index.js +38 -73
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ LoroRepo is the collection-sync layer that sits above Flock. It keeps document m
|
|
|
9
9
|
## What you get
|
|
10
10
|
|
|
11
11
|
- **Metadata-first coordination** – `repo.listDoc()` and `repo.watch()` expose LWW metadata so UIs can render collections before bodies arrive.
|
|
12
|
-
- **On-demand documents** – `
|
|
12
|
+
- **On-demand documents** – `openPersistedDoc()` hands back a repo-managed `LoroDoc` that persists locally and can sync once or join live rooms; `openDetachedDoc()` is a read-only snapshot.
|
|
13
13
|
- **Binary asset orchestration** – `linkAsset()`/`fetchAsset()` dedupe SHA-256 addressed blobs across docs, while `gcAssets()` sweeps unreferenced payloads.
|
|
14
14
|
- **Pluggable adapters** – supply your own `TransportAdapter`, `StorageAdapter`, and `AssetTransportAdapter` (or use the built-ins below) to target servers, CF Durable Objects, or local-first meshes.
|
|
15
15
|
- **Consistent events** – every event includes `by: "local" | "sync" | "live"` so you can react differently to local edits, explicit sync pulls, or realtime merges.
|
|
@@ -22,36 +22,37 @@ import {
|
|
|
22
22
|
BroadcastChannelTransportAdapter,
|
|
23
23
|
IndexedDBStorageAdaptor,
|
|
24
24
|
} from "loro-repo";
|
|
25
|
-
import { LoroDoc } from "loro-crdt";
|
|
26
25
|
|
|
27
26
|
type DocMeta = { title?: string; tags?: string[] };
|
|
28
27
|
|
|
29
|
-
const repo =
|
|
28
|
+
const repo = await LoroRepo.create<DocMeta>({
|
|
30
29
|
transportAdapter: new BroadcastChannelTransportAdapter({ namespace: "notes" }),
|
|
31
30
|
storageAdapter: new IndexedDBStorageAdaptor({ dbName: "notes-db" }),
|
|
32
|
-
docFactory: async () => new LoroDoc(),
|
|
33
31
|
});
|
|
34
32
|
|
|
35
|
-
await repo.ready();
|
|
36
33
|
await repo.sync({ scope: "meta" }); // metadata-first
|
|
37
34
|
|
|
38
35
|
await repo.upsertDocMeta("note:welcome", { title: "Welcome" });
|
|
39
36
|
|
|
40
|
-
const handle = await repo.
|
|
41
|
-
await handle.
|
|
37
|
+
const handle = await repo.openPersistedDoc("note:welcome");
|
|
38
|
+
await handle.syncOnce(); // optional: fetch body once
|
|
39
|
+
const room = await handle.joinRoom(); // optional: live updates
|
|
42
40
|
handle.doc.getText("content").insert(0, "Hello from LoroRepo");
|
|
43
41
|
handle.doc.commit();
|
|
44
|
-
|
|
42
|
+
room.unsubscribe();
|
|
43
|
+
await repo.unloadDoc("note:welcome");
|
|
45
44
|
```
|
|
46
45
|
|
|
47
46
|
## Using the API
|
|
48
47
|
|
|
49
|
-
- **
|
|
48
|
+
- **Create a repo** with `await LoroRepo.create<Meta>({ transportAdapter?, storageAdapter?, assetTransportAdapter?, docFrontierDebounceMs? })`; metadata is hydrated automatically.
|
|
49
|
+
- **Define your metadata contract** once via the generic `Meta`. All metadata helpers (`upsertDocMeta`, `getDocMeta`, `listDoc`, `watch`) stay type-safe.
|
|
50
50
|
- **Choose sync lanes** with `repo.sync({ scope: "meta" | "doc" | "full", docIds?: string[] })` to pull remote changes on demand.
|
|
51
|
+
- **Work with documents** using `openPersistedDoc(docId)` for repo-managed docs (persisted snapshots + frontier tracking) and `openDetachedDoc(docId)` for isolated snapshots; call `joinDocRoom`/`handle.joinRoom` for live sync, or `unloadDoc`/`flush` to persist and drop cached docs.
|
|
51
52
|
- **Join realtime rooms** by calling `joinMetaRoom()` / `joinDocRoom(docId)`; the behaviour depends entirely on the transport adapter you injected.
|
|
52
53
|
- **Manage assets** through `linkAsset`, `uploadAsset`, `fetchAsset` (alias `ensureAsset`), `listAssets`, and `gcAssets({ minKeepMs })`.
|
|
53
54
|
- **React to changes** by subscribing with `repo.watch(listener, { docIds, kinds, metadataFields, by })`.
|
|
54
|
-
- **Shut down cleanly** via `await repo.
|
|
55
|
+
- **Shut down cleanly** via `await repo.destroy()` to flush snapshots and dispose adapters.
|
|
55
56
|
|
|
56
57
|
## Built-in adapters
|
|
57
58
|
|
|
@@ -83,22 +84,22 @@ await handle.close();
|
|
|
83
84
|
## Core API surface
|
|
84
85
|
|
|
85
86
|
**Lifecycle**
|
|
86
|
-
- `
|
|
87
|
-
- `await repo.ready()` – hydrate metadata snapshot before touching docs.
|
|
87
|
+
- `await LoroRepo.create<Meta>({ transportAdapter?, storageAdapter?, assetTransportAdapter?, docFrontierDebounceMs? })` – hydrate metadata and initialise adapters.
|
|
88
88
|
- `await repo.sync({ scope: "meta" | "doc" | "full", docIds?: string[] })` – pull remote updates on demand.
|
|
89
|
-
- `await repo.
|
|
89
|
+
- `await repo.destroy()` – persist pending work and dispose adapters.
|
|
90
90
|
|
|
91
91
|
**Metadata**
|
|
92
92
|
- `await repo.upsertDocMeta(docId, patch)` – LWW merge with your `Meta` type.
|
|
93
93
|
- `await repo.getDocMeta(docId)` – clone the stored metadata (or `undefined`).
|
|
94
94
|
- `await repo.listDoc(query?)` – list docs by prefix/range/limit (`RepoDocMeta<Meta>[]`).
|
|
95
|
-
- `repo.
|
|
95
|
+
- `repo.getMeta()` – access raw `Flock` if you need advanced scans.
|
|
96
96
|
|
|
97
97
|
**Documents**
|
|
98
|
-
- `await repo.
|
|
98
|
+
- `await repo.openPersistedDoc(docId)` – returns `{ doc, syncOnce, joinRoom }`; mutations persist locally and frontiers are written to metadata.
|
|
99
99
|
- `await repo.openDetachedDoc(docId)` – isolated snapshot handle (no persistence, no live sync) ideal for read-only tasks.
|
|
100
|
-
- `await repo.
|
|
101
|
-
- `await repo.
|
|
100
|
+
- `await repo.joinDocRoom(docId, params?)` or `await handle.joinRoom(auth?)` – spawn a realtime session through your transport; use `subscription.unsubscribe()` when done.
|
|
101
|
+
- `await repo.unloadDoc(docId)` – flush pending work for a doc and evict it from memory.
|
|
102
|
+
- `await repo.flush()` – persist all loaded docs and flush pending frontier updates.
|
|
102
103
|
|
|
103
104
|
**Assets**
|
|
104
105
|
- `await repo.linkAsset(docId, { content, mime?, tag?, policy?, assetId?, createdAt? })` – upload + link, returning the SHA-256 assetId.
|
package/dist/index.cjs
CHANGED
|
@@ -6,16 +6,12 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
19
15
|
}
|
|
20
16
|
return to;
|
|
21
17
|
};
|
|
@@ -26,18 +22,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
22
|
|
|
27
23
|
//#endregion
|
|
28
24
|
let __loro_dev_flock = require("@loro-dev/flock");
|
|
29
|
-
|
|
25
|
+
__loro_dev_flock = __toESM(__loro_dev_flock);
|
|
26
|
+
let loro_adaptors_loro = require("loro-adaptors/loro");
|
|
27
|
+
loro_adaptors_loro = __toESM(loro_adaptors_loro);
|
|
30
28
|
let loro_protocol = require("loro-protocol");
|
|
29
|
+
loro_protocol = __toESM(loro_protocol);
|
|
31
30
|
let loro_websocket = require("loro-websocket");
|
|
31
|
+
loro_websocket = __toESM(loro_websocket);
|
|
32
32
|
let loro_crdt = require("loro-crdt");
|
|
33
|
+
loro_crdt = __toESM(loro_crdt);
|
|
34
|
+
let loro_adaptors_flock = require("loro-adaptors/flock");
|
|
35
|
+
loro_adaptors_flock = __toESM(loro_adaptors_flock);
|
|
33
36
|
let node_fs = require("node:fs");
|
|
37
|
+
node_fs = __toESM(node_fs);
|
|
34
38
|
let node_path = require("node:path");
|
|
35
39
|
node_path = __toESM(node_path);
|
|
36
40
|
let node_crypto = require("node:crypto");
|
|
41
|
+
node_crypto = __toESM(node_crypto);
|
|
37
42
|
|
|
38
43
|
//#region src/loro-adaptor.ts
|
|
39
44
|
function createRepoFlockAdaptorFromDoc(flock, config = {}) {
|
|
40
|
-
return new
|
|
45
|
+
return new loro_adaptors_flock.FlockAdaptor(flock, config);
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
//#endregion
|
|
@@ -391,7 +396,7 @@ var WebSocketTransportAdapter = class {
|
|
|
391
396
|
});
|
|
392
397
|
await this.leaveDocSession(docId).catch(() => {});
|
|
393
398
|
}
|
|
394
|
-
const adaptor = new
|
|
399
|
+
const adaptor = new loro_adaptors_loro.LoroAdaptor(doc);
|
|
395
400
|
debug("joining doc room", {
|
|
396
401
|
docId,
|
|
397
402
|
roomId,
|
|
@@ -1895,13 +1900,11 @@ var AssetManager = class {
|
|
|
1895
1900
|
if (params.assetId && params.assetId !== assetId) throw new Error("Provided assetId does not match content digest");
|
|
1896
1901
|
const existing = this.assets.get(assetId);
|
|
1897
1902
|
if (existing) {
|
|
1898
|
-
if (
|
|
1899
|
-
|
|
1900
|
-
existing.data = clone;
|
|
1901
|
-
if (this.storage) await this.storage.save({
|
|
1903
|
+
if (this.storage) {
|
|
1904
|
+
if (!await this.storage.loadAsset(assetId)) await this.storage.save({
|
|
1902
1905
|
type: "asset",
|
|
1903
1906
|
assetId,
|
|
1904
|
-
data:
|
|
1907
|
+
data: bytes.slice()
|
|
1905
1908
|
});
|
|
1906
1909
|
}
|
|
1907
1910
|
let metadataMutated = false;
|
|
@@ -1928,7 +1931,7 @@ var AssetManager = class {
|
|
|
1928
1931
|
await this.persistMeta();
|
|
1929
1932
|
this.eventBus.emit({
|
|
1930
1933
|
kind: "asset-metadata",
|
|
1931
|
-
asset: this.createAssetDownload(assetId, metadata$1,
|
|
1934
|
+
asset: this.createAssetDownload(assetId, metadata$1, bytes),
|
|
1932
1935
|
by: "local"
|
|
1933
1936
|
});
|
|
1934
1937
|
}
|
|
@@ -1958,7 +1961,8 @@ var AssetManager = class {
|
|
|
1958
1961
|
assetId,
|
|
1959
1962
|
data: storedBytes.slice()
|
|
1960
1963
|
});
|
|
1961
|
-
this.rememberAsset(metadata
|
|
1964
|
+
this.rememberAsset(metadata);
|
|
1965
|
+
this.markAssetAsOrphan(assetId, metadata);
|
|
1962
1966
|
this.updateDocAssetMetadata(assetId, metadata);
|
|
1963
1967
|
this.metaFlock.put(["a", assetId], assetMetaToJson(metadata));
|
|
1964
1968
|
await this.persistMeta();
|
|
@@ -1979,13 +1983,11 @@ var AssetManager = class {
|
|
|
1979
1983
|
const existing = this.assets.get(assetId);
|
|
1980
1984
|
if (existing) {
|
|
1981
1985
|
metadata = existing.metadata;
|
|
1982
|
-
if (
|
|
1983
|
-
|
|
1984
|
-
existing.data = clone;
|
|
1985
|
-
if (this.storage) await this.storage.save({
|
|
1986
|
+
if (this.storage) {
|
|
1987
|
+
if (!await this.storage.loadAsset(assetId)) await this.storage.save({
|
|
1986
1988
|
type: "asset",
|
|
1987
1989
|
assetId,
|
|
1988
|
-
data:
|
|
1990
|
+
data: bytes.slice()
|
|
1989
1991
|
});
|
|
1990
1992
|
}
|
|
1991
1993
|
let nextMetadata = metadata;
|
|
@@ -2025,11 +2027,11 @@ var AssetManager = class {
|
|
|
2025
2027
|
await this.persistMeta();
|
|
2026
2028
|
this.eventBus.emit({
|
|
2027
2029
|
kind: "asset-metadata",
|
|
2028
|
-
asset: this.createAssetDownload(assetId, metadata,
|
|
2030
|
+
asset: this.createAssetDownload(assetId, metadata, bytes),
|
|
2029
2031
|
by: "local"
|
|
2030
2032
|
});
|
|
2031
2033
|
} else metadata = existing.metadata;
|
|
2032
|
-
storedBytes =
|
|
2034
|
+
storedBytes = bytes;
|
|
2033
2035
|
this.rememberAsset(metadata);
|
|
2034
2036
|
} else {
|
|
2035
2037
|
metadata = {
|
|
@@ -2055,7 +2057,7 @@ var AssetManager = class {
|
|
|
2055
2057
|
assetId,
|
|
2056
2058
|
data: storedBytes.slice()
|
|
2057
2059
|
});
|
|
2058
|
-
this.rememberAsset(metadata
|
|
2060
|
+
this.rememberAsset(metadata);
|
|
2059
2061
|
this.updateDocAssetMetadata(assetId, metadata);
|
|
2060
2062
|
this.metaFlock.put(["a", assetId], assetMetaToJson(metadata));
|
|
2061
2063
|
created = true;
|
|
@@ -2063,9 +2065,7 @@ var AssetManager = class {
|
|
|
2063
2065
|
const mapping = this.docAssets.get(docId) ?? /* @__PURE__ */ new Map();
|
|
2064
2066
|
mapping.set(assetId, metadata);
|
|
2065
2067
|
this.docAssets.set(docId, mapping);
|
|
2066
|
-
|
|
2067
|
-
refs.add(docId);
|
|
2068
|
-
this.assetToDocRefs.set(assetId, refs);
|
|
2068
|
+
this.addDocReference(assetId, docId);
|
|
2069
2069
|
this.metaFlock.put([
|
|
2070
2070
|
"ld",
|
|
2071
2071
|
docId,
|
|
@@ -2095,20 +2095,7 @@ var AssetManager = class {
|
|
|
2095
2095
|
docId,
|
|
2096
2096
|
assetId
|
|
2097
2097
|
]);
|
|
2098
|
-
|
|
2099
|
-
if (refs) {
|
|
2100
|
-
refs.delete(docId);
|
|
2101
|
-
if (refs.size === 0) {
|
|
2102
|
-
this.assetToDocRefs.delete(assetId);
|
|
2103
|
-
const record = this.assets.get(assetId);
|
|
2104
|
-
if (record) this.orphanedAssets.set(assetId, {
|
|
2105
|
-
metadata: record.metadata,
|
|
2106
|
-
deletedAt: Date.now()
|
|
2107
|
-
});
|
|
2108
|
-
this.metaFlock.delete(["a", assetId]);
|
|
2109
|
-
this.assets.delete(assetId);
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2098
|
+
this.removeDocAssetReference(assetId, docId);
|
|
2112
2099
|
await this.persistMeta();
|
|
2113
2100
|
this.eventBus.emit({
|
|
2114
2101
|
kind: "asset-unlink",
|
|
@@ -2195,12 +2182,11 @@ var AssetManager = class {
|
|
|
2195
2182
|
this.handleAssetRemoval(assetId, by);
|
|
2196
2183
|
return;
|
|
2197
2184
|
}
|
|
2198
|
-
|
|
2199
|
-
this.rememberAsset(metadata, existingData);
|
|
2185
|
+
this.rememberAsset(metadata);
|
|
2200
2186
|
this.updateDocAssetMetadata(assetId, cloneRepoAssetMetadata(metadata));
|
|
2201
2187
|
if (!previous || !assetMetadataEqual(previous.metadata, metadata)) this.eventBus.emit({
|
|
2202
2188
|
kind: "asset-metadata",
|
|
2203
|
-
asset: this.createAssetDownload(assetId, metadata
|
|
2189
|
+
asset: this.createAssetDownload(assetId, metadata),
|
|
2204
2190
|
by
|
|
2205
2191
|
});
|
|
2206
2192
|
}
|
|
@@ -2215,11 +2201,7 @@ var AssetManager = class {
|
|
|
2215
2201
|
if (typeof assetId !== "string") continue;
|
|
2216
2202
|
const metadata = assetMetaFromJson(row.value);
|
|
2217
2203
|
if (!metadata) continue;
|
|
2218
|
-
|
|
2219
|
-
nextAssets.set(assetId, {
|
|
2220
|
-
metadata,
|
|
2221
|
-
data: existing?.data
|
|
2222
|
-
});
|
|
2204
|
+
nextAssets.set(assetId, { metadata });
|
|
2223
2205
|
}
|
|
2224
2206
|
const nextDocAssets = /* @__PURE__ */ new Map();
|
|
2225
2207
|
const linkRows = this.metaFlock.scan({ prefix: ["ld"] });
|
|
@@ -2255,12 +2237,18 @@ var AssetManager = class {
|
|
|
2255
2237
|
this.assetToDocRefs.set(assetId, refs);
|
|
2256
2238
|
}
|
|
2257
2239
|
this.assets.clear();
|
|
2258
|
-
for (const record of nextAssets.values()) this.rememberAsset(record.metadata
|
|
2240
|
+
for (const record of nextAssets.values()) this.rememberAsset(record.metadata);
|
|
2241
|
+
for (const assetId of nextAssets.keys()) {
|
|
2242
|
+
const refs = this.assetToDocRefs.get(assetId);
|
|
2243
|
+
if (!refs || refs.size === 0) {
|
|
2244
|
+
if (!this.orphanedAssets.has(assetId)) this.markAssetAsOrphan(assetId, nextAssets.get(assetId).metadata);
|
|
2245
|
+
} else this.orphanedAssets.delete(assetId);
|
|
2246
|
+
}
|
|
2259
2247
|
for (const [assetId, record] of nextAssets) {
|
|
2260
2248
|
const previous = prevAssets.get(assetId)?.metadata;
|
|
2261
2249
|
if (!assetMetadataEqual(previous, record.metadata)) this.eventBus.emit({
|
|
2262
2250
|
kind: "asset-metadata",
|
|
2263
|
-
asset: this.createAssetDownload(assetId, record.metadata
|
|
2251
|
+
asset: this.createAssetDownload(assetId, record.metadata),
|
|
2264
2252
|
by
|
|
2265
2253
|
});
|
|
2266
2254
|
}
|
|
@@ -2356,36 +2344,24 @@ var AssetManager = class {
|
|
|
2356
2344
|
};
|
|
2357
2345
|
}
|
|
2358
2346
|
async materializeAsset(assetId) {
|
|
2359
|
-
|
|
2360
|
-
if (record?.data) return {
|
|
2361
|
-
metadata: record.metadata,
|
|
2362
|
-
bytes: record.data.slice()
|
|
2363
|
-
};
|
|
2347
|
+
const record = this.assets.get(assetId);
|
|
2364
2348
|
if (record && this.storage) {
|
|
2365
2349
|
const stored = await this.storage.loadAsset(assetId);
|
|
2366
|
-
if (stored) {
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
metadata: record.metadata,
|
|
2371
|
-
bytes: clone
|
|
2372
|
-
};
|
|
2373
|
-
}
|
|
2350
|
+
if (stored) return {
|
|
2351
|
+
metadata: record.metadata,
|
|
2352
|
+
bytes: stored
|
|
2353
|
+
};
|
|
2374
2354
|
}
|
|
2375
2355
|
if (!record && this.storage) {
|
|
2376
2356
|
const stored = await this.storage.loadAsset(assetId);
|
|
2377
2357
|
if (stored) {
|
|
2378
2358
|
const metadata$1 = this.getAssetMetadata(assetId);
|
|
2379
2359
|
if (!metadata$1) throw new Error(`Missing metadata for asset ${assetId}`);
|
|
2380
|
-
|
|
2381
|
-
this.assets.set(assetId, {
|
|
2382
|
-
metadata: metadata$1,
|
|
2383
|
-
data: clone.slice()
|
|
2384
|
-
});
|
|
2360
|
+
this.assets.set(assetId, { metadata: metadata$1 });
|
|
2385
2361
|
this.updateDocAssetMetadata(assetId, metadata$1);
|
|
2386
2362
|
return {
|
|
2387
2363
|
metadata: metadata$1,
|
|
2388
|
-
bytes:
|
|
2364
|
+
bytes: stored
|
|
2389
2365
|
};
|
|
2390
2366
|
}
|
|
2391
2367
|
}
|
|
@@ -2401,10 +2377,7 @@ var AssetManager = class {
|
|
|
2401
2377
|
...remote.policy ? { policy: remote.policy } : {},
|
|
2402
2378
|
...remote.tag ? { tag: remote.tag } : {}
|
|
2403
2379
|
};
|
|
2404
|
-
this.assets.set(assetId, {
|
|
2405
|
-
metadata,
|
|
2406
|
-
data: remoteBytes.slice()
|
|
2407
|
-
});
|
|
2380
|
+
this.assets.set(assetId, { metadata });
|
|
2408
2381
|
this.updateDocAssetMetadata(assetId, metadata);
|
|
2409
2382
|
this.metaFlock.put(["a", assetId], assetMetaToJson(metadata));
|
|
2410
2383
|
await this.persistMeta();
|
|
@@ -2426,18 +2399,14 @@ var AssetManager = class {
|
|
|
2426
2399
|
if (assets) assets.set(assetId, metadata);
|
|
2427
2400
|
}
|
|
2428
2401
|
}
|
|
2429
|
-
rememberAsset(metadata
|
|
2430
|
-
|
|
2431
|
-
this.assets.set(metadata.assetId, {
|
|
2432
|
-
metadata,
|
|
2433
|
-
data
|
|
2434
|
-
});
|
|
2435
|
-
this.orphanedAssets.delete(metadata.assetId);
|
|
2402
|
+
rememberAsset(metadata) {
|
|
2403
|
+
this.assets.set(metadata.assetId, { metadata });
|
|
2436
2404
|
}
|
|
2437
2405
|
addDocReference(assetId, docId) {
|
|
2438
2406
|
const refs = this.assetToDocRefs.get(assetId) ?? /* @__PURE__ */ new Set();
|
|
2439
2407
|
refs.add(docId);
|
|
2440
2408
|
this.assetToDocRefs.set(assetId, refs);
|
|
2409
|
+
this.orphanedAssets.delete(assetId);
|
|
2441
2410
|
}
|
|
2442
2411
|
removeDocAssetReference(assetId, docId) {
|
|
2443
2412
|
const refs = this.assetToDocRefs.get(assetId);
|