@connecttomahdi/rxdb 17.0.0-beta.17 → 17.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (379) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +47 -4
  3. package/CLAUDE.md +2 -0
  4. package/dist/cjs/change-event-buffer.js +2 -1
  5. package/dist/cjs/change-event-buffer.js.map +1 -1
  6. package/dist/cjs/custom-index.js +85 -12
  7. package/dist/cjs/custom-index.js.map +1 -1
  8. package/dist/cjs/doc-cache.js +117 -35
  9. package/dist/cjs/doc-cache.js.map +1 -1
  10. package/dist/cjs/event-reduce.js +10 -1
  11. package/dist/cjs/event-reduce.js.map +1 -1
  12. package/dist/cjs/plugin-helpers.js +16 -0
  13. package/dist/cjs/plugin-helpers.js.map +1 -1
  14. package/dist/cjs/plugins/attachments/index.js +3 -3
  15. package/dist/cjs/plugins/attachments/index.js.map +1 -1
  16. package/dist/cjs/plugins/cleanup/cleanup.js +5 -3
  17. package/dist/cjs/plugins/cleanup/cleanup.js.map +1 -1
  18. package/dist/cjs/plugins/crdt/index.js +52 -0
  19. package/dist/cjs/plugins/crdt/index.js.map +1 -1
  20. package/dist/cjs/plugins/dev-mode/check-query.js +7 -1
  21. package/dist/cjs/plugins/dev-mode/check-query.js.map +1 -1
  22. package/dist/cjs/plugins/dev-mode/check-schema.js +2 -1
  23. package/dist/cjs/plugins/dev-mode/check-schema.js.map +1 -1
  24. package/dist/cjs/plugins/dev-mode/error-messages.js +43 -5
  25. package/dist/cjs/plugins/dev-mode/error-messages.js.map +1 -1
  26. package/dist/cjs/plugins/encryption-crypto-js/index.js +22 -6
  27. package/dist/cjs/plugins/encryption-crypto-js/index.js.map +1 -1
  28. package/dist/cjs/plugins/leader-election/index.js +5 -5
  29. package/dist/cjs/plugins/leader-election/index.js.map +1 -1
  30. package/dist/cjs/plugins/local-documents/local-documents.js +20 -13
  31. package/dist/cjs/plugins/local-documents/local-documents.js.map +1 -1
  32. package/dist/cjs/plugins/migration-schema/migration-helpers.js +3 -0
  33. package/dist/cjs/plugins/migration-schema/migration-helpers.js.map +1 -1
  34. package/dist/cjs/plugins/migration-schema/rx-migration-state.js +1 -1
  35. package/dist/cjs/plugins/migration-schema/rx-migration-state.js.map +1 -1
  36. package/dist/cjs/plugins/pipeline/rx-pipeline.js +5 -1
  37. package/dist/cjs/plugins/pipeline/rx-pipeline.js.map +1 -1
  38. package/dist/cjs/plugins/query-builder/mquery/nosql-query-builder.js +4 -2
  39. package/dist/cjs/plugins/query-builder/mquery/nosql-query-builder.js.map +1 -1
  40. package/dist/cjs/plugins/replication/index.js +40 -2
  41. package/dist/cjs/plugins/replication/index.js.map +1 -1
  42. package/dist/cjs/plugins/replication-google-drive/document-handling.js +17 -6
  43. package/dist/cjs/plugins/replication-google-drive/document-handling.js.map +1 -1
  44. package/dist/cjs/plugins/replication-google-drive/google-drive-helper.js +1 -1
  45. package/dist/cjs/plugins/replication-google-drive/google-drive-helper.js.map +1 -1
  46. package/dist/cjs/plugins/replication-google-drive/google-drive-types.js.map +1 -1
  47. package/dist/cjs/plugins/replication-google-drive/signaling.js +4 -1
  48. package/dist/cjs/plugins/replication-google-drive/signaling.js.map +1 -1
  49. package/dist/cjs/plugins/replication-google-drive/upstream.js +7 -4
  50. package/dist/cjs/plugins/replication-google-drive/upstream.js.map +1 -1
  51. package/dist/cjs/plugins/replication-microsoft-onedrive/signaling.js +4 -1
  52. package/dist/cjs/plugins/replication-microsoft-onedrive/signaling.js.map +1 -1
  53. package/dist/cjs/plugins/state/rx-state.js +14 -3
  54. package/dist/cjs/plugins/state/rx-state.js.map +1 -1
  55. package/dist/cjs/plugins/storage-dexie/rx-storage-instance-dexie.js +10 -17
  56. package/dist/cjs/plugins/storage-dexie/rx-storage-instance-dexie.js.map +1 -1
  57. package/dist/cjs/plugins/storage-memory/binary-search-bounds.js +112 -40
  58. package/dist/cjs/plugins/storage-memory/binary-search-bounds.js.map +1 -1
  59. package/dist/cjs/plugins/storage-memory/memory-helper.js +127 -40
  60. package/dist/cjs/plugins/storage-memory/memory-helper.js.map +1 -1
  61. package/dist/cjs/plugins/storage-memory/memory-indexes.js +1 -0
  62. package/dist/cjs/plugins/storage-memory/memory-indexes.js.map +1 -1
  63. package/dist/cjs/plugins/storage-memory/memory-types.js.map +1 -1
  64. package/dist/cjs/plugins/storage-memory/rx-storage-instance-memory.js +97 -37
  65. package/dist/cjs/plugins/storage-memory/rx-storage-instance-memory.js.map +1 -1
  66. package/dist/cjs/plugins/storage-mongodb/mongodb-helper.js +42 -1
  67. package/dist/cjs/plugins/storage-mongodb/mongodb-helper.js.map +1 -1
  68. package/dist/cjs/plugins/storage-mongodb/rx-storage-instance-mongodb.js +7 -7
  69. package/dist/cjs/plugins/storage-mongodb/rx-storage-instance-mongodb.js.map +1 -1
  70. package/dist/cjs/plugins/test-utils/config.js +1 -1
  71. package/dist/cjs/plugins/test-utils/config.js.map +1 -1
  72. package/dist/cjs/plugins/test-utils/performance.js +122 -92
  73. package/dist/cjs/plugins/test-utils/performance.js.map +1 -1
  74. package/dist/cjs/plugins/test-utils/schema-objects.js +1 -1
  75. package/dist/cjs/plugins/test-utils/schema-objects.js.map +1 -1
  76. package/dist/cjs/plugins/test-utils/test-util.js +62 -0
  77. package/dist/cjs/plugins/test-utils/test-util.js.map +1 -1
  78. package/dist/cjs/plugins/utils/utils-map.js +2 -2
  79. package/dist/cjs/plugins/utils/utils-map.js.map +1 -1
  80. package/dist/cjs/plugins/utils/utils-object-deep-equal.js +3 -2
  81. package/dist/cjs/plugins/utils/utils-object-deep-equal.js.map +1 -1
  82. package/dist/cjs/plugins/utils/utils-object-dot-prop.js +25 -0
  83. package/dist/cjs/plugins/utils/utils-object-dot-prop.js.map +1 -1
  84. package/dist/cjs/plugins/utils/utils-object.js +102 -27
  85. package/dist/cjs/plugins/utils/utils-object.js.map +1 -1
  86. package/dist/cjs/plugins/utils/utils-other.js +9 -4
  87. package/dist/cjs/plugins/utils/utils-other.js.map +1 -1
  88. package/dist/cjs/plugins/utils/utils-premium.js +1 -19
  89. package/dist/cjs/plugins/utils/utils-premium.js.map +1 -1
  90. package/dist/cjs/plugins/utils/utils-revision.js +20 -10
  91. package/dist/cjs/plugins/utils/utils-revision.js.map +1 -1
  92. package/dist/cjs/plugins/utils/utils-rxdb-version.js +1 -1
  93. package/dist/cjs/plugins/utils/utils-rxdb-version.js.map +1 -1
  94. package/dist/cjs/plugins/utils/utils-string.js +11 -8
  95. package/dist/cjs/plugins/utils/utils-string.js.map +1 -1
  96. package/dist/cjs/plugins/utils/utils-time.js +21 -16
  97. package/dist/cjs/plugins/utils/utils-time.js.map +1 -1
  98. package/dist/cjs/query-cache.js +6 -4
  99. package/dist/cjs/query-cache.js.map +1 -1
  100. package/dist/cjs/query-planner.js +2 -2
  101. package/dist/cjs/query-planner.js.map +1 -1
  102. package/dist/cjs/replication-protocol/downstream.js +1 -1
  103. package/dist/cjs/replication-protocol/downstream.js.map +1 -1
  104. package/dist/cjs/rx-collection-helper.js +11 -6
  105. package/dist/cjs/rx-collection-helper.js.map +1 -1
  106. package/dist/cjs/rx-collection.js +34 -6
  107. package/dist/cjs/rx-collection.js.map +1 -1
  108. package/dist/cjs/rx-database.js +40 -7
  109. package/dist/cjs/rx-database.js.map +1 -1
  110. package/dist/cjs/rx-document.js +10 -3
  111. package/dist/cjs/rx-document.js.map +1 -1
  112. package/dist/cjs/rx-query-helper.js +35 -12
  113. package/dist/cjs/rx-query-helper.js.map +1 -1
  114. package/dist/cjs/rx-query-single-result.js +9 -2
  115. package/dist/cjs/rx-query-single-result.js.map +1 -1
  116. package/dist/cjs/rx-query.js +72 -29
  117. package/dist/cjs/rx-query.js.map +1 -1
  118. package/dist/cjs/rx-schema-helper.js +9 -3
  119. package/dist/cjs/rx-schema-helper.js.map +1 -1
  120. package/dist/cjs/rx-schema.js +1 -0
  121. package/dist/cjs/rx-schema.js.map +1 -1
  122. package/dist/cjs/rx-storage-helper.js +212 -129
  123. package/dist/cjs/rx-storage-helper.js.map +1 -1
  124. package/dist/cjs/types/rx-error.d.js.map +1 -1
  125. package/dist/cjs/types/rx-schema.d.js.map +1 -1
  126. package/dist/esm/change-event-buffer.js +2 -1
  127. package/dist/esm/change-event-buffer.js.map +1 -1
  128. package/dist/esm/custom-index.js +85 -12
  129. package/dist/esm/custom-index.js.map +1 -1
  130. package/dist/esm/doc-cache.js +118 -36
  131. package/dist/esm/doc-cache.js.map +1 -1
  132. package/dist/esm/event-reduce.js +10 -1
  133. package/dist/esm/event-reduce.js.map +1 -1
  134. package/dist/esm/plugin-helpers.js +16 -0
  135. package/dist/esm/plugin-helpers.js.map +1 -1
  136. package/dist/esm/plugins/attachments/index.js +3 -3
  137. package/dist/esm/plugins/attachments/index.js.map +1 -1
  138. package/dist/esm/plugins/cleanup/cleanup.js +5 -3
  139. package/dist/esm/plugins/cleanup/cleanup.js.map +1 -1
  140. package/dist/esm/plugins/crdt/index.js +52 -0
  141. package/dist/esm/plugins/crdt/index.js.map +1 -1
  142. package/dist/esm/plugins/dev-mode/check-query.js +7 -1
  143. package/dist/esm/plugins/dev-mode/check-query.js.map +1 -1
  144. package/dist/esm/plugins/dev-mode/check-schema.js +2 -1
  145. package/dist/esm/plugins/dev-mode/check-schema.js.map +1 -1
  146. package/dist/esm/plugins/dev-mode/error-messages.js +43 -5
  147. package/dist/esm/plugins/dev-mode/error-messages.js.map +1 -1
  148. package/dist/esm/plugins/encryption-crypto-js/index.js +22 -6
  149. package/dist/esm/plugins/encryption-crypto-js/index.js.map +1 -1
  150. package/dist/esm/plugins/leader-election/index.js +4 -4
  151. package/dist/esm/plugins/leader-election/index.js.map +1 -1
  152. package/dist/esm/plugins/local-documents/local-documents.js +20 -13
  153. package/dist/esm/plugins/local-documents/local-documents.js.map +1 -1
  154. package/dist/esm/plugins/migration-schema/migration-helpers.js +3 -0
  155. package/dist/esm/plugins/migration-schema/migration-helpers.js.map +1 -1
  156. package/dist/esm/plugins/migration-schema/rx-migration-state.js +1 -1
  157. package/dist/esm/plugins/migration-schema/rx-migration-state.js.map +1 -1
  158. package/dist/esm/plugins/pipeline/rx-pipeline.js +5 -1
  159. package/dist/esm/plugins/pipeline/rx-pipeline.js.map +1 -1
  160. package/dist/esm/plugins/query-builder/mquery/nosql-query-builder.js +4 -2
  161. package/dist/esm/plugins/query-builder/mquery/nosql-query-builder.js.map +1 -1
  162. package/dist/esm/plugins/replication/index.js +40 -2
  163. package/dist/esm/plugins/replication/index.js.map +1 -1
  164. package/dist/esm/plugins/replication-google-drive/document-handling.js +17 -6
  165. package/dist/esm/plugins/replication-google-drive/document-handling.js.map +1 -1
  166. package/dist/esm/plugins/replication-google-drive/google-drive-helper.js +1 -1
  167. package/dist/esm/plugins/replication-google-drive/google-drive-helper.js.map +1 -1
  168. package/dist/esm/plugins/replication-google-drive/google-drive-types.js.map +1 -1
  169. package/dist/esm/plugins/replication-google-drive/signaling.js +4 -1
  170. package/dist/esm/plugins/replication-google-drive/signaling.js.map +1 -1
  171. package/dist/esm/plugins/replication-google-drive/upstream.js +7 -4
  172. package/dist/esm/plugins/replication-google-drive/upstream.js.map +1 -1
  173. package/dist/esm/plugins/replication-microsoft-onedrive/signaling.js +4 -1
  174. package/dist/esm/plugins/replication-microsoft-onedrive/signaling.js.map +1 -1
  175. package/dist/esm/plugins/state/rx-state.js +15 -4
  176. package/dist/esm/plugins/state/rx-state.js.map +1 -1
  177. package/dist/esm/plugins/storage-dexie/rx-storage-instance-dexie.js +11 -18
  178. package/dist/esm/plugins/storage-dexie/rx-storage-instance-dexie.js.map +1 -1
  179. package/dist/esm/plugins/storage-memory/binary-search-bounds.js +107 -40
  180. package/dist/esm/plugins/storage-memory/binary-search-bounds.js.map +1 -1
  181. package/dist/esm/plugins/storage-memory/memory-helper.js +128 -41
  182. package/dist/esm/plugins/storage-memory/memory-helper.js.map +1 -1
  183. package/dist/esm/plugins/storage-memory/memory-indexes.js +1 -0
  184. package/dist/esm/plugins/storage-memory/memory-indexes.js.map +1 -1
  185. package/dist/esm/plugins/storage-memory/memory-types.js.map +1 -1
  186. package/dist/esm/plugins/storage-memory/rx-storage-instance-memory.js +90 -30
  187. package/dist/esm/plugins/storage-memory/rx-storage-instance-memory.js.map +1 -1
  188. package/dist/esm/plugins/storage-mongodb/mongodb-helper.js +39 -0
  189. package/dist/esm/plugins/storage-mongodb/mongodb-helper.js.map +1 -1
  190. package/dist/esm/plugins/storage-mongodb/rx-storage-instance-mongodb.js +8 -8
  191. package/dist/esm/plugins/storage-mongodb/rx-storage-instance-mongodb.js.map +1 -1
  192. package/dist/esm/plugins/test-utils/config.js +1 -1
  193. package/dist/esm/plugins/test-utils/config.js.map +1 -1
  194. package/dist/esm/plugins/test-utils/performance.js +122 -92
  195. package/dist/esm/plugins/test-utils/performance.js.map +1 -1
  196. package/dist/esm/plugins/test-utils/schema-objects.js +1 -1
  197. package/dist/esm/plugins/test-utils/schema-objects.js.map +1 -1
  198. package/dist/esm/plugins/test-utils/test-util.js +59 -0
  199. package/dist/esm/plugins/test-utils/test-util.js.map +1 -1
  200. package/dist/esm/plugins/utils/utils-map.js +2 -2
  201. package/dist/esm/plugins/utils/utils-map.js.map +1 -1
  202. package/dist/esm/plugins/utils/utils-object-deep-equal.js +3 -2
  203. package/dist/esm/plugins/utils/utils-object-deep-equal.js.map +1 -1
  204. package/dist/esm/plugins/utils/utils-object-dot-prop.js +25 -0
  205. package/dist/esm/plugins/utils/utils-object-dot-prop.js.map +1 -1
  206. package/dist/esm/plugins/utils/utils-object.js +102 -27
  207. package/dist/esm/plugins/utils/utils-object.js.map +1 -1
  208. package/dist/esm/plugins/utils/utils-other.js +9 -4
  209. package/dist/esm/plugins/utils/utils-other.js.map +1 -1
  210. package/dist/esm/plugins/utils/utils-premium.js +1 -19
  211. package/dist/esm/plugins/utils/utils-premium.js.map +1 -1
  212. package/dist/esm/plugins/utils/utils-revision.js +20 -10
  213. package/dist/esm/plugins/utils/utils-revision.js.map +1 -1
  214. package/dist/esm/plugins/utils/utils-rxdb-version.js +1 -1
  215. package/dist/esm/plugins/utils/utils-rxdb-version.js.map +1 -1
  216. package/dist/esm/plugins/utils/utils-string.js +11 -8
  217. package/dist/esm/plugins/utils/utils-string.js.map +1 -1
  218. package/dist/esm/plugins/utils/utils-time.js +21 -16
  219. package/dist/esm/plugins/utils/utils-time.js.map +1 -1
  220. package/dist/esm/query-cache.js +7 -5
  221. package/dist/esm/query-cache.js.map +1 -1
  222. package/dist/esm/query-planner.js +2 -2
  223. package/dist/esm/query-planner.js.map +1 -1
  224. package/dist/esm/replication-protocol/downstream.js +1 -1
  225. package/dist/esm/replication-protocol/downstream.js.map +1 -1
  226. package/dist/esm/rx-collection-helper.js +12 -7
  227. package/dist/esm/rx-collection-helper.js.map +1 -1
  228. package/dist/esm/rx-collection.js +35 -7
  229. package/dist/esm/rx-collection.js.map +1 -1
  230. package/dist/esm/rx-database.js +40 -7
  231. package/dist/esm/rx-database.js.map +1 -1
  232. package/dist/esm/rx-document.js +11 -4
  233. package/dist/esm/rx-document.js.map +1 -1
  234. package/dist/esm/rx-query-helper.js +35 -12
  235. package/dist/esm/rx-query-helper.js.map +1 -1
  236. package/dist/esm/rx-query-single-result.js +10 -3
  237. package/dist/esm/rx-query-single-result.js.map +1 -1
  238. package/dist/esm/rx-query.js +72 -29
  239. package/dist/esm/rx-query.js.map +1 -1
  240. package/dist/esm/rx-schema-helper.js +9 -3
  241. package/dist/esm/rx-schema-helper.js.map +1 -1
  242. package/dist/esm/rx-schema.js +1 -0
  243. package/dist/esm/rx-schema.js.map +1 -1
  244. package/dist/esm/rx-storage-helper.js +176 -94
  245. package/dist/esm/rx-storage-helper.js.map +1 -1
  246. package/dist/esm/types/rx-error.d.js.map +1 -1
  247. package/dist/esm/types/rx-schema.d.js.map +1 -1
  248. package/dist/types/custom-index.d.ts +5 -0
  249. package/dist/types/doc-cache.d.ts +1 -1
  250. package/dist/types/index.d.ts +25 -26
  251. package/dist/types/plugins/dev-mode/error-messages.d.ts +36 -0
  252. package/dist/types/plugins/leader-election/index.d.ts +1 -0
  253. package/dist/types/plugins/replication-google-drive/document-handling.d.ts +4 -1
  254. package/dist/types/plugins/replication-google-drive/google-drive-types.d.ts +1 -0
  255. package/dist/types/plugins/state/rx-state.d.ts +1 -1
  256. package/dist/types/plugins/storage-denokv/index.d.ts +1 -1
  257. package/dist/types/plugins/storage-dexie/rx-storage-dexie.d.ts +1 -1
  258. package/dist/types/plugins/storage-localstorage/index.d.ts +1 -1
  259. package/dist/types/plugins/storage-memory/binary-search-bounds.d.ts +21 -10
  260. package/dist/types/plugins/storage-memory/memory-helper.d.ts +7 -3
  261. package/dist/types/plugins/storage-memory/memory-types.d.ts +5 -0
  262. package/dist/types/plugins/storage-mongodb/mongodb-helper.d.ts +9 -1
  263. package/dist/types/plugins/storage-mongodb/rx-storage-instance-mongodb.d.ts +2 -2
  264. package/dist/types/plugins/storage-mongodb/rx-storage-mongodb.d.ts +1 -1
  265. package/dist/types/plugins/storage-remote/rx-storage-remote.d.ts +1 -1
  266. package/dist/types/plugins/storage-sqlite/index.d.ts +1 -1
  267. package/dist/types/plugins/test-utils/performance.d.ts +36 -0
  268. package/dist/types/plugins/test-utils/test-util.d.ts +17 -0
  269. package/dist/types/plugins/utils/utils-object.d.ts +8 -3
  270. package/dist/types/plugins/utils/utils-premium.d.ts +0 -2
  271. package/dist/types/plugins/utils/utils-rxdb-version.d.ts +1 -1
  272. package/dist/types/rx-database.d.ts +1 -1
  273. package/dist/types/rx-query-single-result.d.ts +1 -1
  274. package/dist/types/rx-query.d.ts +3 -2
  275. package/dist/types/rx-storage-helper.d.ts +15 -0
  276. package/eslint.config.mjs +2 -1
  277. package/package.json +732 -729
  278. package/scripts/check-code-block-line-length.js +91 -0
  279. package/scripts/check-em-dashes.js +53 -0
  280. package/scripts/docs-fetch-git-history.mjs +36 -0
  281. package/scripts/install-foundationdb.sh +0 -6
  282. package/scripts/notify-indexnow.mjs +171 -0
  283. package/scripts/start-foundationdb-docker.sh +73 -0
  284. package/src/change-event-buffer.ts +4 -1
  285. package/src/custom-index.ts +93 -16
  286. package/src/doc-cache.ts +117 -41
  287. package/src/event-reduce.ts +10 -1
  288. package/src/plugin-helpers.ts +10 -0
  289. package/src/plugins/attachments/index.ts +10 -12
  290. package/src/plugins/cleanup/cleanup.ts +5 -3
  291. package/src/plugins/crdt/index.ts +55 -0
  292. package/src/plugins/dev-mode/check-query.ts +7 -1
  293. package/src/plugins/dev-mode/check-schema.ts +2 -1
  294. package/src/plugins/dev-mode/error-messages.ts +45 -5
  295. package/src/plugins/encryption-crypto-js/index.ts +18 -6
  296. package/src/plugins/leader-election/index.ts +9 -8
  297. package/src/plugins/local-documents/local-documents.ts +21 -12
  298. package/src/plugins/migration-schema/migration-helpers.ts +3 -0
  299. package/src/plugins/migration-schema/rx-migration-state.ts +1 -1
  300. package/src/plugins/pipeline/rx-pipeline.ts +5 -1
  301. package/src/plugins/query-builder/mquery/nosql-query-builder.ts +8 -2
  302. package/src/plugins/replication/index.ts +41 -3
  303. package/src/plugins/replication-google-drive/document-handling.ts +17 -5
  304. package/src/plugins/replication-google-drive/google-drive-helper.ts +1 -1
  305. package/src/plugins/replication-google-drive/google-drive-types.ts +1 -0
  306. package/src/plugins/replication-google-drive/signaling.ts +4 -1
  307. package/src/plugins/replication-google-drive/upstream.ts +7 -4
  308. package/src/plugins/replication-microsoft-onedrive/signaling.ts +4 -1
  309. package/src/plugins/state/rx-state.ts +17 -5
  310. package/src/plugins/storage-dexie/rx-storage-instance-dexie.ts +0 -27
  311. package/src/plugins/storage-memory/binary-search-bounds.ts +105 -40
  312. package/src/plugins/storage-memory/memory-helper.ts +158 -67
  313. package/src/plugins/storage-memory/memory-indexes.ts +1 -0
  314. package/src/plugins/storage-memory/memory-types.ts +5 -0
  315. package/src/plugins/storage-memory/rx-storage-instance-memory.ts +104 -53
  316. package/src/plugins/storage-mongodb/mongodb-helper.ts +43 -1
  317. package/src/plugins/storage-mongodb/rx-storage-instance-mongodb.ts +11 -9
  318. package/src/plugins/test-utils/config.ts +2 -1
  319. package/src/plugins/test-utils/performance.ts +159 -85
  320. package/src/plugins/test-utils/schema-objects.ts +1 -1
  321. package/src/plugins/test-utils/test-util.ts +71 -0
  322. package/src/plugins/utils/utils-map.ts +2 -2
  323. package/src/plugins/utils/utils-object-deep-equal.ts +2 -4
  324. package/src/plugins/utils/utils-object-dot-prop.ts +25 -0
  325. package/src/plugins/utils/utils-object.ts +103 -28
  326. package/src/plugins/utils/utils-other.ts +9 -4
  327. package/src/plugins/utils/utils-premium.ts +11 -37
  328. package/src/plugins/utils/utils-revision.ts +20 -9
  329. package/src/plugins/utils/utils-rxdb-version.ts +1 -1
  330. package/src/plugins/utils/utils-string.ts +11 -9
  331. package/src/plugins/utils/utils-time.ts +21 -17
  332. package/src/query-cache.ts +6 -5
  333. package/src/query-planner.ts +2 -2
  334. package/src/replication-protocol/downstream.ts +1 -1
  335. package/src/rx-collection-helper.ts +12 -6
  336. package/src/rx-collection.ts +39 -8
  337. package/src/rx-database.ts +49 -17
  338. package/src/rx-document.ts +12 -3
  339. package/src/rx-query-helper.ts +36 -15
  340. package/src/rx-query-single-result.ts +10 -3
  341. package/src/rx-query.ts +48 -8
  342. package/src/rx-schema-helper.ts +7 -4
  343. package/src/rx-schema.ts +1 -0
  344. package/src/rx-storage-helper.ts +210 -139
  345. package/src/types/rx-error.d.ts +3 -0
  346. package/src/types/rx-schema.d.ts +5 -0
  347. package/dist/esm/package.json +0 -1
  348. package/dist/types/types/conflict-handling.d.ts +0 -48
  349. package/dist/types/types/couchdb.d.ts +0 -293
  350. package/dist/types/types/index.d.ts +0 -32
  351. package/dist/types/types/modules/index.d.ts +0 -0
  352. package/dist/types/types/modules/mocha.parallel.d.ts +0 -1
  353. package/dist/types/types/plugins/backup.d.ts +0 -35
  354. package/dist/types/types/plugins/cleanup.d.ts +0 -38
  355. package/dist/types/types/plugins/crdt.d.ts +0 -76
  356. package/dist/types/types/plugins/dexie.d.ts +0 -30
  357. package/dist/types/types/plugins/local-documents.d.ts +0 -49
  358. package/dist/types/types/plugins/migration.d.ts +0 -14
  359. package/dist/types/types/plugins/reactivity.d.ts +0 -40
  360. package/dist/types/types/plugins/replication-graphql.d.ts +0 -98
  361. package/dist/types/types/plugins/replication.d.ts +0 -175
  362. package/dist/types/types/plugins/state.d.ts +0 -4
  363. package/dist/types/types/plugins/update.d.ts +0 -23
  364. package/dist/types/types/plugins/webmcp.d.ts +0 -40
  365. package/dist/types/types/query-planner.d.ts +0 -47
  366. package/dist/types/types/replication-protocol.d.ts +0 -296
  367. package/dist/types/types/rx-attachment.d.ts +0 -46
  368. package/dist/types/types/rx-change-event.d.ts +0 -85
  369. package/dist/types/types/rx-collection.d.ts +0 -117
  370. package/dist/types/types/rx-database-internal-store.d.ts +0 -54
  371. package/dist/types/types/rx-database.d.ts +0 -124
  372. package/dist/types/types/rx-document.d.ts +0 -160
  373. package/dist/types/types/rx-error.d.ts +0 -222
  374. package/dist/types/types/rx-plugin.d.ts +0 -167
  375. package/dist/types/types/rx-query.d.ts +0 -144
  376. package/dist/types/types/rx-schema.d.ts +0 -209
  377. package/dist/types/types/rx-storage.d.ts +0 -347
  378. package/dist/types/types/rx-storage.interface.d.ts +0 -312
  379. package/dist/types/types/util.d.ts +0 -180
