@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
@@ -31,7 +31,19 @@ export function deepFreeze<T>(o: T): T {
31
31
  * and we can reuse the generated function.
32
32
  */
33
33
  export type ObjectPathMonadFunction<T, R = any> = (obj: T) => R;
34
+
35
+ /**
36
+ * Cache for objectPathMonad to avoid re-creating closures
37
+ * and re-splitting strings for the same paths.
38
+ */
39
+ const objectPathMonadCache = new Map<string, ObjectPathMonadFunction<any>>();
40
+
34
41
  export function objectPathMonad<T, R = any>(objectPath: string): ObjectPathMonadFunction<T, R> {
42
+ let fn = objectPathMonadCache.get(objectPath);
43
+ if (fn) {
44
+ return fn;
45
+ }
46
+
35
47
  const split = objectPath.split('.');
36
48
 
37
49
  // reuse this variable for better performance.
@@ -43,21 +55,84 @@ export function objectPathMonad<T, R = any>(objectPath: string): ObjectPathMonad
43
55
  * directly return the field of the object.
44
56
  */
45
57
  if (splitLength === 1) {
46
- return (obj: T) => (obj as any)[objectPath];
58
+ fn = (obj: T) => (obj as any)[objectPath];
59
+ } else if (splitLength === 2) {
60
+ /**
61
+ * Fast path for 2-segment paths (e.g. 'nested.field').
62
+ * Avoids the loop overhead for the most common nested case.
63
+ */
64
+ const key0 = split[0];
65
+ const key1 = split[1];
66
+ fn = (obj: T) => {
67
+ const v = (obj as any)[key0];
68
+ return v === undefined ? v : v[key1];
69
+ };
70
+ } else if (splitLength === 3) {
71
+ /**
72
+ * Fast path for 3-segment paths (e.g. 'deep.deeper.deepNr').
73
+ * Common in index fields and nested document properties.
74
+ */
75
+ const key0 = split[0];
76
+ const key1 = split[1];
77
+ const key2 = split[2];
78
+ fn = (obj: T) => {
79
+ const v = (obj as any)[key0];
80
+ if (v === undefined) return v;
81
+ const v2 = v[key1];
82
+ return v2 === undefined ? v2 : v2[key2];
83
+ };
84
+ } else if (splitLength === 4) {
85
+ /**
86
+ * Fast path for 4-segment paths.
87
+ * Avoids loop overhead for deeper nested properties.
88
+ */
89
+ const key0 = split[0];
90
+ const key1 = split[1];
91
+ const key2 = split[2];
92
+ const key3 = split[3];
93
+ fn = (obj: T) => {
94
+ const v = (obj as any)[key0];
95
+ if (v === undefined) return v;
96
+ const v2 = v[key1];
97
+ if (v2 === undefined) return v2;
98
+ const v3 = v2[key2];
99
+ return v3 === undefined ? v3 : v3[key3];
100
+ };
101
+ } else if (splitLength === 5) {
102
+ /**
103
+ * Fast path for 5-segment paths.
104
+ * Avoids loop overhead for deeply nested properties.
105
+ */
106
+ const key0 = split[0];
107
+ const key1 = split[1];
108
+ const key2 = split[2];
109
+ const key3 = split[3];
110
+ const key4 = split[4];
111
+ fn = (obj: T) => {
112
+ const v = (obj as any)[key0];
113
+ if (v === undefined) return v;
114
+ const v2 = v[key1];
115
+ if (v2 === undefined) return v2;
116
+ const v3 = v2[key2];
117
+ if (v3 === undefined) return v3;
118
+ const v4 = v3[key3];
119
+ return v4 === undefined ? v4 : v4[key4];
120
+ };
121
+ } else {
122
+ fn = (obj: T) => {
123
+ let currentVal: any = obj;
124
+ for (let i = 0; i < splitLength; ++i) {
125
+ currentVal = currentVal[split[i]];
126
+ if (currentVal === undefined) {
127
+ return currentVal;
128
+ }
129
+ }
130
+ return currentVal;
131
+ };
47
132
  }
48
133
 
49
-
50
- return (obj: T) => {
51
- let currentVal: any = obj;
52
- for (let i = 0; i < splitLength; ++i) {
53
- const subPath = split[i];
54
- currentVal = currentVal[subPath];
55
- if (typeof currentVal === 'undefined') {
56
- return currentVal;
57
- }
58
- }
59
- return currentVal;
60
- };
134
+ objectPathMonadCache.set(objectPath, fn);
135
+ return fn;
61
136
  }
62
137
 
63
138
 
@@ -97,11 +172,12 @@ export function flattenObject(ob: any) {
97
172
 
98
173
  /**
99
174
  * does a flat copy on the objects,
100
- * is about 3 times faster than using deepClone
101
- * @link https://jsperf.com/object-rest-spread-vs-clone/2
175
+ * is about 3 times faster than using deepClone.
176
+ * Using the spread operator instead of Object.assign
177
+ * because V8 optimizes spread for plain objects (~4x faster).
102
178
  */
103
179
  export function flatClone<T>(obj: T | DeepReadonlyObject<T> | Readonly<T>): T {
104
- return Object.assign({}, obj) as any;
180
+ return { ...obj } as any;
105
181
  }
106
182
 
107
183
  /**
@@ -164,16 +240,9 @@ export function sortObject(obj: any, noArraySort = false): any {
164
240
  * @link https://github.com/zxdong262/deep-copy/blob/master/src/index.ts
165
241
  */
166
242
  function deepClone<T>(src: T | DeepReadonlyObject<T>): T {
167
- if (!src) {
168
- return src;
169
- }
170
- if (src === null || typeof (src) !== 'object') {
243
+ if (!src || typeof src !== 'object') {
171
244
  return src;
172
245
  }
173
- // Blobs are immutable — pass through without cloning, otherwise it gets converted into a normal object, which breaks things.
174
- if (typeof Blob !== 'undefined' && src instanceof Blob) {
175
- return src as any;
176
- }
177
246
  if (Array.isArray(src)) {
178
247
  const ret = new Array(src.length);
179
248
  let i = ret.length;
@@ -182,6 +251,10 @@ function deepClone<T>(src: T | DeepReadonlyObject<T>): T {
182
251
  }
183
252
  return ret as any;
184
253
  }
254
+ // Blobs are immutable — pass through without cloning, otherwise it gets converted into a normal object, which breaks things.
255
+ if (typeof Blob !== 'undefined' && src instanceof Blob) {
256
+ return src as any;
257
+ }
185
258
  const dest: any = {};
186
259
  // eslint-disable-next-line guard-for-in
187
260
  for (const key in src) {
@@ -195,7 +268,11 @@ export const clone = deepClone;
195
268
 
196
269
  /**
197
270
  * overwrites the getter with the actual value
198
- * Mostly used for caching stuff on the first run
271
+ * Mostly used for caching stuff on the first run.
272
+ *
273
+ * Using a value descriptor instead of a getter descriptor
274
+ * so that subsequent property accesses are direct value lookups
275
+ * instead of function calls, which is ~37% faster for reads.
199
276
  */
200
277
  export function overwriteGetterForCaching<ValueType = any>(
201
278
  obj: any,
@@ -203,9 +280,7 @@ export function overwriteGetterForCaching<ValueType = any>(
203
280
  value: ValueType
204
281
  ): ValueType {
205
282
  Object.defineProperty(obj, getterName, {
206
- get: function () {
207
- return value;
208
- }
283
+ value
209
284
  });
210
285
  return value;
211
286
  }
@@ -2,12 +2,17 @@ export function runXTimes(xTimes: number, fn: (idx: number) => void) {
2
2
  new Array(xTimes).fill(0).forEach((_v, idx) => fn(idx));
3
3
  }
4
4
 
5
+ /**
6
+ * Move the throw into a separate function
7
+ * so that V8 can better inline the main ensureNotFalsy function.
8
+ */
9
+ function ensureNotFalsyThrow(message?: string): never {
10
+ throw new Error('ensureNotFalsy() is falsy: ' + (message || ''));
11
+ }
12
+
5
13
  export function ensureNotFalsy<T>(obj: T | false | undefined | null, message?: string): T {
6
14
  if (!obj) {
7
- if (!message) {
8
- message = '';
9
- }
10
- throw new Error('ensureNotFalsy() is falsy: ' + message);
15
+ ensureNotFalsyThrow(message);
11
16
  }
12
17
  return obj;
13
18
  }
@@ -1,37 +1,11 @@
1
- import { RXDB_UTILS_GLOBAL } from './utils-global.ts';
2
- import { defaultHashSha256 } from './utils-hash.ts';
3
- import { PROMISE_RESOLVE_FALSE } from './utils-promise.ts';
4
-
5
- export const PREMIUM_FLAG_HASH = '6da4936d1425ff3a5c44c02342c6daf791d266be3ae8479b8ec59e261df41b93';
6
- export const NON_PREMIUM_COLLECTION_LIMIT = 999;
7
-
8
- let hasPremiumPromise: Promise<boolean> = PROMISE_RESOLVE_FALSE;
9
- let premiumChecked = false;
10
-
11
- /**
12
- * Here we check if the premium flag has been set.
13
- * This code exists in the open source version of RxDB.
14
- * Yes you are allowed to fork the repo and just overwrite this function.
15
- * However you might better spend this time developing your real project
16
- * and supporting the RxDB efforts by buying premium.
17
- */
18
- export async function hasPremiumFlag() {
19
- if (premiumChecked) {
20
- return hasPremiumPromise;
21
- }
22
- premiumChecked = true;
23
-
24
- hasPremiumPromise = (async () => {
25
- if (
26
- RXDB_UTILS_GLOBAL.premium &&
27
- typeof RXDB_UTILS_GLOBAL.premium === 'string' &&
28
- (await defaultHashSha256(RXDB_UTILS_GLOBAL.premium) === PREMIUM_FLAG_HASH)
29
- ) {
30
- return true;
31
- } else {
32
- return false;
33
- }
34
- })();
35
-
36
- return hasPremiumPromise;
37
- }
1
+ export const PREMIUM_FLAG_HASH = '6da4936d1425ff3a5c44c02342c6daf791d266be3ae8479b8ec59e261df41b93';
2
+ export const NON_PREMIUM_COLLECTION_LIMIT = 999;
3
+
4
+ /**
5
+ * Here we check if the premium flag has been set.
6
+ * This code exists in the open source version of RxDB.
7
+ * Yes you are allowed to fork the repo and just overwrite this function.
8
+ */
9
+ export async function hasPremiumFlag() {
10
+ return true;
11
+ }
@@ -9,13 +9,22 @@ import { newRxError } from '../../rx-error.ts';
9
9
  * then use getHeightOfRevision() instead which is faster.
10
10
  */
11
11
  export function parseRevision(revision: string): { height: number; hash: string; } {
12
- const split = revision.split('-');
13
- if (split.length !== 2) {
12
+ const dashIndex = revision.indexOf('-');
13
+ if (dashIndex === -1) {
14
14
  throw new Error('malformatted revision: ' + revision);
15
15
  }
16
+ let height: number;
17
+ if (dashIndex === 1) {
18
+ height = revision.charCodeAt(0) - 48;
19
+ } else {
20
+ height = 0;
21
+ for (let i = 0; i < dashIndex; i++) {
22
+ height = height * 10 + (revision.charCodeAt(i) - 48);
23
+ }
24
+ }
16
25
  return {
17
- height: parseInt(split[0], 10),
18
- hash: split[1]
26
+ height,
27
+ hash: revision.substring(dashIndex + 1)
19
28
  };
20
29
  }
21
30
 
@@ -33,12 +42,14 @@ export function getHeightOfRevision(revision: string): number {
33
42
  }
34
43
  // Fast path for single-digit revision heights (most common case)
35
44
  if (dashIndex === 1) {
36
- const code = revision.charCodeAt(0);
37
- if (code >= 48 && code <= 57) { // '0'-'9'
38
- return code - 48;
39
- }
45
+ return revision.charCodeAt(0) - 48;
46
+ }
47
+ // Manual number parsing for multi-digit heights (avoids parseInt + substring)
48
+ let num = 0;
49
+ for (let i = 0; i < dashIndex; i++) {
50
+ num = num * 10 + (revision.charCodeAt(i) - 48);
40
51
  }
41
- return parseInt(revision.substring(0, dashIndex), 10);
52
+ return num;
42
53
  }
43
54
 
44
55
 
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * This file is replaced in the 'npm run build:version' script.
3
3
  */
4
- export const RXDB_VERSION = '17.0.0-beta.17';
4
+ export const RXDB_VERSION = '17.1.0';
@@ -37,17 +37,19 @@ export function ucfirst(str: string): string {
37
37
  * removes trailing and ending dots from the string
38
38
  */
39
39
  export function trimDots(str: string): string {
40
- // start
41
- while (str.charAt(0) === '.') {
42
- str = str.substr(1);
40
+ let start = 0;
41
+ let end = str.length;
42
+ // charCode 46 is a dot ('.')
43
+ while (start < end && str.charCodeAt(start) === 46) {
44
+ start++;
43
45
  }
44
-
45
- // end
46
- while (str.slice(-1) === '.') {
47
- str = str.slice(0, -1);
46
+ while (end > start && str.charCodeAt(end - 1) === 46) {
47
+ end--;
48
48
  }
49
-
50
- return str;
49
+ if (start === 0 && end === str.length) {
50
+ return str;
51
+ }
52
+ return str.substring(start, end);
51
53
  }
52
54
 
53
55
  /**
@@ -10,28 +10,32 @@
10
10
  * We had to move from having no decimals, to having two decimal
11
11
  * because it turned out that some storages are such fast that
12
12
  * calling this method too often would return 'the future'.
13
+ *
14
+ * Tracks the current millisecond and a sub-millisecond counter (1-99)
15
+ * separately as integers to avoid floating point rounding errors
16
+ * and eliminate the need for Math.round().
13
17
  */
14
- let _lastNow: number = 0;
18
+ let _lastNowMs: number = 0;
19
+ let _lastNowSub: number = 0;
15
20
  /**
16
21
  * Returns the current time in milliseconds,
17
22
  * also ensures to not return the same value twice.
18
23
  */
19
24
  export function now(): number {
20
- let ret = Date.now();
21
- ret = ret + 0.01;
22
- if (ret <= _lastNow) {
23
- ret = _lastNow + 0.01;
25
+ const dateNow = Date.now();
26
+ if (dateNow > _lastNowMs) {
27
+ _lastNowMs = dateNow;
28
+ /**
29
+ * Start at 1 (not 0) so the returned value is always
30
+ * dateNow + 0.01 at minimum, matching the original behavior
31
+ * of always adding 0.01 to Date.now().
32
+ */
33
+ _lastNowSub = 1;
34
+ } else {
35
+ if (++_lastNowSub === 100) {
36
+ _lastNowMs++;
37
+ _lastNowSub = 1;
38
+ }
24
39
  }
25
-
26
- /**
27
- * Strip the returned number to max two decimals.
28
- * In theory we would not need this but
29
- * in practice JavaScript has no such good number precision
30
- * so rounding errors could add another decimal place.
31
- * Use Math.round instead of toFixed(2)+parseFloat for better performance.
32
- */
33
- const twoDecimals = Math.round(ret * 100) / 100;
34
-
35
- _lastNow = twoDecimals;
36
- return twoDecimals;
40
+ return _lastNowMs + _lastNowSub * 0.01;
37
41
  }
@@ -10,7 +10,6 @@ import type {
10
10
  import {
11
11
  getFromMapOrCreate,
12
12
  nextTick,
13
- now,
14
13
  requestIdlePromise
15
14
  } from './plugins/utils/index.ts';
16
15
 
@@ -47,6 +46,9 @@ export function uncacheRxQuery(queryCache: QueryCache, rxQuery: RxQuery) {
47
46
 
48
47
 
49
48
  export function countRxQuerySubscribers(rxQuery: RxQuery): number {
49
+ if (!(rxQuery as any)._refCount$) {
50
+ return 0;
51
+ }
50
52
  return rxQuery.refCount$.observers.length;
51
53
  }
52
54
 
@@ -65,7 +67,7 @@ export const defaultCacheReplacementPolicyMonad: (
65
67
  unExecutedLifetime: number
66
68
  ) => RxCacheReplacementPolicy = (
67
69
  tryToKeepMax,
68
- unExecutedLifetime
70
+ _unExecutedLifetime
69
71
  ) => (
70
72
  _collection: RxCollection,
71
73
  queryCache: QueryCache
@@ -74,7 +76,6 @@ export const defaultCacheReplacementPolicyMonad: (
74
76
  return;
75
77
  }
76
78
 
77
- const minUnExecutedLifetime = now() - unExecutedLifetime;
78
79
  const maybeUncache: RxQuery[] = [];
79
80
 
80
81
  const queriesInCache = Array.from(queryCache._map.values());
@@ -83,8 +84,8 @@ export const defaultCacheReplacementPolicyMonad: (
83
84
  if (countRxQuerySubscribers(rxQuery) > 0) {
84
85
  continue;
85
86
  }
86
- // directly uncache queries that never executed and are older than unExecutedLifetime
87
- if (rxQuery._lastEnsureEqual === 0 && rxQuery._creationTime < minUnExecutedLifetime) {
87
+ // directly uncache queries that have never been executed
88
+ if (rxQuery._lastEnsureEqual === 0) {
88
89
  uncacheRxQuery(queryCache, rxQuery);
89
90
  continue;
90
91
  }
@@ -341,7 +341,7 @@ export function getMatcherQueryOpts(
341
341
  inclusiveStart: false
342
342
  };
343
343
  default:
344
- throw new Error('SNH');
344
+ throw newRxError('SNH');
345
345
  }
346
346
  }
347
347
 
@@ -367,7 +367,7 @@ export function rateQueryPlan<RxDocType>(
367
367
  const nonMinKeyCount = countUntilNotMatching(queryPlan.startKeys, keyValue => keyValue !== INDEX_MIN && keyValue !== INDEX_MAX);
368
368
  addQuality(nonMinKeyCount * pointsPerMatchingKey);
369
369
 
370
- const nonMaxKeyCount = countUntilNotMatching(queryPlan.startKeys, keyValue => keyValue !== INDEX_MAX && keyValue !== INDEX_MIN);
370
+ const nonMaxKeyCount = countUntilNotMatching(queryPlan.endKeys, keyValue => keyValue !== INDEX_MAX && keyValue !== INDEX_MIN);
371
371
  addQuality(nonMaxKeyCount * pointsPerMatchingKey);
372
372
 
373
373
  const equalKeyCount = countUntilNotMatching(queryPlan.startKeys, (keyValue, idx) => {
@@ -223,7 +223,7 @@ export async function startReplicationDownstream<RxDocType, CheckpointType = any
223
223
 
224
224
  tasks.forEach(task => {
225
225
  if (task === 'RESYNC') {
226
- throw new Error('SNH');
226
+ throw newRxError('SNH');
227
227
  }
228
228
  docsOfAllTasks = docsOfAllTasks.concat(task.documents);
229
229
  lastCheckpoint = stackCheckpoints([lastCheckpoint, task.checkpoint]);
@@ -13,8 +13,7 @@ import type {
13
13
  import {
14
14
  createRevision,
15
15
  flatClone,
16
- now,
17
- RX_META_LWT_MINIMUM
16
+ now
18
17
  } from './plugins/utils/index.ts';
19
18
  import {
20
19
  fillObjectWithDefaults,
@@ -45,16 +44,23 @@ export function fillObjectDataBeforeInsert<RxDocType>(
45
44
  data
46
45
  );
47
46
  }
48
- data._meta = { lwt: RX_META_LWT_MINIMUM };
47
+ /**
48
+ * _meta and _rev are not set here because
49
+ * they are always overwritten by the wrapped storage instance
50
+ * in getWrappedStorageInstance() before the actual write.
51
+ * Skipping them here avoids unnecessary object allocations on the hot path.
52
+ *
53
+ * _deleted and _attachments still need to be initialized here because
54
+ * the wrapped storage does NOT set them, and they are required
55
+ * for the document to be valid before the storage write
56
+ * (e.g. _attachments is checked during attachment normalization in bulkInsert).
57
+ */
49
58
  if (!('_deleted' in data)) {
50
59
  data._deleted = false;
51
60
  }
52
61
  if (!('_attachments' in data)) {
53
62
  data._attachments = {};
54
63
  }
55
- if (!('_rev' in data)) {
56
- data._rev = '';
57
- }
58
64
  return data;
59
65
  }
60
66
 
@@ -102,7 +102,8 @@ import {
102
102
  getWrappedStorageInstance,
103
103
  getWrittenDocumentsFromBulkWriteResponse,
104
104
  throwIfIsStorageWriteError,
105
- WrappedRxStorageInstance
105
+ WrappedRxStorageInstance,
106
+ RX_COLLECTION_BULK_INSERT_CONTEXT
106
107
  } from './rx-storage-helper.ts';
107
108
  import { IncrementalWriteQueue } from './incremental-write.ts';
108
109
  import { beforeDocumentUpdateWrite } from './rx-document.ts';
@@ -240,15 +241,19 @@ export class RxCollectionBase<
240
241
  * we retry after some times to account for this.
241
242
  */
242
243
  let count = 0;
243
- while (count < 25 && OPEN_COLLECTIONS.size >= NON_PREMIUM_COLLECTION_LIMIT) {
244
+ let startTime = 0;
245
+ while (count < 35 && OPEN_COLLECTIONS.size >= NON_PREMIUM_COLLECTION_LIMIT) {
246
+ startTime = Date.now();
244
247
  await this.promiseWait(30);
245
248
  count++;
246
249
  }
247
250
  if (OPEN_COLLECTIONS.size > NON_PREMIUM_COLLECTION_LIMIT) {
251
+ const timeInRetry = Date.now() - startTime;
248
252
  throw newRxError('COL23', {
249
253
  database: this.database.name,
250
254
  collection: this.name,
251
255
  args: {
256
+ timeInRetry,
252
257
  existing: Array.from(OPEN_COLLECTIONS.values()).map(c => ({
253
258
  db: c.database ? c.database.name : '',
254
259
  c: c.name
@@ -278,7 +283,7 @@ export class RxCollectionBase<
278
283
  this.storageInstance,
279
284
  this.schema.primaryPath,
280
285
  (newData, oldData) => beforeDocumentUpdateWrite(this as any, newData, oldData),
281
- result => this._runHooks('post', 'save', result)
286
+ result => this._runHooks('post', 'save', result, this._docCache.getCachedRxDocument(result))
282
287
  );
283
288
 
284
289
  this.$ = this.eventBulks$.pipe(
@@ -450,8 +455,19 @@ export class RxCollectionBase<
450
455
 
451
456
 
452
457
  if (ids.size !== docsData.length) {
458
+ const duplicateIdSet = new Set<string>();
459
+ const seenIds = new Set<string>();
460
+ for (const row of insertRows) {
461
+ const id = (row.document as any)[primaryPath];
462
+ if (seenIds.has(id)) {
463
+ duplicateIdSet.add(id);
464
+ } else {
465
+ seenIds.add(id);
466
+ }
467
+ }
453
468
  throw newRxError('COL22', {
454
469
  collection: this.name,
470
+ duplicateIds: Array.from(duplicateIdSet),
455
471
  args: {
456
472
  documents: docsData
457
473
  }
@@ -485,7 +501,7 @@ export class RxCollectionBase<
485
501
 
486
502
  const results = await this.storageInstance.bulkWrite(
487
503
  insertRows,
488
- 'rx-collection-bulk-insert'
504
+ RX_COLLECTION_BULK_INSERT_CONTEXT
489
505
  );
490
506
 
491
507
 
@@ -1178,10 +1194,25 @@ function _incrementalUpsertEnsureRxDocumentExists<RxDocType>(
1178
1194
  return rxCollection.findOne(primary).exec()
1179
1195
  .then(doc => {
1180
1196
  if (!doc) {
1181
- return rxCollection.insert(json).then(newDoc => ({
1182
- doc: newDoc,
1183
- inserted: true
1184
- }));
1197
+ return rxCollection.insert(json)
1198
+ .then(newDoc => ({
1199
+ doc: newDoc,
1200
+ inserted: true
1201
+ }))
1202
+ .catch((err) => {
1203
+ /**
1204
+ * If the insert fails with a conflict error,
1205
+ * it means another concurrent operation already
1206
+ * inserted a document with the same primary key
1207
+ * between our findOne() and insert() calls.
1208
+ * Re-run the whole function which will now find the
1209
+ * existing document via cache or query.
1210
+ */
1211
+ if ((err as any).code === 'CONFLICT') {
1212
+ return _incrementalUpsertEnsureRxDocumentExists(rxCollection, primary, json);
1213
+ }
1214
+ throw err;
1215
+ });
1185
1216
  } else {
1186
1217
  return {
1187
1218
  doc,