anchordb 0.2.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 (438) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/LICENSE +21 -0
  3. package/README.md +160 -0
  4. package/dist/cjs/conflict/strategies.d.ts +110 -0
  5. package/dist/cjs/conflict/strategies.d.ts.map +1 -0
  6. package/dist/cjs/conflict/strategies.js +298 -0
  7. package/dist/cjs/conflict/strategies.js.map +1 -0
  8. package/dist/cjs/conflict/types.d.ts +38 -0
  9. package/dist/cjs/conflict/types.d.ts.map +1 -0
  10. package/dist/cjs/conflict/types.js +3 -0
  11. package/dist/cjs/conflict/types.js.map +1 -0
  12. package/dist/cjs/core/anchor-db.d.ts +154 -0
  13. package/dist/cjs/core/anchor-db.d.ts.map +1 -0
  14. package/dist/cjs/core/anchor-db.js +273 -0
  15. package/dist/cjs/core/anchor-db.js.map +1 -0
  16. package/dist/cjs/core/errors.d.ts +125 -0
  17. package/dist/cjs/core/errors.d.ts.map +1 -0
  18. package/dist/cjs/core/errors.js +174 -0
  19. package/dist/cjs/core/errors.js.map +1 -0
  20. package/dist/cjs/core/hex.d.ts +4 -0
  21. package/dist/cjs/core/hex.d.ts.map +1 -0
  22. package/dist/cjs/core/hex.js +41 -0
  23. package/dist/cjs/core/hex.js.map +1 -0
  24. package/dist/cjs/core/hlc.d.ts +96 -0
  25. package/dist/cjs/core/hlc.d.ts.map +1 -0
  26. package/dist/cjs/core/hlc.js +161 -0
  27. package/dist/cjs/core/hlc.js.map +1 -0
  28. package/dist/cjs/core/object-id.d.ts +38 -0
  29. package/dist/cjs/core/object-id.d.ts.map +1 -0
  30. package/dist/cjs/core/object-id.js +167 -0
  31. package/dist/cjs/core/object-id.js.map +1 -0
  32. package/dist/cjs/core/random.d.ts +6 -0
  33. package/dist/cjs/core/random.d.ts.map +1 -0
  34. package/dist/cjs/core/random.js +39 -0
  35. package/dist/cjs/core/random.js.map +1 -0
  36. package/dist/cjs/core/runtime.d.ts +96 -0
  37. package/dist/cjs/core/runtime.d.ts.map +1 -0
  38. package/dist/cjs/core/runtime.js +3 -0
  39. package/dist/cjs/core/runtime.js.map +1 -0
  40. package/dist/cjs/core/uuid.d.ts +16 -0
  41. package/dist/cjs/core/uuid.d.ts.map +1 -0
  42. package/dist/cjs/core/uuid.js +37 -0
  43. package/dist/cjs/core/uuid.js.map +1 -0
  44. package/dist/cjs/decorators/index.d.ts +48 -0
  45. package/dist/cjs/decorators/index.d.ts.map +1 -0
  46. package/dist/cjs/decorators/index.js +295 -0
  47. package/dist/cjs/decorators/index.js.map +1 -0
  48. package/dist/cjs/events/emitter.d.ts +16 -0
  49. package/dist/cjs/events/emitter.d.ts.map +1 -0
  50. package/dist/cjs/events/emitter.js +56 -0
  51. package/dist/cjs/events/emitter.js.map +1 -0
  52. package/dist/cjs/index/keys.d.ts +79 -0
  53. package/dist/cjs/index/keys.d.ts.map +1 -0
  54. package/dist/cjs/index/keys.js +208 -0
  55. package/dist/cjs/index/keys.js.map +1 -0
  56. package/dist/cjs/index.d.ts +81 -0
  57. package/dist/cjs/index.d.ts.map +1 -0
  58. package/dist/cjs/index.js +193 -0
  59. package/dist/cjs/index.js.map +1 -0
  60. package/dist/cjs/inspector/agent.d.ts +75 -0
  61. package/dist/cjs/inspector/agent.d.ts.map +1 -0
  62. package/dist/cjs/inspector/agent.js +520 -0
  63. package/dist/cjs/inspector/agent.js.map +1 -0
  64. package/dist/cjs/inspector/auth.d.ts +49 -0
  65. package/dist/cjs/inspector/auth.d.ts.map +1 -0
  66. package/dist/cjs/inspector/auth.js +234 -0
  67. package/dist/cjs/inspector/auth.js.map +1 -0
  68. package/dist/cjs/inspector/bridge.d.ts +141 -0
  69. package/dist/cjs/inspector/bridge.d.ts.map +1 -0
  70. package/dist/cjs/inspector/bridge.js +190 -0
  71. package/dist/cjs/inspector/bridge.js.map +1 -0
  72. package/dist/cjs/inspector/client.d.ts +111 -0
  73. package/dist/cjs/inspector/client.d.ts.map +1 -0
  74. package/dist/cjs/inspector/client.js +218 -0
  75. package/dist/cjs/inspector/client.js.map +1 -0
  76. package/dist/cjs/inspector/protocol.d.ts +160 -0
  77. package/dist/cjs/inspector/protocol.d.ts.map +1 -0
  78. package/dist/cjs/inspector/protocol.js +53 -0
  79. package/dist/cjs/inspector/protocol.js.map +1 -0
  80. package/dist/cjs/inspector/transports/in-process.d.ts +7 -0
  81. package/dist/cjs/inspector/transports/in-process.d.ts.map +1 -0
  82. package/dist/cjs/inspector/transports/in-process.js +58 -0
  83. package/dist/cjs/inspector/transports/in-process.js.map +1 -0
  84. package/dist/cjs/inspector/transports/websocket.d.ts +39 -0
  85. package/dist/cjs/inspector/transports/websocket.d.ts.map +1 -0
  86. package/dist/cjs/inspector/transports/websocket.js +60 -0
  87. package/dist/cjs/inspector/transports/websocket.js.map +1 -0
  88. package/dist/cjs/interop/csv.d.ts +53 -0
  89. package/dist/cjs/interop/csv.d.ts.map +1 -0
  90. package/dist/cjs/interop/csv.js +230 -0
  91. package/dist/cjs/interop/csv.js.map +1 -0
  92. package/dist/cjs/interop/ejson.d.ts +41 -0
  93. package/dist/cjs/interop/ejson.d.ts.map +1 -0
  94. package/dist/cjs/interop/ejson.js +182 -0
  95. package/dist/cjs/interop/ejson.js.map +1 -0
  96. package/dist/cjs/interop/export-import.d.ts +98 -0
  97. package/dist/cjs/interop/export-import.d.ts.map +1 -0
  98. package/dist/cjs/interop/export-import.js +222 -0
  99. package/dist/cjs/interop/export-import.js.map +1 -0
  100. package/dist/cjs/model/document.d.ts +66 -0
  101. package/dist/cjs/model/document.d.ts.map +1 -0
  102. package/dist/cjs/model/document.js +302 -0
  103. package/dist/cjs/model/document.js.map +1 -0
  104. package/dist/cjs/model/model.d.ts +178 -0
  105. package/dist/cjs/model/model.d.ts.map +1 -0
  106. package/dist/cjs/model/model.js +823 -0
  107. package/dist/cjs/model/model.js.map +1 -0
  108. package/dist/cjs/package.json +3 -0
  109. package/dist/cjs/query/aggregation/expressions.d.ts +34 -0
  110. package/dist/cjs/query/aggregation/expressions.d.ts.map +1 -0
  111. package/dist/cjs/query/aggregation/expressions.js +552 -0
  112. package/dist/cjs/query/aggregation/expressions.js.map +1 -0
  113. package/dist/cjs/query/aggregation/pipeline.d.ts +79 -0
  114. package/dist/cjs/query/aggregation/pipeline.d.ts.map +1 -0
  115. package/dist/cjs/query/aggregation/pipeline.js +597 -0
  116. package/dist/cjs/query/aggregation/pipeline.js.map +1 -0
  117. package/dist/cjs/query/aggregation/source.d.ts +35 -0
  118. package/dist/cjs/query/aggregation/source.d.ts.map +1 -0
  119. package/dist/cjs/query/aggregation/source.js +81 -0
  120. package/dist/cjs/query/aggregation/source.js.map +1 -0
  121. package/dist/cjs/query/builder/query.d.ts +113 -0
  122. package/dist/cjs/query/builder/query.d.ts.map +1 -0
  123. package/dist/cjs/query/builder/query.js +215 -0
  124. package/dist/cjs/query/builder/query.js.map +1 -0
  125. package/dist/cjs/query/filter.d.ts +50 -0
  126. package/dist/cjs/query/filter.d.ts.map +1 -0
  127. package/dist/cjs/query/filter.js +275 -0
  128. package/dist/cjs/query/filter.js.map +1 -0
  129. package/dist/cjs/query/path.d.ts +41 -0
  130. package/dist/cjs/query/path.d.ts.map +1 -0
  131. package/dist/cjs/query/path.js +294 -0
  132. package/dist/cjs/query/path.js.map +1 -0
  133. package/dist/cjs/query/update.d.ts +30 -0
  134. package/dist/cjs/query/update.d.ts.map +1 -0
  135. package/dist/cjs/query/update.js +205 -0
  136. package/dist/cjs/query/update.js.map +1 -0
  137. package/dist/cjs/reactive/live-query.d.ts +41 -0
  138. package/dist/cjs/reactive/live-query.d.ts.map +1 -0
  139. package/dist/cjs/reactive/live-query.js +88 -0
  140. package/dist/cjs/reactive/live-query.js.map +1 -0
  141. package/dist/cjs/schema/cast.d.ts +38 -0
  142. package/dist/cjs/schema/cast.d.ts.map +1 -0
  143. package/dist/cjs/schema/cast.js +280 -0
  144. package/dist/cjs/schema/cast.js.map +1 -0
  145. package/dist/cjs/schema/index.d.ts +5 -0
  146. package/dist/cjs/schema/index.d.ts.map +1 -0
  147. package/dist/cjs/schema/index.js +27 -0
  148. package/dist/cjs/schema/index.js.map +1 -0
  149. package/dist/cjs/schema/schema.d.ts +58 -0
  150. package/dist/cjs/schema/schema.d.ts.map +1 -0
  151. package/dist/cjs/schema/schema.js +363 -0
  152. package/dist/cjs/schema/schema.js.map +1 -0
  153. package/dist/cjs/schema/types.d.ts +144 -0
  154. package/dist/cjs/schema/types.d.ts.map +1 -0
  155. package/dist/cjs/schema/types.js +20 -0
  156. package/dist/cjs/schema/types.js.map +1 -0
  157. package/dist/cjs/schema/validate.d.ts +15 -0
  158. package/dist/cjs/schema/validate.d.ts.map +1 -0
  159. package/dist/cjs/schema/validate.js +101 -0
  160. package/dist/cjs/schema/validate.js.map +1 -0
  161. package/dist/cjs/storage/adapters/capacitor-sqlite.d.ts +67 -0
  162. package/dist/cjs/storage/adapters/capacitor-sqlite.d.ts.map +1 -0
  163. package/dist/cjs/storage/adapters/capacitor-sqlite.js +69 -0
  164. package/dist/cjs/storage/adapters/capacitor-sqlite.js.map +1 -0
  165. package/dist/cjs/storage/adapters/expo-sqlite.d.ts +55 -0
  166. package/dist/cjs/storage/adapters/expo-sqlite.d.ts.map +1 -0
  167. package/dist/cjs/storage/adapters/expo-sqlite.js +53 -0
  168. package/dist/cjs/storage/adapters/expo-sqlite.js.map +1 -0
  169. package/dist/cjs/storage/adapters/indexeddb.d.ts +55 -0
  170. package/dist/cjs/storage/adapters/indexeddb.d.ts.map +1 -0
  171. package/dist/cjs/storage/adapters/indexeddb.js +393 -0
  172. package/dist/cjs/storage/adapters/indexeddb.js.map +1 -0
  173. package/dist/cjs/storage/adapters/memory.d.ts +44 -0
  174. package/dist/cjs/storage/adapters/memory.d.ts.map +1 -0
  175. package/dist/cjs/storage/adapters/memory.js +286 -0
  176. package/dist/cjs/storage/adapters/memory.js.map +1 -0
  177. package/dist/cjs/storage/adapters/node-sqlite.d.ts +59 -0
  178. package/dist/cjs/storage/adapters/node-sqlite.d.ts.map +1 -0
  179. package/dist/cjs/storage/adapters/node-sqlite.js +457 -0
  180. package/dist/cjs/storage/adapters/node-sqlite.js.map +1 -0
  181. package/dist/cjs/storage/adapters/sql-base.d.ts +84 -0
  182. package/dist/cjs/storage/adapters/sql-base.d.ts.map +1 -0
  183. package/dist/cjs/storage/adapters/sql-base.js +393 -0
  184. package/dist/cjs/storage/adapters/sql-base.js.map +1 -0
  185. package/dist/cjs/storage/types.d.ts +131 -0
  186. package/dist/cjs/storage/types.d.ts.map +1 -0
  187. package/dist/cjs/storage/types.js +3 -0
  188. package/dist/cjs/storage/types.js.map +1 -0
  189. package/dist/cjs/sync/adapters/rest.d.ts +31 -0
  190. package/dist/cjs/sync/adapters/rest.d.ts.map +1 -0
  191. package/dist/cjs/sync/adapters/rest.js +75 -0
  192. package/dist/cjs/sync/adapters/rest.js.map +1 -0
  193. package/dist/cjs/sync/attach.d.ts +30 -0
  194. package/dist/cjs/sync/attach.d.ts.map +1 -0
  195. package/dist/cjs/sync/attach.js +104 -0
  196. package/dist/cjs/sync/attach.js.map +1 -0
  197. package/dist/cjs/sync/engine.d.ts +96 -0
  198. package/dist/cjs/sync/engine.d.ts.map +1 -0
  199. package/dist/cjs/sync/engine.js +491 -0
  200. package/dist/cjs/sync/engine.js.map +1 -0
  201. package/dist/cjs/sync/protocol.d.ts +128 -0
  202. package/dist/cjs/sync/protocol.d.ts.map +1 -0
  203. package/dist/cjs/sync/protocol.js +38 -0
  204. package/dist/cjs/sync/protocol.js.map +1 -0
  205. package/dist/cjs/sync/queue.d.ts +77 -0
  206. package/dist/cjs/sync/queue.d.ts.map +1 -0
  207. package/dist/cjs/sync/queue.js +245 -0
  208. package/dist/cjs/sync/queue.js.map +1 -0
  209. package/dist/cjs/sync/server/memory-server.d.ts +65 -0
  210. package/dist/cjs/sync/server/memory-server.d.ts.map +1 -0
  211. package/dist/cjs/sync/server/memory-server.js +193 -0
  212. package/dist/cjs/sync/server/memory-server.js.map +1 -0
  213. package/dist/cjs/timestamps/index.d.ts +47 -0
  214. package/dist/cjs/timestamps/index.d.ts.map +1 -0
  215. package/dist/cjs/timestamps/index.js +88 -0
  216. package/dist/cjs/timestamps/index.js.map +1 -0
  217. package/dist/cjs/timestamps/timezone.d.ts +65 -0
  218. package/dist/cjs/timestamps/timezone.d.ts.map +1 -0
  219. package/dist/cjs/timestamps/timezone.js +208 -0
  220. package/dist/cjs/timestamps/timezone.js.map +1 -0
  221. package/dist/esm/conflict/strategies.d.ts +110 -0
  222. package/dist/esm/conflict/strategies.d.ts.map +1 -0
  223. package/dist/esm/conflict/strategies.js +289 -0
  224. package/dist/esm/conflict/strategies.js.map +1 -0
  225. package/dist/esm/conflict/types.d.ts +38 -0
  226. package/dist/esm/conflict/types.d.ts.map +1 -0
  227. package/dist/esm/conflict/types.js +2 -0
  228. package/dist/esm/conflict/types.js.map +1 -0
  229. package/dist/esm/core/anchor-db.d.ts +154 -0
  230. package/dist/esm/core/anchor-db.d.ts.map +1 -0
  231. package/dist/esm/core/anchor-db.js +269 -0
  232. package/dist/esm/core/anchor-db.js.map +1 -0
  233. package/dist/esm/core/errors.d.ts +125 -0
  234. package/dist/esm/core/errors.d.ts.map +1 -0
  235. package/dist/esm/core/errors.js +161 -0
  236. package/dist/esm/core/errors.js.map +1 -0
  237. package/dist/esm/core/hex.d.ts +4 -0
  238. package/dist/esm/core/hex.d.ts.map +1 -0
  239. package/dist/esm/core/hex.js +37 -0
  240. package/dist/esm/core/hex.js.map +1 -0
  241. package/dist/esm/core/hlc.d.ts +96 -0
  242. package/dist/esm/core/hlc.d.ts.map +1 -0
  243. package/dist/esm/core/hlc.js +153 -0
  244. package/dist/esm/core/hlc.js.map +1 -0
  245. package/dist/esm/core/object-id.d.ts +38 -0
  246. package/dist/esm/core/object-id.d.ts.map +1 -0
  247. package/dist/esm/core/object-id.js +163 -0
  248. package/dist/esm/core/object-id.js.map +1 -0
  249. package/dist/esm/core/random.d.ts +6 -0
  250. package/dist/esm/core/random.d.ts.map +1 -0
  251. package/dist/esm/core/random.js +34 -0
  252. package/dist/esm/core/random.js.map +1 -0
  253. package/dist/esm/core/runtime.d.ts +96 -0
  254. package/dist/esm/core/runtime.d.ts.map +1 -0
  255. package/dist/esm/core/runtime.js +2 -0
  256. package/dist/esm/core/runtime.js.map +1 -0
  257. package/dist/esm/core/uuid.d.ts +16 -0
  258. package/dist/esm/core/uuid.d.ts.map +1 -0
  259. package/dist/esm/core/uuid.js +33 -0
  260. package/dist/esm/core/uuid.js.map +1 -0
  261. package/dist/esm/decorators/index.d.ts +48 -0
  262. package/dist/esm/decorators/index.d.ts.map +1 -0
  263. package/dist/esm/decorators/index.js +286 -0
  264. package/dist/esm/decorators/index.js.map +1 -0
  265. package/dist/esm/events/emitter.d.ts +16 -0
  266. package/dist/esm/events/emitter.d.ts.map +1 -0
  267. package/dist/esm/events/emitter.js +52 -0
  268. package/dist/esm/events/emitter.js.map +1 -0
  269. package/dist/esm/index/keys.d.ts +79 -0
  270. package/dist/esm/index/keys.d.ts.map +1 -0
  271. package/dist/esm/index/keys.js +198 -0
  272. package/dist/esm/index/keys.js.map +1 -0
  273. package/dist/esm/index.d.ts +81 -0
  274. package/dist/esm/index.d.ts.map +1 -0
  275. package/dist/esm/index.js +59 -0
  276. package/dist/esm/index.js.map +1 -0
  277. package/dist/esm/inspector/agent.d.ts +75 -0
  278. package/dist/esm/inspector/agent.d.ts.map +1 -0
  279. package/dist/esm/inspector/agent.js +482 -0
  280. package/dist/esm/inspector/agent.js.map +1 -0
  281. package/dist/esm/inspector/auth.d.ts +49 -0
  282. package/dist/esm/inspector/auth.d.ts.map +1 -0
  283. package/dist/esm/inspector/auth.js +228 -0
  284. package/dist/esm/inspector/auth.js.map +1 -0
  285. package/dist/esm/inspector/bridge.d.ts +141 -0
  286. package/dist/esm/inspector/bridge.d.ts.map +1 -0
  287. package/dist/esm/inspector/bridge.js +182 -0
  288. package/dist/esm/inspector/bridge.js.map +1 -0
  289. package/dist/esm/inspector/client.d.ts +111 -0
  290. package/dist/esm/inspector/client.d.ts.map +1 -0
  291. package/dist/esm/inspector/client.js +213 -0
  292. package/dist/esm/inspector/client.js.map +1 -0
  293. package/dist/esm/inspector/protocol.d.ts +160 -0
  294. package/dist/esm/inspector/protocol.d.ts.map +1 -0
  295. package/dist/esm/inspector/protocol.js +43 -0
  296. package/dist/esm/inspector/protocol.js.map +1 -0
  297. package/dist/esm/inspector/transports/in-process.d.ts +7 -0
  298. package/dist/esm/inspector/transports/in-process.d.ts.map +1 -0
  299. package/dist/esm/inspector/transports/in-process.js +55 -0
  300. package/dist/esm/inspector/transports/in-process.js.map +1 -0
  301. package/dist/esm/inspector/transports/websocket.d.ts +39 -0
  302. package/dist/esm/inspector/transports/websocket.d.ts.map +1 -0
  303. package/dist/esm/inspector/transports/websocket.js +56 -0
  304. package/dist/esm/inspector/transports/websocket.js.map +1 -0
  305. package/dist/esm/interop/csv.d.ts +53 -0
  306. package/dist/esm/interop/csv.d.ts.map +1 -0
  307. package/dist/esm/interop/csv.js +222 -0
  308. package/dist/esm/interop/csv.js.map +1 -0
  309. package/dist/esm/interop/ejson.d.ts +41 -0
  310. package/dist/esm/interop/ejson.d.ts.map +1 -0
  311. package/dist/esm/interop/ejson.js +176 -0
  312. package/dist/esm/interop/ejson.js.map +1 -0
  313. package/dist/esm/interop/export-import.d.ts +98 -0
  314. package/dist/esm/interop/export-import.d.ts.map +1 -0
  315. package/dist/esm/interop/export-import.js +210 -0
  316. package/dist/esm/interop/export-import.js.map +1 -0
  317. package/dist/esm/model/document.d.ts +66 -0
  318. package/dist/esm/model/document.d.ts.map +1 -0
  319. package/dist/esm/model/document.js +297 -0
  320. package/dist/esm/model/document.js.map +1 -0
  321. package/dist/esm/model/model.d.ts +178 -0
  322. package/dist/esm/model/model.d.ts.map +1 -0
  323. package/dist/esm/model/model.js +815 -0
  324. package/dist/esm/model/model.js.map +1 -0
  325. package/dist/esm/package.json +3 -0
  326. package/dist/esm/query/aggregation/expressions.d.ts +34 -0
  327. package/dist/esm/query/aggregation/expressions.d.ts.map +1 -0
  328. package/dist/esm/query/aggregation/expressions.js +545 -0
  329. package/dist/esm/query/aggregation/expressions.js.map +1 -0
  330. package/dist/esm/query/aggregation/pipeline.d.ts +79 -0
  331. package/dist/esm/query/aggregation/pipeline.d.ts.map +1 -0
  332. package/dist/esm/query/aggregation/pipeline.js +591 -0
  333. package/dist/esm/query/aggregation/pipeline.js.map +1 -0
  334. package/dist/esm/query/aggregation/source.d.ts +35 -0
  335. package/dist/esm/query/aggregation/source.d.ts.map +1 -0
  336. package/dist/esm/query/aggregation/source.js +77 -0
  337. package/dist/esm/query/aggregation/source.js.map +1 -0
  338. package/dist/esm/query/builder/query.d.ts +113 -0
  339. package/dist/esm/query/builder/query.d.ts.map +1 -0
  340. package/dist/esm/query/builder/query.js +209 -0
  341. package/dist/esm/query/builder/query.js.map +1 -0
  342. package/dist/esm/query/filter.d.ts +50 -0
  343. package/dist/esm/query/filter.d.ts.map +1 -0
  344. package/dist/esm/query/filter.js +267 -0
  345. package/dist/esm/query/filter.js.map +1 -0
  346. package/dist/esm/query/path.d.ts +41 -0
  347. package/dist/esm/query/path.d.ts.map +1 -0
  348. package/dist/esm/query/path.js +282 -0
  349. package/dist/esm/query/path.js.map +1 -0
  350. package/dist/esm/query/update.d.ts +30 -0
  351. package/dist/esm/query/update.d.ts.map +1 -0
  352. package/dist/esm/query/update.js +198 -0
  353. package/dist/esm/query/update.js.map +1 -0
  354. package/dist/esm/reactive/live-query.d.ts +41 -0
  355. package/dist/esm/reactive/live-query.d.ts.map +1 -0
  356. package/dist/esm/reactive/live-query.js +83 -0
  357. package/dist/esm/reactive/live-query.js.map +1 -0
  358. package/dist/esm/schema/cast.d.ts +38 -0
  359. package/dist/esm/schema/cast.d.ts.map +1 -0
  360. package/dist/esm/schema/cast.js +275 -0
  361. package/dist/esm/schema/cast.js.map +1 -0
  362. package/dist/esm/schema/index.d.ts +5 -0
  363. package/dist/esm/schema/index.d.ts.map +1 -0
  364. package/dist/esm/schema/index.js +5 -0
  365. package/dist/esm/schema/index.js.map +1 -0
  366. package/dist/esm/schema/schema.d.ts +58 -0
  367. package/dist/esm/schema/schema.d.ts.map +1 -0
  368. package/dist/esm/schema/schema.js +358 -0
  369. package/dist/esm/schema/schema.js.map +1 -0
  370. package/dist/esm/schema/types.d.ts +144 -0
  371. package/dist/esm/schema/types.d.ts.map +1 -0
  372. package/dist/esm/schema/types.js +17 -0
  373. package/dist/esm/schema/types.js.map +1 -0
  374. package/dist/esm/schema/validate.d.ts +15 -0
  375. package/dist/esm/schema/validate.d.ts.map +1 -0
  376. package/dist/esm/schema/validate.js +98 -0
  377. package/dist/esm/schema/validate.js.map +1 -0
  378. package/dist/esm/storage/adapters/capacitor-sqlite.d.ts +67 -0
  379. package/dist/esm/storage/adapters/capacitor-sqlite.d.ts.map +1 -0
  380. package/dist/esm/storage/adapters/capacitor-sqlite.js +65 -0
  381. package/dist/esm/storage/adapters/capacitor-sqlite.js.map +1 -0
  382. package/dist/esm/storage/adapters/expo-sqlite.d.ts +55 -0
  383. package/dist/esm/storage/adapters/expo-sqlite.d.ts.map +1 -0
  384. package/dist/esm/storage/adapters/expo-sqlite.js +49 -0
  385. package/dist/esm/storage/adapters/expo-sqlite.js.map +1 -0
  386. package/dist/esm/storage/adapters/indexeddb.d.ts +55 -0
  387. package/dist/esm/storage/adapters/indexeddb.d.ts.map +1 -0
  388. package/dist/esm/storage/adapters/indexeddb.js +389 -0
  389. package/dist/esm/storage/adapters/indexeddb.js.map +1 -0
  390. package/dist/esm/storage/adapters/memory.d.ts +44 -0
  391. package/dist/esm/storage/adapters/memory.d.ts.map +1 -0
  392. package/dist/esm/storage/adapters/memory.js +282 -0
  393. package/dist/esm/storage/adapters/memory.js.map +1 -0
  394. package/dist/esm/storage/adapters/node-sqlite.d.ts +59 -0
  395. package/dist/esm/storage/adapters/node-sqlite.d.ts.map +1 -0
  396. package/dist/esm/storage/adapters/node-sqlite.js +450 -0
  397. package/dist/esm/storage/adapters/node-sqlite.js.map +1 -0
  398. package/dist/esm/storage/adapters/sql-base.d.ts +84 -0
  399. package/dist/esm/storage/adapters/sql-base.d.ts.map +1 -0
  400. package/dist/esm/storage/adapters/sql-base.js +383 -0
  401. package/dist/esm/storage/adapters/sql-base.js.map +1 -0
  402. package/dist/esm/storage/types.d.ts +131 -0
  403. package/dist/esm/storage/types.d.ts.map +1 -0
  404. package/dist/esm/storage/types.js +2 -0
  405. package/dist/esm/storage/types.js.map +1 -0
  406. package/dist/esm/sync/adapters/rest.d.ts +31 -0
  407. package/dist/esm/sync/adapters/rest.d.ts.map +1 -0
  408. package/dist/esm/sync/adapters/rest.js +71 -0
  409. package/dist/esm/sync/adapters/rest.js.map +1 -0
  410. package/dist/esm/sync/attach.d.ts +30 -0
  411. package/dist/esm/sync/attach.d.ts.map +1 -0
  412. package/dist/esm/sync/attach.js +98 -0
  413. package/dist/esm/sync/attach.js.map +1 -0
  414. package/dist/esm/sync/engine.d.ts +96 -0
  415. package/dist/esm/sync/engine.d.ts.map +1 -0
  416. package/dist/esm/sync/engine.js +487 -0
  417. package/dist/esm/sync/engine.js.map +1 -0
  418. package/dist/esm/sync/protocol.d.ts +128 -0
  419. package/dist/esm/sync/protocol.d.ts.map +1 -0
  420. package/dist/esm/sync/protocol.js +33 -0
  421. package/dist/esm/sync/protocol.js.map +1 -0
  422. package/dist/esm/sync/queue.d.ts +77 -0
  423. package/dist/esm/sync/queue.d.ts.map +1 -0
  424. package/dist/esm/sync/queue.js +241 -0
  425. package/dist/esm/sync/queue.js.map +1 -0
  426. package/dist/esm/sync/server/memory-server.d.ts +65 -0
  427. package/dist/esm/sync/server/memory-server.d.ts.map +1 -0
  428. package/dist/esm/sync/server/memory-server.js +189 -0
  429. package/dist/esm/sync/server/memory-server.js.map +1 -0
  430. package/dist/esm/timestamps/index.d.ts +47 -0
  431. package/dist/esm/timestamps/index.d.ts.map +1 -0
  432. package/dist/esm/timestamps/index.js +70 -0
  433. package/dist/esm/timestamps/index.js.map +1 -0
  434. package/dist/esm/timestamps/timezone.d.ts +65 -0
  435. package/dist/esm/timestamps/timezone.d.ts.map +1 -0
  436. package/dist/esm/timestamps/timezone.js +196 -0
  437. package/dist/esm/timestamps/timezone.js.map +1 -0
  438. package/package.json +163 -0
