ar_sync 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +53 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +128 -0
  8. data/Rakefile +10 -0
  9. data/ar_sync.gemspec +28 -0
  10. data/bin/console +12 -0
  11. data/bin/setup +8 -0
  12. data/core/ActioncableAdapter.d.ts +10 -0
  13. data/core/ActioncableAdapter.js +29 -0
  14. data/core/ArSyncApi.d.ts +5 -0
  15. data/core/ArSyncApi.js +74 -0
  16. data/core/ArSyncModelBase.d.ts +71 -0
  17. data/core/ArSyncModelBase.js +110 -0
  18. data/core/ConnectionAdapter.d.ts +7 -0
  19. data/core/ConnectionAdapter.js +2 -0
  20. data/core/ConnectionManager.d.ts +19 -0
  21. data/core/ConnectionManager.js +75 -0
  22. data/core/DataType.d.ts +60 -0
  23. data/core/DataType.js +2 -0
  24. data/core/hooksBase.d.ts +29 -0
  25. data/core/hooksBase.js +80 -0
  26. data/graph/ArSyncModel.d.ts +10 -0
  27. data/graph/ArSyncModel.js +22 -0
  28. data/graph/ArSyncStore.d.ts +28 -0
  29. data/graph/ArSyncStore.js +593 -0
  30. data/graph/hooks.d.ts +3 -0
  31. data/graph/hooks.js +10 -0
  32. data/graph/index.d.ts +2 -0
  33. data/graph/index.js +4 -0
  34. data/lib/ar_sync.rb +25 -0
  35. data/lib/ar_sync/class_methods.rb +215 -0
  36. data/lib/ar_sync/collection.rb +83 -0
  37. data/lib/ar_sync/config.rb +18 -0
  38. data/lib/ar_sync/core.rb +138 -0
  39. data/lib/ar_sync/field.rb +96 -0
  40. data/lib/ar_sync/instance_methods.rb +130 -0
  41. data/lib/ar_sync/rails.rb +155 -0
  42. data/lib/ar_sync/type_script.rb +80 -0
  43. data/lib/ar_sync/version.rb +3 -0
  44. data/lib/generators/ar_sync/install/install_generator.rb +87 -0
  45. data/lib/generators/ar_sync/types/types_generator.rb +11 -0
  46. data/package-lock.json +1115 -0
  47. data/package.json +19 -0
  48. data/src/core/ActioncableAdapter.ts +30 -0
  49. data/src/core/ArSyncApi.ts +75 -0
  50. data/src/core/ArSyncModelBase.ts +126 -0
  51. data/src/core/ConnectionAdapter.ts +5 -0
  52. data/src/core/ConnectionManager.ts +69 -0
  53. data/src/core/DataType.ts +73 -0
  54. data/src/core/hooksBase.ts +86 -0
  55. data/src/graph/ArSyncModel.ts +21 -0
  56. data/src/graph/ArSyncStore.ts +567 -0
  57. data/src/graph/hooks.ts +7 -0
  58. data/src/graph/index.ts +2 -0
  59. data/src/tree/ArSyncModel.ts +145 -0
  60. data/src/tree/ArSyncStore.ts +323 -0
  61. data/src/tree/hooks.ts +7 -0
  62. data/src/tree/index.ts +2 -0
  63. data/tree/ArSyncModel.d.ts +39 -0
  64. data/tree/ArSyncModel.js +143 -0
  65. data/tree/ArSyncStore.d.ts +21 -0
  66. data/tree/ArSyncStore.js +365 -0
  67. data/tree/hooks.d.ts +3 -0
  68. data/tree/hooks.js +10 -0
  69. data/tree/index.d.ts +2 -0
  70. data/tree/index.js +4 -0
  71. data/tsconfig.json +15 -0
  72. data/vendor/assets/javascripts/ar_sync_actioncable_adapter.js.erb +7 -0
  73. data/vendor/assets/javascripts/ar_sync_graph.js.erb +17 -0
  74. data/vendor/assets/javascripts/ar_sync_tree.js.erb +17 -0
  75. metadata +187 -0
