@connecttomahdi/rxdb 17.0.0-beta.17 → 17.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) 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 +0 -7
  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 +5 -23
  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 +1 -8
  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 +5 -23
  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/plugins/dev-mode/error-messages.d.ts +36 -0
  251. package/dist/types/plugins/leader-election/index.d.ts +1 -0
  252. package/dist/types/plugins/replication-google-drive/document-handling.d.ts +4 -1
  253. package/dist/types/plugins/replication-google-drive/google-drive-types.d.ts +1 -0
  254. package/dist/types/plugins/state/rx-state.d.ts +1 -1
  255. package/dist/types/plugins/storage-denokv/index.d.ts +1 -1
  256. package/dist/types/plugins/storage-dexie/rx-storage-dexie.d.ts +1 -1
  257. package/dist/types/plugins/storage-localstorage/index.d.ts +1 -1
  258. package/dist/types/plugins/storage-memory/binary-search-bounds.d.ts +21 -10
  259. package/dist/types/plugins/storage-memory/memory-helper.d.ts +7 -3
  260. package/dist/types/plugins/storage-memory/memory-types.d.ts +5 -0
  261. package/dist/types/plugins/storage-mongodb/mongodb-helper.d.ts +9 -1
  262. package/dist/types/plugins/storage-mongodb/rx-storage-instance-mongodb.d.ts +2 -2
  263. package/dist/types/plugins/storage-mongodb/rx-storage-mongodb.d.ts +1 -1
  264. package/dist/types/plugins/storage-remote/rx-storage-remote.d.ts +1 -1
  265. package/dist/types/plugins/storage-sqlite/index.d.ts +1 -1
  266. package/dist/types/plugins/test-utils/performance.d.ts +36 -0
  267. package/dist/types/plugins/test-utils/test-util.d.ts +17 -0
  268. package/dist/types/plugins/utils/utils-object.d.ts +8 -3
  269. package/dist/types/plugins/utils/utils-premium.d.ts +0 -2
  270. package/dist/types/plugins/utils/utils-rxdb-version.d.ts +1 -1
  271. package/dist/types/rx-database.d.ts +1 -1
  272. package/dist/types/rx-query-single-result.d.ts +1 -1
  273. package/dist/types/rx-query.d.ts +3 -2
  274. package/dist/types/rx-storage-helper.d.ts +15 -0
  275. package/dist/types/types/rx-error.d.ts +3 -0
  276. package/dist/types/types/rx-schema.d.ts +5 -0
  277. package/eslint.config.mjs +2 -1
  278. package/package.json +38 -35
  279. package/scripts/check-code-block-line-length.js +91 -0
  280. package/scripts/check-em-dashes.js +53 -0
  281. package/scripts/copy-path.mjs +20 -0
  282. package/scripts/docs-fetch-git-history.mjs +36 -0
  283. package/scripts/fix-types.mjs +15 -8
  284. package/scripts/install-foundationdb.sh +0 -6
  285. package/scripts/notify-indexnow.mjs +171 -0
  286. package/scripts/start-foundationdb-docker.sh +73 -0
  287. package/src/change-event-buffer.ts +4 -1
  288. package/src/custom-index.ts +93 -16
  289. package/src/doc-cache.ts +117 -41
  290. package/src/event-reduce.ts +10 -1
  291. package/src/plugin-helpers.ts +10 -0
  292. package/src/plugins/attachments/index.ts +10 -12
  293. package/src/plugins/cleanup/cleanup.ts +5 -3
  294. package/src/plugins/crdt/index.ts +55 -0
  295. package/src/plugins/dev-mode/check-query.ts +7 -1
  296. package/src/plugins/dev-mode/check-schema.ts +2 -1
  297. package/src/plugins/dev-mode/error-messages.ts +45 -5
  298. package/src/plugins/encryption-crypto-js/index.ts +18 -6
  299. package/src/plugins/leader-election/index.ts +9 -8
  300. package/src/plugins/local-documents/local-documents.ts +21 -12
  301. package/src/plugins/migration-schema/migration-helpers.ts +3 -0
  302. package/src/plugins/migration-schema/rx-migration-state.ts +1 -1
  303. package/src/plugins/pipeline/rx-pipeline.ts +5 -1
  304. package/src/plugins/query-builder/mquery/nosql-query-builder.ts +8 -2
  305. package/src/plugins/replication/index.ts +41 -3
  306. package/src/plugins/replication-google-drive/document-handling.ts +17 -5
  307. package/src/plugins/replication-google-drive/google-drive-helper.ts +1 -1
  308. package/src/plugins/replication-google-drive/google-drive-types.ts +1 -0
  309. package/src/plugins/replication-google-drive/signaling.ts +4 -1
  310. package/src/plugins/replication-google-drive/upstream.ts +7 -4
  311. package/src/plugins/replication-microsoft-onedrive/signaling.ts +4 -1
  312. package/src/plugins/state/rx-state.ts +17 -5
  313. package/src/plugins/storage-dexie/rx-storage-instance-dexie.ts +0 -27
  314. package/src/plugins/storage-memory/binary-search-bounds.ts +105 -40
  315. package/src/plugins/storage-memory/memory-helper.ts +158 -67
  316. package/src/plugins/storage-memory/memory-indexes.ts +1 -0
  317. package/src/plugins/storage-memory/memory-types.ts +5 -0
  318. package/src/plugins/storage-memory/rx-storage-instance-memory.ts +104 -53
  319. package/src/plugins/storage-mongodb/mongodb-helper.ts +43 -1
  320. package/src/plugins/storage-mongodb/rx-storage-instance-mongodb.ts +11 -9
  321. package/src/plugins/test-utils/config.ts +2 -1
  322. package/src/plugins/test-utils/performance.ts +159 -85
  323. package/src/plugins/test-utils/schema-objects.ts +1 -1
  324. package/src/plugins/test-utils/test-util.ts +71 -0
  325. package/src/plugins/utils/utils-map.ts +2 -2
  326. package/src/plugins/utils/utils-object-deep-equal.ts +2 -4
  327. package/src/plugins/utils/utils-object-dot-prop.ts +25 -0
  328. package/src/plugins/utils/utils-object.ts +103 -28
  329. package/src/plugins/utils/utils-other.ts +9 -4
  330. package/src/plugins/utils/utils-premium.ts +11 -37
  331. package/src/plugins/utils/utils-revision.ts +20 -9
  332. package/src/plugins/utils/utils-rxdb-version.ts +1 -1
  333. package/src/plugins/utils/utils-string.ts +11 -9
  334. package/src/plugins/utils/utils-time.ts +21 -17
  335. package/src/query-cache.ts +6 -5
  336. package/src/query-planner.ts +2 -2
  337. package/src/replication-protocol/downstream.ts +1 -1
  338. package/src/rx-collection-helper.ts +12 -6
  339. package/src/rx-collection.ts +39 -8
  340. package/src/rx-database.ts +49 -17
  341. package/src/rx-document.ts +12 -3
  342. package/src/rx-query-helper.ts +36 -15
  343. package/src/rx-query-single-result.ts +10 -3
  344. package/src/rx-query.ts +48 -8
  345. package/src/rx-schema-helper.ts +7 -4
  346. package/src/rx-schema.ts +1 -0
  347. package/src/rx-storage-helper.ts +210 -139
  348. package/src/types/rx-error.d.ts +3 -0
  349. package/src/types/rx-schema.d.ts +5 -0
