ar_sync 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
data/src/tree/hooks.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { useArSyncFetch } from '../core/hooksBase'
2
+ import { useArSyncModelWithClass, Request, DataAndStatus } from '../core/hooksBase'
3
+ import ArSyncModel from './ArSyncModel'
4
+
5
+ export function useArSyncModel<T>(request: Request | null): DataAndStatus<T> {
6
+ return useArSyncModelWithClass<T>(ArSyncModel, request)
7
+ }
data/src/tree/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ import ArSyncModel from './ArSyncModel'
2
+ export default ArSyncModel
@@ -0,0 +1,39 @@
1
+ import ArSyncModelBase from '../core/ArSyncModelBase';
2
+ import ConnectionAdapter from '../core/ConnectionAdapter';
3
+ declare class ArSyncRecord {
4
+ immutable: any;
5
+ request: any;
6
+ subscriptions: any;
7
+ store: any;
8
+ retryLoadTimer: any;
9
+ data: any;
10
+ bufferTimer: any;
11
+ bufferedPatches: any;
12
+ eventListeners: any;
13
+ networkSubscription: any;
14
+ complete: boolean;
15
+ notfound?: boolean;
16
+ static connectionManager: any;
17
+ constructor(request: any, option?: {
18
+ immutable?: boolean | undefined;
19
+ });
20
+ release(): void;
21
+ unsubscribeAll(): void;
22
+ load(callback: any, retryCount?: number): void;
23
+ retryLoad(callback: any, retryCount: any): void;
24
+ patchReceived(patch: any): void;
25
+ subscribe(event: any, callback: any): {
26
+ unsubscribe: () => void;
27
+ };
28
+ trigger(event: any, arg?: any): void;
29
+ initializeStore(keys: any, data: any, option: any): void;
30
+ }
31
+ export default class ArSyncModel<T> extends ArSyncModelBase<T> {
32
+ static setConnectionAdapter(adapter: ConnectionAdapter): void;
33
+ static createRefModel(request: any, option: any): ArSyncRecord;
34
+ refManagerClass(): typeof ArSyncModel;
35
+ connectionManager(): any;
36
+ static _cache: {};
37
+ static cacheTimeout: number;
38
+ }
39
+ export {};
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ArSyncStore_1 = require("./ArSyncStore");
4
+ const ArSyncApi_1 = require("../core/ArSyncApi");
5
+ const ConnectionManager_1 = require("../core/ConnectionManager");
6
+ const ArSyncModelBase_1 = require("../core/ArSyncModelBase");
7
+ class ArSyncRecord {
8
+ constructor(request, option = {}) {
9
+ this.immutable = option.immutable ? true : false;
10
+ this.request = request;
11
+ this.subscriptions = [];
12
+ this.store = null;
13
+ this.data = null;
14
+ this.complete = false;
15
+ this.bufferedPatches = [];
16
+ this.eventListeners = { events: {}, serial: 0 };
17
+ this.networkSubscription = ArSyncRecord.connectionManager.subscribeNetwork((status) => {
18
+ if (this.notfound) {
19
+ this.trigger('connection', status);
20
+ return;
21
+ }
22
+ if (status) {
23
+ this.load(() => {
24
+ this.trigger('connection', status);
25
+ this.trigger('change', { path: [], value: this.data });
26
+ });
27
+ }
28
+ else {
29
+ this.unsubscribeAll();
30
+ this.trigger('connection', false);
31
+ }
32
+ });
33
+ this.load(() => {
34
+ this.trigger('load');
35
+ this.trigger('change', { path: [], value: this.data });
36
+ });
37
+ }
38
+ release() {
39
+ this.unsubscribeAll();
40
+ this.networkSubscription.unsubscribe();
41
+ }
42
+ unsubscribeAll() {
43
+ if (this.retryLoadTimer)
44
+ clearTimeout(this.retryLoadTimer);
45
+ for (const s of this.subscriptions)
46
+ s.unsubscribe();
47
+ this.subscriptions = [];
48
+ }
49
+ load(callback, retryCount = 0) {
50
+ ArSyncApi_1.default.syncFetch(this.request).then(syncData => {
51
+ const { keys, data, limit, order } = syncData;
52
+ this.initializeStore(keys, data, { limit, order, immutable: this.immutable });
53
+ if (callback)
54
+ callback(true, this.data);
55
+ }).catch(e => {
56
+ console.error(e);
57
+ if (e.retry) {
58
+ this.retryLoad(callback, retryCount + 1);
59
+ }
60
+ else {
61
+ this.initializeStore(null, null, null);
62
+ if (callback)
63
+ callback(false, this.data);
64
+ }
65
+ });
66
+ }
67
+ retryLoad(callback, retryCount) {
68
+ const sleepSeconds = Math.min(Math.pow(2, retryCount), 30);
69
+ this.retryLoadTimer = setTimeout(() => {
70
+ this.retryLoadTimer = null;
71
+ this.load(callback, retryCount);
72
+ }, sleepSeconds * 1000);
73
+ }
74
+ patchReceived(patch) {
75
+ const buffer = this.bufferedPatches;
76
+ buffer.push(patch);
77
+ if (this.bufferTimer)
78
+ return;
79
+ this.bufferTimer = setTimeout(() => {
80
+ this.bufferTimer = null;
81
+ this.bufferedPatches;
82
+ const buf = this.bufferedPatches;
83
+ this.bufferedPatches = [];
84
+ const { changes, events } = this.store.batchUpdate(buf);
85
+ this.data = this.store.data;
86
+ changes.forEach(change => this.trigger('change', change));
87
+ events.forEach(event => {
88
+ this.trigger(event.type, event.data);
89
+ });
90
+ }, 16);
91
+ }
92
+ subscribe(event, callback) {
93
+ let listeners = this.eventListeners.events[event];
94
+ if (!listeners)
95
+ this.eventListeners.events[event] = listeners = {};
96
+ const id = this.eventListeners.serial++;
97
+ listeners[id] = callback;
98
+ return { unsubscribe: () => { delete listeners[id]; } };
99
+ }
100
+ trigger(event, arg) {
101
+ const listeners = this.eventListeners.events[event];
102
+ if (!listeners)
103
+ return;
104
+ for (const id in listeners)
105
+ listeners[id](arg);
106
+ }
107
+ initializeStore(keys, data, option) {
108
+ this.complete = true;
109
+ if (!keys) {
110
+ this.notfound = true;
111
+ return;
112
+ }
113
+ this.notfound = false;
114
+ const query = this.request.query;
115
+ if (this.store) {
116
+ this.store.replaceData(data);
117
+ }
118
+ else {
119
+ this.store = new ArSyncStore_1.default(query, data, option);
120
+ this.data = this.store.data;
121
+ }
122
+ this.subscriptions = keys.map(key => {
123
+ return ArSyncRecord.connectionManager.subscribe(key, patch => this.patchReceived(patch));
124
+ });
125
+ }
126
+ }
127
+ class ArSyncModel extends ArSyncModelBase_1.default {
128
+ static setConnectionAdapter(adapter) {
129
+ ArSyncRecord.connectionManager = new ConnectionManager_1.default(adapter);
130
+ }
131
+ static createRefModel(request, option) {
132
+ return new ArSyncRecord(request, option);
133
+ }
134
+ refManagerClass() {
135
+ return ArSyncModel;
136
+ }
137
+ connectionManager() {
138
+ return ArSyncRecord.connectionManager;
139
+ }
140
+ }
141
+ ArSyncModel._cache = {};
142
+ ArSyncModel.cacheTimeout = 10 * 1000;
143
+ exports.default = ArSyncModel;
@@ -0,0 +1,21 @@
1
+ export default class ArSyncStore {
2
+ data: any;
3
+ query: any;
4
+ immutable: any;
5
+ constructor(query: any, data: any, option?: {
6
+ immutable?: boolean | undefined;
7
+ });
8
+ replaceData(data: any): void;
9
+ batchUpdate(patches: any): {
10
+ changes: any;
11
+ events: never[];
12
+ };
13
+ update(patch: any): {
14
+ changes: any;
15
+ events: never[];
16
+ };
17
+ _slicePatch(patchData: any, query: any): {};
18
+ _applyPatch(data: any, accessKeys: any, actualPath: any, updator: any, query: any, patchData: any): void;
19
+ _update(patch: any, updator: any, events: any): void;
20
+ static parseQuery(query: any, attrsonly?: any): {};
21
+ }
@@ -0,0 +1,365 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Updator {
4
+ constructor(immutable) {
5
+ this.changes = [];
6
+ this.markedForFreezeObjects = [];
7
+ this.immutable = immutable;
8
+ }
9
+ static createFrozenObject(obj) {
10
+ if (!obj)
11
+ return obj;
12
+ if (obj.constructor === Array) {
13
+ obj = obj.map(el => Updator.createFrozenObject(el));
14
+ }
15
+ else if (typeof obj === 'object') {
16
+ obj = Object.assign({}, obj);
17
+ for (const key in obj) {
18
+ obj[key] = Updator.createFrozenObject(obj[key]);
19
+ }
20
+ }
21
+ Object.freeze(obj);
22
+ return obj;
23
+ }
24
+ replaceData(data, newData) {
25
+ if (this.immutable)
26
+ return Updator.createFrozenObject(newData);
27
+ return this.recursivelyReplaceData(data, newData);
28
+ }
29
+ recursivelyReplaceData(data, newData) {
30
+ const replaceArray = (as, bs) => {
31
+ const aids = {};
32
+ for (const a of as) {
33
+ if (!a.id)
34
+ return false;
35
+ aids[a.id] = a;
36
+ }
37
+ const order = {};
38
+ bs.forEach((b, i) => {
39
+ if (!b.id)
40
+ return false;
41
+ if (aids[b.id]) {
42
+ replaceObject(aids[b.id], b);
43
+ }
44
+ else {
45
+ as.push(b);
46
+ }
47
+ order[b.id] = i + 1;
48
+ });
49
+ as.sort((a, b) => {
50
+ const oa = order[a.id] || Infinity;
51
+ const ob = order[b.id] || Infinity;
52
+ return oa > ob ? +1 : oa < ob ? -1 : 0;
53
+ });
54
+ while (as.length && !order[as[as.length - 1].id])
55
+ as.pop();
56
+ return true;
57
+ };
58
+ const replaceObject = (aobj, bobj) => {
59
+ const keys = {};
60
+ for (const key in aobj)
61
+ keys[key] = true;
62
+ for (const key in bobj)
63
+ keys[key] = true;
64
+ for (const key in keys) {
65
+ const a = aobj[key];
66
+ const b = bobj[key];
67
+ if ((a instanceof Array) && (b instanceof Array)) {
68
+ if (!replaceArray(a, b))
69
+ aobj[key] = b;
70
+ }
71
+ else if (a && b && (typeof a === 'object') && (typeof b === 'object') && !(a instanceof Array) && !(b instanceof Array)) {
72
+ replaceObject(a, b);
73
+ }
74
+ else if (a !== b) {
75
+ aobj[key] = b;
76
+ }
77
+ }
78
+ };
79
+ replaceObject(data, newData);
80
+ return data;
81
+ }
82
+ mark(obj) {
83
+ if (!this.immutable)
84
+ return obj;
85
+ if (!Object.isFrozen(this.data))
86
+ return obj;
87
+ const mobj = (obj.constructor === Array) ? [...obj] : Object.assign({}, obj);
88
+ this.markedForFreezeObjects.push(mobj);
89
+ return mobj;
90
+ }
91
+ trace(data, path) {
92
+ path.forEach(key => {
93
+ if (this.immutable)
94
+ data[key] = this.mark(data[key]);
95
+ data = data[key];
96
+ });
97
+ return data;
98
+ }
99
+ assign(el, path, column, value, orderParam) {
100
+ if (this.immutable)
101
+ value = Updator.createFrozenObject(value);
102
+ if (el.constructor === Array && !el[column]) {
103
+ this.changes.push({
104
+ path: path.concat([value.id]),
105
+ target: el,
106
+ id: value.id,
107
+ valueWas: null,
108
+ value
109
+ });
110
+ const limitReached = orderParam && orderParam.limit != null && el.length === orderParam.limit;
111
+ let removed;
112
+ if (orderParam && orderParam.order == 'desc') {
113
+ el.unshift(value);
114
+ if (limitReached)
115
+ removed = el.pop();
116
+ }
117
+ else {
118
+ el.push(value);
119
+ if (limitReached)
120
+ removed = el.pop();
121
+ }
122
+ if (removed)
123
+ this.changes.push({
124
+ path: path.concat([removed.id]),
125
+ target: el,
126
+ id: removed.id,
127
+ valueWas: removed,
128
+ value: null
129
+ });
130
+ }
131
+ else if (!this.valueEquals(el[column], value)) {
132
+ this.changes.push({
133
+ path: path.concat([column]),
134
+ target: el,
135
+ column: column,
136
+ valueWas: el[column],
137
+ value
138
+ });
139
+ el[column] = value;
140
+ }
141
+ }
142
+ valueEquals(a, b) {
143
+ if (a === b)
144
+ return true;
145
+ if (!a || !b)
146
+ return a == b;
147
+ if (typeof a !== 'object')
148
+ return false;
149
+ if (typeof b !== 'object')
150
+ return false;
151
+ const ja = JSON.stringify(a);
152
+ const jb = JSON.stringify(b);
153
+ return ja === jb;
154
+ }
155
+ add(tree, accessKeys, path, column, value, orderParam) {
156
+ const root = this.mark(tree);
157
+ const data = this.trace(root, accessKeys);
158
+ if (data)
159
+ this.assign(data, path, column, value, orderParam);
160
+ return root;
161
+ }
162
+ remove(tree, accessKeys, path, column) {
163
+ const root = this.mark(tree);
164
+ let data = this.trace(root, accessKeys);
165
+ if (!data)
166
+ return root;
167
+ if (data.constructor === Array) {
168
+ this.changes.push({
169
+ path: path.concat([data[column].id]),
170
+ target: data,
171
+ id: data[column].id,
172
+ valueWas: data[column],
173
+ value: null
174
+ });
175
+ data.splice(column, 1);
176
+ }
177
+ else if (data[column] !== null) {
178
+ this.changes.push({
179
+ path: path.concat([column]),
180
+ target: data,
181
+ column: column,
182
+ valueWas: data[column],
183
+ value: null
184
+ });
185
+ data[column] = null;
186
+ }
187
+ return root;
188
+ }
189
+ cleanup() {
190
+ this.markedForFreezeObjects.forEach(mobj => Object.freeze(mobj));
191
+ }
192
+ }
193
+ class ArSyncStore {
194
+ constructor(query, data, option = {}) {
195
+ this.data = option.immutable ? Updator.createFrozenObject(data) : data;
196
+ this.query = ArSyncStore.parseQuery(query);
197
+ this.immutable = option.immutable;
198
+ }
199
+ replaceData(data) {
200
+ this.data = new Updator(this.immutable).replaceData(this.data, data);
201
+ }
202
+ batchUpdate(patches) {
203
+ const events = [];
204
+ const updator = new Updator(this.immutable);
205
+ patches.forEach(patch => this._update(patch, updator, events));
206
+ updator.cleanup();
207
+ return { changes: updator.changes, events };
208
+ }
209
+ update(patch) {
210
+ return this.batchUpdate([patch]);
211
+ }
212
+ _slicePatch(patchData, query) {
213
+ const obj = {};
214
+ for (const key in patchData) {
215
+ if (key === 'id' || query.attributes['*']) {
216
+ obj[key] = patchData[key];
217
+ }
218
+ else {
219
+ const subq = query.attributes[key];
220
+ if (subq) {
221
+ obj[subq.column || key] = patchData[key];
222
+ }
223
+ }
224
+ }
225
+ return obj;
226
+ }
227
+ _applyPatch(data, accessKeys, actualPath, updator, query, patchData) {
228
+ for (const key in patchData) {
229
+ const subq = query.attributes[key];
230
+ const value = patchData[key];
231
+ if (subq || query.attributes['*']) {
232
+ const subcol = (subq && subq.column) || key;
233
+ if (data[subcol] !== value) {
234
+ this.data = updator.add(this.data, accessKeys, actualPath, subcol, value);
235
+ }
236
+ }
237
+ }
238
+ }
239
+ _update(patch, updator, events) {
240
+ const { action, path } = patch;
241
+ const patchData = patch.data;
242
+ let query = this.query;
243
+ let data = this.data;
244
+ const actualPath = [];
245
+ const accessKeys = [];
246
+ for (let i = 0; i < path.length - 1; i++) {
247
+ const nameOrId = path[i];
248
+ if (typeof (nameOrId) === 'number') {
249
+ const idx = data.findIndex(o => o.id === nameOrId);
250
+ if (idx < 0)
251
+ return;
252
+ actualPath.push(nameOrId);
253
+ accessKeys.push(idx);
254
+ data = data[idx];
255
+ }
256
+ else {
257
+ const { attributes } = query;
258
+ if (!attributes[nameOrId])
259
+ return;
260
+ const column = attributes[nameOrId].column || nameOrId;
261
+ query = attributes[nameOrId];
262
+ actualPath.push(column);
263
+ accessKeys.push(column);
264
+ data = data[column];
265
+ }
266
+ if (!data)
267
+ return;
268
+ }
269
+ const nameOrId = path[path.length - 1];
270
+ let id, idx, column, target = data;
271
+ if (typeof (nameOrId) === 'number') {
272
+ id = nameOrId;
273
+ idx = data.findIndex(o => o.id === id);
274
+ target = data[idx];
275
+ }
276
+ else if (nameOrId) {
277
+ const { attributes } = query;
278
+ if (!attributes[nameOrId])
279
+ return;
280
+ column = attributes[nameOrId].column || nameOrId;
281
+ query = attributes[nameOrId];
282
+ target = data[column];
283
+ }
284
+ if (action === 'create') {
285
+ const obj = this._slicePatch(patchData, query);
286
+ if (column) {
287
+ this.data = updator.add(this.data, accessKeys, actualPath, column, obj);
288
+ }
289
+ else if (!target) {
290
+ const ordering = Object.assign({}, patch.ordering);
291
+ const limitOverride = query.params && query.params.limit;
292
+ ordering.order = query.params && query.params.order || ordering.order;
293
+ if (ordering.limit == null || limitOverride != null && limitOverride < ordering.limit)
294
+ ordering.limit = limitOverride;
295
+ this.data = updator.add(this.data, accessKeys, actualPath, data.length, obj, ordering);
296
+ }
297
+ return;
298
+ }
299
+ if (action === 'destroy') {
300
+ if (column) {
301
+ this.data = updator.remove(this.data, accessKeys, actualPath, column);
302
+ }
303
+ else if (idx >= 0) {
304
+ this.data = updator.remove(this.data, accessKeys, actualPath, idx);
305
+ }
306
+ return;
307
+ }
308
+ if (!target)
309
+ return;
310
+ if (column) {
311
+ actualPath.push(column);
312
+ accessKeys.push(column);
313
+ }
314
+ else if (id) {
315
+ actualPath.push(id);
316
+ accessKeys.push(idx);
317
+ }
318
+ if (action === 'update') {
319
+ this._applyPatch(target, accessKeys, actualPath, updator, query, patchData);
320
+ }
321
+ else {
322
+ const eventData = { target, path: actualPath, data: patchData.data };
323
+ events.push({ type: patchData.type, data: eventData });
324
+ }
325
+ }
326
+ static parseQuery(query, attrsonly) {
327
+ const attributes = {};
328
+ let column = null;
329
+ let params = null;
330
+ if (query.constructor !== Array)
331
+ query = [query];
332
+ for (const arg of query) {
333
+ if (typeof (arg) === 'string') {
334
+ attributes[arg] = {};
335
+ }
336
+ else if (typeof (arg) === 'object') {
337
+ for (const key in arg) {
338
+ const value = arg[key];
339
+ if (attrsonly) {
340
+ attributes[key] = this.parseQuery(value);
341
+ continue;
342
+ }
343
+ if (key === 'attributes') {
344
+ const child = this.parseQuery(value, true);
345
+ for (const k in child)
346
+ attributes[k] = child[k];
347
+ }
348
+ else if (key === 'as') {
349
+ column = value;
350
+ }
351
+ else if (key === 'params') {
352
+ params = value;
353
+ }
354
+ else {
355
+ attributes[key] = this.parseQuery(value);
356
+ }
357
+ }
358
+ }
359
+ }
360
+ if (attrsonly)
361
+ return attributes;
362
+ return { attributes, column, params };
363
+ }
364
+ }
365
+ exports.default = ArSyncStore;