@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
@@ -1,18 +1,19 @@
1
1
  /**
2
- * Everything in this file was copied and adapted from
3
- * @link https://github.com/mikolalysenko/binary-search-bounds
4
- *
5
- * We should use the original npm module instead when this bug is fixed:
6
- * @link https://github.com/mikolalysenko/binary-search-bounds/pull/14
2
+ * Optimized binary search functions for the memory storage.
3
+ * Based on https://github.com/mikolalysenko/binary-search-bounds
4
+ * but with performance improvements:
5
+ * - Removed unnecessary undefined checks for comparator
6
+ * - Inlined the norm() wrapper to avoid extra function calls
7
+ * - Added string-specialized variants to avoid temporary array allocations
7
8
  */
8
9
 
9
- function ge(a, y, c, l, h) {
10
+ export function boundGE(a, y, c, lo, hi) {
11
+ var l = lo === undefined ? 0 : lo | 0;
12
+ var h = hi === undefined ? a.length - 1 : hi | 0;
10
13
  var i = h + 1;
11
14
  while (l <= h) {
12
15
  var m = l + h >>> 1;
13
- var x = a[m];
14
- var p = c !== undefined ? c(x, y) : x - y;
15
- if (p >= 0) {
16
+ if (c(a[m], y) >= 0) {
16
17
  i = m;
17
18
  h = m - 1;
18
19
  } else {
@@ -21,13 +22,13 @@ function ge(a, y, c, l, h) {
21
22
  }
22
23
  return i;
23
24
  }
24
- function gt(a, y, c, l, h) {
25
+ export function boundGT(a, y, c, lo, hi) {
26
+ var l = lo === undefined ? 0 : lo | 0;
27
+ var h = hi === undefined ? a.length - 1 : hi | 0;
25
28
  var i = h + 1;
26
29
  while (l <= h) {
27
30
  var m = l + h >>> 1;
28
- var x = a[m];
29
- var p = c !== undefined ? c(x, y) : x - y;
30
- if (p > 0) {
31
+ if (c(a[m], y) > 0) {
31
32
  i = m;
32
33
  h = m - 1;
33
34
  } else {
@@ -36,13 +37,13 @@ function gt(a, y, c, l, h) {
36
37
  }
37
38
  return i;
38
39
  }
39
- function lt(a, y, c, l, h) {
40
+ export function boundLT(a, y, c, lo, hi) {
41
+ var l = lo === undefined ? 0 : lo | 0;
42
+ var h = hi === undefined ? a.length - 1 : hi | 0;
40
43
  var i = l - 1;
41
44
  while (l <= h) {
42
- var m = l + h >>> 1,
43
- x = a[m];
44
- var p = c !== undefined ? c(x, y) : x - y;
45
- if (p < 0) {
45
+ var m = l + h >>> 1;
46
+ if (c(a[m], y) < 0) {
46
47
  i = m;
47
48
  l = m + 1;
48
49
  } else {
@@ -51,13 +52,13 @@ function lt(a, y, c, l, h) {
51
52
  }
52
53
  return i;
53
54
  }
54
- function le(a, y, c, l, h) {
55
+ export function boundLE(a, y, c, lo, hi) {
56
+ var l = lo === undefined ? 0 : lo | 0;
57
+ var h = hi === undefined ? a.length - 1 : hi | 0;
55
58
  var i = l - 1;
56
59
  while (l <= h) {
57
- var m = l + h >>> 1,
58
- x = a[m];
59
- var p = c !== undefined ? c(x, y) : x - y;
60
- if (p <= 0) {
60
+ var m = l + h >>> 1;
61
+ if (c(a[m], y) <= 0) {
61
62
  i = m;
62
63
  l = m + 1;
63
64
  } else {
@@ -66,11 +67,12 @@ function le(a, y, c, l, h) {
66
67
  }
67
68
  return i;
68
69
  }
69
- function eq(a, y, c, l, h) {
70
+ export function boundEQ(a, y, c, lo, hi) {
71
+ var l = lo === undefined ? 0 : lo | 0;
72
+ var h = hi === undefined ? a.length - 1 : hi | 0;
70
73
  while (l <= h) {
71
- var m = l + h >>> 1,
72
- x = a[m];
73
- var p = c !== undefined ? c(x, y) : x - y;
74
+ var m = l + h >>> 1;
75
+ var p = c(a[m], y);
74
76
  if (p === 0) {
75
77
  return m;
76
78
  }
@@ -82,22 +84,87 @@ function eq(a, y, c, l, h) {
82
84
  }
83
85
  return -1;
84
86
  }
85
- function norm(a, y, c, l, h, f) {
86
- return f(a, y, c, l === undefined ? 0 : l | 0, h === undefined ? a.length - 1 : h | 0);
87
- }
88
- export function boundGE(a, y, c, l, h) {
89
- return norm(a, y, c, l, h, ge);
87
+
88
+ /**
89
+ * Specialized binary search functions that compare DocWithIndexString
90
+ * entries directly against an index string, avoiding temporary array allocations.
91
+ * Used in query() and count() hot paths.
92
+ */
93
+ export function boundGEByIndexString(a, indexString) {
94
+ var l = 0;
95
+ var h = a.length - 1;
96
+ var i = h + 1;
97
+ while (l <= h) {
98
+ var m = l + h >>> 1;
99
+ if (a[m][0] >= indexString) {
100
+ i = m;
101
+ h = m - 1;
102
+ } else {
103
+ l = m + 1;
104
+ }
105
+ }
106
+ return i;
90
107
  }
91
- export function boundGT(a, y, c, l, h) {
92
- return norm(a, y, c, l, h, gt);
108
+ export function boundGTByIndexString(a, indexString) {
109
+ var l = 0;
110
+ var h = a.length - 1;
111
+ var i = h + 1;
112
+ while (l <= h) {
113
+ var m = l + h >>> 1;
114
+ if (a[m][0] > indexString) {
115
+ i = m;
116
+ h = m - 1;
117
+ } else {
118
+ l = m + 1;
119
+ }
120
+ }
121
+ return i;
93
122
  }
94
- export function boundLT(a, y, c, l, h) {
95
- return norm(a, y, c, l, h, lt);
123
+ export function boundEQByIndexString(a, indexString) {
124
+ var l = 0;
125
+ var h = a.length - 1;
126
+ while (l <= h) {
127
+ var m = l + h >>> 1;
128
+ var s = a[m][0];
129
+ if (s === indexString) {
130
+ return m;
131
+ }
132
+ if (s < indexString) {
133
+ l = m + 1;
134
+ } else {
135
+ h = m - 1;
136
+ }
137
+ }
138
+ return -1;
96
139
  }
97
- export function boundLE(a, y, c, l, h) {
98
- return norm(a, y, c, l, h, le);
140
+ export function boundLTByIndexString(a, indexString) {
141
+ var l = 0;
142
+ var h = a.length - 1;
143
+ var i = l - 1;
144
+ while (l <= h) {
145
+ var m = l + h >>> 1;
146
+ if (a[m][0] < indexString) {
147
+ i = m;
148
+ l = m + 1;
149
+ } else {
150
+ h = m - 1;
151
+ }
152
+ }
153
+ return i;
99
154
  }
100
- export function boundEQ(a, y, c, l, h) {
101
- return norm(a, y, c, l, h, eq);
155
+ export function boundLEByIndexString(a, indexString) {
156
+ var l = 0;
157
+ var h = a.length - 1;
158
+ var i = l - 1;
159
+ while (l <= h) {
160
+ var m = l + h >>> 1;
161
+ if (a[m][0] <= indexString) {
162
+ i = m;
163
+ l = m + 1;
164
+ } else {
165
+ h = m - 1;
166
+ }
167
+ }
168
+ return i;
102
169
  }
103
170
  //# sourceMappingURL=binary-search-bounds.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"binary-search-bounds.js","names":["ge","a","y","c","l","h","i","m","x","p","undefined","gt","lt","le","eq","norm","f","length","boundGE","boundGT","boundLT","boundLE","boundEQ"],"sources":["../../../../src/plugins/storage-memory/binary-search-bounds.ts"],"sourcesContent":["/**\r\n * Everything in this file was copied and adapted from\r\n * @link https://github.com/mikolalysenko/binary-search-bounds\r\n *\r\n * We should use the original npm module instead when this bug is fixed:\r\n * @link https://github.com/mikolalysenko/binary-search-bounds/pull/14\r\n */\r\n\r\n\r\n\r\ntype Compare<T> = ((a: T, b: T) => number | null | undefined);\r\n\r\nfunction ge<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any): number {\r\n let i: number = h + 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n const x: any = a[m];\r\n const p: any = (c !== undefined) ? c(x, y) : (x - (y as any));\r\n if (p >= 0) {\r\n i = m; h = m - 1;\r\n } else {\r\n l = m + 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nfunction gt<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any): number {\r\n let i = h + 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n const x = a[m];\r\n const p: any = (c !== undefined) ? c(x, y) : ((x as any) - (y as any));\r\n if (p > 0) {\r\n i = m; h = m - 1;\r\n } else {\r\n l = m + 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nfunction lt<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any): number {\r\n let i = l - 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1, x = a[m];\r\n const p: any = (c !== undefined) ? c(x, y) : ((x as any) - (y as any));\r\n if (p < 0) {\r\n i = m; l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nfunction le<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any): number {\r\n let i = l - 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1, x = a[m];\r\n const p: any = (c !== undefined) ? c(x, y) : ((x as any) - (y as any));\r\n if (p <= 0) {\r\n i = m; l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nfunction eq<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any): number {\r\n while (l <= h) {\r\n const m = (l + h) >>> 1, x = a[m];\r\n const p: any = (c !== undefined) ? c(x, y) : ((x as any) - (y as any));\r\n if (p === 0) {\r\n return m;\r\n }\r\n if (p <= 0) {\r\n l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return -1;\r\n}\r\n\r\nfunction norm<T>(a: T[], y: T, c: Compare<T>, l: any, h: any, f: any) {\r\n return f(a, y, c, (l === undefined) ? 0 : l | 0, (h === undefined) ? a.length - 1 : h | 0);\r\n}\r\n\r\n\r\nexport function boundGE<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any) {\r\n return norm(a, y, c, l, h, ge);\r\n}\r\nexport function boundGT<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any) {\r\n return norm(a, y, c, l, h, gt);\r\n}\r\nexport function boundLT<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any) {\r\n return norm(a, y, c, l, h, lt);\r\n}\r\nexport function boundLE<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any) {\r\n return norm(a, y, c, l, h, le);\r\n}\r\nexport function boundEQ<T>(a: T[], y: T, c: Compare<T>, l?: any, h?: any) {\r\n return norm(a, y, c, l, h, eq);\r\n}\r\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"binary-search-bounds.js","names":["boundGE","a","y","c","lo","hi","l","undefined","h","length","i","m","boundGT","boundLT","boundLE","boundEQ","p","boundGEByIndexString","indexString","boundGTByIndexString","boundEQByIndexString","s","boundLTByIndexString","boundLEByIndexString"],"sources":["../../../../src/plugins/storage-memory/binary-search-bounds.ts"],"sourcesContent":["/**\r\n * Optimized binary search functions for the memory storage.\r\n * Based on https://github.com/mikolalysenko/binary-search-bounds\r\n * but with performance improvements:\r\n * - Removed unnecessary undefined checks for comparator\r\n * - Inlined the norm() wrapper to avoid extra function calls\r\n * - Added string-specialized variants to avoid temporary array allocations\r\n */\r\n\r\ntype Compare<T> = ((a: T, b: T) => number | null | undefined);\r\n\r\nexport function boundGE<T>(a: T[], y: T, c: Compare<T>, lo?: any, hi?: any): number {\r\n let l: number = lo === undefined ? 0 : lo | 0;\r\n let h: number = hi === undefined ? a.length - 1 : hi | 0;\r\n let i: number = h + 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n if ((c(a[m], y) as number) >= 0) {\r\n i = m; h = m - 1;\r\n } else {\r\n l = m + 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nexport function boundGT<T>(a: T[], y: T, c: Compare<T>, lo?: any, hi?: any): number {\r\n let l: number = lo === undefined ? 0 : lo | 0;\r\n let h: number = hi === undefined ? a.length - 1 : hi | 0;\r\n let i = h + 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n if ((c(a[m], y) as number) > 0) {\r\n i = m; h = m - 1;\r\n } else {\r\n l = m + 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nexport function boundLT<T>(a: T[], y: T, c: Compare<T>, lo?: any, hi?: any): number {\r\n let l: number = lo === undefined ? 0 : lo | 0;\r\n let h: number = hi === undefined ? a.length - 1 : hi | 0;\r\n let i = l - 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n if ((c(a[m], y) as number) < 0) {\r\n i = m; l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nexport function boundLE<T>(a: T[], y: T, c: Compare<T>, lo?: any, hi?: any): number {\r\n let l: number = lo === undefined ? 0 : lo | 0;\r\n let h: number = hi === undefined ? a.length - 1 : hi | 0;\r\n let i = l - 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n if ((c(a[m], y) as number) <= 0) {\r\n i = m; l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nexport function boundEQ<T>(a: T[], y: T, c: Compare<T>, lo?: any, hi?: any): number {\r\n let l: number = lo === undefined ? 0 : lo | 0;\r\n let h: number = hi === undefined ? a.length - 1 : hi | 0;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n const p = c(a[m], y) as number;\r\n if (p === 0) {\r\n return m;\r\n }\r\n if (p <= 0) {\r\n l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return -1;\r\n}\r\n\r\n/**\r\n * Specialized binary search functions that compare DocWithIndexString\r\n * entries directly against an index string, avoiding temporary array allocations.\r\n * Used in query() and count() hot paths.\r\n */\r\nexport function boundGEByIndexString<T extends [string, ...any[]]>(a: T[], indexString: string): number {\r\n let l = 0;\r\n let h = a.length - 1;\r\n let i: number = h + 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n if (a[m][0] >= indexString) {\r\n i = m; h = m - 1;\r\n } else {\r\n l = m + 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nexport function boundGTByIndexString<T extends [string, ...any[]]>(a: T[], indexString: string): number {\r\n let l = 0;\r\n let h = a.length - 1;\r\n let i = h + 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n if (a[m][0] > indexString) {\r\n i = m; h = m - 1;\r\n } else {\r\n l = m + 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nexport function boundEQByIndexString<T extends [string, ...any[]]>(a: T[], indexString: string): number {\r\n let l = 0;\r\n let h = a.length - 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n const s = a[m][0];\r\n if (s === indexString) {\r\n return m;\r\n }\r\n if (s < indexString) {\r\n l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return -1;\r\n}\r\n\r\nexport function boundLTByIndexString<T extends [string, ...any[]]>(a: T[], indexString: string): number {\r\n let l = 0;\r\n let h = a.length - 1;\r\n let i = l - 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n if (a[m][0] < indexString) {\r\n i = m; l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return i;\r\n}\r\n\r\nexport function boundLEByIndexString<T extends [string, ...any[]]>(a: T[], indexString: string): number {\r\n let l = 0;\r\n let h = a.length - 1;\r\n let i = l - 1;\r\n while (l <= h) {\r\n const m = (l + h) >>> 1;\r\n if (a[m][0] <= indexString) {\r\n i = m; l = m + 1;\r\n } else {\r\n h = m - 1;\r\n }\r\n }\r\n return i;\r\n}\r\n"],"mappings":"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","ignoreList":[]}
@@ -1,6 +1,6 @@
1
1
  import { pushAtSortPosition } from 'array-push-at-sort-position';
2
2
  import { newRxError } from "../../rx-error.js";
3
- import { boundEQ } from "./binary-search-bounds.js";
3
+ import { boundEQByIndexString } from "./binary-search-bounds.js";
4
4
  export function getMemoryCollectionKey(databaseName, collectionName, schemaVersion) {
5
5
  return [databaseName, collectionName, schemaVersion].join('--memory--');
6
6
  }
@@ -12,6 +12,14 @@ export function ensureNotRemoved(instance) {
12
12
  export function attachmentMapKey(documentId, attachmentId) {
13
13
  return documentId + '||' + attachmentId;
14
14
  }
15
+
16
+ /**
17
+ * @performance
18
+ * Threshold for using in-place splice vs. full merge-sort when inserting
19
+ * documents into indexes. Below this batch size, in-place binary search + splice
20
+ * is faster because it avoids allocating a new full-size array and copying all elements.
21
+ */
22
+ var IN_PLACE_INSERT_THRESHOLD = 64;
15
23
  function sortByIndexStringComparator(a, b) {
16
24
  if (a[0] < b[0]) {
17
25
  return -1;
@@ -25,29 +33,57 @@ function sortByIndexStringComparator(a, b) {
25
33
  */
26
34
  export function putWriteRowToState(docId, state, stateByIndex, document, docInState) {
27
35
  state.documents.set(docId, document);
28
- for (var i = 0; i < stateByIndex.length; ++i) {
36
+ var stateByIndexLength = stateByIndex.length;
37
+ for (var i = 0; i < stateByIndexLength; ++i) {
29
38
  var byIndex = stateByIndex[i];
30
39
  var docsWithIndex = byIndex.docsWithIndex;
31
40
  var getIndexableString = byIndex.getIndexableString;
32
41
  var newIndexString = getIndexableString(document);
33
- var insertPosition = pushAtSortPosition(docsWithIndex, [newIndexString, document, docId], sortByIndexStringComparator, 0);
34
42
 
35
43
  /**
36
- * Remove previous if it was in the state
44
+ * @performance
45
+ * When updating a document, first compute whether the index changed.
46
+ * If it did not change, we only need to update the document reference
47
+ * in-place without any splice operations.
37
48
  */
38
49
  if (docInState) {
39
50
  var previousIndexString = getIndexableString(docInState);
40
51
  if (previousIndexString === newIndexString) {
41
52
  /**
42
53
  * Performance shortcut.
43
- * If index was not changed -> The old doc must be before or after the new one.
54
+ * Index did not change, so the old entry is at the same position.
55
+ * We can find it by string-specialized binary search and update in-place.
44
56
  */
45
- var prev = docsWithIndex[insertPosition - 1];
46
- if (prev && prev[2] === docId) {
57
+ var eqPos = boundEQByIndexString(docsWithIndex, previousIndexString);
58
+ if (eqPos !== -1) {
59
+ /**
60
+ * There might be multiple entries with the same index string
61
+ * (e.g. different documents). Search around eqPos for ours.
62
+ */
63
+ if (docsWithIndex[eqPos][2] === docId) {
64
+ docsWithIndex[eqPos][1] = document;
65
+ continue;
66
+ }
67
+ // Check neighbors
68
+ var prev = docsWithIndex[eqPos - 1];
69
+ if (prev && prev[0] === previousIndexString && prev[2] === docId) {
70
+ docsWithIndex[eqPos - 1][1] = document;
71
+ continue;
72
+ }
73
+ var next = docsWithIndex[eqPos + 1];
74
+ if (next && next[0] === previousIndexString && next[2] === docId) {
75
+ docsWithIndex[eqPos + 1][1] = document;
76
+ continue;
77
+ }
78
+ }
79
+ // Fallback: use the old insert+remove approach
80
+ var insertPosition = pushAtSortPosition(docsWithIndex, [newIndexString, document, docId], sortByIndexStringComparator, 0);
81
+ var prevEntry = docsWithIndex[insertPosition - 1];
82
+ if (prevEntry && prevEntry[2] === docId) {
47
83
  docsWithIndex.splice(insertPosition - 1, 1);
48
84
  } else {
49
- var next = docsWithIndex[insertPosition + 1];
50
- if (next[2] === docId) {
85
+ var nextEntry = docsWithIndex[insertPosition + 1];
86
+ if (nextEntry[2] === docId) {
51
87
  docsWithIndex.splice(insertPosition + 1, 1);
52
88
  } else {
53
89
  throw newRxError('SNH', {
@@ -58,26 +94,35 @@ export function putWriteRowToState(docId, state, stateByIndex, document, docInSt
58
94
  });
59
95
  }
60
96
  }
97
+ continue;
61
98
  } else {
62
99
  /**
63
- * Index changed, we must search for the old one and remove it.
100
+ * Index changed, we must remove the old entry and insert the new one.
64
101
  */
65
- var indexBefore = boundEQ(docsWithIndex, [previousIndexString], compareDocsWithIndex);
66
- docsWithIndex.splice(indexBefore, 1);
102
+ var indexBefore = boundEQByIndexString(docsWithIndex, previousIndexString);
103
+ if (indexBefore !== -1) {
104
+ docsWithIndex.splice(indexBefore, 1);
105
+ }
67
106
  }
68
107
  }
108
+ pushAtSortPosition(docsWithIndex, [newIndexString, document, docId], sortByIndexStringComparator, 0);
69
109
  }
70
110
  }
71
111
 
72
112
  /**
73
113
  * @hotPath
74
114
  * Efficiently inserts multiple documents into the state at once.
75
- * Instead of inserting one-by-one with Array.splice() (O(n) per insert),
76
- * this pre-computes all index entries, sorts them, and merges them into
77
- * the existing sorted arrays in a single pass (O(n log n + n + m)).
115
+ *
116
+ * Uses two strategies based on batch size:
117
+ * - For small batches (relative to existing index size), uses in-place
118
+ * binary search + splice per document. This avoids allocating a new
119
+ * full-size array and copying all elements, reducing GC pressure.
120
+ * - For large batches (or empty indexes), pre-computes all index entries,
121
+ * sorts them, and merges into the existing sorted arrays in a single pass.
78
122
  */
79
123
  export function bulkInsertToState(primaryPath, state, stateByIndex, docs) {
80
124
  var docsLength = docs.length;
125
+ var stateByIndexLength = stateByIndex.length;
81
126
 
82
127
  // Extract documents and docIds once, store in Map
83
128
  var documents = new Array(docsLength);
@@ -90,36 +135,74 @@ export function bulkInsertToState(primaryPath, state, stateByIndex, docs) {
90
135
  state.documents.set(docId, doc);
91
136
  }
92
137
 
93
- // For each index, batch-compute entries, sort, and merge
94
- for (var indexI = 0; indexI < stateByIndex.length; ++indexI) {
95
- var byIndex = stateByIndex[indexI];
96
- var docsWithIndex = byIndex.docsWithIndex;
97
- var getIndexableString = byIndex.getIndexableString;
98
-
99
- // Build new entries
100
- var newEntries = new Array(docsLength);
101
- for (var _i = 0; _i < docsLength; ++_i) {
102
- var _doc = documents[_i];
103
- newEntries[_i] = [getIndexableString(_doc), _doc, docIds[_i]];
138
+ /**
139
+ * @performance
140
+ * For small batch sizes, use in-place binary search + splice
141
+ * instead of creating a full merged array copy. This is faster
142
+ * for serial inserts and small bulk inserts because it avoids:
143
+ * - Allocating a new array of size n+m
144
+ * - Copying all n existing elements
145
+ * - GC pressure from discarding the old array
146
+ *
147
+ * The threshold is based on when the merge approach becomes more
148
+ * efficient than individual splices.
149
+ */
150
+ var useInPlaceInsert = docsLength < IN_PLACE_INSERT_THRESHOLD;
151
+ if (useInPlaceInsert) {
152
+ for (var indexI = 0; indexI < stateByIndexLength; ++indexI) {
153
+ var byIndex = stateByIndex[indexI];
154
+ var docsWithIndex = byIndex.docsWithIndex;
155
+ var getIndexableString = byIndex.getIndexableString;
156
+ if (docsWithIndex.length === 0) {
157
+ for (var _i = 0; _i < docsLength; ++_i) {
158
+ var _doc = documents[_i];
159
+ var indexString = getIndexableString(_doc);
160
+ docsWithIndex.push([indexString, _doc, docIds[_i]]);
161
+ }
162
+ docsWithIndex.sort(sortByIndexStringComparator);
163
+ } else {
164
+ for (var _i2 = 0; _i2 < docsLength; ++_i2) {
165
+ var _doc2 = documents[_i2];
166
+ var _indexString = getIndexableString(_doc2);
167
+ var newEntry = [_indexString, _doc2, docIds[_i2]];
168
+ pushAtSortPosition(docsWithIndex, newEntry, sortByIndexStringComparator, 0);
169
+ }
170
+ }
104
171
  }
172
+ } else {
173
+ // For each index, batch-compute entries, sort, and merge
174
+ for (var _indexI = 0; _indexI < stateByIndexLength; ++_indexI) {
175
+ var _byIndex = stateByIndex[_indexI];
176
+ var _docsWithIndex = _byIndex.docsWithIndex;
177
+ var _getIndexableString = _byIndex.getIndexableString;
105
178
 
106
- // Sort by index string
107
- newEntries.sort(sortByIndexStringComparator);
108
- if (docsWithIndex.length === 0) {
109
- // Index is empty, just assign sorted entries
110
- byIndex.docsWithIndex = newEntries;
111
- } else {
112
- // Merge sorted arrays
113
- byIndex.docsWithIndex = mergeSortedArrays(docsWithIndex, newEntries, sortByIndexStringComparator);
179
+ // Build new entries
180
+ var newEntries = new Array(docsLength);
181
+ for (var _i3 = 0; _i3 < docsLength; ++_i3) {
182
+ var _doc3 = documents[_i3];
183
+ newEntries[_i3] = [_getIndexableString(_doc3), _doc3, docIds[_i3]];
184
+ }
185
+
186
+ // Sort by index string
187
+ newEntries.sort(sortByIndexStringComparator);
188
+ if (_docsWithIndex.length === 0) {
189
+ // Index is empty, just assign sorted entries
190
+ _byIndex.docsWithIndex = newEntries;
191
+ } else {
192
+ // Merge sorted arrays
193
+ _byIndex.docsWithIndex = mergeSortedArrays(_docsWithIndex, newEntries);
194
+ }
114
195
  }
115
196
  }
116
197
  }
117
198
 
118
199
  /**
119
- * Merges two sorted arrays into a single sorted array.
200
+ * Merges two sorted DocWithIndexString arrays into a single sorted array.
120
201
  * Runs in O(n + m) where n and m are the lengths of the input arrays.
202
+ * @performance Comparator is inlined to avoid function call overhead
203
+ * per comparison, which is significant for large arrays.
121
204
  */
122
- function mergeSortedArrays(a, b, comparator) {
205
+ function mergeSortedArrays(a, b) {
123
206
  var aLen = a.length;
124
207
  var bLen = b.length;
125
208
  var result = new Array(aLen + bLen);
@@ -127,7 +210,7 @@ function mergeSortedArrays(a, b, comparator) {
127
210
  var bi = 0;
128
211
  var ri = 0;
129
212
  while (ai < aLen && bi < bLen) {
130
- if (comparator(a[ai], b[bi]) <= 0) {
213
+ if (a[ai][0] <= b[bi][0]) {
131
214
  result[ri++] = a[ai++];
132
215
  } else {
133
216
  result[ri++] = b[bi++];
@@ -144,12 +227,16 @@ function mergeSortedArrays(a, b, comparator) {
144
227
  export function removeDocFromState(primaryPath, schema, state, doc) {
145
228
  var docId = doc[primaryPath];
146
229
  state.documents.delete(docId);
147
- Object.values(state.byIndex).forEach(byIndex => {
230
+ var stateByIndex = state.byIndexArray;
231
+ for (var i = 0; i < stateByIndex.length; ++i) {
232
+ var byIndex = stateByIndex[i];
148
233
  var docsWithIndex = byIndex.docsWithIndex;
149
234
  var indexString = byIndex.getIndexableString(doc);
150
- var positionInIndex = boundEQ(docsWithIndex, [indexString], compareDocsWithIndex);
151
- docsWithIndex.splice(positionInIndex, 1);
152
- });
235
+ var positionInIndex = boundEQByIndexString(docsWithIndex, indexString);
236
+ if (positionInIndex !== -1) {
237
+ docsWithIndex.splice(positionInIndex, 1);
238
+ }
239
+ }
153
240
  }
154
241
  export function compareDocsWithIndex(a, b) {
155
242
  var indexStringA = a[0];
@@ -1 +1 @@
1
- {"version":3,"file":"memory-helper.js","names":["pushAtSortPosition","newRxError","boundEQ","getMemoryCollectionKey","databaseName","collectionName","schemaVersion","join","ensureNotRemoved","instance","internals","removed","Error","schema","version","attachmentMapKey","documentId","attachmentId","sortByIndexStringComparator","a","b","putWriteRowToState","docId","state","stateByIndex","document","docInState","documents","set","i","length","byIndex","docsWithIndex","getIndexableString","newIndexString","insertPosition","previousIndexString","prev","splice","next","args","indexBefore","compareDocsWithIndex","bulkInsertToState","primaryPath","docs","docsLength","Array","docIds","doc","indexI","newEntries","sort","mergeSortedArrays","comparator","aLen","bLen","result","ai","bi","ri","removeDocFromState","delete","Object","values","forEach","indexString","positionInIndex","indexStringA","indexStringB"],"sources":["../../../../src/plugins/storage-memory/memory-helper.ts"],"sourcesContent":["import type {\r\n BulkWriteRow,\r\n RxDocumentData,\r\n RxJsonSchema\r\n} from '../../types/index.d.ts';\r\nimport type {\r\n DocWithIndexString,\r\n MemoryStorageInternals,\r\n MemoryStorageInternalsByIndex\r\n} from './memory-types.ts';\r\nimport type { RxStorageInstanceMemory } from './rx-storage-instance-memory.ts';\r\nimport {\r\n pushAtSortPosition\r\n} from 'array-push-at-sort-position';\r\nimport { newRxError } from '../../rx-error.ts';\r\nimport { boundEQ } from './binary-search-bounds.ts';\r\n\r\n\r\nexport function getMemoryCollectionKey(\r\n databaseName: string,\r\n collectionName: string,\r\n schemaVersion: number\r\n): string {\r\n return [\r\n databaseName,\r\n collectionName,\r\n schemaVersion\r\n ].join('--memory--');\r\n}\r\n\r\n\r\nexport function ensureNotRemoved(\r\n instance: RxStorageInstanceMemory<any>\r\n) {\r\n if (instance.internals.removed) {\r\n throw new Error(\r\n 'removed already ' +\r\n instance.databaseName + ' - ' + instance.collectionName +\r\n ' - ' + instance.schema.version\r\n );\r\n }\r\n}\r\n\r\nexport function attachmentMapKey(documentId: string, attachmentId: string): string {\r\n return documentId + '||' + attachmentId;\r\n}\r\n\r\n\r\nfunction sortByIndexStringComparator<RxDocType>(a: DocWithIndexString<RxDocType>, b: DocWithIndexString<RxDocType>) {\r\n if (a[0] < b[0]) {\r\n return -1;\r\n } else {\r\n return 1;\r\n }\r\n}\r\n\r\n\r\n\r\n/**\r\n * @hotPath\r\n */\r\nexport function putWriteRowToState<RxDocType>(\r\n docId: string,\r\n state: MemoryStorageInternals<RxDocType>,\r\n stateByIndex: MemoryStorageInternalsByIndex<RxDocType>[],\r\n document: RxDocumentData<RxDocType>,\r\n docInState?: RxDocumentData<RxDocType>\r\n) {\r\n state.documents.set(docId, document as any);\r\n for (let i = 0; i < stateByIndex.length; ++i) {\r\n const byIndex = stateByIndex[i];\r\n const docsWithIndex = byIndex.docsWithIndex;\r\n const getIndexableString = byIndex.getIndexableString;\r\n const newIndexString = getIndexableString(document as any);\r\n const insertPosition = pushAtSortPosition(\r\n docsWithIndex,\r\n [\r\n newIndexString,\r\n document,\r\n docId,\r\n ],\r\n sortByIndexStringComparator,\r\n 0\r\n );\r\n\r\n /**\r\n * Remove previous if it was in the state\r\n */\r\n if (docInState) {\r\n const previousIndexString = getIndexableString(docInState);\r\n if (previousIndexString === newIndexString) {\r\n /**\r\n * Performance shortcut.\r\n * If index was not changed -> The old doc must be before or after the new one.\r\n */\r\n const prev = docsWithIndex[insertPosition - 1];\r\n if (prev && prev[2] === docId) {\r\n docsWithIndex.splice(insertPosition - 1, 1);\r\n } else {\r\n const next = docsWithIndex[insertPosition + 1];\r\n if (next[2] === docId) {\r\n docsWithIndex.splice(insertPosition + 1, 1);\r\n } else {\r\n throw newRxError('SNH', {\r\n document,\r\n args: {\r\n byIndex\r\n }\r\n });\r\n }\r\n }\r\n } else {\r\n /**\r\n * Index changed, we must search for the old one and remove it.\r\n */\r\n const indexBefore = boundEQ(\r\n docsWithIndex,\r\n [\r\n previousIndexString\r\n ] as any,\r\n compareDocsWithIndex\r\n );\r\n docsWithIndex.splice(indexBefore, 1);\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n/**\r\n * @hotPath\r\n * Efficiently inserts multiple documents into the state at once.\r\n * Instead of inserting one-by-one with Array.splice() (O(n) per insert),\r\n * this pre-computes all index entries, sorts them, and merges them into\r\n * the existing sorted arrays in a single pass (O(n log n + n + m)).\r\n */\r\nexport function bulkInsertToState<RxDocType>(\r\n primaryPath: string,\r\n state: MemoryStorageInternals<RxDocType>,\r\n stateByIndex: MemoryStorageInternalsByIndex<RxDocType>[],\r\n docs: { document: RxDocumentData<RxDocType> }[]\r\n) {\r\n const docsLength = docs.length;\r\n\r\n // Extract documents and docIds once, store in Map\r\n const documents: RxDocumentData<RxDocType>[] = new Array(docsLength);\r\n const docIds: string[] = new Array(docsLength);\r\n for (let i = 0; i < docsLength; ++i) {\r\n const doc = docs[i].document;\r\n const docId: string = (doc as any)[primaryPath];\r\n documents[i] = doc;\r\n docIds[i] = docId;\r\n state.documents.set(docId, doc as any);\r\n }\r\n\r\n // For each index, batch-compute entries, sort, and merge\r\n for (let indexI = 0; indexI < stateByIndex.length; ++indexI) {\r\n const byIndex = stateByIndex[indexI];\r\n const docsWithIndex = byIndex.docsWithIndex;\r\n const getIndexableString = byIndex.getIndexableString;\r\n\r\n // Build new entries\r\n const newEntries: DocWithIndexString<RxDocType>[] = new Array(docsLength);\r\n for (let i = 0; i < docsLength; ++i) {\r\n const doc = documents[i];\r\n newEntries[i] = [\r\n getIndexableString(doc as any),\r\n doc,\r\n docIds[i]\r\n ];\r\n }\r\n\r\n // Sort by index string\r\n newEntries.sort(sortByIndexStringComparator);\r\n\r\n if (docsWithIndex.length === 0) {\r\n // Index is empty, just assign sorted entries\r\n byIndex.docsWithIndex = newEntries;\r\n } else {\r\n // Merge sorted arrays\r\n byIndex.docsWithIndex = mergeSortedArrays(docsWithIndex, newEntries, sortByIndexStringComparator);\r\n }\r\n }\r\n}\r\n\r\n\r\n/**\r\n * Merges two sorted arrays into a single sorted array.\r\n * Runs in O(n + m) where n and m are the lengths of the input arrays.\r\n */\r\nfunction mergeSortedArrays<T>(\r\n a: T[],\r\n b: T[],\r\n comparator: (x: T, y: T) => number\r\n): T[] {\r\n const aLen = a.length;\r\n const bLen = b.length;\r\n const result: T[] = new Array(aLen + bLen);\r\n let ai = 0;\r\n let bi = 0;\r\n let ri = 0;\r\n\r\n while (ai < aLen && bi < bLen) {\r\n if (comparator(a[ai], b[bi]) <= 0) {\r\n result[ri++] = a[ai++];\r\n } else {\r\n result[ri++] = b[bi++];\r\n }\r\n }\r\n\r\n while (ai < aLen) {\r\n result[ri++] = a[ai++];\r\n }\r\n while (bi < bLen) {\r\n result[ri++] = b[bi++];\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport function removeDocFromState<RxDocType>(\r\n primaryPath: string,\r\n schema: RxJsonSchema<RxDocumentData<RxDocType>>,\r\n state: MemoryStorageInternals<RxDocType>,\r\n doc: RxDocumentData<RxDocType>\r\n) {\r\n const docId: string = (doc as any)[primaryPath];\r\n state.documents.delete(docId);\r\n\r\n Object.values(state.byIndex).forEach(byIndex => {\r\n const docsWithIndex = byIndex.docsWithIndex;\r\n const indexString = byIndex.getIndexableString(doc);\r\n\r\n const positionInIndex = boundEQ(\r\n docsWithIndex,\r\n [\r\n indexString\r\n ] as any,\r\n compareDocsWithIndex\r\n );\r\n docsWithIndex.splice(positionInIndex, 1);\r\n });\r\n}\r\n\r\n\r\nexport function compareDocsWithIndex<RxDocType>(\r\n a: DocWithIndexString<RxDocType>,\r\n b: DocWithIndexString<RxDocType>\r\n): 1 | 0 | -1 {\r\n const indexStringA = a[0];\r\n const indexStringB = b[0];\r\n if (indexStringA < indexStringB) {\r\n return -1;\r\n } else if (indexStringA === indexStringB) {\r\n return 0;\r\n } else {\r\n return 1;\r\n }\r\n}\r\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"memory-helper.js","names":["pushAtSortPosition","newRxError","boundEQByIndexString","getMemoryCollectionKey","databaseName","collectionName","schemaVersion","join","ensureNotRemoved","instance","internals","removed","Error","schema","version","attachmentMapKey","documentId","attachmentId","IN_PLACE_INSERT_THRESHOLD","sortByIndexStringComparator","a","b","putWriteRowToState","docId","state","stateByIndex","document","docInState","documents","set","stateByIndexLength","length","i","byIndex","docsWithIndex","getIndexableString","newIndexString","previousIndexString","eqPos","prev","next","insertPosition","prevEntry","splice","nextEntry","args","indexBefore","bulkInsertToState","primaryPath","docs","docsLength","Array","docIds","doc","useInPlaceInsert","indexI","indexString","push","sort","newEntry","newEntries","mergeSortedArrays","aLen","bLen","result","ai","bi","ri","removeDocFromState","delete","byIndexArray","positionInIndex","compareDocsWithIndex","indexStringA","indexStringB"],"sources":["../../../../src/plugins/storage-memory/memory-helper.ts"],"sourcesContent":["import type {\r\n RxDocumentData,\r\n RxJsonSchema\r\n} from '../../types/index.d.ts';\r\nimport type {\r\n DocWithIndexString,\r\n MemoryStorageInternals,\r\n MemoryStorageInternalsByIndex\r\n} from './memory-types.ts';\r\nimport type { RxStorageInstanceMemory } from './rx-storage-instance-memory.ts';\r\nimport {\r\n pushAtSortPosition\r\n} from 'array-push-at-sort-position';\r\nimport { newRxError } from '../../rx-error.ts';\r\nimport { boundEQByIndexString } from './binary-search-bounds.ts';\r\n\r\n\r\nexport function getMemoryCollectionKey(\r\n databaseName: string,\r\n collectionName: string,\r\n schemaVersion: number\r\n): string {\r\n return [\r\n databaseName,\r\n collectionName,\r\n schemaVersion\r\n ].join('--memory--');\r\n}\r\n\r\n\r\nexport function ensureNotRemoved(\r\n instance: RxStorageInstanceMemory<any>\r\n) {\r\n if (instance.internals.removed) {\r\n throw new Error(\r\n 'removed already ' +\r\n instance.databaseName + ' - ' + instance.collectionName +\r\n ' - ' + instance.schema.version\r\n );\r\n }\r\n}\r\n\r\nexport function attachmentMapKey(documentId: string, attachmentId: string): string {\r\n return documentId + '||' + attachmentId;\r\n}\r\n\r\n\r\n/**\r\n * @performance\r\n * Threshold for using in-place splice vs. full merge-sort when inserting\r\n * documents into indexes. Below this batch size, in-place binary search + splice\r\n * is faster because it avoids allocating a new full-size array and copying all elements.\r\n */\r\nconst IN_PLACE_INSERT_THRESHOLD = 64;\r\n\r\nfunction sortByIndexStringComparator<RxDocType>(a: DocWithIndexString<RxDocType>, b: DocWithIndexString<RxDocType>) {\r\n if (a[0] < b[0]) {\r\n return -1;\r\n } else {\r\n return 1;\r\n }\r\n}\r\n\r\n\r\n\r\n/**\r\n * @hotPath\r\n */\r\nexport function putWriteRowToState<RxDocType>(\r\n docId: string,\r\n state: MemoryStorageInternals<RxDocType>,\r\n stateByIndex: MemoryStorageInternalsByIndex<RxDocType>[],\r\n document: RxDocumentData<RxDocType>,\r\n docInState?: RxDocumentData<RxDocType>\r\n) {\r\n state.documents.set(docId, document as any);\r\n const stateByIndexLength = stateByIndex.length;\r\n for (let i = 0; i < stateByIndexLength; ++i) {\r\n const byIndex = stateByIndex[i];\r\n const docsWithIndex = byIndex.docsWithIndex;\r\n const getIndexableString = byIndex.getIndexableString;\r\n const newIndexString = getIndexableString(document as any);\r\n\r\n /**\r\n * @performance\r\n * When updating a document, first compute whether the index changed.\r\n * If it did not change, we only need to update the document reference\r\n * in-place without any splice operations.\r\n */\r\n if (docInState) {\r\n const previousIndexString = getIndexableString(docInState);\r\n if (previousIndexString === newIndexString) {\r\n /**\r\n * Performance shortcut.\r\n * Index did not change, so the old entry is at the same position.\r\n * We can find it by string-specialized binary search and update in-place.\r\n */\r\n const eqPos = boundEQByIndexString(\r\n docsWithIndex,\r\n previousIndexString\r\n );\r\n if (eqPos !== -1) {\r\n /**\r\n * There might be multiple entries with the same index string\r\n * (e.g. different documents). Search around eqPos for ours.\r\n */\r\n if (docsWithIndex[eqPos][2] === docId) {\r\n docsWithIndex[eqPos][1] = document;\r\n continue;\r\n }\r\n // Check neighbors\r\n const prev = docsWithIndex[eqPos - 1];\r\n if (prev && prev[0] === previousIndexString && prev[2] === docId) {\r\n docsWithIndex[eqPos - 1][1] = document;\r\n continue;\r\n }\r\n const next = docsWithIndex[eqPos + 1];\r\n if (next && next[0] === previousIndexString && next[2] === docId) {\r\n docsWithIndex[eqPos + 1][1] = document;\r\n continue;\r\n }\r\n }\r\n // Fallback: use the old insert+remove approach\r\n const insertPosition = pushAtSortPosition(\r\n docsWithIndex,\r\n [newIndexString, document, docId],\r\n sortByIndexStringComparator,\r\n 0\r\n );\r\n const prevEntry = docsWithIndex[insertPosition - 1];\r\n if (prevEntry && prevEntry[2] === docId) {\r\n docsWithIndex.splice(insertPosition - 1, 1);\r\n } else {\r\n const nextEntry = docsWithIndex[insertPosition + 1];\r\n if (nextEntry[2] === docId) {\r\n docsWithIndex.splice(insertPosition + 1, 1);\r\n } else {\r\n throw newRxError('SNH', {\r\n document,\r\n args: {\r\n byIndex\r\n }\r\n });\r\n }\r\n }\r\n continue;\r\n } else {\r\n /**\r\n * Index changed, we must remove the old entry and insert the new one.\r\n */\r\n const indexBefore = boundEQByIndexString(\r\n docsWithIndex,\r\n previousIndexString\r\n );\r\n if (indexBefore !== -1) {\r\n docsWithIndex.splice(indexBefore, 1);\r\n }\r\n }\r\n }\r\n\r\n pushAtSortPosition(\r\n docsWithIndex,\r\n [newIndexString, document, docId],\r\n sortByIndexStringComparator,\r\n 0\r\n );\r\n }\r\n}\r\n\r\n\r\n/**\r\n * @hotPath\r\n * Efficiently inserts multiple documents into the state at once.\r\n *\r\n * Uses two strategies based on batch size:\r\n * - For small batches (relative to existing index size), uses in-place\r\n * binary search + splice per document. This avoids allocating a new\r\n * full-size array and copying all elements, reducing GC pressure.\r\n * - For large batches (or empty indexes), pre-computes all index entries,\r\n * sorts them, and merges into the existing sorted arrays in a single pass.\r\n */\r\nexport function bulkInsertToState<RxDocType>(\r\n primaryPath: string,\r\n state: MemoryStorageInternals<RxDocType>,\r\n stateByIndex: MemoryStorageInternalsByIndex<RxDocType>[],\r\n docs: { document: RxDocumentData<RxDocType> }[]\r\n) {\r\n const docsLength = docs.length;\r\n const stateByIndexLength = stateByIndex.length;\r\n\r\n // Extract documents and docIds once, store in Map\r\n const documents: RxDocumentData<RxDocType>[] = new Array(docsLength);\r\n const docIds: string[] = new Array(docsLength);\r\n for (let i = 0; i < docsLength; ++i) {\r\n const doc = docs[i].document;\r\n const docId: string = (doc as any)[primaryPath];\r\n documents[i] = doc;\r\n docIds[i] = docId;\r\n state.documents.set(docId, doc as any);\r\n }\r\n\r\n /**\r\n * @performance\r\n * For small batch sizes, use in-place binary search + splice\r\n * instead of creating a full merged array copy. This is faster\r\n * for serial inserts and small bulk inserts because it avoids:\r\n * - Allocating a new array of size n+m\r\n * - Copying all n existing elements\r\n * - GC pressure from discarding the old array\r\n *\r\n * The threshold is based on when the merge approach becomes more\r\n * efficient than individual splices.\r\n */\r\n const useInPlaceInsert = docsLength < IN_PLACE_INSERT_THRESHOLD;\r\n\r\n if (useInPlaceInsert) {\r\n for (let indexI = 0; indexI < stateByIndexLength; ++indexI) {\r\n const byIndex = stateByIndex[indexI];\r\n const docsWithIndex = byIndex.docsWithIndex;\r\n const getIndexableString = byIndex.getIndexableString;\r\n\r\n if (docsWithIndex.length === 0) {\r\n for (let i = 0; i < docsLength; ++i) {\r\n const doc = documents[i];\r\n const indexString = getIndexableString(doc as any);\r\n docsWithIndex.push([indexString, doc, docIds[i]]);\r\n }\r\n docsWithIndex.sort(sortByIndexStringComparator);\r\n } else {\r\n for (let i = 0; i < docsLength; ++i) {\r\n const doc = documents[i];\r\n const indexString = getIndexableString(doc as any);\r\n const newEntry: DocWithIndexString<RxDocType> = [indexString, doc, docIds[i]];\r\n pushAtSortPosition(\r\n docsWithIndex,\r\n newEntry,\r\n sortByIndexStringComparator,\r\n 0\r\n );\r\n }\r\n }\r\n }\r\n } else {\r\n // For each index, batch-compute entries, sort, and merge\r\n for (let indexI = 0; indexI < stateByIndexLength; ++indexI) {\r\n const byIndex = stateByIndex[indexI];\r\n const docsWithIndex = byIndex.docsWithIndex;\r\n const getIndexableString = byIndex.getIndexableString;\r\n\r\n // Build new entries\r\n const newEntries: DocWithIndexString<RxDocType>[] = new Array(docsLength);\r\n for (let i = 0; i < docsLength; ++i) {\r\n const doc = documents[i];\r\n newEntries[i] = [\r\n getIndexableString(doc as any),\r\n doc,\r\n docIds[i]\r\n ];\r\n }\r\n\r\n // Sort by index string\r\n newEntries.sort(sortByIndexStringComparator);\r\n\r\n if (docsWithIndex.length === 0) {\r\n // Index is empty, just assign sorted entries\r\n byIndex.docsWithIndex = newEntries;\r\n } else {\r\n // Merge sorted arrays\r\n byIndex.docsWithIndex = mergeSortedArrays(docsWithIndex, newEntries);\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n/**\r\n * Merges two sorted DocWithIndexString arrays into a single sorted array.\r\n * Runs in O(n + m) where n and m are the lengths of the input arrays.\r\n * @performance Comparator is inlined to avoid function call overhead\r\n * per comparison, which is significant for large arrays.\r\n */\r\nfunction mergeSortedArrays<RxDocType>(\r\n a: DocWithIndexString<RxDocType>[],\r\n b: DocWithIndexString<RxDocType>[]\r\n): DocWithIndexString<RxDocType>[] {\r\n const aLen = a.length;\r\n const bLen = b.length;\r\n const result: DocWithIndexString<RxDocType>[] = new Array(aLen + bLen);\r\n let ai = 0;\r\n let bi = 0;\r\n let ri = 0;\r\n\r\n while (ai < aLen && bi < bLen) {\r\n if (a[ai][0] <= b[bi][0]) {\r\n result[ri++] = a[ai++];\r\n } else {\r\n result[ri++] = b[bi++];\r\n }\r\n }\r\n\r\n while (ai < aLen) {\r\n result[ri++] = a[ai++];\r\n }\r\n while (bi < bLen) {\r\n result[ri++] = b[bi++];\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport function removeDocFromState<RxDocType>(\r\n primaryPath: string,\r\n schema: RxJsonSchema<RxDocumentData<RxDocType>>,\r\n state: MemoryStorageInternals<RxDocType>,\r\n doc: RxDocumentData<RxDocType>\r\n) {\r\n const docId: string = (doc as any)[primaryPath];\r\n state.documents.delete(docId);\r\n\r\n const stateByIndex = state.byIndexArray;\r\n for (let i = 0; i < stateByIndex.length; ++i) {\r\n const byIndex = stateByIndex[i];\r\n const docsWithIndex = byIndex.docsWithIndex;\r\n const indexString = byIndex.getIndexableString(doc);\r\n\r\n const positionInIndex = boundEQByIndexString(\r\n docsWithIndex,\r\n indexString\r\n );\r\n if (positionInIndex !== -1) {\r\n docsWithIndex.splice(positionInIndex, 1);\r\n }\r\n }\r\n}\r\n\r\n\r\nexport function compareDocsWithIndex<RxDocType>(\r\n a: DocWithIndexString<RxDocType>,\r\n b: DocWithIndexString<RxDocType>\r\n): 1 | 0 | -1 {\r\n const indexStringA = a[0];\r\n const indexStringB = b[0];\r\n if (indexStringA < indexStringB) {\r\n return -1;\r\n } else if (indexStringA === indexStringB) {\r\n return 0;\r\n } else {\r\n return 1;\r\n }\r\n}\r\n"],"mappings":"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","ignoreList":[]}
@@ -14,6 +14,7 @@ export function addIndexesToInternalsState(state, schema) {
14
14
  getIndexableString: getIndexableStringMonad(schema, indexAr)
15
15
  };
16
16
  });
17
+ state.byIndexArray = Object.values(state.byIndex);
17
18
  }
18
19
  export function getMemoryIndexName(index) {
19
20
  return index.join(',');
@@ -1 +1 @@
1
- {"version":3,"file":"memory-indexes.js","names":["getIndexableStringMonad","getPrimaryFieldOfPrimaryKey","toArray","addIndexesToInternalsState","state","schema","primaryPath","primaryKey","useIndexes","indexes","map","row","push","forEach","indexAr","byIndex","getMemoryIndexName","index","docsWithIndex","getIndexableString","join"],"sources":["../../../../src/plugins/storage-memory/memory-indexes.ts"],"sourcesContent":["import { getIndexableStringMonad } from '../../custom-index.ts';\r\nimport { getPrimaryFieldOfPrimaryKey } from '../../rx-schema-helper.ts';\r\nimport type { RxDocumentData, RxJsonSchema } from '../../types/index.d.ts';\r\nimport { toArray } from '../../plugins/utils/index.ts';\r\nimport type { MemoryStorageInternals } from './memory-types.ts';\r\n\r\nexport function addIndexesToInternalsState<RxDocType>(\r\n state: MemoryStorageInternals<RxDocType>,\r\n schema: RxJsonSchema<RxDocumentData<RxDocType>>\r\n) {\r\n const primaryPath = getPrimaryFieldOfPrimaryKey(schema.primaryKey);\r\n const useIndexes: string[][] = !schema.indexes ? [] : schema.indexes.map(row => toArray(row)) as any;\r\n\r\n // we need this index for running cleanup()\r\n useIndexes.push([\r\n '_deleted',\r\n '_meta.lwt',\r\n primaryPath\r\n ]);\r\n\r\n\r\n useIndexes.forEach(indexAr => {\r\n state.byIndex[getMemoryIndexName(indexAr)] = {\r\n index: indexAr,\r\n docsWithIndex: [],\r\n getIndexableString: getIndexableStringMonad(schema, indexAr)\r\n };\r\n });\r\n}\r\n\r\n\r\nexport function getMemoryIndexName(index: string[]): string {\r\n return index.join(',');\r\n}\r\n"],"mappings":"AAAA,SAASA,uBAAuB,QAAQ,uBAAuB;AAC/D,SAASC,2BAA2B,QAAQ,2BAA2B;AAEvE,SAASC,OAAO,QAAQ,8BAA8B;AAGtD,OAAO,SAASC,0BAA0BA,CACtCC,KAAwC,EACxCC,MAA+C,EACjD;EACE,IAAMC,WAAW,GAAGL,2BAA2B,CAACI,MAAM,CAACE,UAAU,CAAC;EAClE,IAAMC,UAAsB,GAAG,CAACH,MAAM,CAACI,OAAO,GAAG,EAAE,GAAGJ,MAAM,CAACI,OAAO,CAACC,GAAG,CAACC,GAAG,IAAIT,OAAO,CAACS,GAAG,CAAC,CAAQ;;EAEpG;EACAH,UAAU,CAACI,IAAI,CAAC,CACZ,UAAU,EACV,WAAW,EACXN,WAAW,CACd,CAAC;EAGFE,UAAU,CAACK,OAAO,CAACC,OAAO,IAAI;IAC1BV,KAAK,CAACW,OAAO,CAACC,kBAAkB,CAACF,OAAO,CAAC,CAAC,GAAG;MACzCG,KAAK,EAAEH,OAAO;MACdI,aAAa,EAAE,EAAE;MACjBC,kBAAkB,EAAEnB,uBAAuB,CAACK,MAAM,EAAES,OAAO;IAC/D,CAAC;EACL,CAAC,CAAC;AACN;AAGA,OAAO,SAASE,kBAAkBA,CAACC,KAAe,EAAU;EACxD,OAAOA,KAAK,CAACG,IAAI,CAAC,GAAG,CAAC;AAC1B","ignoreList":[]}
1
+ {"version":3,"file":"memory-indexes.js","names":["getIndexableStringMonad","getPrimaryFieldOfPrimaryKey","toArray","addIndexesToInternalsState","state","schema","primaryPath","primaryKey","useIndexes","indexes","map","row","push","forEach","indexAr","byIndex","getMemoryIndexName","index","docsWithIndex","getIndexableString","byIndexArray","Object","values","join"],"sources":["../../../../src/plugins/storage-memory/memory-indexes.ts"],"sourcesContent":["import { getIndexableStringMonad } from '../../custom-index.ts';\r\nimport { getPrimaryFieldOfPrimaryKey } from '../../rx-schema-helper.ts';\r\nimport type { RxDocumentData, RxJsonSchema } from '../../types/index.d.ts';\r\nimport { toArray } from '../../plugins/utils/index.ts';\r\nimport type { MemoryStorageInternals } from './memory-types.ts';\r\n\r\nexport function addIndexesToInternalsState<RxDocType>(\r\n state: MemoryStorageInternals<RxDocType>,\r\n schema: RxJsonSchema<RxDocumentData<RxDocType>>\r\n) {\r\n const primaryPath = getPrimaryFieldOfPrimaryKey(schema.primaryKey);\r\n const useIndexes: string[][] = !schema.indexes ? [] : schema.indexes.map(row => toArray(row)) as any;\r\n\r\n // we need this index for running cleanup()\r\n useIndexes.push([\r\n '_deleted',\r\n '_meta.lwt',\r\n primaryPath\r\n ]);\r\n\r\n\r\n useIndexes.forEach(indexAr => {\r\n state.byIndex[getMemoryIndexName(indexAr)] = {\r\n index: indexAr,\r\n docsWithIndex: [],\r\n getIndexableString: getIndexableStringMonad(schema, indexAr)\r\n };\r\n });\r\n state.byIndexArray = Object.values(state.byIndex);\r\n}\r\n\r\n\r\nexport function getMemoryIndexName(index: string[]): string {\r\n return index.join(',');\r\n}\r\n"],"mappings":"AAAA,SAASA,uBAAuB,QAAQ,uBAAuB;AAC/D,SAASC,2BAA2B,QAAQ,2BAA2B;AAEvE,SAASC,OAAO,QAAQ,8BAA8B;AAGtD,OAAO,SAASC,0BAA0BA,CACtCC,KAAwC,EACxCC,MAA+C,EACjD;EACE,IAAMC,WAAW,GAAGL,2BAA2B,CAACI,MAAM,CAACE,UAAU,CAAC;EAClE,IAAMC,UAAsB,GAAG,CAACH,MAAM,CAACI,OAAO,GAAG,EAAE,GAAGJ,MAAM,CAACI,OAAO,CAACC,GAAG,CAACC,GAAG,IAAIT,OAAO,CAACS,GAAG,CAAC,CAAQ;;EAEpG;EACAH,UAAU,CAACI,IAAI,CAAC,CACZ,UAAU,EACV,WAAW,EACXN,WAAW,CACd,CAAC;EAGFE,UAAU,CAACK,OAAO,CAACC,OAAO,IAAI;IAC1BV,KAAK,CAACW,OAAO,CAACC,kBAAkB,CAACF,OAAO,CAAC,CAAC,GAAG;MACzCG,KAAK,EAAEH,OAAO;MACdI,aAAa,EAAE,EAAE;MACjBC,kBAAkB,EAAEnB,uBAAuB,CAACK,MAAM,EAAES,OAAO;IAC/D,CAAC;EACL,CAAC,CAAC;EACFV,KAAK,CAACgB,YAAY,GAAGC,MAAM,CAACC,MAAM,CAAClB,KAAK,CAACW,OAAO,CAAC;AACrD;AAGA,OAAO,SAASC,kBAAkBA,CAACC,KAAe,EAAU;EACxD,OAAOA,KAAK,CAACM,IAAI,CAAC,GAAG,CAAC;AAC1B","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"memory-types.js","names":[],"sources":["../../../../src/plugins/storage-memory/memory-types.ts"],"sourcesContent":["import { Subject } from 'rxjs';\r\nimport type {\r\n CategorizeBulkWriteRowsOutput,\r\n EventBulk,\r\n RxAttachmentWriteData,\r\n RxDocumentData,\r\n RxJsonSchema,\r\n RxStorage,\r\n RxStorageChangeEvent,\r\n RxStorageDefaultCheckpoint\r\n} from '../../types/index.d.ts';\r\n\r\nexport type RxStorageMemorySettings = {};\r\nexport type RxStorageMemoryInstanceCreationOptions = {};\r\nexport type RxStorageMemory = RxStorage<MemoryStorageInternals<any>, RxStorageMemoryInstanceCreationOptions> & {\r\n /**\r\n * State by collectionKey\r\n */\r\n collectionStates: Map<string, MemoryStorageInternals<any>>;\r\n};\r\n\r\nexport type MemoryStorageInternalsByIndex<RxDocType> = {\r\n index: string[];\r\n docsWithIndex: DocWithIndexString<RxDocType>[];\r\n getIndexableString: (docData: RxDocumentData<RxDocType>) => string;\r\n};\r\n\r\n/**\r\n * The internals are shared between multiple storage instances\r\n * that have been created with the same [databaseName+collectionName] combination.\r\n */\r\nexport type MemoryStorageInternals<RxDocType> = {\r\n // used to debug stuff and identify instances\r\n id: string;\r\n\r\n /**\r\n * Schema of the first instance created with the given settings.\r\n * Used to ensure that the same storage is not re-created with\r\n * a different schema.\r\n */\r\n schema: RxJsonSchema<RxDocumentData<RxDocType>>;\r\n\r\n /**\r\n * We reuse the memory state when multiple instances\r\n * are created with the same params.\r\n * If refCount becomes 0, we can delete the state.\r\n */\r\n refCount: number;\r\n /**\r\n * If this becomes true,\r\n * it means that an instance has called remove()\r\n * so all other instances should also not work anymore.\r\n */\r\n removed: boolean;\r\n documents: Map<string, RxDocumentData<RxDocType>>;\r\n /**\r\n * Attachments data, indexed by a combined string\r\n * consisting of [documentId + '||' + attachmentId]\r\n */\r\n attachments: Map<string, {\r\n writeData: RxAttachmentWriteData;\r\n digest: string;\r\n }>;\r\n byIndex: {\r\n /**\r\n * Because RxDB requires a deterministic sorting\r\n * on all indexes, we can be sure that the composed index key\r\n * of each document is unique, because it contains the primaryKey\r\n * as last index part.\r\n * So we do not have to store the index-position when we want to do fast\r\n * writes. Instead we can do a binary search over the existing array\r\n * because RxDB also knows the previous state of the document when we do a bulkWrite().\r\n */\r\n [indexName: string]: MemoryStorageInternalsByIndex<RxDocType>;\r\n };\r\n\r\n /**\r\n * We need these to do lazy writes.\r\n */\r\n ensurePersistenceTask?: CategorizeBulkWriteRowsOutput<RxDocType>;\r\n ensurePersistenceIdlePromise?: Promise<void>;\r\n\r\n changes$: Subject<EventBulk<RxStorageChangeEvent<RxDocumentData<RxDocType>>, RxStorageDefaultCheckpoint>>;\r\n};\r\n\r\nexport type DocWithIndexString<RxDocType> = [\r\n string, // indexString, must be first because often we only need that one.\r\n RxDocumentData<RxDocType>, // document\r\n string, // id\r\n];\r\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"memory-types.js","names":[],"sources":["../../../../src/plugins/storage-memory/memory-types.ts"],"sourcesContent":["import { Subject } from 'rxjs';\r\nimport type {\r\n CategorizeBulkWriteRowsOutput,\r\n EventBulk,\r\n RxAttachmentWriteData,\r\n RxDocumentData,\r\n RxJsonSchema,\r\n RxStorage,\r\n RxStorageChangeEvent,\r\n RxStorageDefaultCheckpoint\r\n} from '../../types/index.d.ts';\r\n\r\nexport type RxStorageMemorySettings = {};\r\nexport type RxStorageMemoryInstanceCreationOptions = {};\r\nexport type RxStorageMemory = RxStorage<MemoryStorageInternals<any>, RxStorageMemoryInstanceCreationOptions> & {\r\n /**\r\n * State by collectionKey\r\n */\r\n collectionStates: Map<string, MemoryStorageInternals<any>>;\r\n};\r\n\r\nexport type MemoryStorageInternalsByIndex<RxDocType> = {\r\n index: string[];\r\n docsWithIndex: DocWithIndexString<RxDocType>[];\r\n getIndexableString: (docData: RxDocumentData<RxDocType>) => string;\r\n};\r\n\r\n/**\r\n * The internals are shared between multiple storage instances\r\n * that have been created with the same [databaseName+collectionName] combination.\r\n */\r\nexport type MemoryStorageInternals<RxDocType> = {\r\n // used to debug stuff and identify instances\r\n id: string;\r\n\r\n /**\r\n * Schema of the first instance created with the given settings.\r\n * Used to ensure that the same storage is not re-created with\r\n * a different schema.\r\n */\r\n schema: RxJsonSchema<RxDocumentData<RxDocType>>;\r\n\r\n /**\r\n * We reuse the memory state when multiple instances\r\n * are created with the same params.\r\n * If refCount becomes 0, we can delete the state.\r\n */\r\n refCount: number;\r\n /**\r\n * If this becomes true,\r\n * it means that an instance has called remove()\r\n * so all other instances should also not work anymore.\r\n */\r\n removed: boolean;\r\n documents: Map<string, RxDocumentData<RxDocType>>;\r\n /**\r\n * Attachments data, indexed by a combined string\r\n * consisting of [documentId + '||' + attachmentId]\r\n */\r\n attachments: Map<string, {\r\n writeData: RxAttachmentWriteData;\r\n digest: string;\r\n }>;\r\n byIndex: {\r\n /**\r\n * Because RxDB requires a deterministic sorting\r\n * on all indexes, we can be sure that the composed index key\r\n * of each document is unique, because it contains the primaryKey\r\n * as last index part.\r\n * So we do not have to store the index-position when we want to do fast\r\n * writes. Instead we can do a binary search over the existing array\r\n * because RxDB also knows the previous state of the document when we do a bulkWrite().\r\n */\r\n [indexName: string]: MemoryStorageInternalsByIndex<RxDocType>;\r\n };\r\n /**\r\n * Cached array of all MemoryStorageInternalsByIndex values.\r\n * Avoids calling Object.values(byIndex) on every write operation.\r\n */\r\n byIndexArray: MemoryStorageInternalsByIndex<RxDocType>[];\r\n\r\n /**\r\n * We need these to do lazy writes.\r\n */\r\n ensurePersistenceTask?: CategorizeBulkWriteRowsOutput<RxDocType>;\r\n ensurePersistenceIdlePromise?: Promise<void>;\r\n\r\n changes$: Subject<EventBulk<RxStorageChangeEvent<RxDocumentData<RxDocType>>, RxStorageDefaultCheckpoint>>;\r\n};\r\n\r\nexport type DocWithIndexString<RxDocType> = [\r\n string, // indexString, must be first because often we only need that one.\r\n RxDocumentData<RxDocType>, // document\r\n string, // id\r\n];\r\n"],"mappings":"","ignoreList":[]}