@@ -51,7 +51,9 @@ import {
51
51
  getMongoDBIndexName,
52
52
  prepareMongoDBQuery,
53
53
  swapMongoToRxDoc,
54
- swapRxDocToMongo
54
+ swapRxDocToMongo,
55
+ getMongoDBClient,
56
+ closeMongoDBClient
55
57
  } from './mongodb-helper.ts';
56
58
 
57
59
  export class RxStorageInstanceMongoDB<RxDocType> implements RxStorageInstance<
@@ -65,7 +67,6 @@ export class RxStorageInstanceMongoDB<RxDocType> implements RxStorageInstance<
65
67
  public readonly inMongoPrimaryPath: string;
66
68
  public closed?: Promise<void>;
67
69
  private readonly changes$: Subject<EventBulk<RxStorageChangeEvent<RxDocumentData<RxDocType>>, RxStorageDefaultCheckpoint>> = new Subject();
68
- public readonly mongoClient: MongoClient;
69
70
  public readonly mongoDatabase: MongoDatabase;
70
71
  public readonly mongoCollectionPromise: Promise<MongoCollection<RxDocumentData<RxDocType> | any>>;
71
72
  // public mongoChangeStream?: MongoChangeStream<any, ChangeStreamDocument<any>>;
@@ -94,15 +95,14 @@ export class RxStorageInstanceMongoDB<RxDocType> implements RxStorageInstance<
94
95
  public readonly schema: Readonly<RxJsonSchema<RxDocumentData<RxDocType>>>,