@@ -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, fileIdByDocId, concurrency = 5) {
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 fileId = (0, _index.ensureNotFalsy)(fileIdByDocId[docId]);
82
- var url = googleDriveOptions.apiEndpoint + ("/upload/drive/v3/files/" + encodeURIComponent(fileId)) + "?uploadType=media&supportsAllDrives=true&fields=id";
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: "PATCH",
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.send(message);
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 fileIdByDocId = {};
156
+ var fileMetaByDocId = {};
157
157
  docFiles.files.forEach(file => {
158
158
  var docId = file.name.split('.')[0];
159
- fileIdByDocId[docId] = file.id;
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 = fileIdByDocId[docId];
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, fileIdByDocId)]);
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":";;;;;;;;;;;AACA,IAAAA,QAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,iBAAA,GAAAF,OAAA;AACA,IAAAG,kBAAA,GAAAH,OAAA;AAQO,IAAMI,aAAa,GAAAC,OAAA,CAAAD,aAAA,GAAG,eAAe;AAErC,eAAeE,cAAcA,CAChCC,kBAAkD,EAClDC,IAAoB,EACpBC,WAAuD,EACvDC,SAAqD,EACvD;EACE,IAAIA,SAAS,CAACC,MAAM,GAAGC,sCAAmB,EAAE;IACxC,MAAM,IAAAC,mBAAU,EAAC,OAAO,EAAE;MACtBC,IAAI,EAAE;QACFF,mBAAmB,EAAnBA;MACJ;IACJ,CAAC,CAAC;EACN;EAEA,IAAMG,GAAG,GAAGL,SAAS,CAACM,GAAG,CAACC,GAAG,IAAKA,GAAG,CAACC,gBAAgB,CAAST,WAAW,CAAC,CAAC;EAC5E,IAAMU,SAAS,GAAG,MAAM,IAAAC,kCAAgB,EACpCb,kBAAkB,EAClBC,IAAI,EACJO,GACJ,CAAC;EACD,IAAMM,aAAa,GAAG,IAAIC,GAAG,CAAiB,CAAC;EAC/C,IAAMC,OAAiB,GAAGJ,SAAS,CAACK,KAAK,CAACR,GAAG,CAAES,CAAC,IAAK;IACjD,IAAMC,MAAM,GAAG,IAAAC,qBAAc,EAACF,CAAC,CAACG,EAAE,CAAC;IACnC,IAAMC,KAAK,GAAGJ,CAAC,CAACK,IAAI,CAACC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClCV,aAAa,CAACW,GAAG,CAACH,KAAK,EAAEH,MAAM,CAAC;IAChC,OAAOA,MAAM;EACjB,CAAC,CAAC;EACF,IAAMO,gBAAgB,GAAG,MAAM,IAAAC,uCAAqB,EAChD3B,kBAAkB,EAClBgB,OACJ,CAAC;EAED,IAAMY,SAAiD,GAAG,EAAE;EAC5D,IAAMC,YAAwD,GAAG,EAAE;EACnE1B,SAAS,CAAC2B,OAAO,CAACpB,GAAG,IAAI;IACrB,IAAMY,KAAK,GAAIZ,GAAG,CAACC,gBAAgB,CAAST,WAAW,CAAC;IACxD,IAAI6B,WAA6D;IACjE,IAAMZ,MAAM,GAAGL,aAAa,CAACkB,GAAG,CAACV,KAAK,CAAC;IACvC,IAAIH,MAAM,EAAE;MACRY,WAAW,GAAGL,gBAAgB,CAACO,IAAI,CAACd,MAAM,CAAC;IAC/C;IACA,IAAIT,GAAG,CAACwB,kBAAkB,EAAE;MACxB,IAAI,CAAC,IAAAC,gBAAS,EAACzB,GAAG,CAACwB,kBAAkB,EAAEH,WAAW,CAAC,EAAE;QACjDH,SAAS,CAACQ,IAAI,CAAC,IAAAhB,qBAAc,EAACW,WAAW,CAAC,CAAC;MAC/C,CAAC,MAAM;QACHF,YAAY,CAACO,IAAI,CAAC1B,GAAG,CAAC;MAC1B;IACJ,CAAC,MAAM,IAAIqB,WAAW,EAAE;MACpBH,SAAS,CAACQ,IAAI,CAACL,WAAW,CAAC;IAC/B,CAAC,MAAM;MACHF,YAAY,CAACO,IAAI,CAAC1B,GAAG,CAAC;IAC1B;EACJ,CAAC,CAAC;EAEF,IAAKmB,YAAY,CAACzB,MAAM,GAAGwB,SAAS,CAACxB,MAAM,KAAMD,SAAS,CAACC,MAAM,EAAE;IAC/D,MAAM,IAAAE,mBAAU,EAAC,KAAK,EAAE;MACpB+B,QAAQ,EAAElC,SAAS;MACnBI,IAAI,EAAE;QACFsB,YAAY;QACZD,SAAS;QACTF,gBAAgB,EAAEA,gBAAgB,CAACO;MACvC;IACJ,CAAC,CAAC;EACN;EAEA,OAAO;IACHL,SAAS;IACTC;EACJ,CAAC;AACL;AAEO,eAAeS,UAAUA,CAC5BtC,kBAAkD,EAClDC,IAAoB,EACpBE,SAAsD,EACxD;EACE,IAAMoC,SAAS,GAAGtC,IAAI,CAACuC,OAAO,CAACrB,MAAM;EAErC,IAAMsB,OAAO,GACTzC,kBAAkB,CAAC0C,WAAW,yBACXC,kBAAkB,CAACJ,SAAS,CAAC,OAAG,GACnD,IAAIK,eAAe,CAAC;IAChBC,MAAM,EAAE,iCAAiC;IACzCC,iBAAiB,EAAE;EACvB,CAAC,CAAC,CAACC,QAAQ,CAAC,CAAC;EACjB,IAAMC,OAAO,GAAG,MAAMC,KAAK,CAACR,OAAO,EAAE;IACjCS,MAAM,EAAE,KAAK;IACbC,OAAO,EAAE;MACLC,aAAa,cAAYpD,kBAAkB,CAACqD;IAChD;EACJ,CAAC,CAAC;EACF,IAAI,CAACL,OAAO,CAACM,EAAE,EAAE;IACb,MAAM,MAAM,IAAAC,wBAAe,EAACP,OAAO,CAAC;EACxC;EACA,IAAMQ,IAAuB,GAAG,MAAMR,OAAO,CAACS,IAAI,CAAC,CAAC;EACpD,IAAMC,OAAO,GAAGF,IAAI,CAACG,QAAQ,IAAI,GAAG;EACpC,IAAMC,OAAO,GAAGC,MAAM,CAACH,OAAO,CAAC;EAC/B,IAAIvD,SAAS,KAAK,CAACqD,IAAI,CAACG,QAAQ,IAAIC,OAAO,GAAG,CAAC,CAAC,EAAE;IAC9C,MAAM,IAAAtD,mBAAU,EAAC,OAAO,EAAE;MACtBC,IAAI,EAAE;QACFqD,OAAO;QACPrB,SAAS;QACTuB,IAAI,EAAEN,IAAI,CAACM,IAAI;QACfN,IAAI;QACJrD,SAAS,EAAEA,SAAS,EAAEC;MAC1B;IACJ,CAAC,CAAC;EACN;EAEA,IAAM2D,IAAI,GAAG,IAAA3C,qBAAc,EAAC4B,OAAO,CAACG,OAAO,CAACnB,GAAG,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;EACxE,IAAMgC,WAAW,GAAG,MAAM,IAAAC,wCAAqB,EAC3CjE,kBAAkB,EAClBuC,SAAS,EACTwB,IAAI,EACJ5D,SACJ,CAAC;EACD,IAAI6D,WAAW,CAACE,MAAM,KAAK,GAAG,EAAE;IAC5B,MAAM,IAAA5D,mBAAU,EAAC,OAAO,EAAE;MACtBC,IAAI,EAAE;QACFgC,SAAS;QACTiB,IAAI;QACJrD,SAAS,EAAEA,SAAS,EAAEC;MAC1B;IACJ,CAAC,CAAC;EACN;AACJ;AAGO,eAAe+D,cAAcA,CAChCnE,kBAAkD,EAClDC,IAAoB,EAIrB;EACC,IAAMsC,SAAS,GAAGtC,IAAI,CAACuC,OAAO,CAACrB,MAAM;EACrC,IAAMiD,UAAU,GACZpE,kBAAkB,CAAC0C,WAAW,yBACXC,kBAAkB,CAACJ,SAAS,CAAC,gBAAY;EAEhE,IAAM8B,GAAG,GAAG,MAAMpB,KAAK,CAACmB,UAAU,EAAE;IAChClB,MAAM,EAAE,KAAK;IACbC,OAAO,EAAE;MACLC,aAAa,cAAYpD,kBAAkB,CAACqD;IAChD;EACJ,CAAC,CAAC;EAEF,IAAI,CAACgB,GAAG,CAACf,EAAE,EAAE;IACT,MAAM,MAAM,IAAAC,wBAAe,EAACc,GAAG,CAAC;EACpC;EACA,IAAMN,IAAI,GAAG,IAAA3C,qBAAc,EACvBiD,GAAG,CAAClB,OAAO,CAACnB,GAAG,CAAC,MAAM,CAAC,EACvB,0BACJ,CAAC;EAED,IAAMsC,IAAI,GAAG,MAAMD,GAAG,CAACC,IAAI,CAAC,CAAC;;EAE7B;EACA,IAAI,CAACA,IAAI,IAAI,CAACA,IAAI,CAACC,IAAI,CAAC,CAAC,EAAE;IACvB,OAAO;MACHR,IAAI;MACJS,IAAI,EAAEC;IACV,CAAC;EACL;EAEA,OAAO;IACHV,IAAI;IACJS,IAAI,EAAEE,IAAI,CAACC,KAAK,CAACL,IAAI;EACzB,CAAC;AACL;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAeM,cAAcA,CAChC5E,kBAAkD,EAClDC,IAAoB,EACpBC,WAA4B,EAC9B;EACE,IAAM2E,OAAO,GAAG,MAAMV,cAAc,CAChCnE,kBAAkB,EAClBC,IACJ,CAAC;EACD,IAAI,CAAC4E,OAAO,CAACL,IAAI,EAAE;IACf;EACJ;EAGA,IAAMM,MAAM,GAAGD,OAAO,CAACL,IAAI,CAAC/D,GAAG,CAACC,GAAG,IAAIA,GAAG,CAACC,gBAAgB,CAACT,WAAW,CAAC,CAAC;EACzE,IAAM6E,QAAQ,GAAG,MAAM,IAAAlE,kCAAgB,EACnCb,kBAAkB,EAClBC,IAAI,EACJ6E,MACJ,CAAC;EACD,IAAMhE,aAAqC,GAAG,CAAC,CAAC;EAEhDiE,QAAQ,CAAC9D,KAAK,CAACa,OAAO,CAACkD,IAAI,IAAI;IAC3B,IAAM1D,KAAK,GAAG0D,IAAI,CAACzD,IAAI,CAACC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAQ;IAC5CV,aAAa,CAACQ,KAAK,CAAC,GAAG0D,IAAI,CAAC3D,EAAE;EAClC,CAAC,CAAC;EAEF,IAAM4D,QAAgD,GAAG,EAAE;EAC3D,IAAMC,QAAgD,GAAG,EAAE;EAC3DL,OAAO,CAACL,IAAI,CAACW,MAAM,CAACzE,GAAG,IAAI;IACvB,IAAMY,KAAK,GAAGZ,GAAG,CAACC,gBAAgB,CAACT,WAAW,CAAC;IAC/C,IAAMkF,UAAU,GAAGtE,aAAa,CAACQ,KAAK,CAAQ;IAC9C,IAAI,CAAC8D,UAAU,EAAE;MACbH,QAAQ,CAAC7C,IAAI,CAAC1B,GAAG,CAACC,gBAAgB,CAAC;IACvC,CAAC,MAAM;MACHuE,QAAQ,CAAC9C,IAAI,CAAC1B,GAAG,CAACC,gBAAgB,CAAC;IACvC;EACJ,CAAC,CAAC;EAEF,MAAM0E,OAAO,CAACC,GAAG,CAAC,CACd,IAAAC,qCAAmB,EACfvF,kBAAkB,EAClBC,IAAI,EACJC,WAAW,EACX+E,QACJ,CAAC,EACD,IAAAO,qCAAmB,EACfxF,kBAAkB,EAClBE,WAAW,EACXgF,QAAQ,EACRpE,aACJ,CAAC,CACJ,CAAC;;EAGF;EACA,MAAMwB,UAAU,CACZtC,kBAAkB,EAClBC,IAAI,EACJwE,SACJ,CAAC;AAEL;AAEO,eAAegB,mBAAmBA,CACrCzF,kBAAkD,EAClDC,IAAoB,EACpBC,WAAuD,EACvDC,SAAqD,EACN;EAC/C,IAAMuF,cAAc,GAAG,MAAM3F,cAAc,CACvCC,kBAAkB,EAClBC,IAAI,EACJC,WAAW,EACXC,SACJ,CAAC;EACD,MAAMmC,UAAU,CACZtC,kBAAkB,EAClBC,IAAI,EACJyF,cAAc,CAAC7D,YACnB,CAAC;EAED,OAAO6D,cAAc,CAAC9D,SAAS;AACnC","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.send(message);
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 + '';