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.
@@ -2,7 +2,7 @@ import { Flock } from "@loro-dev/flock";
2
2
  import { Frontiers, LoroDoc } from "loro-crdt";
3
3
  import { JoinError, JoinResponseOk, RoomId, UpdateError } from "loro-protocol";
4
4
  import { LoroWebsocketClientOptions } from "loro-websocket";
5
- import { FlockAdaptorConfig } from "loro-adaptors";
5
+ import { FlockAdaptorConfig } from "loro-adaptors/flock";
6
6
 
7
7
  //#region src/types.d.ts
8
8
  type GlobalBlob = typeof globalThis extends {
@@ -714,5 +714,5 @@ declare class LoroRepo<Meta extends JsonObject = JsonObject> {
714
714
  destroy(): Promise<void>;
715
715
  }
716
716
  //#endregion
717
- export { AssetContent, AssetDownload, AssetId, AssetTransportAdapter, AssetUploadMetadata, BroadcastChannelTransportAdapter, type BroadcastChannelTransportOptions, FileSystemStorageAdaptor, type FileSystemStorageAdaptorOptions, GarbageCollectionOptions, IndexedDBStorageAdaptor, type IndexedDBStorageAdaptorOptions, JsonObject, JsonValue, LinkAssetOptions, ListDocQuery, LoroRepo, LoroRepoOptions, RepoAssetMetadata, RepoDocHandle, RepoDocMeta, RepoEvent, RepoEventBy, RepoEventFilter, RepoEventKind, RepoEventListener, RepoEventType, type RepoSyncOptions, RepoWatchHandle, StorageAdapter, StorageSavePayload, SyncScope, TransportAdapter, type TransportJoinParams, type TransportSubscription, TransportSyncRequest, type TransportSyncResult, UploadAssetOptions, WebSocketTransportAdapter, WebSocketTransportOptions };
718
- //# sourceMappingURL=index-DsCaL9JX.d.cts.map
717
+ export { AssetContent, AssetDownload, AssetId, AssetTransportAdapter, AssetUploadMetadata, BroadcastChannelTransportAdapter, type BroadcastChannelTransportOptions, FileSystemStorageAdaptor, type FileSystemStorageAdaptorOptions, GarbageCollectionOptions, IndexedDBStorageAdaptor, type IndexedDBStorageAdaptorOptions, JsonObject, JsonValue, LinkAssetOptions, ListDocQuery, LoroRepo, LoroRepoOptions, RepoAssetMetadata, RepoDocHandle, RepoDocMeta, RepoEvent, RepoEventBy, RepoEventFilter, RepoEventKind, RepoEventListener, RepoEventType, type RepoSyncOptions, RepoWatchHandle, StorageAdapter, StorageSavePayload, SyncScope, TransportAdapter, type TransportJoinParams, type TransportSubscription, TransportSyncRequest, type TransportSyncResult, UploadAssetOptions, WebSocketTransportAdapter, type WebSocketTransportOptions };
718
+ //# sourceMappingURL=index.d.cts.map
@@ -1,8 +1,9 @@
1
1
  import { Flock } from "@loro-dev/flock";
2
- import { FlockAdaptor, FlockAdaptorConfig, LoroAdaptor } from "loro-adaptors";
2
+ import { LoroAdaptor } from "loro-adaptors/loro";
3
3
  import { JoinError, JoinResponseOk, RoomId, UpdateError } from "loro-protocol";
4
4
  import { LoroWebsocketClientOptions } from "loro-websocket";
5
5
  import { Frontiers, LoroDoc } from "loro-crdt";
6
+ import { FlockAdaptor, FlockAdaptorConfig } from "loro-adaptors/flock";
6
7
 
7
8
  //#region src/types.d.ts
8
9
  type GlobalBlob = typeof globalThis extends {
@@ -714,5 +715,5 @@ declare class LoroRepo<Meta extends JsonObject = JsonObject> {
714
715
  destroy(): Promise<void>;
715
716
  }
716
717
  //#endregion
717
- export { AssetContent, AssetDownload, AssetId, AssetTransportAdapter, AssetUploadMetadata, BroadcastChannelTransportAdapter, type BroadcastChannelTransportOptions, FileSystemStorageAdaptor, type FileSystemStorageAdaptorOptions, GarbageCollectionOptions, IndexedDBStorageAdaptor, type IndexedDBStorageAdaptorOptions, JsonObject, JsonValue, LinkAssetOptions, ListDocQuery, LoroRepo, LoroRepoOptions, RepoAssetMetadata, RepoDocHandle, RepoDocMeta, RepoEvent, RepoEventBy, RepoEventFilter, RepoEventKind, RepoEventListener, RepoEventType, type RepoSyncOptions, RepoWatchHandle, StorageAdapter, StorageSavePayload, SyncScope, TransportAdapter, type TransportJoinParams, type TransportSubscription, TransportSyncRequest, type TransportSyncResult, UploadAssetOptions, WebSocketTransportAdapter, WebSocketTransportOptions };
718
- //# sourceMappingURL=index-tq65q3qY.d.ts.map
718
+ export { AssetContent, AssetDownload, AssetId, AssetTransportAdapter, AssetUploadMetadata, BroadcastChannelTransportAdapter, type BroadcastChannelTransportOptions, FileSystemStorageAdaptor, type FileSystemStorageAdaptorOptions, GarbageCollectionOptions, IndexedDBStorageAdaptor, type IndexedDBStorageAdaptorOptions, JsonObject, JsonValue, LinkAssetOptions, ListDocQuery, LoroRepo, LoroRepoOptions, RepoAssetMetadata, RepoDocHandle, RepoDocMeta, RepoEvent, RepoEventBy, RepoEventFilter, RepoEventKind, RepoEventListener, RepoEventType, type RepoSyncOptions, RepoWatchHandle, StorageAdapter, StorageSavePayload, SyncScope, TransportAdapter, type TransportJoinParams, type TransportSubscription, TransportSyncRequest, type TransportSyncResult, UploadAssetOptions, WebSocketTransportAdapter, type WebSocketTransportOptions };
719
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { Flock } from "@loro-dev/flock";
2
- import { FlockAdaptor, LoroAdaptor } from "loro-adaptors";
2
+ import { LoroAdaptor } from "loro-adaptors/loro";
3
3
  import { CrdtType, bytesToHex } from "loro-protocol";
4
4
  import { LoroWebsocketClient } from "loro-websocket";
5
5
  import { LoroDoc } from "loro-crdt";
6
+ import { FlockAdaptor } from "loro-adaptors/flock";
6
7
  import { promises } from "node:fs";
7
8
  import * as path from "node:path";
8
9
  import { randomUUID } from "node:crypto";
@@ -1867,13 +1868,11 @@ var AssetManager = class {
1867
1868
  if (params.assetId && params.assetId !== assetId) throw new Error("Provided assetId does not match content digest");
1868
1869
  const existing = this.assets.get(assetId);
1869
1870
  if (existing) {
1870
- if (!existing.data) {
1871
- const clone = bytes.slice();
1872
- existing.data = clone;
1873
- if (this.storage) await this.storage.save({
1871
+ if (this.storage) {
1872
+ if (!await this.storage.loadAsset(assetId)) await this.storage.save({
1874
1873
  type: "asset",
1875
1874
  assetId,
1876
- data: clone.slice()
1875
+ data: bytes.slice()
1877
1876
  });
1878
1877
  }
1879
1878
  let metadataMutated = false;
@@ -1900,7 +1899,7 @@ var AssetManager = class {
1900
1899
  await this.persistMeta();
1901
1900
  this.eventBus.emit({
1902
1901
  kind: "asset-metadata",
1903
- asset: this.createAssetDownload(assetId, metadata$1, existing.data),
1902
+ asset: this.createAssetDownload(assetId, metadata$1, bytes),
1904
1903
  by: "local"
1905
1904
  });
1906
1905
  }
@@ -1930,7 +1929,8 @@ var AssetManager = class {
1930
1929
  assetId,
1931
1930
  data: storedBytes.slice()
1932
1931
  });
1933
- this.rememberAsset(metadata, storedBytes);
1932
+ this.rememberAsset(metadata);
1933
+ this.markAssetAsOrphan(assetId, metadata);
1934
1934
  this.updateDocAssetMetadata(assetId, metadata);
1935
1935
  this.metaFlock.put(["a", assetId], assetMetaToJson(metadata));
1936
1936
  await this.persistMeta();
@@ -1951,13 +1951,11 @@ var AssetManager = class {
1951
1951
  const existing = this.assets.get(assetId);
1952
1952
  if (existing) {
1953
1953
  metadata = existing.metadata;
1954
- if (!existing.data) {
1955
- const clone = bytes.slice();
1956
- existing.data = clone;
1957
- if (this.storage) await this.storage.save({
1954
+ if (this.storage) {
1955
+ if (!await this.storage.loadAsset(assetId)) await this.storage.save({
1958
1956
  type: "asset",
1959
1957
  assetId,
1960
- data: clone.slice()
1958
+ data: bytes.slice()
1961
1959
  });
1962
1960
  }
1963
1961
  let nextMetadata = metadata;
@@ -1997,11 +1995,11 @@ var AssetManager = class {
1997
1995
  await this.persistMeta();
1998
1996
  this.eventBus.emit({
1999
1997
  kind: "asset-metadata",
2000
- asset: this.createAssetDownload(assetId, metadata, existing.data),
1998
+ asset: this.createAssetDownload(assetId, metadata, bytes),
2001
1999
  by: "local"
2002
2000
  });
2003
2001
  } else metadata = existing.metadata;
2004
- storedBytes = existing.data;
2002
+ storedBytes = bytes;
2005
2003
  this.rememberAsset(metadata);
2006
2004
  } else {
2007
2005
  metadata = {
@@ -2027,7 +2025,7 @@ var AssetManager = class {
2027
2025
  assetId,
2028
2026
  data: storedBytes.slice()
2029
2027
  });
2030
- this.rememberAsset(metadata, storedBytes);
2028
+ this.rememberAsset(metadata);
2031
2029
  this.updateDocAssetMetadata(assetId, metadata);
2032
2030
  this.metaFlock.put(["a", assetId], assetMetaToJson(metadata));
2033
2031
  created = true;
@@ -2035,9 +2033,7 @@ var AssetManager = class {
2035
2033
  const mapping = this.docAssets.get(docId) ?? /* @__PURE__ */ new Map();
2036
2034
  mapping.set(assetId, metadata);
2037
2035
  this.docAssets.set(docId, mapping);
2038
- const refs = this.assetToDocRefs.get(assetId) ?? /* @__PURE__ */ new Set();
2039
- refs.add(docId);
2040
- this.assetToDocRefs.set(assetId, refs);
2036
+ this.addDocReference(assetId, docId);
2041
2037
  this.metaFlock.put([
2042
2038
  "ld",
2043
2039
  docId,
@@ -2067,20 +2063,7 @@ var AssetManager = class {
2067
2063
  docId,
2068
2064
  assetId
2069
2065
  ]);
2070
- const refs = this.assetToDocRefs.get(assetId);
2071
- if (refs) {
2072
- refs.delete(docId);
2073
- if (refs.size === 0) {
2074
- this.assetToDocRefs.delete(assetId);
2075
- const record = this.assets.get(assetId);
2076
- if (record) this.orphanedAssets.set(assetId, {
2077
- metadata: record.metadata,
2078
- deletedAt: Date.now()
2079
- });
2080
- this.metaFlock.delete(["a", assetId]);
2081
- this.assets.delete(assetId);
2082
- }
2083
- }
2066
+ this.removeDocAssetReference(assetId, docId);
2084
2067
  await this.persistMeta();
2085
2068
  this.eventBus.emit({
2086
2069
  kind: "asset-unlink",
@@ -2167,12 +2150,11 @@ var AssetManager = class {
2167
2150
  this.handleAssetRemoval(assetId, by);
2168
2151
  return;
2169
2152
  }
2170
- const existingData = previous?.data;
2171
- this.rememberAsset(metadata, existingData);
2153
+ this.rememberAsset(metadata);
2172
2154
  this.updateDocAssetMetadata(assetId, cloneRepoAssetMetadata(metadata));
2173
2155
  if (!previous || !assetMetadataEqual(previous.metadata, metadata)) this.eventBus.emit({
2174
2156
  kind: "asset-metadata",
2175
- asset: this.createAssetDownload(assetId, metadata, existingData),
2157
+ asset: this.createAssetDownload(assetId, metadata),
2176
2158
  by
2177
2159
  });
2178
2160
  }
@@ -2187,11 +2169,7 @@ var AssetManager = class {
2187
2169
  if (typeof assetId !== "string") continue;
2188
2170
  const metadata = assetMetaFromJson(row.value);
2189
2171
  if (!metadata) continue;
2190
- const existing = this.assets.get(assetId);
2191
- nextAssets.set(assetId, {
2192
- metadata,
2193
- data: existing?.data
2194
- });
2172
+ nextAssets.set(assetId, { metadata });
2195
2173
  }
2196
2174
  const nextDocAssets = /* @__PURE__ */ new Map();
2197
2175
  const linkRows = this.metaFlock.scan({ prefix: ["ld"] });
@@ -2227,12 +2205,18 @@ var AssetManager = class {
2227
2205
  this.assetToDocRefs.set(assetId, refs);
2228
2206
  }
2229
2207
  this.assets.clear();
2230
- for (const record of nextAssets.values()) this.rememberAsset(record.metadata, record.data);
2208
+ for (const record of nextAssets.values()) this.rememberAsset(record.metadata);
2209
+ for (const assetId of nextAssets.keys()) {
2210
+ const refs = this.assetToDocRefs.get(assetId);
2211
+ if (!refs || refs.size === 0) {
2212
+ if (!this.orphanedAssets.has(assetId)) this.markAssetAsOrphan(assetId, nextAssets.get(assetId).metadata);
2213
+ } else this.orphanedAssets.delete(assetId);
2214
+ }
2231
2215
  for (const [assetId, record] of nextAssets) {
2232
2216
  const previous = prevAssets.get(assetId)?.metadata;
2233
2217
  if (!assetMetadataEqual(previous, record.metadata)) this.eventBus.emit({
2234
2218
  kind: "asset-metadata",
2235
- asset: this.createAssetDownload(assetId, record.metadata, record.data),
2219
+ asset: this.createAssetDownload(assetId, record.metadata),
2236
2220
  by
2237
2221
  });
2238
2222
  }
@@ -2328,36 +2312,24 @@ var AssetManager = class {
2328
2312
  };
2329
2313
  }
2330
2314
  async materializeAsset(assetId) {
2331
- let record = this.assets.get(assetId);
2332
- if (record?.data) return {
2333
- metadata: record.metadata,
2334
- bytes: record.data.slice()
2335
- };
2315
+ const record = this.assets.get(assetId);
2336
2316
  if (record && this.storage) {
2337
2317
  const stored = await this.storage.loadAsset(assetId);
2338
- if (stored) {
2339
- const clone = stored.slice();
2340
- record.data = clone.slice();
2341
- return {
2342
- metadata: record.metadata,
2343
- bytes: clone
2344
- };
2345
- }
2318
+ if (stored) return {
2319
+ metadata: record.metadata,
2320
+ bytes: stored
2321
+ };
2346
2322
  }
2347
2323
  if (!record && this.storage) {
2348
2324
  const stored = await this.storage.loadAsset(assetId);
2349
2325
  if (stored) {
2350
2326
  const metadata$1 = this.getAssetMetadata(assetId);
2351
2327
  if (!metadata$1) throw new Error(`Missing metadata for asset ${assetId}`);
2352
- const clone = stored.slice();
2353
- this.assets.set(assetId, {
2354
- metadata: metadata$1,
2355
- data: clone.slice()
2356
- });
2328
+ this.assets.set(assetId, { metadata: metadata$1 });
2357
2329
  this.updateDocAssetMetadata(assetId, metadata$1);
2358
2330
  return {
2359
2331
  metadata: metadata$1,
2360
- bytes: clone
2332
+ bytes: stored
2361
2333
  };
2362
2334
  }
2363
2335
  }
@@ -2373,10 +2345,7 @@ var AssetManager = class {
2373
2345
  ...remote.policy ? { policy: remote.policy } : {},
2374
2346
  ...remote.tag ? { tag: remote.tag } : {}
2375
2347
  };
2376
- this.assets.set(assetId, {
2377
- metadata,
2378
- data: remoteBytes.slice()
2379
- });
2348
+ this.assets.set(assetId, { metadata });
2380
2349
  this.updateDocAssetMetadata(assetId, metadata);
2381
2350
  this.metaFlock.put(["a", assetId], assetMetaToJson(metadata));
2382
2351
  await this.persistMeta();
@@ -2398,18 +2367,14 @@ var AssetManager = class {
2398
2367
  if (assets) assets.set(assetId, metadata);
2399
2368
  }
2400
2369
  }
2401
- rememberAsset(metadata, bytes) {
2402
- const data = bytes ? bytes.slice() : this.assets.get(metadata.assetId)?.data;
2403
- this.assets.set(metadata.assetId, {
2404
- metadata,
2405
- data
2406
- });
2407
- this.orphanedAssets.delete(metadata.assetId);
2370
+ rememberAsset(metadata) {
2371
+ this.assets.set(metadata.assetId, { metadata });
2408
2372
  }
2409
2373
  addDocReference(assetId, docId) {
2410
2374
  const refs = this.assetToDocRefs.get(assetId) ?? /* @__PURE__ */ new Set();
2411
2375
  refs.add(docId);
2412
2376
  this.assetToDocRefs.set(assetId, refs);
2377
+ this.orphanedAssets.delete(assetId);
2413
2378
  }
2414
2379
  removeDocAssetReference(assetId, docId) {
2415
2380
  const refs = this.assetToDocRefs.get(assetId);