95
96
  public readonly internals: MongoDBStorageInternals,
96
97
  public readonly options: Readonly<RxStorageMongoDBInstanceCreationOptions>,
97
- public readonly settings: RxStorageMongoDBSettings
98
+ public readonly settings: RxStorageMongoDBSettings,
99
+ public readonly mongoClient: MongoClient
98
100
  ) {
99
101
  if (this.schema.attachments) {
100
102
  throw new Error('attachments not supported in mongodb storage, make a PR if you need that');
101
103
  }
102
104
  this.primaryPath = getPrimaryFieldOfPrimaryKey(this.schema.primaryKey);
103
105
  this.inMongoPrimaryPath = this.primaryPath === '_id' ? MONGO_ID_SUBSTITUTE_FIELDNAME : this.primaryPath;
104
-
105
- this.mongoClient = new MongoClient(storage.databaseSettings.connection, MONGO_OPTIONS_DRIVER_INFO);
106
106
  this.mongoDatabase = this.mongoClient.db(databaseName + '-v' + this.schema.version);
107
107
 
108
108
  const indexes = (this.schema.indexes ? this.schema.indexes.slice() : []).map(index => {
@@ -440,17 +440,18 @@ export class RxStorageInstanceMongoDB<RxDocType> implements RxStorageInstance<
440
440
  await this.mongoCollectionPromise;
441
441
  await firstValueFrom(this.runningOperations.pipe(filter((c: number) => c === 0)));
442
442
  // await ensureNotFalsy(this.mongoChangeStream).close();
443
- await this.mongoClient.close();
443
+ await closeMongoDBClient(this.storage.databaseSettings.connection);
444
444
  })();
445
445
  return this.closed;
446
446
  }
447
447
  }
448
448
 
