@comapeo/core 2.1.0 → 2.2.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.
Files changed (73) hide show
  1. package/dist/blob-store/downloader.d.ts +43 -0
  2. package/dist/blob-store/downloader.d.ts.map +1 -0
  3. package/dist/blob-store/entries-stream.d.ts +13 -0
  4. package/dist/blob-store/entries-stream.d.ts.map +1 -0
  5. package/dist/blob-store/hyperdrive-index.d.ts +20 -0
  6. package/dist/blob-store/hyperdrive-index.d.ts.map +1 -0
  7. package/dist/blob-store/index.d.ts +29 -21
  8. package/dist/blob-store/index.d.ts.map +1 -1
  9. package/dist/blob-store/utils.d.ts +27 -0
  10. package/dist/blob-store/utils.d.ts.map +1 -0
  11. package/dist/core-manager/index.d.ts +1 -1
  12. package/dist/core-manager/index.d.ts.map +1 -1
  13. package/dist/core-ownership.d.ts.map +1 -1
  14. package/dist/datastore/index.d.ts +1 -1
  15. package/dist/datastore/index.d.ts.map +1 -1
  16. package/dist/datatype/index.d.ts +5 -1
  17. package/dist/discovery/local-discovery.d.ts.map +1 -1
  18. package/dist/errors.d.ts +6 -1
  19. package/dist/errors.d.ts.map +1 -1
  20. package/dist/fastify-plugins/blobs.d.ts.map +1 -1
  21. package/dist/fastify-plugins/maps.d.ts.map +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/lib/error.d.ts +14 -0
  24. package/dist/lib/error.d.ts.map +1 -1
  25. package/dist/mapeo-manager.d.ts.map +1 -1
  26. package/dist/mapeo-project.d.ts +17 -17
  27. package/dist/mapeo-project.d.ts.map +1 -1
  28. package/dist/member-api.d.ts +4 -0
  29. package/dist/member-api.d.ts.map +1 -1
  30. package/dist/roles.d.ts.map +1 -1
  31. package/dist/schema/project.d.ts +2 -2
  32. package/dist/sync/core-sync-state.d.ts +20 -15
  33. package/dist/sync/core-sync-state.d.ts.map +1 -1
  34. package/dist/sync/namespace-sync-state.d.ts +13 -1
  35. package/dist/sync/namespace-sync-state.d.ts.map +1 -1
  36. package/dist/sync/peer-sync-controller.d.ts +1 -1
  37. package/dist/sync/sync-api.d.ts +22 -3
  38. package/dist/sync/sync-api.d.ts.map +1 -1
  39. package/dist/sync/sync-state.d.ts +12 -0
  40. package/dist/sync/sync-state.d.ts.map +1 -1
  41. package/dist/translation-api.d.ts +2 -2
  42. package/dist/translation-api.d.ts.map +1 -1
  43. package/dist/types.d.ts +7 -0
  44. package/dist/types.d.ts.map +1 -1
  45. package/package.json +6 -1
  46. package/src/blob-store/downloader.js +130 -0
  47. package/src/blob-store/entries-stream.js +81 -0
  48. package/src/blob-store/hyperdrive-index.js +122 -0
  49. package/src/blob-store/index.js +56 -115
  50. package/src/blob-store/utils.js +54 -0
  51. package/src/core-manager/index.js +2 -1
  52. package/src/core-ownership.js +2 -4
  53. package/src/datastore/index.js +4 -3
  54. package/src/datatype/index.d.ts +5 -1
  55. package/src/datatype/index.js +22 -9
  56. package/src/discovery/local-discovery.js +2 -1
  57. package/src/errors.js +11 -2
  58. package/src/fastify-plugins/blobs.js +16 -1
  59. package/src/fastify-plugins/maps.js +2 -1
  60. package/src/lib/error.js +24 -0
  61. package/src/mapeo-manager.js +3 -2
  62. package/src/mapeo-project.js +89 -19
  63. package/src/member-api.js +68 -26
  64. package/src/roles.js +38 -32
  65. package/src/sync/core-sync-state.js +39 -23
  66. package/src/sync/namespace-sync-state.js +22 -0
  67. package/src/sync/sync-api.js +30 -4
  68. package/src/sync/sync-state.js +18 -0
  69. package/src/translation-api.js +5 -9
  70. package/src/types.ts +8 -0
  71. package/dist/blob-store/live-download.d.ts +0 -107
  72. package/dist/blob-store/live-download.d.ts.map +0 -1
  73. package/src/blob-store/live-download.js +0 -373
@@ -118,7 +118,7 @@ export const translationTable: import("drizzle-orm/sqlite-core").SQLiteTableWith
118
118
  tableName: "translation";
119
119
  dataType: "string";
120
120
  columnType: "SQLiteText";
121
- data: "UNRECOGNIZED" | "observation" | "track" | "preset" | "field" | "projectSettings" | "deviceInfo" | "role" | "type_unspecified";
121
+ data: "track" | "role" | "projectSettings" | "preset" | "observation" | "field" | "deviceInfo" | "UNRECOGNIZED" | "type_unspecified";
122
122
  driverParam: string;
123
123
  notNull: true;
124
124
  hasDefault: false;
@@ -2009,7 +2009,7 @@ export const coresTable: import("drizzle-orm/sqlite-core").SQLiteTableWithColumn
2009
2009
  tableName: "cores";
2010
2010
  dataType: "string";
2011
2011
  columnType: "SQLiteText";
2012
- data: "blob" | "auth" | "config" | "data" | "blobIndex";
2012
+ data: "auth" | "config" | "data" | "blobIndex" | "blob";
2013
2013
  driverParam: string;
2014
2014
  notNull: true;
2015
2015
  hasDefault: false;