@@ -0,0 +1,593 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ArSyncApi_1 = require("../core/ArSyncApi");
4
+ const ModelBatchRequest = {
5
+ timer: null,
6
+ apiRequests: {},
7
+ fetch(api, query, id) {
8
+ this.setTimer();
9
+ return new Promise(resolve => {
10
+ const queryJSON = JSON.stringify(query);
11
+ const apiRequest = this.apiRequests[api] = this.apiRequests[api] || {};
12
+ const queryRequests = apiRequest[queryJSON] = apiRequest[queryJSON] || { query, requests: {} };
13
+ const request = queryRequests.requests[id] = queryRequests.requests[id] || { id, callbacks: [] };
14
+ request.callbacks.push(resolve);
15
+ });
16
+ },
17
+ batchFetch() {
18
+ const { apiRequests } = this;
19
+ for (const api in apiRequests) {
20
+ const apiRequest = apiRequests[api];
21
+ for (const { query, requests } of Object.values(apiRequest)) {
22
+ const ids = Object.values(requests).map(({ id }) => id);
23
+ ArSyncApi_1.default.syncFetch({ api, query, params: { ids } }).then((models) => {
24
+ for (const model of models)
25
+ requests[model.id].model = model;
26
+ for (const { model, callbacks } of Object.values(requests)) {
27
+ for (const callback of callbacks)
28
+ callback(model);
29
+ }
30
+ });
31
+ }
32
+ }
33
+ this.apiRequests = {};
34
+ },
35
+ setTimer() {
36
+ if (this.timer)
37
+ return;
38
+ this.timer = setTimeout(() => {
39
+ this.timer = null;
40
+ this.batchFetch();
41
+ }, 20);
42
+ }
43
+ };
44
+ class ArSyncContainerBase {
45
+ constructor() {
46
+ this.listeners = [];
47
+ }
48
+ replaceData(_data, _sync_keys) { }
49
+ initForReload(request) {
50
+ this.networkSubscriber = ArSyncStore.connectionManager.subscribeNetwork((state) => {
51
+ if (state) {
52
+ ArSyncApi_1.default.syncFetch(request).then(data => {
53
+ if (this.data) {
54
+ this.replaceData(data);
55
+ if (this.onConnectionChange)
56
+ this.onConnectionChange(true);
57
+ if (this.onChange)
58
+ this.onChange([], this.data);
59
+ }
60
+ });
61
+ }
62
+ else {
63
+ if (this.onConnectionChange)
64
+ this.onConnectionChange(false);
65
+ }
66
+ });
67
+ }
68
+ release() {
69
+ if (this.networkSubscriber)
70
+ this.networkSubscriber.unsubscribe();
71
+ this.unsubscribeAll();
72
+ for (const child of Object.values(this.children)) {
73
+ if (child)
74
+ child.release();
75
+ }
76
+ this.data = null;
77
+ }
78
+ onChange(path, data) {
79
+ if (this.parentModel)
80
+ this.parentModel.onChange([this.parentKey, ...path], data);
81
+ }
82
+ subscribe(key, listener) {
83
+ this.listeners.push(ArSyncStore.connectionManager.subscribe(key, listener));
84
+ }
85
+ unsubscribeAll() {
86
+ for (const l of this.listeners)
87
+ l.unsubscribe();
88
+ this.listeners = [];
89
+ }
90
+ static parseQuery(query, attrsonly = false) {
91
+ const attributes = {};
92
+ let column = null;
93
+ let params = null;
94
+ if (!query)
95
+ query = [];
96
+ if (query.constructor !== Array)
97
+ query = [query];
98
+ for (const arg of query) {
99
+ if (typeof (arg) === 'string') {
100
+ attributes[arg] = {};
101
+ }
102
+ else if (typeof (arg) === 'object') {
103
+ for (const key in arg) {
104
+ const value = arg[key];
105
+ if (attrsonly) {
106
+ attributes[key] = this.parseQuery(value);
107
+ continue;
108
+ }
109
+ if (key === 'attributes') {
110
+ const child = this.parseQuery(value, true);
111
+ for (const k in child)
112
+ attributes[k] = child[k];
113
+ }
114
+ else if (key === 'as') {
115
+ column = value;
116
+ }
117
+ else if (key === 'params') {
118
+ params = value;
119
+ }
120
+ else {
121
+ attributes[key] = this.parseQuery(value);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ if (attrsonly)
127
+ return attributes;
128
+ return { attributes, as: column, params };
129
+ }
130
+ static _load({ api, id, params, query }, root) {
131
+ const parsedQuery = ArSyncRecord.parseQuery(query);
132
+ if (id) {
133
+ return ModelBatchRequest.fetch(api, query, id).then(data => new ArSyncRecord(parsedQuery, data[0], null, root));
134
+ }
135
+ else {
136
+ const request = { api, query, params };
137
+ return ArSyncApi_1.default.syncFetch(request).then((response) => {
138
+ if (response.collection && response.order) {
139
+ return new ArSyncCollection(response.sync_keys, 'collection', parsedQuery, response, request, root);
140
+ }
141
+ else {
142
+ return new ArSyncRecord(parsedQuery, response, request, root);
143
+ }
144
+ });
145
+ }
146
+ }
147
+ static load(apiParams, root) {
148
+ if (!(apiParams instanceof Array))
149
+ return this._load(apiParams, root);
150
+ return new Promise((resolve, _reject) => {
151
+ const resultModels = [];
152
+ let countdown = apiParams.length;
153
+ apiParams.forEach((param, i) => {
154
+ this._load(param, root).then(model => {
155
+ resultModels[i] = model;
156
+ countdown--;
157
+ if (countdown === 0)
158
+ resolve(resultModels);
159
+ });
160
+ });
161
+ });
162
+ }
163
+ }
164
+ class ArSyncRecord extends ArSyncContainerBase {
165
+ constructor(query, data, request, root) {
166
+ super();
167
+ this.root = root;
168
+ if (request)
169
+ this.initForReload(request);
170
+ this.query = query;
171
+ this.data = {};
172
+ this.children = {};
173
+ this.replaceData(data);
174
+ }
175
+ setSyncKeys(sync_keys) {
176
+ this.sync_keys = sync_keys;
177
+ if (!this.sync_keys) {
178
+ this.sync_keys = [];
179
+ console.error('warning: no sync_keys');
180
+ }
181
+ }
182
+ replaceData(data) {
183
+ this.setSyncKeys(data.sync_keys);
184
+ this.unsubscribeAll();
185
+ if (this.data.id !== data.id) {
186
+ this.mark();
187
+ this.data.id = data.id;
188
+ }
189
+ this.paths = [];
190
+ for (const key in this.query.attributes) {
191
+ const subQuery = this.query.attributes[key];
192
+ const aliasName = subQuery.as || key;
193
+ const subData = data[aliasName];
194
+ if (key === 'sync_keys')
195
+ continue;
196
+ if (subQuery.attributes && (subData instanceof Array || (subData && subData.collection && subData.order))) {
197
+ if (this.children[aliasName]) {
198
+ this.children[aliasName].replaceData(subData, this.sync_keys);
199
+ }
200
+ else {
201
+ const collection = new ArSyncCollection(this.sync_keys, key, subQuery, subData, null, this.root);
202
+ this.mark();
203
+ this.children[aliasName] = collection;
204
+ this.data[aliasName] = collection.data;
205
+ collection.parentModel = this;
206
+ collection.parentKey = aliasName;
207
+ }
208
+ }
209
+ else {
210
+ if (subQuery.attributes)
211
+ this.paths.push(key);
212
+ if (subData && subData.sync_keys) {
213
+ if (this.children[aliasName]) {
214
+ this.children[aliasName].replaceData(subData);
215
+ }
216
+ else {
217
+ const model = new ArSyncRecord(subQuery, subData, null, this.root);
218
+ this.mark();
219
+ this.children[aliasName] = model;
220
+ this.data[aliasName] = model.data;
221
+ model.parentModel = this;
222
+ model.parentKey = aliasName;
223
+ }
224
+ }
225
+ else {
226
+ if (this.children[aliasName]) {
227
+ this.children[aliasName].release();
228
+ delete this.children[aliasName];
229
+ }
230
+ if (this.data[aliasName] !== subData) {
231
+ this.mark();
232
+ this.data[aliasName] = subData;
233
+ }
234
+ }
235
+ }
236
+ }
237
+ this.subscribeAll();
238
+ }
239
+ onNotify(notifyData, path) {
240
+ const { action, class_name, id } = notifyData;
241
+ if (action === 'remove') {
242
+ this.children[path].release();
243
+ this.children[path] = null;
244
+ this.mark();
245
+ this.data[path] = null;
246
+ this.onChange([path], null);
247
+ }
248
+ else if (action === 'add') {
249
+ if (this.data.id === id)
250
+ return;
251
+ const query = this.query.attributes[path];
252
+ ModelBatchRequest.fetch(class_name, query, id).then(data => {
253
+ if (!data)
254
+ return;
255
+ const model = new ArSyncRecord(query, data, null, this.root);
256
+ if (this.children[path])
257
+ this.children[path].release();
258
+ this.children[path] = model;
259
+ this.mark();
260
+ this.data[path] = model.data;
261
+ model.parentModel = this;
262
+ model.parentKey = path;
263
+ this.onChange([path], model.data);
264
+ });
265
+ }
266
+ else {
267
+ ModelBatchRequest.fetch(class_name, this.reloadQuery(), id).then(data => {
268
+ this.update(data);
269
+ });
270
+ }
271
+ }
272
+ subscribeAll() {
273
+ const callback = data => this.onNotify(data);
274
+ for (const key of this.sync_keys) {
275
+ this.subscribe(key, callback);
276
+ }
277
+ for (const path of this.paths) {
278
+ const pathCallback = data => this.onNotify(data, path);
279
+ for (const key of this.sync_keys)
280
+ this.subscribe(key + path, pathCallback);
281
+ }
282
+ }
283
+ reloadQuery() {
284
+ if (this.reloadQueryCache)
285
+ return this.reloadQueryCache;
286
+ const reloadQuery = this.reloadQueryCache = { attributes: [] };
287
+ for (const key in this.query.attributes) {
288
+ if (key === 'sync_keys')
289
+ continue;
290
+ const val = this.query.attributes[key];
291
+ if (!val || !val.attributes) {
292
+ reloadQuery.attributes.push(key);
293
+ }
294
+ else if (!val.params && Object.keys(val.attributes).length === 0) {
295
+ reloadQuery.attributes.push({ [key]: val });
296
+ }
297
+ }
298
+ return reloadQuery;
299
+ }
300
+ update(data) {
301
+ for (const key in data) {
302
+ if (this.data[key] === data[key])
303
+ continue;
304
+ this.mark();
305
+ this.data[key] = data[key];
306
+ this.onChange([key], data[key]);
307
+ }
308
+ }
309
+ markAndSet(key, data) {
310
+ this.mark();
311
+ this.data[key] = data;
312
+ }
313
+ mark() {
314
+ if (!this.root || !this.root.immutable || !Object.isFrozen(this.data))
315
+ return;
316
+ this.data = Object.assign({}, this.data);
317
+ this.root.mark(this.data);
318
+ if (this.parentModel)
319
+ this.parentModel.markAndSet(this.parentKey, this.data);
320
+ }
321
+ onChange(path, data) {
322
+ if (this.parentModel)
323
+ this.parentModel.onChange([this.parentKey, ...path], data);
324
+ }
325
+ }
326
+ class ArSyncCollection extends ArSyncContainerBase {
327
+ constructor(sync_keys, path, query, data, request, root) {
328
+ super();
329
+ this.root = root;
330
+ this.path = path;
331
+ if (request)
332
+ this.initForReload(request);
333
+ if (query.params && (query.params.order || query.params.limit)) {
334
+ this.order = { limit: query.params.limit, mode: query.params.order || 'asc' };
335
+ }
336
+ else {
337
+ this.order = { limit: null, mode: 'asc' };
338
+ }
339
+ this.query = query;
340
+ this.data = [];
341
+ this.children = [];
342
+ this.replaceData(data, sync_keys);
343
+ }
344
+ setSyncKeys(sync_keys) {
345
+ if (sync_keys) {
346
+ this.sync_keys = sync_keys.map(key => key + this.path);
347
+ }
348
+ else {
349
+ console.error('warning: no sync_keys');
350
+ this.sync_keys = [];
351
+ }
352
+ }
353
+ replaceData(data, sync_keys) {
354
+ this.setSyncKeys(sync_keys);
355
+ const existings = {};
356
+ for (const child of this.children)
357
+ existings[child.data.id] = child;
358
+ let collection;
359
+ if (data.collection && data.order) {
360
+ collection = data.collection;
361
+ this.order = data.order;
362
+ }
363
+ else {
364
+ collection = data;
365
+ }
366
+ const newChildren = [];
367
+ const newData = [];
368
+ for (const subData of collection) {
369
+ let model = existings[subData.id];
370
+ if (model) {
371
+ model.replaceData(subData);
372
+ }
373
+ else {
374
+ model = new ArSyncRecord(this.query, subData, null, this.root);
375
+ model.parentModel = this;
376
+ model.parentKey = subData.id;
377
+ }
378
+ newChildren.push(model);
379
+ newData.push(model.data);
380
+ }
381
+ while (this.children.length) {
382
+ const child = this.children.pop();
383
+ if (!existings[child.data.id])
384
+ child.release();
385
+ }
386
+ if (this.data.length || newChildren.length)
387
+ this.mark();
388
+ while (this.data.length)
389
+ this.data.pop();
390
+ for (const child of newChildren)
391
+ this.children.push(child);
392
+ for (const el of newData)
393
+ this.data.push(el);
394
+ this.subscribeAll();
395
+ }
396
+ consumeAdd(className, id) {
397
+ if (this.data.findIndex(a => a.id === id) >= 0)
398
+ return;
399
+ if (this.order.limit === this.data.length) {
400
+ if (this.order.mode === 'asc') {
401
+ const last = this.data[this.data.length - 1];
402
+ if (last && last.id < id)
403
+ return;
404
+ }
405
+ else {
406
+ const last = this.data[this.data.length - 1];
407
+ if (last && last.id > id)
408
+ return;
409
+ }
410
+ }
411
+ ModelBatchRequest.fetch(className, this.query, id).then((data) => {
412
+ if (!data)
413
+ return;
414
+ const model = new ArSyncRecord(this.query, data, null, this.root);
415
+ model.parentModel = this;
416
+ model.parentKey = id;
417
+ const overflow = this.order.limit && this.order.limit === this.data.length;
418
+ let rmodel;
419
+ this.mark();
420
+ if (this.order.mode === 'asc') {
421
+ const last = this.data[this.data.length - 1];
422
+ this.children.push(model);
423
+ this.data.push(model.data);
424
+ if (last && last.id > id) {
425
+ this.children.sort((a, b) => a.data.id < b.data.id ? -1 : +1);
426
+ this.data.sort((a, b) => a.id < b.id ? -1 : +1);
427
+ }
428
+ if (overflow) {
429
+ rmodel = this.children.shift();
430
+ rmodel.release();
431
+ this.data.shift();
432
+ }
433
+ }
434
+ else {
435
+ const first = this.data[0];
436
+ this.children.unshift(model);
437
+ this.data.unshift(model.data);
438
+ if (first && first.id > id) {
439
+ this.children.sort((a, b) => a.data.id > b.data.id ? -1 : +1);
440
+ this.data.sort((a, b) => a.id > b.id ? -1 : +1);
441
+ }
442
+ if (overflow) {
443
+ rmodel = this.children.pop();
444
+ rmodel.release();
445
+ this.data.pop();
446
+ }
447
+ }
448
+ this.onChange([model.id], model.data);
449
+ if (rmodel)
450
+ this.onChange([rmodel.id], null);
451
+ });
452
+ }
453
+ consumeRemove(id) {
454
+ const idx = this.data.findIndex(a => a.id === id);
455
+ if (idx < 0)
456
+ return;
457
+ this.mark();
458
+ this.children[idx].release();
459
+ this.children.splice(idx, 1);
460
+ this.data.splice(idx, 1);
461
+ this.onChange([id], null);
462
+ }
463
+ onNotify(notifyData) {
464
+ if (notifyData.action === 'add') {
465
+ this.consumeAdd(notifyData.class_name, notifyData.id);
466
+ }
467
+ else if (notifyData.action === 'remove') {
468
+ this.consumeRemove(notifyData.id);
469
+ }
470
+ }
471
+ subscribeAll() {
472
+ const callback = data => this.onNotify(data);
473
+ for (const key of this.sync_keys)
474
+ this.subscribe(key, callback);
475
+ }
476
+ markAndSet(id, data) {
477
+ this.mark();
478
+ const idx = this.data.findIndex(a => a.id === id);
479
+ if (idx >= 0)
480
+ this.data[idx] = data;
481
+ }
482
+ mark() {
483
+ if (!this.root || !this.root.immutable || !Object.isFrozen(this.data))
484
+ return;
485
+ this.data = [...this.data];
486
+ this.root.mark(this.data);
487
+ if (this.parentModel)
488
+ this.parentModel.markAndSet(this.parentKey, this.data);
489
+ }
490
+ }
491
+ class ArSyncStore {
492
+ constructor(request, { immutable } = {}) {
493
+ this.immutable = immutable;
494
+ this.markedForFreezeObjects = [];
495
+ this.changes = [];
496
+ this.eventListeners = { events: {}, serial: 0 };
497
+ this.request = request;
498
+ this.complete = false;
499
+ this.data = null;
500
+ this.load(0);
501
+ }
502
+ load(retryCount) {
503
+ ArSyncContainerBase.load(this.request, this).then((container) => {
504
+ if (this.markForRelease) {
505
+ container.release();
506
+ return;
507
+ }
508
+ this.container = container;
509
+ this.data = container.data;
510
+ if (this.immutable)
511
+ this.freezeRecursive(this.data);
512
+ this.complete = true;
513
+ this.notfound = false;
514
+ this.trigger('load');
515
+ this.trigger('change', { path: [], value: this.data });
516
+ container.onChange = (path, value) => {
517
+ this.changes.push({ path, value });
518
+ this.setChangesBufferTimer();
519
+ };
520
+ container.onConnectionChange = state => {
521
+ this.trigger('connection', state);
522
+ };
523
+ }).catch(e => {
524
+ if (this.markForRelease)
525
+ return;
526
+ if (!e.retry) {
527
+ this.complete = true;
528
+ this.notfound = true;
529
+ this.trigger('load');
530
+ return;
531
+ }
532
+ const sleepSeconds = Math.min(Math.pow(2, retryCount), 30);
533
+ this.retryLoadTimer = setTimeout(() => {
534
+ this.retryLoadTimer = null;
535
+ this.load(retryCount + 1);
536
+ }, sleepSeconds * 1000);
537
+ });
538
+ }
539
+ setChangesBufferTimer() {
540
+ if (this.changesBufferTimer)
541
+ return;
542
+ this.changesBufferTimer = setTimeout(() => {
543
+ this.changesBufferTimer = null;
544
+ const changes = this.changes;
545
+ this.changes = [];
546
+ this.freezeMarked();
547
+ this.data = this.container.data;
548
+ changes.forEach(patch => this.trigger('change', patch));
549
+ }, 20);
550
+ }
551
+ subscribe(event, callback) {
552
+ let listeners = this.eventListeners.events[event];
553
+ if (!listeners)
554
+ this.eventListeners.events[event] = listeners = {};
555
+ const id = this.eventListeners.serial++;
556
+ listeners[id] = callback;
557
+ return { unsubscribe: () => { delete listeners[id]; } };
558
+ }
559
+ trigger(event, arg) {
560
+ const listeners = this.eventListeners.events[event];
561
+ if (!listeners)
562
+ return;
563
+ for (const id in listeners)
564
+ listeners[id](arg);
565
+ }
566
+ mark(object) {
567
+ this.markedForFreezeObjects.push(object);
568
+ }
569
+ freezeRecursive(obj) {
570
+ if (Object.isFrozen(obj))
571
+ return obj;
572
+ for (const key in obj)
573
+ this.freezeRecursive(obj[key]);
574
+ Object.freeze(obj);
575
+ }
576
+ freezeMarked() {
577
+ this.markedForFreezeObjects.forEach(obj => this.freezeRecursive(obj));
578
+ this.markedForFreezeObjects = [];
579
+ }
580
+ release() {
581
+ if (this.retryLoadTimer)
582
+ clearTimeout(this.retryLoadTimer);
583
+ if (this.changesBufferTimer)
584
+ clearTimeout(this.changesBufferTimer);
585
+ if (this.container) {
586
+ this.container.release();
587
+ }
588
+ else {
589
+ this.markForRelease = true;
590
+ }
591
+ }
592
+ }
593
+ exports.default = ArSyncStore;