@dxos/teleport-extension-replicator 0.1.56-main.e47dfd1 → 0.1.56-main.ed2f871

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.
@@ -1,10 +1,10 @@
1
1
  import "@dxos/node-std/globals";
2
2
 
3
3
  // packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts
4
- import invariant from "tiny-invariant";
5
4
  import { asyncTimeout, DeferredTask, synchronized } from "@dxos/async";
6
5
  import { Context } from "@dxos/context";
7
6
  import { failUndefined } from "@dxos/debug";
7
+ import { invariant } from "@dxos/invariant";
8
8
  import { PublicKey } from "@dxos/keys";
9
9
  import { log, logInfo } from "@dxos/log";
10
10
  import { schema, RpcClosedError } from "@dxos/protocols";
@@ -25,14 +25,13 @@ var ReplicatorExtension = class {
25
25
  constructor() {
26
26
  this._ctx = new Context({
27
27
  onError: (err) => {
28
- var _a;
29
28
  log.catch(err, void 0, {
30
29
  F: __dxlog_file,
31
30
  L: 31,
32
31
  S: this,
33
32
  C: (f, a) => f(...a)
34
33
  });
35
- (_a = this._extensionContext) == null ? void 0 : _a.close(err);
34
+ this._extensionContext?.close(err);
36
35
  }
37
36
  });
38
37
  this._feeds = new ComplexMap(PublicKey.hash);
@@ -62,11 +61,10 @@ var ReplicatorExtension = class {
62
61
  });
63
62
  }
64
63
  get extensionInfo() {
65
- var _a, _b, _c;
66
64
  return {
67
- initiator: (_a = this._extensionContext) == null ? void 0 : _a.initiator,
68
- localPeerId: (_b = this._extensionContext) == null ? void 0 : _b.localPeerId,
69
- remotePeerId: (_c = this._extensionContext) == null ? void 0 : _c.remotePeerId,
65
+ initiator: this._extensionContext?.initiator,
66
+ localPeerId: this._extensionContext?.localPeerId,
67
+ remotePeerId: this._extensionContext?.remotePeerId,
70
68
  feeds: Array.from(this._feeds.keys())
71
69
  };
72
70
  }
@@ -125,7 +123,15 @@ var ReplicatorExtension = class {
125
123
  S: this,
126
124
  C: (f, a) => f(...a)
127
125
  });
128
- invariant(this._extensionContext.initiator === true, "Invalid call");
126
+ invariant(this._extensionContext.initiator === true, "Invalid call", {
127
+ F: __dxlog_file,
128
+ L: 109,
129
+ S: this,
130
+ A: [
131
+ "this._extensionContext!.initiator === true",
132
+ "'Invalid call'"
133
+ ]
134
+ });
129
135
  this._updateTask.schedule();
130
136
  },
131
137
  startReplication: async ({ info }) => {
@@ -137,7 +143,15 @@ var ReplicatorExtension = class {
137
143
  S: this,
138
144
  C: (f, a) => f(...a)
139
145
  });
140
- invariant(this._extensionContext.initiator === false, "Invalid call");
146
+ invariant(this._extensionContext.initiator === false, "Invalid call", {
147
+ F: __dxlog_file,
148
+ L: 114,
149
+ S: this,
150
+ A: [
151
+ "this._extensionContext!.initiator === false",
152
+ "'Invalid call'"
153
+ ]
154
+ });
141
155
  const streamTag = await this._acceptReplication(info);
142
156
  return {
143
157
  streamTag
@@ -152,7 +166,15 @@ var ReplicatorExtension = class {
152
166
  S: this,
153
167
  C: (f, a) => f(...a)
154
168
  });
155
- invariant(this._extensionContext.initiator === false, "Invalid call");
169
+ invariant(this._extensionContext.initiator === false, "Invalid call", {
170
+ F: __dxlog_file,
171
+ L: 124,
172
+ S: this,
173
+ A: [
174
+ "this._extensionContext!.initiator === false",
175
+ "'Invalid call'"
176
+ ]
177
+ });
156
178
  await this._stopReplication(info.feedKey);
157
179
  }
158
180
  }
@@ -165,7 +187,6 @@ var ReplicatorExtension = class {
165
187
  this._updateTask.schedule();
166
188
  }
