@signaldb/sync 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SyncManager.d.ts +50 -6
- package/dist/applyChanges.d.ts +1 -1
- package/dist/index.mjs +325 -251
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +3 -3
- package/dist/index.umd.js.map +1 -1
- package/dist/utils/debounce.d.ts +2 -2
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
var N = Object.defineProperty;
|
|
2
|
+
var v = (c, e, t) => e in c ? N(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t;
|
|
3
|
+
var l = (c, e, t) => v(c, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import { isEqual as m, Collection as y, modify as E, randomId as D } from "@signaldb/core";
|
|
5
|
+
function S(c, e, t = {}) {
|
|
6
|
+
let s, n;
|
|
7
|
+
const { leading: a = !1, trailing: o = !0 } = t;
|
|
8
|
+
function r(...d) {
|
|
9
|
+
const i = a && !s, u = o && !s;
|
|
10
|
+
return s && clearTimeout(s), s = setTimeout(() => {
|
|
11
|
+
s = null, o && !i && (n = c.apply(this, d));
|
|
12
|
+
}, e), i ? n = c.apply(this, d) : u || (n = null), n;
|
|
10
13
|
}
|
|
11
|
-
return
|
|
14
|
+
return r;
|
|
12
15
|
}
|
|
13
|
-
class
|
|
16
|
+
class M {
|
|
14
17
|
constructor() {
|
|
15
|
-
this
|
|
18
|
+
l(this, "queue", []);
|
|
19
|
+
l(this, "pendingPromise", !1);
|
|
16
20
|
}
|
|
17
21
|
/**
|
|
18
22
|
* Method to add a new promise to the queue and returns a promise that resolves when this task is done
|
|
19
23
|
* @param task Function that returns a promise that will be added to the queue
|
|
20
24
|
* @returns Promise that resolves when the task is done
|
|
21
25
|
*/
|
|
22
|
-
add(
|
|
23
|
-
return new Promise((
|
|
24
|
-
this.queue.push(() =>
|
|
25
|
-
throw n
|
|
26
|
+
add(e) {
|
|
27
|
+
return new Promise((t, s) => {
|
|
28
|
+
this.queue.push(() => e().then(t).catch((n) => {
|
|
29
|
+
throw s(n), n;
|
|
26
30
|
})), this.dequeue();
|
|
27
31
|
});
|
|
28
32
|
}
|
|
@@ -39,77 +43,79 @@ class E {
|
|
|
39
43
|
dequeue() {
|
|
40
44
|
if (this.pendingPromise || this.queue.length === 0)
|
|
41
45
|
return;
|
|
42
|
-
const
|
|
43
|
-
|
|
46
|
+
const e = this.queue.shift();
|
|
47
|
+
e && (this.pendingPromise = !0, e().then(() => {
|
|
44
48
|
this.pendingPromise = !1, this.dequeue();
|
|
45
49
|
}).catch(() => {
|
|
46
50
|
this.pendingPromise = !1, this.dequeue();
|
|
47
51
|
}));
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
|
-
function g(
|
|
51
|
-
const
|
|
52
|
-
for (const [
|
|
53
|
-
const
|
|
54
|
-
|
|
54
|
+
function g(c, e) {
|
|
55
|
+
const t = [], s = [], n = [], a = new Map(c.map((r) => [r.id, r])), o = new Map(e.map((r) => [r.id, r]));
|
|
56
|
+
for (const [r, d] of a) {
|
|
57
|
+
const i = o.get(r);
|
|
58
|
+
i ? m(i, d) || s.push(i) : n.push(d);
|
|
55
59
|
}
|
|
56
|
-
for (const [
|
|
57
|
-
a.has(
|
|
58
|
-
return { added:
|
|
60
|
+
for (const [r, d] of o)
|
|
61
|
+
a.has(r) || t.push(d);
|
|
62
|
+
return { added: t, modified: s, removed: n };
|
|
59
63
|
}
|
|
60
|
-
function
|
|
61
|
-
if (
|
|
62
|
-
return
|
|
63
|
-
const
|
|
64
|
-
return
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
}),
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
}),
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
}),
|
|
64
|
+
function C(c, e) {
|
|
65
|
+
if (e.items != null)
|
|
66
|
+
return e.items;
|
|
67
|
+
const t = c || [];
|
|
68
|
+
return e.changes.added.forEach((s) => {
|
|
69
|
+
const n = t.findIndex((a) => a.id === s.id);
|
|
70
|
+
n === -1 ? t.push(s) : t[n] = s;
|
|
71
|
+
}), e.changes.modified.forEach((s) => {
|
|
72
|
+
const n = t.findIndex((a) => a.id === s.id);
|
|
73
|
+
n === -1 ? t.push(s) : t[n] = s;
|
|
74
|
+
}), e.changes.removed.forEach((s) => {
|
|
75
|
+
const n = t.findIndex((a) => a.id === s.id);
|
|
76
|
+
n !== -1 && t.splice(n, 1);
|
|
77
|
+
}), t;
|
|
74
78
|
}
|
|
75
|
-
function
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
async function P(c, e) {
|
|
80
|
+
const t = new y();
|
|
81
|
+
t.batch(() => {
|
|
82
|
+
c.forEach((n) => t.insert(n)), e.forEach((n) => {
|
|
79
83
|
if (n.type === "remove") {
|
|
80
|
-
|
|
84
|
+
t.removeOne({ id: n.data });
|
|
81
85
|
return;
|
|
82
86
|
}
|
|
83
|
-
const
|
|
87
|
+
const a = { id: n.data.id }, o = t.findOne(a);
|
|
84
88
|
if (n.type === "insert") {
|
|
85
|
-
|
|
89
|
+
o ? t.updateOne(a, { $set: n.data }) : t.insert(n.data);
|
|
86
90
|
return;
|
|
87
91
|
}
|
|
88
|
-
|
|
92
|
+
o ? t.updateOne(a, n.data.modifier) : t.insert(E(a, n.data.modifier));
|
|
89
93
|
});
|
|
90
|
-
})
|
|
94
|
+
});
|
|
95
|
+
const s = t.find().fetch();
|
|
96
|
+
return await t.dispose(), s;
|
|
91
97
|
}
|
|
92
|
-
function
|
|
93
|
-
return
|
|
98
|
+
function O(c) {
|
|
99
|
+
return c.added.length > 0 || c.modified.length > 0 || c.removed.length > 0;
|
|
94
100
|
}
|
|
95
|
-
function
|
|
96
|
-
return
|
|
101
|
+
function I(c, e) {
|
|
102
|
+
return O(g(c, e));
|
|
97
103
|
}
|
|
98
|
-
async function
|
|
99
|
-
let
|
|
100
|
-
if (
|
|
101
|
-
const
|
|
102
|
-
if (
|
|
103
|
-
const
|
|
104
|
-
|
|
104
|
+
async function x({ changes: c, lastSnapshot: e, data: t, pull: s, push: n, insert: a, update: o, remove: r, batch: d }) {
|
|
105
|
+
let i = t, u = e || [], p = C(e, i);
|
|
106
|
+
if (c.length > 0) {
|
|
107
|
+
const f = await P(u, c);
|
|
108
|
+
if (I(u, f)) {
|
|
109
|
+
const $ = await P(p, c), w = g(p, $);
|
|
110
|
+
O(w) && (await n(w), i = await s(), p = C(p, i)), u = f;
|
|
105
111
|
}
|
|
106
112
|
}
|
|
107
|
-
const
|
|
113
|
+
const h = i.changes == null ? g(u, i.items) : i.changes;
|
|
108
114
|
return d(() => {
|
|
109
|
-
|
|
110
|
-
}),
|
|
115
|
+
h.added.forEach((f) => a(f)), h.modified.forEach((f) => o(f.id, { $set: f })), h.removed.forEach((f) => r(f.id));
|
|
116
|
+
}), p;
|
|
111
117
|
}
|
|
112
|
-
class
|
|
118
|
+
class q {
|
|
113
119
|
/**
|
|
114
120
|
* @param options Collection options
|
|
115
121
|
* @param options.pull Function to pull data from remote source.
|
|
@@ -120,62 +126,60 @@ class I {
|
|
|
120
126
|
* @param [options.reactivity] Reactivity adapter to use for reactivity.
|
|
121
127
|
* @param [options.onError] Function to handle errors that occur async during syncing.
|
|
122
128
|
*/
|
|
123
|
-
constructor(
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
constructor(e) {
|
|
130
|
+
l(this, "options");
|
|
131
|
+
l(this, "collections", /* @__PURE__ */ new Map());
|
|
132
|
+
l(this, "changes");
|
|
133
|
+
l(this, "snapshots");
|
|
134
|
+
l(this, "syncOperations");
|
|
135
|
+
l(this, "remoteChanges", []);
|
|
136
|
+
l(this, "syncQueues", /* @__PURE__ */ new Map());
|
|
137
|
+
l(this, "persistenceReady");
|
|
138
|
+
l(this, "isDisposed", !1);
|
|
139
|
+
l(this, "instanceId", D());
|
|
140
|
+
l(this, "id");
|
|
141
|
+
l(this, "deboucedPush", S((e) => {
|
|
142
|
+
this.pushChanges(e).catch(() => {
|
|
126
143
|
});
|
|
127
|
-
}, 100)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}), this.snapshots =
|
|
144
|
+
}, 100));
|
|
145
|
+
this.options = {
|
|
146
|
+
autostart: !0,
|
|
147
|
+
...e
|
|
148
|
+
}, this.id = this.options.id || "default-sync-manager";
|
|
149
|
+
const { reactivity: t } = this.options, s = this.createPersistenceAdapter("changes"), n = this.createPersistenceAdapter("snapshots"), a = this.createPersistenceAdapter("sync-operations");
|
|
150
|
+
this.changes = new y({
|
|
151
|
+
name: `${this.options.id}-changes`,
|
|
133
152
|
persistence: s == null ? void 0 : s.adapter,
|
|
134
|
-
reactivity:
|
|
135
|
-
}), this.
|
|
153
|
+
reactivity: t
|
|
154
|
+
}), this.snapshots = new y({
|
|
155
|
+
name: `${this.options.id}-snapshots`,
|
|
156
|
+
persistence: n == null ? void 0 : n.adapter,
|
|
157
|
+
reactivity: t
|
|
158
|
+
}), this.syncOperations = new y({
|
|
159
|
+
name: `${this.options.id}-sync-operations`,
|
|
136
160
|
persistence: a == null ? void 0 : a.adapter,
|
|
137
|
-
reactivity:
|
|
138
|
-
}), this.changes.on("persistence.error", (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
this.syncOperations.once("persistence.error", o), this.syncOperations.once("persistence.init", i);
|
|
145
|
-
}),
|
|
146
|
-
new Promise((i, o) => {
|
|
147
|
-
if (!s) {
|
|
148
|
-
i();
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
this.changes.once("persistence.error", o), this.changes.once("persistence.init", i);
|
|
152
|
-
}),
|
|
153
|
-
new Promise((i, o) => {
|
|
154
|
-
if (!a) {
|
|
155
|
-
i();
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
this.snapshots.once("persistence.error", o), this.snapshots.once("persistence.init", i);
|
|
159
|
-
})
|
|
161
|
+
reactivity: t
|
|
162
|
+
}), this.changes.on("persistence.error", (o) => s == null ? void 0 : s.handler(o)), this.snapshots.on("persistence.error", (o) => n == null ? void 0 : n.handler(o)), this.syncOperations.on("persistence.error", (o) => a == null ? void 0 : a.handler(o)), this.persistenceReady = Promise.all([
|
|
163
|
+
this.syncOperations.isReady(),
|
|
164
|
+
this.changes.isReady(),
|
|
165
|
+
this.snapshots.isReady()
|
|
160
166
|
]).then(() => {
|
|
161
167
|
}), this.changes.setMaxListeners(1e3), this.snapshots.setMaxListeners(1e3), this.syncOperations.setMaxListeners(1e3);
|
|
162
168
|
}
|
|
163
|
-
createPersistenceAdapter(
|
|
164
|
-
var e;
|
|
169
|
+
createPersistenceAdapter(e) {
|
|
165
170
|
if (this.options.persistenceAdapter == null)
|
|
166
171
|
return;
|
|
167
|
-
|
|
168
|
-
let s = () => {
|
|
172
|
+
let t = () => {
|
|
169
173
|
};
|
|
170
174
|
return {
|
|
171
|
-
adapter: this.options.persistenceAdapter(`${
|
|
172
|
-
|
|
175
|
+
adapter: this.options.persistenceAdapter(`${this.id}-${e}`, (n) => {
|
|
176
|
+
t = n;
|
|
173
177
|
}),
|
|
174
|
-
handler: (
|
|
178
|
+
handler: (n) => t(n)
|
|
175
179
|
};
|
|
176
180
|
}
|
|
177
|
-
getSyncQueue(
|
|
178
|
-
return this.syncQueues.get(
|
|
181
|
+
getSyncQueue(e) {
|
|
182
|
+
return this.syncQueues.get(e) == null && this.syncQueues.set(e, new M()), this.syncQueues.get(e);
|
|
179
183
|
}
|
|
180
184
|
/**
|
|
181
185
|
* Clears all internal data structures
|
|
@@ -189,15 +193,26 @@ class I {
|
|
|
189
193
|
}
|
|
190
194
|
/**
|
|
191
195
|
* Gets a collection with it's options by name
|
|
196
|
+
* @deprecated Use getCollectionProperties instead.
|
|
192
197
|
* @param name Name of the collection
|
|
193
198
|
* @throws Will throw an error if the name wasn't found
|
|
194
199
|
* @returns Tuple of collection and options
|
|
195
200
|
*/
|
|
196
|
-
getCollection(
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
getCollection(e) {
|
|
202
|
+
const { collection: t, options: s } = this.getCollectionProperties(e);
|
|
203
|
+
return [t, s];
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Gets collection options by name
|
|
207
|
+
* @param name Name of the collection
|
|
208
|
+
* @throws Will throw an error if the name wasn't found
|
|
209
|
+
* @returns An object of all properties of the collection
|
|
210
|
+
*/
|
|
211
|
+
getCollectionProperties(e) {
|
|
212
|
+
const t = this.collections.get(e);
|
|
213
|
+
if (t == null)
|
|
214
|
+
throw new Error(`Collection with id '${e}' not found`);
|
|
215
|
+
return t;
|
|
201
216
|
}
|
|
202
217
|
/**
|
|
203
218
|
* Adds a collection to the sync manager.
|
|
@@ -205,87 +220,141 @@ class I {
|
|
|
205
220
|
* @param options Options for the collection. The object needs at least a `name` property.
|
|
206
221
|
* @param options.name Unique name of the collection
|
|
207
222
|
*/
|
|
208
|
-
addCollection(
|
|
223
|
+
addCollection(e, t) {
|
|
209
224
|
if (this.isDisposed)
|
|
210
225
|
throw new Error("SyncManager is disposed");
|
|
211
|
-
this.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
await this.syncWithData(e.name, a).then(() => {
|
|
222
|
-
this.syncOperations.removeMany({
|
|
223
|
-
id: { $ne: o },
|
|
224
|
-
collectionName: e.name,
|
|
225
|
-
$or: [
|
|
226
|
-
{ end: { $lte: i } },
|
|
227
|
-
{ status: "active" }
|
|
228
|
-
]
|
|
229
|
-
}), this.syncOperations.updateOne({ id: o }, {
|
|
230
|
-
$set: { status: "done", end: Date.now() }
|
|
231
|
-
});
|
|
232
|
-
}).catch((d) => {
|
|
233
|
-
throw this.options.onError && this.options.onError(e, d), this.syncOperations.updateOne({ id: o }, {
|
|
234
|
-
$set: { status: "error", end: Date.now(), error: d.stack || d.message }
|
|
235
|
-
}), d;
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
}), this.collections.set(e.name, [t, e]);
|
|
239
|
-
const n = (a) => {
|
|
240
|
-
for (const i of this.remoteChanges)
|
|
241
|
-
if (m(i, a))
|
|
226
|
+
this.collections.set(t.name, {
|
|
227
|
+
collection: e,
|
|
228
|
+
options: t,
|
|
229
|
+
readyPromise: e.isReady(),
|
|
230
|
+
syncPaused: !0
|
|
231
|
+
// always start paused as the autostart will start it
|
|
232
|
+
});
|
|
233
|
+
const s = (a) => {
|
|
234
|
+
for (const o of this.remoteChanges)
|
|
235
|
+
if (m(o, a))
|
|
242
236
|
return !0;
|
|
243
237
|
return !1;
|
|
244
|
-
},
|
|
245
|
-
for (let
|
|
246
|
-
if (m(this.remoteChanges[
|
|
247
|
-
this.remoteChanges.splice(
|
|
238
|
+
}, n = (a) => {
|
|
239
|
+
for (let o = 0; o < this.remoteChanges.length; o += 1)
|
|
240
|
+
if (m(this.remoteChanges[o], a)) {
|
|
241
|
+
this.remoteChanges.splice(o, 1);
|
|
248
242
|
return;
|
|
249
243
|
}
|
|
250
244
|
};
|
|
251
|
-
|
|
252
|
-
if (
|
|
253
|
-
|
|
245
|
+
e.on("added", (a) => {
|
|
246
|
+
if (s({ collectionName: t.name, type: "insert", data: a })) {
|
|
247
|
+
n({ collectionName: t.name, type: "insert", data: a });
|
|
254
248
|
return;
|
|
255
249
|
}
|
|
256
250
|
this.changes.insert({
|
|
257
|
-
collectionName:
|
|
251
|
+
collectionName: t.name,
|
|
258
252
|
time: Date.now(),
|
|
259
253
|
type: "insert",
|
|
260
254
|
data: a
|
|
261
|
-
}), this.schedulePush(
|
|
262
|
-
}),
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
|
|
255
|
+
}), !this.getCollectionProperties(t.name).syncPaused && this.schedulePush(t.name);
|
|
256
|
+
}), e.on("changed", ({ id: a }, o) => {
|
|
257
|
+
const r = { id: a, modifier: o };
|
|
258
|
+
if (s({ collectionName: t.name, type: "update", data: r })) {
|
|
259
|
+
n({ collectionName: t.name, type: "update", data: r });
|
|
266
260
|
return;
|
|
267
261
|
}
|
|
268
262
|
this.changes.insert({
|
|
269
|
-
collectionName:
|
|
263
|
+
collectionName: t.name,
|
|
270
264
|
time: Date.now(),
|
|
271
265
|
type: "update",
|
|
272
|
-
data:
|
|
273
|
-
}), this.schedulePush(
|
|
274
|
-
}),
|
|
275
|
-
if (
|
|
276
|
-
|
|
266
|
+
data: r
|
|
267
|
+
}), !this.getCollectionProperties(t.name).syncPaused && this.schedulePush(t.name);
|
|
268
|
+
}), e.on("removed", ({ id: a }) => {
|
|
269
|
+
if (s({ collectionName: t.name, type: "remove", data: a })) {
|
|
270
|
+
n({ collectionName: t.name, type: "remove", data: a });
|
|
277
271
|
return;
|
|
278
272
|
}
|
|
279
273
|
this.changes.insert({
|
|
280
|
-
collectionName:
|
|
274
|
+
collectionName: t.name,
|
|
281
275
|
time: Date.now(),
|
|
282
276
|
type: "remove",
|
|
283
277
|
data: a
|
|
284
|
-
}), this.schedulePush(
|
|
278
|
+
}), !this.getCollectionProperties(t.name).syncPaused && this.schedulePush(t.name);
|
|
279
|
+
}), this.options.autostart && this.startSync(t.name).catch((a) => {
|
|
280
|
+
this.options.onError && this.options.onError(this.getCollectionProperties(t.name).options, a);
|
|
285
281
|
});
|
|
286
282
|
}
|
|
287
|
-
schedulePush(
|
|
288
|
-
this.deboucedPush(
|
|
283
|
+
schedulePush(e) {
|
|
284
|
+
this.deboucedPush(e);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Setup all collections to be synced with remote changes
|
|
288
|
+
* and enable automatic pushing changes to the remote source.
|
|
289
|
+
*/
|
|
290
|
+
async startAll() {
|
|
291
|
+
await Promise.all([...this.collections.keys()].map((e) => this.startSync(e)));
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Setup a collection to be synced with remote changes
|
|
295
|
+
* and enable automatic pushing changes to the remote source.
|
|
296
|
+
* @param name Name of the collection
|
|
297
|
+
*/
|
|
298
|
+
async startSync(e) {
|
|
299
|
+
const t = this.getCollectionProperties(e);
|
|
300
|
+
if (!t.syncPaused)
|
|
301
|
+
return;
|
|
302
|
+
this.schedulePush(e);
|
|
303
|
+
const s = this.options.registerRemoteChange ? await this.options.registerRemoteChange(t.options, async (n) => {
|
|
304
|
+
if (n == null)
|
|
305
|
+
await this.sync(e);
|
|
306
|
+
else {
|
|
307
|
+
const a = Date.now(), o = this.syncOperations.insert({
|
|
308
|
+
start: a,
|
|
309
|
+
collectionName: e,
|
|
310
|
+
instanceId: this.instanceId,
|
|
311
|
+
status: "active"
|
|
312
|
+
});
|
|
313
|
+
await this.syncWithData(e, n).then(() => {
|
|
314
|
+
this.syncOperations.removeMany({
|
|
315
|
+
id: { $ne: o },
|
|
316
|
+
collectionName: e,
|
|
317
|
+
$or: [
|
|
318
|
+
{ end: { $lte: a } },
|
|
319
|
+
{ status: "active" }
|
|
320
|
+
]
|
|
321
|
+
}), this.syncOperations.updateOne({ id: o }, {
|
|
322
|
+
$set: { status: "done", end: Date.now() }
|
|
323
|
+
});
|
|
324
|
+
}).catch((r) => {
|
|
325
|
+
throw this.options.onError && this.options.onError(this.getCollectionProperties(e).options, r), this.syncOperations.updateOne({ id: o }, {
|
|
326
|
+
$set: { status: "error", end: Date.now(), error: r.stack || r.message }
|
|
327
|
+
}), r;
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}) : void 0;
|
|
331
|
+
this.collections.set(e, {
|
|
332
|
+
...t,
|
|
333
|
+
syncPaused: !1,
|
|
334
|
+
cleanupFunction: s
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Pauses the sync process for all collections.
|
|
339
|
+
* This means that the collections will not be synced with remote changes
|
|
340
|
+
* and changes will not automatically be pushed to the remote source.
|
|
341
|
+
*/
|
|
342
|
+
async pauseAll() {
|
|
343
|
+
await Promise.all([...this.collections.keys()].map((e) => this.pauseSync(e)));
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Pauses the sync process for a collection.
|
|
347
|
+
* This means that the collection will not be synced with remote changes
|
|
348
|
+
* and changes will not automatically be pushed to the remote source.
|
|
349
|
+
* @param name Name of the collection
|
|
350
|
+
*/
|
|
351
|
+
async pauseSync(e) {
|
|
352
|
+
const t = this.getCollectionProperties(e);
|
|
353
|
+
t.syncPaused || (t.cleanupFunction && await t.cleanupFunction(), this.collections.set(e, {
|
|
354
|
+
...t,
|
|
355
|
+
cleanupFunction: void 0,
|
|
356
|
+
syncPaused: !0
|
|
357
|
+
}));
|
|
289
358
|
}
|
|
290
359
|
/**
|
|
291
360
|
* Starts the sync process for all collections
|
|
@@ -293,12 +362,12 @@ class I {
|
|
|
293
362
|
async syncAll() {
|
|
294
363
|
if (this.isDisposed)
|
|
295
364
|
throw new Error("SyncManager is disposed");
|
|
296
|
-
const
|
|
297
|
-
if (await Promise.all([...this.collections.keys()].map((
|
|
298
|
-
|
|
299
|
-
}))),
|
|
365
|
+
const e = [];
|
|
366
|
+
if (await Promise.all([...this.collections.keys()].map((t) => this.sync(t).catch((s) => {
|
|
367
|
+
e.push({ id: t, error: s });
|
|
368
|
+
}))), e.length > 0)
|
|
300
369
|
throw new Error(`Error while syncing collections:
|
|
301
|
-
${
|
|
370
|
+
${e.map((t) => `${t.id}: ${t.error.message}`).join(`
|
|
302
371
|
|
|
303
372
|
`)}`);
|
|
304
373
|
}
|
|
@@ -307,8 +376,11 @@ ${t.map((e) => `${e.id}: ${e.error.message}`).join(`
|
|
|
307
376
|
* @param [name] Name of the collection. If not provided, it will check if any collection is currently beeing synced.
|
|
308
377
|
* @returns True if the collection is currently beeing synced, false otherwise.
|
|
309
378
|
*/
|
|
310
|
-
isSyncing(
|
|
311
|
-
return this.syncOperations.findOne(
|
|
379
|
+
isSyncing(e) {
|
|
380
|
+
return this.syncOperations.findOne({
|
|
381
|
+
...e ? { collectionName: e } : {},
|
|
382
|
+
status: "active"
|
|
383
|
+
}, { fields: { status: 1 } }) != null;
|
|
312
384
|
}
|
|
313
385
|
/**
|
|
314
386
|
* Checks if the sync manager is ready to sync.
|
|
@@ -324,52 +396,54 @@ ${t.map((e) => `${e.id}: ${e.error.message}`).join(`
|
|
|
324
396
|
* @param options.force If true, the sync process will be started even if there are no changes and onlyWithChanges is true.
|
|
325
397
|
* @param options.onlyWithChanges If true, the sync process will only be started if there are changes.
|
|
326
398
|
*/
|
|
327
|
-
async sync(
|
|
399
|
+
async sync(e, t = {}) {
|
|
328
400
|
if (this.isDisposed)
|
|
329
401
|
throw new Error("SyncManager is disposed");
|
|
330
402
|
await this.isReady();
|
|
331
|
-
const
|
|
332
|
-
|
|
403
|
+
const { options: s, readyPromise: n } = this.getCollectionProperties(e);
|
|
404
|
+
await n;
|
|
405
|
+
const a = this.syncOperations.find({
|
|
406
|
+
collectionName: e,
|
|
333
407
|
instanceId: this.instanceId,
|
|
334
408
|
status: "active"
|
|
335
|
-
}).count() > 0,
|
|
336
|
-
let
|
|
337
|
-
await new Promise((
|
|
338
|
-
setTimeout(
|
|
409
|
+
}).count() > 0, o = Date.now();
|
|
410
|
+
let r = null;
|
|
411
|
+
await new Promise((i) => {
|
|
412
|
+
setTimeout(i, 0);
|
|
339
413
|
});
|
|
340
414
|
const d = async () => {
|
|
341
|
-
const
|
|
342
|
-
if (
|
|
343
|
-
collectionName:
|
|
415
|
+
const i = this.syncOperations.findOne({ collectionName: e, status: "done" }, { sort: { end: -1 } });
|
|
416
|
+
if (t != null && t.onlyWithChanges && this.changes.find({
|
|
417
|
+
collectionName: e,
|
|
344
418
|
$and: [
|
|
345
|
-
{ time: { $lte:
|
|
419
|
+
{ time: { $lte: o } }
|
|
346
420
|
]
|
|
347
421
|
}, { sort: { time: 1 } }).count() === 0)
|
|
348
422
|
return;
|
|
349
|
-
a || (
|
|
350
|
-
start:
|
|
351
|
-
collectionName:
|
|
423
|
+
a || (r = this.syncOperations.insert({
|
|
424
|
+
start: o,
|
|
425
|
+
collectionName: e,
|
|
352
426
|
instanceId: this.instanceId,
|
|
353
427
|
status: "active"
|
|
354
428
|
}));
|
|
355
|
-
const
|
|
356
|
-
lastFinishedSyncStart:
|
|
357
|
-
lastFinishedSyncEnd:
|
|
429
|
+
const u = await this.options.pull(s, {
|
|
430
|
+
lastFinishedSyncStart: i == null ? void 0 : i.start,
|
|
431
|
+
lastFinishedSyncEnd: i == null ? void 0 : i.end
|
|
358
432
|
});
|
|
359
|
-
await this.syncWithData(
|
|
433
|
+
await this.syncWithData(e, u);
|
|
360
434
|
};
|
|
361
|
-
await (
|
|
362
|
-
throw
|
|
363
|
-
$set: { status: "error", end: Date.now(), error:
|
|
364
|
-
})),
|
|
365
|
-
}),
|
|
366
|
-
id: { $ne:
|
|
367
|
-
collectionName:
|
|
435
|
+
await (t != null && t.force ? d() : this.getSyncQueue(e).add(d)).catch((i) => {
|
|
436
|
+
throw r != null && (this.options.onError && this.options.onError(s, i), this.syncOperations.updateOne({ id: r }, {
|
|
437
|
+
$set: { status: "error", end: Date.now(), error: i.stack || i.message }
|
|
438
|
+
})), i;
|
|
439
|
+
}), r != null && (this.syncOperations.removeMany({
|
|
440
|
+
id: { $ne: r },
|
|
441
|
+
collectionName: e,
|
|
368
442
|
$or: [
|
|
369
|
-
{ end: { $lte:
|
|
443
|
+
{ end: { $lte: o } },
|
|
370
444
|
{ status: "active" }
|
|
371
445
|
]
|
|
372
|
-
}), this.syncOperations.updateOne({ id:
|
|
446
|
+
}), this.syncOperations.updateOne({ id: r }, {
|
|
373
447
|
$set: { status: "done", end: Date.now() }
|
|
374
448
|
}));
|
|
375
449
|
}
|
|
@@ -377,102 +451,102 @@ ${t.map((e) => `${e.id}: ${e.error.message}`).join(`
|
|
|
377
451
|
* Starts the push process for a collection (sync process but only if there are changes)
|
|
378
452
|
* @param name Name of the collection
|
|
379
453
|
*/
|
|
380
|
-
async pushChanges(
|
|
381
|
-
await this.sync(
|
|
454
|
+
async pushChanges(e) {
|
|
455
|
+
await this.sync(e, {
|
|
382
456
|
onlyWithChanges: !0
|
|
383
457
|
});
|
|
384
458
|
}
|
|
385
|
-
async syncWithData(
|
|
386
|
-
const n = this.
|
|
387
|
-
collectionName:
|
|
459
|
+
async syncWithData(e, t) {
|
|
460
|
+
const { collection: s, options: n } = this.getCollectionProperties(e), a = Date.now(), o = this.syncOperations.findOne({ collectionName: e, status: "done" }, { sort: { end: -1 } }), r = this.snapshots.findOne({ collectionName: e }, { sort: { time: -1 } }), d = this.changes.find({
|
|
461
|
+
collectionName: e,
|
|
388
462
|
$and: [
|
|
389
|
-
{ time: { $lte:
|
|
463
|
+
{ time: { $lte: a } }
|
|
390
464
|
]
|
|
391
465
|
}, { sort: { time: 1 } }).fetch();
|
|
392
|
-
await
|
|
393
|
-
changes:
|
|
394
|
-
lastSnapshot:
|
|
395
|
-
data:
|
|
396
|
-
pull: () => this.options.pull(
|
|
466
|
+
await x({
|
|
467
|
+
changes: d,
|
|
468
|
+
lastSnapshot: r == null ? void 0 : r.items,
|
|
469
|
+
data: t,
|
|
470
|
+
pull: () => this.options.pull(n, {
|
|
397
471
|
lastFinishedSyncStart: o == null ? void 0 : o.start,
|
|
398
472
|
lastFinishedSyncEnd: o == null ? void 0 : o.end
|
|
399
473
|
}),
|
|
400
|
-
push: (
|
|
401
|
-
insert: (
|
|
402
|
-
if (
|
|
474
|
+
push: (i) => this.options.push(n, { changes: i }),
|
|
475
|
+
insert: (i) => {
|
|
476
|
+
if (i.id && s.findOne({ id: i.id })) {
|
|
403
477
|
this.remoteChanges.push({
|
|
404
|
-
collectionName:
|
|
478
|
+
collectionName: e,
|
|
405
479
|
type: "update",
|
|
406
|
-
data: { id:
|
|
407
|
-
}), s.updateOne({ id:
|
|
480
|
+
data: { id: i.id, modifier: { $set: i } }
|
|
481
|
+
}), s.updateOne({ id: i.id }, { $set: i });
|
|
408
482
|
return;
|
|
409
483
|
}
|
|
410
484
|
this.remoteChanges.push({
|
|
411
|
-
collectionName:
|
|
485
|
+
collectionName: e,
|
|
412
486
|
type: "insert",
|
|
413
|
-
data:
|
|
414
|
-
}), s.insert(
|
|
487
|
+
data: i
|
|
488
|
+
}), s.insert(i);
|
|
415
489
|
},
|
|
416
|
-
update: (
|
|
417
|
-
if (
|
|
418
|
-
const p =
|
|
490
|
+
update: (i, u) => {
|
|
491
|
+
if (i && !s.findOne({ id: i })) {
|
|
492
|
+
const p = { ...u.$set, id: i };
|
|
419
493
|
this.remoteChanges.push({
|
|
420
|
-
collectionName:
|
|
494
|
+
collectionName: e,
|
|
421
495
|
type: "insert",
|
|
422
496
|
data: p
|
|
423
497
|
}), s.insert(p);
|
|
424
498
|
return;
|
|
425
499
|
}
|
|
426
500
|
this.remoteChanges.push({
|
|
427
|
-
collectionName:
|
|
501
|
+
collectionName: e,
|
|
428
502
|
type: "update",
|
|
429
|
-
data: { id:
|
|
430
|
-
}), s.updateOne({ id:
|
|
503
|
+
data: { id: i, modifier: u }
|
|
504
|
+
}), s.updateOne({ id: i }, u);
|
|
431
505
|
},
|
|
432
|
-
remove: (
|
|
433
|
-
s.findOne({ id:
|
|
434
|
-
collectionName:
|
|
506
|
+
remove: (i) => {
|
|
507
|
+
s.findOne({ id: i }) && (this.remoteChanges.push({
|
|
508
|
+
collectionName: e,
|
|
435
509
|
type: "remove",
|
|
436
|
-
data:
|
|
437
|
-
}), s.removeOne({ id:
|
|
510
|
+
data: i
|
|
511
|
+
}), s.removeOne({ id: i }));
|
|
438
512
|
},
|
|
439
|
-
batch: (
|
|
513
|
+
batch: (i) => {
|
|
440
514
|
s.batch(() => {
|
|
441
|
-
|
|
515
|
+
i();
|
|
442
516
|
});
|
|
443
517
|
}
|
|
444
|
-
}).then(async (
|
|
445
|
-
if (this.snapshots.removeMany({ collectionName:
|
|
446
|
-
collectionName:
|
|
447
|
-
id: { $in:
|
|
518
|
+
}).then(async (i) => {
|
|
519
|
+
if (this.snapshots.removeMany({ collectionName: e, time: { $lte: a } }), this.changes.removeMany({
|
|
520
|
+
collectionName: e,
|
|
521
|
+
id: { $in: d.map((h) => h.id) }
|
|
448
522
|
}), this.snapshots.insert({
|
|
449
|
-
time:
|
|
450
|
-
collectionName:
|
|
451
|
-
items:
|
|
523
|
+
time: a,
|
|
524
|
+
collectionName: e,
|
|
525
|
+
items: i
|
|
452
526
|
}), await new Promise((h) => {
|
|
453
527
|
setTimeout(h, 0);
|
|
454
528
|
}), this.changes.find({
|
|
455
|
-
collectionName:
|
|
529
|
+
collectionName: e
|
|
456
530
|
}).count() > 0) {
|
|
457
|
-
await this.sync(
|
|
531
|
+
await this.sync(e, {
|
|
458
532
|
force: !0,
|
|
459
533
|
onlyWithChanges: !0
|
|
460
534
|
});
|
|
461
535
|
return;
|
|
462
536
|
}
|
|
463
537
|
const p = s.find({
|
|
464
|
-
id: { $nin:
|
|
538
|
+
id: { $nin: i.map((h) => h.id) }
|
|
465
539
|
}).map((h) => h.id);
|
|
466
540
|
s.batch(() => {
|
|
467
|
-
|
|
468
|
-
const
|
|
541
|
+
i.forEach((h) => {
|
|
542
|
+
const f = !!s.findOne({ id: h.id });
|
|
469
543
|
/* istanbul ignore else -- @preserve */
|
|
470
|
-
|
|
471
|
-
collectionName:
|
|
544
|
+
f ? (this.remoteChanges.push({
|
|
545
|
+
collectionName: e,
|
|
472
546
|
type: "update",
|
|
473
547
|
data: { id: h.id, modifier: { $set: h } }
|
|
474
548
|
}), s.updateOne({ id: h.id }, { $set: h })) : (this.remoteChanges.push({
|
|
475
|
-
collectionName:
|
|
549
|
+
collectionName: e,
|
|
476
550
|
type: "insert",
|
|
477
551
|
data: h
|
|
478
552
|
}), s.insert(h));
|
|
@@ -484,6 +558,6 @@ ${t.map((e) => `${e.id}: ${e.error.message}`).join(`
|
|
|
484
558
|
}
|
|
485
559
|
}
|
|
486
560
|
export {
|
|
487
|
-
|
|
561
|
+
q as SyncManager
|
|
488
562
|
};
|
|
489
563
|
//# sourceMappingURL=index.mjs.map
|