ar_sync 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,7 @@
1
1
  import ArSyncApi from './ArSyncApi'
2
+ export type Request = { api: string; query: any; params?: any; id?: IDType }
3
+
4
+ type IDType = number | string
2
5
 
3
6
  class ModelBatchRequest {
4
7
  timer: number | null = null
@@ -6,8 +9,8 @@ class ModelBatchRequest {
6
9
  Map<string,
7
10
  {
8
11
  query,
9
- requests: Map<number, {
10
- id: number
12
+ requests: Map<IDType, {
13
+ id: IDType
11
14
  model?
12
15
  callbacks: {
13
16
  resolve: (model: any) => void
@@ -17,7 +20,7 @@ class ModelBatchRequest {
17
20
  }
18
21
  >
19
22
  >()
20
- fetch(api: string, query, id: number) {
23
+ fetch(api: string, query, id: IDType) {
21
24
  this.setTimer()
22
25
  return new Promise((resolve, reject) => {
23
26
  const queryJSON = JSON.stringify(query)
@@ -36,7 +39,7 @@ class ModelBatchRequest {
36
39
  const ids = Array.from(requests.keys())
37
40
  ArSyncApi.syncFetch({ api, query, params: { ids } }).then((models: any[]) => {
38
41
  for (const model of models) {
39
- const req = requests.get(model.id)
42
+ const req = requests.get(model._sync.id)
40
43
  if (req) req.model = model
41
44
  }
42
45
  requests.forEach(({ model, callbacks }) => {
@@ -67,18 +70,18 @@ type ParsedQuery = {
67
70
  params: any
68
71
  } | {}
69
72
 
73
+ type SyncField = { id: IDType; keys: string[] }
70
74
  type Unsubscribable = { unsubscribe: () => void }
71
75
 
72
76
  class ArSyncContainerBase {
73
77
  data
74
78
  listeners: Unsubscribable[] = []
75
79
  networkSubscriber?: Unsubscribable
76
- parentModel
80
+ parentModel: ArSyncRecord | ArSyncCollection | null = null
77
81
  parentKey
78
82
  children: ArSyncContainerBase[] | { [key: string]: ArSyncContainerBase | null }
79
- sync_keys: string[]
80
83
  onConnectionChange?: (status: boolean) => void
81
- replaceData(_data, _sync_keys?) {}
84
+ replaceData(_data, _parentSyncKeys?) {}
82
85
  initForReload(request) {
83
86
  this.networkSubscriber = ArSyncStore.connectionManager.subscribeNetwork((state) => {
84
87
  if (!state) {
@@ -197,63 +200,52 @@ class ArSyncContainerBase {
197
200
  if (attrsonly) return attributes
198
201
  return { attributes, as: column, params }
199
202
  }
200
- static _load({ api, id, params, query }, root) {
203
+ static load({ api, id, params, query }: Request, root: ArSyncStore) {
201
204
  const parsedQuery = ArSyncRecord.parseQuery(query)
202
205
  const compactQueryAttributes = ArSyncRecord.compactQueryAttributes(parsedQuery)
203
206
  if (id != null) {
204
207
  return modelBatchRequest.fetch(api, compactQueryAttributes, id).then(data => {
205
208
  if (!data) throw { retry: false }
206
209
  const request = { api, id, query: compactQueryAttributes }
207
- return new ArSyncRecord(parsedQuery, data, request, root)
210
+ return new ArSyncRecord(parsedQuery, data, request, root, null, null)
208
211
  })
209
212
  } else {
210
213
  const request = { api, query: compactQueryAttributes, params }
211
214
  return ArSyncApi.syncFetch(request).then((response: any) => {
212
215
  if (!response) {
213
216
  throw { retry: false }
214
- } else if (response.collection && response.order) {
215
- return new ArSyncCollection(response.sync_keys, 'collection', parsedQuery, response, request, root)
217
+ } else if (response.collection && response.order && response._sync) {
218
+ return new ArSyncCollection(response._sync.keys, 'collection', parsedQuery, response, request, root, null, null)
216
219
  } else if (response instanceof Array) {
217
- return new ArSyncCollection([], '', parsedQuery, response, request, root)
220
+ return new ArSyncCollection([], '', parsedQuery, response, request, root, null, null)
218
221
  } else {
219
- return new ArSyncRecord(parsedQuery, response, request, root)
222
+ return new ArSyncRecord(parsedQuery, response, request, root, null, null)
220
223
  }
221
224
  })
222
225
  }
223
226
  }
224
- static load(apiParams, root) {
225
- if (!(apiParams instanceof Array)) return this._load(apiParams, root)
226
- return new Promise((resolve, _reject) => {
227
- const resultModels: any[] = []
228
- let countdown = apiParams.length
229
- apiParams.forEach((param, i) => {
230
- this._load(param, root).then(model => {
231
- resultModels[i] = model
232
- countdown --
233
- if (countdown === 0) resolve(resultModels)
234
- })
235
- })
236
- })
237
- }
238
227
  }
239
228
 
240
229
  type NotifyData = {
241
230
  action: 'add' | 'remove' | 'update'
242
- class_name: string
243
- id: number
231
+ class: string
232
+ id: IDType
244
233
  field?: string
245
234
  }
246
235
 
247
236
  class ArSyncRecord extends ArSyncContainerBase {
248
- id: number
249
- root
237
+ id: IDType
238
+ root: ArSyncStore
250
239
  query
251
240
  queryAttributes
252
241
  data
242
+ syncKeys: string[]
253
243
  children: { [key: string]: ArSyncContainerBase | null }
254
244
  paths: string[]
255
245
  reloadQueryCache
256
- constructor(query, data, request, root) {
246
+ rootRecord: boolean
247
+ fetching = new Set<string>()
248
+ constructor(query, data, request, root: ArSyncStore, parentModel: ArSyncRecord | ArSyncCollection | null, parentKey: string | number | null) {
257
249
  super()
258
250
  this.root = root
259
251
  if (request) this.initForReload(request)
@@ -261,48 +253,43 @@ class ArSyncRecord extends ArSyncContainerBase {
261
253
  this.queryAttributes = query.attributes || {}
262
254
  this.data = {}
263
255
  this.children = {}
256
+ this.rootRecord = !parentModel
257
+ this.id = data._sync.id
258
+ this.syncKeys = data._sync.keys
264
259
  this.replaceData(data)
260
+ this.parentModel = parentModel
261
+ this.parentKey = parentKey
265
262
  }
266
- setSyncKeys(sync_keys: string[] | undefined) {
267
- this.sync_keys = sync_keys ?? []
268
- }
269
- replaceData(data) {
270
- this.setSyncKeys(data.sync_keys)
263
+ replaceData(data: { _sync: SyncField }) {
264
+ this.id = data._sync.id
265
+ this.syncKeys = data._sync.keys
271
266
  this.unsubscribeAll()
272
- if (this.data.id !== data.id) {
273
- this.mark()
274
- this.data.id = data.id
275
- }
276
267
  this.paths = []
277
268
  for (const key in this.queryAttributes) {
278
269
  const subQuery = this.queryAttributes[key]
279
270
  const aliasName = subQuery.as || key
280
271
  const subData = data[aliasName]
281
272
  const child = this.children[aliasName]
282
- if (key === 'sync_keys') continue
283
- if (subData instanceof Array || (subData && subData.collection && subData.order)) {
273
+ if (key === '_sync') continue
274
+ if (subData instanceof Array || (subData && subData.collection && subData.order && subData._sync)) {
284
275
  if (child) {
285
- child.replaceData(subData, this.sync_keys)
276
+ child.replaceData(subData, this.syncKeys)
286
277
  } else {
287
- const collection = new ArSyncCollection(this.sync_keys, key, subQuery, subData, null, this.root)
278
+ const collection = new ArSyncCollection(this.syncKeys, key, subQuery, subData, null, this.root, this, aliasName)
288
279
  this.mark()
289
280
  this.children[aliasName] = collection
290
281
  this.data[aliasName] = collection.data
291
- collection.parentModel = this
292
- collection.parentKey = aliasName
293
282
  }
294
283
  } else {
295
284
  if (subQuery.attributes && Object.keys(subQuery.attributes).length > 0) this.paths.push(key)
296
- if (subData && subData.sync_keys) {
285
+ if (subData && subData._sync) {
297
286
  if (child) {
298
287
  child.replaceData(subData)
299
288
  } else {
300
- const model = new ArSyncRecord(subQuery, subData, null, this.root)
289
+ const model = new ArSyncRecord(subQuery, subData, null, this.root, this, aliasName)
301
290
  this.mark()
302
291
  this.children[aliasName] = model
303
292
  this.data[aliasName] = model.data
304
- model.parentModel = this
305
- model.parentKey = aliasName
306
293
  }
307
294
  } else {
308
295
  if(child) {
@@ -318,6 +305,7 @@ class ArSyncRecord extends ArSyncContainerBase {
318
305
  }
319
306
  if (this.queryAttributes['*']) {
320
307
  for (const key in data) {
308
+ if (key === '_sync') continue
321
309
  if (!this.queryAttributes[key] && this.data[key] !== data[key]) {
322
310
  this.mark()
323
311
  this.data[key] = data[key]
@@ -327,28 +315,34 @@ class ArSyncRecord extends ArSyncContainerBase {
327
315
  this.subscribeAll()
328
316
  }
329
317
  onNotify(notifyData: NotifyData, path?: string) {
330
- const { action, class_name: className, id } = notifyData
318
+ const { action, class: className, id } = notifyData
331
319
  const query = path && this.queryAttributes[path]
332
320
  const aliasName = (query && query.as) || path;
333
321
  if (action === 'remove') {
334
322
  const child = this.children[aliasName]
323
+ this.fetching.delete(`${aliasName}:${id}`) // To cancel consumeAdd
335
324
  if (child) child.release()
336
325
  this.children[aliasName] = null
337
326
  this.mark()
338
327
  this.data[aliasName] = null
339
328
  this.onChange([aliasName], null)
340
329
  } else if (action === 'add') {
341
- if (this.data[aliasName] && this.data[aliasName].id === id) return
330
+ const child = this.children[aliasName]
331
+ if (child instanceof ArSyncRecord && child.id === id) return
332
+ const fetchKey = `${aliasName}:${id}`
333
+ this.fetching.add(fetchKey)
342
334
  modelBatchRequest.fetch(className, ArSyncRecord.compactQueryAttributes(query), id).then(data => {
335
+ // Record already removed
336
+ if (!this.fetching.has(fetchKey)) return
337
+
338
+ this.fetching.delete(fetchKey)
343
339
  if (!data || !this.data) return
344
- const model = new ArSyncRecord(query, data, null, this.root)
340
+ const model = new ArSyncRecord(query, data, null, this.root, this, aliasName)
345
341
  const child = this.children[aliasName]
346
342
  if (child) child.release()
347
343
  this.children[aliasName] = model
348
344
  this.mark()
349
345
  this.data[aliasName] = model.data
350
- model.parentModel = this
351
- model.parentKey = aliasName
352
346
  this.onChange([aliasName], model.data)
353
347
  }).catch(e => {
354
348
  console.error(`failed to load ${className}:${id} ${e}`)
@@ -366,12 +360,16 @@ class ArSyncRecord extends ArSyncContainerBase {
366
360
  }
367
361
  subscribeAll() {
368
362
  const callback = data => this.onNotify(data)
369
- for (const key of this.sync_keys) {
363
+ for (const key of this.syncKeys) {
370
364
  this.subscribe(key, callback)
371
365
  }
372
366
  for (const path of this.paths) {
373
367
  const pathCallback = data => this.onNotify(data, path)
374
- for (const key of this.sync_keys) this.subscribe(key + path, pathCallback)
368
+ for (const key of this.syncKeys) this.subscribe(key + path, pathCallback)
369
+ }
370
+ if (this.rootRecord) {
371
+ const key = this.syncKeys[0]
372
+ if (key) this.subscribe(key + '_destroy', () => this.root.handleDestroy())
375
373
  }
376
374
  }
377
375
  patchQuery(key: string) {
@@ -383,7 +381,7 @@ class ArSyncRecord extends ArSyncContainerBase {
383
381
  let arrayQuery = [] as string[] | null
384
382
  const hashQuery = {}
385
383
  for (const key in this.queryAttributes) {
386
- if (key === 'sync_keys') continue
384
+ if (key === '_sync') continue
387
385
  const val = this.queryAttributes[key]
388
386
  if (!val || !val.attributes) {
389
387
  arrayQuery?.push(key)
@@ -397,6 +395,7 @@ class ArSyncRecord extends ArSyncContainerBase {
397
395
  }
398
396
  update(data) {
399
397
  for (const key in data) {
398
+ if (key === '_sync') continue
400
399
  const subQuery = this.queryAttributes[key]
401
400
  if (subQuery && subQuery.attributes && Object.keys(subQuery.attributes).length > 0) continue
402
401
  if (this.data[key] === data[key]) continue
@@ -413,22 +412,24 @@ class ArSyncRecord extends ArSyncContainerBase {
413
412
  if (!this.root || !this.root.immutable || !Object.isFrozen(this.data)) return
414
413
  this.data = { ...this.data }
415
414
  this.root.mark(this.data)
416
- if (this.parentModel) this.parentModel.markAndSet(this.parentKey, this.data)
415
+ if (this.parentModel && this.parentKey) (this.parentModel as { markAndSet(key: string | number, data: any): any }).markAndSet(this.parentKey, this.data)
417
416
  }
418
417
  }
419
418
 
420
419
  type Ordering = { first?: number; last?: number; orderBy: string; direction: 'asc' | 'desc' }
421
420
  class ArSyncCollection extends ArSyncContainerBase {
422
- root
421
+ root: ArSyncStore
423
422
  path: string
424
423
  ordering: Ordering = { orderBy: 'id', direction: 'asc' }
425
424
  query
426
425
  queryAttributes
427
426
  compactQueryAttributes
427
+ syncKeys: string[]
428
428
  data: any[]
429
429
  children: ArSyncRecord[]
430
430
  aliasOrderKey = 'id'
431
- constructor(sync_keys: string[], path: string, query, data: any[], request, root){
431
+ fetching = new Set<IDType>()
432
+ constructor(parentSyncKeys: string[], path: string, query, data: any[], request, root: ArSyncStore, parentModel: ArSyncRecord | null, parentKey: string | null){
432
433
  super()
433
434
  this.root = root
434
435
  this.path = path
@@ -441,7 +442,9 @@ class ArSyncCollection extends ArSyncContainerBase {
441
442
  }
442
443
  this.data = []
443
444
  this.children = []
444
- this.replaceData(data, sync_keys)
445
+ this.replaceData(data, parentSyncKeys)
446
+ this.parentModel = parentModel
447
+ this.parentKey = parentKey
445
448
  }
446
449
  setOrdering(ordering: { first?: unknown; last?: unknown; orderBy?: unknown; direction?: unknown }) {
447
450
  let direction: 'asc' | 'desc' = 'asc'
@@ -456,17 +459,17 @@ class ArSyncCollection extends ArSyncContainerBase {
456
459
  this.aliasOrderKey = (subQuery && subQuery.as) || orderBy
457
460
  this.ordering = { first, last, direction, orderBy }
458
461
  }
459
- setSyncKeys(sync_keys: string[]) {
460
- if (sync_keys) {
461
- this.sync_keys = sync_keys.map(key => key + this.path)
462
+ setSyncKeys(parentSyncKeys: string[] | undefined) {
463
+ if (parentSyncKeys) {
464
+ this.syncKeys = parentSyncKeys.map(key => key + this.path)
462
465
  } else {
463
- this.sync_keys = []
466
+ this.syncKeys = []
464
467
  }
465
468
  }
466
- replaceData(data: any[] | { collection: any[]; ordering: Ordering }, sync_keys: string[]) {
467
- this.setSyncKeys(sync_keys)
468
- const existings = new Map<number, ArSyncRecord>()
469
- for (const child of this.children) existings.set(child.data.id, child)
469
+ replaceData(data: any[] | { collection: any[]; ordering: Ordering }, parentSyncKeys: string[]) {
470
+ this.setSyncKeys(parentSyncKeys)
471
+ const existings = new Map<IDType, ArSyncRecord>()
472
+ for (const child of this.children) existings.set(child.id, child)
470
473
  let collection: any[]
471
474
  if (Array.isArray(data)) {
472
475
  collection = data
@@ -478,14 +481,12 @@ class ArSyncCollection extends ArSyncContainerBase {
478
481
  const newData: any[] = []
479
482
  for (const subData of collection) {
480
483
  let model: ArSyncRecord | undefined = undefined
481
- if (typeof(subData) === 'object' && subData && 'sync_keys' in subData) model = existings.get(subData.id)
484
+ if (typeof(subData) === 'object' && subData && '_sync' in subData) model = existings.get(subData._sync.id)
482
485
  let data = subData
483
486
  if (model) {
484
487
  model.replaceData(subData)
485
- } else if (subData.sync_keys) {
486
- model = new ArSyncRecord(this.query, subData, null, this.root)
487
- model.parentModel = this
488
- model.parentKey = subData.id
488
+ } else if (subData._sync) {
489
+ model = new ArSyncRecord(this.query, subData, null, this.root, this, subData._sync.id)
489
490
  }
490
491
  if (model) {
491
492
  newChildren.push(model)
@@ -495,7 +496,7 @@ class ArSyncCollection extends ArSyncContainerBase {
495
496
  }
496
497
  while (this.children.length) {
497
498
  const child = this.children.pop()!
498
- if (!existings.has(child.data.id)) child.release()
499
+ if (!existings.has(child.id)) child.release()
499
500
  }
500
501
  if (this.data.length || newChildren.length) this.mark()
501
502
  while (this.data.length) this.data.pop()
@@ -503,13 +504,13 @@ class ArSyncCollection extends ArSyncContainerBase {
503
504
  for (const el of newData) this.data.push(el)
504
505
  this.subscribeAll()
505
506
  }
506
- consumeAdd(className: string, id: number) {
507
+ consumeAdd(className: string, id: IDType) {
507
508
  const { first, last, direction } = this.ordering
508
509
  const limit = first || last
509
- if (this.data.findIndex(a => a.id === id) >= 0) return
510
- if (limit && limit <= this.data.length) {
511
- const lastItem = this.data[this.data.length - 1]
512
- const firstItem = this.data[0]
510
+ if (this.children.find(a => a.id === id)) return
511
+ if (limit && limit <= this.children.length) {
512
+ const lastItem = this.children[this.children.length - 1]
513
+ const firstItem = this.children[0]
513
514
  if (direction === 'asc') {
514
515
  if (first) {
515
516
  if (lastItem && lastItem.id < id) return
@@ -524,11 +525,14 @@ class ArSyncCollection extends ArSyncContainerBase {
524
525
  }
525
526
  }
526
527
  }
528
+ this.fetching.add(id)
527
529
  modelBatchRequest.fetch(className, this.compactQueryAttributes, id).then((data: any) => {
530
+ // Record already removed
531
+ if (!this.fetching.has(id)) return
532
+
533
+ this.fetching.delete(id)
528
534
  if (!data || !this.data) return
529
- const model = new ArSyncRecord(this.query, data, null, this.root)
530
- model.parentModel = this
531
- model.parentKey = id
535
+ const model = new ArSyncRecord(this.query, data, null, this.root, this, id)
532
536
  const overflow = limit && limit <= this.data.length
533
537
  let rmodel: ArSyncRecord | undefined
534
538
  this.mark()
@@ -583,8 +587,9 @@ class ArSyncCollection extends ArSyncContainerBase {
583
587
  this.data.sort((a, b) => a[orderKey] > b[orderKey] ? -1 : +1)
584
588
  }
585
589
  }
586
- consumeRemove(id: number) {
587
- const idx = this.data.findIndex(a => a.id === id)
590
+ consumeRemove(id: IDType) {
591
+ const idx = this.children.findIndex(a => a.id === id)
592
+ this.fetching.delete(id) // To cancel consumeAdd
588
593
  if (idx < 0) return
589
594
  this.mark()
590
595
  this.children[idx].release()
@@ -592,58 +597,64 @@ class ArSyncCollection extends ArSyncContainerBase {
592
597
  this.data.splice(idx, 1)
593
598
  this.onChange([id], null)
594
599
  }
595
- onNotify(notifyData) {
600
+ onNotify(notifyData: NotifyData) {
596
601
  if (notifyData.action === 'add') {
597
- this.consumeAdd(notifyData.class_name, notifyData.id)
602
+ this.consumeAdd(notifyData.class, notifyData.id)
598
603
  } else if (notifyData.action === 'remove') {
599
604
  this.consumeRemove(notifyData.id)
600
605
  }
601
606
  }
602
607
  subscribeAll() {
603
608
  const callback = data => this.onNotify(data)
604
- for (const key of this.sync_keys) this.subscribe(key, callback)
609
+ for (const key of this.syncKeys) this.subscribe(key, callback)
605
610
  }
606
611
  onChange(path: (string | number)[], data) {
607
612
  super.onChange(path, data)
608
613
  if (path[1] === this.aliasOrderKey) this.markAndSort()
609
614
  }
610
- markAndSet(id: number, data) {
615
+ markAndSet(id: IDType, data) {
611
616
  this.mark()
612
- const idx = this.data.findIndex(a => a.id === id)
617
+ const idx = this.children.findIndex(a => a.id === id)
613
618
  if (idx >= 0) this.data[idx] = data
614
619
  }
615
620
  mark() {
616
621
  if (!this.root || !this.root.immutable || !Object.isFrozen(this.data)) return
617
622
  this.data = [...this.data]
618
623
  this.root.mark(this.data)
619
- if (this.parentModel) this.parentModel.markAndSet(this.parentKey, this.data)
624
+ if (this.parentModel && this.parentKey) (this.parentModel as { markAndSet(key: string | number, data: any): any }).markAndSet(this.parentKey, this.data)
620
625
  }
621
626
  }
622
627
 
623
- export default class ArSyncStore {
628
+ export class ArSyncStore {
624
629
  immutable: boolean
625
630
  markedForFreezeObjects: any[]
626
631
  changes
627
632
  eventListeners
628
633
  markForRelease: true | undefined
629
634
  container
630
- request
631
- complete: boolean
635
+ request: Request
636
+ complete = false
632
637
  notfound?: boolean
638
+ destroyed = false
633
639
  data
634
640
  changesBufferTimer: number | undefined | null
635
641
  retryLoadTimer: number | undefined | null
636
642
  static connectionManager
637
- constructor(request, { immutable } = {} as { immutable?: boolean }) {
643
+ constructor(request: Request, { immutable } = {} as { immutable?: boolean }) {
638
644
  this.immutable = !!immutable
639
645
  this.markedForFreezeObjects = []
640
646
  this.changes = []
641
647
  this.eventListeners = { events: {}, serial: 0 }
642
648
  this.request = request
643
- this.complete = false
644
649
  this.data = null
645
650
  this.load(0)
646
651
  }
652
+ handleDestroy() {
653
+ this.release()
654
+ this.data = null
655
+ this.destroyed = true
656
+ this.trigger('destroy')
657
+ }
647
658
  load(retryCount: number) {
648
659
  ArSyncContainerBase.load(this.request, this).then((container: ArSyncContainerBase) => {
649
660
  if (this.markForRelease) {
data/src/core/hooks.ts CHANGED
@@ -21,11 +21,11 @@ function checkHooks() {
21
21
  if (!useState) throw 'uninitialized. needs `initializeHooks({ useState, useEffect, useMemo, useRef })`'
22
22
  }
23
23
 
24
- interface ModelStatus { complete: boolean; notfound?: boolean; connected: boolean }
24
+ interface ModelStatus { complete: boolean; notfound?: boolean; connected: boolean; destroyed: boolean }
25
25
  export type DataAndStatus<T> = [T | null, ModelStatus]
26
26
  export interface Request { api: string; params?: any; id?: number; query: any }
27
27
 
28
- const initialResult: DataAndStatus<any> = [null, { complete: false, notfound: undefined, connected: true }]
28
+ const initialResult: DataAndStatus<any> = [null, { complete: false, notfound: undefined, connected: true, destroyed: false }]
29
29
  export function useArSyncModel<T>(request: Request | null): DataAndStatus<T> {
30
30
  checkHooks()
31
31
  const [result, setResult] = useState<DataAndStatus<T>>(initialResult)
@@ -39,12 +39,12 @@ export function useArSyncModel<T>(request: Request | null): DataAndStatus<T> {
39
39
  }
40
40
  const model = new ArSyncModel<T>(request, { immutable: true })
41
41
  function update() {
42
- const { complete, notfound, connected, data } = model
42
+ const { complete, notfound, connected, destroyed, data } = model
43
43
  setResult(resultWas => {
44
44
  const [dataWas, statusWas] = resultWas
45
- const statusPersisted = statusWas.complete === complete && statusWas.notfound === notfound && statusWas.connected === connected
45
+ const statusPersisted = statusWas.complete === complete && statusWas.notfound === notfound && statusWas.connected === connected && statusWas.destroyed === destroyed
46
46
  if (dataWas === data && statusPersisted) return resultWas
47
- const status = statusPersisted ? statusWas : { complete, notfound, connected }
47
+ const status = statusPersisted ? statusWas : { complete, notfound, connected, destroyed }
48
48
  return [data, status]
49
49
  })
50
50
  }
@@ -55,6 +55,7 @@ export function useArSyncModel<T>(request: Request | null): DataAndStatus<T> {
55
55
  }
56
56
  model.subscribe('load', update)
57
57
  model.subscribe('change', update)
58
+ model.subscribe('destroy', update)
58
59
  model.subscribe('connection', update)
59
60
  return () => model.release()
60
61
  }, [requestString])
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - tompng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-16 00:00:00.000000000 Z
11
+ date: 2024-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: pry
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: sqlite3
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -105,7 +91,6 @@ files:
105
91
  - ".gitignore"
106
92
  - ".travis.yml"
107
93
  - Gemfile
108
- - Gemfile.lock
109
94
  - LICENSE.txt
110
95
  - README.md
111
96
  - Rakefile
@@ -129,7 +114,8 @@ files:
129
114
  - core/hooks.d.ts
130
115
  - core/hooks.js
131
116
  - gemfiles/Gemfile-rails-6
132
- - gemfiles/Gemfile-rails-7
117
+ - gemfiles/Gemfile-rails-7-0
118
+ - gemfiles/Gemfile-rails-7-1
133
119
  - index.d.ts
134
120
  - index.js
135
121
  - lib/ar_sync.rb
@@ -176,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
176
162
  - !ruby/object:Gem::Version
177
163
  version: '0'
178
164
  requirements: []
179
- rubygems_version: 3.3.3
165
+ rubygems_version: 3.5.9
180
166
  signing_key:
181
167
  specification_version: 4
182
168
  summary: ActiveRecord - JavaScript Sync
data/Gemfile.lock DELETED
@@ -1,54 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- ar_sync (1.1.1)
5
- activerecord
6
- ar_serializer
7
-
8
- GEM
9
- remote: https://rubygems.org/
10
- specs:
11
- activemodel (7.0.2.3)
12
- activesupport (= 7.0.2.3)
13
- activerecord (7.0.2.3)
14
- activemodel (= 7.0.2.3)
15
- activesupport (= 7.0.2.3)
16
- activerecord-import (1.4.0)
17
- activerecord (>= 4.2)
18
- activesupport (7.0.2.3)
19
- concurrent-ruby (~> 1.0, >= 1.0.2)
20
- i18n (>= 1.6, < 2)
21
- minitest (>= 5.1)
22
- tzinfo (~> 2.0)
23
- ar_serializer (1.2.0)
24
- activerecord
25
- top_n_loader
26
- coderay (1.1.3)
27
- concurrent-ruby (1.1.10)
28
- i18n (1.10.0)
29
- concurrent-ruby (~> 1.0)
30
- method_source (1.0.0)
31
- minitest (5.15.0)
32
- pry (0.14.1)
33
- coderay (~> 1.1)
34
- method_source (~> 1.0)
35
- rake (13.0.6)
36
- sqlite3 (1.4.2)
37
- top_n_loader (1.0.2)
38
- activerecord
39
- tzinfo (2.0.4)
40
- concurrent-ruby (~> 1.0)
41
-
42
- PLATFORMS
43
- ruby
44
-
45
- DEPENDENCIES
46
- activerecord-import
47
- ar_serializer
48
- ar_sync!
49
- pry
50
- rake
51
- sqlite3
52
-
53
- BUNDLED WITH
54
- 2.1.2