@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
@@ -0,0 +1,91 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const MAX_LINE_LENGTH = 86;
5
+
6
+ const targetDirs = [
7
+ path.join(__dirname, '../docs-src/docs'),
8
+ path.join(__dirname, '../docs-src/src')
9
+ ];
10
+
11
+ let hasError = false;
12
+
13
+ function walkDir(dir) {
14
+ if (!fs.existsSync(dir)) return;
15
+ const files = fs.readdirSync(dir);
16
+ for (const file of files) {
17
+ const fullPath = path.join(dir, file);
18
+ const stat = fs.statSync(fullPath);
19
+ if (stat.isDirectory()) {
20
+ walkDir(fullPath);
21
+ } else if (
22
+ fullPath.endsWith('.md') ||
23
+ fullPath.endsWith('.mdx')
24
+ ) {
25
+ checkFile(fullPath);
26
+ }
27
+ }
28
+ }
29
+
30
+ function checkFile(filePath) {
31
+ const content = fs.readFileSync(filePath, 'utf-8');
32
+ const lines = content.split('\n');
33
+
34
+ let inCodeBlock = false;
35
+
36
+ for (let i = 0; i < lines.length; i++) {
37
+ const line = lines[i];
38
+ const trimmed = line.trim();
39
+
40
+ if (trimmed.startsWith('```')) {
41
+ // Single-line code block: ```code```
42
+ const rest = trimmed.slice(3);
43
+ if (rest.endsWith('```') && rest.length > 3) {
44
+ continue;
45
+ }
46
+ inCodeBlock = !inCodeBlock;
47
+ continue;
48
+ }
49
+
50
+ if (inCodeBlock && line.length > MAX_LINE_LENGTH) {
51
+ const relativePath = path.relative(
52
+ path.join(__dirname, '..'),
53
+ filePath
54
+ );
55
+ console.error(
56
+ 'Error: Code block line too long ' +
57
+ `(${line.length} > ${MAX_LINE_LENGTH}) ` +
58
+ `in ${relativePath}:${i + 1}`
59
+ );
60
+ console.error(`> ${line}`);
61
+ console.error('-'.repeat(100));
62
+ hasError = true;
63
+ }
64
+ }
65
+ }
66
+
67
+ console.log(
68
+ 'Checking documentation code blocks ' +
69
+ `for lines longer than ${MAX_LINE_LENGTH} characters...`
70
+ );
71
+
72
+ for (const dir of targetDirs) {
73
+ walkDir(dir);
74
+ }
75
+
76
+ if (hasError) {
77
+ console.error(
78
+ '\nDocumentation contains code block lines ' +
79
+ `exceeding ${MAX_LINE_LENGTH} characters.`
80
+ );
81
+ console.error(
82
+ 'Please shorten these lines to fit within the limit.'
83
+ );
84
+ process.exit(1);
85
+ } else {
86
+ console.log(
87
+ 'Success: All code block lines are within ' +
88
+ `${MAX_LINE_LENGTH} characters.`
89
+ );
90
+ process.exit(0);
91
+ }
@@ -0,0 +1,53 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const targetDirs = [
5
+ path.join(__dirname, '../docs-src/docs'),
6
+ path.join(__dirname, '../docs-src/src')
7
+ ];
8
+
9
+ let hasError = false;
10
+
11
+ function walkDir(dir) {
12
+ if (!fs.existsSync(dir)) return;
13
+ const files = fs.readdirSync(dir);
14
+ for (const file of files) {
15
+ const fullPath = path.join(dir, file);
16
+ const stat = fs.statSync(fullPath);
17
+ if (stat.isDirectory()) {
18
+ walkDir(fullPath);
19
+ } else if (fullPath.endsWith('.md') || fullPath.endsWith('.mdx') || fullPath.endsWith('.tsx') || fullPath.endsWith('.ts')) {
20
+ checkFile(fullPath);
21
+ }
22
+ }
23
+ }
24
+
25
+ function checkFile(filePath) {
26
+ const content = fs.readFileSync(filePath, 'utf-8');
27
+ const lines = content.split('\n');
28
+
29
+ for (let i = 0; i < lines.length; i++) {
30
+ const line = lines[i];
31
+ if (line.includes('—') || line.includes('–')) {
32
+ console.error(`Error: Em/En dash found in ${filePath}:${i + 1}`);
33
+ console.error(`> ${line.trim()}`);
34
+ console.error('-'.repeat(100));
35
+ hasError = true;
36
+ }
37
+ }
38
+ }
39
+
40
+ console.log('Checking documentation for em-dashes and en-dashes...');
41
+
42
+ for (const dir of targetDirs) {
43
+ walkDir(dir);
44
+ }
45
+
46
+ if (hasError) {
47
+ console.error('\nDocumentation contains prohibited em-dash (—) or en-dash (–) characters.');
48
+ console.error('Please rephrase to comply with project guidelines.');
49
+ process.exit(1);
50
+ } else {
51
+ console.log('Success: No em-dashes or en-dashes found.');
52
+ process.exit(0);
53
+ }
@@ -0,0 +1,20 @@
1
+ import { promises as fs } from 'node:fs';
2
+
3
+ async function main() {
4
+ const [, , sourcePath, targetPath] = process.argv;
5
+
6
+ if (!sourcePath || !targetPath) {
7
+ console.error('copy-path requires <source> and <target>');
8
+ process.exit(1);
9
+ }
10
+
11
+ await fs.cp(sourcePath, targetPath, {
12
+ recursive: true,
13
+ force: true
14
+ });
15
+ }
16
+
17
+ main().catch(err => {
18
+ console.error(`copy-path error: ${err.message}`);
19
+ process.exit(1);
20
+ });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Docusaurus uses 'git log' to determine the last update time for each docs page.
3
+ * In shallow clones (common in CI), all files report the same commit date
4
+ * because git only has one commit available. This causes every page to show
5
+ * the same "Last updated" date.
6
+ *
7
+ * This script ensures the full git history is available before building docs,
8
+ * so that 'git log' returns the actual per-file last modification date.
9
+ */
10
+ import { execSync } from 'child_process';
11
+
12
+ function run() {
13
+ let isShallow;
14
+ try {
15
+ isShallow = execSync('git rev-parse --is-shallow-repository', { encoding: 'utf-8' }).trim();
16
+ } catch (err) {
17
+ console.log('Could not determine if repository is shallow: ' + err.message);
18
+ console.log('Skipping git history fetch.');
19
+ return;
20
+ }
21
+
22
+ if (isShallow === 'true') {
23
+ console.log('Shallow repository detected. Fetching full git history for accurate docs timestamps...');
24
+ try {
25
+ execSync('git fetch --unshallow', { stdio: 'inherit' });
26
+ console.log('Full git history fetched successfully.');
27
+ } catch (err) {
28
+ console.warn('Warning: Could not fetch full git history: ' + err.message);
29
+ console.warn('Docs "Last updated" dates may be inaccurate.');
30
+ }
31
+ } else {
32
+ console.log('Full git history already available.');
33
+ }
34
+ }
35
+
36
+ run();
@@ -1,11 +1,18 @@
1
- import { promises as fs } from 'node:fs';
2
-
3
- async function main () {
4
- const file = './dist/types/index.d.ts';
5
- try {
6
- let content = await fs.readFile(file, { encoding: 'utf-8' });
7
- // Convert only bare '.ts' specifier endings, keep existing '.d.ts' intact.
8
- content = content.replace(/(?<!\.d)\.ts(?=['"])/g, '.d.ts');
1
+ import { promises as fs } from 'node:fs';
2
+
3
+ async function main () {
4
+ const sourceTypesDir = './src/types';
5
+ const targetTypesDir = './dist/types/types';
6
+ const file = './dist/types/index.d.ts';
7
+ try {
8
+ await fs.cp(sourceTypesDir, targetTypesDir, {
9
+ recursive: true,
10
+ force: true
11
+ });
12
+
13
+ let content = await fs.readFile(file, { encoding: 'utf-8' });
14
+ // Convert only bare '.ts' specifier endings, keep existing '.d.ts' intact.
15
+ content = content.replace(/(?<!\.d)\.ts(?=['"])/g, '.d.ts');
9
16
 
10
17
  // Guard against malformed declaration specifiers.
11
18
  if (/\.d\.d\.ts(?=['"])/.test(content)) {
@@ -6,9 +6,3 @@ wget -O foundationdb-client.deb https://github.com/apple/foundationdb/releases/d
6
6
  sudo dpkg -i foundationdb-client.deb
7
7
  rm foundationdb-client.deb
8
8
 
9
-
10
- echo "# installing FoundationDB server:"
11
- wget -O foundationdb-server.deb https://github.com/apple/foundationdb/releases/download/7.3.59/foundationdb-server_7.3.59-1_amd64.deb
12
- sudo dpkg -i foundationdb-server.deb
13
- rm foundationdb-server.deb
14
-
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Notifies Bing IndexNow about changed documentation pages.
3
+ * Gathers all docs pages from docs-src/ and submits their URLs
4
+ * to the IndexNow API so that Bing re-indexes them.
5
+ *
6
+ * @link https://www.bing.com/indexnow/getstarted
7
+ */
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ const INDEXNOW_KEY = 'bc55ad38ac6d4cdfa33c3f7f8667999b';
16
+ const SITE_HOST = 'rxdb.info';
17
+ const SITE_URL = 'https://' + SITE_HOST;
18
+ const KEY_LOCATION = SITE_URL + '/' + INDEXNOW_KEY + '.txt';
19
+ const INDEXNOW_ENDPOINT = 'https://api.indexnow.org/indexnow';
20
+
21
+ const DOCS_DIR = path.join(__dirname, '..', 'docs-src', 'docs');
22
+ const PAGES_DIR = path.join(__dirname, '..', 'docs-src', 'src', 'pages');
23
+
24
+ const MAX_RETRIES = 5;
25
+
26
+ /**
27
+ * Recursively walks a directory and calls the callback for each file.
28
+ */
29
+ function walk(dir, callback) {
30
+ const list = fs.readdirSync(dir);
31
+ for (const file of list) {
32
+ const filePath = path.join(dir, file);
33
+ const stat = fs.statSync(filePath);
34
+ if (stat.isDirectory()) {
35
+ walk(filePath, callback);
36
+ } else {
37
+ callback(filePath);
38
+ }
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Extracts the slug from markdown frontmatter.
44
+ * Falls back to the filename without extension.
45
+ */
46
+ function getSlugFromMarkdown(filePath) {
47
+ const content = fs.readFileSync(filePath, 'utf-8');
48
+ const frontMatch = content.match(/^---\s*([\s\S]*?)\s*---/);
49
+ if (!frontMatch) {
50
+ return path.basename(filePath, '.md');
51
+ }
52
+ const frontmatter = frontMatch[1];
53
+ const slugMatch = frontmatter.match(/slug:\s*(.*)/);
54
+ if (slugMatch) {
55
+ let slug = slugMatch[1].trim();
56
+ slug = slug.replace(/\.html$/, '');
57
+ return slug;
58
+ }
59
+ return path.basename(filePath, '.md');
60
+ }
61
+
62
+ /**
63
+ * Gathers all documentation page URLs from docs-src.
64
+ */
65
+ function gatherPageUrls() {
66
+ const urls = [];
67
+
68
+ // Add the homepage
69
+ urls.push(SITE_URL + '/');
70
+
71
+ // Gather markdown docs
72
+ if (fs.existsSync(DOCS_DIR)) {
73
+ walk(DOCS_DIR, (filePath) => {
74
+ if (filePath.endsWith('.md')) {
75
+ const slug = getSlugFromMarkdown(filePath);
76
+ urls.push(SITE_URL + '/' + slug + '.html');
77
+ }
78
+ });
79
+ }
80
+
81
+ // Gather .tsx pages (non-component files in pages directory)
82
+ if (fs.existsSync(PAGES_DIR)) {
83
+ walk(PAGES_DIR, (filePath) => {
84
+ if (filePath.endsWith('.tsx')) {
85
+ const relativePath = path.relative(PAGES_DIR, filePath);
86
+ const slug = relativePath
87
+ .replace(/\.tsx$/, '')
88
+ .replace(/\/index$/, '');
89
+ if (slug === 'index') {
90
+ // Already added as homepage
91
+ return;
92
+ }
93
+ urls.push(SITE_URL + '/' + slug + '.html');
94
+ }
95
+ });
96
+ }
97
+
98
+ return urls;
99
+ }
100
+
101
+ /**
102
+ * Sleep for the given number of milliseconds.
103
+ */
104
+ function sleep(ms) {
105
+ return new Promise(resolve => setTimeout(resolve, ms));
106
+ }
107
+
108
+ /**
109
+ * Submits URLs to the IndexNow API with retry logic.
110
+ * Retries up to MAX_RETRIES times with exponential backoff.
111
+ */
112
+ async function submitToIndexNow(urls) {
113
+ const body = JSON.stringify({
114
+ host: SITE_HOST,
115
+ key: INDEXNOW_KEY,
116
+ keyLocation: KEY_LOCATION,
117
+ urlList: urls
118
+ });
119
+
120
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
121
+ try {
122
+ console.log('IndexNow submission attempt ' + attempt + '/' + MAX_RETRIES + '...');
123
+ const response = await fetch(INDEXNOW_ENDPOINT, {
124
+ method: 'POST',
125
+ headers: {
126
+ 'Content-Type': 'application/json; charset=utf-8'
127
+ },
128
+ body
129
+ });
130
+
131
+ if (response.ok || response.status === 200 || response.status === 202) {
132
+ console.log('IndexNow submission successful (HTTP ' + response.status + ')');
133
+ return;
134
+ }
135
+
136
+ console.error('IndexNow returned HTTP ' + response.status + ': ' + response.statusText);
137
+ const responseText = await response.text().catch(() => '');
138
+ if (responseText) {
139
+ console.error('Response body: ' + responseText);
140
+ }
141
+ } catch (err) {
142
+ console.error('IndexNow request failed: ' + err.message);
143
+ }
144
+
145
+ if (attempt < MAX_RETRIES) {
146
+ const waitSeconds = Math.pow(2, attempt);
147
+ console.log('Retrying in ' + waitSeconds + ' seconds...');
148
+ await sleep(waitSeconds * 1000);
149
+ }
150
+ }
151
+
152
+ throw new Error('IndexNow submission failed after ' + MAX_RETRIES + ' attempts');
153
+ }
154
+
155
+ async function main() {
156
+ console.log('Gathering documentation page URLs...');
157
+ const urls = gatherPageUrls();
158
+ console.log('Found ' + urls.length + ' pages to submit:\n');
159
+ for (const url of urls) {
160
+ console.log(' ' + url);
161
+ }
162
+ console.log('');
163
+
164
+ await submitToIndexNow(urls);
165
+ console.log('Done. Bing IndexNow has been notified about ' + urls.length + ' pages.');
166
+ }
167
+
168
+ main().catch((err) => {
169
+ console.error(err);
170
+ process.exit(1);
171
+ });
@@ -0,0 +1,73 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ FDB_VERSION="7.3.59"
5
+ CONTAINER_NAME="rxdb-foundationdb"
6
+ FDB_CLUSTER_FILE="/etc/foundationdb/fdb.cluster"
7
+ TIMEOUT_SECONDS=30
8
+
9
+ echo "# Starting FoundationDB Docker container..."
10
+
11
+ # Remove any existing container
12
+ docker rm -f "$CONTAINER_NAME" 2>/dev/null || true
13
+
14
+ # Start the FoundationDB server container with host networking
15
+ docker run -d \
16
+ --name "$CONTAINER_NAME" \
17
+ --network host \
18
+ -e FDB_NETWORKING_MODE=host \
19
+ "foundationdb/foundationdb:${FDB_VERSION}"
20
+
21
+ echo "# Waiting for container to initialize..."
22
+ sleep 2
23
+
24
+ # Create the cluster file directory on the host
25
+ sudo mkdir -p /etc/foundationdb
26
+
27
+ # Copy the cluster file from the container to the host.
28
+ # The container generates a cluster file on startup at /var/fdb/fdb.cluster.
29
+ # With --network host and FDB_NETWORKING_MODE=host, the cluster file
30
+ # contains an IP address reachable from the host.
31
+ docker cp "$CONTAINER_NAME:/var/fdb/fdb.cluster" /tmp/fdb.cluster
32
+ sudo cp /tmp/fdb.cluster "$FDB_CLUSTER_FILE"
33
+ rm /tmp/fdb.cluster
34
+ echo "# Cluster file contents:"
35
+ cat "$FDB_CLUSTER_FILE"
36
+
37
+ # Wait for the FoundationDB server to be reachable
38
+ echo "# Waiting for FoundationDB to be reachable..."
39
+ SECONDS_WAITED=0
40
+ while [ "$SECONDS_WAITED" -lt "$TIMEOUT_SECONDS" ]; do
41
+ if fdbcli --exec "status minimal" --timeout 5 2>/dev/null; then
42
+ echo "# FoundationDB server is reachable."
43
+ break
44
+ fi
45
+ sleep 1
46
+ SECONDS_WAITED=$((SECONDS_WAITED + 1))
47
+ done
48
+
49
+ if [ "$SECONDS_WAITED" -ge "$TIMEOUT_SECONDS" ]; then
50
+ echo "# WARNING: Timed out waiting for FoundationDB to be reachable."
51
+ fi
52
+
53
+ # Configure the database for single-machine operation with in-memory storage engine
54
+ echo "# Configuring database..."
55
+ fdbcli --exec "configure new single memory" --timeout "$TIMEOUT_SECONDS" || true
56
+
57
+ # Wait for the database to become available after configuration
58
+ echo "# Waiting for database to become available..."
59
+ SECONDS_WAITED=0
60
+ while [ "$SECONDS_WAITED" -lt "$TIMEOUT_SECONDS" ]; do
61
+ STATUS=$(fdbcli --exec "status minimal" --timeout 5 2>/dev/null || echo "")
62
+ if echo "$STATUS" | grep -q "The database is available"; then
63
+ echo "# FoundationDB is ready!"
64
+ exit 0
65
+ fi
66
+ sleep 1
67
+ SECONDS_WAITED=$((SECONDS_WAITED + 1))
68
+ done
69
+
70
+ echo "# ERROR: FoundationDB did not become available within ${TIMEOUT_SECONDS} seconds."
71
+ echo "# Container logs:"
72
+ docker logs "$CONTAINER_NAME" 2>&1 | tail -50
73
+ exit 1
@@ -13,6 +13,9 @@ import type {
13
13
  import {
14
14
  requestIdlePromiseNoQueue
15
15
  } from './plugins/utils/index.ts';
16
+ import {
17
+ newRxError
18
+ } from './rx-error.ts';
16
19
 
17
20
 
18
21
  /**
@@ -140,7 +143,7 @@ export class ChangeEventBuffer<RxDocType> {
140
143
  this.processTasks();
141
144
  const ret = this.getFrom(pointer);
142
145
  if (ret === null) {
143
- throw new Error('out of bounds');
146
+ throw newRxError('COB1');
144
147
  } else {
145
148
  ret.forEach(cE => fn(cE));
146
149
  }
@@ -26,6 +26,9 @@ import {
26
26
  INDEX_MAX,
27
27
  INDEX_MIN
28
28
  } from './query-planner.ts';
29
+ import {
30
+ newRxError
31
+ } from './rx-error.ts';
29
32
 
30
33
 
31
34
  /**
@@ -56,7 +59,7 @@ export function getIndexMeta<RxDocType>(
56
59
  fieldName
57
60
  );
58
61
  if (!schemaPart) {
59
- throw new Error('not in schema: ' + fieldName);
62
+ throw newRxError('CI1', { fieldName });
60
63
  }
61
64
  const type = schemaPart.type;
62
65
  let parsedLengths: ParsedLengths | undefined;
@@ -84,13 +87,54 @@ export function getIndexMeta<RxDocType>(
84
87
  return fieldValue ? '1' : '0';
85
88
  };
86
89
  } else { // number
87
- getIndexStringPart = docData => {
88
- const fieldValue = getValue(docData);
89
- return getNumberIndexString(
90
- parsedLengths as any,
91
- fieldValue
92
- );
93
- };
90
+ /**
91
+ * @performance
92
+ * Inline the number index string generation to avoid
93
+ * function call overhead and redundant boundary checks.
94
+ * Document data in the hot path is assumed to be valid.
95
+ */
96
+ const pLengths = parsedLengths as ParsedLengths;
97
+ const pMin = pLengths.minimum;
98
+ const pMax = pLengths.maximum;
99
+ const pRoundedMin = pLengths.roundedMinimum;
100
+ const pNonDecimals = pLengths.nonDecimals;
101
+ const pDecimals = pLengths.decimals;
102
+ const pMultiplier = pLengths.multiplier;
103
+ if (pDecimals === 0) {
104
+ getIndexStringPart = docData => {
105
+ let fieldValue = getValue(docData);
106
+ if (typeof fieldValue === 'undefined') {
107
+ fieldValue = 0;
108
+ }
109
+ if (fieldValue < pMin) {
110
+ fieldValue = pMin;
111
+ }
112
+ if (fieldValue > pMax) {
113
+ fieldValue = pMax;
114
+ }
115
+ return (Math.floor(fieldValue) - pRoundedMin).toString().padStart(pNonDecimals, '0');
116
+ };
117
+ } else {
118
+ getIndexStringPart = docData => {
119
+ let fieldValue = getValue(docData);
120
+ if (typeof fieldValue === 'undefined') {
121
+ fieldValue = 0;
122
+ }
123
+ if (fieldValue < pMin) {
124
+ fieldValue = pMin;
125
+ }
126
+ if (fieldValue > pMax) {
127
+ fieldValue = pMax;
128
+ }
129
+ const flooredValue = Math.floor(fieldValue);
130
+ const shifted = Math.min(
131
+ Math.round((fieldValue - flooredValue) * pMultiplier),
132
+ pMultiplier - 1
133
+ );
134
+ const str = (flooredValue - pRoundedMin).toString().padStart(pNonDecimals, '0');
135
+ return str + shifted.toString().padStart(pDecimals, '0');
136
+ };
137
+ }
94
138
  }
95
139
 
96
140
  const ret: IndexMetaField<RxDocType> = {
@@ -125,10 +169,25 @@ export function getIndexableStringMonad<RxDocType>(
125
169
  const fieldNamePropertiesAmount = fieldNameProperties.length;
126
170
  const indexPartsFunctions = fieldNameProperties.map(r => r.getIndexStringPart);
127
171
 
128
-
129
172
  /**
130
173
  * @hotPath Performance of this function is very critical!
174
+ * Specialize for common field counts to avoid loop overhead.
131
175
  */
176
+ if (fieldNamePropertiesAmount === 1) {
177
+ return indexPartsFunctions[0];
178
+ }
179
+ if (fieldNamePropertiesAmount === 2) {
180
+ const fn0 = indexPartsFunctions[0];
181
+ const fn1 = indexPartsFunctions[1];
182
+ return (docData: RxDocumentData<RxDocType>): string => fn0(docData) + fn1(docData);
183
+ }
184
+ if (fieldNamePropertiesAmount === 3) {
185
+ const fn0 = indexPartsFunctions[0];
186
+ const fn1 = indexPartsFunctions[1];
187
+ const fn2 = indexPartsFunctions[2];
188
+ return (docData: RxDocumentData<RxDocType>): string => fn0(docData) + fn1(docData) + fn2(docData);
189
+ }
190
+
132
191
  const ret = function (docData: RxDocumentData<RxDocType>): string {
133
192
  let str = '';
134
193
  for (let i = 0; i < fieldNamePropertiesAmount; ++i) {
@@ -146,6 +205,11 @@ declare type ParsedLengths = {
146
205
  nonDecimals: number;
147
206
  decimals: number;
148
207
  roundedMinimum: number;
208
+ /**
209
+ * Pre-computed Math.pow(10, decimals) to avoid
210
+ * recomputing on every getNumberIndexString call.
211
+ */
212
+ multiplier: number;
149
213
  };
150
214
  export function getStringLengthOfIndexNumber(
151
215
  schemaPart: JsonSchema
@@ -167,7 +231,8 @@ export function getStringLengthOfIndexNumber(
167
231
  maximum,
168
232
  nonDecimals,
169
233
  decimals,
170
- roundedMinimum: minimum
234
+ roundedMinimum: minimum,
235
+ multiplier: Math.pow(10, decimals)
171
236
  };
172
237
  }
173
238
 
@@ -233,9 +298,19 @@ export function getNumberIndexString(
233
298
  let str = nonDecimalsValueAsString.padStart(parsedLengths.nonDecimals, '0');
234
299
 
235
300
  if (parsedLengths.decimals > 0) {
236
- const splitByDecimalPoint = fieldValue.toString().split('.');
237
- const decimalValueAsString = splitByDecimalPoint.length > 1 ? splitByDecimalPoint[1] : '0';
238
- str += decimalValueAsString.padEnd(parsedLengths.decimals, '0');
301
+ /**
302
+ * @performance
303
+ * Use math to extract decimal digits instead of toString().split('.')
304
+ * which creates intermediate strings and arrays.
305
+ * multiplier is pre-computed in ParsedLengths to avoid Math.pow() per call.
306
+ */
307
+ const multiplier = parsedLengths.multiplier;
308
+ const shifted = Math.min(
309
+ Math.round((fieldValue - Math.floor(fieldValue)) * multiplier),
310
+ multiplier - 1
311
+ );
312
+ const decimalPart = shifted.toString();
313
+ str += decimalPart.padStart(parsedLengths.decimals, '0');
239
314
  }
240
315
  return str;
241
316
  }
@@ -298,7 +373,7 @@ export function getStartIndexStringFromLowerBound(
298
373
  }
299
374
  break;
300
375
  default:
301
- throw new Error('unknown index type ' + type);
376
+ throw newRxError('CI2', { type: type as string });
302
377
  }
303
378
  });
304
379
  return str;
@@ -331,8 +406,10 @@ export function getStartIndexStringFromUpperBound(
331
406
  }
332
407
  break;
333
408
  case 'boolean':
334
- if (bound === null) {
409
+ if (bound === null || bound === INDEX_MAX) {
335
410
  str += '1';
411
+ } else if (bound === INDEX_MIN) {
412
+ str += '0';
336
413
  } else {
337
414
  const boolToStr = bound ? '1' : '0';
338
415
  str += boolToStr;
@@ -357,7 +434,7 @@ export function getStartIndexStringFromUpperBound(
357
434
  }
358
435
  break;
359
436
  default:
360
- throw new Error('unknown index type ' + type);
437
+ throw newRxError('CI2', { type: type as string });
361
438
  }
362
439
  });
363
440
  return str;