@@ -0,0 +1,823 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationError = exports.castValue = exports.Model = void 0;
4
+ exports.hydrateDoc = hydrateDoc;
5
+ exports.serialise = serialise;
6
+ exports.pluralize = pluralize;
7
+ const errors_ts_1 = require("../core/errors.js");
8
+ Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_ts_1.ValidationError; } });
9
+ const object_id_ts_1 = require("../core/object-id.js");
10
+ const cast_ts_1 = require("../schema/cast.js");
11
+ Object.defineProperty(exports, "castValue", { enumerable: true, get: function () { return cast_ts_1.castValue; } });
12
+ const validate_ts_1 = require("../schema/validate.js");
13
+ const filter_ts_1 = require("../query/filter.js");
14
+ const update_ts_1 = require("../query/update.js");
15
+ const path_ts_1 = require("../query/path.js");
16
+ const query_ts_1 = require("../query/builder/query.js");
17
+ const keys_ts_1 = require("../index/keys.js");
18
+ const pipeline_ts_1 = require("../query/aggregation/pipeline.js");
19
+ const source_ts_1 = require("../query/aggregation/source.js");
20
+ /**
21
+ * Mongoose's `Model`.
22
+ *
23
+ * Every mutation funnels through `persist()`, which is the single place that stamps timestamps,
24
+ * assigns HLC values and (in synced mode) records a mutation. Having one path is what makes
25
+ * "Lens edits behave exactly like app edits" true by construction rather than by discipline.
26
+ */
27
+ class Model {
28
+ constructor(name, schema, runtime, options = {}) {
29
+ this.indexesReady = null;
30
+ /** Set by createModelConstructor so query results can be hydrated into Documents. */
31
+ this.documentFactory = null;
32
+ this.modelName = name;
33
+ this.schema = schema;
34
+ this.runtime = runtime;
35
+ this.collectionName = options.collection ?? schema.options.collection ?? pluralize(name);
36
+ // Statics declared on the schema become methods on the model, as in Mongoose.
37
+ for (const [key, fn] of Object.entries(schema.statics)) {
38
+ this[key] = fn.bind(this);
39
+ }
40
+ }
41
+ /** Wired by the model constructor; keeps Model free of an import cycle with Document. */
42
+ _setDocumentFactory(factory) {
43
+ this.documentFactory = factory;
44
+ }
45
+ get adapter() {
46
+ return this.runtime.adapter;
47
+ }
48
+ // ---- index bootstrap -----------------------------------------------------
49
+ /**
50
+ * Creates schema-declared indexes on first use, mirroring Mongoose's `autoIndex`.
51
+ * Memoised, so concurrent first queries do not race to build the same index.
52
+ */
53
+ async ensureIndexes() {
54
+ this.indexesReady ??= (async () => {
55
+ await this.runtime.ready();
56
+ await this.adapter.ensureCollection(this.collectionName);
57
+ for (const declared of this.schema.indexes()) {
58
+ const spec = {
59
+ name: declared.name,
60
+ key: declared.key,
61
+ ...(declared.options.unique !== undefined ? { unique: declared.options.unique } : {}),
62
+ ...(declared.options.sparse !== undefined ? { sparse: declared.options.sparse } : {}),
63
+ ...(declared.options.partialFilterExpression
64
+ ? { partialFilterExpression: declared.options.partialFilterExpression }
65
+ : {}),
66
+ ...(declared.options.expireAfterSeconds !== undefined
67
+ ? { expireAfterSeconds: declared.options.expireAfterSeconds }
68
+ : {}),
69
+ };
70
+ await this.adapter.createIndex(this.collectionName, spec);
71
+ }
72
+ })();
73
+ return this.indexesReady;
74
+ }
75
+ async createIndex(key, options = {}) {
76
+ await this.runtime.ready();
77
+ await this.adapter.ensureCollection(this.collectionName);
78
+ const entries = Object.entries(key);
79
+ const name = options.name ?? (0, keys_ts_1.defaultIndexName)(entries);
80
+ await this.adapter.createIndex(this.collectionName, { ...options, name, key: entries });
81
+ return name;
82
+ }
83
+ async createIndexes(specs) {
84
+ const out = [];
85
+ for (const spec of specs)
86
+ out.push(await this.createIndex(spec.key, spec.options ?? {}));
87
+ return out;
88
+ }
89
+ async listIndexes() {
90
+ await this.ensureIndexes();
91
+ const explicit = await this.adapter.listIndexes(this.collectionName);
92
+ // `_id` always has an implicit unique index and is never droppable.
93
+ return [{ name: "_id_", key: [["_id", 1]], unique: true }, ...explicit];
94
+ }
95
+ async dropIndex(name) {
96
+ if (name === "_id_") {
97
+ throw new errors_ts_1.MongoServerError({ message: "cannot drop _id index", code: 72 });
98
+ }
99
+ await this.adapter.dropIndex(this.collectionName, name);
100
+ }
101
+ async dropIndexes() {
102
+ await this.runtime.ready();
103
+ for (const idx of await this.adapter.listIndexes(this.collectionName)) {
104
+ await this.adapter.dropIndex(this.collectionName, idx.name);
105
+ }
106
+ }
107
+ // ---- reads ---------------------------------------------------------------
108
+ find(filter = {}) {
109
+ return new query_ts_1.Query(this, { op: "find", filter });
110
+ }
111
+ findOne(filter = {}) {
112
+ return new query_ts_1.Query(this, { op: "findOne", filter });
113
+ }
114
+ findById(id) {
115
+ return new query_ts_1.Query(this, { op: "findOne", filter: { _id: normaliseId(id) } });
116
+ }
117
+ countDocuments(filter = {}) {
118
+ return new query_ts_1.Query(this, { op: "count", filter });
119
+ }
120
+ async estimatedDocumentCount() {
121
+ await this.ensureIndexes();
122
+ const n = await this.adapter.count({ collection: this.collectionName, constraints: [] });
123
+ return n ?? (await this.find({}).count());
124
+ }
125
+ async exists(filter) {
126
+ const doc = await this.findOne(filter).select("_id").exec();
127
+ return doc ? { _id: doc._id } : null;
128
+ }
129
+ distinct(field, filter = {}) {
130
+ const q = new query_ts_1.Query(this, { op: "distinct", filter, distinctField: field });
131
+ return q;
132
+ }
133
+ /**
134
+ * MongoDB aggregation pipeline.
135
+ *
136
+ * The pipeline array is plain MongoDB syntax, so the identical value can be handed to
137
+ * `Model.aggregate()` on a Mongoose backend. Pass `{ mongoCompatible: true }` to have any
138
+ * non-portable construct rejected at development time rather than discovered in production.
139
+ */
140
+ async aggregate(pipeline, options = {}) {
141
+ await this.ensureIndexes();
142
+ await this.runPreHooks("aggregate", { modelName: this.modelName, op: "aggregate" });
143
+ const result = await (0, pipeline_ts_1.runPipeline)(pipeline, this.aggregationSource(), {
144
+ ...(this.runtime.time.serverTimeZone ? { timezone: options.timezone } : { timezone: options.timezone }),
145
+ ...options,
146
+ });
147
+ await this.runPostHooks("aggregate", result.documents, { modelName: this.modelName, op: "aggregate" });
148
+ return result.documents;
149
+ }
150
+ /** Same pipeline, but reports what was pushed into storage and what ran in JS. */
151
+ async explainAggregate(pipeline, options = {}) {
152
+ await this.ensureIndexes();
153
+ const result = await (0, pipeline_ts_1.runPipeline)(pipeline, this.aggregationSource(), { ...options, explain: true });
154
+ return result.explain;
155
+ }
156
+ aggregationSource() {
157
+ return new source_ts_1.StorageAggregationSource({
158
+ adapter: this.adapter,
159
+ collection: this.collectionName,
160
+ schema: this.schema,
161
+ // $lookup names a COLLECTION, so resolve it to a registered model when one exists — that is
162
+ // what lets the joined documents be hydrated with their own schema types.
163
+ resolveCollection: (name) => {
164
+ const model = this.runtime.getModelByCollection?.(name);
165
+ if (model)
166
+ return { collection: model.collectionName, schema: model.schema };
167
+ return { collection: name, schema: this.schema };
168
+ },
169
+ });
170
+ }
171
+ /**
172
+ * Bulk write, mirroring Mongoose. Operations are applied in order and reported per type.
173
+ */
174
+ async bulkWrite(operations) {
175
+ const summary = { insertedCount: 0, matchedCount: 0, modifiedCount: 0, deletedCount: 0, upsertedCount: 0 };
176
+ for (const op of operations) {
177
+ const kind = Object.keys(op)[0];
178
+ const spec = op[kind];
179
+ switch (kind) {
180
+ case "insertOne": {
181
+ await this.insertOne(spec.document);
182
+ summary.insertedCount++;
183
+ break;
184
+ }
185
+ case "updateOne":
186
+ case "updateMany": {
187
+ const s = spec;
188
+ const res = await (kind === "updateOne" ? this.updateOne : this.updateMany).call(this, s.filter, s.update, s.upsert ? { upsert: true } : {});
189
+ summary.matchedCount += res.matchedCount;
190
+ summary.modifiedCount += res.modifiedCount;
191
+ summary.upsertedCount += res.upsertedCount;
192
+ break;
193
+ }
194
+ case "replaceOne": {
195
+ const s = spec;
196
+ const res = await this.replaceOne(s.filter, s.replacement);
197
+ summary.matchedCount += res.matchedCount;
198
+ summary.modifiedCount += res.modifiedCount;
199
+ break;
200
+ }
201
+ case "deleteOne":
202
+ case "deleteMany": {
203
+ const s = spec;
204
+ const res = await (kind === "deleteOne" ? this.deleteOne : this.deleteMany).call(this, s.filter);
205
+ summary.deletedCount += res.deletedCount;
206
+ break;
207
+ }
208
+ default:
209
+ throw new errors_ts_1.MongoServerError({ message: `Unknown bulkWrite operation "${String(kind)}"`, code: 9 });
210
+ }
211
+ }
212
+ return summary;
213
+ }
214
+ // ---- writes --------------------------------------------------------------
215
+ async create(input) {
216
+ if (Array.isArray(input))
217
+ return this.insertMany(input);
218
+ return this.insertOne(input);
219
+ }
220
+ async insertOne(input) {
221
+ await this.ensureIndexes();
222
+ const row = await this.prepareInsert(input);
223
+ await this.persist([{ type: "insert", collection: this.collectionName, _id: row.doc._id, row }], "save", {
224
+ doc: row.doc,
225
+ });
226
+ return this.hydrate(row);
227
+ }
228
+ /**
229
+ * `ordered: true` (the default) stops at the first error; `ordered: false` attempts every
230
+ * document and reports all failures in a BulkWriteError — matching MongoDB, including the
231
+ * accurate `insertedCount`.
232
+ */
233
+ async insertMany(inputs, options = {}) {
234
+ await this.ensureIndexes();
235
+ const ordered = options.ordered ?? true;
236
+ if (ordered) {
237
+ const rows = [];
238
+ for (const input of inputs)
239
+ rows.push(await this.prepareInsert(input));
240
+ await this.persist(rows.map((row) => ({ type: "insert", collection: this.collectionName, _id: row.doc._id, row })), "insertMany", {});
241
+ return rows.map((r) => this.hydrate(r));
242
+ }
243
+ const inserted = [];
244
+ const insertedIds = {};
245
+ const writeErrors = [];
246
+ for (let i = 0; i < inputs.length; i++) {
247
+ try {
248
+ const row = await this.prepareInsert(inputs[i]);
249
+ await this.persist([{ type: "insert", collection: this.collectionName, _id: row.doc._id, row }], "save", {
250
+ doc: row.doc,
251
+ });
252
+ inserted.push(row);
253
+ insertedIds[i] = row.doc._id;
254
+ }
255
+ catch (err) {
256
+ const e = err;
257
+ writeErrors.push({ index: i, code: e.code ?? 0, errmsg: e.message, err: e });
258
+ }
259
+ }
260
+ if (writeErrors.length > 0) {
261
+ throw new errors_ts_1.BulkWriteError({ writeErrors, insertedCount: inserted.length, insertedIds });
262
+ }
263
+ return inserted.map((r) => this.hydrate(r));
264
+ }
265
+ async updateOne(filter, update, options = {}) {
266
+ return this.runUpdate(filter, update, { ...options, multi: false });
267
+ }
268
+ async updateMany(filter, update, options = {}) {
269
+ return this.runUpdate(filter, update, { ...options, multi: true });
270
+ }
271
+ async replaceOne(filter, replacement, options = {}) {
272
+ return this.runUpdate(filter, replacement, { ...options, multi: false, replace: true });
273
+ }
274
+ async findOneAndUpdate(filter, update, options = {}) {
275
+ const before = await this.findOne(filter).exec();
276
+ if (!before) {
277
+ if (options.upsert) {
278
+ await this.runUpdate(filter, update, { ...options, multi: false });
279
+ return this.findOne(filter).exec();
280
+ }
281
+ return null;
282
+ }
283
+ await this.runUpdate({ _id: before._id }, update, { ...options, multi: false });
284
+ // Mongoose returns the pre-update document unless `new: true`.
285
+ return options.new ? this.findById(before._id).exec() : before;
286
+ }
287
+ async findByIdAndUpdate(id, update, options = {}) {
288
+ return this.findOneAndUpdate({ _id: normaliseId(id) }, update, options);
289
+ }
290
+ async findOneAndDelete(filter) {
291
+ const doc = await this.findOne(filter).exec();
292
+ if (!doc)
293
+ return null;
294
+ await this.deleteOne({ _id: doc._id });
295
+ return doc;
296
+ }
297
+ async findByIdAndDelete(id) {
298
+ return this.findOneAndDelete({ _id: normaliseId(id) });
299
+ }
300
+ async deleteOne(filter) {
301
+ return this.runDelete(filter, false);
302
+ }
303
+ async deleteMany(filter) {
304
+ return this.runDelete(filter, true);
305
+ }
306
+ // ---- internals -----------------------------------------------------------
307
+ async prepareInsert(input) {
308
+ const now = this.runtime.time.now();
309
+ const raw = (0, path_ts_1.deepClone)(input);
310
+ const id = raw._id !== undefined ? normaliseId(raw._id) : new object_id_ts_1.ObjectId().toHexString();
311
+ delete raw._id;
312
+ const { doc } = (0, cast_ts_1.castDocument)(raw, this.schema, { applyDefaults: true });
313
+ doc._id = id;
314
+ const { createdAt, updatedAt } = this.schema.timestampFields;
315
+ if (createdAt)
316
+ doc[createdAt] = now;
317
+ if (updatedAt)
318
+ doc[updatedAt] = now;
319
+ if (this.schema.versionKey)
320
+ doc[this.schema.versionKey] = 0;
321
+ await this.runPreHooks("validate", { modelName: this.modelName, op: "validate", doc });
322
+ await (0, validate_ts_1.validateDocument)(doc, this.schema, { modelName: this.modelName });
323
+ await this.runPostHooks("validate", doc, { modelName: this.modelName, op: "validate", doc });
324
+ return {
325
+ doc: serialise(doc),
326
+ meta: {
327
+ version: 0,
328
+ hlc: this.runtime.clock.tickStamp(),
329
+ dirty: this.runtime.syncEnabled,
330
+ deleted: false,
331
+ createdAt: now,
332
+ updatedAt: now,
333
+ },
334
+ };
335
+ }
336
+ async runUpdate(filter, update, options) {
337
+ await this.ensureIndexes();
338
+ await this.runPreHooks(options.multi ? "updateMany" : "updateOne", {
339
+ modelName: this.modelName,
340
+ op: options.multi ? "updateMany" : "updateOne",
341
+ filter,
342
+ update,
343
+ });
344
+ const matches = await this.loadMatching(filter, options.multi ? undefined : 1);
345
+ if (matches.length === 0 && options.upsert) {
346
+ const seed = buildUpsertSeed(filter, update);
347
+ const created = await this.insertOne(seed);
348
+ return { acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedCount: 1, upsertedId: created._id };
349
+ }
350
+ const now = this.runtime.time.now();
351
+ const ops = [];
352
+ let modified = 0;
353
+ for (const row of matches) {
354
+ const currentDoc = hydrateDoc(row, this.schema);
355
+ const replace = options.replace ?? (0, update_ts_1.isReplacement)(update);
356
+ let nextDoc;
357
+ if (replace) {
358
+ const { doc: castReplacement } = (0, cast_ts_1.castDocument)(stripImmutable(update, this.schema), this.schema, { applyDefaults: true });
359
+ nextDoc = castReplacement;
360
+ nextDoc._id = currentDoc._id;
361
+ // createdAt survives a replace unless explicitly overridden (§26.4).
362
+ const createdField = this.schema.timestampFields.createdAt;
363
+ if (createdField)
364
+ nextDoc[createdField] = currentDoc[createdField] ?? row.meta.createdAt;
365
+ }
366
+ else {
367
+ const applied = (0, update_ts_1.applyUpdate)(currentDoc, update);
368
+ const { doc: recast } = (0, cast_ts_1.castDocument)(applied, this.schema, { applyDefaults: false });
369
+ nextDoc = recast;
370
+ nextDoc._id = currentDoc._id;
371
+ const createdField = this.schema.timestampFields.createdAt;
372
+ if (createdField)
373
+ nextDoc[createdField] = currentDoc[createdField];
374
+ }
375
+ if (options.runValidators !== false) {
376
+ const paths = replace ? undefined : (0, update_ts_1.updatedPaths)(update);
377
+ await (0, validate_ts_1.validateDocument)(nextDoc, this.schema, {
378
+ modelName: this.modelName,
379
+ ...(paths ? { pathsToValidate: paths.filter((p) => this.schema.paths.has(p)) } : {}),
380
+ });
381
+ }
382
+ // Did this update actually change anything? Compare with updatedAt and the version key
383
+ // excluded on both sides: those are stamped below precisely because the cast above drops them,
384
+ // so including them would guarantee a difference and modifiedCount could never be 0.
385
+ //
386
+ // Mongo treats a no-op update as exactly that — matched, not modified, updatedAt untouched.
387
+ // Skipping the write is what makes that true here, and it is what stops a bulk
388
+ // "set status to active" over 10,000 documents queueing 10,000 mutations when only a few
389
+ // hundred needed changing.
390
+ if (sameContent(serialise(nextDoc), row.doc, this.schema))
391
+ continue;
392
+ modified++;
393
+ const updatedField = this.schema.timestampFields.updatedAt;
394
+ if (updatedField)
395
+ nextDoc[updatedField] = now;
396
+ if (this.schema.versionKey) {
397
+ nextDoc[this.schema.versionKey] = Number(currentDoc[this.schema.versionKey] ?? 0) + 1;
398
+ }
399
+ const serialised = serialise(nextDoc);
400
+ ops.push({
401
+ type: replace ? "replace" : "update",
402
+ collection: this.collectionName,
403
+ _id: row.doc._id,
404
+ row: {
405
+ doc: serialised,
406
+ meta: { ...row.meta, updatedAt: now, hlc: this.runtime.clock.tickStamp(), dirty: this.runtime.syncEnabled },
407
+ },
408
+ });
409
+ }
410
+ if (ops.length > 0)
411
+ await this.persist(ops, options.multi ? "updateMany" : "updateOne", { filter, update });
412
+ return {
413
+ acknowledged: true,
414
+ matchedCount: matches.length,
415
+ modifiedCount: modified,
416
+ upsertedCount: 0,
417
+ upsertedId: null,
418
+ };
419
+ }
420
+ async runDelete(filter, multi) {
421
+ await this.ensureIndexes();
422
+ await this.runPreHooks(multi ? "deleteMany" : "deleteOne", {
423
+ modelName: this.modelName,
424
+ op: multi ? "deleteMany" : "deleteOne",
425
+ filter,
426
+ });
427
+ const matches = await this.loadMatching(filter, multi ? undefined : 1);
428
+ if (matches.length === 0)
429
+ return { acknowledged: true, deletedCount: 0 };
430
+ const now = this.runtime.time.now();
431
+ const ops = matches.map((row) => this.runtime.syncEnabled
432
+ ? // Synced mode keeps a tombstone: the deletion itself has to be replayable to the server.
433
+ {
434
+ type: "delete",
435
+ collection: this.collectionName,
436
+ _id: row.doc._id,
437
+ row: {
438
+ doc: row.doc,
439
+ meta: {
440
+ ...row.meta,
441
+ deleted: true,
442
+ deletedAt: now,
443
+ updatedAt: now,
444
+ dirty: true,
445
+ hlc: this.runtime.clock.tickStamp(),
446
+ },
447
+ },
448
+ }
449
+ : // Local-only mode has nobody to tell, so the row simply goes.
450
+ { type: "hardDelete", collection: this.collectionName, _id: row.doc._id });
451
+ await this.persist(ops, multi ? "deleteMany" : "deleteOne", { filter });
452
+ return { acknowledged: true, deletedCount: matches.length };
453
+ }
454
+ /** The single write path: storage, then mutation queue, then events. */
455
+ async persist(ops, hook, ctx) {
456
+ await this.adapter.write(ops);
457
+ if (this.runtime.syncEnabled) {
458
+ await this.runtime.recordMutations(this.collectionName, ops);
459
+ }
460
+ for (const op of ops) {
461
+ this.runtime.events.emit("change", {
462
+ collection: this.collectionName,
463
+ modelName: this.modelName,
464
+ operation: op.type === "hardDelete" ? "delete" : op.type,
465
+ documentId: op._id,
466
+ document: op.row ? hydrateDoc(op.row, this.schema) : null,
467
+ });
468
+ }
469
+ await this.runPostHooks(hook, ops, { modelName: this.modelName, op: hook, ...ctx });
470
+ }
471
+ async loadMatching(rawFilter, limit) {
472
+ const filter = (0, cast_ts_1.castFilter)(rawFilter, this.schema);
473
+ const result = await this.adapter.find({
474
+ collection: this.collectionName,
475
+ constraints: (0, filter_ts_1.extractConstraints)(filter),
476
+ });
477
+ // The adapter narrows; the JS matcher decides. Same reasoning as run(): extracted constraints
478
+ // are not the whole filter, so matching is never skipped.
479
+ const out = [];
480
+ for (const row of result.rows) {
481
+ if (!(0, filter_ts_1.matchesFilter)(hydrateDoc(row, this.schema), filter))
482
+ continue;
483
+ out.push(row);
484
+ if (limit !== undefined && out.length >= limit)
485
+ break;
486
+ }
487
+ return out;
488
+ }
489
+ async runPreHooks(name, ctx) {
490
+ for (const fn of this.schema.preHooks.get(name) ?? []) {
491
+ await fn.call(ctx.doc ?? this, ctx);
492
+ }
493
+ }
494
+ async runPostHooks(name, result, ctx) {
495
+ for (const fn of this.schema.postHooks.get(name) ?? []) {
496
+ await fn.call(ctx.doc ?? this, result, ctx);
497
+ }
498
+ }
499
+ /**
500
+ * Return a Document, matching what queries return.
501
+ *
502
+ * Mongoose's create()/insertMany() hand back Documents, so `(await User.create(...)).save()`
503
+ * works. Returning a plain object here while find() returned a Document would be an inconsistency
504
+ * a user would hit immediately and could not explain.
505
+ */
506
+ hydrate(row) {
507
+ const doc = hydrateDoc(row, this.schema);
508
+ return (this.documentFactory ? this.documentFactory(doc) : doc);
509
+ }
510
+ // ---- query execution -----------------------------------------------------
511
+ /** Entry point for every `Query`. This is where the whole chain becomes one storage plan. */
512
+ async run(state) {
513
+ await this.ensureIndexes();
514
+ await this.runPreHooks(state.op === "findOne" ? "findOne" : "find", {
515
+ modelName: this.modelName,
516
+ op: state.op === "findOne" ? "findOne" : "find",
517
+ filter: state.filter,
518
+ });
519
+ // Cast filter values through the schema first, so a hex string reaches the matcher as the
520
+ // ObjectId the document actually holds.
521
+ state = { ...state, filter: (0, cast_ts_1.castFilter)(state.filter, this.schema) };
522
+ const constraints = (0, filter_ts_1.extractConstraints)(state.filter);
523
+ const wantsOne = state.op === "findOne";
524
+ const effectiveLimit = wantsOne ? 1 : state.limit;
525
+ /**
526
+ * `extractConstraints` drops whatever it cannot express — a `$regex`, an `$or`, an
527
+ * `$elemMatch`. The adapter therefore reports it "applied all constraints" while conditions
528
+ * remain unevaluated. Trusting that flag as "the filter is satisfied" would return rows that do
529
+ * not match, so:
530
+ *
531
+ * - the JS matcher below always runs and is the sole authority on correctness;
532
+ * - the storage engine may apply skip/limit ONLY when extraction was lossless, because paging
533
+ * over a row set that still needs filtering pages over the wrong rows.
534
+ */
535
+ const lossless = (0, filter_ts_1.isFullyExtractable)(state.filter);
536
+ const canPushPaging = lossless;
537
+ const result = await this.adapter.find({
538
+ collection: this.collectionName,
539
+ constraints,
540
+ ...(state.sort ? { sort: state.sort } : {}),
541
+ ...(canPushPaging && state.skip !== undefined ? { skip: state.skip } : {}),
542
+ ...(canPushPaging && effectiveLimit !== undefined ? { limit: effectiveLimit } : {}),
543
+ });
544
+ let docs = result.rows.map((row) => hydrateDoc(row, this.schema));
545
+ const examined = docs.length;
546
+ // Always filter. Cheap on an already-narrowed set, and the only way the answer is guaranteed.
547
+ docs = docs.filter((d) => (0, filter_ts_1.matchesFilter)(d, state.filter));
548
+ if (state.sort && !result.applied.sort)
549
+ docs = sortDocs(docs, state.sort);
550
+ if (state.skip !== undefined && !(canPushPaging && result.applied.skip))
551
+ docs = docs.slice(state.skip);
552
+ if (effectiveLimit !== undefined && !(canPushPaging && result.applied.limit)) {
553
+ docs = docs.slice(0, effectiveLimit);
554
+ }
555
+ if (state.op === "count")
556
+ return docs.length;
557
+ if (state.op === "distinct") {
558
+ const field = state.distinctField;
559
+ const seen = [];
560
+ for (const doc of docs) {
561
+ const value = (0, path_ts_1.getPath)(doc, field);
562
+ const values = Array.isArray(value) ? value : [value];
563
+ for (const v of values) {
564
+ if (v !== undefined && !seen.some((s) => (0, path_ts_1.compareValues)(s, v) === 0))
565
+ seen.push(v);
566
+ }
567
+ }
568
+ return seen;
569
+ }
570
+ if (state.populate.length > 0) {
571
+ await this.applyPopulate(docs, state.populate);
572
+ }
573
+ if (state.projection)
574
+ docs = docs.map((d) => project(d, state.projection));
575
+ if (state.explain) {
576
+ const explain = {
577
+ op: state.op,
578
+ filter: state.filter,
579
+ stage: result.indexUsed ? "IXSCAN" : "COLLSCAN",
580
+ indexUsed: result.indexUsed ?? null,
581
+ pushedDown: result.applied,
582
+ documentsExamined: examined,
583
+ documentsReturned: docs.length,
584
+ populatedPaths: state.populate.map((p) => p.path),
585
+ ...(state.sort ? { sort: state.sort } : {}),
586
+ };
587
+ return explain;
588
+ }
589
+ // Mongoose returns Documents (with .save(), .isModified()) unless .lean() is used. Matching
590
+ // that is what lets a loaded document be edited and saved without re-learning anything.
591
+ const output = state.lean || !this.documentFactory
592
+ ? docs.map(stripUndefined)
593
+ : docs.map((d) => this.documentFactory(d));
594
+ await this.runPostHooks(wantsOne ? "findOne" : "find", output, {
595
+ modelName: this.modelName,
596
+ op: wantsOne ? "findOne" : "find",
597
+ filter: state.filter,
598
+ });
599
+ if (wantsOne)
600
+ return output[0] ?? null;
601
+ return output;
602
+ }
603
+ /**
604
+ * Batched population: every referenced id across the whole page is collected and fetched with one
605
+ * query per target collection. The naive alternative is one query per document per path, which
606
+ * turns a 50-row page into 50 round trips.
607
+ */
608
+ async applyPopulate(docs, specs) {
609
+ for (const spec of specs) {
610
+ const refName = spec.model ?? this.schema.refs().get(spec.path);
611
+ if (!refName) {
612
+ throw new Error(`Cannot populate "${spec.path}" on model "${this.modelName}": no ref is declared for that path. ` +
613
+ `Add \`ref\` to the schema, or pass \`{ path, model }\`.`);
614
+ }
615
+ const target = this.runtime.getModel(refName);
616
+ const ids = [];
617
+ for (const doc of docs) {
618
+ const value = (0, path_ts_1.getPath)(doc, spec.path);
619
+ if (value === undefined || value === null)
620
+ continue;
621
+ for (const v of Array.isArray(value) ? value : [value])
622
+ ids.push(String(v));
623
+ }
624
+ if (ids.length === 0)
625
+ continue;
626
+ const uniqueIds = [...new Set(ids.map(String))];
627
+ const query = target.find({ _id: { $in: uniqueIds }, ...(spec.match ?? {}) });
628
+ if (spec.select)
629
+ query.select(spec.select);
630
+ if (spec.options?.sort)
631
+ query.sort(spec.options.sort);
632
+ if (spec.options?.limit !== undefined)
633
+ query.limit(spec.options.limit);
634
+ if (spec.options?.skip !== undefined)
635
+ query.skip(spec.options.skip);
636
+ if (spec.populate)
637
+ query.populate(spec.populate);
638
+ const found = (await query.exec());
639
+ const byId = new Map(found.map((d) => [String(d._id), d]));
640
+ const onMissing = this.runtime.onMissingRef;
641
+ for (const doc of docs) {
642
+ const value = (0, path_ts_1.getPath)(doc, spec.path);
643
+ if (value === undefined || value === null)
644
+ continue;
645
+ if (Array.isArray(value)) {
646
+ const resolved = value
647
+ .map((v) => byId.get(String(v)) ?? missingRef(v, onMissing, spec.path, this.modelName))
648
+ .filter((v) => v !== undefined);
649
+ (0, path_ts_1.setPath)(doc, spec.path, resolved);
650
+ }
651
+ else {
652
+ const hit = byId.get(String(value));
653
+ (0, path_ts_1.setPath)(doc, spec.path, hit ?? missingRef(value, onMissing, spec.path, this.modelName));
654
+ }
655
+ }
656
+ }
657
+ }
658
+ }
659
+ exports.Model = Model;
660
+ /**
661
+ * A ref with no local target. Offline-first makes this ordinary rather than exceptional: the
662
+ * referenced document may simply not have synced down yet, so the behaviour is configurable and
663
+ * defaults to Mongoose's (null).
664
+ */
665
+ function missingRef(id, mode, path, modelName) {
666
+ if (mode === "keep-id")
667
+ return id;
668
+ if (mode === "throw") {
669
+ throw new errors_ts_1.DocumentNotFoundError({ _id: id }, `${modelName}.${path} — the referenced document is not present locally. ` +
670
+ `It may not have synced yet; use onMissingRef: "null" or "keep-id" to tolerate this.`);
671
+ }
672
+ return null;
673
+ }
674
+ /**
675
+ * Content equality for an update, ignoring the fields an update always rewrites.
676
+ *
677
+ * `updatedAt` and the version key are stamped on every write, so a straight comparison would report
678
+ * every matched document as modified. Everything else is compared exactly.
679
+ */
680
+ function sameContent(next, stored, schema) {
681
+ const volatileKeys = [schema.timestampFields.updatedAt, schema.versionKey].filter(Boolean);
682
+ const strip = (doc) => {
683
+ if (doc === null || typeof doc !== "object")
684
+ return doc;
685
+ const copy = {};
686
+ for (const [key, value] of Object.entries(doc)) {
687
+ if (!volatileKeys.includes(key))
688
+ copy[key] = value;
689
+ }
690
+ return copy;
691
+ };
692
+ return JSON.stringify(strip(next)) === JSON.stringify(strip(stored));
693
+ }
694
+ function buildUpsertSeed(filter, update) {
695
+ const seed = {};
696
+ // Equality conditions in the filter seed the new document, as Mongo does.
697
+ for (const [key, value] of Object.entries(filter)) {
698
+ if (key.startsWith("$"))
699
+ continue;
700
+ if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date))
701
+ continue;
702
+ (0, path_ts_1.setPath)(seed, key, value);
703
+ }
704
+ return (0, update_ts_1.applyUpdate)(seed, update, { isInsert: true });
705
+ }
706
+ function stripImmutable(doc, schema) {
707
+ const out = { ...doc };
708
+ for (const [path, def] of schema.paths) {
709
+ if (def.immutable)
710
+ delete out[path];
711
+ }
712
+ return out;
713
+ }
714
+ function sortDocs(docs, sort) {
715
+ return [...docs].sort((a, b) => {
716
+ for (const [path, dir] of sort) {
717
+ const c = (0, path_ts_1.compareValues)((0, path_ts_1.getPath)(a, path), (0, path_ts_1.getPath)(b, path));
718
+ if (c !== 0)
719
+ return dir === 1 ? c : -c;
720
+ }
721
+ return 0;
722
+ });
723
+ }
724
+ function project(doc, projection) {
725
+ const entries = Object.entries(projection).filter(([k]) => k !== "_id");
726
+ const including = entries.some(([, v]) => v === 1);
727
+ const out = {};
728
+ if (including) {
729
+ for (const [path, flag] of entries) {
730
+ if (flag === 1) {
731
+ const value = (0, path_ts_1.getPath)(doc, path);
732
+ if (value !== undefined)
733
+ (0, path_ts_1.setPath)(out, path, value);
734
+ }
735
+ }
736
+ if (projection._id !== 0)
737
+ out._id = doc._id;
738
+ return out;
739
+ }
740
+ Object.assign(out, (0, path_ts_1.deepClone)(doc));
741
+ for (const [path] of entries)
742
+ delete out[path];
743
+ if (projection._id === 0)
744
+ delete out._id;
745
+ return out;
746
+ }
747
+ function stripUndefined(doc) {
748
+ const out = {};
749
+ for (const [k, v] of Object.entries(doc))
750
+ if (v !== undefined)
751
+ out[k] = v;
752
+ return out;
753
+ }
754
+ /** Storage holds JSON; typed values (ObjectId, Date) are rebuilt on read. */
755
+ function hydrateDoc(row, schema) {
756
+ const doc = (0, path_ts_1.deepClone)(row.doc);
757
+ // Mongoose exposes _id as an ObjectId, so code doing doc._id.equals(...) or .toHexString()
758
+ // works unchanged. Storage keeps the hex string; the conversion happens here on read.
759
+ if (typeof doc._id === "string" && object_id_ts_1.ObjectId.isValid(doc._id))
760
+ doc._id = new object_id_ts_1.ObjectId(doc._id);
761
+ for (const [path, def] of schema.paths) {
762
+ if (path === "_id")
763
+ continue;
764
+ const value = (0, path_ts_1.getPath)(doc, path);
765
+ if (value === undefined || value === null)
766
+ continue;
767
+ if (def.instance === "Date" && typeof value === "string")
768
+ (0, path_ts_1.setPath)(doc, path, new Date(value));
769
+ else if (def.instance === "ObjectId" && typeof value === "string" && object_id_ts_1.ObjectId.isValid(value)) {
770
+ (0, path_ts_1.setPath)(doc, path, new object_id_ts_1.ObjectId(value));
771
+ }
772
+ else if (def.instance === "Array" && def.arrayType && Array.isArray(value)) {
773
+ if (def.arrayType.instance === "Date")
774
+ (0, path_ts_1.setPath)(doc, path, value.map((v) => (typeof v === "string" ? new Date(v) : v)));
775
+ else if (def.arrayType.instance === "ObjectId") {
776
+ (0, path_ts_1.setPath)(doc, path, value.map((v) => (typeof v === "string" && object_id_ts_1.ObjectId.isValid(v) ? new object_id_ts_1.ObjectId(v) : v)));
777
+ }
778
+ }
779
+ }
780
+ return doc;
781
+ }
782
+ /** Inverse of hydrate: typed values become their JSON forms for storage and the wire. */
783
+ function serialise(doc) {
784
+ if (doc === null || typeof doc !== "object")
785
+ return doc;
786
+ const out = {};
787
+ for (const [key, value] of Object.entries(doc)) {
788
+ out[key] = serialiseValue(value);
789
+ }
790
+ return out;
791
+ }
792
+ function serialiseValue(value) {
793
+ if (value instanceof object_id_ts_1.ObjectId)
794
+ return value.toHexString();
795
+ if (value instanceof Date)
796
+ return value.toISOString();
797
+ if (Array.isArray(value))
798
+ return value.map(serialiseValue);
799
+ if (value !== null && typeof value === "object" && !(value instanceof Uint8Array)) {
800
+ return serialise(value);
801
+ }
802
+ return value;
803
+ }
804
+ function normaliseId(id) {
805
+ if (id instanceof object_id_ts_1.ObjectId)
806
+ return id.toHexString();
807
+ if (typeof id === "string")
808
+ return id;
809
+ if (id && typeof id.toHexString === "function") {
810
+ return id.toHexString();
811
+ }
812
+ return String(id);
813
+ }
814
+ /** Mongoose's collection naming: lowercase and pluralise the model name. */
815
+ function pluralize(name) {
816
+ const lower = name.toLowerCase();
817
+ if (/(s|x|z|ch|sh)$/.test(lower))
818
+ return `${lower}es`;
819
+ if (/[^aeiou]y$/.test(lower))
820
+ return `${lower.slice(0, -1)}ies`;
821
+ return `${lower}s`;
822
+ }
823
+ //# sourceMappingURL=model.js.map