@dxos/teleport-extension-replicator 0.8.3 → 0.8.4-main.03d5cd7b56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/{browser → neutral}/index.mjs +56 -195
- package/dist/lib/{browser → neutral}/index.mjs.map +3 -3
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/types/src/replicator-extension.d.ts +0 -7
- package/dist/types/src/replicator-extension.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -21
- package/src/replicator-extension.test.ts +1 -2
- package/src/replicator-extension.ts +2 -2
- package/src/stress.test.ts +7 -6
- package/src/testing.ts +1 -1
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/node/index.cjs +0 -439
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
- package/dist/lib/node-esm/index.mjs +0 -418
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "@dxos/node-std/globals";
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
import {
|
|
3
|
+
// src/replicator-extension.ts
|
|
4
|
+
import { DeferredTask, asyncTimeout, synchronized } from "@dxos/async";
|
|
5
5
|
import { Context } from "@dxos/context";
|
|
6
6
|
import { failUndefined } from "@dxos/debug";
|
|
7
7
|
import { invariant } from "@dxos/invariant";
|
|
@@ -11,49 +11,46 @@ import { RpcClosedError, TimeoutError } from "@dxos/protocols";
|
|
|
11
11
|
import { schema } from "@dxos/protocols/proto";
|
|
12
12
|
import { createProtoRpcPeer } from "@dxos/rpc";
|
|
13
13
|
import { ComplexMap } from "@dxos/util";
|
|
14
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts";
|
|
14
15
|
function _ts_decorate(decorators, target, key, desc) {
|
|
15
16
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
17
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
18
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
19
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
20
|
}
|
|
20
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport-extension-replicator/src/replicator-extension.ts";
|
|
21
21
|
var ReplicatorExtension = class {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
_ctx = new Context({
|
|
23
|
+
onError: (err) => {
|
|
24
|
+
this._extensionContext?.close(err);
|
|
25
|
+
}
|
|
26
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 23 });
|
|
27
|
+
_feeds = new ComplexMap(PublicKey.hash);
|
|
28
|
+
_streams = new ComplexMap(PublicKey.hash);
|
|
29
|
+
_rpc;
|
|
30
|
+
_extensionContext;
|
|
31
|
+
_options = {
|
|
32
|
+
upload: false
|
|
33
|
+
};
|
|
34
|
+
_updateTask = new DeferredTask(this._ctx, async () => {
|
|
35
|
+
try {
|
|
36
|
+
if (this._extensionContext.initiator === false) {
|
|
37
|
+
await this._rpc.rpc.ReplicatorService.updateFeeds({
|
|
38
|
+
feeds: Array.from(this._feeds.values()).map((feed) => ({
|
|
39
|
+
feedKey: feed.key,
|
|
40
|
+
download: true,
|
|
41
|
+
upload: this._options.upload
|
|
42
|
+
}))
|
|
43
|
+
});
|
|
44
|
+
} else if (this._extensionContext.initiator === true) {
|
|
45
|
+
await this._reevaluateFeeds();
|
|
26
46
|
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
this._feeds = new ComplexMap(PublicKey.hash);
|
|
32
|
-
this._streams = new ComplexMap(PublicKey.hash);
|
|
33
|
-
this._options = {
|
|
34
|
-
upload: false
|
|
35
|
-
};
|
|
36
|
-
this._updateTask = new DeferredTask(this._ctx, async () => {
|
|
37
|
-
try {
|
|
38
|
-
if (this._extensionContext.initiator === false) {
|
|
39
|
-
await this._rpc.rpc.ReplicatorService.updateFeeds({
|
|
40
|
-
feeds: Array.from(this._feeds.values()).map((feed) => ({
|
|
41
|
-
feedKey: feed.key,
|
|
42
|
-
download: true,
|
|
43
|
-
upload: this._options.upload
|
|
44
|
-
}))
|
|
45
|
-
});
|
|
46
|
-
} else if (this._extensionContext.initiator === true) {
|
|
47
|
-
await this._reevaluateFeeds();
|
|
48
|
-
}
|
|
49
|
-
} catch (err) {
|
|
50
|
-
if (err instanceof RpcClosedError) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
throw err;
|
|
47
|
+
} catch (err) {
|
|
48
|
+
if (err instanceof RpcClosedError) {
|
|
49
|
+
return;
|
|
54
50
|
}
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
57
54
|
get extensionInfo() {
|
|
58
55
|
return {
|
|
59
56
|
initiator: this._extensionContext?.initiator,
|
|
@@ -66,12 +63,7 @@ var ReplicatorExtension = class {
|
|
|
66
63
|
this._options = options;
|
|
67
64
|
log("setOptions", {
|
|
68
65
|
options
|
|
69
|
-
}, {
|
|
70
|
-
F: __dxlog_file,
|
|
71
|
-
L: 79,
|
|
72
|
-
S: this,
|
|
73
|
-
C: (f, a) => f(...a)
|
|
74
|
-
});
|
|
66
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 65, S: this });
|
|
75
67
|
if (this._extensionContext) {
|
|
76
68
|
this._updateTask.schedule();
|
|
77
69
|
}
|
|
@@ -81,24 +73,14 @@ var ReplicatorExtension = class {
|
|
|
81
73
|
this._feeds.set(feed.key, feed);
|
|
82
74
|
log("addFeed", {
|
|
83
75
|
feedKey: feed.key
|
|
84
|
-
}, {
|
|
85
|
-
F: __dxlog_file,
|
|
86
|
-
L: 88,
|
|
87
|
-
S: this,
|
|
88
|
-
C: (f, a) => f(...a)
|
|
89
|
-
});
|
|
76
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 75, S: this });
|
|
90
77
|
if (this._extensionContext) {
|
|
91
78
|
this._updateTask.schedule();
|
|
92
79
|
}
|
|
93
80
|
}
|
|
94
81
|
async onOpen(context) {
|
|
95
82
|
this._extensionContext = context;
|
|
96
|
-
log("open", void 0, {
|
|
97
|
-
F: __dxlog_file,
|
|
98
|
-
L: 96,
|
|
99
|
-
S: this,
|
|
100
|
-
C: (f, a) => f(...a)
|
|
101
|
-
});
|
|
83
|
+
log("open", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 84, S: this });
|
|
102
84
|
this._rpc = createProtoRpcPeer({
|
|
103
85
|
requested: {
|
|
104
86
|
ReplicatorService: schema.getService("dxos.mesh.teleport.replicator.ReplicatorService")
|
|
@@ -111,41 +93,15 @@ var ReplicatorExtension = class {
|
|
|
111
93
|
updateFeeds: async ({ feeds }) => {
|
|
112
94
|
log("received feed info", {
|
|
113
95
|
feeds
|
|
114
|
-
}, {
|
|
115
|
-
|
|
116
|
-
L: 108,
|
|
117
|
-
S: this,
|
|
118
|
-
C: (f, a) => f(...a)
|
|
119
|
-
});
|
|
120
|
-
invariant(this._extensionContext.initiator === true, "Invalid call", {
|
|
121
|
-
F: __dxlog_file,
|
|
122
|
-
L: 109,
|
|
123
|
-
S: this,
|
|
124
|
-
A: [
|
|
125
|
-
"this._extensionContext!.initiator === true",
|
|
126
|
-
"'Invalid call'"
|
|
127
|
-
]
|
|
128
|
-
});
|
|
96
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 95, S: this });
|
|
97
|
+
invariant(this._extensionContext.initiator === true, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 98, S: this, A: ["this._extensionContext.initiator === true", "'Invalid call'"] });
|
|
129
98
|
this._updateTask.schedule();
|
|
130
99
|
},
|
|
131
100
|
startReplication: async ({ info }) => {
|
|
132
101
|
log("starting replication...", {
|
|
133
102
|
info
|
|
134
|
-
}, {
|
|
135
|
-
|
|
136
|
-
L: 113,
|
|
137
|
-
S: this,
|
|
138
|
-
C: (f, a) => f(...a)
|
|
139
|
-
});
|
|
140
|
-
invariant(this._extensionContext.initiator === false, "Invalid call", {
|
|
141
|
-
F: __dxlog_file,
|
|
142
|
-
L: 114,
|
|
143
|
-
S: this,
|
|
144
|
-
A: [
|
|
145
|
-
"this._extensionContext!.initiator === false",
|
|
146
|
-
"'Invalid call'"
|
|
147
|
-
]
|
|
148
|
-
});
|
|
103
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 102, S: this });
|
|
104
|
+
invariant(this._extensionContext.initiator === false, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 105, S: this, A: ["this._extensionContext.initiator === false", "'Invalid call'"] });
|
|
149
105
|
const streamTag = await this._acceptReplication(info);
|
|
150
106
|
return {
|
|
151
107
|
streamTag
|
|
@@ -154,21 +110,8 @@ var ReplicatorExtension = class {
|
|
|
154
110
|
stopReplication: async ({ info }) => {
|
|
155
111
|
log("stopping replication...", {
|
|
156
112
|
info
|
|
157
|
-
}, {
|
|
158
|
-
|
|
159
|
-
L: 122,
|
|
160
|
-
S: this,
|
|
161
|
-
C: (f, a) => f(...a)
|
|
162
|
-
});
|
|
163
|
-
invariant(this._extensionContext.initiator === false, "Invalid call", {
|
|
164
|
-
F: __dxlog_file,
|
|
165
|
-
L: 124,
|
|
166
|
-
S: this,
|
|
167
|
-
A: [
|
|
168
|
-
"this._extensionContext!.initiator === false",
|
|
169
|
-
"'Invalid call'"
|
|
170
|
-
]
|
|
171
|
-
});
|
|
113
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 112, S: this });
|
|
114
|
+
invariant(this._extensionContext.initiator === false, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 116, S: this, A: ["this._extensionContext.initiator === false", "'Invalid call'"] });
|
|
172
115
|
await this._stopReplication(info.feedKey);
|
|
173
116
|
}
|
|
174
117
|
}
|
|
@@ -184,12 +127,7 @@ var ReplicatorExtension = class {
|
|
|
184
127
|
async onClose(err) {
|
|
185
128
|
log("close", {
|
|
186
129
|
err
|
|
187
|
-
}, {
|
|
188
|
-
F: __dxlog_file,
|
|
189
|
-
L: 141,
|
|
190
|
-
S: this,
|
|
191
|
-
C: (f, a) => f(...a)
|
|
192
|
-
});
|
|
130
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 130, S: this });
|
|
193
131
|
await this._ctx.dispose();
|
|
194
132
|
await this._rpc?.close();
|
|
195
133
|
for (const feedKey of this._streams.keys()) {
|
|
@@ -199,12 +137,7 @@ var ReplicatorExtension = class {
|
|
|
199
137
|
async onAbort(err) {
|
|
200
138
|
log("abort", {
|
|
201
139
|
err
|
|
202
|
-
}, {
|
|
203
|
-
F: __dxlog_file,
|
|
204
|
-
L: 150,
|
|
205
|
-
S: this,
|
|
206
|
-
C: (f, a) => f(...a)
|
|
207
|
-
});
|
|
140
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 140, S: this });
|
|
208
141
|
await this._ctx.dispose();
|
|
209
142
|
await this._rpc?.abort();
|
|
210
143
|
for (const feedKey of this._streams.keys()) {
|
|
@@ -212,12 +145,7 @@ var ReplicatorExtension = class {
|
|
|
212
145
|
}
|
|
213
146
|
}
|
|
214
147
|
async _reevaluateFeeds() {
|
|
215
|
-
log("_reevaluateFeeds", void 0, {
|
|
216
|
-
F: __dxlog_file,
|
|
217
|
-
L: 161,
|
|
218
|
-
S: this,
|
|
219
|
-
C: (f, a) => f(...a)
|
|
220
|
-
});
|
|
148
|
+
log("_reevaluateFeeds", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 150, S: this });
|
|
221
149
|
for (const feedKey of this._feeds.keys()) {
|
|
222
150
|
if (this._ctx.disposed) {
|
|
223
151
|
return;
|
|
@@ -226,12 +154,7 @@ var ReplicatorExtension = class {
|
|
|
226
154
|
try {
|
|
227
155
|
await asyncTimeout(this._stopReplication(feedKey), 1e3);
|
|
228
156
|
} catch (err) {
|
|
229
|
-
log.catch(err, void 0, {
|
|
230
|
-
F: __dxlog_file,
|
|
231
|
-
L: 170,
|
|
232
|
-
S: this,
|
|
233
|
-
C: (f, a) => f(...a)
|
|
234
|
-
});
|
|
157
|
+
log.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 159, S: this });
|
|
235
158
|
}
|
|
236
159
|
}
|
|
237
160
|
if (this._ctx.disposed) {
|
|
@@ -252,30 +175,9 @@ var ReplicatorExtension = class {
|
|
|
252
175
|
async _initiateReplication(feedInfo) {
|
|
253
176
|
log("initiating replication", {
|
|
254
177
|
feedInfo
|
|
255
|
-
}, {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
S: this,
|
|
259
|
-
C: (f, a) => f(...a)
|
|
260
|
-
});
|
|
261
|
-
invariant(this._extensionContext.initiator === true, "Invalid call", {
|
|
262
|
-
F: __dxlog_file,
|
|
263
|
-
L: 192,
|
|
264
|
-
S: this,
|
|
265
|
-
A: [
|
|
266
|
-
"this._extensionContext!.initiator === true",
|
|
267
|
-
"'Invalid call'"
|
|
268
|
-
]
|
|
269
|
-
});
|
|
270
|
-
invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`, {
|
|
271
|
-
F: __dxlog_file,
|
|
272
|
-
L: 193,
|
|
273
|
-
S: this,
|
|
274
|
-
A: [
|
|
275
|
-
"!this._streams.has(feedInfo.feedKey)",
|
|
276
|
-
"`Replication already in progress for feed: ${feedInfo.feedKey}`"
|
|
277
|
-
]
|
|
278
|
-
});
|
|
178
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 177, S: this });
|
|
179
|
+
invariant(this._extensionContext.initiator === true, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 180, S: this, A: ["this._extensionContext.initiator === true", "'Invalid call'"] });
|
|
180
|
+
invariant(!this._streams.has(feedInfo.feedKey), `Replication already in progress for feed: ${feedInfo.feedKey}`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 181, S: this, A: ["!this._streams.has(feedInfo.feedKey)", "`Replication already in progress for feed: ${feedInfo.feedKey}`"] });
|
|
279
181
|
const { streamTag } = await this._rpc.rpc.ReplicatorService.startReplication({
|
|
280
182
|
info: feedInfo
|
|
281
183
|
});
|
|
@@ -289,15 +191,7 @@ var ReplicatorExtension = class {
|
|
|
289
191
|
* @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.
|
|
290
192
|
*/
|
|
291
193
|
async _acceptReplication(feedInfo) {
|
|
292
|
-
invariant(this._extensionContext.initiator === false, "Invalid call", {
|
|
293
|
-
F: __dxlog_file,
|
|
294
|
-
L: 208,
|
|
295
|
-
S: this,
|
|
296
|
-
A: [
|
|
297
|
-
"this._extensionContext!.initiator === false",
|
|
298
|
-
"'Invalid call'"
|
|
299
|
-
]
|
|
300
|
-
});
|
|
194
|
+
invariant(this._extensionContext.initiator === false, "Invalid call", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 194, S: this, A: ["this._extensionContext.initiator === false", "'Invalid call'"] });
|
|
301
195
|
if (!this._feeds.has(feedInfo.feedKey) || this._streams.has(feedInfo.feedKey)) {
|
|
302
196
|
return void 0;
|
|
303
197
|
}
|
|
@@ -309,21 +203,8 @@ var ReplicatorExtension = class {
|
|
|
309
203
|
log("replicate", {
|
|
310
204
|
info,
|
|
311
205
|
streamTag
|
|
312
|
-
}, {
|
|
313
|
-
|
|
314
|
-
L: 220,
|
|
315
|
-
S: this,
|
|
316
|
-
C: (f, a) => f(...a)
|
|
317
|
-
});
|
|
318
|
-
invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`, {
|
|
319
|
-
F: __dxlog_file,
|
|
320
|
-
L: 221,
|
|
321
|
-
S: this,
|
|
322
|
-
A: [
|
|
323
|
-
"!this._streams.has(info.feedKey)",
|
|
324
|
-
"`Replication already in progress for feed: ${info.feedKey}`"
|
|
325
|
-
]
|
|
326
|
-
});
|
|
206
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 203, S: this });
|
|
207
|
+
invariant(!this._streams.has(info.feedKey), `Replication already in progress for feed: ${info.feedKey}`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 207, S: this, A: ["!this._streams.has(info.feedKey)", "`Replication already in progress for feed: ${info.feedKey}`"] });
|
|
327
208
|
const feed = this._feeds.get(info.feedKey) ?? failUndefined();
|
|
328
209
|
const networkStream = await this._extensionContext.createStream(streamTag, {
|
|
329
210
|
contentType: "application/x-hypercore"
|
|
@@ -342,47 +223,27 @@ var ReplicatorExtension = class {
|
|
|
342
223
|
log.info("replication stream timeout", {
|
|
343
224
|
err,
|
|
344
225
|
info
|
|
345
|
-
}, {
|
|
346
|
-
F: __dxlog_file,
|
|
347
|
-
L: 257,
|
|
348
|
-
S: this,
|
|
349
|
-
C: (f, a) => f(...a)
|
|
350
|
-
});
|
|
226
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 239, S: this });
|
|
351
227
|
return;
|
|
352
228
|
}
|
|
353
229
|
if (err?.message === "Writable stream closed prematurely" || err?.message === "Cannot call write after a stream was destroyed") {
|
|
354
230
|
log("replication stream closed", {
|
|
355
231
|
err,
|
|
356
232
|
info
|
|
357
|
-
}, {
|
|
358
|
-
F: __dxlog_file,
|
|
359
|
-
L: 265,
|
|
360
|
-
S: this,
|
|
361
|
-
C: (f, a) => f(...a)
|
|
362
|
-
});
|
|
233
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 247, S: this });
|
|
363
234
|
return;
|
|
364
235
|
}
|
|
365
236
|
if (replicationStreamErrors === 0) {
|
|
366
237
|
log.info("replication stream error", {
|
|
367
238
|
err,
|
|
368
239
|
info
|
|
369
|
-
}, {
|
|
370
|
-
F: __dxlog_file,
|
|
371
|
-
L: 271,
|
|
372
|
-
S: this,
|
|
373
|
-
C: (f, a) => f(...a)
|
|
374
|
-
});
|
|
240
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 255, S: this });
|
|
375
241
|
} else {
|
|
376
242
|
log.info("replication stream error", {
|
|
377
243
|
err,
|
|
378
244
|
feedKey: info.feedKey,
|
|
379
245
|
count: replicationStreamErrors
|
|
380
|
-
}, {
|
|
381
|
-
F: __dxlog_file,
|
|
382
|
-
L: 273,
|
|
383
|
-
S: this,
|
|
384
|
-
C: (f, a) => f(...a)
|
|
385
|
-
});
|
|
246
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 260, S: this });
|
|
386
247
|
}
|
|
387
248
|
replicationStreamErrors++;
|
|
388
249
|
});
|
|
@@ -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 { type Duplex } from 'node:stream';\n\nimport { asyncTimeout, DeferredTask, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { type FeedWrapper } from '@dxos/feed-store';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log, logInfo } from '@dxos/log';\nimport { RpcClosedError, TimeoutError } from '@dxos/protocols';\nimport { schema } from '@dxos/protocols/proto';\nimport { type FeedInfo, type ReplicatorService } from '@dxos/protocols/proto/dxos/mesh/teleport/replicator';\nimport { createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';\nimport { type ExtensionContext, type 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 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>): void {\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): Promise<void> {\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 timeout: 10_000,\n });\n await this._rpc.open();\n\n this._updateTask.schedule();\n }\n\n async onClose(err?: Error | undefined): Promise<void> {\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 async onAbort(err?: Error | undefined): Promise<void> {\n log('abort', { err });\n\n await this._ctx.dispose();\n await this._rpc?.abort();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n @synchronized\n private async _reevaluateFeeds(): Promise<void> {\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): Promise<void> {\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): Promise<void> {\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 let replicationStreamErrors = 0;\n\n // https://github.com/holepunchto/hypercore/tree/v9.12.0#var-stream--feedreplicateisinitiator-options\n const replicationStream = feed.replicate(true, {\n live: true,\n upload: info.upload,\n download: info.download,\n noise: false,\n encrypted: false,\n maxRequests: 1024,\n });\n\n // Left for testing.\n // const debug = true;\n // if (debug) {\n // feed.on('sync', () => {\n // log.info('sync', { key: feed.key, length: feed.length });\n // });\n // feed.on('download', (index: number, data: any) => {\n // log.info('download', {\n // key: feed.key,\n // index,\n // length: feed.length,\n // data: data.length,\n // });\n // });\n // }\n\n replicationStream.on('error', (err) => {\n if (err instanceof TimeoutError) {\n log.info('replication stream timeout', { err, info });\n return;\n }\n // TODO(nf): use sentinel errors\n if (\n err?.message === 'Writable stream closed prematurely' ||\n err?.message === 'Cannot call write after a stream was destroyed'\n ) {\n log('replication stream closed', { err, info });\n return;\n }\n\n // TODO(nf): WARN on first error? log full info on some subsequent errors?\n if (replicationStreamErrors === 0) {\n log.info('replication stream error', { err, info });\n } else {\n log.info('replication stream error', { err, feedKey: info.feedKey, count: replicationStreamErrors });\n }\n replicationStreamErrors++;\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): Promise<void> {\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": ";;;
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport type { ProtocolStream } from 'hypercore-protocol';\nimport { type Duplex } from 'node:stream';\n\nimport { DeferredTask, asyncTimeout, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { type FeedWrapper } from '@dxos/feed-store';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log, logInfo } from '@dxos/log';\nimport { RpcClosedError, TimeoutError } from '@dxos/protocols';\nimport { schema } from '@dxos/protocols/proto';\nimport { type FeedInfo, type ReplicatorService } from '@dxos/protocols/proto/dxos/mesh/teleport/replicator';\nimport { type ProtoRpcPeer, createProtoRpcPeer } from '@dxos/rpc';\nimport { type ExtensionContext, type 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 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>): void {\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): Promise<void> {\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 timeout: 10_000,\n });\n await this._rpc.open();\n\n this._updateTask.schedule();\n }\n\n async onClose(err?: Error | undefined): Promise<void> {\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 async onAbort(err?: Error | undefined): Promise<void> {\n log('abort', { err });\n\n await this._ctx.dispose();\n await this._rpc?.abort();\n for (const feedKey of this._streams.keys()) {\n await this._stopReplication(feedKey);\n }\n }\n\n @synchronized\n private async _reevaluateFeeds(): Promise<void> {\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): Promise<void> {\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): Promise<void> {\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 let replicationStreamErrors = 0;\n\n // https://github.com/holepunchto/hypercore/tree/v9.12.0#var-stream--feedreplicateisinitiator-options\n const replicationStream = feed.replicate(true, {\n live: true,\n upload: info.upload,\n download: info.download,\n noise: false,\n encrypted: false,\n maxRequests: 1024,\n });\n\n // Left for testing.\n // const debug = true;\n // if (debug) {\n // feed.on('sync', () => {\n // log.info('sync', { key: feed.key, length: feed.length });\n // });\n // feed.on('download', (index: number, data: any) => {\n // log.info('download', {\n // key: feed.key,\n // index,\n // length: feed.length,\n // data: data.length,\n // });\n // });\n // }\n\n replicationStream.on('error', (err) => {\n if (err instanceof TimeoutError) {\n log.info('replication stream timeout', { err, info });\n return;\n }\n // TODO(nf): use sentinel errors\n if (\n err?.message === 'Writable stream closed prematurely' ||\n err?.message === 'Cannot call write after a stream was destroyed'\n ) {\n log('replication stream closed', { err, info });\n return;\n }\n\n // TODO(nf): WARN on first error? log full info on some subsequent errors?\n if (replicationStreamErrors === 0) {\n log.info('replication stream error', { err, info });\n } else {\n log.info('replication stream error', { err, feedKey: info.feedKey, count: replicationStreamErrors });\n }\n replicationStreamErrors++;\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): Promise<void> {\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": ["Context", "failUndefined", "invariant", "PublicKey", "log", "RpcClosedError", "TimeoutError", "schema", "createProtoRpcPeer", "ComplexMap", "onError", "err", "_extensionContext", "_feeds", "_streams", "hash", "_rpc", "_options", "upload", "_updateTask", "ReplicatorService", "updateFeeds", "feeds", "Array", "from", "values", "feed", "feedKey", "key", "download", "_reevaluateFeeds", "initiator", "localPeerId", "remotePeerId", "setOptions", "options", "schedule", "addFeed", "requested", "exposed", "handlers", "startReplication", "info", "streamTag", "_acceptReplication", "stopReplication", "_stopReplication", "port", "contentType", "timeout", "_ctx", "close", "abort", "disposed", "catch", "_initiateReplication", "feedInfo", "rpc", "undefined", "_replicateFeed", "tag", "has", "get", "networkStream", "createStream", "live", "noise", "encrypted", "maxRequests", "count", "replicationStreamErrors", "replicationStream", "stream"]
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"inputs":{"src/replicator-extension.ts":{"bytes":36158,"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/protocols/proto","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":408,"imports":[{"path":"src/replicator-extension.ts","kind":"import-statement","original":"./replicator-extension"}],"format":"esm"}},"outputs":{"dist/lib/neutral/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16928},"dist/lib/neutral/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/protocols/proto","kind":"import-statement","external":true},{"path":"@dxos/rpc","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["ReplicatorExtension"],"entryPoint":"src/index.ts","inputs":{"src/replicator-extension.ts":{"bytesInOutput":10583},"src/index.ts":{"bytesInOutput":0}},"bytes":10717}}}
|
|
@@ -21,14 +21,7 @@ export declare class ReplicatorExtension implements TeleportExtension {
|
|
|
21
21
|
onClose(err?: Error | undefined): Promise<void>;
|
|
22
22
|
onAbort(err?: Error | undefined): Promise<void>;
|
|
23
23
|
private _reevaluateFeeds;
|
|
24
|
-
/**
|
|
25
|
-
* Try to initiate feed replication.
|
|
26
|
-
*/
|
|
27
24
|
private _initiateReplication;
|
|
28
|
-
/**
|
|
29
|
-
* Respond to a remote request to replicate a feed.
|
|
30
|
-
* @returns A stream tag for the replication stream or `undefined` if we don't want to replicate.
|
|
31
|
-
*/
|
|
32
25
|
private _acceptReplication;
|
|
33
26
|
private _replicateFeed;
|
|
34
27
|
private _stopReplication;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replicator-extension.d.ts","sourceRoot":"","sources":["../../../src/replicator-extension.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,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,CAIlB;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;
|
|
1
|
+
{"version":3,"file":"replicator-extension.d.ts","sourceRoot":"","sources":["../../../src/replicator-extension.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQpD,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAG/E,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,CAIlB;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,CAO5C;IAED,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,IAAI,CAMpC;IAEK,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CrD;IAEK,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAOpD;IAEK,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpD;YAGa,gBAAgB;YA8BhB,oBAAoB;YAiBpB,kBAAkB;YAYlB,cAAc;YAqEd,gBAAgB;CAS/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/testing.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,qBAAa,WAAW;IACtB,WAAW,IAAI,SAAS;
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/testing.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,qBAAa,WAAW;IACtB,WAAW,IAAI,SAAS,CAEvB;CACF;AAGD,qBAAa,SAAS;IACb,OAAO,gDAA4C;IACnD,OAAO,UAAwD;IAC/D,SAAS,gBAEb;IAEG,eAAe,CAAC,SAAS,SAAI,uDAQlC;IAED,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,WAAW,uDAEhD;CACF;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;EAuB5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;EAUhC,CAAC"}
|