@@ -112,12 +112,16 @@ export class CoreSyncState {
112
112
  * blocks/ranges that are added here
113
113
  *
114
114
  * @param {PeerId} peerId
115
- * @param {Array<{ start: number, length: number }>} ranges
115
+ * @param {number} start
116
+ * @param {number} length
117
+ * @returns {void}
118
+ */
119
+ addWantRange(peerId: PeerId, start: number, length: number): void;
120
+ /**
121
+ * @param {PeerId} peerId
122
+ * @returns {void}
116
123
  */
117
- setPeerWants(peerId: PeerId, ranges: Array<{
118
- start: number;
119
- length: number;
120
- }>): void;
124
+ clearWantRanges(peerId: PeerId): void;
121
125
  /**
122
126
  * @param {PeerId} peerId
123
127
  */
@@ -138,9 +142,6 @@ export class CoreSyncState {
138
142
  * Only exported for testing
139
143
  */
140
144
  export class PeerState {
141
- constructor({ wantAll }?: {
142
- wantAll?: boolean | undefined;
143
- });
144
145
  /** @type {PeerNamespaceState['status']} */
145
146
  status: PeerNamespaceState["status"];
146
147
  get preHavesBitfield(): RemoteBitfield;
@@ -154,18 +155,22 @@ export class PeerState {
154
155
  */
155
156
  setHavesBitfield(bitfield: HypercoreRemoteBitfield): void;
156
157
  /**
157
- * Set a range of blocks that a peer wants. This is not part of the Hypercore
158
+ * Add a range of blocks that a peer wants. This is not part of the Hypercore
158
159
  * protocol, so we need our own extension messages that a peer can use to
159
160
  * inform us which blocks they are interested in. For most cores peers always
160
- * want all blocks, but for blob cores often peers only want preview or
161
+ * want all blocks, but for blob cores peers may only want preview or
161
162
  * thumbnail versions of media
162
163
  *
163
- * @param {{ start: number, length: number }} range
164
+ * @param {number} start
165
+ * @param {number} length
166
+ * @returns {void}
167
+ */
168
+ addWantRange(start: number, length: number): void;
169
+ /**
170
+ * Set the range of blocks that this peer wants to the empty set. In other
171
+ * words, this peer wants nothing from this core.
164
172
  */
165
- setWantRange({ start, length }: {
166
- start: number;
167
- length: number;
168
- }): void;
173
+ clearWantRanges(): void;
169
174
  /**
170
175
  * Returns whether the peer has the block at `index`. If a pre-have bitfield
171
176
  * has been passed, this is used if no connected peer bitfield is available.
@@ -1 +1 @@
1
- {"version":3,"file":"core-sync-state.d.ts","sourceRoot":"","sources":["../../src/sync/core-sync-state.js"],"names":[],"mappings":"AAwXA;;;;;;;GAOG;AACH,uCALW,aAAa;;;;EA6DvB;AAED;;;;GAIG;AACH,8BAFW,MAAM,UAMhB;AA9bD,uFAAuF;AAEvF;;GAEG;AACH;;GAEG;AACH;;;;;;;GAOG;AACH;;;;;GAKG;AACH;;;;;;GAMG;AACH;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IAaE;;;;;;OAMG;IACH,kEALG;QAAyB,QAAQ,EAAzB,MAAM,IAAI;QACgE,mBAAmB,EAA7F,GAAG,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,kBAAkB,CAAC;QACnD,SAAS,EAAzB,SAAS;QACK,MAAM;KAAC,EAY/B;IAEU,YAAM,YAAY,CAAA;IAY7B;;;;;;OAMG;IACH,iBAFW,OAAO,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,QAiC/C;IAED;;;;;;;;OAQG;IACH,uBAJW,MAAM,SACN,MAAM,YACN,WAAW,QAsBrB;IAED;;;;;;;OAOG;IACH,qBAHW,MAAM,UACN,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,QAQlD;IAED;;OAEG;IACH,gBAFW,MAAM,QAMhB;IAED;;OAEG;IACH,uBAFW,MAAM,QAOhB;;CAkEF;AAED;;;;;;;;GAQG;AACH;IAUE;;OAEC;IALD,2CAA2C;IAC3C,QADW,kBAAkB,CAAC,QAAQ,CAAC,CACrB;IAKlB,uCAEC;IACD;;;OAGG;IACH,sBAHW,MAAM,YACN,WAAW,WAIrB;IACD;;OAEG;IACH,2BAFW,uBAAuB,QAIjC;IACD;;;;;;;;OAQG;IACH,gCAFW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,QAK3C;IACD;;;;;OAKG;IACH,YAFW,MAAM,WAIhB;IACD;;;;;;OAMG;IACH,gBAJW,MAAM,GACJ,MAAM,CAOlB;IACD;;;;OAIG;IACH,YAFW,MAAM,WAKhB;IACD;;;;;;OAMG;IACH,gBAJW,MAAM,GACJ,MAAM,CASlB;;CACF;uBA9WY,cAAc;qBAGd,MAAM;;;;;YAIL,MAAM,GAAG,SAAS;gBAClB,SAAS;kBACT,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;yBACtB,GAAG,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,kBAAkB,CAAC;eACnE,SAAS;;;;;;UAIT,MAAM;;;;UACN,MAAM;;;;YACN,MAAM;;;;;;UAIN,MAAM;;;;UACN,MAAM;;;;YACN,MAAM;YACN,SAAS,GAAG,UAAU,GAAG,SAAS;;;;;;gBAIlC,MAAM;;;;gBACN,cAAc;;;;kBACd,GAAG,MAAgB,IAAN,MAAM,GAAG,kBAAkB,GAAE;;+BAjCe,aAAa;uBAD7D,cAAc;2BAD9B,oCAAoC;6CAE4B,aAAa"}
1
+ {"version":3,"file":"core-sync-state.d.ts","sourceRoot":"","sources":["../../src/sync/core-sync-state.js"],"names":[],"mappings":"AAwYA;;;;;;;GAOG;AACH,uCALW,aAAa;;;;EA6DvB;AAED;;;;GAIG;AACH,8BAFW,MAAM,UAMhB;AA9cD,uFAAuF;AAEvF;;GAEG;AACH;;GAEG;AACH;;;;;;;GAOG;AACH;;;;;GAKG;AACH;;;;;;GAMG;AACH;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IAaE;;;;;;OAMG;IACH,kEALG;QAAyB,QAAQ,EAAzB,MAAM,IAAI;QACgE,mBAAmB,EAA7F,GAAG,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,kBAAkB,CAAC;QACnD,SAAS,EAAzB,SAAS;QACK,MAAM;KAAC,EAY/B;IAEU,YAAM,YAAY,CAAA;IAY7B;;;;;;OAMG;IACH,iBAFW,OAAO,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,QAiC/C;IAED;;;;;;;;OAQG;IACH,uBAJW,MAAM,SACN,MAAM,YACN,WAAW,QAsBrB;IAED;;;;;;;;;OASG;IACH,qBALW,MAAM,SACN,MAAM,UACN,MAAM,GACJ,IAAI,CAMhB;IAED;;;OAGG;IACH,wBAHW,MAAM,GACJ,IAAI,CAMhB;IAED;;OAEG;IACH,gBAFW,MAAM,QAMhB;IAED;;OAEG;IACH,uBAFW,MAAM,QAOhB;;CAkEF;AAED;;;;;;;;GAQG;AACH;IAUE,2CAA2C;IAC3C,QADW,kBAAkB,CAAC,QAAQ,CAAC,CACrB;IAClB,uCAEC;IACD;;;OAGG;IACH,sBAHW,MAAM,YACN,WAAW,WAIrB;IACD;;OAEG;IACH,2BAFW,uBAAuB,QAIjC;IACD;;;;;;;;;;OAUG;IACH,oBAJW,MAAM,UACN,MAAM,GACJ,IAAI,CAKhB;IACD;;;OAGG;IACH,wBAEC;IACD;;;;;OAKG;IACH,YAFW,MAAM,WAIhB;IACD;;;;;;OAMG;IACH,gBAJW,MAAM,GACJ,MAAM,CAOlB;IACD;;;;OAIG;IACH,YAFW,MAAM,WAIhB;IACD;;;;;;OAMG;IACH,gBAJW,MAAM,GACJ,MAAM,CAQlB;;CACF;uBA9XY,cAAc;qBAGd,MAAM;;;;;YAIL,MAAM,GAAG,SAAS;gBAClB,SAAS;kBACT,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;yBACtB,GAAG,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,kBAAkB,CAAC;eACnE,SAAS;;;;;;UAIT,MAAM;;;;UACN,MAAM;;;;YACN,MAAM;;;;;;UAIN,MAAM;;;;UACN,MAAM;;;;YACN,MAAM;YACN,SAAS,GAAG,UAAU,GAAG,SAAS;;;;;;gBAIlC,MAAM;;;;gBACN,cAAc;;;;kBACd,GAAG,MAAgB,IAAN,MAAM,GAAG,kBAAkB,GAAE;;+BAjCe,aAAa;uBAD7D,cAAc;2BAD9B,oCAAoC;6CAE4B,aAAa"}
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * @template {Namespace} [TNamespace=Namespace]
7
7
  */
8
- export class NamespaceSyncState<TNamespace extends Namespace = "blob" | "auth" | "config" | "data" | "blobIndex"> {
8
+ export class NamespaceSyncState<TNamespace extends Namespace = "auth" | "config" | "data" | "blobIndex" | "blob"> {
9
9
  /**
10
10
  * @param {object} opts
11
11
  * @param {TNamespace} opts.namespace
@@ -32,6 +32,18 @@ export class NamespaceSyncState<TNamespace extends Namespace = "blob" | "auth" |
32
32
  * @param {string} peerId
33
33
  */
34
34
  disconnectPeer(peerId: string): void;
35
+ /**
36
+ * @param {string} peerId
37
+ * @param {number} start
38
+ * @param {number} length
39
+ * @returns {void}
40
+ */
41
+ addWantRange(peerId: string, start: number, length: number): void;
42
+ /**
43
+ * @param {string} peerId
44
+ * @returns {void}
45
+ */
46
+ clearWantRanges(peerId: string): void;
35
47
  #private;
36
48
  }
37
49
  export type SyncState = Omit<import("./core-sync-state.js").DerivedState, "coreLength"> & {
@@ -1 +1 @@
1
- {"version":3,"file":"namespace-sync-state.d.ts","sourceRoot":"","sources":["../../src/sync/namespace-sync-state.js"],"names":[],"mappings":"AAGA,+CAA+C;AAE/C;;GAEG;AAEH;;GAEG;AACH,gCAF0B,UAAU,SAAvB,SAAW;IAatB;;;;;;;OAOG;IACH,gFANG;QAAyB,SAAS,EAA1B,UAAU;QAC2C,WAAW,EAAhE,OAAO,0BAA0B,EAAE,WAAW;QAC7B,QAAQ,EAAzB,MAAM,IAAI;QACgE,mBAAmB,EAA7F,GAAG,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,kBAAkB,CAAC;QACrD,MAAM;KAAC,EAiC/B;IAED,4BAEC;IAED,2BAA2B;IAC3B,YADc,SAAS,CA4BtB;IAED;;OAEG;IACH,gBAFW,MAAM,QAMhB;IAED;;OAEG;IACH,uBAFW,MAAM,QAMhB;;CA2CF;wBAvJY,IAAI,CAAC,OAAO,sBAAsB,EAAE,YAAY,EAAE,YAAY,CAAC,GAAG;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;+BAH1F,aAAa;uBAHrB,cAAc"}
1
+ {"version":3,"file":"namespace-sync-state.d.ts","sourceRoot":"","sources":["../../src/sync/namespace-sync-state.js"],"names":[],"mappings":"AAGA,+CAA+C;AAE/C;;GAEG;AAEH;;GAEG;AACH,gCAF0B,UAAU,SAAvB,SAAW;IAatB;;;;;;;OAOG;IACH,gFANG;QAAyB,SAAS,EAA1B,UAAU;QAC2C,WAAW,EAAhE,OAAO,0BAA0B,EAAE,WAAW;QAC7B,QAAQ,EAAzB,MAAM,IAAI;QACgE,mBAAmB,EAA7F,GAAG,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,kBAAkB,CAAC;QACrD,MAAM;KAAC,EAiC/B;IAED,4BAEC;IAED,2BAA2B;IAC3B,YADc,SAAS,CA4BtB;IAED;;OAEG;IACH,gBAFW,MAAM,QAMhB;IAED;;OAEG;IACH,uBAFW,MAAM,QAMhB;IAwBD;;;;;OAKG;IACH,qBALW,MAAM,SACN,MAAM,UACN,MAAM,GACJ,IAAI,CAMhB;IAED;;;OAGG;IACH,wBAHW,MAAM,GACJ,IAAI,CAMhB;;CAqBF;wBA7KY,IAAI,CAAC,OAAO,sBAAsB,EAAE,YAAY,EAAE,YAAY,CAAC,GAAG;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;+BAH1F,aAAa;uBAHrB,cAAc"}
@@ -24,7 +24,7 @@ export class PeerSyncController {
24
24
  });
25
25
  get peerKey(): Buffer;
26
26
  get peerId(): string;
27
- get syncCapability(): Record<"blob" | "auth" | "config" | "data" | "blobIndex", SyncCapability>;
27
+ get syncCapability(): Record<"auth" | "config" | "data" | "blobIndex" | "blob", SyncCapability>;
28
28
  /** @param {SyncEnabledState} syncEnabledState */
29
29
  setSyncEnabledState(syncEnabledState: SyncEnabledState): void;
30
30
  /**
@@ -2,13 +2,15 @@
2
2
  /** @import * as http from 'node:http' */
3
3
  /** @import { CoreOwnership } from '../core-ownership.js' */
4
4
  /** @import { OpenedNoiseStream } from '../lib/noise-secret-stream-helpers.js' */
5
- /** @import { ReplicationStream } from '../types.js' */
5
+ /** @import { BlobFilter, ReplicationStream } from '../types.js' */
6
6
  export const kHandleDiscoveryKey: unique symbol;
7
7
  export const kSyncState: unique symbol;
8
8
  export const kRequestFullStop: unique symbol;
9
9
  export const kRescindFullStopRequest: unique symbol;
10
10
  export const kWaitForInitialSyncWithPeer: unique symbol;
11
11
  export const kSetBlobDownloadFilter: unique symbol;
12
+ export const kAddBlobWantRange: unique symbol;
13
+ export const kClearBlobWantRanges: unique symbol;
12
14
  /**
13
15
  * @typedef {'initial' | 'full'} SyncType
14
16
  */
@@ -49,7 +51,7 @@ export class SyncApi extends TypedEmitter<SyncEvents> {
49
51
  * @param {import('../roles.js').Roles} opts.roles
50
52
  * @param {() => Promise<Iterable<string>>} opts.getServerWebsocketUrls
51
53
  * @param {() => ReplicationStream} opts.getReplicationStream
52
- * @param {import('../types.js').BlobFilter | null} opts.blobDownloadFilter
54
+ * @param {null | BlobFilter} opts.blobDownloadFilter
53
55
  * @param {number} [opts.throttleMs]
54
56
  * @param {Logger} [opts.logger]
55
57
  */
@@ -59,7 +61,7 @@ export class SyncApi extends TypedEmitter<SyncEvents> {
59
61
  roles: import("../roles.js").Roles;
60
62
  getServerWebsocketUrls: () => Promise<Iterable<string>>;
61
63
  getReplicationStream: () => ReplicationStream;
62
- blobDownloadFilter: import("../types.js").BlobFilter | null;
64
+ blobDownloadFilter: null | BlobFilter;
63
65
  throttleMs?: number | undefined;
64
66
  logger?: Logger | undefined;
65
67
  });
@@ -108,6 +110,22 @@ export class SyncApi extends TypedEmitter<SyncEvents> {
108
110
  waitForSync(type: SyncType): Promise<void>;
109
111
  /** @param {import('../types.js').BlobFilter | null} blobDownloadFilter */
110
112
  [kSetBlobDownloadFilter](blobDownloadFilter: import("../types.js").BlobFilter | null): void;
113
+ /**
114
+ * Add some blob blocks this peer wants.
115
+ *
116
+ * @param {string} peerId
117
+ * @param {number} start
118
+ * @param {number} length
119
+ * @returns {void}
120
+ */
121
+ [kAddBlobWantRange](peerId: string, start: number, length: number): void;
122
+ /**
123
+ * Clear the blob blocks this peer wants.
124
+ *
125
+ * @param {string} peerId
126
+ * @returns {void}
127
+ */
128
+ [kClearBlobWantRanges](peerId: string): void;
111
129
  [kHandleDiscoveryKey](discoveryKey: Buffer, protomux: import("protomux")<import("@hyperswarm/secret-stream")>): void;
112
130
  /**
113
131
  * Request a graceful stop to all sync.
@@ -180,5 +198,6 @@ import { TypedEmitter } from 'tiny-typed-emitter';
180
198
  import { SyncState } from './sync-state.js';
181
199
  import type { CoreOwnership } from '../core-ownership.js';
182
200
  import type { ReplicationStream } from '../types.js';
201
+ import type { BlobFilter } from '../types.js';
183
202
  import { Logger } from '../logger.js';
184
203
  //# sourceMappingURL=sync-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync-api.d.ts","sourceRoot":"","sources":["../../src/sync/sync-api.js"],"names":[],"mappings":"AAcA,2EAA2E;AAC3E,yCAAyC;AACzC,4DAA4D;AAC5D,iFAAiF;AACjF,uDAAuD;AAEvD,gDAAiE;AACjE,uCAA8C;AAC9C,6CAAoD;AACpD,oDAA2D;AAC3D,wDAEC;AACD,mDAAmE;AAEnE;;GAEG;AAEH;;GAEG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;GAKG;AAEH;;;GAGG;AAEH;;GAEG;AACH;IA4BE;;;;;;;;;;OAUG;IACH,0IATG;QAA6D,WAAW,EAAhE,OAAO,0BAA0B,EAAE,WAAW;QAC1B,aAAa,EAAjC,aAAa;QACqB,KAAK,EAAvC,OAAO,aAAa,EAAE,KAAK;QACW,sBAAsB,EAA5D,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACD,oBAAoB,EAAlD,MAAM,iBAAiB;QACuB,kBAAkB,EAAhE,OAAO,aAAa,EAAE,UAAU,GAAG,IAAI;QACzB,UAAU;QACV,MAAM;KAAC,EAgD/B;IAuCD;;;OAGG;IACH,YAFa,KAAK,CAIjB;IAqHD;;OAEG;IACH,kBAFa,IAAI,CAsDhB;IAED;;OAEG;IACH,qBAFa,IAAI,CAQhB;IAED;;;;;;;;;;OAUG;IACH;;yBAOC;IAED;;;;OAIG;IACH,aAGC;IAkBD;;;OAGG;IACH,kDAHW,IAAI,GAAG,MAAM,GACX,IAAI,CAOhB;IAED;;;OAGG;IACH,kBAHW,QAAQ,GACN,OAAO,CAAC,IAAI,CAAC,CAazB;IA5SD,0EAA0E;IAC1E,6CADY,OAAO,aAAa,EAAE,UAAU,GAAG,IAAI,QAOlD;oFA8E4E,2BACtD;IA4KvB;;OAEG;IACH,2BAGC;IAED;;OAEG;IACH,kCAGC;IA8BD;;;;OAIG;IACH,wCAJW,MAAM,eACN,WAAW,GACT,OAAO,CAAC,IAAI,CAAC,CA6BzB;IA5WC,wBAKE;;CAyfL;uBA5lBY,SAAS,GAAG,MAAM;+BAIlB,MAAM,GAAG,SAAS,GAAG,KAAK;;;;;mBAMzB,OAAO;;;;UACP,MAAM;;;;YACN,MAAM;;;;;;;;;aAMN,mCAAmC;;;;UACnC,mCAAmC;;;;;;aAKnC;QAAE,aAAa,EAAE,OAAO,CAAA;KAAE;;;;UAC1B;QAAE,aAAa,EAAE,OAAO,CAAA;KAAE;;;;2BAC1B,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC;;;kBAKrC,CAAC,SAAS,EAAE,KAAK,KAAK,IAAI;;6BA7DX,oBAAoB;0BAEvB,iBAAiB;mCAcR,sBAAsB;uCAElB,aAAa;uBAd7B,cAAc"}
1
+ {"version":3,"file":"sync-api.d.ts","sourceRoot":"","sources":["../../src/sync/sync-api.js"],"names":[],"mappings":"AAcA,2EAA2E;AAC3E,yCAAyC;AACzC,4DAA4D;AAC5D,iFAAiF;AACjF,mEAAmE;AAEnE,gDAAiE;AACjE,uCAA8C;AAC9C,6CAAoD;AACpD,oDAA2D;AAC3D,wDAEC;AACD,mDAAmE;AACnE,8CAA8D;AAC9D,iDAAoE;AAEpE;;GAEG;AAEH;;GAEG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;GAKG;AAEH;;;GAGG;AAEH;;GAEG;AACH;IA6BE;;;;;;;;;;OAUG;IACH,0IATG;QAA6D,WAAW,EAAhE,OAAO,0BAA0B,EAAE,WAAW;QAC1B,aAAa,EAAjC,aAAa;QACqB,KAAK,EAAvC,OAAO,aAAa,EAAE,KAAK;QACW,sBAAsB,EAA5D,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACD,oBAAoB,EAAlD,MAAM,iBAAiB;QACC,kBAAkB,EAA1C,IAAI,GAAG,UAAU;QACH,UAAU;QACV,MAAM;KAAC,EAiD/B;IA6DD;;;OAGG;IACH,YAFa,KAAK,CAIjB;IAqHD;;OAEG;IACH,kBAFa,IAAI,CAsDhB;IAED;;OAEG;IACH,qBAFa,IAAI,CAQhB;IAED;;;;;;;;;;OAUG;IACH;;yBAOC;IAED;;;;OAIG;IACH,aAGC;IAkBD;;;OAGG;IACH,kDAHW,IAAI,GAAG,MAAM,GACX,IAAI,CAOhB;IAED;;;OAGG;IACH,kBAHW,QAAQ,GACN,OAAO,CAAC,IAAI,CAAC,CAazB;IAlUD,0EAA0E;IAC1E,6CADY,OAAO,aAAa,EAAE,UAAU,GAAG,IAAI,QAOlD;IAED;;;;;;;OAOG;IACH,4BALW,MAAM,SACN,MAAM,UACN,MAAM,GACJ,IAAI,CAIhB;IAED;;;;;OAKG;IACH,+BAHW,MAAM,GACJ,IAAI,CAIhB;oFA0Da,2BACf;IAgMC;;OAEG;IACH,2BAGC;IAED;;OAEG;IACH,kCAGC;IA8BD;;;;OAIG;IACH,wCAJW,MAAM,eACN,WAAW,GACT,OAAO,CAAC,IAAI,CAAC,CA6BzB;IApYC,wBAKE;;CAihBL;uBApnBY,SAAS,GAAG,MAAM;+BAIlB,MAAM,GAAG,SAAS,GAAG,KAAK;;;;;mBAMzB,OAAO;;;;UACP,MAAM;;;;YACN,MAAM;;;;;;;;;aAMN,mCAAmC;;;;UACnC,mCAAmC;;;;;;aAKnC;QAAE,aAAa,EAAE,OAAO,CAAA;KAAE;;;;UAC1B;QAAE,aAAa,EAAE,OAAO,CAAA;KAAE;;;;2BAC1B,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC;;;kBAKrC,CAAC,SAAS,EAAE,KAAK,KAAK,IAAI;;6BA/DX,oBAAoB;0BAEvB,iBAAiB;mCAcR,sBAAsB;uCAEN,aAAa;gCAAb,aAAa;uBAdzC,cAAc"}
@@ -38,6 +38,18 @@ export class SyncState extends TypedEmitter<{
38
38
  * @returns {State}
39
39
  */
40
40
  getState(): State;
41
+ /**
42
+ * @param {string} peerId
43
+ * @param {number} start
44
+ * @param {number} length
45
+ * @returns {void}
46
+ */
47
+ addBlobWantRange(peerId: string, start: number, length: number): void;
48
+ /**
49
+ * @param {string} peerId
50
+ * @returns {void}
51
+ */
52
+ clearBlobWantRanges(peerId: string): void;
41
53
  #private;
42
54
  }
43
55
  export type State = Record<Namespace, import("./namespace-sync-state.js").SyncState>;
@@ -1 +1 @@
1
- {"version":3,"file":"sync-state.d.ts","sourceRoot":"","sources":["../../src/sync/sync-state.js"],"names":[],"mappings":"AAKA,+CAA+C;AAE/C;;;;;GAKG;AAEH;;;GAGG;AACH;WAFmC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;;IAIvD;;;;;;;OAOG;IACH,sEALG;QAA6D,WAAW,EAAhE,OAAO,0BAA0B,EAAE,WAAW;QAC4B,mBAAmB,EAA7F,GAAG,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,kBAAkB,CAAC;QACrD,UAAU;QACa,MAAM;KAAC,EActD;IAED;;OAEG;IACH,gBAFW,MAAM,QAMhB;IAED;;OAEG;IACH,uBAFW,MAAM,QAMhB;IAED;;OAEG;IACH,YAFa,KAAK,CAOjB;;CAKF;oBAjEY,MAAM,CAClB,SAAY,EACZ,OAAU,2BAA2B,EAAE,SAAS,CAC7C;6BAXyB,oBAAoB;+BAKlB,aAAa"}
1
+ {"version":3,"file":"sync-state.d.ts","sourceRoot":"","sources":["../../src/sync/sync-state.js"],"names":[],"mappings":"AAKA,+CAA+C;AAE/C;;;;;GAKG;AAEH;;;GAGG;AACH;WAFmC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;;IAIvD;;;;;;;OAOG;IACH,sEALG;QAA6D,WAAW,EAAhE,OAAO,0BAA0B,EAAE,WAAW;QAC4B,mBAAmB,EAA7F,GAAG,CAAC,MAAM,EAAE,OAAO,2BAA2B,EAAE,kBAAkB,CAAC;QACrD,UAAU;QACa,MAAM;KAAC,EActD;IAED;;OAEG;IACH,gBAFW,MAAM,QAMhB;IAED;;OAEG;IACH,uBAFW,MAAM,QAMhB;IAED;;OAEG;IACH,YAFa,KAAK,CAOjB;IAED;;;;;OAKG;IACH,yBALW,MAAM,SACN,MAAM,UACN,MAAM,GACJ,IAAI,CAIhB;IAED;;;OAGG;IACH,4BAHW,MAAM,GACJ,IAAI,CAIhB;;CAKF;oBAnFY,MAAM,CAClB,SAAY,EACZ,OAAU,2BAA2B,EAAE,SAAS,CAC7C;6BAXyB,oBAAoB;+BAKlB,aAAa"}
@@ -58,7 +58,7 @@ export default class TranslationApi {
58
58
  * @param {TranslationValue} doc
59
59
  */
60
60
  index(doc: TranslationValue): void;
61
- get dataType(): import("./datatype/index.js").DataType<import("./datastore/index.js").DataStore<"config", "translation" | "preset" | "field" | "projectSettings" | "deviceInfo" | "icon">, import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
61
+ get dataType(): import("./datatype/index.js").DataType<import("./datastore/index.js").DataStore<"config", "translation" | "projectSettings" | "preset" | "icon" | "field" | "deviceInfo">, import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
62
62
  name: "translation";
63
63
  schema: undefined;
64
64
  columns: {
@@ -178,7 +178,7 @@ export default class TranslationApi {
178
178
  tableName: "translation";
179
179
  dataType: "string";
180
180
  columnType: "SQLiteText";
181
- data: "UNRECOGNIZED" | "observation" | "track" | "preset" | "field" | "projectSettings" | "deviceInfo" | "role" | "type_unspecified";
181
+ data: "track" | "role" | "projectSettings" | "preset" | "observation" | "field" | "deviceInfo" | "UNRECOGNIZED" | "type_unspecified";
182
182
  driverParam: string;
183
183
  notNull: true;
184
184
  hasDefault: false;
@@ -1 +1 @@
1
- {"version":3,"file":"translation-api.d.ts","sourceRoot":"","sources":["../src/translation-api.js"],"names":[],"mappings":"AAKA,uEAAuE;AACvE,+CAA+C;AAE/C,iEAEC;AACD;IAQE;;;;;;;;;OASG;IACH,0BARG;QAMS,QAAQ,EANT,OAAO,qBAAqB,EAAE,QAAQ,CAChD,OAAW,sBAAsB,EAAE,SAAS,CAAC,QAAQ,CAAC,EACtD,cAAkB,qBAAqB,EAAE,gBAAgB,EACzD,aAAiB,EACjB,WAAe,EACf,gBAAoB,CACjB;KACH,EAWA;IAED,+BAA+B;IAC/B,SADc,OAAO,CAAC,IAAI,CAAC,CAG1B;IAED;;OAEG;IACH,WAFW,gBAAgB;;;;;;;;;;;;;;;;;;;;OAe1B;IAED,kGAAkG;IAElG;;;;;OAKG;IACH,WALW,YACR,IAAI,CAAC,gBAAgB,EAAC,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC,EAC5D,aAAe,GAAG,YAAY,CAAC,GAAG;QAAC,MAAM;;;UAA6B;KAAC,GAC3D,OAAO,CAAC,OAAO,iBAAiB,EAAE,WAAW,EAAE,CAAC,CAqC5D;IAED;;OAEG;IACH,WAFW,gBAAgB,QAkB1B;IAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAEC;IALD,mHAEC;;CAIF;sCApIkD,iBAAiB;iCACnC,WAAW;iCADO,iBAAiB"}
1
+ {"version":3,"file":"translation-api.d.ts","sourceRoot":"","sources":["../src/translation-api.js"],"names":[],"mappings":"AAKA,uEAAuE;AACvE,+CAA+C;AAE/C,iEAEC;AACD;IAQE;;;;;;;;;OASG;IACH,0BARG;QAMS,QAAQ,EANT,OAAO,qBAAqB,EAAE,QAAQ,CAChD,OAAW,sBAAsB,EAAE,SAAS,CAAC,QAAQ,CAAC,EACtD,cAAkB,qBAAqB,EAAE,gBAAgB,EACzD,aAAiB,EACjB,WAAe,EACf,gBAAoB,CACjB;KACH,EAWA;IAED,+BAA+B;IAC/B,SADc,OAAO,CAAC,IAAI,CAAC,CAG1B;IAED;;OAEG;IACH,WAFW,gBAAgB;;;;;;;;;;;;;;;;;;;;OAW1B;IAED,kGAAkG;IAElG;;;;;OAKG;IACH,WALW,YACR,IAAI,CAAC,gBAAgB,EAAC,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC,EAC5D,aAAe,GAAG,YAAY,CAAC,GAAG;QAAC,MAAM;;;UAA6B;KAAC,GAC3D,OAAO,CAAC,OAAO,iBAAiB,EAAE,WAAW,EAAE,CAAC,CAqC5D;IAED;;OAEG;IACH,WAFW,gBAAgB,QAkB1B;IAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAEC;IALD,mHAEC;;CAIF;sCAhIkD,iBAAiB;iCACnC,WAAW;iCADO,iBAAiB"}
package/dist/types.d.ts CHANGED
@@ -8,6 +8,8 @@ import { Duplex } from 'streamx';
8
8
  import RandomAccessStorage from 'random-access-storage';
9
9
  import { DefaultListener, ListenerSignature } from 'tiny-typed-emitter';
10
10
  import type { NAMESPACES } from './constants.js';
11
+ import type { Readable } from 'stream';
12
+ import type { HyperdriveEntry } from 'hyperdrive';
11
13
  export type Namespace = (typeof NAMESPACES)[number];
12
14
  type SupportedBlobVariants = typeof SUPPORTED_BLOB_VARIANTS;
13
15
  export type BlobType = keyof SupportedBlobVariants;
@@ -112,5 +114,10 @@ export type DefaultEmitterEvents<L extends ListenerSignature<L> = DefaultListene
112
114
  newListener: (event: keyof L, listener: L[keyof L]) => void;
113
115
  removeListener: (event: keyof L, listener: L[keyof L]) => void;
114
116
  };
117
+ export type BlobStoreEntriesStream = Readable & {
118
+ [Symbol.asyncIterator](): AsyncIterableIterator<HyperdriveEntry & {
119
+ driveId: string;
120
+ }>;
121
+ };
115
122
  export {};
116
123
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comapeo/core",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Offline p2p mapping library",
5
5
  "main": "src/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -108,6 +108,7 @@
108
108
  "homepage": "https://github.com/digidem/comapeo-core#readme",
109
109
  "devDependencies": {
110
110
  "@bufbuild/buf": "^1.26.1",
111
+ "@comapeo/cloud": "^0.1.0",
111
112
  "@comapeo/core2.0.1": "npm:@comapeo/core@2.0.1",
112
113
  "@mapeo/default-config": "5.0.0",
113
114
  "@mapeo/mock-data": "^2.1.1",
@@ -133,6 +134,7 @@
133
134
  "cpy-cli": "^5.0.0",
134
135
  "drizzle-kit": "^0.20.14",
135
136
  "eslint": "^8.57.0",
137
+ "execa": "^9.5.1",
136
138
  "husky": "^8.0.0",
137
139
  "iterpal": "^0.4.0",
138
140
  "lint-staged": "^14.0.1",
@@ -140,6 +142,7 @@
140
142
  "math-random-seed": "^2.0.0",
141
143
  "nanobench": "^3.0.0",
142
144
  "npm-run-all": "^4.1.5",
145
+ "p-props": "^6.0.0",
143
146
  "prettier": "^2.8.8",
144
147
  "random-access-file": "^4.0.7",
145
148
  "random-access-memory": "^6.2.1",
@@ -163,6 +166,7 @@
163
166
  "@mapeo/crypto": "1.0.0-alpha.10",
164
167
  "@mapeo/sqlite-indexer": "1.0.0-alpha.9",
165
168
  "@sinclair/typebox": "^0.29.6",
169
+ "@sindresorhus/merge-streams": "^4.0.0",
166
170
  "b4a": "^1.6.3",
167
171
  "bcp-47": "^2.1.0",
168
172
  "better-sqlite3": "^8.7.0",
@@ -200,6 +204,7 @@
200
204
  "tiny-typed-emitter": "^2.1.0",
201
205
  "type-fest": "^4.5.0",
202
206
  "undici": "^6.13.0",
207
+ "unix-path-resolve": "^1.0.2",
203
208
  "varint": "^6.0.0",
204
209
  "ws": "^8.18.0",
205
210
  "yauzl-promise": "^4.0.0"
@@ -0,0 +1,130 @@
1
+ import { TypedEmitter } from 'tiny-typed-emitter'
2
+ import { createEntriesStream } from './entries-stream.js'
3
+ import { filePathMatchesFilter } from './utils.js'
4
+
5
+ /** @import { BlobFilter } from '../types.js' */
6
+ /** @import { THyperdriveIndex } from './hyperdrive-index.js' */
7
+
8
+ /**
9
+ * Like hyperdrive.download() but 'live', and for multiple drives.
10
+ *
11
+ * Will emit an 'error' event for any unexpected errors. A consumer must attach
12
+ * an error listener to avoid uncaught errors. Sources of errors include:
13
+ *
14
+ * - If the entries stream emits an error
15
+ * - If a drive referenced in an entry is not found
16
+ * - If core.has() throws (e.g. if hypercore is closed)
17
+ * - If core.download().done() throws, which should not happen according to
18
+ * current hypercore code.
19
+ * - If the entries stream ends unexpectedly (it should be live and not end)
20
+ *
21
+ * NB: unlike hyperdrive.download(), this will also download deleted and
22
+ * previous versions of blobs - we don't currently support editing or deleting
23
+ * of blobs, so this should not be an issue, and if we do in the future,
24
+ * downloading deleted and previous versions may be desirable behavior anyway
25
+ *
26
+ * @extends {TypedEmitter<{ error: (error: Error) => void }>}
27
+ */
28
+ export class Downloader extends TypedEmitter {
29
+ /** @type {THyperdriveIndex} */
30
+ #driveIndex
31
+ /** @type {Set<{ done(): Promise<void>, destroy(): void }>} */
32
+ #queuedDownloads = new Set()
33
+ #entriesStream
34
+ #processEntriesPromise
35
+ #ac = new AbortController()
36
+ #shouldDownloadFile
37
+
38
+ /**
39
+ * @param {THyperdriveIndex} driveIndex
40
+ * @param {object} [options]
41
+ * @param {BlobFilter | null} [options.filter] Filter blobs of specific types and/or sizes to download
42
+ */
43
+ constructor(driveIndex, { filter } = {}) {
44
+ super()
45
+ this.#driveIndex = driveIndex
46
+
47
+ this.#shouldDownloadFile = filter
48
+ ? filePathMatchesFilter.bind(null, filter)
49
+ : () => true
50
+
51
+ this.#entriesStream = createEntriesStream(driveIndex, { live: true })
52
+ this.#entriesStream.once('error', this.#handleError)
53
+
54
+ this.#ac.signal.addEventListener('abort', this.#handleAbort, { once: true })
55
+
56
+ this.#processEntriesPromise = this.#processEntries()
57
+ this.#processEntriesPromise.catch(this.#handleError)
58
+ }
59
+
60
+ /**
61
+ * Start processing entries from the entries stream - if an entry matches the
62
+ * filter, and we don't already have it, queue it for download. If the
63
+ * Downloader is live, this method will never resolve, otherwise it will
64
+ * resolve when all the entries have been processed and downloaded.
65
+ */
66
+ async #processEntries() {
67
+ for await (const entry of this.#entriesStream) {
68
+ this.#ac.signal.throwIfAborted()
69
+ const {
70
+ driveId,
71
+ key: filePath,
72
+ value: { blob },
73
+ } = entry
74
+ if (!this.#shouldDownloadFile(filePath)) continue
75
+ const drive = this.#driveIndex.get(driveId)
76
+ // ERROR HANDLING: this is unexpected and should not happen
77
+ if (!drive) throw new Error('Drive not found: ' + driveId)
78
+ const blobs = await drive.getBlobs()
79
+ this.#ac.signal.throwIfAborted()
80
+ await this.#processEntry(blobs.core, blob)
81
+ this.#ac.signal.throwIfAborted()
82
+ }
83
+ throw new Error('Entries stream ended unexpectedly')
84
+ }
85
+
86
+ /**
87
+ * Update state and queue missing entries for download
88
+ *
89
+ * @param {import('hypercore')} blobsCore
90
+ * @param {{ blockOffset: number, blockLength: number, byteLength: number }} blob
91
+ */
92
+ async #processEntry(blobsCore, { blockOffset: start, blockLength: length }) {
93
+ const end = start + length
94
+ const have = await blobsCore.has(start, end)
95
+ this.#ac.signal.throwIfAborted()
96
+ if (have) return
97
+ const download = blobsCore.download({ start, end })
98
+ this.#queuedDownloads.add(download)
99
+ download
100
+ .done()
101
+ // According to the code, this should never throw.
102
+ .catch(this.#handleError)
103
+ .finally(() => {
104
+ this.#queuedDownloads.delete(download)
105
+ })
106
+ }
107
+
108
+ /**
109
+ * Cancel the downloads and clean up resources.
110
+ */
111
+ destroy() {
112
+ this.#ac.abort()
113
+ }
114
+
115
+ /** @param {Error} error */
116
+ #handleError = (error) => {
117
+ if (this.#ac.signal.aborted) return
118
+ this.emit('error', error)
119
+ this.#ac.abort(error)
120
+ }
121
+
122
+ #handleAbort = () => {
123
+ for (const download of this.#queuedDownloads) download.destroy()
124
+ this.#ac.signal.removeEventListener('abort', this.#handleAbort)
125
+ this.#entriesStream.removeListener('error', this.#ac.abort)
126
+ // queuedDownloads is likely to be empty here anyway, but clear just in case.
127
+ this.#queuedDownloads.clear()
128
+ this.#entriesStream.destroy()
129
+ }
130
+ }
@@ -0,0 +1,81 @@
1
+ import SubEncoder from 'sub-encoder'
2
+ import mergeStreams from '@sindresorhus/merge-streams'
3
+ import { Transform, pipeline } from 'node:stream'
4
+ import { noop } from '../utils.js'
5
+
6
+ /** @import Hyperdrive from 'hyperdrive' */
7
+ /** @import { BlobStoreEntriesStream } from '../types.js' */
8
+ /** @import { THyperdriveIndex } from './hyperdrive-index.js' */
9
+
10
+ const keyEncoding = new SubEncoder('files', 'utf-8')
11
+
12
+ /**
13
+ *
14
+ * @param {THyperdriveIndex} driveIndex
15
+ * @param {object} opts
16
+ * @param {boolean} [opts.live=false]
17
+ * @returns {BlobStoreEntriesStream}
18
+ */
19
+ export function createEntriesStream(driveIndex, { live = false } = {}) {
20
+ const mergedEntriesStreams = mergeStreams(
21
+ [...driveIndex].map((drive) => getHistoryStream(drive.db, { live }))
22
+ )
23
+ driveIndex.on('add-drive', addDrive)
24
+ // Close is always emitted, so we can use it to remove the listener
25
+ mergedEntriesStreams.once('close', () =>
26
+ driveIndex.off('add-drive', addDrive)
27
+ )
28
+ return mergedEntriesStreams
29
+
30
+ /** @param {Hyperdrive} drive */
31
+ function addDrive(drive) {
32
+ mergedEntriesStreams.add(getHistoryStream(drive.db, { live }))
33
+ }
34
+ }
35
+
36
+ /**
37
+ *
38
+ * @param {import('hyperbee')} bee
39
+ * @param {object} opts
40
+ * @param {boolean} opts.live
41
+ */
42
+ function getHistoryStream(bee, { live }) {
43
+ // This will also include old versions of files, but it is the only way to
44
+ // get a live stream from a Hyperbee, however we currently do not support
45
+ // edits of blobs, so this should not be an issue, and the consequence is
46
+ // that old versions are downloaded too, which is acceptable.
47
+ const historyStream = bee.createHistoryStream({
48
+ live,
49
+ // `keyEncoding` is necessary because hyperdrive stores file index data
50
+ // under the `files` sub-encoding key
51
+ keyEncoding,
52
+ })
53
+ return pipeline(historyStream, new AddDriveIds(bee.core), noop)
54
+ }
55
+
56
+ class AddDriveIds extends Transform {
57
+ #core
58
+ #cachedDriveId
59
+
60
+ /** @param {import('hypercore')} core */
61
+ constructor(core) {
62
+ super({ objectMode: true })
63
+ this.#core = core
64
+ this.#cachedDriveId = core.discoveryKey?.toString('hex')
65
+ }
66
+
67
+ /** @type {Transform['_transform']} */
68
+ _transform(entry, _, callback) {
69
+ // Minimal performance optimization to only call toString() once.
70
+ // core.discoveryKey will always be defined by the time it starts
71
+ // streaming, but could be null when the instance is first created.
72
+ let driveId
73
+ if (this.#cachedDriveId) {
74
+ driveId = this.#cachedDriveId
75
+ } else {
76
+ driveId = this.#core.discoveryKey?.toString('hex')
77
+ this.#cachedDriveId = driveId
78
+ }
79
+ callback(null, { ...entry, driveId })
80
+ }
81
+ }