167
189
  async onClose(err) {
168
- var _a;
169
190
  log("close", {
170
191
  err
171
192
  }, {
@@ -175,13 +196,12 @@ var ReplicatorExtension = class {
175
196
  C: (f, a) => f(...a)
176
197
  });
177
198
  await this._ctx.dispose();
178
- await ((_a = this._rpc) == null ? void 0 : _a.close());
199
+ await this._rpc?.close();
179
200
  for (const feedKey of this._streams.keys()) {
180
201
  await this._stopReplication(feedKey);
181
202
  }
182
203
  }
183
204
  async _reevaluateFeeds() {
184
- var _a;
185
205
  log("_reevaluateFeeds", void 0, {
186
206
  F: __dxlog_file,
187
207
  L: 150,
@@ -192,7 +212,7 @@ var ReplicatorExtension = class {
192
212
  if (this._ctx.disposed) {
193
213
  return;
194
214
  }
195
- if (this._streams.has(feedKey) && this._options.upload !== ((_a = this._streams.get(feedKey)) == null ? void 0 : _a.info.upload)) {
215
+ if (this._streams.has(feedKey) && this._options.upload !== this._streams.get(feedKey)?.info.upload) {
196
216
  try {
197
217
  await asyncTimeout(this._stopReplication(feedKey), 1e3);
198
218
  } catch (err) {
@@ -228,8 +248,24 @@ var ReplicatorExtension = class {
228
248
  S: this,
229
249
  C: (f, a) => f(...a)
230
250
  });
231
- invariant(this._extensionContext.initiator === true, "Invalid call");
232
- invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`);
251
+ invariant(this._extensionContext.initiator === true, "Invalid call", {
252
+ F: __dxlog_file,
253
+ L: 181,
254
+ S: this,
255
+ A: [
256
+ "this._extensionContext!.initiator === true",
257
+ "'Invalid call'"
258
+ ]
259
+ });
260
+ invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`, {
261
+ F: __dxlog_file,
262
+ L: 182,
263
+ S: this,
264
+ A: [
265
+ "!this._streams.has(feedInfo.feedKey)",
266
+ "`Replication already in progress for feed: ${feedInfo.feedKey}`"
267
+ ]
268
+ });
233
269
  const { streamTag } = await this._rpc.rpc.ReplicatorService.startReplication({
234
270
  info: feedInfo
235
271
  });
@@ -243,7 +279,15 @@ var ReplicatorExtension = class {
243
279
  * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.
244
280
  */
245
281
  async _acceptReplication(feedInfo) {
246
- invariant(this._extensionContext.initiator === false, "Invalid call");
282
+ invariant(this._extensionContext.initiator === false, "Invalid call", {
283
+ F: __dxlog_file,
284
+ L: 197,
285
+ S: this,
286
+ A: [
287
+ "this._extensionContext!.initiator === false",
288
+ "'Invalid call'"
289
+ ]
290
+ });
247
291
  if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {
248
292
  return void 0;
249
293
  }
@@ -252,7 +296,6 @@ var ReplicatorExtension = class {
252
296
  return tag;
253
297
  }
254
298
  async _replicateFeed(info, streamTag) {
255
- var _a;
256
299
  log("replicate", {
257
300
  info,
258
301
  streamTag
@@ -262,8 +305,16 @@ var ReplicatorExtension = class {
262
305
  S: this,
263
306
  C: (f, a) => f(...a)
264
307
  });
265
- invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`);
266
- const feed = (_a = this._feeds.get(info.feedKey)) != null ? _a : failUndefined();
308
+ invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`, {
309
+ F: __dxlog_file,
310
+ L: 210,
311
+ S: this,
312
+ A: [
313
+ "!this._streams.has(info.feedKey)",
314
+ "`Replication already in progress for feed: ${info.feedKey}`"
315
+ ]
316
+ });
317
+ const feed = this._feeds.get(info.feedKey) ?? failUndefined();
267
318
  const networkStream = await this._extensionContext.createStream(streamTag, {
268
319
  contentType: "application/x-hypercore"
269
320
  });
@@ -275,7 +326,7 @@ var ReplicatorExtension = class {
275
326
  encrypted: false
276
327
  });
277
328
  replicationStream.on("error", (err) => {
278
- if ((err == null ? void 0 : err.message) === "Writable stream closed prematurely" || (err == null ? void 0 : err.message) === "Cannot call write after a stream was destroyed") {
329
+ if (err?.message === "Writable stream closed prematurely" || err?.message === "Cannot call write after a stream was destroyed") {
279
330
  return;
280
331
  }
281
332
  log.warn("replication stream error", {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/replicator-extension.ts"],
4
- "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport type { ProtocolStream } from 'hypercore-protocol';\nimport { Duplex } from 'node:stream';\nimport invariant from 'tiny-invariant';\n\nimport { asyncTimeout, DeferredTask, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { FeedWrapper } from '@dxos/feed-store';\nimport { PublicKey } from '@dxos/keys';\nimport { log, logInfo } from '@dxos/log';\nimport { schema, RpcClosedError } from '@dxos/protocols';\nimport { FeedInfo, ReplicatorService } from '@dxos/protocols/proto/dxos/mesh/teleport/replicator';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\nimport { ExtensionContext, TeleportExtension } from '@dxos/teleport';\nimport { ComplexMap } from '@dxos/util';\n\nexport type ReplicationOptions = {\n upload: boolean;\n};\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class ReplicatorExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n log.catch(err);\n this._extensionContext?.close(err);\n },\n });\n\n private readonly _feeds = new ComplexMap<PublicKey, FeedWrapper<any>>(PublicKey.hash);\n private readonly _streams = new ComplexMap<PublicKey, ActiveStream>(PublicKey.hash);\n\n private _rpc?: ProtoRpcPeer<ServiceBundle>;\n private _extensionContext?: ExtensionContext;\n\n private _options: ReplicationOptions = {\n upload: false,\n };\n\n private readonly _updateTask = new DeferredTask(this._ctx, async () => {\n try {\n if (this._extensionContext!.initiator === false) {\n await this._rpc!.rpc.ReplicatorService.updateFeeds({\n feeds: Array.from(this._feeds.values()).map((feed) => ({\n feedKey: feed.key,\n download: true,\n upload: this._options.upload,\n })),\n });\n } else if (this._extensionContext!.initiator === true) {\n await this._reevaluateFeeds();\n }\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return; // Some RPC requests might be pending while closing.\n }\n throw err;\n }\n });\n\n @logInfo\n private get extensionInfo() {\n return {\n initiator: this._extensionContext?.initiator,\n localPeerId: this._extensionContext?.localPeerId,\n remotePeerId: this._extensionContext?.remotePeerId,\n feeds: Array.from(this._feeds.keys()),\n };\n }\n\n setOptions(options: ReplicationOptions): this {\n this._options = options;\n log('setOptions', { options });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n return this;\n }\n\n addFeed(feed: FeedWrapper<any>) {\n this._feeds.set(feed.key, feed);\n log('addFeed', { feedKey: feed.key });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n }\n\n async onOpen(context: ExtensionContext) {\n this._extensionContext = context;\n log('open');\n\n this._rpc = createProtoRpcPeer<ServiceBundle, ServiceBundle>({\n requested: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n exposed: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n handlers: {\n ReplicatorService: {\n updateFeeds: async ({ feeds }) => {\n log('received feed info', { feeds });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n this._updateTask.schedule();\n },\n startReplication: async ({ info }) => {\n log('starting replication...', { info });\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n const streamTag = await this._acceptReplication(info);\n return {\n streamTag,\n };\n },\n stopReplication: async ({ info }) => {\n log('stopping replication...', { info });\n // TODO(dmaretskyi): Make sure any peer can stop replication.\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n await this._stopReplication(info.feedKey);\n },\n },\n },\n port: await context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n });\n await this._rpc.open();\n\n this._updateTask.schedule();\n }\n\n async onClose(err?: Error | undefined) {\n log('close', { err });\n await this._ctx.dispose();\n await this._rpc?.close();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n @synchronized\n private async _reevaluateFeeds() {\n log('_reevaluateFeeds');\n for (const feedKey of this._feeds.keys()) {\n if (this._ctx.disposed) {\n return;\n }\n if (this._streams.has(feedKey) && this._options.upload !== this._streams.get(feedKey)?.info.upload) {\n try {\n await asyncTimeout(this._stopReplication(feedKey), 1000);\n } catch (err) {\n log.catch(err);\n }\n }\n\n if (this._ctx.disposed) {\n return;\n }\n if (!this._streams.has(feedKey)) {\n await this._initiateReplication({\n feedKey,\n download: true,\n upload: this._options.upload,\n });\n }\n }\n }\n\n /**\n * Try to initiate feed replication.\n */\n private async _initiateReplication(feedInfo: FeedInfo) {\n log('initiating replication', { feedInfo });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`);\n const { streamTag } = await this._rpc!.rpc.ReplicatorService.startReplication({ info: feedInfo });\n if (!streamTag) {\n return;\n }\n\n await this._replicateFeed(feedInfo, streamTag);\n }\n\n /**\n * Respond to a remote request to replicate a feed.\n * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.\n */\n @synchronized\n private async _acceptReplication(feedInfo: FeedInfo): Promise<string | undefined> {\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {\n return undefined; // We don't have the feed or we are already replicating it.\n }\n\n const tag = `feed-${feedInfo.feedKey.toHex()}-${PublicKey.random().toHex().slice(0, 8)}`; // Generate a unique tag for the stream.\n await this._replicateFeed(feedInfo, tag);\n return tag;\n }\n\n private async _replicateFeed(info: FeedInfo, streamTag: string) {\n log('replicate', { info, streamTag });\n invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`);\n\n const feed = this._feeds.get(info.feedKey) ?? failUndefined();\n const networkStream = await this._extensionContext!.createStream(streamTag, {\n contentType: 'application/x-hypercore',\n });\n const replicationStream = feed.replicate(true, {\n live: true,\n upload: info.upload,\n download: info.download,\n noise: false,\n encrypted: false,\n });\n\n // left for testing\n // feed.on('download', (index: number, data: any) => {\n // log('download', {\n // key: info.feedKey,\n // index\n // });\n // });\n\n replicationStream.on('error', (err) => {\n if (\n err?.message === 'Writable stream closed prematurely' ||\n err?.message === 'Cannot call write after a stream was destroyed'\n ) {\n return;\n }\n\n log.warn('replication stream error', { err, info });\n });\n\n this._streams.set(info.feedKey, {\n streamTag,\n networkStream,\n replicationStream,\n info,\n });\n\n networkStream.pipe(replicationStream as any).pipe(networkStream);\n }\n\n private async _stopReplication(feedKey: PublicKey) {\n const stream = this._streams.get(feedKey);\n if (!stream) {\n return;\n }\n\n stream.networkStream.destroy();\n this._streams.delete(feedKey);\n }\n}\n\ntype ServiceBundle = {\n ReplicatorService: ReplicatorService;\n};\n\ntype ActiveStream = {\n streamTag: string;\n networkStream: Duplex;\n replicationStream: ProtocolStream;\n info: FeedInfo;\n};\n"],
5
- "mappings": "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",
6
- "names": ["invariant", "asyncTimeout", "DeferredTask", "synchronized", "Context", "failUndefined", "PublicKey", "log", "logInfo", "schema", "RpcClosedError", "createProtoRpcPeer", "ComplexMap", "ReplicatorExtension", "_ctx", "onError", "err", "catch", "_extensionContext", "close", "_feeds", "hash", "_streams", "_options", "upload", "_updateTask", "initiator", "_rpc", "rpc", "ReplicatorService", "updateFeeds", "feeds", "Array", "from", "values", "map", "feed", "feedKey", "key", "download", "_reevaluateFeeds", "extensionInfo", "localPeerId", "remotePeerId", "keys", "setOptions", "options", "schedule", "addFeed", "set", "onOpen", "context", "requested", "getService", "exposed", "handlers", "startReplication", "info", "streamTag", "_acceptReplication", "stopReplication", "_stopReplication", "port", "createPort", "contentType", "open", "onClose", "dispose", "disposed", "has", "get", "_initiateReplication", "feedInfo", "_replicateFeed", "undefined", "tag", "toHex", "random", "slice", "networkStream", "createStream", "replicationStream", "replicate", "live", "noise", "encrypted", "on", "message", "warn", "pipe", "stream", "destroy", "delete"]
4
+ "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport type { ProtocolStream } from 'hypercore-protocol';\nimport { Duplex } from 'node:stream';\n\nimport { asyncTimeout, DeferredTask, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { FeedWrapper } from '@dxos/feed-store';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log, logInfo } from '@dxos/log';\nimport { schema, RpcClosedError } from '@dxos/protocols';\nimport { FeedInfo, ReplicatorService } from '@dxos/protocols/proto/dxos/mesh/teleport/replicator';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\nimport { ExtensionContext, TeleportExtension } from '@dxos/teleport';\nimport { ComplexMap } from '@dxos/util';\n\nexport type ReplicationOptions = {\n upload: boolean;\n};\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class ReplicatorExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n log.catch(err);\n this._extensionContext?.close(err);\n },\n });\n\n private readonly _feeds = new ComplexMap<PublicKey, FeedWrapper<any>>(PublicKey.hash);\n private readonly _streams = new ComplexMap<PublicKey, ActiveStream>(PublicKey.hash);\n\n private _rpc?: ProtoRpcPeer<ServiceBundle>;\n private _extensionContext?: ExtensionContext;\n\n private _options: ReplicationOptions = {\n upload: false,\n };\n\n private readonly _updateTask = new DeferredTask(this._ctx, async () => {\n try {\n if (this._extensionContext!.initiator === false) {\n await this._rpc!.rpc.ReplicatorService.updateFeeds({\n feeds: Array.from(this._feeds.values()).map((feed) => ({\n feedKey: feed.key,\n download: true,\n upload: this._options.upload,\n })),\n });\n } else if (this._extensionContext!.initiator === true) {\n await this._reevaluateFeeds();\n }\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return; // Some RPC requests might be pending while closing.\n }\n throw err;\n }\n });\n\n @logInfo\n private get extensionInfo() {\n return {\n initiator: this._extensionContext?.initiator,\n localPeerId: this._extensionContext?.localPeerId,\n remotePeerId: this._extensionContext?.remotePeerId,\n feeds: Array.from(this._feeds.keys()),\n };\n }\n\n setOptions(options: ReplicationOptions): this {\n this._options = options;\n log('setOptions', { options });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n return this;\n }\n\n addFeed(feed: FeedWrapper<any>) {\n this._feeds.set(feed.key, feed);\n log('addFeed', { feedKey: feed.key });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n }\n\n async onOpen(context: ExtensionContext) {\n this._extensionContext = context;\n log('open');\n\n this._rpc = createProtoRpcPeer<ServiceBundle, ServiceBundle>({\n requested: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n exposed: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n handlers: {\n ReplicatorService: {\n updateFeeds: async ({ feeds }) => {\n log('received feed info', { feeds });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n this._updateTask.schedule();\n },\n startReplication: async ({ info }) => {\n log('starting replication...', { info });\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n const streamTag = await this._acceptReplication(info);\n return {\n streamTag,\n };\n },\n stopReplication: async ({ info }) => {\n log('stopping replication...', { info });\n // TODO(dmaretskyi): Make sure any peer can stop replication.\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n await this._stopReplication(info.feedKey);\n },\n },\n },\n port: await context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n });\n await this._rpc.open();\n\n this._updateTask.schedule();\n }\n\n async onClose(err?: Error | undefined) {\n log('close', { err });\n await this._ctx.dispose();\n await this._rpc?.close();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n @synchronized\n private async _reevaluateFeeds() {\n log('_reevaluateFeeds');\n for (const feedKey of this._feeds.keys()) {\n if (this._ctx.disposed) {\n return;\n }\n if (this._streams.has(feedKey) && this._options.upload !== this._streams.get(feedKey)?.info.upload) {\n try {\n await asyncTimeout(this._stopReplication(feedKey), 1000);\n } catch (err) {\n log.catch(err);\n }\n }\n\n if (this._ctx.disposed) {\n return;\n }\n if (!this._streams.has(feedKey)) {\n await this._initiateReplication({\n feedKey,\n download: true,\n upload: this._options.upload,\n });\n }\n }\n }\n\n /**\n * Try to initiate feed replication.\n */\n private async _initiateReplication(feedInfo: FeedInfo) {\n log('initiating replication', { feedInfo });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`);\n const { streamTag } = await this._rpc!.rpc.ReplicatorService.startReplication({ info: feedInfo });\n if (!streamTag) {\n return;\n }\n\n await this._replicateFeed(feedInfo, streamTag);\n }\n\n /**\n * Respond to a remote request to replicate a feed.\n * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.\n */\n @synchronized\n private async _acceptReplication(feedInfo: FeedInfo): Promise<string | undefined> {\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {\n return undefined; // We don't have the feed or we are already replicating it.\n }\n\n const tag = `feed-${feedInfo.feedKey.toHex()}-${PublicKey.random().toHex().slice(0, 8)}`; // Generate a unique tag for the stream.\n await this._replicateFeed(feedInfo, tag);\n return tag;\n }\n\n private async _replicateFeed(info: FeedInfo, streamTag: string) {\n log('replicate', { info, streamTag });\n invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`);\n\n const feed = this._feeds.get(info.feedKey) ?? failUndefined();\n const networkStream = await this._extensionContext!.createStream(streamTag, {\n contentType: 'application/x-hypercore',\n });\n const replicationStream = feed.replicate(true, {\n live: true,\n upload: info.upload,\n download: info.download,\n noise: false,\n encrypted: false,\n });\n\n // left for testing\n // feed.on('download', (index: number, data: any) => {\n // log('download', {\n // key: info.feedKey,\n // index\n // });\n // });\n\n replicationStream.on('error', (err) => {\n if (\n err?.message === 'Writable stream closed prematurely' ||\n err?.message === 'Cannot call write after a stream was destroyed'\n ) {\n return;\n }\n\n log.warn('replication stream error', { err, info });\n });\n\n this._streams.set(info.feedKey, {\n streamTag,\n networkStream,\n replicationStream,\n info,\n });\n\n networkStream.pipe(replicationStream as any).pipe(networkStream);\n }\n\n private async _stopReplication(feedKey: PublicKey) {\n const stream = this._streams.get(feedKey);\n if (!stream) {\n return;\n }\n\n stream.networkStream.destroy();\n this._streams.delete(feedKey);\n }\n}\n\ntype ServiceBundle = {\n ReplicatorService: ReplicatorService;\n};\n\ntype ActiveStream = {\n streamTag: string;\n networkStream: Duplex;\n replicationStream: ProtocolStream;\n info: FeedInfo;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["asyncTimeout", "DeferredTask", "synchronized", "Context", "failUndefined", "invariant", "PublicKey", "log", "logInfo", "schema", "RpcClosedError", "createProtoRpcPeer", "ComplexMap", "ReplicatorExtension", "_ctx", "onError", "err", "catch", "_extensionContext", "close", "_feeds", "hash", "_streams", "_options", "upload", "_updateTask", "initiator", "_rpc", "rpc", "ReplicatorService", "updateFeeds", "feeds", "Array", "from", "values", "map", "feed", "feedKey", "key", "download", "_reevaluateFeeds", "extensionInfo", "localPeerId", "remotePeerId", "keys", "setOptions", "options", "schedule", "addFeed", "set", "onOpen", "context", "requested", "getService", "exposed", "handlers", "startReplication", "info", "streamTag", "_acceptReplication", "stopReplication", "_stopReplication", "port", "createPort", "contentType", "open", "onClose", "dispose", "disposed", "has", "get", "_initiateReplication", "feedInfo", "_replicateFeed", "undefined", "tag", "toHex", "random", "slice", "networkStream", "createStream", "replicationStream", "replicate", "live", "noise", "encrypted", "on", "message", "warn", "pipe", "stream", "destroy", "delete"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts":{"bytes":31881,"imports":[{"path":"tiny-invariant","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}]},"packages/core/mesh/teleport-extension-replicator/src/index.ts":{"bytes":520,"imports":[{"path":"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts","kind":"import-statement","original":"./replicator-extension"}]}},"outputs":{"packages/core/mesh/teleport-extension-replicator/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14626},"packages/core/mesh/teleport-extension-replicator/dist/lib/browser/index.mjs":{"imports":[{"path":"tiny-invariant","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["ReplicatorExtension"],"entryPoint":"packages/core/mesh/teleport-extension-replicator/src/index.ts","inputs":{"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts":{"bytesInOutput":9465},"packages/core/mesh/teleport-extension-replicator/src/index.ts":{"bytesInOutput":0}},"bytes":9648}}}
1
+ {"inputs":{"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts":{"bytes":33894,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-replicator/src/index.ts":{"bytes":520,"imports":[{"path":"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts","kind":"import-statement","original":"./replicator-extension"}],"format":"esm"}},"outputs":{"packages/core/mesh/teleport-extension-replicator/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14638},"packages/core/mesh/teleport-extension-replicator/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["ReplicatorExtension"],"entryPoint":"packages/core/mesh/teleport-extension-replicator/src/index.ts","inputs":{"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts":{"bytesInOutput":10545},"packages/core/mesh/teleport-extension-replicator/src/index.ts":{"bytesInOutput":0}},"bytes":10728}}}
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // packages/core/mesh/teleport-extension-replicator/src/index.ts
@@ -35,10 +25,10 @@ __export(src_exports, {
35
25
  module.exports = __toCommonJS(src_exports);
36
26
 
37
27
  // packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts
38
- var import_tiny_invariant = __toESM(require("tiny-invariant"));
39
28
  var import_async = require("@dxos/async");
40
29
  var import_context = require("@dxos/context");
41
30
  var import_debug = require("@dxos/debug");
31
+ var import_invariant = require("@dxos/invariant");
42
32
  var import_keys = require("@dxos/keys");
43
33
  var import_log = require("@dxos/log");
44
34
  var import_protocols = require("@dxos/protocols");
@@ -59,14 +49,13 @@ var ReplicatorExtension = class {
59
49
  constructor() {
60
50
  this._ctx = new import_context.Context({
61
51
  onError: (err) => {
62
- var _a;
63
52
  import_log.log.catch(err, void 0, {
64
53
  F: __dxlog_file,
65
54
  L: 31,
66
55
  S: this,
67
56
  C: (f, a) => f(...a)
68
57
  });
69
- (_a = this._extensionContext) == null ? void 0 : _a.close(err);
58
+ this._extensionContext?.close(err);
70
59
  }
71
60
  });
72
61
  this._feeds = new import_util.ComplexMap(import_keys.PublicKey.hash);
@@ -96,11 +85,10 @@ var ReplicatorExtension = class {
96
85
  });
97
86
  }
98
87
  get extensionInfo() {
99
- var _a, _b, _c;
100
88
  return {
101
- initiator: (_a = this._extensionContext) == null ? void 0 : _a.initiator,
102
- localPeerId: (_b = this._extensionContext) == null ? void 0 : _b.localPeerId,
103
- remotePeerId: (_c = this._extensionContext) == null ? void 0 : _c.remotePeerId,
89
+ initiator: this._extensionContext?.initiator,
90
+ localPeerId: this._extensionContext?.localPeerId,
91
+ remotePeerId: this._extensionContext?.remotePeerId,
104
92
  feeds: Array.from(this._feeds.keys())
105
93
  };
106
94
  }
@@ -159,7 +147,15 @@ var ReplicatorExtension = class {
159
147
  S: this,
160
148
  C: (f, a) => f(...a)
161
149
  });
162
- (0, import_tiny_invariant.default)(this._extensionContext.initiator === true, "Invalid call");
150
+ (0, import_invariant.invariant)(this._extensionContext.initiator === true, "Invalid call", {
151
+ F: __dxlog_file,
152
+ L: 109,
153
+ S: this,
154
+ A: [
155
+ "this._extensionContext!.initiator === true",
156
+ "'Invalid call'"
157
+ ]
158
+ });
163
159
  this._updateTask.schedule();
164
160
  },
165
161
  startReplication: async ({ info }) => {
@@ -171,7 +167,15 @@ var ReplicatorExtension = class {
171
167
  S: this,
172
168
  C: (f, a) => f(...a)
173
169
  });
174
- (0, import_tiny_invariant.default)(this._extensionContext.initiator === false, "Invalid call");
170
+ (0, import_invariant.invariant)(this._extensionContext.initiator === false, "Invalid call", {
171
+ F: __dxlog_file,
172
+ L: 114,
173
+ S: this,
174
+ A: [
175
+ "this._extensionContext!.initiator === false",
176
+ "'Invalid call'"
177
+ ]
178
+ });
175
179
  const streamTag = await this._acceptReplication(info);
176
180
  return {
177
181
  streamTag
@@ -186,7 +190,15 @@ var ReplicatorExtension = class {
186
190
  S: this,
187
191
  C: (f, a) => f(...a)
188
192
  });
189
- (0, import_tiny_invariant.default)(this._extensionContext.initiator === false, "Invalid call");
193
+ (0, import_invariant.invariant)(this._extensionContext.initiator === false, "Invalid call", {
194
+ F: __dxlog_file,
195
+ L: 124,
196
+ S: this,
197
+ A: [
198
+ "this._extensionContext!.initiator === false",
199
+ "'Invalid call'"
200
+ ]
201
+ });
190
202
  await this._stopReplication(info.feedKey);
191
203
  }
192
204
  }
@@ -199,7 +211,6 @@ var ReplicatorExtension = class {
199
211
  this._updateTask.schedule();
200
212
  }
201
213
  async onClose(err) {
202
- var _a;
203
214
  (0, import_log.log)("close", {
204
215
  err
205
216
  }, {
@@ -209,13 +220,12 @@ var ReplicatorExtension = class {
209
220
  C: (f, a) => f(...a)
210
221
  });
211
222
  await this._ctx.dispose();
212
- await ((_a = this._rpc) == null ? void 0 : _a.close());
223
+ await this._rpc?.close();
213
224
  for (const feedKey of this._streams.keys()) {
214
225
  await this._stopReplication(feedKey);
215
226
  }
216
227
  }
217
228
  async _reevaluateFeeds() {
218
- var _a;
219
229
  (0, import_log.log)("_reevaluateFeeds", void 0, {
220
230
  F: __dxlog_file,
221
231
  L: 150,
@@ -226,7 +236,7 @@ var ReplicatorExtension = class {
226
236
  if (this._ctx.disposed) {
227
237
  return;
228
238
  }
229
- if (this._streams.has(feedKey) && this._options.upload !== ((_a = this._streams.get(feedKey)) == null ? void 0 : _a.info.upload)) {
239
+ if (this._streams.has(feedKey) && this._options.upload !== this._streams.get(feedKey)?.info.upload) {
230
240
  try {
231
241
  await (0, import_async.asyncTimeout)(this._stopReplication(feedKey), 1e3);
232
242
  } catch (err) {
@@ -262,8 +272,24 @@ var ReplicatorExtension = class {
262
272
  S: this,
263
273
  C: (f, a) => f(...a)
264
274
  });
265
- (0, import_tiny_invariant.default)(this._extensionContext.initiator === true, "Invalid call");
266
- (0, import_tiny_invariant.default)(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`);
275
+ (0, import_invariant.invariant)(this._extensionContext.initiator === true, "Invalid call", {
276
+ F: __dxlog_file,
277
+ L: 181,
278
+ S: this,
279
+ A: [
280
+ "this._extensionContext!.initiator === true",
281
+ "'Invalid call'"
282
+ ]
283
+ });
284
+ (0, import_invariant.invariant)(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`, {
285
+ F: __dxlog_file,
286
+ L: 182,
287
+ S: this,
288
+ A: [
289
+ "!this._streams.has(feedInfo.feedKey)",
290
+ "`Replication already in progress for feed: ${feedInfo.feedKey}`"
291
+ ]
292
+ });
267
293
  const { streamTag } = await this._rpc.rpc.ReplicatorService.startReplication({
268
294
  info: feedInfo
269
295
  });
@@ -277,7 +303,15 @@ var ReplicatorExtension = class {
277
303
  * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.
278
304
  */
279
305
  async _acceptReplication(feedInfo) {
280
- (0, import_tiny_invariant.default)(this._extensionContext.initiator === false, "Invalid call");
306
+ (0, import_invariant.invariant)(this._extensionContext.initiator === false, "Invalid call", {
307
+ F: __dxlog_file,
308
+ L: 197,
309
+ S: this,
310
+ A: [
311
+ "this._extensionContext!.initiator === false",
312
+ "'Invalid call'"
313
+ ]
314
+ });
281
315
  if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {
282
316
  return void 0;
283
317
  }
@@ -286,7 +320,6 @@ var ReplicatorExtension = class {
286
320
  return tag;
287
321
  }
288
322
  async _replicateFeed(info, streamTag) {
289
- var _a;
290
323
  (0, import_log.log)("replicate", {
291
324
  info,
292
325
  streamTag
@@ -296,8 +329,16 @@ var ReplicatorExtension = class {
296
329
  S: this,
297
330
  C: (f, a) => f(...a)
298
331
  });
299
- (0, import_tiny_invariant.default)(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`);
300
- const feed = (_a = this._feeds.get(info.feedKey)) != null ? _a : (0, import_debug.failUndefined)();
332
+ (0, import_invariant.invariant)(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`, {
333
+ F: __dxlog_file,
334
+ L: 210,
335
+ S: this,
336
+ A: [
337
+ "!this._streams.has(info.feedKey)",
338
+ "`Replication already in progress for feed: ${info.feedKey}`"
339
+ ]
340
+ });
341
+ const feed = this._feeds.get(info.feedKey) ?? (0, import_debug.failUndefined)();
301
342
  const networkStream = await this._extensionContext.createStream(streamTag, {
302
343
  contentType: "application/x-hypercore"
303
344
  });
@@ -309,7 +350,7 @@ var ReplicatorExtension = class {
309
350
  encrypted: false
310
351
  });
311
352
  replicationStream.on("error", (err) => {
312
- if ((err == null ? void 0 : err.message) === "Writable stream closed prematurely" || (err == null ? void 0 : err.message) === "Cannot call write after a stream was destroyed") {
353
+ if (err?.message === "Writable stream closed prematurely" || err?.message === "Cannot call write after a stream was destroyed") {
313
354
  return;
314
355
  }
315
356
  import_log.log.warn("replication stream error", {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/index.ts", "../../../src/replicator-extension.ts"],
4
- "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nexport * from './replicator-extension';\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport type { ProtocolStream } from 'hypercore-protocol';\nimport { Duplex } from 'node:stream';\nimport invariant from 'tiny-invariant';\n\nimport { asyncTimeout, DeferredTask, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { FeedWrapper } from '@dxos/feed-store';\nimport { PublicKey } from '@dxos/keys';\nimport { log, logInfo } from '@dxos/log';\nimport { schema, RpcClosedError } from '@dxos/protocols';\nimport { FeedInfo, ReplicatorService } from '@dxos/protocols/proto/dxos/mesh/teleport/replicator';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\nimport { ExtensionContext, TeleportExtension } from '@dxos/teleport';\nimport { ComplexMap } from '@dxos/util';\n\nexport type ReplicationOptions = {\n upload: boolean;\n};\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class ReplicatorExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n log.catch(err);\n this._extensionContext?.close(err);\n },\n });\n\n private readonly _feeds = new ComplexMap<PublicKey, FeedWrapper<any>>(PublicKey.hash);\n private readonly _streams = new ComplexMap<PublicKey, ActiveStream>(PublicKey.hash);\n\n private _rpc?: ProtoRpcPeer<ServiceBundle>;\n private _extensionContext?: ExtensionContext;\n\n private _options: ReplicationOptions = {\n upload: false,\n };\n\n private readonly _updateTask = new DeferredTask(this._ctx, async () => {\n try {\n if (this._extensionContext!.initiator === false) {\n await this._rpc!.rpc.ReplicatorService.updateFeeds({\n feeds: Array.from(this._feeds.values()).map((feed) => ({\n feedKey: feed.key,\n download: true,\n upload: this._options.upload,\n })),\n });\n } else if (this._extensionContext!.initiator === true) {\n await this._reevaluateFeeds();\n }\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return; // Some RPC requests might be pending while closing.\n }\n throw err;\n }\n });\n\n @logInfo\n private get extensionInfo() {\n return {\n initiator: this._extensionContext?.initiator,\n localPeerId: this._extensionContext?.localPeerId,\n remotePeerId: this._extensionContext?.remotePeerId,\n feeds: Array.from(this._feeds.keys()),\n };\n }\n\n setOptions(options: ReplicationOptions): this {\n this._options = options;\n log('setOptions', { options });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n return this;\n }\n\n addFeed(feed: FeedWrapper<any>) {\n this._feeds.set(feed.key, feed);\n log('addFeed', { feedKey: feed.key });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n }\n\n async onOpen(context: ExtensionContext) {\n this._extensionContext = context;\n log('open');\n\n this._rpc = createProtoRpcPeer<ServiceBundle, ServiceBundle>({\n requested: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n exposed: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n handlers: {\n ReplicatorService: {\n updateFeeds: async ({ feeds }) => {\n log('received feed info', { feeds });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n this._updateTask.schedule();\n },\n startReplication: async ({ info }) => {\n log('starting replication...', { info });\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n const streamTag = await this._acceptReplication(info);\n return {\n streamTag,\n };\n },\n stopReplication: async ({ info }) => {\n log('stopping replication...', { info });\n // TODO(dmaretskyi): Make sure any peer can stop replication.\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n await this._stopReplication(info.feedKey);\n },\n },\n },\n port: await context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n });\n await this._rpc.open();\n\n this._updateTask.schedule();\n }\n\n async onClose(err?: Error | undefined) {\n log('close', { err });\n await this._ctx.dispose();\n await this._rpc?.close();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n @synchronized\n private async _reevaluateFeeds() {\n log('_reevaluateFeeds');\n for (const feedKey of this._feeds.keys()) {\n if (this._ctx.disposed) {\n return;\n }\n if (this._streams.has(feedKey) && this._options.upload !== this._streams.get(feedKey)?.info.upload) {\n try {\n await asyncTimeout(this._stopReplication(feedKey), 1000);\n } catch (err) {\n log.catch(err);\n }\n }\n\n if (this._ctx.disposed) {\n return;\n }\n if (!this._streams.has(feedKey)) {\n await this._initiateReplication({\n feedKey,\n download: true,\n upload: this._options.upload,\n });\n }\n }\n }\n\n /**\n * Try to initiate feed replication.\n */\n private async _initiateReplication(feedInfo: FeedInfo) {\n log('initiating replication', { feedInfo });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`);\n const { streamTag } = await this._rpc!.rpc.ReplicatorService.startReplication({ info: feedInfo });\n if (!streamTag) {\n return;\n }\n\n await this._replicateFeed(feedInfo, streamTag);\n }\n\n /**\n * Respond to a remote request to replicate a feed.\n * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.\n */\n @synchronized\n private async _acceptReplication(feedInfo: FeedInfo): Promise<string | undefined> {\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {\n return undefined; // We don't have the feed or we are already replicating it.\n }\n\n const tag = `feed-${feedInfo.feedKey.toHex()}-${PublicKey.random().toHex().slice(0, 8)}`; // Generate a unique tag for the stream.\n await this._replicateFeed(feedInfo, tag);\n return tag;\n }\n\n private async _replicateFeed(info: FeedInfo, streamTag: string) {\n log('replicate', { info, streamTag });\n invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`);\n\n const feed = this._feeds.get(info.feedKey) ?? failUndefined();\n const networkStream = await this._extensionContext!.createStream(streamTag, {\n contentType: 'application/x-hypercore',\n });\n const replicationStream = feed.replicate(true, {\n live: true,\n upload: info.upload,\n download: info.download,\n noise: false,\n encrypted: false,\n });\n\n // left for testing\n // feed.on('download', (index: number, data: any) => {\n // log('download', {\n // key: info.feedKey,\n // index\n // });\n // });\n\n replicationStream.on('error', (err) => {\n if (\n err?.message === 'Writable stream closed prematurely' ||\n err?.message === 'Cannot call write after a stream was destroyed'\n ) {\n return;\n }\n\n log.warn('replication stream error', { err, info });\n });\n\n this._streams.set(info.feedKey, {\n streamTag,\n networkStream,\n replicationStream,\n info,\n });\n\n networkStream.pipe(replicationStream as any).pipe(networkStream);\n }\n\n private async _stopReplication(feedKey: PublicKey) {\n const stream = this._streams.get(feedKey);\n if (!stream) {\n return;\n }\n\n stream.networkStream.destroy();\n this._streams.delete(feedKey);\n }\n}\n\ntype ServiceBundle = {\n ReplicatorService: ReplicatorService;\n};\n\ntype ActiveStream = {\n streamTag: string;\n networkStream: Duplex;\n replicationStream: ProtocolStream;\n info: FeedInfo;\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nexport * from './replicator-extension';\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport type { ProtocolStream } from 'hypercore-protocol';\nimport { Duplex } from 'node:stream';\n\nimport { asyncTimeout, DeferredTask, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { FeedWrapper } from '@dxos/feed-store';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log, logInfo } from '@dxos/log';\nimport { schema, RpcClosedError } from '@dxos/protocols';\nimport { FeedInfo, ReplicatorService } from '@dxos/protocols/proto/dxos/mesh/teleport/replicator';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\nimport { ExtensionContext, TeleportExtension } from '@dxos/teleport';\nimport { ComplexMap } from '@dxos/util';\n\nexport type ReplicationOptions = {\n upload: boolean;\n};\n\n/**\n * Manages replication between a set of feeds for a single teleport session.\n */\nexport class ReplicatorExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n log.catch(err);\n this._extensionContext?.close(err);\n },\n });\n\n private readonly _feeds = new ComplexMap<PublicKey, FeedWrapper<any>>(PublicKey.hash);\n private readonly _streams = new ComplexMap<PublicKey, ActiveStream>(PublicKey.hash);\n\n private _rpc?: ProtoRpcPeer<ServiceBundle>;\n private _extensionContext?: ExtensionContext;\n\n private _options: ReplicationOptions = {\n upload: false,\n };\n\n private readonly _updateTask = new DeferredTask(this._ctx, async () => {\n try {\n if (this._extensionContext!.initiator === false) {\n await this._rpc!.rpc.ReplicatorService.updateFeeds({\n feeds: Array.from(this._feeds.values()).map((feed) => ({\n feedKey: feed.key,\n download: true,\n upload: this._options.upload,\n })),\n });\n } else if (this._extensionContext!.initiator === true) {\n await this._reevaluateFeeds();\n }\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return; // Some RPC requests might be pending while closing.\n }\n throw err;\n }\n });\n\n @logInfo\n private get extensionInfo() {\n return {\n initiator: this._extensionContext?.initiator,\n localPeerId: this._extensionContext?.localPeerId,\n remotePeerId: this._extensionContext?.remotePeerId,\n feeds: Array.from(this._feeds.keys()),\n };\n }\n\n setOptions(options: ReplicationOptions): this {\n this._options = options;\n log('setOptions', { options });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n return this;\n }\n\n addFeed(feed: FeedWrapper<any>) {\n this._feeds.set(feed.key, feed);\n log('addFeed', { feedKey: feed.key });\n if (this._extensionContext) {\n this._updateTask.schedule();\n }\n }\n\n async onOpen(context: ExtensionContext) {\n this._extensionContext = context;\n log('open');\n\n this._rpc = createProtoRpcPeer<ServiceBundle, ServiceBundle>({\n requested: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n exposed: {\n ReplicatorService: schema.getService('dxos.mesh.teleport.replicator.ReplicatorService'),\n },\n handlers: {\n ReplicatorService: {\n updateFeeds: async ({ feeds }) => {\n log('received feed info', { feeds });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n this._updateTask.schedule();\n },\n startReplication: async ({ info }) => {\n log('starting replication...', { info });\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n const streamTag = await this._acceptReplication(info);\n return {\n streamTag,\n };\n },\n stopReplication: async ({ info }) => {\n log('stopping replication...', { info });\n // TODO(dmaretskyi): Make sure any peer can stop replication.\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n await this._stopReplication(info.feedKey);\n },\n },\n },\n port: await context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n });\n await this._rpc.open();\n\n this._updateTask.schedule();\n }\n\n async onClose(err?: Error | undefined) {\n log('close', { err });\n await this._ctx.dispose();\n await this._rpc?.close();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n @synchronized\n private async _reevaluateFeeds() {\n log('_reevaluateFeeds');\n for (const feedKey of this._feeds.keys()) {\n if (this._ctx.disposed) {\n return;\n }\n if (this._streams.has(feedKey) && this._options.upload !== this._streams.get(feedKey)?.info.upload) {\n try {\n await asyncTimeout(this._stopReplication(feedKey), 1000);\n } catch (err) {\n log.catch(err);\n }\n }\n\n if (this._ctx.disposed) {\n return;\n }\n if (!this._streams.has(feedKey)) {\n await this._initiateReplication({\n feedKey,\n download: true,\n upload: this._options.upload,\n });\n }\n }\n }\n\n /**\n * Try to initiate feed replication.\n */\n private async _initiateReplication(feedInfo: FeedInfo) {\n log('initiating replication', { feedInfo });\n invariant(this._extensionContext!.initiator === true, 'Invalid call');\n invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`);\n const { streamTag } = await this._rpc!.rpc.ReplicatorService.startReplication({ info: feedInfo });\n if (!streamTag) {\n return;\n }\n\n await this._replicateFeed(feedInfo, streamTag);\n }\n\n /**\n * Respond to a remote request to replicate a feed.\n * @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.\n */\n @synchronized\n private async _acceptReplication(feedInfo: FeedInfo): Promise<string | undefined> {\n invariant(this._extensionContext!.initiator === false, 'Invalid call');\n\n if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {\n return undefined; // We don't have the feed or we are already replicating it.\n }\n\n const tag = `feed-${feedInfo.feedKey.toHex()}-${PublicKey.random().toHex().slice(0, 8)}`; // Generate a unique tag for the stream.\n await this._replicateFeed(feedInfo, tag);\n return tag;\n }\n\n private async _replicateFeed(info: FeedInfo, streamTag: string) {\n log('replicate', { info, streamTag });\n invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`);\n\n const feed = this._feeds.get(info.feedKey) ?? failUndefined();\n const networkStream = await this._extensionContext!.createStream(streamTag, {\n contentType: 'application/x-hypercore',\n });\n const replicationStream = feed.replicate(true, {\n live: true,\n upload: info.upload,\n download: info.download,\n noise: false,\n encrypted: false,\n });\n\n // left for testing\n // feed.on('download', (index: number, data: any) => {\n // log('download', {\n // key: info.feedKey,\n // index\n // });\n // });\n\n replicationStream.on('error', (err) => {\n if (\n err?.message === 'Writable stream closed prematurely' ||\n err?.message === 'Cannot call write after a stream was destroyed'\n ) {\n return;\n }\n\n log.warn('replication stream error', { err, info });\n });\n\n this._streams.set(info.feedKey, {\n streamTag,\n networkStream,\n replicationStream,\n info,\n });\n\n networkStream.pipe(replicationStream as any).pipe(networkStream);\n }\n\n private async _stopReplication(feedKey: PublicKey) {\n const stream = this._streams.get(feedKey);\n if (!stream) {\n return;\n }\n\n stream.networkStream.destroy();\n this._streams.delete(feedKey);\n }\n}\n\ntype ServiceBundle = {\n ReplicatorService: ReplicatorService;\n};\n\ntype ActiveStream = {\n streamTag: string;\n networkStream: Duplex;\n replicationStream: ProtocolStream;\n info: FeedInfo;\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;ACOA,mBAAyD;AACzD,qBAAwB;AACxB,mBAA8B;AAE9B,uBAA0B;AAC1B,kBAA0B;AAC1B,iBAA6B;AAC7B,uBAAuC;AAEvC,iBAAiD;AAEjD,kBAA2B;;;;;;;;;;;;AASpB,IAAMA,sBAAN,MAAMA;EAAN;AACYC,gBAAO,IAAIC,uBAAQ;MAClCC,SAAS,CAACC,QAAAA;AACRC,uBAAIC,MAAMF,KAAAA,QAAAA;;;;;;AACV,aAAKG,mBAAmBC,MAAMJ,GAAAA;MAChC;IACF,CAAA;AAEiBK,kBAAS,IAAIC,uBAAwCC,sBAAUC,IAAI;AACnEC,oBAAW,IAAIH,uBAAoCC,sBAAUC,IAAI;AAK1EE,oBAA+B;MACrCC,QAAQ;IACV;AAEiBC,uBAAc,IAAIC,0BAAa,KAAKhB,MAAM,YAAA;AACzD,UAAI;AACF,YAAI,KAAKM,kBAAmBW,cAAc,OAAO;AAC/C,gBAAM,KAAKC,KAAMC,IAAIC,kBAAkBC,YAAY;YACjDC,OAAOC,MAAMC,KAAK,KAAKhB,OAAOiB,OAAM,CAAA,EAAIC,IAAI,CAACC,UAAU;cACrDC,SAASD,KAAKE;cACdC,UAAU;cACVhB,QAAQ,KAAKD,SAASC;YACxB,EAAA;UACF,CAAA;QACF,WAAW,KAAKR,kBAAmBW,cAAc,MAAM;AACrD,gBAAM,KAAKc,iBAAgB;QAC7B;MACF,SAAS5B,KAAK;AACZ,YAAIA,eAAe6B,iCAAgB;AACjC;QACF;AACA,cAAM7B;MACR;IACF,CAAA;;EAEA,IACY8B,gBAAgB;AAC1B,WAAO;MACLhB,WAAW,KAAKX,mBAAmBW;MACnCiB,aAAa,KAAK5B,mBAAmB4B;MACrCC,cAAc,KAAK7B,mBAAmB6B;MACtCb,OAAOC,MAAMC,KAAK,KAAKhB,OAAO4B,KAAI,CAAA;IACpC;EACF;EAEAC,WAAWC,SAAmC;AAC5C,SAAKzB,WAAWyB;AAChBlC,wBAAI,cAAc;MAAEkC;IAAQ,GAAA;;;;;;AAC5B,QAAI,KAAKhC,mBAAmB;AAC1B,WAAKS,YAAYwB,SAAQ;IAC3B;AACA,WAAO;EACT;EAEAC,QAAQb,MAAwB;AAC9B,SAAKnB,OAAOiC,IAAId,KAAKE,KAAKF,IAAAA;AAC1BvB,wBAAI,WAAW;MAAEwB,SAASD,KAAKE;IAAI,GAAA;;;;;;AACnC,QAAI,KAAKvB,mBAAmB;AAC1B,WAAKS,YAAYwB,SAAQ;IAC3B;EACF;EAEA,MAAMG,OAAOC,SAA2B;AACtC,SAAKrC,oBAAoBqC;AACzBvC,wBAAI,QAAA,QAAA;;;;;;AAEJ,SAAKc,WAAO0B,+BAAiD;MAC3DC,WAAW;QACTzB,mBAAmB0B,wBAAOC,WAAW,iDAAA;MACvC;MACAC,SAAS;QACP5B,mBAAmB0B,wBAAOC,WAAW,iDAAA;MACvC;MACAE,UAAU;QACR7B,mBAAmB;UACjBC,aAAa,OAAO,EAAEC,MAAK,MAAE;AAC3BlB,gCAAI,sBAAsB;cAAEkB;YAAM,GAAA;;;;;;AAClC4B,4CAAU,KAAK5C,kBAAmBW,cAAc,MAAM,gBAAA;;;;;;;;;AACtD,iBAAKF,YAAYwB,SAAQ;UAC3B;UACAY,kBAAkB,OAAO,EAAEC,KAAI,MAAE;AAC/BhD,gCAAI,2BAA2B;cAAEgD;YAAK,GAAA;;;;;;AACtCF,4CAAU,KAAK5C,kBAAmBW,cAAc,OAAO,gBAAA;;;;;;;;;AAEvD,kBAAMoC,YAAY,MAAM,KAAKC,mBAAmBF,IAAAA;AAChD,mBAAO;cACLC;YACF;UACF;UACAE,iBAAiB,OAAO,EAAEH,KAAI,MAAE;AAC9BhD,gCAAI,2BAA2B;cAAEgD;YAAK,GAAA;;;;;;AAEtCF,4CAAU,KAAK5C,kBAAmBW,cAAc,OAAO,gBAAA;;;;;;;;;AAEvD,kBAAM,KAAKuC,iBAAiBJ,KAAKxB,OAAO;UAC1C;QACF;MACF;MACA6B,MAAM,MAAMd,QAAQe,WAAW,OAAO;QACpCC,aAAa;MACf,CAAA;IACF,CAAA;AACA,UAAM,KAAKzC,KAAK0C,KAAI;AAEpB,SAAK7C,YAAYwB,SAAQ;EAC3B;EAEA,MAAMsB,QAAQ1D,KAAyB;AACrCC,wBAAI,SAAS;MAAED;IAAI,GAAA;;;;;;AACnB,UAAM,KAAKH,KAAK8D,QAAO;AACvB,UAAM,KAAK5C,MAAMX,MAAAA;AACjB,eAAWqB,WAAW,KAAKhB,SAASwB,KAAI,GAAI;AAC1C,YAAM,KAAKoB,iBAAiB5B,OAAAA;IAC9B;EACF;EAEA,MACcG,mBAAmB;AAC/B3B,wBAAI,oBAAA,QAAA;;;;;;AACJ,eAAWwB,WAAW,KAAKpB,OAAO4B,KAAI,GAAI;AACxC,UAAI,KAAKpC,KAAK+D,UAAU;AACtB;MACF;AACA,UAAI,KAAKnD,SAASoD,IAAIpC,OAAAA,KAAY,KAAKf,SAASC,WAAW,KAAKF,SAASqD,IAAIrC,OAAAA,GAAUwB,KAAKtC,QAAQ;AAClG,YAAI;AACF,oBAAMoD,2BAAa,KAAKV,iBAAiB5B,OAAAA,GAAU,GAAA;QACrD,SAASzB,KAAK;AACZC,yBAAIC,MAAMF,KAAAA,QAAAA;;;;;;QACZ;MACF;AAEA,UAAI,KAAKH,KAAK+D,UAAU;AACtB;MACF;AACA,UAAI,CAAC,KAAKnD,SAASoD,IAAIpC,OAAAA,GAAU;AAC/B,cAAM,KAAKuC,qBAAqB;UAC9BvC;UACAE,UAAU;UACVhB,QAAQ,KAAKD,SAASC;QACxB,CAAA;MACF;IACF;EACF;;;;EAKA,MAAcqD,qBAAqBC,UAAoB;AACrDhE,wBAAI,0BAA0B;MAAEgE;IAAS,GAAA;;;;;;AACzClB,oCAAU,KAAK5C,kBAAmBW,cAAc,MAAM,gBAAA;;;;;;;;;AACtDiC,oCAAU,CAAC,KAAKtC,SAASoD,IAAII,SAASxC,OAAO,GAAG,6CAA6CwC,SAASxC,OAAO,IAAE;;;;;;;;;AAC/G,UAAM,EAAEyB,UAAS,IAAK,MAAM,KAAKnC,KAAMC,IAAIC,kBAAkB+B,iBAAiB;MAAEC,MAAMgB;IAAS,CAAA;AAC/F,QAAI,CAACf,WAAW;AACd;IACF;AAEA,UAAM,KAAKgB,eAAeD,UAAUf,SAAAA;EACtC;;;;;EAMA,MACcC,mBAAmBc,UAAiD;AAChFlB,oCAAU,KAAK5C,kBAAmBW,cAAc,OAAO,gBAAA;;;;;;;;;AAEvD,QAAI,CAAC,KAAKT,OAAOwD,IAAII,SAASxC,OAAO,KAAK,KAAKhB,SAASoD,IAAII,SAASxC,OAAO,GAAG;AAC7E,aAAO0C;IACT;AAEA,UAAMC,MAAM,QAAQH,SAASxC,QAAQ4C,MAAK,CAAA,IAAM9D,sBAAU+D,OAAM,EAAGD,MAAK,EAAGE,MAAM,GAAG,CAAA,CAAA;AACpF,UAAM,KAAKL,eAAeD,UAAUG,GAAAA;AACpC,WAAOA;EACT;EAEA,MAAcF,eAAejB,MAAgBC,WAAmB;AAC9DjD,wBAAI,aAAa;MAAEgD;MAAMC;IAAU,GAAA;;;;;;AACnCH,oCAAU,CAAC,KAAKtC,SAASoD,IAAIZ,KAAKxB,OAAO,GAAG,6CAA6CwB,KAAKxB,OAAO,IAAE;;;;;;;;;AAEvG,UAAMD,OAAO,KAAKnB,OAAOyD,IAAIb,KAAKxB,OAAO,SAAK+C,4BAAAA;AAC9C,UAAMC,gBAAgB,MAAM,KAAKtE,kBAAmBuE,aAAaxB,WAAW;MAC1EM,aAAa;IACf,CAAA;AACA,UAAMmB,oBAAoBnD,KAAKoD,UAAU,MAAM;MAC7CC,MAAM;MACNlE,QAAQsC,KAAKtC;MACbgB,UAAUsB,KAAKtB;MACfmD,OAAO;MACPC,WAAW;IACb,CAAA;AAUAJ,sBAAkBK,GAAG,SAAS,CAAChF,QAAAA;AAC7B,UACEA,KAAKiF,YAAY,wCACjBjF,KAAKiF,YAAY,kDACjB;AACA;MACF;AAEAhF,qBAAIiF,KAAK,4BAA4B;QAAElF;QAAKiD;MAAK,GAAA;;;;;;IACnD,CAAA;AAEA,SAAKxC,SAAS6B,IAAIW,KAAKxB,SAAS;MAC9ByB;MACAuB;MACAE;MACA1B;IACF,CAAA;AAEAwB,kBAAcU,KAAKR,iBAAAA,EAA0BQ,KAAKV,aAAAA;EACpD;EAEA,MAAcpB,iBAAiB5B,SAAoB;AACjD,UAAM2D,SAAS,KAAK3E,SAASqD,IAAIrC,OAAAA;AACjC,QAAI,CAAC2D,QAAQ;AACX;IACF;AAEAA,WAAOX,cAAcY,QAAO;AAC5B,SAAK5E,SAAS6E,OAAO7D,OAAAA;EACvB;AACF;;EAnMG8D;GAvCU3F,oBAAAA,WAAAA,iBAAAA,IAAAA;;EAwHV4F;GAxHU5F,oBAAAA,WAAAA,oBAAAA,IAAAA;;EAuKV4F;GAvKU5F,oBAAAA,WAAAA,sBAAAA,IAAAA;",
6
6
  "names": ["ReplicatorExtension", "_ctx", "Context", "onError", "err", "log", "catch", "_extensionContext", "close", "_feeds", "ComplexMap", "PublicKey", "hash", "_streams", "_options", "upload", "_updateTask", "DeferredTask", "initiator", "_rpc", "rpc", "ReplicatorService", "updateFeeds", "feeds", "Array", "from", "values", "map", "feed", "feedKey", "key", "download", "_reevaluateFeeds", "RpcClosedError", "extensionInfo", "localPeerId", "remotePeerId", "keys", "setOptions", "options", "schedule", "addFeed", "set", "onOpen", "context", "createProtoRpcPeer", "requested", "schema", "getService", "exposed", "handlers", "invariant", "startReplication", "info", "streamTag", "_acceptReplication", "stopReplication", "_stopReplication", "port", "createPort", "contentType", "open", "onClose", "dispose", "disposed", "has", "get", "asyncTimeout", "_initiateReplication", "feedInfo", "_replicateFeed", "undefined", "tag", "toHex", "random", "slice", "failUndefined", "networkStream", "createStream", "replicationStream", "replicate", "live", "noise", "encrypted", "on", "message", "warn", "pipe", "stream", "destroy", "delete", "logInfo", "synchronized"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts":{"bytes":31881,"imports":[{"path":"tiny-invariant","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}]},"packages/core/mesh/teleport-extension-replicator/src/index.ts":{"bytes":520,"imports":[{"path":"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts","kind":"import-statement","original":"./replicator-extension"}]}},"outputs":{"packages/core/mesh/teleport-extension-replicator/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14777},"packages/core/mesh/teleport-extension-replicator/dist/lib/node/index.cjs":{"imports":[{"path":"tiny-invariant","kind":"require-call","external":true},{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/context","kind":"require-call","external":true},{"path":"@dxos/debug","kind":"require-call","external":true},{"path":"@dxos/keys","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"@dxos/protocols","kind":"require-call","external":true},{"path":"@dxos/rpc","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true}],"exports":[],"entryPoint":"packages/core/mesh/teleport-extension-replicator/src/index.ts","inputs":{"packages/core/mesh/teleport-extension-replicator/src/index.ts":{"bytesInOutput":143},"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts":{"bytesInOutput":10042}},"bytes":11876}}}
1
+ {"inputs":{"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts":{"bytes":33894,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/context","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/protocols","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/core/mesh/teleport-extension-replicator/src/index.ts":{"bytes":520,"imports":[{"path":"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts","kind":"import-statement","original":"./replicator-extension"}],"format":"esm"}},"outputs":{"packages/core/mesh/teleport-extension-replicator/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14739},"packages/core/mesh/teleport-extension-replicator/dist/lib/node/index.cjs":{"imports":[{"path":"@dxos/async","kind":"require-call","external":true},{"path":"@dxos/context","kind":"require-call","external":true},{"path":"@dxos/debug","kind":"require-call","external":true},{"path":"@dxos/invariant","kind":"require-call","external":true},{"path":"@dxos/keys","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"@dxos/protocols","kind":"require-call","external":true},{"path":"@dxos/rpc","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true}],"exports":[],"entryPoint":"packages/core/mesh/teleport-extension-replicator/src/index.ts","inputs":{"packages/core/mesh/teleport-extension-replicator/src/index.ts":{"bytesInOutput":143},"packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts":{"bytesInOutput":11083}},"bytes":12320}}}
@@ -1 +1 @@
1
- {"version":3,"file":"replicator-extension.d.ts","sourceRoot":"","sources":["../../../src/replicator-extension.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAM/C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAKlB;IAEH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+D;IACtF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2D;IAEpF,OAAO,CAAC,IAAI,CAAC,CAA8B;IAC3C,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAE7C,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAmBzB;IAGH,OAAO,KAAK,aAAa,GAOxB;IAED,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAS7C,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC;IAQxB,MAAM,CAAC,OAAO,EAAE,gBAAgB;IA6ChC,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS;YAUvB,gBAAgB;IA2B9B;;OAEG;YACW,oBAAoB;IAYlC;;;OAGG;YAEW,kBAAkB;YAYlB,cAAc;YA6Cd,gBAAgB;CAS/B"}
1
+ {"version":3,"file":"replicator-extension.d.ts","sourceRoot":"","sources":["../../../src/replicator-extension.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAO/C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAKlB;IAEH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+D;IACtF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2D;IAEpF,OAAO,CAAC,IAAI,CAAC,CAA8B;IAC3C,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAE7C,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAmBzB;IAGH,OAAO,KAAK,aAAa,GAOxB;IAED,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAS7C,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC;IAQxB,MAAM,CAAC,OAAO,EAAE,gBAAgB;IA6ChC,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS;YAUvB,gBAAgB;IA2B9B;;OAEG;YACW,oBAAoB;IAYlC;;;OAGG;YAEW,kBAAkB;YAYlB,cAAc;YA6Cd,gBAAgB;CAS/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/teleport-extension-replicator",
3
- "version": "0.1.56-main.e47dfd1",
3
+ "version": "0.1.56-main.ed2f871",
4
4
  "description": "Replicator extension for teleport.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -16,25 +16,25 @@
16
16
  "src"
17
17
  ],
18
18
  "dependencies": {
19
- "tiny-invariant": "^1.3.1",
20
- "@dxos/async": "0.1.56-main.e47dfd1",
21
- "@dxos/context": "0.1.56-main.e47dfd1",
22
- "@dxos/debug": "0.1.56-main.e47dfd1",
23
- "@dxos/feed-store": "0.1.56-main.e47dfd1",
24
- "@dxos/keys": "0.1.56-main.e47dfd1",
25
- "@dxos/log": "0.1.56-main.e47dfd1",
26
- "@dxos/node-std": "0.1.56-main.e47dfd1",
27
- "@dxos/protocols": "0.1.56-main.e47dfd1",
28
- "@dxos/rpc": "0.1.56-main.e47dfd1",
29
- "@dxos/teleport": "0.1.56-main.e47dfd1",
30
- "@dxos/util": "0.1.56-main.e47dfd1"
19
+ "@dxos/async": "0.1.56-main.ed2f871",
20
+ "@dxos/context": "0.1.56-main.ed2f871",
21
+ "@dxos/debug": "0.1.56-main.ed2f871",
22
+ "@dxos/feed-store": "0.1.56-main.ed2f871",
23
+ "@dxos/invariant": "0.1.56-main.ed2f871",
24
+ "@dxos/keys": "0.1.56-main.ed2f871",
25
+ "@dxos/log": "0.1.56-main.ed2f871",
26
+ "@dxos/node-std": "0.1.56-main.ed2f871",
27
+ "@dxos/protocols": "0.1.56-main.ed2f871",
28
+ "@dxos/rpc": "0.1.56-main.ed2f871",
29
+ "@dxos/teleport": "0.1.56-main.ed2f871",
30
+ "@dxos/util": "0.1.56-main.ed2f871"
31
31
  },
32
32
  "devDependencies": {
33
33
  "add": "^2.0.6",
34
34
  "fast-check": "~3.3.0",
35
35
  "typescript": "^5.0.4",
36
- "@dxos/keyring": "0.1.56-main.e47dfd1",
37
- "@dxos/random-access-storage": "0.1.56-main.e47dfd1"
36
+ "@dxos/keyring": "0.1.56-main.ed2f871",
37
+ "@dxos/random-access-storage": "0.1.56-main.ed2f871"
38
38
  },
39
39
  "publishConfig": {
40
40
  "access": "public"
@@ -4,12 +4,12 @@
4
4
 
5
5
  import type { ProtocolStream } from 'hypercore-protocol';
6
6
  import { Duplex } from 'node:stream';
7
- import invariant from 'tiny-invariant';
8
7
 
9
8
  import { asyncTimeout, DeferredTask, synchronized } from '@dxos/async';
10
9
  import { Context } from '@dxos/context';
11
10
  import { failUndefined } from '@dxos/debug';
12
11
  import { FeedWrapper } from '@dxos/feed-store';
12
+ import { invariant } from '@dxos/invariant';
13
13
  import { PublicKey } from '@dxos/keys';
14
14
  import { log, logInfo } from '@dxos/log';
15
15
  import { schema, RpcClosedError } from '@dxos/protocols';