cozy-pouch-link 60.15.1 → 60.16.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/CozyPouchLink.js +123 -3
- package/dist/CozyPouchLink.spec.js +5 -0
- package/dist/PouchManager.js +168 -28
- package/dist/PouchManager.spec.js +1 -1
- package/dist/remote.spec.js +0 -2
- package/dist/replicateOnce.js +40 -28
- package/dist/startReplication.js +318 -82
- package/dist/startReplication.spec.js +385 -11
- package/package.json +3 -3
- package/types/CozyPouchLink.d.ts +34 -2
- package/types/PouchManager.d.ts +28 -2
- package/types/startReplication.d.ts +11 -1
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import MicroEE from 'microee'
|
|
2
2
|
import { fetchRemoteLastSequence, fetchRemoteInstance } from './remote'
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
replicateAllDocs,
|
|
6
|
+
startReplication,
|
|
7
|
+
sharedDriveReplicateAllDocs
|
|
8
|
+
} from './startReplication'
|
|
9
|
+
import helpers from './helpers'
|
|
6
10
|
|
|
7
11
|
jest.mock('./remote', () => ({
|
|
8
12
|
fetchRemoteLastSequence: jest.fn(),
|
|
@@ -14,6 +18,8 @@ jest.mock('./helpers', () => ({
|
|
|
14
18
|
insertBulkDocs: jest.fn()
|
|
15
19
|
}))
|
|
16
20
|
|
|
21
|
+
const { insertBulkDocs } = helpers
|
|
22
|
+
|
|
17
23
|
const url = 'http://test.local'
|
|
18
24
|
|
|
19
25
|
const generateDocs = nDocs => {
|
|
@@ -124,7 +130,8 @@ describe('startReplication', () => {
|
|
|
124
130
|
pouch,
|
|
125
131
|
replicationOptions,
|
|
126
132
|
getReplicationURL,
|
|
127
|
-
storage
|
|
133
|
+
storage,
|
|
134
|
+
null
|
|
128
135
|
)
|
|
129
136
|
|
|
130
137
|
expect(fetchRemoteInstance).toHaveBeenCalledWith(
|
|
@@ -151,7 +158,8 @@ describe('startReplication', () => {
|
|
|
151
158
|
pouch,
|
|
152
159
|
replicationOptions,
|
|
153
160
|
getReplicationURL,
|
|
154
|
-
storage
|
|
161
|
+
storage,
|
|
162
|
+
null
|
|
155
163
|
)
|
|
156
164
|
mockReplicationOn.emit('complete')
|
|
157
165
|
await promise
|
|
@@ -179,7 +187,8 @@ describe('startReplication', () => {
|
|
|
179
187
|
pouch,
|
|
180
188
|
replicationOptions,
|
|
181
189
|
getReplicationURL,
|
|
182
|
-
storage
|
|
190
|
+
storage,
|
|
191
|
+
null
|
|
183
192
|
)
|
|
184
193
|
mockReplicationOn.emit('complete')
|
|
185
194
|
await promise
|
|
@@ -206,7 +215,8 @@ describe('startReplication', () => {
|
|
|
206
215
|
pouch,
|
|
207
216
|
replicationOptions,
|
|
208
217
|
getReplicationURL,
|
|
209
|
-
storage
|
|
218
|
+
storage,
|
|
219
|
+
null
|
|
210
220
|
)
|
|
211
221
|
mockReplicationOn.emit('error', 'some_error_message')
|
|
212
222
|
await expect(promise).rejects.toEqual('some_error_message')
|
|
@@ -225,7 +235,8 @@ describe('startReplication', () => {
|
|
|
225
235
|
pouch,
|
|
226
236
|
replicationOptions,
|
|
227
237
|
getReplicationURL,
|
|
228
|
-
storage
|
|
238
|
+
storage,
|
|
239
|
+
null
|
|
229
240
|
)
|
|
230
241
|
// Sync format
|
|
231
242
|
mockReplicationOn.emit('change', {
|
|
@@ -275,7 +286,8 @@ describe('startReplication', () => {
|
|
|
275
286
|
pouch,
|
|
276
287
|
replicationOptions,
|
|
277
288
|
getReplicationURL,
|
|
278
|
-
storage
|
|
289
|
+
storage,
|
|
290
|
+
null
|
|
279
291
|
)
|
|
280
292
|
mockReplicationOn.emit('change', {
|
|
281
293
|
change: {
|
|
@@ -315,7 +327,8 @@ describe('startReplication', () => {
|
|
|
315
327
|
pouch,
|
|
316
328
|
replicationOptions,
|
|
317
329
|
getReplicationURL,
|
|
318
|
-
storage
|
|
330
|
+
storage,
|
|
331
|
+
null
|
|
319
332
|
)
|
|
320
333
|
mockReplicationOn.emit('change', {
|
|
321
334
|
change: {
|
|
@@ -356,7 +369,8 @@ describe('startReplication', () => {
|
|
|
356
369
|
pouch,
|
|
357
370
|
replicationOptions,
|
|
358
371
|
getReplicationURL,
|
|
359
|
-
storage
|
|
372
|
+
storage,
|
|
373
|
+
null
|
|
360
374
|
)
|
|
361
375
|
|
|
362
376
|
expect(promise.cancel).toBeDefined()
|
|
@@ -385,6 +399,366 @@ describe('startReplication', () => {
|
|
|
385
399
|
expect(result).toStrictEqual([])
|
|
386
400
|
})
|
|
387
401
|
})
|
|
402
|
+
|
|
403
|
+
describe('sharedDriveReplicateAllDocs', () => {
|
|
404
|
+
const driveId = 'test-drive-123'
|
|
405
|
+
const doctype = 'io.cozy.files'
|
|
406
|
+
|
|
407
|
+
const mockClient = {
|
|
408
|
+
collection: jest.fn()
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const mockCollection = {
|
|
412
|
+
fetchChanges: jest.fn()
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const mockPouch = {
|
|
416
|
+
get: jest.fn(),
|
|
417
|
+
remove: jest.fn(),
|
|
418
|
+
bulkGet: jest.fn(),
|
|
419
|
+
bulkDocs: jest.fn()
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const mockStorage = {
|
|
423
|
+
getLastReplicatedDocID: jest.fn(),
|
|
424
|
+
persistLastReplicatedDocID: jest.fn(),
|
|
425
|
+
getDoctypeLastSequence: jest.fn(),
|
|
426
|
+
persistDoctypeLastSequence: jest.fn()
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
beforeEach(() => {
|
|
430
|
+
jest.resetAllMocks()
|
|
431
|
+
mockClient.collection.mockReturnValue(mockCollection)
|
|
432
|
+
insertBulkDocs.mockResolvedValue()
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
it('should throw error when driveId is not provided', async () => {
|
|
436
|
+
await expect(
|
|
437
|
+
sharedDriveReplicateAllDocs({
|
|
438
|
+
pouch: mockPouch,
|
|
439
|
+
storage: mockStorage,
|
|
440
|
+
doctype,
|
|
441
|
+
client: mockClient,
|
|
442
|
+
initialReplication: false
|
|
443
|
+
})
|
|
444
|
+
).rejects.toThrow('sharedDriveReplicateAllDocs: driveId is required')
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
it('should handle initial replication with empty results', async () => {
|
|
448
|
+
mockStorage.getDoctypeLastSequence.mockResolvedValue(null)
|
|
449
|
+
mockCollection.fetchChanges.mockResolvedValue({
|
|
450
|
+
newLastSeq: 'seq-1',
|
|
451
|
+
results: [],
|
|
452
|
+
pending: false
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
const result = await sharedDriveReplicateAllDocs({
|
|
456
|
+
driveId,
|
|
457
|
+
pouch: mockPouch,
|
|
458
|
+
storage: mockStorage,
|
|
459
|
+
doctype,
|
|
460
|
+
client: mockClient,
|
|
461
|
+
initialReplication: true
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
expect(result).toEqual([])
|
|
465
|
+
expect(mockCollection.fetchChanges).toHaveBeenCalledWith(
|
|
466
|
+
{ include_docs: true },
|
|
467
|
+
{
|
|
468
|
+
includeFilePath: false,
|
|
469
|
+
skipDeleted: true,
|
|
470
|
+
skipTrashed: true,
|
|
471
|
+
limit: 1000
|
|
472
|
+
}
|
|
473
|
+
)
|
|
474
|
+
expect(insertBulkDocs).toHaveBeenCalledWith(mockPouch, [])
|
|
475
|
+
expect(mockStorage.persistDoctypeLastSequence).toHaveBeenCalledWith(
|
|
476
|
+
doctype,
|
|
477
|
+
'seq-1'
|
|
478
|
+
)
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
it('should handle initial replication with single batch of documents', async () => {
|
|
482
|
+
mockStorage.getDoctypeLastSequence.mockResolvedValue(null)
|
|
483
|
+
const mockDocs = [
|
|
484
|
+
{ doc: { _id: 'doc-1', name: 'file1.txt' } },
|
|
485
|
+
{ doc: { _id: 'doc-2', name: 'file2.txt' } }
|
|
486
|
+
]
|
|
487
|
+
mockCollection.fetchChanges.mockResolvedValue({
|
|
488
|
+
newLastSeq: 'seq-2',
|
|
489
|
+
results: mockDocs,
|
|
490
|
+
pending: false
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
const result = await sharedDriveReplicateAllDocs({
|
|
494
|
+
driveId,
|
|
495
|
+
pouch: mockPouch,
|
|
496
|
+
storage: mockStorage,
|
|
497
|
+
doctype,
|
|
498
|
+
client: mockClient,
|
|
499
|
+
initialReplication: true
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
const expectedDocs = [
|
|
503
|
+
{ _id: 'doc-1', name: 'file1.txt', driveId },
|
|
504
|
+
{ _id: 'doc-2', name: 'file2.txt', driveId }
|
|
505
|
+
]
|
|
506
|
+
|
|
507
|
+
expect(result).toEqual(expectedDocs)
|
|
508
|
+
expect(mockCollection.fetchChanges).toHaveBeenCalledWith(
|
|
509
|
+
{ include_docs: true },
|
|
510
|
+
{
|
|
511
|
+
includeFilePath: false,
|
|
512
|
+
skipDeleted: true,
|
|
513
|
+
skipTrashed: true,
|
|
514
|
+
limit: 1000
|
|
515
|
+
}
|
|
516
|
+
)
|
|
517
|
+
expect(insertBulkDocs).toHaveBeenCalledWith(mockPouch, expectedDocs)
|
|
518
|
+
expect(mockStorage.persistDoctypeLastSequence).toHaveBeenCalledWith(
|
|
519
|
+
doctype,
|
|
520
|
+
'seq-2'
|
|
521
|
+
)
|
|
522
|
+
})
|
|
523
|
+
|
|
524
|
+
it('should handle incremental replication from last saved doc ID', async () => {
|
|
525
|
+
mockStorage.getDoctypeLastSequence.mockResolvedValue('seq-1')
|
|
526
|
+
const mockDocs = [{ doc: { _id: 'doc-3', name: 'file3.txt' } }]
|
|
527
|
+
mockCollection.fetchChanges.mockResolvedValue({
|
|
528
|
+
newLastSeq: 'seq-3',
|
|
529
|
+
results: mockDocs,
|
|
530
|
+
pending: false
|
|
531
|
+
})
|
|
532
|
+
|
|
533
|
+
const result = await sharedDriveReplicateAllDocs({
|
|
534
|
+
driveId,
|
|
535
|
+
pouch: mockPouch,
|
|
536
|
+
storage: mockStorage,
|
|
537
|
+
doctype,
|
|
538
|
+
client: mockClient,
|
|
539
|
+
initialReplication: false
|
|
540
|
+
})
|
|
541
|
+
|
|
542
|
+
const expectedDocs = [{ _id: 'doc-3', name: 'file3.txt', driveId }]
|
|
543
|
+
|
|
544
|
+
expect(result).toEqual(expectedDocs)
|
|
545
|
+
expect(mockCollection.fetchChanges).toHaveBeenCalledWith(
|
|
546
|
+
{ include_docs: true, since: 'seq-1' },
|
|
547
|
+
{
|
|
548
|
+
includeFilePath: false,
|
|
549
|
+
skipDeleted: false,
|
|
550
|
+
skipTrashed: false,
|
|
551
|
+
limit: 1000
|
|
552
|
+
}
|
|
553
|
+
)
|
|
554
|
+
expect(insertBulkDocs).toHaveBeenCalledWith(mockPouch, expectedDocs)
|
|
555
|
+
expect(mockStorage.persistDoctypeLastSequence).toHaveBeenCalledWith(
|
|
556
|
+
doctype,
|
|
557
|
+
'seq-3'
|
|
558
|
+
)
|
|
559
|
+
})
|
|
560
|
+
|
|
561
|
+
it('should handle replication with multiple batches (pagination)', async () => {
|
|
562
|
+
mockStorage.getDoctypeLastSequence.mockResolvedValue(null)
|
|
563
|
+
|
|
564
|
+
// First batch
|
|
565
|
+
mockCollection.fetchChanges.mockResolvedValueOnce({
|
|
566
|
+
newLastSeq: 'seq-1',
|
|
567
|
+
results: [{ doc: { _id: 'doc-1', name: 'file1.txt' } }],
|
|
568
|
+
pending: true
|
|
569
|
+
})
|
|
570
|
+
|
|
571
|
+
// Second batch
|
|
572
|
+
mockCollection.fetchChanges.mockResolvedValueOnce({
|
|
573
|
+
newLastSeq: 'seq-2',
|
|
574
|
+
results: [{ doc: { _id: 'doc-2', name: 'file2.txt' } }],
|
|
575
|
+
pending: false
|
|
576
|
+
})
|
|
577
|
+
|
|
578
|
+
const result = await sharedDriveReplicateAllDocs({
|
|
579
|
+
driveId,
|
|
580
|
+
pouch: mockPouch,
|
|
581
|
+
storage: mockStorage,
|
|
582
|
+
doctype,
|
|
583
|
+
client: mockClient,
|
|
584
|
+
initialReplication: true
|
|
585
|
+
})
|
|
586
|
+
|
|
587
|
+
const expectedDocs = [
|
|
588
|
+
{ _id: 'doc-1', name: 'file1.txt', driveId },
|
|
589
|
+
{ _id: 'doc-2', name: 'file2.txt', driveId }
|
|
590
|
+
]
|
|
591
|
+
|
|
592
|
+
expect(result).toEqual(expectedDocs)
|
|
593
|
+
expect(mockCollection.fetchChanges).toHaveBeenCalledTimes(2)
|
|
594
|
+
expect(insertBulkDocs).toHaveBeenCalledTimes(2)
|
|
595
|
+
expect(mockStorage.persistDoctypeLastSequence).toHaveBeenCalledTimes(2)
|
|
596
|
+
})
|
|
597
|
+
|
|
598
|
+
it('should handle deleted documents by removing them from local pouch', async () => {
|
|
599
|
+
mockStorage.getDoctypeLastSequence.mockResolvedValue(null)
|
|
600
|
+
const mockDocs = [
|
|
601
|
+
{ doc: { _id: 'doc-1', name: 'file1.txt' } },
|
|
602
|
+
{ doc: { _id: 'doc-2', name: 'file2.txt', _deleted: true } }
|
|
603
|
+
]
|
|
604
|
+
mockCollection.fetchChanges.mockResolvedValue({
|
|
605
|
+
newLastSeq: 'seq-1',
|
|
606
|
+
results: mockDocs,
|
|
607
|
+
pending: false
|
|
608
|
+
})
|
|
609
|
+
|
|
610
|
+
// Mock that doc-2 exists in local pouch
|
|
611
|
+
mockPouch.bulkGet.mockResolvedValue({
|
|
612
|
+
results: [
|
|
613
|
+
{
|
|
614
|
+
docs: [
|
|
615
|
+
{
|
|
616
|
+
ok: { _id: 'doc-2', _rev: '1-abc', name: 'file2.txt' }
|
|
617
|
+
}
|
|
618
|
+
]
|
|
619
|
+
}
|
|
620
|
+
]
|
|
621
|
+
})
|
|
622
|
+
mockPouch.bulkDocs.mockResolvedValue([{ ok: true, id: 'doc-2' }])
|
|
623
|
+
|
|
624
|
+
const result = await sharedDriveReplicateAllDocs({
|
|
625
|
+
driveId,
|
|
626
|
+
pouch: mockPouch,
|
|
627
|
+
storage: mockStorage,
|
|
628
|
+
doctype,
|
|
629
|
+
client: mockClient,
|
|
630
|
+
initialReplication: true
|
|
631
|
+
})
|
|
632
|
+
|
|
633
|
+
const expectedDocs = [
|
|
634
|
+
{ _id: 'doc-1', name: 'file1.txt', driveId },
|
|
635
|
+
{ _id: 'doc-2', name: 'file2.txt', _deleted: true, driveId }
|
|
636
|
+
]
|
|
637
|
+
|
|
638
|
+
expect(result).toEqual(expectedDocs)
|
|
639
|
+
expect(mockPouch.bulkGet).toHaveBeenCalledWith({
|
|
640
|
+
docs: [{ id: 'doc-2' }]
|
|
641
|
+
})
|
|
642
|
+
expect(mockPouch.bulkDocs).toHaveBeenCalledWith([
|
|
643
|
+
{
|
|
644
|
+
_id: 'doc-2',
|
|
645
|
+
_rev: '1-abc',
|
|
646
|
+
name: 'file2.txt',
|
|
647
|
+
_deleted: true
|
|
648
|
+
}
|
|
649
|
+
])
|
|
650
|
+
expect(insertBulkDocs).toHaveBeenCalledWith(
|
|
651
|
+
mockPouch,
|
|
652
|
+
expectedDocs.filter(doc => !doc._deleted)
|
|
653
|
+
)
|
|
654
|
+
})
|
|
655
|
+
|
|
656
|
+
it('should handle deleted documents when they do not exist in local pouch', async () => {
|
|
657
|
+
mockStorage.getDoctypeLastSequence.mockResolvedValue(null)
|
|
658
|
+
const mockDocs = [{ doc: { _id: 'doc-1', _deleted: true } }]
|
|
659
|
+
mockCollection.fetchChanges.mockResolvedValue({
|
|
660
|
+
newLastSeq: 'seq-1',
|
|
661
|
+
results: mockDocs,
|
|
662
|
+
pending: false
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
// Mock that doc-1 does not exist in local pouch (bulkGet returns error)
|
|
666
|
+
mockPouch.bulkGet.mockResolvedValue({
|
|
667
|
+
results: [
|
|
668
|
+
{
|
|
669
|
+
docs: [
|
|
670
|
+
{
|
|
671
|
+
error: {
|
|
672
|
+
status: 404,
|
|
673
|
+
name: 'not_found',
|
|
674
|
+
message: 'missing'
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
]
|
|
678
|
+
}
|
|
679
|
+
]
|
|
680
|
+
})
|
|
681
|
+
mockPouch.bulkDocs.mockResolvedValue([])
|
|
682
|
+
|
|
683
|
+
const result = await sharedDriveReplicateAllDocs({
|
|
684
|
+
driveId,
|
|
685
|
+
pouch: mockPouch,
|
|
686
|
+
storage: mockStorage,
|
|
687
|
+
doctype,
|
|
688
|
+
client: mockClient,
|
|
689
|
+
initialReplication: true
|
|
690
|
+
})
|
|
691
|
+
|
|
692
|
+
const expectedDocs = [{ _id: 'doc-1', _deleted: true, driveId }]
|
|
693
|
+
|
|
694
|
+
expect(result).toEqual(expectedDocs)
|
|
695
|
+
expect(mockPouch.bulkGet).toHaveBeenCalledWith({
|
|
696
|
+
docs: [{ id: 'doc-1' }]
|
|
697
|
+
})
|
|
698
|
+
expect(mockPouch.bulkDocs).not.toHaveBeenCalled()
|
|
699
|
+
expect(insertBulkDocs).toHaveBeenCalledWith(
|
|
700
|
+
mockPouch,
|
|
701
|
+
expectedDocs.filter(doc => !doc._deleted)
|
|
702
|
+
)
|
|
703
|
+
})
|
|
704
|
+
|
|
705
|
+
it('should use correct options for initial vs incremental replication', async () => {
|
|
706
|
+
mockStorage.getDoctypeLastSequence.mockResolvedValue('seq-1')
|
|
707
|
+
mockCollection.fetchChanges.mockResolvedValue({
|
|
708
|
+
newLastSeq: 'seq-2',
|
|
709
|
+
results: [],
|
|
710
|
+
pending: false
|
|
711
|
+
})
|
|
712
|
+
|
|
713
|
+
// Test initial replication
|
|
714
|
+
await sharedDriveReplicateAllDocs({
|
|
715
|
+
driveId,
|
|
716
|
+
pouch: mockPouch,
|
|
717
|
+
storage: mockStorage,
|
|
718
|
+
doctype,
|
|
719
|
+
client: mockClient,
|
|
720
|
+
initialReplication: true
|
|
721
|
+
})
|
|
722
|
+
|
|
723
|
+
expect(mockCollection.fetchChanges).toHaveBeenCalledWith(
|
|
724
|
+
{ include_docs: true, since: 'seq-1' },
|
|
725
|
+
{
|
|
726
|
+
includeFilePath: false,
|
|
727
|
+
skipDeleted: true,
|
|
728
|
+
skipTrashed: true,
|
|
729
|
+
limit: 1000
|
|
730
|
+
}
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
jest.clearAllMocks()
|
|
734
|
+
mockStorage.getDoctypeLastSequence.mockResolvedValue('seq-1')
|
|
735
|
+
mockCollection.fetchChanges.mockResolvedValue({
|
|
736
|
+
newLastSeq: 'seq-3',
|
|
737
|
+
results: [],
|
|
738
|
+
pending: false
|
|
739
|
+
})
|
|
740
|
+
|
|
741
|
+
// Test incremental replication
|
|
742
|
+
await sharedDriveReplicateAllDocs({
|
|
743
|
+
driveId,
|
|
744
|
+
pouch: mockPouch,
|
|
745
|
+
storage: mockStorage,
|
|
746
|
+
doctype,
|
|
747
|
+
client: mockClient,
|
|
748
|
+
initialReplication: false
|
|
749
|
+
})
|
|
750
|
+
|
|
751
|
+
expect(mockCollection.fetchChanges).toHaveBeenCalledWith(
|
|
752
|
+
{ include_docs: true, since: 'seq-1' },
|
|
753
|
+
{
|
|
754
|
+
includeFilePath: false,
|
|
755
|
+
skipDeleted: false,
|
|
756
|
+
skipTrashed: false,
|
|
757
|
+
limit: 1000
|
|
758
|
+
}
|
|
759
|
+
)
|
|
760
|
+
})
|
|
761
|
+
})
|
|
388
762
|
})
|
|
389
763
|
|
|
390
764
|
const getPouchMock = () => {
|
|
@@ -405,6 +779,6 @@ const getPouchMock = () => {
|
|
|
405
779
|
const getReplicationOptionsMock = () => ({
|
|
406
780
|
strategy: 'fromRemote',
|
|
407
781
|
initialReplication: false,
|
|
408
|
-
warmupQueries:
|
|
782
|
+
warmupQueries: [],
|
|
409
783
|
doctype: 'io.cozy.files'
|
|
410
784
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-pouch-link",
|
|
3
|
-
"version": "60.
|
|
3
|
+
"version": "60.16.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "git+https://github.com/cozy/cozy-client.git"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"cozy-client": "^60.15.
|
|
16
|
+
"cozy-client": "^60.15.2",
|
|
17
17
|
"pouchdb-browser": "^7.2.2",
|
|
18
18
|
"pouchdb-find": "^7.2.2"
|
|
19
19
|
},
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"typecheck": "tsc -p tsconfig.json"
|
|
42
42
|
},
|
|
43
43
|
"sideEffects": false,
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "fef043f6cf4ee1bb86f73388a33a7afce8d66b38"
|
|
45
45
|
}
|
package/types/CozyPouchLink.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export function getReplicationURL(uri:
|
|
1
|
+
export function getReplicationURL(uri: string, token: any, doctype: string, replicationOptions?: {
|
|
2
|
+
driveId: string;
|
|
3
|
+
}): string;
|
|
2
4
|
export default PouchLink;
|
|
3
5
|
export type CozyPouchDocument = any;
|
|
4
6
|
export type ReplicationStatus = "idle" | "replicating";
|
|
@@ -96,7 +98,17 @@ declare class PouchLink extends CozyLink {
|
|
|
96
98
|
private startReplicationDebounced;
|
|
97
99
|
/** @type {import('cozy-client/src/performances/types').PerformanceAPI} */
|
|
98
100
|
performanceApi: any;
|
|
99
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Get the authenticated replication URL for a specific doctype
|
|
103
|
+
*
|
|
104
|
+
* @param {string} doctype - The document type to replicate (e.g., 'io.cozy.files')
|
|
105
|
+
* @param {object} [replicationOptions={}] - Replication options
|
|
106
|
+
* @param {string} [replicationOptions.driveId] - The ID of the shared drive to replicate (for shared drives)
|
|
107
|
+
* @returns {string} The authenticated replication URL
|
|
108
|
+
*/
|
|
109
|
+
getReplicationURL(doctype: string, replicationOptions?: {
|
|
110
|
+
driveId: string;
|
|
111
|
+
}): string;
|
|
100
112
|
registerClient(client: any): Promise<void>;
|
|
101
113
|
client: any;
|
|
102
114
|
/**
|
|
@@ -239,6 +251,26 @@ declare class PouchLink extends CozyLink {
|
|
|
239
251
|
addReferencesTo(mutation: any): Promise<void>;
|
|
240
252
|
dbMethod(method: any, mutation: any): Promise<any>;
|
|
241
253
|
syncImmediately(): Promise<void>;
|
|
254
|
+
/**
|
|
255
|
+
* Adds a new doctype to the list of managed doctypes, sets its replication options,
|
|
256
|
+
* adds it to the pouches, and starts replication.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} doctype - The name of the doctype to add.
|
|
259
|
+
* @param {Object} replicationOptions - The replication options for the doctype.
|
|
260
|
+
* @param {Object} options - The replication options for the doctype.
|
|
261
|
+
* @param {boolean} [options.shouldStartReplication=true] - Whether the replication should be started.
|
|
262
|
+
*/
|
|
263
|
+
addDoctype(doctype: string, replicationOptions: any, options: {
|
|
264
|
+
shouldStartReplication: boolean;
|
|
265
|
+
}): Promise<void>;
|
|
266
|
+
/**
|
|
267
|
+
* Removes a doctype from the list of managed doctypes, deletes its replication options,
|
|
268
|
+
* and removes it from the pouches.
|
|
269
|
+
*
|
|
270
|
+
* @param {string} doctype - The name of the doctype to remove.
|
|
271
|
+
*/
|
|
272
|
+
removeDoctype(doctype: string): Promise<void>;
|
|
273
|
+
getSharedDriveDoctypes(): string[];
|
|
242
274
|
}
|
|
243
275
|
import { CozyLink } from "cozy-client";
|
|
244
276
|
import { PouchLocalStorage } from "./localStorage";
|
package/types/PouchManager.d.ts
CHANGED
|
@@ -17,12 +17,12 @@ declare class PouchManager {
|
|
|
17
17
|
events: any;
|
|
18
18
|
dbQueryEngines: Map<any, any>;
|
|
19
19
|
init(): Promise<void>;
|
|
20
|
-
pouches:
|
|
20
|
+
pouches: {};
|
|
21
|
+
doctypesReplicationOptions: any;
|
|
21
22
|
/** @type {Record<string, import('./types').SyncInfo>} - Stores synchronization info per doctype */
|
|
22
23
|
syncedDoctypes: Record<string, import('./types').SyncInfo>;
|
|
23
24
|
warmedUpQueries: any;
|
|
24
25
|
getReplicationURL: any;
|
|
25
|
-
doctypesReplicationOptions: any;
|
|
26
26
|
listenerLaunched: boolean;
|
|
27
27
|
ensureDatabasesExistDone: boolean;
|
|
28
28
|
/**
|
|
@@ -94,6 +94,32 @@ declare class PouchManager {
|
|
|
94
94
|
checkToWarmupDoctype(doctype: any, replicationOptions: any): void;
|
|
95
95
|
areQueriesWarmedUp(doctype: any, queries: any): Promise<any>;
|
|
96
96
|
clearWarmedUpQueries(): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Adds a new doctype to the list of managed doctypes, sets its replication options,
|
|
99
|
+
* creates a new PouchDB instance for it, and sets up the query engine.
|
|
100
|
+
*
|
|
101
|
+
* @param {string} doctype - The name of the doctype to add.
|
|
102
|
+
* @param {Object} replicationOptions - The replication options for the doctype.
|
|
103
|
+
*/
|
|
104
|
+
addDoctype(doctype: string, replicationOptions: any): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Removes a doctype from the list of managed doctypes, deletes its replication options,
|
|
107
|
+
* destroys its PouchDB instance, and removes it from the pouches.
|
|
108
|
+
*
|
|
109
|
+
* @param {string} doctype - The name of the doctype to remove.
|
|
110
|
+
*/
|
|
111
|
+
removeDoctype(doctype: string): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Persists the names of the PouchDB databases.
|
|
114
|
+
*
|
|
115
|
+
* This method is primarily used to ensure that database names are saved for
|
|
116
|
+
* old browsers that do not support `indexeddb.databases()`. This persistence
|
|
117
|
+
* facilitates cleanup processes. Note that PouchDB automatically adds the
|
|
118
|
+
* `_pouch_` prefix to database names.
|
|
119
|
+
*
|
|
120
|
+
* @returns {Promise<void>}
|
|
121
|
+
*/
|
|
122
|
+
persistDatabasesNames(): Promise<void>;
|
|
97
123
|
}
|
|
98
124
|
import { PouchLocalStorage } from "./localStorage";
|
|
99
125
|
import Loop from "./loop";
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
export function startReplication(pouch: object, replicationOptions: {
|
|
2
2
|
strategy: string;
|
|
3
3
|
initialReplication: boolean;
|
|
4
|
+
driveId: string;
|
|
4
5
|
doctype: string;
|
|
5
6
|
warmupQueries: import('cozy-client/types/types').Query[];
|
|
6
|
-
}, getReplicationURL: Function, storage: import('./localStorage').PouchLocalStorage): import('./types').CancelablePromise;
|
|
7
|
+
}, getReplicationURL: Function, storage: import('./localStorage').PouchLocalStorage, client: CozyClient): import('./types').CancelablePromise;
|
|
7
8
|
export function replicateAllDocs({ db, baseUrl, doctype, storage }: {
|
|
8
9
|
db: object;
|
|
9
10
|
baseUrl: string;
|
|
10
11
|
doctype: string;
|
|
11
12
|
storage: import('./localStorage').PouchLocalStorage;
|
|
12
13
|
}): Promise<any[]>;
|
|
14
|
+
export function sharedDriveReplicateAllDocs({ driveId, pouch, storage, initialReplication, doctype, client }: {
|
|
15
|
+
driveId: string;
|
|
16
|
+
pouch: any;
|
|
17
|
+
storage: any;
|
|
18
|
+
doctype: string;
|
|
19
|
+
initialReplication: boolean;
|
|
20
|
+
client: CozyClient;
|
|
21
|
+
}): Promise<any[]>;
|
|
22
|
+
import CozyClient from "cozy-client";
|