@connecttomahdi/rxdb 17.0.0-beta.17 → 17.1.1
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/AGENTS.md +4 -0
- package/CHANGELOG.md +47 -4
- package/CLAUDE.md +2 -0
- package/dist/cjs/change-event-buffer.js +2 -1
- package/dist/cjs/change-event-buffer.js.map +1 -1
- package/dist/cjs/custom-index.js +85 -12
- package/dist/cjs/custom-index.js.map +1 -1
- package/dist/cjs/doc-cache.js +117 -35
- package/dist/cjs/doc-cache.js.map +1 -1
- package/dist/cjs/event-reduce.js +10 -1
- package/dist/cjs/event-reduce.js.map +1 -1
- package/dist/cjs/plugin-helpers.js +16 -0
- package/dist/cjs/plugin-helpers.js.map +1 -1
- package/dist/cjs/plugins/attachments/index.js +3 -3
- package/dist/cjs/plugins/attachments/index.js.map +1 -1
- package/dist/cjs/plugins/cleanup/cleanup.js +5 -3
- package/dist/cjs/plugins/cleanup/cleanup.js.map +1 -1
- package/dist/cjs/plugins/crdt/index.js +52 -0
- package/dist/cjs/plugins/crdt/index.js.map +1 -1
- package/dist/cjs/plugins/dev-mode/check-query.js +7 -1
- package/dist/cjs/plugins/dev-mode/check-query.js.map +1 -1
- package/dist/cjs/plugins/dev-mode/check-schema.js +2 -1
- package/dist/cjs/plugins/dev-mode/check-schema.js.map +1 -1
- package/dist/cjs/plugins/dev-mode/error-messages.js +43 -5
- package/dist/cjs/plugins/dev-mode/error-messages.js.map +1 -1
- package/dist/cjs/plugins/encryption-crypto-js/index.js +22 -6
- package/dist/cjs/plugins/encryption-crypto-js/index.js.map +1 -1
- package/dist/cjs/plugins/leader-election/index.js +5 -5
- package/dist/cjs/plugins/leader-election/index.js.map +1 -1
- package/dist/cjs/plugins/local-documents/local-documents.js +20 -13
- package/dist/cjs/plugins/local-documents/local-documents.js.map +1 -1
- package/dist/cjs/plugins/migration-schema/migration-helpers.js +3 -0
- package/dist/cjs/plugins/migration-schema/migration-helpers.js.map +1 -1
- package/dist/cjs/plugins/migration-schema/rx-migration-state.js +1 -1
- package/dist/cjs/plugins/migration-schema/rx-migration-state.js.map +1 -1
- package/dist/cjs/plugins/pipeline/rx-pipeline.js +5 -1
- package/dist/cjs/plugins/pipeline/rx-pipeline.js.map +1 -1
- package/dist/cjs/plugins/query-builder/mquery/nosql-query-builder.js +4 -2
- package/dist/cjs/plugins/query-builder/mquery/nosql-query-builder.js.map +1 -1
- package/dist/cjs/plugins/replication/index.js +40 -2
- package/dist/cjs/plugins/replication/index.js.map +1 -1
- package/dist/cjs/plugins/replication-google-drive/document-handling.js +17 -6
- package/dist/cjs/plugins/replication-google-drive/document-handling.js.map +1 -1
- package/dist/cjs/plugins/replication-google-drive/google-drive-helper.js +1 -1
- package/dist/cjs/plugins/replication-google-drive/google-drive-helper.js.map +1 -1
- package/dist/cjs/plugins/replication-google-drive/google-drive-types.js.map +1 -1
- package/dist/cjs/plugins/replication-google-drive/signaling.js +4 -1
- package/dist/cjs/plugins/replication-google-drive/signaling.js.map +1 -1
- package/dist/cjs/plugins/replication-google-drive/upstream.js +7 -4
- package/dist/cjs/plugins/replication-google-drive/upstream.js.map +1 -1
- package/dist/cjs/plugins/replication-microsoft-onedrive/signaling.js +4 -1
- package/dist/cjs/plugins/replication-microsoft-onedrive/signaling.js.map +1 -1
- package/dist/cjs/plugins/state/rx-state.js +14 -3
- package/dist/cjs/plugins/state/rx-state.js.map +1 -1
- package/dist/cjs/plugins/storage-dexie/rx-storage-instance-dexie.js +0 -7
- package/dist/cjs/plugins/storage-dexie/rx-storage-instance-dexie.js.map +1 -1
- package/dist/cjs/plugins/storage-memory/binary-search-bounds.js +112 -40
- package/dist/cjs/plugins/storage-memory/binary-search-bounds.js.map +1 -1
- package/dist/cjs/plugins/storage-memory/memory-helper.js +127 -40
- package/dist/cjs/plugins/storage-memory/memory-helper.js.map +1 -1
- package/dist/cjs/plugins/storage-memory/memory-indexes.js +1 -0
- package/dist/cjs/plugins/storage-memory/memory-indexes.js.map +1 -1
- package/dist/cjs/plugins/storage-memory/memory-types.js.map +1 -1
- package/dist/cjs/plugins/storage-memory/rx-storage-instance-memory.js +97 -37
- package/dist/cjs/plugins/storage-memory/rx-storage-instance-memory.js.map +1 -1
- package/dist/cjs/plugins/storage-mongodb/mongodb-helper.js +42 -1
- package/dist/cjs/plugins/storage-mongodb/mongodb-helper.js.map +1 -1
- package/dist/cjs/plugins/storage-mongodb/rx-storage-instance-mongodb.js +7 -7
- package/dist/cjs/plugins/storage-mongodb/rx-storage-instance-mongodb.js.map +1 -1
- package/dist/cjs/plugins/test-utils/config.js +1 -1
- package/dist/cjs/plugins/test-utils/config.js.map +1 -1
- package/dist/cjs/plugins/test-utils/performance.js +122 -92
- package/dist/cjs/plugins/test-utils/performance.js.map +1 -1
- package/dist/cjs/plugins/test-utils/schema-objects.js +1 -1
- package/dist/cjs/plugins/test-utils/schema-objects.js.map +1 -1
- package/dist/cjs/plugins/test-utils/test-util.js +62 -0
- package/dist/cjs/plugins/test-utils/test-util.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-map.js +2 -2
- package/dist/cjs/plugins/utils/utils-map.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-object-deep-equal.js +3 -2
- package/dist/cjs/plugins/utils/utils-object-deep-equal.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-object-dot-prop.js +25 -0
- package/dist/cjs/plugins/utils/utils-object-dot-prop.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-object.js +102 -27
- package/dist/cjs/plugins/utils/utils-object.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-other.js +9 -4
- package/dist/cjs/plugins/utils/utils-other.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-premium.js +5 -23
- package/dist/cjs/plugins/utils/utils-premium.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-revision.js +20 -10
- package/dist/cjs/plugins/utils/utils-revision.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-rxdb-version.js +1 -1
- package/dist/cjs/plugins/utils/utils-rxdb-version.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-string.js +11 -8
- package/dist/cjs/plugins/utils/utils-string.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-time.js +21 -16
- package/dist/cjs/plugins/utils/utils-time.js.map +1 -1
- package/dist/cjs/query-cache.js +6 -4
- package/dist/cjs/query-cache.js.map +1 -1
- package/dist/cjs/query-planner.js +2 -2
- package/dist/cjs/query-planner.js.map +1 -1
- package/dist/cjs/replication-protocol/downstream.js +1 -1
- package/dist/cjs/replication-protocol/downstream.js.map +1 -1
- package/dist/cjs/rx-collection-helper.js +11 -6
- package/dist/cjs/rx-collection-helper.js.map +1 -1
- package/dist/cjs/rx-collection.js +34 -6
- package/dist/cjs/rx-collection.js.map +1 -1
- package/dist/cjs/rx-database.js +40 -7
- package/dist/cjs/rx-database.js.map +1 -1
- package/dist/cjs/rx-document.js +10 -3
- package/dist/cjs/rx-document.js.map +1 -1
- package/dist/cjs/rx-query-helper.js +35 -12
- package/dist/cjs/rx-query-helper.js.map +1 -1
- package/dist/cjs/rx-query-single-result.js +9 -2
- package/dist/cjs/rx-query-single-result.js.map +1 -1
- package/dist/cjs/rx-query.js +72 -29
- package/dist/cjs/rx-query.js.map +1 -1
- package/dist/cjs/rx-schema-helper.js +9 -3
- package/dist/cjs/rx-schema-helper.js.map +1 -1
- package/dist/cjs/rx-schema.js +1 -0
- package/dist/cjs/rx-schema.js.map +1 -1
- package/dist/cjs/rx-storage-helper.js +212 -129
- package/dist/cjs/rx-storage-helper.js.map +1 -1
- package/dist/cjs/types/rx-error.d.js.map +1 -1
- package/dist/cjs/types/rx-schema.d.js.map +1 -1
- package/dist/esm/change-event-buffer.js +2 -1
- package/dist/esm/change-event-buffer.js.map +1 -1
- package/dist/esm/custom-index.js +85 -12
- package/dist/esm/custom-index.js.map +1 -1
- package/dist/esm/doc-cache.js +118 -36
- package/dist/esm/doc-cache.js.map +1 -1
- package/dist/esm/event-reduce.js +10 -1
- package/dist/esm/event-reduce.js.map +1 -1
- package/dist/esm/plugin-helpers.js +16 -0
- package/dist/esm/plugin-helpers.js.map +1 -1
- package/dist/esm/plugins/attachments/index.js +3 -3
- package/dist/esm/plugins/attachments/index.js.map +1 -1
- package/dist/esm/plugins/cleanup/cleanup.js +5 -3
- package/dist/esm/plugins/cleanup/cleanup.js.map +1 -1
- package/dist/esm/plugins/crdt/index.js +52 -0
- package/dist/esm/plugins/crdt/index.js.map +1 -1
- package/dist/esm/plugins/dev-mode/check-query.js +7 -1
- package/dist/esm/plugins/dev-mode/check-query.js.map +1 -1
- package/dist/esm/plugins/dev-mode/check-schema.js +2 -1
- package/dist/esm/plugins/dev-mode/check-schema.js.map +1 -1
- package/dist/esm/plugins/dev-mode/error-messages.js +43 -5
- package/dist/esm/plugins/dev-mode/error-messages.js.map +1 -1
- package/dist/esm/plugins/encryption-crypto-js/index.js +22 -6
- package/dist/esm/plugins/encryption-crypto-js/index.js.map +1 -1
- package/dist/esm/plugins/leader-election/index.js +4 -4
- package/dist/esm/plugins/leader-election/index.js.map +1 -1
- package/dist/esm/plugins/local-documents/local-documents.js +20 -13
- package/dist/esm/plugins/local-documents/local-documents.js.map +1 -1
- package/dist/esm/plugins/migration-schema/migration-helpers.js +3 -0
- package/dist/esm/plugins/migration-schema/migration-helpers.js.map +1 -1
- package/dist/esm/plugins/migration-schema/rx-migration-state.js +1 -1
- package/dist/esm/plugins/migration-schema/rx-migration-state.js.map +1 -1
- package/dist/esm/plugins/pipeline/rx-pipeline.js +5 -1
- package/dist/esm/plugins/pipeline/rx-pipeline.js.map +1 -1
- package/dist/esm/plugins/query-builder/mquery/nosql-query-builder.js +4 -2
- package/dist/esm/plugins/query-builder/mquery/nosql-query-builder.js.map +1 -1
- package/dist/esm/plugins/replication/index.js +40 -2
- package/dist/esm/plugins/replication/index.js.map +1 -1
- package/dist/esm/plugins/replication-google-drive/document-handling.js +17 -6
- package/dist/esm/plugins/replication-google-drive/document-handling.js.map +1 -1
- package/dist/esm/plugins/replication-google-drive/google-drive-helper.js +1 -1
- package/dist/esm/plugins/replication-google-drive/google-drive-helper.js.map +1 -1
- package/dist/esm/plugins/replication-google-drive/google-drive-types.js.map +1 -1
- package/dist/esm/plugins/replication-google-drive/signaling.js +4 -1
- package/dist/esm/plugins/replication-google-drive/signaling.js.map +1 -1
- package/dist/esm/plugins/replication-google-drive/upstream.js +7 -4
- package/dist/esm/plugins/replication-google-drive/upstream.js.map +1 -1
- package/dist/esm/plugins/replication-microsoft-onedrive/signaling.js +4 -1
- package/dist/esm/plugins/replication-microsoft-onedrive/signaling.js.map +1 -1
- package/dist/esm/plugins/state/rx-state.js +15 -4
- package/dist/esm/plugins/state/rx-state.js.map +1 -1
- package/dist/esm/plugins/storage-dexie/rx-storage-instance-dexie.js +1 -8
- package/dist/esm/plugins/storage-dexie/rx-storage-instance-dexie.js.map +1 -1
- package/dist/esm/plugins/storage-memory/binary-search-bounds.js +107 -40
- package/dist/esm/plugins/storage-memory/binary-search-bounds.js.map +1 -1
- package/dist/esm/plugins/storage-memory/memory-helper.js +128 -41
- package/dist/esm/plugins/storage-memory/memory-helper.js.map +1 -1
- package/dist/esm/plugins/storage-memory/memory-indexes.js +1 -0
- package/dist/esm/plugins/storage-memory/memory-indexes.js.map +1 -1
- package/dist/esm/plugins/storage-memory/memory-types.js.map +1 -1
- package/dist/esm/plugins/storage-memory/rx-storage-instance-memory.js +90 -30
- package/dist/esm/plugins/storage-memory/rx-storage-instance-memory.js.map +1 -1
- package/dist/esm/plugins/storage-mongodb/mongodb-helper.js +39 -0
- package/dist/esm/plugins/storage-mongodb/mongodb-helper.js.map +1 -1
- package/dist/esm/plugins/storage-mongodb/rx-storage-instance-mongodb.js +8 -8
- package/dist/esm/plugins/storage-mongodb/rx-storage-instance-mongodb.js.map +1 -1
- package/dist/esm/plugins/test-utils/config.js +1 -1
- package/dist/esm/plugins/test-utils/config.js.map +1 -1
- package/dist/esm/plugins/test-utils/performance.js +122 -92
- package/dist/esm/plugins/test-utils/performance.js.map +1 -1
- package/dist/esm/plugins/test-utils/schema-objects.js +1 -1
- package/dist/esm/plugins/test-utils/schema-objects.js.map +1 -1
- package/dist/esm/plugins/test-utils/test-util.js +59 -0
- package/dist/esm/plugins/test-utils/test-util.js.map +1 -1
- package/dist/esm/plugins/utils/utils-map.js +2 -2
- package/dist/esm/plugins/utils/utils-map.js.map +1 -1
- package/dist/esm/plugins/utils/utils-object-deep-equal.js +3 -2
- package/dist/esm/plugins/utils/utils-object-deep-equal.js.map +1 -1
- package/dist/esm/plugins/utils/utils-object-dot-prop.js +25 -0
- package/dist/esm/plugins/utils/utils-object-dot-prop.js.map +1 -1
- package/dist/esm/plugins/utils/utils-object.js +102 -27
- package/dist/esm/plugins/utils/utils-object.js.map +1 -1
- package/dist/esm/plugins/utils/utils-other.js +9 -4
- package/dist/esm/plugins/utils/utils-other.js.map +1 -1
- package/dist/esm/plugins/utils/utils-premium.js +5 -23
- package/dist/esm/plugins/utils/utils-premium.js.map +1 -1
- package/dist/esm/plugins/utils/utils-revision.js +20 -10
- package/dist/esm/plugins/utils/utils-revision.js.map +1 -1
- package/dist/esm/plugins/utils/utils-rxdb-version.js +1 -1
- package/dist/esm/plugins/utils/utils-rxdb-version.js.map +1 -1
- package/dist/esm/plugins/utils/utils-string.js +11 -8
- package/dist/esm/plugins/utils/utils-string.js.map +1 -1
- package/dist/esm/plugins/utils/utils-time.js +21 -16
- package/dist/esm/plugins/utils/utils-time.js.map +1 -1
- package/dist/esm/query-cache.js +7 -5
- package/dist/esm/query-cache.js.map +1 -1
- package/dist/esm/query-planner.js +2 -2
- package/dist/esm/query-planner.js.map +1 -1
- package/dist/esm/replication-protocol/downstream.js +1 -1
- package/dist/esm/replication-protocol/downstream.js.map +1 -1
- package/dist/esm/rx-collection-helper.js +12 -7
- package/dist/esm/rx-collection-helper.js.map +1 -1
- package/dist/esm/rx-collection.js +35 -7
- package/dist/esm/rx-collection.js.map +1 -1
- package/dist/esm/rx-database.js +40 -7
- package/dist/esm/rx-database.js.map +1 -1
- package/dist/esm/rx-document.js +11 -4
- package/dist/esm/rx-document.js.map +1 -1
- package/dist/esm/rx-query-helper.js +35 -12
- package/dist/esm/rx-query-helper.js.map +1 -1
- package/dist/esm/rx-query-single-result.js +10 -3
- package/dist/esm/rx-query-single-result.js.map +1 -1
- package/dist/esm/rx-query.js +72 -29
- package/dist/esm/rx-query.js.map +1 -1
- package/dist/esm/rx-schema-helper.js +9 -3
- package/dist/esm/rx-schema-helper.js.map +1 -1
- package/dist/esm/rx-schema.js +1 -0
- package/dist/esm/rx-schema.js.map +1 -1
- package/dist/esm/rx-storage-helper.js +176 -94
- package/dist/esm/rx-storage-helper.js.map +1 -1
- package/dist/esm/types/rx-error.d.js.map +1 -1
- package/dist/esm/types/rx-schema.d.js.map +1 -1
- package/dist/types/custom-index.d.ts +5 -0
- package/dist/types/doc-cache.d.ts +1 -1
- package/dist/types/plugins/dev-mode/error-messages.d.ts +36 -0
- package/dist/types/plugins/leader-election/index.d.ts +1 -0
- package/dist/types/plugins/replication-google-drive/document-handling.d.ts +4 -1
- package/dist/types/plugins/replication-google-drive/google-drive-types.d.ts +1 -0
- package/dist/types/plugins/state/rx-state.d.ts +1 -1
- package/dist/types/plugins/storage-denokv/index.d.ts +1 -1
- package/dist/types/plugins/storage-dexie/rx-storage-dexie.d.ts +1 -1
- package/dist/types/plugins/storage-localstorage/index.d.ts +1 -1
- package/dist/types/plugins/storage-memory/binary-search-bounds.d.ts +21 -10
- package/dist/types/plugins/storage-memory/memory-helper.d.ts +7 -3
- package/dist/types/plugins/storage-memory/memory-types.d.ts +5 -0
- package/dist/types/plugins/storage-mongodb/mongodb-helper.d.ts +9 -1
- package/dist/types/plugins/storage-mongodb/rx-storage-instance-mongodb.d.ts +2 -2
- package/dist/types/plugins/storage-mongodb/rx-storage-mongodb.d.ts +1 -1
- package/dist/types/plugins/storage-remote/rx-storage-remote.d.ts +1 -1
- package/dist/types/plugins/storage-sqlite/index.d.ts +1 -1
- package/dist/types/plugins/test-utils/performance.d.ts +36 -0
- package/dist/types/plugins/test-utils/test-util.d.ts +17 -0
- package/dist/types/plugins/utils/utils-object.d.ts +8 -3
- package/dist/types/plugins/utils/utils-premium.d.ts +0 -2
- package/dist/types/plugins/utils/utils-rxdb-version.d.ts +1 -1
- package/dist/types/rx-database.d.ts +1 -1
- package/dist/types/rx-query-single-result.d.ts +1 -1
- package/dist/types/rx-query.d.ts +3 -2
- package/dist/types/rx-storage-helper.d.ts +15 -0
- package/dist/types/types/rx-error.d.ts +3 -0
- package/dist/types/types/rx-schema.d.ts +5 -0
- package/eslint.config.mjs +2 -1
- package/package.json +38 -35
- package/scripts/check-code-block-line-length.js +91 -0
- package/scripts/check-em-dashes.js +53 -0
- package/scripts/copy-path.mjs +20 -0
- package/scripts/docs-fetch-git-history.mjs +36 -0
- package/scripts/fix-types.mjs +15 -8
- package/scripts/install-foundationdb.sh +0 -6
- package/scripts/notify-indexnow.mjs +171 -0
- package/scripts/start-foundationdb-docker.sh +73 -0
- package/src/change-event-buffer.ts +4 -1
- package/src/custom-index.ts +93 -16
- package/src/doc-cache.ts +117 -41
- package/src/event-reduce.ts +10 -1
- package/src/plugin-helpers.ts +10 -0
- package/src/plugins/attachments/index.ts +10 -12
- package/src/plugins/cleanup/cleanup.ts +5 -3
- package/src/plugins/crdt/index.ts +55 -0
- package/src/plugins/dev-mode/check-query.ts +7 -1
- package/src/plugins/dev-mode/check-schema.ts +2 -1
- package/src/plugins/dev-mode/error-messages.ts +45 -5
- package/src/plugins/encryption-crypto-js/index.ts +18 -6
- package/src/plugins/leader-election/index.ts +9 -8
- package/src/plugins/local-documents/local-documents.ts +21 -12
- package/src/plugins/migration-schema/migration-helpers.ts +3 -0
- package/src/plugins/migration-schema/rx-migration-state.ts +1 -1
- package/src/plugins/pipeline/rx-pipeline.ts +5 -1
- package/src/plugins/query-builder/mquery/nosql-query-builder.ts +8 -2
- package/src/plugins/replication/index.ts +41 -3
- package/src/plugins/replication-google-drive/document-handling.ts +17 -5
- package/src/plugins/replication-google-drive/google-drive-helper.ts +1 -1
- package/src/plugins/replication-google-drive/google-drive-types.ts +1 -0
- package/src/plugins/replication-google-drive/signaling.ts +4 -1
- package/src/plugins/replication-google-drive/upstream.ts +7 -4
- package/src/plugins/replication-microsoft-onedrive/signaling.ts +4 -1
- package/src/plugins/state/rx-state.ts +17 -5
- package/src/plugins/storage-dexie/rx-storage-instance-dexie.ts +0 -27
- package/src/plugins/storage-memory/binary-search-bounds.ts +105 -40
- package/src/plugins/storage-memory/memory-helper.ts +158 -67
- package/src/plugins/storage-memory/memory-indexes.ts +1 -0
- package/src/plugins/storage-memory/memory-types.ts +5 -0
- package/src/plugins/storage-memory/rx-storage-instance-memory.ts +104 -53
- package/src/plugins/storage-mongodb/mongodb-helper.ts +43 -1
- package/src/plugins/storage-mongodb/rx-storage-instance-mongodb.ts +11 -9
- package/src/plugins/test-utils/config.ts +2 -1
- package/src/plugins/test-utils/performance.ts +159 -85
- package/src/plugins/test-utils/schema-objects.ts +1 -1
- package/src/plugins/test-utils/test-util.ts +71 -0
- package/src/plugins/utils/utils-map.ts +2 -2
- package/src/plugins/utils/utils-object-deep-equal.ts +2 -4
- package/src/plugins/utils/utils-object-dot-prop.ts +25 -0
- package/src/plugins/utils/utils-object.ts +103 -28
- package/src/plugins/utils/utils-other.ts +9 -4
- package/src/plugins/utils/utils-premium.ts +11 -37
- package/src/plugins/utils/utils-revision.ts +20 -9
- package/src/plugins/utils/utils-rxdb-version.ts +1 -1
- package/src/plugins/utils/utils-string.ts +11 -9
- package/src/plugins/utils/utils-time.ts +21 -17
- package/src/query-cache.ts +6 -5
- package/src/query-planner.ts +2 -2
- package/src/replication-protocol/downstream.ts +1 -1
- package/src/rx-collection-helper.ts +12 -6
- package/src/rx-collection.ts +39 -8
- package/src/rx-database.ts +49 -17
- package/src/rx-document.ts +12 -3
- package/src/rx-query-helper.ts +36 -15
- package/src/rx-query-single-result.ts +10 -3
- package/src/rx-query.ts +48 -8
- package/src/rx-schema-helper.ts +7 -4
- package/src/rx-schema.ts +1 -0
- package/src/rx-storage-helper.ts +210 -139
- package/src/types/rx-error.d.ts +3 -0
- package/src/types/rx-schema.d.ts +5 -0
|
@@ -23,7 +23,7 @@ async function getDocumentFiles(googleDriveOptions, init, docIds) {
|
|
|
23
23
|
var params = new URLSearchParams({
|
|
24
24
|
q,
|
|
25
25
|
pageSize: MAX_DRIVE_PAGE_SIZE + '',
|
|
26
|
-
fields: "nextPageToken, files(id,name,mimeType,parents,modifiedTime,size)",
|
|
26
|
+
fields: "nextPageToken, files(id,name,mimeType,parents,modifiedTime,size,etag)",
|
|
27
27
|
// Shared drives support (safe to include always)
|
|
28
28
|
includeItemsFromAllDrives: "true",
|
|
29
29
|
supportsAllDrives: "true"
|
|
@@ -71,23 +71,34 @@ async function insertDocumentFiles(googleDriveOptions, init, primaryPath, docs)
|
|
|
71
71
|
await (0, _googleDriveHelper.insertMultipartFile)(googleDriveOptions, init.docsFolderId, id + '.json', doc);
|
|
72
72
|
}));
|
|
73
73
|
}
|
|
74
|
-
async function updateDocumentFiles(googleDriveOptions, primaryPath, docs,
|
|
74
|
+
async function updateDocumentFiles(googleDriveOptions, primaryPath, docs, fileMetaByDocId, concurrency = 5) {
|
|
75
75
|
var queue = docs.slice(0);
|
|
76
76
|
var results = {};
|
|
77
77
|
async function worker() {
|
|
78
78
|
while (queue.length) {
|
|
79
79
|
var doc = queue.shift();
|
|
80
80
|
var docId = doc[primaryPath];
|
|
81
|
-
var
|
|
82
|
-
var
|
|
81
|
+
var meta = (0, _index.ensureNotFalsy)(fileMetaByDocId[docId]);
|
|
82
|
+
var fileId = meta.fileId;
|
|
83
|
+
var etag = meta.etag;
|
|
84
|
+
var url = googleDriveOptions.apiEndpoint + ("/upload/drive/v2/files/" + encodeURIComponent(fileId)) + "?uploadType=media&supportsAllDrives=true&fields=id";
|
|
83
85
|
var res = await fetch(url, {
|
|
84
|
-
method: "
|
|
86
|
+
method: "PUT",
|
|
85
87
|
headers: {
|
|
86
88
|
Authorization: "Bearer " + googleDriveOptions.authToken,
|
|
87
|
-
"Content-Type": "application/json; charset=UTF-8"
|
|
89
|
+
"Content-Type": "application/json; charset=UTF-8",
|
|
90
|
+
"If-Match": etag
|
|
88
91
|
},
|
|
89
92
|
body: JSON.stringify(doc)
|
|
90
93
|
});
|
|
94
|
+
if (res.status === 412) {
|
|
95
|
+
throw (0, _rxError.newRxError)('GDR20', {
|
|
96
|
+
args: {
|
|
97
|
+
docId,
|
|
98
|
+
fileId
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
91
102
|
if (!res.ok) {
|
|
92
103
|
throw await (0, _rxError.newRxFetchError)(res, {
|
|
93
104
|
args: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-handling.js","names":["_rxError","require","_index","_googleDriveHelper","MAX_DRIVE_PAGE_SIZE","getDocumentFiles","googleDriveOptions","init","docIds","fileNames","map","id","q","name","replace","join","docsFolderId","length","newRxError","params","URLSearchParams","pageSize","fields","includeItemsFromAllDrives","supportsAllDrives","url","apiEndpoint","toString","res","fetch","method","headers","Authorization","authToken","ok","newRxFetchError","ids","data","json","batchGetFilesMetadata","fileIds","boundary","Math","random","slice","parts","i","encodeURIComponent","batchBody","body","text","insertDocumentFiles","primaryPath","docs","Promise","all","doc","insertMultipartFile","updateDocumentFiles","fileIdByDocId","concurrency","queue","results","worker","shift","docId","fileId","ensureNotFalsy","JSON","stringify","args","Array","from","fetchDocumentContents","byId","ordered","nextIndex","sleep","ms","r","setTimeout","fetchOne","attempt","includes","status","backoffMs","pow","floor","parse","undefined"],"sources":["../../../../src/plugins/replication-google-drive/document-handling.ts"],"sourcesContent":["import { newRxError, newRxFetchError } from '../../rx-error.ts';\r\nimport { ById } from '../../types/util';\r\nimport { ensureNotFalsy } from '../utils/index.ts';\r\nimport { insertMultipartFile } from './google-drive-helper.ts';\r\nimport type {\r\n DriveFileListResponse,\r\n GoogleDriveOptionsWithDefaults\r\n} from './google-drive-types.ts';\r\nimport { DriveStructure } from './init.ts';\r\n\r\nconst MAX_DRIVE_PAGE_SIZE = 1000;\r\n\r\n\r\n\r\nexport async function getDocumentFiles(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n docIds: string[]\r\n): Promise<DriveFileListResponse> {\r\n const fileNames = docIds.map(id => id + '.json');\r\n let q = fileNames\r\n .map(name => `name = '${name.replace(\"'\", \"\\\\'\")}'`)\r\n .join(' or ');\r\n q = '(' + q + ') and trashed = false';\r\n q += ' and \\'' + init.docsFolderId + '\\' in parents';\r\n if (docIds.length >= MAX_DRIVE_PAGE_SIZE) {\r\n throw newRxError('SNH');\r\n }\r\n const params = new URLSearchParams({\r\n q,\r\n pageSize: MAX_DRIVE_PAGE_SIZE + '',\r\n fields: \"nextPageToken, files(id,name,mimeType,parents,modifiedTime,size)\",\r\n // Shared drives support (safe to include always)\r\n includeItemsFromAllDrives: \"true\",\r\n supportsAllDrives: \"true\",\r\n });\r\n const url = googleDriveOptions.apiEndpoint + '/drive/v3/files?' + params.toString();\r\n const res = await fetch(url, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n ids: docIds,\r\n });\r\n }\r\n\r\n const data = await res.json();\r\n return data;\r\n}\r\n\r\nexport async function batchGetFilesMetadata(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileIds: string[]\r\n) {\r\n const boundary = \"batch_\" + Math.random().toString(16).slice(2);\r\n\r\n const parts = fileIds.map((id, i) => {\r\n return (\r\n `--${boundary}\\r\\n` +\r\n `Content-Type: application/http\\r\\n` +\r\n `Content-ID: <item-${i}>\\r\\n\\r\\n` +\r\n `GET /drive/v3/files/${encodeURIComponent(id)}?` +\r\n `fields=id,name,mimeType,parents,modifiedTime,size&supportsAllDrives=true HTTP/1.1\\r\\n\\r\\n`\r\n );\r\n });\r\n\r\n const batchBody = parts.join(\"\") + `--${boundary}--`;\r\n\r\n const res = await fetch(googleDriveOptions.apiEndpoint + \"/batch/drive/v3\", {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n \"Content-Type\": `multipart/mixed; boundary=${boundary}`,\r\n },\r\n body: batchBody,\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res);\r\n }\r\n\r\n // multipart/mixed; you can parse it, or just return raw.\r\n return await res.text();\r\n}\r\n\r\nexport async function insertDocumentFiles<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n primaryPath: keyof RxDocType,\r\n docs: RxDocType[]\r\n) {\r\n // Run uploads in parallel\r\n await Promise.all(docs.map(async (doc) => {\r\n const id = (doc as any)[primaryPath];\r\n await insertMultipartFile(\r\n googleDriveOptions,\r\n init.docsFolderId,\r\n id + '.json',\r\n doc\r\n );\r\n }));\r\n}\r\n\r\nexport async function updateDocumentFiles<DocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n primaryPath: keyof DocType,\r\n docs: DocType[],\r\n fileIdByDocId: Record<string, string>,\r\n concurrency = 5\r\n) {\r\n const queue = docs.slice(0);\r\n const results: Record<string, { id: string }> = {};\r\n\r\n async function worker() {\r\n while (queue.length) {\r\n const doc = queue.shift()!;\r\n const docId = (doc as any)[primaryPath] as string;\r\n const fileId = ensureNotFalsy(fileIdByDocId[docId]);\r\n\r\n const url =\r\n googleDriveOptions.apiEndpoint +\r\n `/upload/drive/v3/files/${encodeURIComponent(fileId)}` +\r\n `?uploadType=media&supportsAllDrives=true&fields=id`;\r\n\r\n const res = await fetch(url, {\r\n method: \"PATCH\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n \"Content-Type\": \"application/json; charset=UTF-8\",\r\n },\r\n body: JSON.stringify(doc),\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n args: {\r\n docId,\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n results[docId] = await res.json(); // { id }\r\n }\r\n }\r\n\r\n await Promise.all(Array.from({ length: concurrency }, () => worker()));\r\n return results;\r\n}\r\n\r\n\r\nexport async function fetchDocumentContents<DocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileIds: string[],\r\n concurrency = 5\r\n): Promise<{ byId: ById<DocType>; ordered: (DocType)[] }> {\r\n const byId: ById<DocType> = {};\r\n const ordered = new Array<DocType>(fileIds.length);\r\n let nextIndex = 0;\r\n\r\n const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\r\n\r\n async function fetchOne(fileId: string, attempt = 0): Promise<DocType | undefined> {\r\n const url =\r\n googleDriveOptions.apiEndpoint +\r\n `/drive/v3/files/${encodeURIComponent(fileId)}?alt=media&supportsAllDrives=true`;\r\n\r\n const res = await fetch(url, {\r\n headers: { Authorization: `Bearer ${googleDriveOptions.authToken}` },\r\n });\r\n\r\n if ([429, 500, 502, 503, 504].includes(res.status) && attempt < 4) {\r\n const backoffMs = 250 * Math.pow(2, attempt) + Math.floor(Math.random() * 200);\r\n await sleep(backoffMs);\r\n return fetchOne(fileId, attempt + 1);\r\n }\r\n\r\n if (!res.ok) throw await newRxFetchError(res, { args: { fileId } });\r\n\r\n const text = await res.text();\r\n return text ? (JSON.parse(text) as DocType) : undefined;\r\n }\r\n\r\n async function worker() {\r\n while (true) {\r\n const i = nextIndex++;\r\n if (i >= fileIds.length) return;\r\n\r\n const fileId = fileIds[i];\r\n const doc = await fetchOne(fileId);\r\n\r\n ordered[i] = ensureNotFalsy(doc);\r\n byId[fileId] = doc as any; // if ById allows undefined, remove `as any`\r\n }\r\n }\r\n\r\n await Promise.all(Array.from({ length: concurrency }, () => worker()));\r\n return { byId, ordered };\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"document-handling.js","names":["_rxError","require","_index","_googleDriveHelper","MAX_DRIVE_PAGE_SIZE","getDocumentFiles","googleDriveOptions","init","docIds","fileNames","map","id","q","name","replace","join","docsFolderId","length","newRxError","params","URLSearchParams","pageSize","fields","includeItemsFromAllDrives","supportsAllDrives","url","apiEndpoint","toString","res","fetch","method","headers","Authorization","authToken","ok","newRxFetchError","ids","data","json","batchGetFilesMetadata","fileIds","boundary","Math","random","slice","parts","i","encodeURIComponent","batchBody","body","text","insertDocumentFiles","primaryPath","docs","Promise","all","doc","insertMultipartFile","updateDocumentFiles","fileMetaByDocId","concurrency","queue","results","worker","shift","docId","meta","ensureNotFalsy","fileId","etag","JSON","stringify","status","args","Array","from","fetchDocumentContents","byId","ordered","nextIndex","sleep","ms","r","setTimeout","fetchOne","attempt","includes","backoffMs","pow","floor","parse","undefined"],"sources":["../../../../src/plugins/replication-google-drive/document-handling.ts"],"sourcesContent":["import { newRxError, newRxFetchError } from '../../rx-error.ts';\r\nimport { ById } from '../../types/util';\r\nimport { ensureNotFalsy } from '../utils/index.ts';\r\nimport { insertMultipartFile } from './google-drive-helper.ts';\r\nimport type {\r\n DriveFileListResponse,\r\n GoogleDriveOptionsWithDefaults\r\n} from './google-drive-types.ts';\r\nimport { DriveStructure } from './init.ts';\r\n\r\nconst MAX_DRIVE_PAGE_SIZE = 1000;\r\n\r\n\r\n\r\nexport async function getDocumentFiles(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n docIds: string[]\r\n): Promise<DriveFileListResponse> {\r\n const fileNames = docIds.map(id => id + '.json');\r\n let q = fileNames\r\n .map(name => `name = '${name.replace(\"'\", \"\\\\'\")}'`)\r\n .join(' or ');\r\n q = '(' + q + ') and trashed = false';\r\n q += ' and \\'' + init.docsFolderId + '\\' in parents';\r\n if (docIds.length >= MAX_DRIVE_PAGE_SIZE) {\r\n throw newRxError('SNH');\r\n }\r\n const params = new URLSearchParams({\r\n q,\r\n pageSize: MAX_DRIVE_PAGE_SIZE + '',\r\n fields: \"nextPageToken, files(id,name,mimeType,parents,modifiedTime,size,etag)\",\r\n // Shared drives support (safe to include always)\r\n includeItemsFromAllDrives: \"true\",\r\n supportsAllDrives: \"true\",\r\n });\r\n const url = googleDriveOptions.apiEndpoint + '/drive/v3/files?' + params.toString();\r\n const res = await fetch(url, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n ids: docIds,\r\n });\r\n }\r\n\r\n const data = await res.json();\r\n return data;\r\n}\r\n\r\nexport async function batchGetFilesMetadata(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileIds: string[]\r\n) {\r\n const boundary = \"batch_\" + Math.random().toString(16).slice(2);\r\n\r\n const parts = fileIds.map((id, i) => {\r\n return (\r\n `--${boundary}\\r\\n` +\r\n `Content-Type: application/http\\r\\n` +\r\n `Content-ID: <item-${i}>\\r\\n\\r\\n` +\r\n `GET /drive/v3/files/${encodeURIComponent(id)}?` +\r\n `fields=id,name,mimeType,parents,modifiedTime,size&supportsAllDrives=true HTTP/1.1\\r\\n\\r\\n`\r\n );\r\n });\r\n\r\n const batchBody = parts.join(\"\") + `--${boundary}--`;\r\n\r\n const res = await fetch(googleDriveOptions.apiEndpoint + \"/batch/drive/v3\", {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n \"Content-Type\": `multipart/mixed; boundary=${boundary}`,\r\n },\r\n body: batchBody,\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res);\r\n }\r\n\r\n // multipart/mixed; you can parse it, or just return raw.\r\n return await res.text();\r\n}\r\n\r\nexport async function insertDocumentFiles<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n primaryPath: keyof RxDocType,\r\n docs: RxDocType[]\r\n) {\r\n // Run uploads in parallel\r\n await Promise.all(docs.map(async (doc) => {\r\n const id = (doc as any)[primaryPath];\r\n await insertMultipartFile(\r\n googleDriveOptions,\r\n init.docsFolderId,\r\n id + '.json',\r\n doc\r\n );\r\n }));\r\n}\r\n\r\nexport async function updateDocumentFiles<DocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n primaryPath: keyof DocType,\r\n docs: DocType[],\r\n fileMetaByDocId: Record<string, { fileId: string; etag: string }>,\r\n concurrency = 5\r\n) {\r\n const queue = docs.slice(0);\r\n const results: Record<string, { id: string }> = {};\r\n\r\n async function worker() {\r\n while (queue.length) {\r\n const doc = queue.shift()!;\r\n const docId = (doc as any)[primaryPath] as string;\r\n const meta = ensureNotFalsy(fileMetaByDocId[docId]);\r\n const fileId = meta.fileId;\r\n const etag = meta.etag;\r\n\r\n const url =\r\n googleDriveOptions.apiEndpoint +\r\n `/upload/drive/v2/files/${encodeURIComponent(fileId)}` +\r\n `?uploadType=media&supportsAllDrives=true&fields=id`;\r\n\r\n const res = await fetch(url, {\r\n method: \"PUT\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n \"Content-Type\": \"application/json; charset=UTF-8\",\r\n \"If-Match\": etag,\r\n },\r\n body: JSON.stringify(doc),\r\n });\r\n\r\n if (res.status === 412) {\r\n throw newRxError('GDR20', {\r\n args: {\r\n docId,\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n args: {\r\n docId,\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n results[docId] = await res.json(); // { id }\r\n }\r\n }\r\n\r\n await Promise.all(Array.from({ length: concurrency }, () => worker()));\r\n return results;\r\n}\r\n\r\n\r\nexport async function fetchDocumentContents<DocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileIds: string[],\r\n concurrency = 5\r\n): Promise<{ byId: ById<DocType>; ordered: (DocType)[] }> {\r\n const byId: ById<DocType> = {};\r\n const ordered = new Array<DocType>(fileIds.length);\r\n let nextIndex = 0;\r\n\r\n const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\r\n\r\n async function fetchOne(fileId: string, attempt = 0): Promise<DocType | undefined> {\r\n const url =\r\n googleDriveOptions.apiEndpoint +\r\n `/drive/v3/files/${encodeURIComponent(fileId)}?alt=media&supportsAllDrives=true`;\r\n\r\n const res = await fetch(url, {\r\n headers: { Authorization: `Bearer ${googleDriveOptions.authToken}` },\r\n });\r\n\r\n if ([429, 500, 502, 503, 504].includes(res.status) && attempt < 4) {\r\n const backoffMs = 250 * Math.pow(2, attempt) + Math.floor(Math.random() * 200);\r\n await sleep(backoffMs);\r\n return fetchOne(fileId, attempt + 1);\r\n }\r\n\r\n if (!res.ok) throw await newRxFetchError(res, { args: { fileId } });\r\n\r\n const text = await res.text();\r\n return text ? (JSON.parse(text) as DocType) : undefined;\r\n }\r\n\r\n async function worker() {\r\n while (true) {\r\n const i = nextIndex++;\r\n if (i >= fileIds.length) return;\r\n\r\n const fileId = fileIds[i];\r\n const doc = await fetchOne(fileId);\r\n\r\n ordered[i] = ensureNotFalsy(doc);\r\n byId[fileId] = doc as any; // if ById allows undefined, remove `as any`\r\n }\r\n }\r\n\r\n await Promise.all(Array.from({ length: concurrency }, () => worker()));\r\n return { byId, ordered };\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -297,7 +297,7 @@ async function insertMultipartFile(googleDriveOptions, folderId, filename, jsonD
|
|
|
297
297
|
var metadata = {
|
|
298
298
|
name: filename,
|
|
299
299
|
mimeType: 'application/json',
|
|
300
|
-
parents: folderId
|
|
300
|
+
parents: [folderId]
|
|
301
301
|
};
|
|
302
302
|
var postData = createMultipartBody(metadata, content);
|
|
303
303
|
var res = await fetch(googleDriveOptions.apiEndpoint + "/upload/drive/v3/files?uploadType=multipart", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-drive-helper.js","names":["_rxError","require","_index","DRIVE_API_VERSION","exports","DRIVE_MAX_PAGE_SIZE","DRIVE_MAX_BULK_SIZE","FOLDER_MIME_TYPE","createFolder","googleDriveOptions","parentId","folderName","url","apiEndpoint","body","name","mimeType","parents","response","fetch","method","headers","Authorization","authToken","JSON","stringify","ok","errorText","text","status","found","findFolder","ensureNotFalsy","newRxFetchError","json","foundFolder","query","searchUrl","encodeURIComponent","searchResponse","searchData","files","length","file","newRxError","args","id","undefined","ensureFolderExists","folderPath","parts","split","filter","p","part","newParentId","createEmptyFile","fileName","join","url2","res","data","etag","createdTime","fileId","size","parseInt","fillFileIfEtagMatches","jsonContent","writeContent","readJsonFileContent","then","r","content","serverTime","deleteIfEtagMatches","deleteFile","Accept","dateHeader","get","unixMs","Date","parse","contentType","includes","err","Error","code","contentText","readFolder","listUrl","listResponse","listData","insertMultipartFile","folderId","filename","jsonData","metadata","postData","createMultipartBody","boundary","multipartBoundary","Math","random","toString","slice","delimiter","closeDelim","listFilesInFolder","q","params","URLSearchParams","pageSize","fields","supportsAllDrives","includeItemsFromAllDrives","catch"],"sources":["../../../../src/plugins/replication-google-drive/google-drive-helper.ts"],"sourcesContent":["import { newRxError, newRxFetchError } from '../../rx-error.ts';\r\nimport { ensureNotFalsy } from '../utils/index.ts';\r\nimport type {\r\n GoogleDriveOptionsWithDefaults,\r\n DriveFileMetadata\r\n} from './google-drive-types.ts';\r\nimport { DriveStructure } from './init.ts';\r\n\r\nexport const DRIVE_API_VERSION = 'v3';\r\nexport const DRIVE_MAX_PAGE_SIZE = 1000;\r\nexport const DRIVE_MAX_BULK_SIZE = DRIVE_MAX_PAGE_SIZE / 4;\r\nexport const FOLDER_MIME_TYPE = 'application/vnd.google-apps.folder';\r\n\r\nexport async function createFolder(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n parentId: string = 'root',\r\n folderName: string\r\n): Promise<string> {\r\n const url = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=id,name,mimeType,trashed';\r\n const body = {\r\n name: folderName,\r\n mimeType: FOLDER_MIME_TYPE,\r\n parents: [parentId]\r\n };\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken,\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(body)\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n\r\n if (response.status == 409) {\r\n // someone else created the same folder, return that one instead.\r\n const found = await findFolder(googleDriveOptions, parentId, folderName);\r\n return ensureNotFalsy(found);\r\n }\r\n\r\n throw await newRxFetchError(response, {\r\n folderName,\r\n parentId\r\n });\r\n }\r\n\r\n await response.json();\r\n\r\n /**\r\n * To make the function idempotent, we do not use the id from the creation-response.\r\n * Instead after creating the folder, we search for it again so that in case\r\n * some other instance created the same folder, we use the oldest one always.\r\n */\r\n const foundFolder = await findFolder(\r\n googleDriveOptions,\r\n parentId,\r\n folderName\r\n );\r\n\r\n return ensureNotFalsy(foundFolder);\r\n}\r\n\r\n\r\nexport async function findFolder(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n parentId: string = 'root',\r\n folderName: string\r\n): Promise<string | undefined> {\r\n const query = \"name = '\" + folderName + \"' and '\" + parentId + \"' in parents and trashed = false and mimeType = '\" + FOLDER_MIME_TYPE + \"'\";\r\n /**\r\n * We sort by createdTime ASC\r\n * so in case the same folder was created multiple times, we always pick the same\r\n * one which is the oldest one.\r\n */\r\n const searchUrl = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=files(id,mimeType)&orderBy=createdTime asc&q=' + encodeURIComponent(query);\r\n const searchResponse = await fetch(searchUrl, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n const searchData = await searchResponse.json();\r\n\r\n if (searchData.files && searchData.files.length > 0) {\r\n const file = searchData.files[0];\r\n if (file.mimeType !== FOLDER_MIME_TYPE) {\r\n throw newRxError('GDR3', {\r\n folderName,\r\n args: {\r\n file,\r\n FOLDER_MIME_TYPE\r\n }\r\n });\r\n }\r\n return file.id;\r\n } else {\r\n return undefined;\r\n }\r\n}\r\n\r\nexport async function ensureFolderExists(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n folderPath: string\r\n): Promise<string> {\r\n const parts = folderPath.split('/').filter(p => p.length > 0);\r\n let parentId = 'root';\r\n for (const part of parts) {\r\n const newParentId = await findFolder(googleDriveOptions, parentId, part);\r\n if (newParentId) {\r\n parentId = newParentId\r\n } else {\r\n parentId = await createFolder(googleDriveOptions, parentId, part);\r\n }\r\n }\r\n return parentId;\r\n}\r\n\r\n\r\nexport async function createEmptyFile(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n parentId: string,\r\n fileName: string\r\n) {\r\n const url = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=id';\r\n const body = {\r\n name: fileName,\r\n parents: [parentId],\r\n mimeType: 'application/json'\r\n };\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken,\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(body)\r\n });\r\n\r\n /**\r\n * Do not throw on duplicates,\r\n * if the file is there already, find its id\r\n * and return that one.\r\n */\r\n if (!response.ok && response.status !== 409) {\r\n throw await newRxFetchError(response, {\r\n folderName: fileName\r\n });\r\n }\r\n\r\n /**\r\n * For idempotent runs, fetch the file again\r\n * after creating it.\r\n */\r\n const query = [\r\n `name = '${fileName}'`,\r\n `'${parentId}' in parents`,\r\n `trashed = false`,\r\n ].join(' and ');\r\n const url2 =\r\n googleDriveOptions.apiEndpoint + '/drive/v3/files' +\r\n '?fields=files(id,etag,size,createdTime)' +\r\n '&orderBy=createdTime asc' +\r\n '&q=' + encodeURIComponent(query);\r\n const res = await fetch(url2, {\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken,\r\n },\r\n });\r\n const data = await res.json();\r\n const file = ensureNotFalsy(data.files[0]);\r\n return {\r\n status: response.status,\r\n etag: ensureNotFalsy(file.etag),\r\n createdTime: ensureNotFalsy(file.createdTime),\r\n fileId: ensureNotFalsy(file.id),\r\n size: parseInt(file.size, 10)\r\n }\r\n}\r\n\r\n\r\nexport async function fillFileIfEtagMatches<T = any>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileId: string,\r\n etag: string,\r\n jsonContent?: any\r\n): Promise<{\r\n status: number;\r\n etag: string;\r\n content: T | undefined;\r\n serverTime: number;\r\n}> {\r\n const url =\r\n `${googleDriveOptions.apiEndpoint}` +\r\n `/upload/drive/v2/files/${encodeURIComponent(fileId)}` +\r\n `?uploadType=media`;\r\n\r\n const writeContent = typeof jsonContent !== 'undefined' ? JSON.stringify(jsonContent) : '';\r\n const res = await fetch(url, {\r\n method: \"PUT\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n \"Content-Type\": \"application/json; charset=utf-8\",\r\n \"If-Match\": etag,\r\n },\r\n body: writeContent,\r\n });\r\n if (res.status !== 412 && res.status !== 200) {\r\n throw await newRxFetchError(res);\r\n }\r\n\r\n return readJsonFileContent<T>(\r\n googleDriveOptions,\r\n fileId\r\n ).then(r => {\r\n return {\r\n content: r.content,\r\n etag: r.etag,\r\n status: res.status,\r\n serverTime: r.serverTime\r\n };\r\n });\r\n}\r\n\r\nexport async function deleteIfEtagMatches(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileId: string,\r\n etag: string\r\n): Promise<void> {\r\n const url =\r\n `${googleDriveOptions.apiEndpoint}` +\r\n `/drive/v2/files/${encodeURIComponent(fileId)}`;\r\n\r\n const res = await fetch(url, {\r\n method: \"DELETE\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n \"If-Match\": etag,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n args: {\r\n etag,\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n if (res.ok) {\r\n // Drive v2 returns 204 No Content on successful delete\r\n return;\r\n }\r\n}\r\n\r\nexport async function deleteFile(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileId: string\r\n): Promise<void> {\r\n const url =\r\n `${googleDriveOptions.apiEndpoint}` +\r\n `/drive/v2/files/${encodeURIComponent(fileId)}`;\r\n\r\n const res = await fetch(url, {\r\n method: \"DELETE\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n args: {\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n if (res.ok) {\r\n // Drive v2 returns 204 No Content on successful delete\r\n return;\r\n }\r\n}\r\n\r\nexport async function readJsonFileContent<T>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileId: string\r\n): Promise<{\r\n etag: string;\r\n content: T | undefined;\r\n serverTime: number;\r\n}> {\r\n const url =\r\n `${googleDriveOptions.apiEndpoint}` +\r\n `/drive/v2/files/${encodeURIComponent(fileId)}?alt=media`;\r\n\r\n const res = await fetch(url, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n Accept: \"application/json\",\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n args: {\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n const dateHeader = res.headers.get('date');\r\n const unixMs = Date.parse(ensureNotFalsy(dateHeader));\r\n\r\n const contentType = res.headers.get(\"content-type\") || \"\";\r\n if (!contentType.includes(\"application/json\")) {\r\n const err = new Error(\"NOT_A_JSON_FILE but \" + contentType);\r\n (err as any).code = \"NOT_A_JSON_FILE\";\r\n (err as any).contentType = contentType;\r\n throw err;\r\n }\r\n\r\n const contentText = await res.text();\r\n const content = contentText.length > 0 ? JSON.parse(contentText) : undefined;\r\n const etag = ensureNotFalsy(res.headers.get('etag'));\r\n return {\r\n etag,\r\n content: content as T,\r\n serverTime: unixMs\r\n };\r\n}\r\n\r\n\r\nexport async function readFolder(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n folderPath: string\r\n): Promise<DriveFileMetadata[]> {\r\n let parentId = 'root';\r\n const parts = folderPath.split('/').filter(p => p.length > 0);\r\n\r\n // Resolve folder path\r\n for (const part of parts) {\r\n const query = \"name = '\" + part + \"' and '\" + parentId + \"' in parents and trashed = false and mimeType = '\" + FOLDER_MIME_TYPE + \"'\";\r\n const searchUrl = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=files(id)&q=' + encodeURIComponent(query);\r\n const searchResponse = await fetch(searchUrl, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n const searchData = await searchResponse.json();\r\n if (searchData.files && searchData.files.length > 0) {\r\n parentId = searchData.files[0].id;\r\n } else {\r\n throw newRxError('SNH', { folderPath });\r\n }\r\n }\r\n\r\n // List children\r\n const query = \"'\" + parentId + \"' in parents and trashed = false\";\r\n const listUrl = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=files(id,name,mimeType,trashed,parents)&q=' + encodeURIComponent(query);\r\n const listResponse = await fetch(listUrl, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n\r\n if (!listResponse.ok) {\r\n throw await newRxFetchError(listResponse, {\r\n folderName: folderPath\r\n });\r\n }\r\n\r\n const listData = await listResponse.json();\r\n return listData.files || [];\r\n}\r\n\r\nexport async function insertMultipartFile<T>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n folderId: string,\r\n filename: string,\r\n jsonData: T\r\n) {\r\n const content = JSON.stringify(jsonData);\r\n\r\n const metadata = {\r\n name: filename,\r\n mimeType: 'application/json',\r\n parents: folderId,\r\n };\r\n\r\n const postData = createMultipartBody(\r\n metadata,\r\n content\r\n );\r\n\r\n const res = await fetch(googleDriveOptions.apiEndpoint + \"/upload/drive/v3/files?uploadType=multipart\", {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n 'Content-Type': 'multipart/related; boundary=\"' + postData.boundary + '\"'\r\n },\r\n body: postData.body\r\n });\r\n if (!res.ok) {\r\n throw await newRxFetchError(res);\r\n }\r\n}\r\n\r\nexport function createMultipartBody(\r\n metadata: Record<string, unknown>,\r\n content: string\r\n) {\r\n const multipartBoundary = '-------1337-use-RxDB-7355608-' + Math.random().toString(16).slice(2);\r\n const delimiter = '\\r\\n--' + multipartBoundary + '\\r\\n';\r\n const closeDelim = '\\r\\n--' + multipartBoundary + '--';\r\n const body = delimiter +\r\n 'Content-Type: application/json\\r\\n\\r\\n' +\r\n JSON.stringify(metadata) +\r\n delimiter +\r\n 'Content-Type: application/json\\r\\n\\r\\n' +\r\n content +\r\n closeDelim;\r\n return { body, boundary: multipartBoundary };\r\n};\r\n\r\n\r\nexport async function listFilesInFolder(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n folderId: string\r\n): Promise<DriveFileMetadata[]> {\r\n\r\n const q = `'${folderId}' in parents and trashed = false`;\r\n\r\n const params = new URLSearchParams({\r\n q,\r\n pageSize: \"1000\", // max allowed\r\n fields: \"files(id,name,mimeType,parents,modifiedTime,size)\",\r\n supportsAllDrives: \"true\",\r\n includeItemsFromAllDrives: \"true\",\r\n });\r\n\r\n const url =\r\n googleDriveOptions.apiEndpoint +\r\n \"/drive/v3/files?\" +\r\n params.toString();\r\n\r\n const res = await fetch(url, {\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n const text = await res.text().catch(() => \"\");\r\n throw new Error(`files.list failed: ${res.status} ${text}`);\r\n }\r\n\r\n const data = await res.json();\r\n return data.files ?? [];\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"google-drive-helper.js","names":["_rxError","require","_index","DRIVE_API_VERSION","exports","DRIVE_MAX_PAGE_SIZE","DRIVE_MAX_BULK_SIZE","FOLDER_MIME_TYPE","createFolder","googleDriveOptions","parentId","folderName","url","apiEndpoint","body","name","mimeType","parents","response","fetch","method","headers","Authorization","authToken","JSON","stringify","ok","errorText","text","status","found","findFolder","ensureNotFalsy","newRxFetchError","json","foundFolder","query","searchUrl","encodeURIComponent","searchResponse","searchData","files","length","file","newRxError","args","id","undefined","ensureFolderExists","folderPath","parts","split","filter","p","part","newParentId","createEmptyFile","fileName","join","url2","res","data","etag","createdTime","fileId","size","parseInt","fillFileIfEtagMatches","jsonContent","writeContent","readJsonFileContent","then","r","content","serverTime","deleteIfEtagMatches","deleteFile","Accept","dateHeader","get","unixMs","Date","parse","contentType","includes","err","Error","code","contentText","readFolder","listUrl","listResponse","listData","insertMultipartFile","folderId","filename","jsonData","metadata","postData","createMultipartBody","boundary","multipartBoundary","Math","random","toString","slice","delimiter","closeDelim","listFilesInFolder","q","params","URLSearchParams","pageSize","fields","supportsAllDrives","includeItemsFromAllDrives","catch"],"sources":["../../../../src/plugins/replication-google-drive/google-drive-helper.ts"],"sourcesContent":["import { newRxError, newRxFetchError } from '../../rx-error.ts';\r\nimport { ensureNotFalsy } from '../utils/index.ts';\r\nimport type {\r\n GoogleDriveOptionsWithDefaults,\r\n DriveFileMetadata\r\n} from './google-drive-types.ts';\r\nimport { DriveStructure } from './init.ts';\r\n\r\nexport const DRIVE_API_VERSION = 'v3';\r\nexport const DRIVE_MAX_PAGE_SIZE = 1000;\r\nexport const DRIVE_MAX_BULK_SIZE = DRIVE_MAX_PAGE_SIZE / 4;\r\nexport const FOLDER_MIME_TYPE = 'application/vnd.google-apps.folder';\r\n\r\nexport async function createFolder(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n parentId: string = 'root',\r\n folderName: string\r\n): Promise<string> {\r\n const url = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=id,name,mimeType,trashed';\r\n const body = {\r\n name: folderName,\r\n mimeType: FOLDER_MIME_TYPE,\r\n parents: [parentId]\r\n };\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken,\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(body)\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n\r\n if (response.status == 409) {\r\n // someone else created the same folder, return that one instead.\r\n const found = await findFolder(googleDriveOptions, parentId, folderName);\r\n return ensureNotFalsy(found);\r\n }\r\n\r\n throw await newRxFetchError(response, {\r\n folderName,\r\n parentId\r\n });\r\n }\r\n\r\n await response.json();\r\n\r\n /**\r\n * To make the function idempotent, we do not use the id from the creation-response.\r\n * Instead after creating the folder, we search for it again so that in case\r\n * some other instance created the same folder, we use the oldest one always.\r\n */\r\n const foundFolder = await findFolder(\r\n googleDriveOptions,\r\n parentId,\r\n folderName\r\n );\r\n\r\n return ensureNotFalsy(foundFolder);\r\n}\r\n\r\n\r\nexport async function findFolder(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n parentId: string = 'root',\r\n folderName: string\r\n): Promise<string | undefined> {\r\n const query = \"name = '\" + folderName + \"' and '\" + parentId + \"' in parents and trashed = false and mimeType = '\" + FOLDER_MIME_TYPE + \"'\";\r\n /**\r\n * We sort by createdTime ASC\r\n * so in case the same folder was created multiple times, we always pick the same\r\n * one which is the oldest one.\r\n */\r\n const searchUrl = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=files(id,mimeType)&orderBy=createdTime asc&q=' + encodeURIComponent(query);\r\n const searchResponse = await fetch(searchUrl, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n const searchData = await searchResponse.json();\r\n\r\n if (searchData.files && searchData.files.length > 0) {\r\n const file = searchData.files[0];\r\n if (file.mimeType !== FOLDER_MIME_TYPE) {\r\n throw newRxError('GDR3', {\r\n folderName,\r\n args: {\r\n file,\r\n FOLDER_MIME_TYPE\r\n }\r\n });\r\n }\r\n return file.id;\r\n } else {\r\n return undefined;\r\n }\r\n}\r\n\r\nexport async function ensureFolderExists(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n folderPath: string\r\n): Promise<string> {\r\n const parts = folderPath.split('/').filter(p => p.length > 0);\r\n let parentId = 'root';\r\n for (const part of parts) {\r\n const newParentId = await findFolder(googleDriveOptions, parentId, part);\r\n if (newParentId) {\r\n parentId = newParentId\r\n } else {\r\n parentId = await createFolder(googleDriveOptions, parentId, part);\r\n }\r\n }\r\n return parentId;\r\n}\r\n\r\n\r\nexport async function createEmptyFile(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n parentId: string,\r\n fileName: string\r\n) {\r\n const url = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=id';\r\n const body = {\r\n name: fileName,\r\n parents: [parentId],\r\n mimeType: 'application/json'\r\n };\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken,\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(body)\r\n });\r\n\r\n /**\r\n * Do not throw on duplicates,\r\n * if the file is there already, find its id\r\n * and return that one.\r\n */\r\n if (!response.ok && response.status !== 409) {\r\n throw await newRxFetchError(response, {\r\n folderName: fileName\r\n });\r\n }\r\n\r\n /**\r\n * For idempotent runs, fetch the file again\r\n * after creating it.\r\n */\r\n const query = [\r\n `name = '${fileName}'`,\r\n `'${parentId}' in parents`,\r\n `trashed = false`,\r\n ].join(' and ');\r\n const url2 =\r\n googleDriveOptions.apiEndpoint + '/drive/v3/files' +\r\n '?fields=files(id,etag,size,createdTime)' +\r\n '&orderBy=createdTime asc' +\r\n '&q=' + encodeURIComponent(query);\r\n const res = await fetch(url2, {\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken,\r\n },\r\n });\r\n const data = await res.json();\r\n const file = ensureNotFalsy(data.files[0]);\r\n return {\r\n status: response.status,\r\n etag: ensureNotFalsy(file.etag),\r\n createdTime: ensureNotFalsy(file.createdTime),\r\n fileId: ensureNotFalsy(file.id),\r\n size: parseInt(file.size, 10)\r\n }\r\n}\r\n\r\n\r\nexport async function fillFileIfEtagMatches<T = any>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileId: string,\r\n etag: string,\r\n jsonContent?: any\r\n): Promise<{\r\n status: number;\r\n etag: string;\r\n content: T | undefined;\r\n serverTime: number;\r\n}> {\r\n const url =\r\n `${googleDriveOptions.apiEndpoint}` +\r\n `/upload/drive/v2/files/${encodeURIComponent(fileId)}` +\r\n `?uploadType=media`;\r\n\r\n const writeContent = typeof jsonContent !== 'undefined' ? JSON.stringify(jsonContent) : '';\r\n const res = await fetch(url, {\r\n method: \"PUT\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n \"Content-Type\": \"application/json; charset=utf-8\",\r\n \"If-Match\": etag,\r\n },\r\n body: writeContent,\r\n });\r\n if (res.status !== 412 && res.status !== 200) {\r\n throw await newRxFetchError(res);\r\n }\r\n\r\n return readJsonFileContent<T>(\r\n googleDriveOptions,\r\n fileId\r\n ).then(r => {\r\n return {\r\n content: r.content,\r\n etag: r.etag,\r\n status: res.status,\r\n serverTime: r.serverTime\r\n };\r\n });\r\n}\r\n\r\nexport async function deleteIfEtagMatches(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileId: string,\r\n etag: string\r\n): Promise<void> {\r\n const url =\r\n `${googleDriveOptions.apiEndpoint}` +\r\n `/drive/v2/files/${encodeURIComponent(fileId)}`;\r\n\r\n const res = await fetch(url, {\r\n method: \"DELETE\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n \"If-Match\": etag,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n args: {\r\n etag,\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n if (res.ok) {\r\n // Drive v2 returns 204 No Content on successful delete\r\n return;\r\n }\r\n}\r\n\r\nexport async function deleteFile(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileId: string\r\n): Promise<void> {\r\n const url =\r\n `${googleDriveOptions.apiEndpoint}` +\r\n `/drive/v2/files/${encodeURIComponent(fileId)}`;\r\n\r\n const res = await fetch(url, {\r\n method: \"DELETE\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n args: {\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n if (res.ok) {\r\n // Drive v2 returns 204 No Content on successful delete\r\n return;\r\n }\r\n}\r\n\r\nexport async function readJsonFileContent<T>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n fileId: string\r\n): Promise<{\r\n etag: string;\r\n content: T | undefined;\r\n serverTime: number;\r\n}> {\r\n const url =\r\n `${googleDriveOptions.apiEndpoint}` +\r\n `/drive/v2/files/${encodeURIComponent(fileId)}?alt=media`;\r\n\r\n const res = await fetch(url, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n Accept: \"application/json\",\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res, {\r\n args: {\r\n fileId\r\n }\r\n });\r\n }\r\n\r\n const dateHeader = res.headers.get('date');\r\n const unixMs = Date.parse(ensureNotFalsy(dateHeader));\r\n\r\n const contentType = res.headers.get(\"content-type\") || \"\";\r\n if (!contentType.includes(\"application/json\")) {\r\n const err = new Error(\"NOT_A_JSON_FILE but \" + contentType);\r\n (err as any).code = \"NOT_A_JSON_FILE\";\r\n (err as any).contentType = contentType;\r\n throw err;\r\n }\r\n\r\n const contentText = await res.text();\r\n const content = contentText.length > 0 ? JSON.parse(contentText) : undefined;\r\n const etag = ensureNotFalsy(res.headers.get('etag'));\r\n return {\r\n etag,\r\n content: content as T,\r\n serverTime: unixMs\r\n };\r\n}\r\n\r\n\r\nexport async function readFolder(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n folderPath: string\r\n): Promise<DriveFileMetadata[]> {\r\n let parentId = 'root';\r\n const parts = folderPath.split('/').filter(p => p.length > 0);\r\n\r\n // Resolve folder path\r\n for (const part of parts) {\r\n const query = \"name = '\" + part + \"' and '\" + parentId + \"' in parents and trashed = false and mimeType = '\" + FOLDER_MIME_TYPE + \"'\";\r\n const searchUrl = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=files(id)&q=' + encodeURIComponent(query);\r\n const searchResponse = await fetch(searchUrl, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n const searchData = await searchResponse.json();\r\n if (searchData.files && searchData.files.length > 0) {\r\n parentId = searchData.files[0].id;\r\n } else {\r\n throw newRxError('SNH', { folderPath });\r\n }\r\n }\r\n\r\n // List children\r\n const query = \"'\" + parentId + \"' in parents and trashed = false\";\r\n const listUrl = googleDriveOptions.apiEndpoint + '/drive/v3/files?fields=files(id,name,mimeType,trashed,parents)&q=' + encodeURIComponent(query);\r\n const listResponse = await fetch(listUrl, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n\r\n if (!listResponse.ok) {\r\n throw await newRxFetchError(listResponse, {\r\n folderName: folderPath\r\n });\r\n }\r\n\r\n const listData = await listResponse.json();\r\n return listData.files || [];\r\n}\r\n\r\nexport async function insertMultipartFile<T>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n folderId: string,\r\n filename: string,\r\n jsonData: T\r\n) {\r\n const content = JSON.stringify(jsonData);\r\n\r\n const metadata = {\r\n name: filename,\r\n mimeType: 'application/json',\r\n parents: [folderId],\r\n };\r\n\r\n const postData = createMultipartBody(\r\n metadata,\r\n content\r\n );\r\n\r\n const res = await fetch(googleDriveOptions.apiEndpoint + \"/upload/drive/v3/files?uploadType=multipart\", {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n 'Content-Type': 'multipart/related; boundary=\"' + postData.boundary + '\"'\r\n },\r\n body: postData.body\r\n });\r\n if (!res.ok) {\r\n throw await newRxFetchError(res);\r\n }\r\n}\r\n\r\nexport function createMultipartBody(\r\n metadata: Record<string, unknown>,\r\n content: string\r\n) {\r\n const multipartBoundary = '-------1337-use-RxDB-7355608-' + Math.random().toString(16).slice(2);\r\n const delimiter = '\\r\\n--' + multipartBoundary + '\\r\\n';\r\n const closeDelim = '\\r\\n--' + multipartBoundary + '--';\r\n const body = delimiter +\r\n 'Content-Type: application/json\\r\\n\\r\\n' +\r\n JSON.stringify(metadata) +\r\n delimiter +\r\n 'Content-Type: application/json\\r\\n\\r\\n' +\r\n content +\r\n closeDelim;\r\n return { body, boundary: multipartBoundary };\r\n};\r\n\r\n\r\nexport async function listFilesInFolder(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n folderId: string\r\n): Promise<DriveFileMetadata[]> {\r\n\r\n const q = `'${folderId}' in parents and trashed = false`;\r\n\r\n const params = new URLSearchParams({\r\n q,\r\n pageSize: \"1000\", // max allowed\r\n fields: \"files(id,name,mimeType,parents,modifiedTime,size)\",\r\n supportsAllDrives: \"true\",\r\n includeItemsFromAllDrives: \"true\",\r\n });\r\n\r\n const url =\r\n googleDriveOptions.apiEndpoint +\r\n \"/drive/v3/files?\" +\r\n params.toString();\r\n\r\n const res = await fetch(url, {\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n const text = await res.text().catch(() => \"\");\r\n throw new Error(`files.list failed: ${res.status} ${text}`);\r\n }\r\n\r\n const data = await res.json();\r\n return data.files ?? [];\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-drive-types.js","names":[],"sources":["../../../../src/plugins/replication-google-drive/google-drive-types.ts"],"sourcesContent":["import type {\r\n ReplicationOptions,\r\n ReplicationPullOptions,\r\n ReplicationPushOptions\r\n} from '../../types/index.d.ts';\r\nimport { SignalingOptions } from './signaling.ts';\r\n\r\nexport type GoogleDriveCheckpointType = {\r\n modifiedTime: string;\r\n /**\r\n * There is no way to do a comparison (> or >=)\r\n * on fileNames or ids in google drive.\r\n * Also modifiedTime can be sometimes the same\r\n * on multiple files.\r\n * Therefore we might overfetch documents and\r\n * after the request removed the ones that have been known before.\r\n */\r\n docIdsWithSameModifiedTime: string[];\r\n};\r\n\r\nexport interface DriveFileMetadata {\r\n id: string;\r\n name: string;\r\n mimeType: string;\r\n parents?: string[];\r\n modifiedTime?: string;\r\n size?: string; // Drive returns size as string\r\n fileSize?: string; // v2\r\n}\r\n\r\nexport type GoogleDriveOptions = {\r\n oauthClientId: string;\r\n authToken: string;\r\n /**\r\n * like \"https://www.googleapis.com\"\r\n * No trailing slash!\r\n */\r\n apiEndpoint?: string;\r\n /**\r\n * Path to a folder in Google Drive where all data is stored.\r\n * Example: 'rxdb-replication/my-app'\r\n */\r\n folderPath: string;\r\n\r\n /**\r\n * Time in milliseconds.\r\n */\r\n transactionTimeout?: number;\r\n};\r\n\r\nexport type GoogleDriveOptionsWithDefaults = {\r\n oauthClientId: string;\r\n authToken: string;\r\n /**\r\n * like \"https://www.googleapis.com\"\r\n * No trailing slash!\r\n */\r\n apiEndpoint: string;\r\n folderPath: string;\r\n /**\r\n * Time in milliseconds.\r\n */\r\n transactionTimeout: number;\r\n};\r\n\r\nexport interface DriveFileListResponse {\r\n nextPageToken?: string;\r\n files: DriveFileMetadata[];\r\n}\r\n\r\n\r\nexport type GoogleDriveSyncPullOptions<RxDocType> = Omit<ReplicationPullOptions<RxDocType, GoogleDriveCheckpointType>, 'handler' | 'stream$'>;\r\n\r\nexport type GoogleDriveSyncPushOptions<RxDocType> = Omit<ReplicationPushOptions<RxDocType>, 'handler'>;\r\n\r\nexport type SyncOptionsGoogleDrive<RxDocType> = Omit<\r\n ReplicationOptions<RxDocType, any>,\r\n 'pull' | 'push'\r\n> & {\r\n googleDrive: GoogleDriveOptions;\r\n signalingOptions?: SignalingOptions;\r\n pull?: GoogleDriveSyncPullOptions<RxDocType>;\r\n push?: GoogleDriveSyncPushOptions<RxDocType>;\r\n};\r\n"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"google-drive-types.js","names":[],"sources":["../../../../src/plugins/replication-google-drive/google-drive-types.ts"],"sourcesContent":["import type {\r\n ReplicationOptions,\r\n ReplicationPullOptions,\r\n ReplicationPushOptions\r\n} from '../../types/index.d.ts';\r\nimport { SignalingOptions } from './signaling.ts';\r\n\r\nexport type GoogleDriveCheckpointType = {\r\n modifiedTime: string;\r\n /**\r\n * There is no way to do a comparison (> or >=)\r\n * on fileNames or ids in google drive.\r\n * Also modifiedTime can be sometimes the same\r\n * on multiple files.\r\n * Therefore we might overfetch documents and\r\n * after the request removed the ones that have been known before.\r\n */\r\n docIdsWithSameModifiedTime: string[];\r\n};\r\n\r\nexport interface DriveFileMetadata {\r\n id: string;\r\n name: string;\r\n mimeType: string;\r\n parents?: string[];\r\n modifiedTime?: string;\r\n size?: string; // Drive returns size as string\r\n fileSize?: string; // v2\r\n etag?: string;\r\n}\r\n\r\nexport type GoogleDriveOptions = {\r\n oauthClientId: string;\r\n authToken: string;\r\n /**\r\n * like \"https://www.googleapis.com\"\r\n * No trailing slash!\r\n */\r\n apiEndpoint?: string;\r\n /**\r\n * Path to a folder in Google Drive where all data is stored.\r\n * Example: 'rxdb-replication/my-app'\r\n */\r\n folderPath: string;\r\n\r\n /**\r\n * Time in milliseconds.\r\n */\r\n transactionTimeout?: number;\r\n};\r\n\r\nexport type GoogleDriveOptionsWithDefaults = {\r\n oauthClientId: string;\r\n authToken: string;\r\n /**\r\n * like \"https://www.googleapis.com\"\r\n * No trailing slash!\r\n */\r\n apiEndpoint: string;\r\n folderPath: string;\r\n /**\r\n * Time in milliseconds.\r\n */\r\n transactionTimeout: number;\r\n};\r\n\r\nexport interface DriveFileListResponse {\r\n nextPageToken?: string;\r\n files: DriveFileMetadata[];\r\n}\r\n\r\n\r\nexport type GoogleDriveSyncPullOptions<RxDocType> = Omit<ReplicationPullOptions<RxDocType, GoogleDriveCheckpointType>, 'handler' | 'stream$'>;\r\n\r\nexport type GoogleDriveSyncPushOptions<RxDocType> = Omit<ReplicationPushOptions<RxDocType>, 'handler'>;\r\n\r\nexport type SyncOptionsGoogleDrive<RxDocType> = Omit<\r\n ReplicationOptions<RxDocType, any>,\r\n 'pull' | 'push'\r\n> & {\r\n googleDrive: GoogleDriveOptions;\r\n signalingOptions?: SignalingOptions;\r\n pull?: GoogleDriveSyncPullOptions<RxDocType>;\r\n push?: GoogleDriveSyncPushOptions<RxDocType>;\r\n};\r\n"],"mappings":"","ignoreList":[]}
|
|
@@ -80,7 +80,9 @@ var SignalingState = exports.SignalingState = /*#__PURE__*/function () {
|
|
|
80
80
|
};
|
|
81
81
|
_proto.pingPeers = async function pingPeers(message) {
|
|
82
82
|
Array.from(this.peerBySenderId.values()).forEach(peer => {
|
|
83
|
-
peer.
|
|
83
|
+
if (peer.connected) {
|
|
84
|
+
peer.send(message);
|
|
85
|
+
}
|
|
84
86
|
});
|
|
85
87
|
};
|
|
86
88
|
_proto.resetReadLoop = async function resetReadLoop() {
|
|
@@ -117,6 +119,7 @@ var SignalingState = exports.SignalingState = /*#__PURE__*/function () {
|
|
|
117
119
|
});
|
|
118
120
|
peer.on('connect', () => {
|
|
119
121
|
this._resync$.next();
|
|
122
|
+
peer.send('RESYNC');
|
|
120
123
|
});
|
|
121
124
|
peer.on('data', dataBuffer => {
|
|
122
125
|
var data = dataBuffer + '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signaling.js","names":["_simplePeer","_interopRequireDefault","require","_connectionHandlerSimplePeer","_index","_googleDriveHelper","_rxjs","_rxError","BACKOFF_STEPS","MAX_BACKOFF_STEP_ID","length","SignalingState","exports","googleDriveOptions","init","signalingOptions","sessionId","randomToken","processedMessageIds","Set","_resync$","Subject","resync$","asObservable","peerBySenderId","Map","processQueue","PROMISE_RESOLVE_VOID","backoffStepId","closed","resetReaderFn","resetReadLoop","ensureProcessNextTickIsSet","cleanupOldSignalingMessages","signalingFolderId","catch","sendMessage","i","processNewMessages","window","addEventListener","document","time","skippable","promiseWaitSkippable","skipBackoffTime","skip","promise","_proto","prototype","data","messageId","fileName","now","join","add","insertMultipartFile","pingPeers","message","Array","from","values","forEach","peer","send","then","_processNewMessages","messages","readMessages","next","senderId","peerInstance","getFromMapOrCreate","_Peer","initiator","trickle","wrtc","config","on","signalData","dataBuffer","console","error","delete","promiseWait","signal","close","removeEventListener","destroy","complete","query","fields","params","URLSearchParams","set","listUrl","apiEndpoint","toString","listResponse","fetch","method","headers","Authorization","authToken","ok","newRxFetchError","listData","json","folderData","files","reverse","useFiles","filter","file","messageIdByFilename","name","has","filesContent","Promise","all","map","fileContent","readJsonFileContent","id","split","content","ensureNotFalsy","lastOfArray","DEFAULT_MAX_AGE_MS","maxAgeMs","cutoffDate","Date","toISOString","url","oldFiles","deleteFile"],"sources":["../../../../src/plugins/replication-google-drive/signaling.ts"],"sourcesContent":["import type {\r\n Instance as SimplePeerInstance\r\n} from 'simple-peer';\r\nimport _Peer from 'simple-peer';\r\nimport {\r\n ensureProcessNextTickIsSet,\r\n SimplePeerConfig,\r\n SimplePeerWrtc\r\n} from '../replication-webrtc/connection-handler-simple-peer';\r\nimport {\r\n ensureNotFalsy,\r\n getFromMapOrCreate,\r\n lastOfArray,\r\n now,\r\n PROMISE_RESOLVE_VOID,\r\n promiseWait,\r\n promiseWaitSkippable,\r\n randomToken\r\n} from '../utils/index.ts';\r\nimport { DriveStructure } from './init.ts';\r\nimport {\r\n DriveFileMetadata,\r\n GoogleDriveOptionsWithDefaults\r\n} from './google-drive-types.ts';\r\nimport {\r\n deleteFile,\r\n insertMultipartFile,\r\n readJsonFileContent\r\n} from './google-drive-helper.ts';\r\nimport { Subject } from 'rxjs';\r\nimport { newRxFetchError } from '../../rx-error.ts';\r\n\r\n\r\nexport type SignalingOptions = {\r\n wrtc?: SimplePeerWrtc;\r\n config?: SimplePeerConfig;\r\n};\r\n\r\n/**\r\n * Timings on when to call the google drive\r\n * api to check for new messages.\r\n */\r\nconst BACKOFF_STEPS = [\r\n 50,\r\n 50,\r\n 100,\r\n 100,\r\n 200,\r\n 400,\r\n 600,\r\n 1_000,\r\n 2_000,\r\n 4_000,\r\n 8_000,\r\n 15_000,\r\n 30_000,\r\n 60_000,\r\n 120_000\r\n];\r\nconst MAX_BACKOFF_STEP_ID = BACKOFF_STEPS.length - 1;\r\n\r\n\r\nexport type SIGNAL = 'RESYNC' | 'NEW_PEER';\r\n\r\nexport class SignalingState {\r\n public readonly sessionId = randomToken(12);\r\n public readonly processedMessageIds = new Set<string>();\r\n\r\n /**\r\n * Emits whenever a new connection\r\n * is there or some connection\r\n * told us to RESYNC\r\n */\r\n private _resync$ = new Subject<void>();\r\n public resync$ = this._resync$.asObservable();\r\n\r\n public peerBySenderId = new Map<string, SimplePeerInstance>();\r\n\r\n private processQueue: Promise<any> = PROMISE_RESOLVE_VOID;\r\n private backoffStepId = 0;\r\n private skipBackoffTime?: () => void;\r\n\r\n\r\n public closed = false;\r\n public resetReaderFn = () => {\r\n this.resetReadLoop();\r\n };\r\n\r\n constructor(\r\n private googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n private init: DriveStructure,\r\n private signalingOptions: SignalingOptions\r\n ) {\r\n ensureProcessNextTickIsSet();\r\n cleanupOldSignalingMessages(\r\n this.googleDriveOptions,\r\n this.init.signalingFolderId\r\n ).catch(() => { });\r\n\r\n // Send \"i exist\" message\r\n this.sendMessage({ i: 'exist' });\r\n this.processNewMessages();\r\n\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('online', this.resetReaderFn);\r\n document.addEventListener('visibilitychange', this.resetReaderFn);\r\n\r\n }\r\n\r\n // start processing loop\r\n (async () => {\r\n while (!this.closed) {\r\n const time = BACKOFF_STEPS[this.backoffStepId];\r\n await this.processNewMessages();\r\n const skippable = promiseWaitSkippable(time);\r\n this.skipBackoffTime = skippable.skip;\r\n await skippable.promise;\r\n this.backoffStepId = this.backoffStepId + 1;\r\n if (this.backoffStepId > MAX_BACKOFF_STEP_ID) {\r\n this.backoffStepId = MAX_BACKOFF_STEP_ID;\r\n }\r\n }\r\n })();\r\n }\r\n\r\n async sendMessage(data: any) {\r\n const messageId = randomToken(12);\r\n const fileName = [\r\n this.sessionId,\r\n now(),\r\n messageId\r\n ].join('_') + '.json';\r\n\r\n // add here so we skip these\r\n this.processedMessageIds.add(messageId);\r\n\r\n await insertMultipartFile(\r\n this.googleDriveOptions,\r\n this.init.signalingFolderId,\r\n fileName,\r\n data\r\n );\r\n }\r\n\r\n async pingPeers(message: SIGNAL) {\r\n Array.from(this.peerBySenderId.values()).forEach(peer => {\r\n peer.send(message);\r\n });\r\n }\r\n\r\n\r\n async resetReadLoop() {\r\n await this.processNewMessages();\r\n this.backoffStepId = 0;\r\n if (this.skipBackoffTime) {\r\n this.skipBackoffTime();\r\n }\r\n }\r\n\r\n async processNewMessages() {\r\n this.processQueue = this.processQueue.then(\r\n () => this._processNewMessages().catch(() => { })\r\n );\r\n return this.processQueue;\r\n }\r\n\r\n async _processNewMessages() {\r\n const messages = await readMessages(\r\n this.googleDriveOptions,\r\n this.init,\r\n this.processedMessageIds\r\n );\r\n if (messages.length > 0) {\r\n this._resync$.next();\r\n }\r\n messages.forEach(message => {\r\n const senderId = message.senderId;\r\n if (senderId === this.sessionId) {\r\n return;\r\n }\r\n let peerInstance: SimplePeerInstance;\r\n\r\n peerInstance = getFromMapOrCreate(\r\n this.peerBySenderId,\r\n senderId,\r\n () => {\r\n const peer = new _Peer({\r\n initiator: senderId > this.sessionId,\r\n trickle: true,\r\n wrtc: this.signalingOptions.wrtc,\r\n config: this.signalingOptions.config\r\n })\r\n peer.on(\"signal\", async (signalData: any) => {\r\n await this.sendMessage(signalData);\r\n });\r\n peer.on('connect', () => {\r\n this._resync$.next();\r\n });\r\n peer.on('data', (dataBuffer: any) => {\r\n const data = dataBuffer + '';\r\n switch (data) {\r\n case 'NEW_PEER':\r\n this.resetReadLoop();\r\n break;\r\n case 'RESYNC':\r\n this._resync$.next();\r\n break;\r\n default:\r\n console.error('Signaling UNKNOWN DATA ' + data);\r\n }\r\n });\r\n peer.on('error', () => {\r\n this._resync$.next();\r\n });\r\n peer.on('close', () => {\r\n this.peerBySenderId.delete(senderId);\r\n this._resync$.next();\r\n });\r\n\r\n\r\n /**\r\n * If we find a new peer,\r\n * we tell everyone else.\r\n */\r\n this.pingPeers('NEW_PEER');\r\n promiseWait().then(() => this._resync$.next());\r\n return peer;\r\n }\r\n );\r\n\r\n if (!message.data.i) {\r\n peerInstance.signal(message.data);\r\n }\r\n });\r\n }\r\n\r\n close() {\r\n this.closed = true;\r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('online', this.resetReaderFn);\r\n window.removeEventListener('visibilitychange', this.resetReaderFn);\r\n }\r\n Array.from(this.peerBySenderId.values()).forEach(peer => peer.destroy())\r\n this._resync$.complete();\r\n }\r\n}\r\n\r\n\r\nexport async function readMessages(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n processedMessageIds: Set<string>\r\n): Promise<{ senderId: string; data: any }[]> {\r\n // ----------------------------\r\n // INLINE: readFolderById logic\r\n // ----------------------------\r\n const query = [\r\n `'${init.signalingFolderId}' in parents`,\r\n `trashed = false`\r\n // If you want to restrict to json only:\r\n // `mimeType = 'application/json'`\r\n // If you prefix signaling files:\r\n // `name contains 'sig__'`\r\n ].join(' and ');\r\n\r\n const fields = 'files(id,name,mimeType,createdTime,parents),nextPageToken';\r\n\r\n const params = new URLSearchParams();\r\n params.set('q', query);\r\n params.set('fields', fields);\r\n /**\r\n * Only fetch the \"newest\" page.\r\n * Later invert the order.\r\n */\r\n params.set('orderBy', 'createdTime desc');\r\n params.set('pageSize', '1000');\r\n\r\n const listUrl =\r\n googleDriveOptions.apiEndpoint +\r\n '/drive/v3/files?' +\r\n params.toString();\r\n\r\n const listResponse = await fetch(listUrl, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n\r\n if (!listResponse.ok) {\r\n throw await newRxFetchError(listResponse);\r\n }\r\n\r\n const listData = await listResponse.json();\r\n let folderData: DriveFileMetadata[] = listData.files || [];\r\n folderData = folderData.reverse();\r\n\r\n const useFiles = folderData.filter(file => {\r\n const messageId = messageIdByFilename(file.name);\r\n return !processedMessageIds.has(messageId);\r\n });\r\n\r\n const filesContent = await Promise.all(\r\n useFiles.map(async (file) => {\r\n const fileContent = await readJsonFileContent(\r\n googleDriveOptions,\r\n file.id\r\n );\r\n const senderId = file.name.split('_')[0];\r\n return {\r\n senderId,\r\n data: fileContent.content\r\n };\r\n })\r\n );\r\n\r\n /**\r\n * Do this afterwards so we can retry on errors without losing messages.\r\n * (No need for async map here.)\r\n */\r\n useFiles.forEach((file) => {\r\n const messageId = messageIdByFilename(file.name);\r\n processedMessageIds.add(messageId);\r\n });\r\n\r\n\r\n\r\n return filesContent;\r\n}\r\n\r\n\r\n\r\nfunction messageIdByFilename(name: string): string {\r\n const fileName = name.split('.')[0];\r\n const messageId = ensureNotFalsy(lastOfArray(fileName.split('_')));\r\n return messageId;\r\n}\r\n\r\nconst DEFAULT_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 1 day\r\n\r\nexport async function cleanupOldSignalingMessages(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n signalingFolderId: string,\r\n maxAgeMs: number = DEFAULT_MAX_AGE_MS\r\n): Promise<number> {\r\n return 2;\r\n\r\n const cutoffDate = new Date(Date.now() - maxAgeMs).toISOString();\r\n\r\n // Hardcoded folderId + query parts (Drive will do the filtering server-side)\r\n const query = [\r\n `'${signalingFolderId}' in parents`,\r\n `trashed = false`,\r\n `mimeType = 'application/json'`,\r\n `createdTime < '${cutoffDate}'`,\r\n // Recommended if folder may contain other JSON:\r\n // `name contains 'sig__'`\r\n ].join(' and ');\r\n\r\n // Hardcoded fields for cleanup\r\n const fields = 'files(id,name,createdTime),nextPageToken';\r\n\r\n const params = new URLSearchParams();\r\n params.set('q', query);\r\n params.set('fields', fields);\r\n params.set('orderBy', 'createdTime asc');\r\n params.set('pageSize', '1000');\r\n\r\n const url =\r\n googleDriveOptions.apiEndpoint +\r\n '/drive/v3/files?' +\r\n params.toString();\r\n\r\n const listResponse = await fetch(url, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n\r\n if (!listResponse.ok) {\r\n throw await newRxFetchError(listResponse);\r\n }\r\n\r\n const listData = await listResponse.json();\r\n const oldFiles: DriveFileMetadata[] = listData.files || [];\r\n\r\n if (!oldFiles.length) {\r\n return 0;\r\n }\r\n\r\n await Promise.all(\r\n oldFiles.map(file =>\r\n deleteFile(googleDriveOptions, file.id).catch(() => { })\r\n )\r\n );\r\n\r\n return oldFiles.length;\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"signaling.js","names":["_simplePeer","_interopRequireDefault","require","_connectionHandlerSimplePeer","_index","_googleDriveHelper","_rxjs","_rxError","BACKOFF_STEPS","MAX_BACKOFF_STEP_ID","length","SignalingState","exports","googleDriveOptions","init","signalingOptions","sessionId","randomToken","processedMessageIds","Set","_resync$","Subject","resync$","asObservable","peerBySenderId","Map","processQueue","PROMISE_RESOLVE_VOID","backoffStepId","closed","resetReaderFn","resetReadLoop","ensureProcessNextTickIsSet","cleanupOldSignalingMessages","signalingFolderId","catch","sendMessage","i","processNewMessages","window","addEventListener","document","time","skippable","promiseWaitSkippable","skipBackoffTime","skip","promise","_proto","prototype","data","messageId","fileName","now","join","add","insertMultipartFile","pingPeers","message","Array","from","values","forEach","peer","connected","send","then","_processNewMessages","messages","readMessages","next","senderId","peerInstance","getFromMapOrCreate","_Peer","initiator","trickle","wrtc","config","on","signalData","dataBuffer","console","error","delete","promiseWait","signal","close","removeEventListener","destroy","complete","query","fields","params","URLSearchParams","set","listUrl","apiEndpoint","toString","listResponse","fetch","method","headers","Authorization","authToken","ok","newRxFetchError","listData","json","folderData","files","reverse","useFiles","filter","file","messageIdByFilename","name","has","filesContent","Promise","all","map","fileContent","readJsonFileContent","id","split","content","ensureNotFalsy","lastOfArray","DEFAULT_MAX_AGE_MS","maxAgeMs","cutoffDate","Date","toISOString","url","oldFiles","deleteFile"],"sources":["../../../../src/plugins/replication-google-drive/signaling.ts"],"sourcesContent":["import type {\r\n Instance as SimplePeerInstance\r\n} from 'simple-peer';\r\nimport _Peer from 'simple-peer';\r\nimport {\r\n ensureProcessNextTickIsSet,\r\n SimplePeerConfig,\r\n SimplePeerWrtc\r\n} from '../replication-webrtc/connection-handler-simple-peer';\r\nimport {\r\n ensureNotFalsy,\r\n getFromMapOrCreate,\r\n lastOfArray,\r\n now,\r\n PROMISE_RESOLVE_VOID,\r\n promiseWait,\r\n promiseWaitSkippable,\r\n randomToken\r\n} from '../utils/index.ts';\r\nimport { DriveStructure } from './init.ts';\r\nimport {\r\n DriveFileMetadata,\r\n GoogleDriveOptionsWithDefaults\r\n} from './google-drive-types.ts';\r\nimport {\r\n deleteFile,\r\n insertMultipartFile,\r\n readJsonFileContent\r\n} from './google-drive-helper.ts';\r\nimport { Subject } from 'rxjs';\r\nimport { newRxFetchError } from '../../rx-error.ts';\r\n\r\n\r\nexport type SignalingOptions = {\r\n wrtc?: SimplePeerWrtc;\r\n config?: SimplePeerConfig;\r\n};\r\n\r\n/**\r\n * Timings on when to call the google drive\r\n * api to check for new messages.\r\n */\r\nconst BACKOFF_STEPS = [\r\n 50,\r\n 50,\r\n 100,\r\n 100,\r\n 200,\r\n 400,\r\n 600,\r\n 1_000,\r\n 2_000,\r\n 4_000,\r\n 8_000,\r\n 15_000,\r\n 30_000,\r\n 60_000,\r\n 120_000\r\n];\r\nconst MAX_BACKOFF_STEP_ID = BACKOFF_STEPS.length - 1;\r\n\r\n\r\nexport type SIGNAL = 'RESYNC' | 'NEW_PEER';\r\n\r\nexport class SignalingState {\r\n public readonly sessionId = randomToken(12);\r\n public readonly processedMessageIds = new Set<string>();\r\n\r\n /**\r\n * Emits whenever a new connection\r\n * is there or some connection\r\n * told us to RESYNC\r\n */\r\n private _resync$ = new Subject<void>();\r\n public resync$ = this._resync$.asObservable();\r\n\r\n public peerBySenderId = new Map<string, SimplePeerInstance>();\r\n\r\n private processQueue: Promise<any> = PROMISE_RESOLVE_VOID;\r\n private backoffStepId = 0;\r\n private skipBackoffTime?: () => void;\r\n\r\n\r\n public closed = false;\r\n public resetReaderFn = () => {\r\n this.resetReadLoop();\r\n };\r\n\r\n constructor(\r\n private googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n private init: DriveStructure,\r\n private signalingOptions: SignalingOptions\r\n ) {\r\n ensureProcessNextTickIsSet();\r\n cleanupOldSignalingMessages(\r\n this.googleDriveOptions,\r\n this.init.signalingFolderId\r\n ).catch(() => { });\r\n\r\n // Send \"i exist\" message\r\n this.sendMessage({ i: 'exist' });\r\n this.processNewMessages();\r\n\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('online', this.resetReaderFn);\r\n document.addEventListener('visibilitychange', this.resetReaderFn);\r\n\r\n }\r\n\r\n // start processing loop\r\n (async () => {\r\n while (!this.closed) {\r\n const time = BACKOFF_STEPS[this.backoffStepId];\r\n await this.processNewMessages();\r\n const skippable = promiseWaitSkippable(time);\r\n this.skipBackoffTime = skippable.skip;\r\n await skippable.promise;\r\n this.backoffStepId = this.backoffStepId + 1;\r\n if (this.backoffStepId > MAX_BACKOFF_STEP_ID) {\r\n this.backoffStepId = MAX_BACKOFF_STEP_ID;\r\n }\r\n }\r\n })();\r\n }\r\n\r\n async sendMessage(data: any) {\r\n const messageId = randomToken(12);\r\n const fileName = [\r\n this.sessionId,\r\n now(),\r\n messageId\r\n ].join('_') + '.json';\r\n\r\n // add here so we skip these\r\n this.processedMessageIds.add(messageId);\r\n\r\n await insertMultipartFile(\r\n this.googleDriveOptions,\r\n this.init.signalingFolderId,\r\n fileName,\r\n data\r\n );\r\n }\r\n\r\n async pingPeers(message: SIGNAL) {\r\n Array.from(this.peerBySenderId.values()).forEach(peer => {\r\n if (peer.connected) {\r\n peer.send(message);\r\n }\r\n });\r\n }\r\n\r\n\r\n async resetReadLoop() {\r\n await this.processNewMessages();\r\n this.backoffStepId = 0;\r\n if (this.skipBackoffTime) {\r\n this.skipBackoffTime();\r\n }\r\n }\r\n\r\n async processNewMessages() {\r\n this.processQueue = this.processQueue.then(\r\n () => this._processNewMessages().catch(() => { })\r\n );\r\n return this.processQueue;\r\n }\r\n\r\n async _processNewMessages() {\r\n const messages = await readMessages(\r\n this.googleDriveOptions,\r\n this.init,\r\n this.processedMessageIds\r\n );\r\n if (messages.length > 0) {\r\n this._resync$.next();\r\n }\r\n messages.forEach(message => {\r\n const senderId = message.senderId;\r\n if (senderId === this.sessionId) {\r\n return;\r\n }\r\n let peerInstance: SimplePeerInstance;\r\n\r\n peerInstance = getFromMapOrCreate(\r\n this.peerBySenderId,\r\n senderId,\r\n () => {\r\n const peer = new _Peer({\r\n initiator: senderId > this.sessionId,\r\n trickle: true,\r\n wrtc: this.signalingOptions.wrtc,\r\n config: this.signalingOptions.config\r\n })\r\n peer.on(\"signal\", async (signalData: any) => {\r\n await this.sendMessage(signalData);\r\n });\r\n peer.on('connect', () => {\r\n this._resync$.next();\r\n peer.send('RESYNC');\r\n });\r\n peer.on('data', (dataBuffer: any) => {\r\n const data = dataBuffer + '';\r\n switch (data) {\r\n case 'NEW_PEER':\r\n this.resetReadLoop();\r\n break;\r\n case 'RESYNC':\r\n this._resync$.next();\r\n break;\r\n default:\r\n console.error('Signaling UNKNOWN DATA ' + data);\r\n }\r\n });\r\n peer.on('error', () => {\r\n this._resync$.next();\r\n });\r\n peer.on('close', () => {\r\n this.peerBySenderId.delete(senderId);\r\n this._resync$.next();\r\n });\r\n\r\n\r\n /**\r\n * If we find a new peer,\r\n * we tell everyone else.\r\n */\r\n this.pingPeers('NEW_PEER');\r\n promiseWait().then(() => this._resync$.next());\r\n return peer;\r\n }\r\n );\r\n\r\n if (!message.data.i) {\r\n peerInstance.signal(message.data);\r\n }\r\n });\r\n }\r\n\r\n close() {\r\n this.closed = true;\r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('online', this.resetReaderFn);\r\n window.removeEventListener('visibilitychange', this.resetReaderFn);\r\n }\r\n Array.from(this.peerBySenderId.values()).forEach(peer => peer.destroy())\r\n this._resync$.complete();\r\n }\r\n}\r\n\r\n\r\nexport async function readMessages(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n processedMessageIds: Set<string>\r\n): Promise<{ senderId: string; data: any }[]> {\r\n // ----------------------------\r\n // INLINE: readFolderById logic\r\n // ----------------------------\r\n const query = [\r\n `'${init.signalingFolderId}' in parents`,\r\n `trashed = false`\r\n // If you want to restrict to json only:\r\n // `mimeType = 'application/json'`\r\n // If you prefix signaling files:\r\n // `name contains 'sig__'`\r\n ].join(' and ');\r\n\r\n const fields = 'files(id,name,mimeType,createdTime,parents),nextPageToken';\r\n\r\n const params = new URLSearchParams();\r\n params.set('q', query);\r\n params.set('fields', fields);\r\n /**\r\n * Only fetch the \"newest\" page.\r\n * Later invert the order.\r\n */\r\n params.set('orderBy', 'createdTime desc');\r\n params.set('pageSize', '1000');\r\n\r\n const listUrl =\r\n googleDriveOptions.apiEndpoint +\r\n '/drive/v3/files?' +\r\n params.toString();\r\n\r\n const listResponse = await fetch(listUrl, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n\r\n if (!listResponse.ok) {\r\n throw await newRxFetchError(listResponse);\r\n }\r\n\r\n const listData = await listResponse.json();\r\n let folderData: DriveFileMetadata[] = listData.files || [];\r\n folderData = folderData.reverse();\r\n\r\n const useFiles = folderData.filter(file => {\r\n const messageId = messageIdByFilename(file.name);\r\n return !processedMessageIds.has(messageId);\r\n });\r\n\r\n const filesContent = await Promise.all(\r\n useFiles.map(async (file) => {\r\n const fileContent = await readJsonFileContent(\r\n googleDriveOptions,\r\n file.id\r\n );\r\n const senderId = file.name.split('_')[0];\r\n return {\r\n senderId,\r\n data: fileContent.content\r\n };\r\n })\r\n );\r\n\r\n /**\r\n * Do this afterwards so we can retry on errors without losing messages.\r\n * (No need for async map here.)\r\n */\r\n useFiles.forEach((file) => {\r\n const messageId = messageIdByFilename(file.name);\r\n processedMessageIds.add(messageId);\r\n });\r\n\r\n\r\n\r\n return filesContent;\r\n}\r\n\r\n\r\n\r\nfunction messageIdByFilename(name: string): string {\r\n const fileName = name.split('.')[0];\r\n const messageId = ensureNotFalsy(lastOfArray(fileName.split('_')));\r\n return messageId;\r\n}\r\n\r\nconst DEFAULT_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 1 day\r\n\r\nexport async function cleanupOldSignalingMessages(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n signalingFolderId: string,\r\n maxAgeMs: number = DEFAULT_MAX_AGE_MS\r\n): Promise<number> {\r\n return 2;\r\n\r\n const cutoffDate = new Date(Date.now() - maxAgeMs).toISOString();\r\n\r\n // Hardcoded folderId + query parts (Drive will do the filtering server-side)\r\n const query = [\r\n `'${signalingFolderId}' in parents`,\r\n `trashed = false`,\r\n `mimeType = 'application/json'`,\r\n `createdTime < '${cutoffDate}'`,\r\n // Recommended if folder may contain other JSON:\r\n // `name contains 'sig__'`\r\n ].join(' and ');\r\n\r\n // Hardcoded fields for cleanup\r\n const fields = 'files(id,name,createdTime),nextPageToken';\r\n\r\n const params = new URLSearchParams();\r\n params.set('q', query);\r\n params.set('fields', fields);\r\n params.set('orderBy', 'createdTime asc');\r\n params.set('pageSize', '1000');\r\n\r\n const url =\r\n googleDriveOptions.apiEndpoint +\r\n '/drive/v3/files?' +\r\n params.toString();\r\n\r\n const listResponse = await fetch(url, {\r\n method: 'GET',\r\n headers: {\r\n Authorization: 'Bearer ' + googleDriveOptions.authToken\r\n }\r\n });\r\n\r\n if (!listResponse.ok) {\r\n throw await newRxFetchError(listResponse);\r\n }\r\n\r\n const listData = await listResponse.json();\r\n const oldFiles: DriveFileMetadata[] = listData.files || [];\r\n\r\n if (!oldFiles.length) {\r\n return 0;\r\n }\r\n\r\n await Promise.all(\r\n oldFiles.map(file =>\r\n deleteFile(googleDriveOptions, file.id).catch(() => { })\r\n )\r\n );\r\n\r\n return oldFiles.length;\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -153,23 +153,26 @@ async function processWalFile(googleDriveOptions, init, primaryPath) {
|
|
|
153
153
|
}
|
|
154
154
|
var docIds = content.rows.map(row => row.newDocumentState[primaryPath]);
|
|
155
155
|
var docFiles = await (0, _documentHandling.getDocumentFiles)(googleDriveOptions, init, docIds);
|
|
156
|
-
var
|
|
156
|
+
var fileMetaByDocId = {};
|
|
157
157
|
docFiles.files.forEach(file => {
|
|
158
158
|
var docId = file.name.split('.')[0];
|
|
159
|
-
|
|
159
|
+
fileMetaByDocId[docId] = {
|
|
160
|
+
fileId: file.id,
|
|
161
|
+
etag: (0, _index.ensureNotFalsy)(file.etag)
|
|
162
|
+
};
|
|
160
163
|
});
|
|
161
164
|
var toInsert = [];
|
|
162
165
|
var toUpdate = [];
|
|
163
166
|
content.rows.filter(row => {
|
|
164
167
|
var docId = row.newDocumentState[primaryPath];
|
|
165
|
-
var fileExists =
|
|
168
|
+
var fileExists = fileMetaByDocId[docId];
|
|
166
169
|
if (!fileExists) {
|
|
167
170
|
toInsert.push(row.newDocumentState);
|
|
168
171
|
} else {
|
|
169
172
|
toUpdate.push(row.newDocumentState);
|
|
170
173
|
}
|
|
171
174
|
});
|
|
172
|
-
await Promise.all([(0, _documentHandling.insertDocumentFiles)(googleDriveOptions, init, primaryPath, toInsert), (0, _documentHandling.updateDocumentFiles)(googleDriveOptions, primaryPath, toUpdate,
|
|
175
|
+
await Promise.all([(0, _documentHandling.insertDocumentFiles)(googleDriveOptions, init, primaryPath, toInsert), (0, _documentHandling.updateDocumentFiles)(googleDriveOptions, primaryPath, toUpdate, fileMetaByDocId)]);
|
|
173
176
|
|
|
174
177
|
// overwrite wal with emptyness
|
|
175
178
|
await writeToWal(googleDriveOptions, init, undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upstream.js","names":["_rxError","require","_index","_documentHandling","_googleDriveHelper","WAL_FILE_NAME","exports","fetchConflicts","googleDriveOptions","init","primaryPath","writeRows","length","DRIVE_MAX_BULK_SIZE","newRxError","args","ids","map","row","newDocumentState","filesMeta","getDocumentFiles","fileIdByDocId","Map","fileIds","files","f","fileId","ensureNotFalsy","id","docId","name","split","set","contentsByFileId","fetchDocumentContents","conflicts","nonConflicts","forEach","fileContent","get","byId","assumedMasterState","deepEqual","push","pushRows","writeToWal","walFileId","walFile","metaUrl","apiEndpoint","encodeURIComponent","URLSearchParams","fields","supportsAllDrives","toString","metaRes","fetch","method","headers","Authorization","authToken","ok","newRxFetchError","meta","json","sizeStr","fileSize","sizeNum","Number","size","etag","writeResult","fillFileIfEtagMatches","status","readWalContent","contentUrl","res","text","trim","rows","undefined","JSON","parse","processWalFile","content","docIds","docFiles","file","toInsert","toUpdate","filter","fileExists","Promise","all","insertDocumentFiles","updateDocumentFiles","handleUpstreamBatch","conflictResult"],"sources":["../../../../src/plugins/replication-google-drive/upstream.ts"],"sourcesContent":["import { RxReplicationWriteToMasterRow, WithDeletedAndAttachments } from '../../index.ts';\r\nimport { newRxError, newRxFetchError } from '../../rx-error.ts';\r\nimport { deepEqual, ensureNotFalsy } from '../utils/index.ts';\r\nimport { fetchDocumentContents, getDocumentFiles, insertDocumentFiles, updateDocumentFiles } from './document-handling.ts';\r\nimport { DRIVE_MAX_BULK_SIZE, fillFileIfEtagMatches } from './google-drive-helper.ts';\r\nimport type {\r\n DriveFileMetadata,\r\n GoogleDriveOptionsWithDefaults\r\n} from './google-drive-types';\r\nimport { DriveStructure } from './init.ts';\r\nimport { commitTransaction, startTransaction } from './transaction.ts';\r\n\r\nexport const WAL_FILE_NAME = 'rxdb-wal.json';\r\n\r\nexport async function fetchConflicts<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n primaryPath: keyof WithDeletedAndAttachments<RxDocType>,\r\n writeRows: RxReplicationWriteToMasterRow<RxDocType>[]\r\n) {\r\n if (writeRows.length > DRIVE_MAX_BULK_SIZE) {\r\n throw newRxError('GDR18', {\r\n args: {\r\n DRIVE_MAX_BULK_SIZE\r\n }\r\n });\r\n }\r\n\r\n const ids = writeRows.map(row => (row.newDocumentState as any)[primaryPath]);\r\n const filesMeta = await getDocumentFiles(\r\n googleDriveOptions,\r\n init,\r\n ids as string[]\r\n );\r\n const fileIdByDocId = new Map<string, string>();\r\n const fileIds: string[] = filesMeta.files.map((f) => {\r\n const fileId = ensureNotFalsy(f.id);\r\n const docId = f.name.split('.')[0];\r\n fileIdByDocId.set(docId, fileId);\r\n return fileId;\r\n });\r\n const contentsByFileId = await fetchDocumentContents<WithDeletedAndAttachments<RxDocType>>(\r\n googleDriveOptions,\r\n fileIds\r\n );\r\n\r\n const conflicts: WithDeletedAndAttachments<RxDocType>[] = [];\r\n const nonConflicts: RxReplicationWriteToMasterRow<RxDocType>[] = [];\r\n writeRows.forEach(row => {\r\n const docId = (row.newDocumentState as any)[primaryPath];\r\n let fileContent: undefined | WithDeletedAndAttachments<RxDocType>;\r\n const fileId = fileIdByDocId.get(docId);\r\n if (fileId) {\r\n fileContent = contentsByFileId.byId[fileId];\r\n }\r\n if (row.assumedMasterState) {\r\n if (!deepEqual(row.assumedMasterState, fileContent)) {\r\n conflicts.push(ensureNotFalsy(fileContent));\r\n } else {\r\n nonConflicts.push(row);\r\n }\r\n } else if (fileContent) {\r\n conflicts.push(fileContent);\r\n } else {\r\n nonConflicts.push(row);\r\n }\r\n });\r\n\r\n if ((nonConflicts.length + conflicts.length) !== writeRows.length) {\r\n throw newRxError('SNH', {\r\n pushRows: writeRows,\r\n args: {\r\n nonConflicts,\r\n conflicts,\r\n contentsByFileId: contentsByFileId.byId\r\n }\r\n });\r\n }\r\n\r\n return {\r\n conflicts,\r\n nonConflicts\r\n };\r\n}\r\n\r\nexport async function writeToWal<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n writeRows?: RxReplicationWriteToMasterRow<RxDocType>[]\r\n) {\r\n const walFileId = init.walFile.fileId;\r\n\r\n const metaUrl =\r\n googleDriveOptions.apiEndpoint +\r\n `/drive/v2/files/${encodeURIComponent(walFileId)}?` +\r\n new URLSearchParams({\r\n fields: \"id,fileSize,mimeType,title,etag\",\r\n supportsAllDrives: \"true\"\r\n }).toString();\r\n const metaRes = await fetch(metaUrl, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n if (!metaRes.ok) {\r\n throw await newRxFetchError(metaRes);\r\n }\r\n const meta: DriveFileMetadata = await metaRes.json();\r\n const sizeStr = meta.fileSize ?? \"0\";\r\n const sizeNum = Number(sizeStr);\r\n if (writeRows && (!meta.fileSize || sizeNum > 0)) {\r\n throw newRxError(\"GDR19\", {\r\n args: {\r\n sizeNum,\r\n walFileId,\r\n size: meta.size,\r\n meta,\r\n writeRows: writeRows?.length\r\n }\r\n });\r\n }\r\n\r\n const etag = ensureNotFalsy(metaRes.headers.get(\"etag\"), 'etag missing');\r\n const writeResult = await fillFileIfEtagMatches(\r\n googleDriveOptions,\r\n walFileId,\r\n etag,\r\n writeRows\r\n );\r\n if (writeResult.status !== 200) {\r\n throw newRxError(\"GDR19\", {\r\n args: {\r\n walFileId,\r\n meta,\r\n writeRows: writeRows?.length\r\n }\r\n });\r\n }\r\n}\r\n\r\n\r\nexport async function readWalContent<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n): Promise<{\r\n etag: string;\r\n rows: RxReplicationWriteToMasterRow<RxDocType>[] | undefined;\r\n}> {\r\n const walFileId = init.walFile.fileId;\r\n const contentUrl =\r\n googleDriveOptions.apiEndpoint +\r\n `/drive/v2/files/${encodeURIComponent(walFileId)}?alt=media`;\r\n\r\n const res = await fetch(contentUrl, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res);\r\n }\r\n const etag = ensureNotFalsy(\r\n res.headers.get(\"etag\"),\r\n \"etag missing on WAL read\"\r\n );\r\n\r\n const text = await res.text();\r\n\r\n // If empty or whitespace → no WAL entries\r\n if (!text || !text.trim()) {\r\n return {\r\n etag,\r\n rows: undefined\r\n };\r\n }\r\n\r\n return {\r\n etag,\r\n rows: JSON.parse(text) as RxReplicationWriteToMasterRow<RxDocType>[]\r\n };\r\n}\r\n\r\n\r\n/**\r\n * Here we read the WAL file content\r\n * and sort the content into the actual\r\n * document files.\r\n * Notice that when the JavaScript process\r\n * exists at any point here, we need to have\r\n * a recoverable state on the next run. So this\r\n * must be idempotent.\r\n */\r\nexport async function processWalFile<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n primaryPath: keyof RxDocType\r\n) {\r\n const content = await readWalContent<RxDocType>(\r\n googleDriveOptions,\r\n init\r\n );\r\n if (!content.rows) {\r\n return;\r\n }\r\n\r\n\r\n const docIds = content.rows.map(row => row.newDocumentState[primaryPath]);\r\n const docFiles = await getDocumentFiles(\r\n googleDriveOptions,\r\n init,\r\n docIds as string[]\r\n );\r\n const fileIdByDocId: Record<string, string> = {};\r\n\r\n docFiles.files.forEach(file => {\r\n const docId = file.name.split('.')[0] as any;\r\n fileIdByDocId[docId] = file.id;\r\n });\r\n\r\n const toInsert: WithDeletedAndAttachments<RxDocType>[] = [];\r\n const toUpdate: WithDeletedAndAttachments<RxDocType>[] = [];\r\n content.rows.filter(row => {\r\n const docId = row.newDocumentState[primaryPath];\r\n const fileExists = fileIdByDocId[docId as any];\r\n if (!fileExists) {\r\n toInsert.push(row.newDocumentState);\r\n } else {\r\n toUpdate.push(row.newDocumentState);\r\n }\r\n });\r\n\r\n await Promise.all([\r\n insertDocumentFiles(\r\n googleDriveOptions,\r\n init,\r\n primaryPath,\r\n toInsert\r\n ),\r\n updateDocumentFiles(\r\n googleDriveOptions,\r\n primaryPath,\r\n toUpdate,\r\n fileIdByDocId,\r\n )\r\n ]);\r\n\r\n\r\n // overwrite wal with emptyness\r\n await writeToWal(\r\n googleDriveOptions,\r\n init,\r\n undefined\r\n );\r\n\r\n}\r\n\r\nexport async function handleUpstreamBatch<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n primaryPath: keyof WithDeletedAndAttachments<RxDocType>,\r\n writeRows: RxReplicationWriteToMasterRow<RxDocType>[]\r\n): Promise<WithDeletedAndAttachments<RxDocType>[]> {\r\n const conflictResult = await fetchConflicts(\r\n googleDriveOptions,\r\n init,\r\n primaryPath,\r\n writeRows\r\n );\r\n await writeToWal(\r\n googleDriveOptions,\r\n init,\r\n conflictResult.nonConflicts\r\n );\r\n\r\n return conflictResult.conflicts;\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"upstream.js","names":["_rxError","require","_index","_documentHandling","_googleDriveHelper","WAL_FILE_NAME","exports","fetchConflicts","googleDriveOptions","init","primaryPath","writeRows","length","DRIVE_MAX_BULK_SIZE","newRxError","args","ids","map","row","newDocumentState","filesMeta","getDocumentFiles","fileIdByDocId","Map","fileIds","files","f","fileId","ensureNotFalsy","id","docId","name","split","set","contentsByFileId","fetchDocumentContents","conflicts","nonConflicts","forEach","fileContent","get","byId","assumedMasterState","deepEqual","push","pushRows","writeToWal","walFileId","walFile","metaUrl","apiEndpoint","encodeURIComponent","URLSearchParams","fields","supportsAllDrives","toString","metaRes","fetch","method","headers","Authorization","authToken","ok","newRxFetchError","meta","json","sizeStr","fileSize","sizeNum","Number","size","etag","writeResult","fillFileIfEtagMatches","status","readWalContent","contentUrl","res","text","trim","rows","undefined","JSON","parse","processWalFile","content","docIds","docFiles","fileMetaByDocId","file","toInsert","toUpdate","filter","fileExists","Promise","all","insertDocumentFiles","updateDocumentFiles","handleUpstreamBatch","conflictResult"],"sources":["../../../../src/plugins/replication-google-drive/upstream.ts"],"sourcesContent":["import { RxReplicationWriteToMasterRow, WithDeletedAndAttachments } from '../../index.ts';\r\nimport { newRxError, newRxFetchError } from '../../rx-error.ts';\r\nimport { deepEqual, ensureNotFalsy } from '../utils/index.ts';\r\nimport { fetchDocumentContents, getDocumentFiles, insertDocumentFiles, updateDocumentFiles } from './document-handling.ts';\r\nimport { DRIVE_MAX_BULK_SIZE, fillFileIfEtagMatches } from './google-drive-helper.ts';\r\nimport type {\r\n DriveFileMetadata,\r\n GoogleDriveOptionsWithDefaults\r\n} from './google-drive-types';\r\nimport { DriveStructure } from './init.ts';\r\nimport { commitTransaction, startTransaction } from './transaction.ts';\r\n\r\nexport const WAL_FILE_NAME = 'rxdb-wal.json';\r\n\r\nexport async function fetchConflicts<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n primaryPath: keyof WithDeletedAndAttachments<RxDocType>,\r\n writeRows: RxReplicationWriteToMasterRow<RxDocType>[]\r\n) {\r\n if (writeRows.length > DRIVE_MAX_BULK_SIZE) {\r\n throw newRxError('GDR18', {\r\n args: {\r\n DRIVE_MAX_BULK_SIZE\r\n }\r\n });\r\n }\r\n\r\n const ids = writeRows.map(row => (row.newDocumentState as any)[primaryPath]);\r\n const filesMeta = await getDocumentFiles(\r\n googleDriveOptions,\r\n init,\r\n ids as string[]\r\n );\r\n const fileIdByDocId = new Map<string, string>();\r\n const fileIds: string[] = filesMeta.files.map((f) => {\r\n const fileId = ensureNotFalsy(f.id);\r\n const docId = f.name.split('.')[0];\r\n fileIdByDocId.set(docId, fileId);\r\n return fileId;\r\n });\r\n const contentsByFileId = await fetchDocumentContents<WithDeletedAndAttachments<RxDocType>>(\r\n googleDriveOptions,\r\n fileIds\r\n );\r\n\r\n const conflicts: WithDeletedAndAttachments<RxDocType>[] = [];\r\n const nonConflicts: RxReplicationWriteToMasterRow<RxDocType>[] = [];\r\n writeRows.forEach(row => {\r\n const docId = (row.newDocumentState as any)[primaryPath];\r\n let fileContent: undefined | WithDeletedAndAttachments<RxDocType>;\r\n const fileId = fileIdByDocId.get(docId);\r\n if (fileId) {\r\n fileContent = contentsByFileId.byId[fileId];\r\n }\r\n if (row.assumedMasterState) {\r\n if (!deepEqual(row.assumedMasterState, fileContent)) {\r\n conflicts.push(ensureNotFalsy(fileContent));\r\n } else {\r\n nonConflicts.push(row);\r\n }\r\n } else if (fileContent) {\r\n conflicts.push(fileContent);\r\n } else {\r\n nonConflicts.push(row);\r\n }\r\n });\r\n\r\n if ((nonConflicts.length + conflicts.length) !== writeRows.length) {\r\n throw newRxError('SNH', {\r\n pushRows: writeRows,\r\n args: {\r\n nonConflicts,\r\n conflicts,\r\n contentsByFileId: contentsByFileId.byId\r\n }\r\n });\r\n }\r\n\r\n return {\r\n conflicts,\r\n nonConflicts\r\n };\r\n}\r\n\r\nexport async function writeToWal<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n writeRows?: RxReplicationWriteToMasterRow<RxDocType>[]\r\n) {\r\n const walFileId = init.walFile.fileId;\r\n\r\n const metaUrl =\r\n googleDriveOptions.apiEndpoint +\r\n `/drive/v2/files/${encodeURIComponent(walFileId)}?` +\r\n new URLSearchParams({\r\n fields: \"id,fileSize,mimeType,title,etag\",\r\n supportsAllDrives: \"true\"\r\n }).toString();\r\n const metaRes = await fetch(metaUrl, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n if (!metaRes.ok) {\r\n throw await newRxFetchError(metaRes);\r\n }\r\n const meta: DriveFileMetadata = await metaRes.json();\r\n const sizeStr = meta.fileSize ?? \"0\";\r\n const sizeNum = Number(sizeStr);\r\n if (writeRows && (!meta.fileSize || sizeNum > 0)) {\r\n throw newRxError(\"GDR19\", {\r\n args: {\r\n sizeNum,\r\n walFileId,\r\n size: meta.size,\r\n meta,\r\n writeRows: writeRows?.length\r\n }\r\n });\r\n }\r\n\r\n const etag = ensureNotFalsy(metaRes.headers.get(\"etag\"), 'etag missing');\r\n const writeResult = await fillFileIfEtagMatches(\r\n googleDriveOptions,\r\n walFileId,\r\n etag,\r\n writeRows\r\n );\r\n if (writeResult.status !== 200) {\r\n throw newRxError(\"GDR19\", {\r\n args: {\r\n walFileId,\r\n meta,\r\n writeRows: writeRows?.length\r\n }\r\n });\r\n }\r\n}\r\n\r\n\r\nexport async function readWalContent<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n): Promise<{\r\n etag: string;\r\n rows: RxReplicationWriteToMasterRow<RxDocType>[] | undefined;\r\n}> {\r\n const walFileId = init.walFile.fileId;\r\n const contentUrl =\r\n googleDriveOptions.apiEndpoint +\r\n `/drive/v2/files/${encodeURIComponent(walFileId)}?alt=media`;\r\n\r\n const res = await fetch(contentUrl, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${googleDriveOptions.authToken}`,\r\n },\r\n });\r\n\r\n if (!res.ok) {\r\n throw await newRxFetchError(res);\r\n }\r\n const etag = ensureNotFalsy(\r\n res.headers.get(\"etag\"),\r\n \"etag missing on WAL read\"\r\n );\r\n\r\n const text = await res.text();\r\n\r\n // If empty or whitespace → no WAL entries\r\n if (!text || !text.trim()) {\r\n return {\r\n etag,\r\n rows: undefined\r\n };\r\n }\r\n\r\n return {\r\n etag,\r\n rows: JSON.parse(text) as RxReplicationWriteToMasterRow<RxDocType>[]\r\n };\r\n}\r\n\r\n\r\n/**\r\n * Here we read the WAL file content\r\n * and sort the content into the actual\r\n * document files.\r\n * Notice that when the JavaScript process\r\n * exists at any point here, we need to have\r\n * a recoverable state on the next run. So this\r\n * must be idempotent.\r\n */\r\nexport async function processWalFile<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n primaryPath: keyof RxDocType\r\n) {\r\n const content = await readWalContent<RxDocType>(\r\n googleDriveOptions,\r\n init\r\n );\r\n if (!content.rows) {\r\n return;\r\n }\r\n\r\n\r\n const docIds = content.rows.map(row => row.newDocumentState[primaryPath]);\r\n const docFiles = await getDocumentFiles(\r\n googleDriveOptions,\r\n init,\r\n docIds as string[]\r\n );\r\n const fileMetaByDocId: Record<string, { fileId: string; etag: string }> = {};\r\n\r\n docFiles.files.forEach(file => {\r\n const docId = file.name.split('.')[0] as any;\r\n fileMetaByDocId[docId] = {\r\n fileId: file.id,\r\n etag: ensureNotFalsy(file.etag),\r\n };\r\n });\r\n\r\n const toInsert: WithDeletedAndAttachments<RxDocType>[] = [];\r\n const toUpdate: WithDeletedAndAttachments<RxDocType>[] = [];\r\n content.rows.filter(row => {\r\n const docId = row.newDocumentState[primaryPath];\r\n const fileExists = fileMetaByDocId[docId as any];\r\n if (!fileExists) {\r\n toInsert.push(row.newDocumentState);\r\n } else {\r\n toUpdate.push(row.newDocumentState);\r\n }\r\n });\r\n\r\n await Promise.all([\r\n insertDocumentFiles(\r\n googleDriveOptions,\r\n init,\r\n primaryPath,\r\n toInsert\r\n ),\r\n updateDocumentFiles(\r\n googleDriveOptions,\r\n primaryPath,\r\n toUpdate,\r\n fileMetaByDocId,\r\n )\r\n ]);\r\n\r\n\r\n // overwrite wal with emptyness\r\n await writeToWal(\r\n googleDriveOptions,\r\n init,\r\n undefined\r\n );\r\n\r\n}\r\n\r\nexport async function handleUpstreamBatch<RxDocType>(\r\n googleDriveOptions: GoogleDriveOptionsWithDefaults,\r\n init: DriveStructure,\r\n primaryPath: keyof WithDeletedAndAttachments<RxDocType>,\r\n writeRows: RxReplicationWriteToMasterRow<RxDocType>[]\r\n): Promise<WithDeletedAndAttachments<RxDocType>[]> {\r\n const conflictResult = await fetchConflicts(\r\n googleDriveOptions,\r\n init,\r\n primaryPath,\r\n writeRows\r\n );\r\n await writeToWal(\r\n googleDriveOptions,\r\n init,\r\n conflictResult.nonConflicts\r\n );\r\n\r\n return conflictResult.conflicts;\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -95,7 +95,9 @@ var SignalingState = exports.SignalingState = /*#__PURE__*/function () {
|
|
|
95
95
|
};
|
|
96
96
|
_proto.pingPeers = async function pingPeers(message) {
|
|
97
97
|
Array.from(this.peerBySenderId.values()).forEach(peer => {
|
|
98
|
-
peer.
|
|
98
|
+
if (peer.connected) {
|
|
99
|
+
peer.send(message);
|
|
100
|
+
}
|
|
99
101
|
});
|
|
100
102
|
};
|
|
101
103
|
_proto.resetReadLoop = async function resetReadLoop() {
|
|
@@ -132,6 +134,7 @@ var SignalingState = exports.SignalingState = /*#__PURE__*/function () {
|
|
|
132
134
|
});
|
|
133
135
|
peer.on('connect', () => {
|
|
134
136
|
this._resync$.next();
|
|
137
|
+
peer.send('RESYNC');
|
|
135
138
|
});
|
|
136
139
|
peer.on('data', dataBuffer => {
|
|
137
140
|
var data = dataBuffer + '';
|