449
- export function createMongoDBStorageInstance<RxDocType>(
449
+ export async function createMongoDBStorageInstance<RxDocType>(
450
450
  storage: RxStorageMongoDB,
451
451
  params: RxStorageInstanceCreationParams<RxDocType, RxStorageMongoDBInstanceCreationOptions>,
452
452
  settings: RxStorageMongoDBSettings
453
453
  ): Promise<RxStorageInstanceMongoDB<RxDocType>> {
454
+ const mongoClient = await getMongoDBClient(storage.databaseSettings.connection);
454
455
  const instance = new RxStorageInstanceMongoDB(
455
456
  storage,
456
457
  params.databaseName,
@@ -458,7 +459,8 @@ export function createMongoDBStorageInstance<RxDocType>(
458
459
  params.schema,
459
460
  {},
460
461
  params.options,
461
- settings
462
+ settings,
463
+ mongoClient
462
464
  );
463
- return Promise.resolve(instance);
465
+ return instance;
464
466
  }
@@ -40,7 +40,8 @@ function getEnvVariables() {
40
40
  const ret: any = {};
41
41
  [
42
42
  'DEFAULT_STORAGE',
43
- 'NODE_ENV'
43
+ 'NODE_ENV',
44
+ 'STORAGE_PASSWORD'
44
45
  ].forEach(k => {
45
46
  ret[k] = Deno.env.get(k);
46
47
  });
@@ -53,6 +53,42 @@ export type PerformanceTestConfig = {
53
53
  * @default true
54
54
  */
55
55
  log?: boolean;
56
+ /**
57
+ * If set, the database will be created with encryption
58
+ * and the schema will mark applicable fields as encrypted.
59
+ */
60
+ password?: any;
61
+ /**
62
+ * Whether to run the bulk find-by-ids test.
63
+ * @default true
64
+ */
65
+ testBulkFindByIds?: boolean;
66
+ /**
67
+ * Whether to run the serial find-by-id test.
68
+ * @default true
69
+ */
70
+ testSerialFindById?: boolean;
71
+ /**
72
+ * Whether to run the find-by-query test.
73
+ * @default true
74
+ */
75
+ testFindByQuery?: boolean;
76
+ /**
77
+ * Whether to run the find-by-query-parallel test.
78
+ * @default true
79
+ */
80
+ testFindByQueryParallel?: boolean;
81
+ /**
82
+ * Whether to run the count query test.
83
+ * @default true
84
+ */
85
+ testCount?: boolean;
86
+ /**
87
+ * Whether to run the property access test.
88
+ * Requires testFindByQuery to also be enabled.
89
+ * @default true
90
+ */
91
+ testPropertyAccess?: boolean;
56
92
  };
57
93
 
58
94
  export type PerformanceTestResult = {
@@ -84,11 +120,23 @@ export async function runPerformanceTests(
84
120
  parallelQueryAmount = 4,
85
121
  insertBatches = 6,
86
122
  waitBetweenTests = 100,
87
- log = true
123
+ log = true,
124
+ password
88
125
  } = config;
126
+ const testBulkFindByIds = config.testBulkFindByIds !== false;
127
+ const testSerialFindById = config.testSerialFindById !== false;
128
+ const testFindByQuery = config.testFindByQuery !== false;
129
+ const testFindByQueryParallel = config.testFindByQueryParallel !== false;
130
+ const testCount = config.testCount !== false;
131
+ const testPropertyAccess = config.testPropertyAccess !== false;
89
132
 
90
133
  const totalTimes: { [k: string]: number[]; } = {};
91
134
 
135
+ // Generate dbName outside the loop to reuse the exact same MongoDB database.
136
+ // This allows `.remove()` to drop the old collections and the next run to cleanly reuse the same
137
+ // namespace, avoiding creating thousands of collections on the DB server causing file exhaustion.
138
+ const dbName = 'test-db-performance-' + randomToken(10);
139
+
92
140
  let runsDone = 0;
93
141
  while (runsDone < runs) {
94
142
  if (log) {
@@ -115,8 +163,16 @@ export async function runPerformanceTests(
115
163
  updateTime();
116
164
 
117
165
  // create database
118
- const dbName = 'test-db-performance-' + randomToken(10);
119
166
  const schema = averageSchema();
167
+ if (password) {
168
+ schema.encrypted = ['deep', 'list'];
169
+ schema.indexes = schema.indexes!.filter(index => {
170
+ if (typeof index === 'string') {
171
+ return !index.startsWith('deep.');
172
+ }
173
+ return !index.some(field => field.startsWith('deep.'));
174
+ });
175
+ }
120
176
  let collection: RxCollection<AverageSchemaDocumentType>;
121
177
  async function createDbWithCollections() {
122
178
  if (collection) {
@@ -133,7 +189,8 @@ export async function runPerformanceTests(
133
189
  * creation time.
134
190
  */
135
191
  multiInstance: false,
136
- storage
192
+ storage,
193
+ password
137
194
  });
138
195
 
139
196
  // create collections
@@ -183,18 +240,20 @@ export async function runPerformanceTests(
183
240
  await awaitBetweenTest(waitBetweenTests);
184
241
  }
185
242
 
186
- // refresh db to ensure we do not run on caches
187
- collection = await createDbWithCollections();
188
- await awaitBetweenTest(waitBetweenTests);
243
+ if (testBulkFindByIds) {
244
+ // refresh db to ensure we do not run on caches
245
+ collection = await createDbWithCollections();
246
+ await awaitBetweenTest(waitBetweenTests);
189
247
 
190
- /**
191
- * Bulk Find by id
192
- */
193
- updateTime();
194
- const idsResult = await collection.findByIds(docIds).exec();
195
- updateTime('find-by-ids-' + docsAmount);
196
- assert.strictEqual(Array.from(idsResult.keys()).length, docsAmount, 'find-by-id amount');
197
- await awaitBetweenTest(waitBetweenTests);
248
+ /**
249
+ * Bulk Find by id
250
+ */
251
+ updateTime();
252
+ const idsResult = await collection.findByIds(docIds).exec();
253
+ updateTime('find-by-ids-' + docsAmount);
254
+ assert.strictEqual(Array.from(idsResult.keys()).length, docsAmount, 'find-by-id amount');
255
+ await awaitBetweenTest(waitBetweenTests);
256
+ }
198
257
 
199
258
  /**
200
259
  * Serial inserts
@@ -212,86 +271,101 @@ export async function runPerformanceTests(
212
271
  }
213
272
  updateTime('serial-inserts-' + serialDocsAmount);
214
273
 
215
- // refresh db to ensure we do not run on caches
216
- collection = await createDbWithCollections();
217
- await awaitBetweenTest(waitBetweenTests);
274
+ if (testSerialFindById || testFindByQuery) {
275
+ // refresh db to ensure we do not run on caches
276
+ collection = await createDbWithCollections();
277
+ await awaitBetweenTest(waitBetweenTests);
278
+ }
218
279
 
219
- /**
220
- * Serial find-by-id
221
- */
222
- updateTime();
223
- for (const id of serialIds) {
224
- await collection.findByIds([id]).exec();
280
+ if (testSerialFindById) {
281
+ /**
282
+ * Serial find-by-id
283
+ */
284
+ updateTime();
285
+ for (const id of serialIds) {
286
+ await collection.findByIds([id]).exec();
287
+ }
288
+ updateTime('serial-find-by-id-' + serialDocsAmount);
289
+ await awaitBetweenTest(waitBetweenTests);
225
290
  }
226
- updateTime('serial-find-by-id-' + serialDocsAmount);
227
- await awaitBetweenTest(waitBetweenTests);
228
291
 
229
- // find by query
230
- updateTime();
231
- const query = collection.find({
232
- selector: {},
233
- sort: [
234
- { var2: 'asc' },
235
- { var1: 'asc' }
236
- ]
237
- });
238
- const queryResult = await query.exec();
239
- updateTime('find-by-query');
240
- assert.strictEqual(queryResult.length, docsAmount + serialDocsAmount, 'find-by-query');
292
+ let queryResult: any[] | undefined;
293
+ if (testFindByQuery) {
294
+ // find by query
295
+ updateTime();
296
+ const query = collection.find({
297
+ selector: {},
298
+ sort: [
299
+ { var2: 'asc' },
300
+ { var1: 'asc' }
301
+ ]
302
+ });
303
+ queryResult = await query.exec();
304
+ updateTime('find-by-query');
305
+ assert.strictEqual(queryResult.length, docsAmount + serialDocsAmount, 'find-by-query');
306
+ }
241
307
 
242
- // refresh db to ensure we do not run on caches
243
- collection = await createDbWithCollections();
244
- await awaitBetweenTest(waitBetweenTests);
308
+ if (testFindByQueryParallel || testCount) {
309
+ // refresh db to ensure we do not run on caches
310
+ collection = await createDbWithCollections();
311
+ await awaitBetweenTest(waitBetweenTests);
312
+ }
245
313
 
246
- // find by multiple queries in parallel
247
- updateTime();
248
- const parallelResult = await Promise.all(
249
- new Array(parallelQueryAmount).fill(0).map((_v, idx) => {
250
- const subQuery = collection.find({
314
+ if (testFindByQueryParallel) {
315
+ // find by multiple queries in parallel
316
+ updateTime();
317
+ const parallelResult = await Promise.all(
318
+ new Array(parallelQueryAmount).fill(0).map((_v, idx) => {
319
+ const subQuery = collection.find({
320
+ selector: {
321
+ var2: idx
322
+ }
323
+ });
324
+ return subQuery.exec();
325
+ })
326
+ );
327
+ updateTime('find-by-query-parallel-' + parallelQueryAmount);
328
+ let parallelSum = 0;
329
+ parallelResult.forEach(r => parallelSum = parallelSum + r.length);
330
+ assert.strictEqual(parallelSum, docsAmount, 'parallelSum');
331
+ await awaitBetweenTest(waitBetweenTests);
332
+ }
333
+
334
+ if (testCount) {
335
+ // run count query
336
+ updateTime();
337
+ let t = 0;
338
+ while (t < parallelQueryAmount) {
339
+ const countQuery = collection.count({
251
340
  selector: {
252
- var2: idx
341
+ var2: {
342
+ $eq: t
343
+ }
253
344
  }
254
345
  });
255
- return subQuery.exec();
256
- })
257
- );
258
- updateTime('find-by-query-parallel-' + parallelQueryAmount);
259
- let parallelSum = 0;
260
- parallelResult.forEach(r => parallelSum = parallelSum + r.length);
261
- assert.strictEqual(parallelSum, docsAmount, 'parallelSum');
262
- await awaitBetweenTest(waitBetweenTests);
263
-
264
- // run count query
265
- updateTime();
266
- let t = 0;
267
- while (t < parallelQueryAmount) {
268
- const countQuery = collection.count({
269
- selector: {
270
- var2: {
271
- $eq: t
272
- }
273
- }
274
- });
275
- const countQueryResult = await countQuery.exec();
276
- assert.ok(countQueryResult >= ((docsAmount / insertBatches) - 5), 'count A ' + countQueryResult);
277
- assert.ok(countQueryResult < (docsAmount * 0.8), 'count B ' + countQueryResult);
278
- t++;
346
+ const countQueryResult = await countQuery.exec();
347
+ assert.ok(countQueryResult >= ((docsAmount / insertBatches) - 5), 'count A ' + countQueryResult);
348
+ assert.ok(countQueryResult < (docsAmount * 0.8), 'count B ' + countQueryResult);
349
+ t++;
350
+ }
351
+ updateTime('4x-count');
352
+ await awaitBetweenTest(waitBetweenTests);
279
353
  }
280
- updateTime('4x-count');
281
- await awaitBetweenTest(waitBetweenTests);
282
354
 
283
- // test property access time
284
- updateTime();
285
- let sum = 0;
286
- for (let i = 0; i < queryResult.length; i++) {
287
- const doc = queryResult[i];
355
+ if (testPropertyAccess && testFindByQuery && queryResult) {
356
+ // test property access time
357
+ updateTime();
358
+ let sum = 0;
359
+ for (let i = 0; i < queryResult.length; i++) {
360
+ const doc = queryResult[i];
288
361
 
289
- // access the same property exactly 2 times
290
- sum += doc.deep.deeper.deepNr;
291
- sum += doc.deep.deeper.deepNr;
362
+ // access the same property exactly 2 times
363
+ sum += doc.deep.deeper.deepNr;
364
+ sum += doc.deep.deeper.deepNr;
365
+ }
366
+ updateTime('property-access');
367
+ assert.ok(sum > 10);
292
368
  }
293
- updateTime('property-access');
294
- assert.ok(sum > 10);
295
369
 
296
370
  await collection.database.remove();
297
371
  }
@@ -302,7 +376,7 @@ export async function runPerformanceTests(
302
376
  docsAmount
303
377
  };
304
378
  Object.entries(totalTimes).forEach(([key, times]) => {
305
- result[key] = roundToThree(averageOfTimeValues(times, 95));
379
+ result[key] = roundToTwo(averageOfTimeValues(times, 95));
306
380
  });
307
381
 
308
382
  if (log) {
@@ -330,8 +404,8 @@ export function averageOfTimeValues(
330
404
  return total / useNumbers.length;
331
405
  }
332
406
 
333
- function roundToThree(num: number) {
334
- return Math.round(num * 1000) / 1000;
407
+ function roundToTwo(num: number) {
408
+ return Math.round(num * 100) / 100;
335
409
  }
336
410
 
337
411
  async function awaitBetweenTest(waitMs: number) {
@@ -236,7 +236,7 @@ export interface SimpleHeroArrayDocumentType {
236
236
  }
237
237
  export function simpleHeroArray(partial: Partial<SimpleHeroArrayDocumentType> = {}): SimpleHeroArrayDocumentType {
238
238
  const defaultObj = {
239
- name: randomStringWithSpecialChars(6, 8),
239
+ name: randomStringWithSpecialChars(8, 10),
240
240
  skills: new Array(3).fill(0).map(() => randomStringWithSpecialChars(3, 6))
241
241
  };
242
242
  return Object.assign(
@@ -70,6 +70,77 @@ export async function awaitCollectionsHaveEqualState<RxDocType>(
70
70
 
71
71
 
72
72
 
73
+ /**
74
+ * Deletes all locally stored IndexedDB databases.
75
+ * Noop if IndexedDB is not available (e.g. in Node.js)
76
+ * or if the .databases() method is not supported.
77
+ */
78
+ export async function clearAllLocalIndexedDB(): Promise<void> {
79
+ if (
80
+ typeof indexedDB === 'undefined' ||
81
+ typeof indexedDB.databases !== 'function'
82
+ ) {
83
+ return;
84
+ }
85
+ const databases = await indexedDB.databases();
86
+ await Promise.all(
87
+ databases
88
+ .filter(db => !!db.name)
89
+ .map(db => {
90
+ return new Promise<void>((resolve, reject) => {
91
+ const req = indexedDB.deleteDatabase(db.name as string);
92
+ req.onsuccess = () => resolve();
93
+ req.onerror = () => reject(req.error);
94
+ });
95
+ })
96
+ );
97
+ }
98
+
99
+ /**
100
+ * Deletes all files and directories stored in the
101
+ * Origin Private File System (OPFS).
102
+ * Noop if OPFS is not available (e.g. in Node.js).
103
+ */
104
+ export async function clearAllLocalOPFS(maxRetries = 20, delayMs = 200): Promise<void> {
105
+ if (
106
+ typeof navigator === 'undefined' ||
107
+ !navigator.storage ||
108
+ typeof navigator.storage.getDirectory !== 'function'
109
+ ) {
110
+ return;
111
+ }
112
+ const root = await navigator.storage.getDirectory();
113
+ // @ts-ignore entries() is not in all TS lib definitions
114
+ for await (const [name] of root.entries()) {
115
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
116
+ try {
117
+ await root.removeEntry(name, { recursive: true });
118
+ break;
119
+ } catch (err: any) {
120
+ if (err?.name === 'NoModificationAllowedError' && attempt < maxRetries - 1) {
121
+ await new Promise(resolve => setTimeout(resolve, delayMs));
122
+ } else {
123
+ throw err;
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Clears all localStorage data.
132
+ * Noop if localStorage is not available (e.g. in Node.js).
133
+ */
134
+ export async function clearAllLocalStorage(): Promise<void> {
135
+ if (
136
+ typeof localStorage === 'undefined' ||
137
+ typeof localStorage.clear !== 'function'
138
+ ) {
139
+ return;
140
+ }
141
+ localStorage.clear();
142
+ }
143
+
73
144
  export function ensureReplicationHasNoErrors(replicationState: RxReplicationState<any, any>) {
74
145
  /**
75
146
  * We do not have to unsubscribe because the observable will cancel anyway.
@@ -1,6 +1,6 @@
1
1
  export function getFromMapOrThrow<K, V>(map: Map<K, V> | WeakMap<any, V>, key: K): V {
2
2
  const val = map.get(key);
3
- if (typeof val === 'undefined') {
3
+ if (val === undefined) {
4
4
  throw new Error('missing value from map ' + key);
5
5
  }
6
6
  return val;
@@ -13,7 +13,7 @@ export function getFromMapOrCreate<MapIndex, MapValue>(
13
13
  ifWasThere?: (value: MapValue) => void
14
14
  ): MapValue {
15
15
  let value = map.get(index);
16
- if (typeof value === 'undefined') {
16
+ if (value === undefined) {
17
17
  value = creator();
18
18
  map.set(index, value);
19
19
  } else if (ifWasThere) {
@@ -30,12 +30,10 @@ export function deepEqual(a: any, b: any): boolean {
30
30
  length = keys.length;
31
31
  if (length !== Object.keys(b).length) return false;
32
32
 
33
- for (i = length; i-- !== 0;)
34
- if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
35
-
33
+ // Single combined loop: check key existence AND deep-compare in one pass.
36
34
  for (i = length; i-- !== 0;) {
37
35
  const key = keys[i];
38
- if (!deepEqual(a[key], b[key])) return false;
36
+ if (!Object.prototype.hasOwnProperty.call(b, key) || !deepEqual(a[key], b[key])) return false;
39
37
  }
40
38
 
41
39
  return true;
@@ -206,6 +206,31 @@ export function getProperty(object: any, path: string | string[], value?: any) {
206
206
  return value === undefined ? object : value;
207
207
  }
208
208
 
209
+ /**
210
+ * Fast path for simple dot-notation paths without bracket
211
+ * notation or backslash escaping. This covers the vast majority
212
+ * of RxDB property access patterns (e.g. 'nested.field')
213
+ * and avoids the expensive getPathSegments() parser.
214
+ */
215
+ if (!path.includes('[') && !path.includes('\\')) {
216
+ const segments = path.split('.');
217
+ let current = object;
218
+ for (let i = 0; i < segments.length; i++) {
219
+ const seg = segments[i];
220
+ if (disallowedKeys.has(seg)) {
221
+ return value;
222
+ }
223
+ current = current[seg];
224
+ if (current === undefined || current === null) {
225
+ if (i !== segments.length - 1) {
226
+ return value;
227
+ }
228
+ break;
229
+ }
230
+ }
231
+ return current === undefined ? value : current;
232
+ }
233
+
209
234
  const pathArray = getPathSegments(path);
210
235
  if (pathArray.length === 0) {
211
236
  return value;