@multiplatform.one/frappe 6.0.4 → 6.3.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 (792) hide show
  1. package/README.md +38 -12
  2. package/dist/cjs/auth.cjs +1 -1
  3. package/dist/cjs/auth.native.js.map +1 -1
  4. package/dist/cjs/call.cjs +1 -1
  5. package/dist/cjs/call.native.js.map +1 -1
  6. package/dist/cjs/collection.cjs +18 -4
  7. package/dist/cjs/collection.native.js +18 -4
  8. package/dist/cjs/collection.native.js.map +1 -1
  9. package/dist/cjs/core/http.cjs +92 -9
  10. package/dist/cjs/core/http.native.js +96 -7
  11. package/dist/cjs/core/http.native.js.map +1 -1
  12. package/dist/cjs/db.cjs +7 -7
  13. package/dist/cjs/db.native.js +4 -4
  14. package/dist/cjs/db.native.js.map +1 -1
  15. package/dist/cjs/doctype.cjs +97 -39
  16. package/dist/cjs/doctype.native.js +116 -46
  17. package/dist/cjs/doctype.native.js.map +1 -1
  18. package/dist/cjs/file.cjs +1 -1
  19. package/dist/cjs/file.native.js.map +1 -1
  20. package/dist/cjs/fixtureDb.cjs +3 -2
  21. package/dist/cjs/fixtureDb.native.js +2 -1
  22. package/dist/cjs/fixtureDb.native.js.map +1 -1
  23. package/dist/cjs/frappeApp.cjs +15 -14
  24. package/dist/cjs/frappeApp.native.js +16 -14
  25. package/dist/cjs/frappeApp.native.js.map +1 -1
  26. package/dist/cjs/frappeReact.cjs +198 -18
  27. package/dist/cjs/frappeReact.native.js +241 -18
  28. package/dist/cjs/frappeReact.native.js.map +1 -1
  29. package/dist/cjs/index.cjs +9 -4
  30. package/dist/cjs/index.native.js +9 -4
  31. package/dist/cjs/index.native.js.map +1 -1
  32. package/dist/cjs/pacer.cjs +2 -2
  33. package/dist/cjs/pacer.native.js +2 -2
  34. package/dist/cjs/pacer.native.js.map +1 -1
  35. package/dist/cjs/realtime.cjs +186 -46
  36. package/dist/cjs/realtime.native.js +268 -48
  37. package/dist/cjs/realtime.native.js.map +1 -1
  38. package/dist/cjs/sync/backfill.cjs +32 -27
  39. package/dist/cjs/sync/backfill.native.js +49 -43
  40. package/dist/cjs/sync/backfill.native.js.map +1 -1
  41. package/dist/cjs/sync/index.cjs +90 -24
  42. package/dist/cjs/sync/index.native.js +112 -10
  43. package/dist/cjs/sync/index.native.js.map +1 -1
  44. package/dist/cjs/sync/merge.cjs +0 -3
  45. package/dist/cjs/sync/merge.native.js +0 -3
  46. package/dist/cjs/sync/merge.native.js.map +1 -1
  47. package/dist/cjs/sync/mutationEngine.cjs +25 -19
  48. package/dist/cjs/sync/mutationEngine.native.js +16 -13
  49. package/dist/cjs/sync/mutationEngine.native.js.map +1 -1
  50. package/dist/cjs/sync/mutationJournal.cjs +9 -4
  51. package/dist/cjs/sync/mutationJournal.native.js +7 -4
  52. package/dist/cjs/sync/mutationJournal.native.js.map +1 -1
  53. package/dist/cjs/sync/normalizedCache.cjs +7 -3
  54. package/dist/cjs/sync/normalizedCache.native.js +7 -2
  55. package/dist/cjs/sync/normalizedCache.native.js.map +1 -1
  56. package/dist/cjs/sync/persistence.cjs +63 -31
  57. package/dist/cjs/sync/persistence.native.js +120 -63
  58. package/dist/cjs/sync/persistence.native.js.map +1 -1
  59. package/dist/cjs/sync/realtime.cjs +124 -13
  60. package/dist/cjs/sync/realtime.native.js +163 -20
  61. package/dist/cjs/sync/realtime.native.js.map +1 -1
  62. package/dist/cjs/sync/rehydration.cjs +16 -10
  63. package/dist/cjs/sync/rehydration.native.js +16 -14
  64. package/dist/cjs/sync/rehydration.native.js.map +1 -1
  65. package/dist/cjs/sync/storage.cjs +3 -3
  66. package/dist/cjs/sync/storage.native.js +1 -1
  67. package/dist/cjs/sync/storage.native.js.map +1 -1
  68. package/dist/cjs/sync/subscriptionManager.cjs +255 -65
  69. package/dist/cjs/sync/subscriptionManager.native.js +330 -93
  70. package/dist/cjs/sync/subscriptionManager.native.js.map +1 -1
  71. package/dist/cjs/sync/types.cjs +2 -0
  72. package/dist/cjs/sync/types.native.js +2 -0
  73. package/dist/cjs/sync/types.native.js.map +1 -1
  74. package/dist/cjs/sync/virtualPageManager.cjs +9 -9
  75. package/dist/cjs/sync/virtualPageManager.native.js +5 -9
  76. package/dist/cjs/sync/virtualPageManager.native.js.map +1 -1
  77. package/dist/cjs/useLiveQuery.cjs +52 -0
  78. package/dist/cjs/useLiveQuery.native.js +59 -0
  79. package/dist/cjs/useLiveQuery.native.js.map +1 -0
  80. package/dist/cjs/util.cjs +11 -2
  81. package/dist/cjs/util.native.js +16 -2
  82. package/dist/cjs/util.native.js.map +1 -1
  83. package/dist/esm/auth.mjs +1 -1
  84. package/dist/esm/auth.mjs.map +1 -1
  85. package/dist/esm/auth.native.js.map +1 -1
  86. package/dist/esm/call.mjs +1 -1
  87. package/dist/esm/call.mjs.map +1 -1
  88. package/dist/esm/call.native.js.map +1 -1
  89. package/dist/esm/collection.mjs +18 -4
  90. package/dist/esm/collection.mjs.map +1 -1
  91. package/dist/esm/collection.native.js +18 -4
  92. package/dist/esm/collection.native.js.map +1 -1
  93. package/dist/esm/core/http.mjs +93 -10
  94. package/dist/esm/core/http.mjs.map +1 -1
  95. package/dist/esm/core/http.native.js +97 -8
  96. package/dist/esm/core/http.native.js.map +1 -1
  97. package/dist/esm/db.mjs +7 -7
  98. package/dist/esm/db.mjs.map +1 -1
  99. package/dist/esm/db.native.js +4 -4
  100. package/dist/esm/db.native.js.map +1 -1
  101. package/dist/esm/doctype.mjs +96 -39
  102. package/dist/esm/doctype.mjs.map +1 -1
  103. package/dist/esm/doctype.native.js +115 -46
  104. package/dist/esm/doctype.native.js.map +1 -1
  105. package/dist/esm/file.mjs +1 -1
  106. package/dist/esm/file.mjs.map +1 -1
  107. package/dist/esm/file.native.js.map +1 -1
  108. package/dist/esm/fixtureDb.mjs +3 -2
  109. package/dist/esm/fixtureDb.mjs.map +1 -1
  110. package/dist/esm/fixtureDb.native.js +2 -1
  111. package/dist/esm/fixtureDb.native.js.map +1 -1
  112. package/dist/esm/frappeApp.mjs +15 -14
  113. package/dist/esm/frappeApp.mjs.map +1 -1
  114. package/dist/esm/frappeApp.native.js +16 -14
  115. package/dist/esm/frappeApp.native.js.map +1 -1
  116. package/dist/esm/frappeReact.mjs +197 -19
  117. package/dist/esm/frappeReact.mjs.map +1 -1
  118. package/dist/esm/frappeReact.native.js +240 -19
  119. package/dist/esm/frappeReact.native.js.map +1 -1
  120. package/dist/esm/index.mjs +5 -4
  121. package/dist/esm/index.mjs.map +1 -1
  122. package/dist/esm/index.native.js +5 -4
  123. package/dist/esm/index.native.js.map +1 -1
  124. package/dist/esm/pacer.mjs +1 -1
  125. package/dist/esm/pacer.native.js +1 -1
  126. package/dist/esm/realtime.mjs +187 -47
  127. package/dist/esm/realtime.mjs.map +1 -1
  128. package/dist/esm/realtime.native.js +269 -49
  129. package/dist/esm/realtime.native.js.map +1 -1
  130. package/dist/esm/sync/backfill.mjs +32 -27
  131. package/dist/esm/sync/backfill.mjs.map +1 -1
  132. package/dist/esm/sync/backfill.native.js +49 -43
  133. package/dist/esm/sync/backfill.native.js.map +1 -1
  134. package/dist/esm/sync/index.mjs +90 -24
  135. package/dist/esm/sync/index.mjs.map +1 -1
  136. package/dist/esm/sync/index.native.js +112 -10
  137. package/dist/esm/sync/index.native.js.map +1 -1
  138. package/dist/esm/sync/merge.mjs +1 -1
  139. package/dist/esm/sync/merge.mjs.map +1 -1
  140. package/dist/esm/sync/merge.native.js +1 -1
  141. package/dist/esm/sync/merge.native.js.map +1 -1
  142. package/dist/esm/sync/mutationEngine.mjs +25 -19
  143. package/dist/esm/sync/mutationEngine.mjs.map +1 -1
  144. package/dist/esm/sync/mutationEngine.native.js +16 -13
  145. package/dist/esm/sync/mutationEngine.native.js.map +1 -1
  146. package/dist/esm/sync/mutationJournal.mjs +9 -4
  147. package/dist/esm/sync/mutationJournal.mjs.map +1 -1
  148. package/dist/esm/sync/mutationJournal.native.js +7 -4
  149. package/dist/esm/sync/mutationJournal.native.js.map +1 -1
  150. package/dist/esm/sync/normalizedCache.mjs +7 -3
  151. package/dist/esm/sync/normalizedCache.mjs.map +1 -1
  152. package/dist/esm/sync/normalizedCache.native.js +7 -2
  153. package/dist/esm/sync/normalizedCache.native.js.map +1 -1
  154. package/dist/esm/sync/persistence.mjs +64 -32
  155. package/dist/esm/sync/persistence.mjs.map +1 -1
  156. package/dist/esm/sync/persistence.native.js +121 -64
  157. package/dist/esm/sync/persistence.native.js.map +1 -1
  158. package/dist/esm/sync/realtime.mjs +124 -13
  159. package/dist/esm/sync/realtime.mjs.map +1 -1
  160. package/dist/esm/sync/realtime.native.js +163 -20
  161. package/dist/esm/sync/realtime.native.js.map +1 -1
  162. package/dist/esm/sync/rehydration.mjs +16 -10
  163. package/dist/esm/sync/rehydration.mjs.map +1 -1
  164. package/dist/esm/sync/rehydration.native.js +16 -14
  165. package/dist/esm/sync/rehydration.native.js.map +1 -1
  166. package/dist/esm/sync/storage.mjs +3 -3
  167. package/dist/esm/sync/storage.mjs.map +1 -1
  168. package/dist/esm/sync/storage.native.js +1 -1
  169. package/dist/esm/sync/storage.native.js.map +1 -1
  170. package/dist/esm/sync/subscriptionManager.mjs +255 -65
  171. package/dist/esm/sync/subscriptionManager.mjs.map +1 -1
  172. package/dist/esm/sync/subscriptionManager.native.js +330 -93
  173. package/dist/esm/sync/subscriptionManager.native.js.map +1 -1
  174. package/dist/esm/sync/types.mjs +2 -0
  175. package/dist/esm/sync/types.mjs.map +1 -1
  176. package/dist/esm/sync/types.native.js +2 -0
  177. package/dist/esm/sync/types.native.js.map +1 -1
  178. package/dist/esm/sync/virtualPageManager.mjs +9 -9
  179. package/dist/esm/sync/virtualPageManager.mjs.map +1 -1
  180. package/dist/esm/sync/virtualPageManager.native.js +5 -9
  181. package/dist/esm/sync/virtualPageManager.native.js.map +1 -1
  182. package/dist/esm/useLiveQuery.mjs +26 -0
  183. package/dist/esm/useLiveQuery.mjs.map +1 -0
  184. package/dist/esm/useLiveQuery.native.js +30 -0
  185. package/dist/esm/useLiveQuery.native.js.map +1 -0
  186. package/dist/esm/util.mjs +11 -3
  187. package/dist/esm/util.mjs.map +1 -1
  188. package/dist/esm/util.native.js +16 -3
  189. package/dist/esm/util.native.js.map +1 -1
  190. package/dist/jsx/auth.mjs +1 -1
  191. package/dist/jsx/auth.mjs.map +1 -1
  192. package/dist/jsx/auth.native.js.map +1 -1
  193. package/dist/jsx/call.mjs +1 -1
  194. package/dist/jsx/call.mjs.map +1 -1
  195. package/dist/jsx/call.native.js.map +1 -1
  196. package/dist/jsx/collection.mjs +18 -4
  197. package/dist/jsx/collection.mjs.map +1 -1
  198. package/dist/jsx/collection.native.js +18 -4
  199. package/dist/jsx/collection.native.js.map +1 -1
  200. package/dist/jsx/core/http.mjs +93 -10
  201. package/dist/jsx/core/http.mjs.map +1 -1
  202. package/dist/jsx/core/http.native.js +96 -7
  203. package/dist/jsx/core/http.native.js.map +1 -1
  204. package/dist/jsx/db.mjs +7 -7
  205. package/dist/jsx/db.mjs.map +1 -1
  206. package/dist/jsx/db.native.js +4 -4
  207. package/dist/jsx/db.native.js.map +1 -1
  208. package/dist/jsx/doctype.mjs +96 -39
  209. package/dist/jsx/doctype.mjs.map +1 -1
  210. package/dist/jsx/doctype.native.js +116 -46
  211. package/dist/jsx/doctype.native.js.map +1 -1
  212. package/dist/jsx/file.mjs +1 -1
  213. package/dist/jsx/file.mjs.map +1 -1
  214. package/dist/jsx/file.native.js.map +1 -1
  215. package/dist/jsx/fixtureDb.mjs +3 -2
  216. package/dist/jsx/fixtureDb.mjs.map +1 -1
  217. package/dist/jsx/fixtureDb.native.js +2 -1
  218. package/dist/jsx/fixtureDb.native.js.map +1 -1
  219. package/dist/jsx/frappeApp.mjs +15 -14
  220. package/dist/jsx/frappeApp.mjs.map +1 -1
  221. package/dist/jsx/frappeApp.native.js +16 -14
  222. package/dist/jsx/frappeApp.native.js.map +1 -1
  223. package/dist/jsx/frappeReact.mjs +197 -19
  224. package/dist/jsx/frappeReact.mjs.map +1 -1
  225. package/dist/jsx/frappeReact.native.js +241 -18
  226. package/dist/jsx/frappeReact.native.js.map +1 -1
  227. package/dist/jsx/index.js +5 -4
  228. package/dist/jsx/index.js.map +1 -1
  229. package/dist/jsx/index.mjs +5 -4
  230. package/dist/jsx/index.mjs.map +1 -1
  231. package/dist/jsx/index.native.js +9 -4
  232. package/dist/jsx/index.native.js.map +1 -1
  233. package/dist/jsx/pacer.mjs +1 -1
  234. package/dist/jsx/pacer.native.js +2 -2
  235. package/dist/jsx/pacer.native.js.map +1 -1
  236. package/dist/jsx/realtime.mjs +187 -47
  237. package/dist/jsx/realtime.mjs.map +1 -1
  238. package/dist/jsx/realtime.native.js +268 -48
  239. package/dist/jsx/realtime.native.js.map +1 -1
  240. package/dist/jsx/sync/backfill.mjs +32 -27
  241. package/dist/jsx/sync/backfill.mjs.map +1 -1
  242. package/dist/jsx/sync/backfill.native.js +49 -43
  243. package/dist/jsx/sync/backfill.native.js.map +1 -1
  244. package/dist/jsx/sync/index.mjs +90 -24
  245. package/dist/jsx/sync/index.mjs.map +1 -1
  246. package/dist/jsx/sync/index.native.js +112 -10
  247. package/dist/jsx/sync/index.native.js.map +1 -1
  248. package/dist/jsx/sync/merge.mjs +1 -1
  249. package/dist/jsx/sync/merge.mjs.map +1 -1
  250. package/dist/jsx/sync/merge.native.js +0 -3
  251. package/dist/jsx/sync/merge.native.js.map +1 -1
  252. package/dist/jsx/sync/mutationEngine.mjs +25 -19
  253. package/dist/jsx/sync/mutationEngine.mjs.map +1 -1
  254. package/dist/jsx/sync/mutationEngine.native.js +16 -13
  255. package/dist/jsx/sync/mutationEngine.native.js.map +1 -1
  256. package/dist/jsx/sync/mutationJournal.mjs +9 -4
  257. package/dist/jsx/sync/mutationJournal.mjs.map +1 -1
  258. package/dist/jsx/sync/mutationJournal.native.js +7 -4
  259. package/dist/jsx/sync/mutationJournal.native.js.map +1 -1
  260. package/dist/jsx/sync/normalizedCache.mjs +7 -3
  261. package/dist/jsx/sync/normalizedCache.mjs.map +1 -1
  262. package/dist/jsx/sync/normalizedCache.native.js +7 -2
  263. package/dist/jsx/sync/normalizedCache.native.js.map +1 -1
  264. package/dist/jsx/sync/persistence.mjs +64 -32
  265. package/dist/jsx/sync/persistence.mjs.map +1 -1
  266. package/dist/jsx/sync/persistence.native.js +120 -63
  267. package/dist/jsx/sync/persistence.native.js.map +1 -1
  268. package/dist/jsx/sync/realtime.mjs +124 -13
  269. package/dist/jsx/sync/realtime.mjs.map +1 -1
  270. package/dist/jsx/sync/realtime.native.js +163 -20
  271. package/dist/jsx/sync/realtime.native.js.map +1 -1
  272. package/dist/jsx/sync/rehydration.mjs +16 -10
  273. package/dist/jsx/sync/rehydration.mjs.map +1 -1
  274. package/dist/jsx/sync/rehydration.native.js +16 -14
  275. package/dist/jsx/sync/rehydration.native.js.map +1 -1
  276. package/dist/jsx/sync/storage.mjs +3 -3
  277. package/dist/jsx/sync/storage.mjs.map +1 -1
  278. package/dist/jsx/sync/storage.native.js +1 -1
  279. package/dist/jsx/sync/storage.native.js.map +1 -1
  280. package/dist/jsx/sync/subscriptionManager.mjs +255 -65
  281. package/dist/jsx/sync/subscriptionManager.mjs.map +1 -1
  282. package/dist/jsx/sync/subscriptionManager.native.js +330 -93
  283. package/dist/jsx/sync/subscriptionManager.native.js.map +1 -1
  284. package/dist/jsx/sync/types.mjs +2 -0
  285. package/dist/jsx/sync/types.mjs.map +1 -1
  286. package/dist/jsx/sync/types.native.js +2 -0
  287. package/dist/jsx/sync/types.native.js.map +1 -1
  288. package/dist/jsx/sync/virtualPageManager.mjs +9 -9
  289. package/dist/jsx/sync/virtualPageManager.mjs.map +1 -1
  290. package/dist/jsx/sync/virtualPageManager.native.js +5 -9
  291. package/dist/jsx/sync/virtualPageManager.native.js.map +1 -1
  292. package/dist/jsx/useLiveQuery.mjs +26 -0
  293. package/dist/jsx/useLiveQuery.mjs.map +1 -0
  294. package/dist/jsx/useLiveQuery.native.js +59 -0
  295. package/dist/jsx/useLiveQuery.native.js.map +1 -0
  296. package/dist/jsx/util.mjs +11 -3
  297. package/dist/jsx/util.mjs.map +1 -1
  298. package/dist/jsx/util.native.js +16 -2
  299. package/dist/jsx/util.native.js.map +1 -1
  300. package/package.json +20 -17
  301. package/src/auth.ts +5 -1
  302. package/src/call.ts +5 -1
  303. package/src/collection.spec.ts +55 -0
  304. package/src/collection.ts +33 -4
  305. package/src/core/http.spec.ts +66 -0
  306. package/src/core/http.ts +115 -9
  307. package/src/core/httpNative.spec.ts +234 -0
  308. package/src/core/types.ts +2 -0
  309. package/src/db.spec.ts +91 -51
  310. package/src/db.ts +27 -8
  311. package/src/doctype.spec.ts +247 -39
  312. package/src/doctype.ts +203 -53
  313. package/src/file.ts +5 -1
  314. package/src/fixtureDb.ts +13 -2
  315. package/src/frappeApp.ts +18 -19
  316. package/src/frappeReact.spec.ts +565 -1
  317. package/src/frappeReact.ts +446 -38
  318. package/src/frappeReactLiveQueryGc.spec.ts +320 -0
  319. package/src/frappeReactNative.spec.ts +65 -0
  320. package/src/index.ts +10 -9
  321. package/src/pacer.ts +2 -2
  322. package/src/realtime.spec.ts +464 -20
  323. package/src/realtime.ts +284 -46
  324. package/src/sync/backfill.spec.ts +43 -0
  325. package/src/sync/backfill.ts +59 -39
  326. package/src/sync/debug.spec.ts +36 -0
  327. package/src/sync/filterValidation.spec.ts +197 -0
  328. package/src/sync/index.ts +98 -7
  329. package/src/sync/merge.ts +3 -3
  330. package/src/sync/mutationEngine.spec.ts +36 -4
  331. package/src/sync/mutationEngine.ts +30 -11
  332. package/src/sync/mutationJournal.ts +18 -4
  333. package/src/sync/normalizedCache.spec.ts +102 -0
  334. package/src/sync/normalizedCache.ts +19 -3
  335. package/src/sync/offlineRestore.spec.ts +423 -0
  336. package/src/sync/persistence.spec.ts +39 -7
  337. package/src/sync/persistence.ts +90 -18
  338. package/src/sync/persistenceGjs.spec.ts +143 -0
  339. package/src/sync/persistenceNative.spec.ts +139 -0
  340. package/src/sync/realtime.spec.ts +18 -1
  341. package/src/sync/realtime.ts +161 -13
  342. package/src/sync/rehydration.ts +23 -5
  343. package/src/sync/storage.ts +5 -4
  344. package/src/sync/subscriptionManager.spec.ts +94 -0
  345. package/src/sync/subscriptionManager.ts +304 -82
  346. package/src/sync/syncModule.spec.ts +137 -0
  347. package/src/sync/types.ts +39 -0
  348. package/src/sync/virtualPageManager.ts +8 -4
  349. package/src/useLiveQuery.ts +58 -0
  350. package/src/util.spec.ts +35 -4
  351. package/src/util.ts +37 -2
  352. package/types/auth.d.ts +13 -0
  353. package/types/auth.d.ts.map +1 -0
  354. package/types/call.d.ts +10 -0
  355. package/types/call.d.ts.map +1 -0
  356. package/types/collection.d.ts +127 -0
  357. package/types/collection.d.ts.map +1 -0
  358. package/types/common/types.d.ts +35 -0
  359. package/types/common/types.d.ts.map +1 -0
  360. package/types/core/http.d.ts +86 -0
  361. package/types/core/http.d.ts.map +1 -0
  362. package/types/core/types.d.ts +74 -0
  363. package/types/core/types.d.ts.map +1 -0
  364. package/types/core/wire.d.ts +405 -0
  365. package/types/core/wire.d.ts.map +1 -0
  366. package/types/db.d.ts +244 -0
  367. package/types/db.d.ts.map +1 -0
  368. package/types/devtools/FrappeDevtoolsPanel.d.ts +7 -0
  369. package/types/devtools/FrappeDevtoolsPanel.d.ts.map +1 -0
  370. package/types/devtools/index.d.ts +4 -0
  371. package/types/devtools/index.d.ts.map +1 -0
  372. package/types/devtools/plugin.d.ts +9 -0
  373. package/types/devtools/plugin.d.ts.map +1 -0
  374. package/types/devtools/theme.d.ts +15 -0
  375. package/types/devtools/theme.d.ts.map +1 -0
  376. package/types/doctype.d.ts +256 -0
  377. package/types/doctype.d.ts.map +1 -0
  378. package/types/file.d.ts +15 -0
  379. package/types/file.d.ts.map +1 -0
  380. package/types/fixtureDb.d.ts +76 -0
  381. package/types/fixtureDb.d.ts.map +1 -0
  382. package/types/fixtures.d.ts +55 -0
  383. package/types/fixtures.d.ts.map +1 -0
  384. package/types/frappeApp.d.ts +45 -0
  385. package/types/frappeApp.d.ts.map +1 -0
  386. package/types/frappeReact.d.ts +270 -0
  387. package/types/frappeReact.d.ts.map +1 -0
  388. package/types/index.d.ts +44 -0
  389. package/types/index.d.ts.map +1 -0
  390. package/types/optimistic.d.ts +38 -0
  391. package/types/optimistic.d.ts.map +1 -0
  392. package/types/pacer.d.ts +193 -0
  393. package/types/pacer.d.ts.map +1 -0
  394. package/types/plugin/index.d.ts +11 -0
  395. package/types/plugin/index.d.ts.map +1 -0
  396. package/types/realtime.d.ts +121 -0
  397. package/types/realtime.d.ts.map +1 -0
  398. package/types/sync/backfill.d.ts +60 -0
  399. package/types/sync/backfill.d.ts.map +1 -0
  400. package/types/sync/filters.d.ts +101 -0
  401. package/types/sync/filters.d.ts.map +1 -0
  402. package/types/sync/index.d.ts +181 -0
  403. package/types/sync/index.d.ts.map +1 -0
  404. package/types/sync/merge.d.ts +59 -0
  405. package/types/sync/merge.d.ts.map +1 -0
  406. package/types/sync/mutationEngine.d.ts +117 -0
  407. package/types/sync/mutationEngine.d.ts.map +1 -0
  408. package/types/sync/mutationJournal.d.ts +60 -0
  409. package/types/sync/mutationJournal.d.ts.map +1 -0
  410. package/types/sync/normalizedCache.d.ts +59 -0
  411. package/types/sync/normalizedCache.d.ts.map +1 -0
  412. package/types/sync/persistence.d.ts +185 -0
  413. package/types/sync/persistence.d.ts.map +1 -0
  414. package/types/sync/realtime.d.ts +121 -0
  415. package/types/sync/realtime.d.ts.map +1 -0
  416. package/types/sync/rehydration.d.ts +109 -0
  417. package/types/sync/rehydration.d.ts.map +1 -0
  418. package/types/sync/storage.d.ts +65 -0
  419. package/types/sync/storage.d.ts.map +1 -0
  420. package/types/sync/subscriptionManager.d.ts +161 -0
  421. package/types/sync/subscriptionManager.d.ts.map +1 -0
  422. package/types/sync/types.d.ts +435 -0
  423. package/types/sync/types.d.ts.map +1 -0
  424. package/types/sync/virtualPageManager.d.ts +190 -0
  425. package/types/sync/virtualPageManager.d.ts.map +1 -0
  426. package/types/useLiveQuery.d.ts +16 -0
  427. package/types/useLiveQuery.d.ts.map +1 -0
  428. package/types/util.d.ts +24 -0
  429. package/types/util.d.ts.map +1 -0
  430. package/dist/cjs/auth.spec.cjs +0 -322
  431. package/dist/cjs/auth.spec.native.js +0 -329
  432. package/dist/cjs/auth.spec.native.js.map +0 -1
  433. package/dist/cjs/call.spec.cjs +0 -427
  434. package/dist/cjs/call.spec.native.js +0 -430
  435. package/dist/cjs/call.spec.native.js.map +0 -1
  436. package/dist/cjs/collection.spec.cjs +0 -186
  437. package/dist/cjs/collection.spec.native.js +0 -216
  438. package/dist/cjs/collection.spec.native.js.map +0 -1
  439. package/dist/cjs/common/types.spec.cjs +0 -266
  440. package/dist/cjs/common/types.spec.native.js +0 -271
  441. package/dist/cjs/common/types.spec.native.js.map +0 -1
  442. package/dist/cjs/core/http.spec.cjs +0 -1259
  443. package/dist/cjs/core/http.spec.native.js +0 -1401
  444. package/dist/cjs/core/http.spec.native.js.map +0 -1
  445. package/dist/cjs/core/wire.spec.cjs +0 -478
  446. package/dist/cjs/core/wire.spec.native.js +0 -482
  447. package/dist/cjs/core/wire.spec.native.js.map +0 -1
  448. package/dist/cjs/db.spec.cjs +0 -862
  449. package/dist/cjs/db.spec.native.js +0 -865
  450. package/dist/cjs/db.spec.native.js.map +0 -1
  451. package/dist/cjs/doctype.spec.cjs +0 -460
  452. package/dist/cjs/doctype.spec.native.js +0 -538
  453. package/dist/cjs/doctype.spec.native.js.map +0 -1
  454. package/dist/cjs/file.spec.cjs +0 -315
  455. package/dist/cjs/file.spec.native.js +0 -342
  456. package/dist/cjs/file.spec.native.js.map +0 -1
  457. package/dist/cjs/frappeApp.spec.cjs +0 -306
  458. package/dist/cjs/frappeApp.spec.native.js +0 -308
  459. package/dist/cjs/frappeApp.spec.native.js.map +0 -1
  460. package/dist/cjs/frappeReact.spec.cjs +0 -531
  461. package/dist/cjs/frappeReact.spec.native.js +0 -670
  462. package/dist/cjs/frappeReact.spec.native.js.map +0 -1
  463. package/dist/cjs/optimistic.spec.cjs +0 -11
  464. package/dist/cjs/optimistic.spec.native.js +0 -19
  465. package/dist/cjs/optimistic.spec.native.js.map +0 -1
  466. package/dist/cjs/pacer.spec.cjs +0 -470
  467. package/dist/cjs/pacer.spec.native.js +0 -537
  468. package/dist/cjs/pacer.spec.native.js.map +0 -1
  469. package/dist/cjs/realtime.spec.cjs +0 -326
  470. package/dist/cjs/realtime.spec.native.js +0 -392
  471. package/dist/cjs/realtime.spec.native.js.map +0 -1
  472. package/dist/cjs/sync/backfill.spec.cjs +0 -586
  473. package/dist/cjs/sync/backfill.spec.native.js +0 -712
  474. package/dist/cjs/sync/backfill.spec.native.js.map +0 -1
  475. package/dist/cjs/sync/debug.spec.cjs +0 -125
  476. package/dist/cjs/sync/debug.spec.native.js +0 -133
  477. package/dist/cjs/sync/debug.spec.native.js.map +0 -1
  478. package/dist/cjs/sync/filters.spec.cjs +0 -168
  479. package/dist/cjs/sync/filters.spec.native.js +0 -173
  480. package/dist/cjs/sync/filters.spec.native.js.map +0 -1
  481. package/dist/cjs/sync/merge.spec.cjs +0 -908
  482. package/dist/cjs/sync/merge.spec.native.js +0 -937
  483. package/dist/cjs/sync/merge.spec.native.js.map +0 -1
  484. package/dist/cjs/sync/multiOrderBy.spec.cjs +0 -165
  485. package/dist/cjs/sync/multiOrderBy.spec.native.js +0 -229
  486. package/dist/cjs/sync/multiOrderBy.spec.native.js.map +0 -1
  487. package/dist/cjs/sync/mutationEngine.spec.cjs +0 -1158
  488. package/dist/cjs/sync/mutationEngine.spec.native.js +0 -1173
  489. package/dist/cjs/sync/mutationEngine.spec.native.js.map +0 -1
  490. package/dist/cjs/sync/mutationJournal.spec.cjs +0 -330
  491. package/dist/cjs/sync/mutationJournal.spec.native.js +0 -333
  492. package/dist/cjs/sync/mutationJournal.spec.native.js.map +0 -1
  493. package/dist/cjs/sync/mutations.spec.cjs +0 -327
  494. package/dist/cjs/sync/mutations.spec.native.js +0 -330
  495. package/dist/cjs/sync/mutations.spec.native.js.map +0 -1
  496. package/dist/cjs/sync/normalizedCache.spec.cjs +0 -302
  497. package/dist/cjs/sync/normalizedCache.spec.native.js +0 -311
  498. package/dist/cjs/sync/normalizedCache.spec.native.js.map +0 -1
  499. package/dist/cjs/sync/persistence.spec.cjs +0 -562
  500. package/dist/cjs/sync/persistence.spec.native.js +0 -572
  501. package/dist/cjs/sync/persistence.spec.native.js.map +0 -1
  502. package/dist/cjs/sync/realtime.spec.cjs +0 -499
  503. package/dist/cjs/sync/realtime.spec.native.js +0 -512
  504. package/dist/cjs/sync/realtime.spec.native.js.map +0 -1
  505. package/dist/cjs/sync/rehydration.spec.cjs +0 -731
  506. package/dist/cjs/sync/rehydration.spec.native.js +0 -736
  507. package/dist/cjs/sync/rehydration.spec.native.js.map +0 -1
  508. package/dist/cjs/sync/storage.spec.cjs +0 -446
  509. package/dist/cjs/sync/storage.spec.native.js +0 -470
  510. package/dist/cjs/sync/storage.spec.native.js.map +0 -1
  511. package/dist/cjs/sync/subscriptionManager.spec.cjs +0 -1102
  512. package/dist/cjs/sync/subscriptionManager.spec.native.js +0 -1136
  513. package/dist/cjs/sync/subscriptionManager.spec.native.js.map +0 -1
  514. package/dist/cjs/sync/subscriptions.spec.cjs +0 -937
  515. package/dist/cjs/sync/subscriptions.spec.native.js +0 -969
  516. package/dist/cjs/sync/subscriptions.spec.native.js.map +0 -1
  517. package/dist/cjs/sync/syncModule.spec.cjs +0 -206
  518. package/dist/cjs/sync/syncModule.spec.native.js +0 -222
  519. package/dist/cjs/sync/syncModule.spec.native.js.map +0 -1
  520. package/dist/cjs/sync/types.spec.cjs +0 -246
  521. package/dist/cjs/sync/types.spec.native.js +0 -256
  522. package/dist/cjs/sync/types.spec.native.js.map +0 -1
  523. package/dist/cjs/sync/virtualPageManager.spec.cjs +0 -801
  524. package/dist/cjs/sync/virtualPageManager.spec.native.js +0 -873
  525. package/dist/cjs/sync/virtualPageManager.spec.native.js.map +0 -1
  526. package/dist/cjs/util.spec.cjs +0 -43
  527. package/dist/cjs/util.spec.native.js +0 -48
  528. package/dist/cjs/util.spec.native.js.map +0 -1
  529. package/dist/esm/auth.spec.mjs +0 -323
  530. package/dist/esm/auth.spec.mjs.map +0 -1
  531. package/dist/esm/auth.spec.native.js +0 -327
  532. package/dist/esm/auth.spec.native.js.map +0 -1
  533. package/dist/esm/call.spec.mjs +0 -428
  534. package/dist/esm/call.spec.mjs.map +0 -1
  535. package/dist/esm/call.spec.native.js +0 -428
  536. package/dist/esm/call.spec.native.js.map +0 -1
  537. package/dist/esm/collection.spec.mjs +0 -187
  538. package/dist/esm/collection.spec.mjs.map +0 -1
  539. package/dist/esm/collection.spec.native.js +0 -214
  540. package/dist/esm/collection.spec.native.js.map +0 -1
  541. package/dist/esm/common/types.spec.mjs +0 -267
  542. package/dist/esm/common/types.spec.mjs.map +0 -1
  543. package/dist/esm/common/types.spec.native.js +0 -269
  544. package/dist/esm/common/types.spec.native.js.map +0 -1
  545. package/dist/esm/core/http.spec.mjs +0 -1260
  546. package/dist/esm/core/http.spec.mjs.map +0 -1
  547. package/dist/esm/core/http.spec.native.js +0 -1399
  548. package/dist/esm/core/http.spec.native.js.map +0 -1
  549. package/dist/esm/core/wire.spec.mjs +0 -479
  550. package/dist/esm/core/wire.spec.mjs.map +0 -1
  551. package/dist/esm/core/wire.spec.native.js +0 -480
  552. package/dist/esm/core/wire.spec.native.js.map +0 -1
  553. package/dist/esm/db.spec.mjs +0 -863
  554. package/dist/esm/db.spec.mjs.map +0 -1
  555. package/dist/esm/db.spec.native.js +0 -863
  556. package/dist/esm/db.spec.native.js.map +0 -1
  557. package/dist/esm/doctype.spec.mjs +0 -461
  558. package/dist/esm/doctype.spec.mjs.map +0 -1
  559. package/dist/esm/doctype.spec.native.js +0 -536
  560. package/dist/esm/doctype.spec.native.js.map +0 -1
  561. package/dist/esm/file.spec.mjs +0 -316
  562. package/dist/esm/file.spec.mjs.map +0 -1
  563. package/dist/esm/file.spec.native.js +0 -340
  564. package/dist/esm/file.spec.native.js.map +0 -1
  565. package/dist/esm/frappeApp.spec.mjs +0 -307
  566. package/dist/esm/frappeApp.spec.mjs.map +0 -1
  567. package/dist/esm/frappeApp.spec.native.js +0 -306
  568. package/dist/esm/frappeApp.spec.native.js.map +0 -1
  569. package/dist/esm/frappeReact.spec.mjs +0 -532
  570. package/dist/esm/frappeReact.spec.mjs.map +0 -1
  571. package/dist/esm/frappeReact.spec.native.js +0 -668
  572. package/dist/esm/frappeReact.spec.native.js.map +0 -1
  573. package/dist/esm/optimistic.spec.mjs +0 -12
  574. package/dist/esm/optimistic.spec.mjs.map +0 -1
  575. package/dist/esm/optimistic.spec.native.js +0 -17
  576. package/dist/esm/optimistic.spec.native.js.map +0 -1
  577. package/dist/esm/pacer.spec.mjs +0 -447
  578. package/dist/esm/pacer.spec.mjs.map +0 -1
  579. package/dist/esm/pacer.spec.native.js +0 -511
  580. package/dist/esm/pacer.spec.native.js.map +0 -1
  581. package/dist/esm/realtime.spec.mjs +0 -327
  582. package/dist/esm/realtime.spec.mjs.map +0 -1
  583. package/dist/esm/realtime.spec.native.js +0 -390
  584. package/dist/esm/realtime.spec.native.js.map +0 -1
  585. package/dist/esm/sync/backfill.spec.mjs +0 -563
  586. package/dist/esm/sync/backfill.spec.mjs.map +0 -1
  587. package/dist/esm/sync/backfill.spec.native.js +0 -686
  588. package/dist/esm/sync/backfill.spec.native.js.map +0 -1
  589. package/dist/esm/sync/debug.spec.mjs +0 -102
  590. package/dist/esm/sync/debug.spec.mjs.map +0 -1
  591. package/dist/esm/sync/debug.spec.native.js +0 -107
  592. package/dist/esm/sync/debug.spec.native.js.map +0 -1
  593. package/dist/esm/sync/filters.spec.mjs +0 -169
  594. package/dist/esm/sync/filters.spec.mjs.map +0 -1
  595. package/dist/esm/sync/filters.spec.native.js +0 -171
  596. package/dist/esm/sync/filters.spec.native.js.map +0 -1
  597. package/dist/esm/sync/merge.spec.mjs +0 -909
  598. package/dist/esm/sync/merge.spec.mjs.map +0 -1
  599. package/dist/esm/sync/merge.spec.native.js +0 -935
  600. package/dist/esm/sync/merge.spec.native.js.map +0 -1
  601. package/dist/esm/sync/multiOrderBy.spec.mjs +0 -166
  602. package/dist/esm/sync/multiOrderBy.spec.mjs.map +0 -1
  603. package/dist/esm/sync/multiOrderBy.spec.native.js +0 -227
  604. package/dist/esm/sync/multiOrderBy.spec.native.js.map +0 -1
  605. package/dist/esm/sync/mutationEngine.spec.mjs +0 -1159
  606. package/dist/esm/sync/mutationEngine.spec.mjs.map +0 -1
  607. package/dist/esm/sync/mutationEngine.spec.native.js +0 -1171
  608. package/dist/esm/sync/mutationEngine.spec.native.js.map +0 -1
  609. package/dist/esm/sync/mutationJournal.spec.mjs +0 -331
  610. package/dist/esm/sync/mutationJournal.spec.mjs.map +0 -1
  611. package/dist/esm/sync/mutationJournal.spec.native.js +0 -331
  612. package/dist/esm/sync/mutationJournal.spec.native.js.map +0 -1
  613. package/dist/esm/sync/mutations.spec.mjs +0 -328
  614. package/dist/esm/sync/mutations.spec.mjs.map +0 -1
  615. package/dist/esm/sync/mutations.spec.native.js +0 -328
  616. package/dist/esm/sync/mutations.spec.native.js.map +0 -1
  617. package/dist/esm/sync/normalizedCache.spec.mjs +0 -303
  618. package/dist/esm/sync/normalizedCache.spec.mjs.map +0 -1
  619. package/dist/esm/sync/normalizedCache.spec.native.js +0 -309
  620. package/dist/esm/sync/normalizedCache.spec.native.js.map +0 -1
  621. package/dist/esm/sync/persistence.spec.mjs +0 -563
  622. package/dist/esm/sync/persistence.spec.mjs.map +0 -1
  623. package/dist/esm/sync/persistence.spec.native.js +0 -570
  624. package/dist/esm/sync/persistence.spec.native.js.map +0 -1
  625. package/dist/esm/sync/realtime.spec.mjs +0 -500
  626. package/dist/esm/sync/realtime.spec.mjs.map +0 -1
  627. package/dist/esm/sync/realtime.spec.native.js +0 -510
  628. package/dist/esm/sync/realtime.spec.native.js.map +0 -1
  629. package/dist/esm/sync/rehydration.spec.mjs +0 -732
  630. package/dist/esm/sync/rehydration.spec.mjs.map +0 -1
  631. package/dist/esm/sync/rehydration.spec.native.js +0 -734
  632. package/dist/esm/sync/rehydration.spec.native.js.map +0 -1
  633. package/dist/esm/sync/storage.spec.mjs +0 -423
  634. package/dist/esm/sync/storage.spec.mjs.map +0 -1
  635. package/dist/esm/sync/storage.spec.native.js +0 -444
  636. package/dist/esm/sync/storage.spec.native.js.map +0 -1
  637. package/dist/esm/sync/subscriptionManager.spec.mjs +0 -1079
  638. package/dist/esm/sync/subscriptionManager.spec.mjs.map +0 -1
  639. package/dist/esm/sync/subscriptionManager.spec.native.js +0 -1110
  640. package/dist/esm/sync/subscriptionManager.spec.native.js.map +0 -1
  641. package/dist/esm/sync/subscriptions.spec.mjs +0 -914
  642. package/dist/esm/sync/subscriptions.spec.mjs.map +0 -1
  643. package/dist/esm/sync/subscriptions.spec.native.js +0 -943
  644. package/dist/esm/sync/subscriptions.spec.native.js.map +0 -1
  645. package/dist/esm/sync/syncModule.spec.mjs +0 -207
  646. package/dist/esm/sync/syncModule.spec.mjs.map +0 -1
  647. package/dist/esm/sync/syncModule.spec.native.js +0 -220
  648. package/dist/esm/sync/syncModule.spec.native.js.map +0 -1
  649. package/dist/esm/sync/types.spec.mjs +0 -247
  650. package/dist/esm/sync/types.spec.mjs.map +0 -1
  651. package/dist/esm/sync/types.spec.native.js +0 -254
  652. package/dist/esm/sync/types.spec.native.js.map +0 -1
  653. package/dist/esm/sync/virtualPageManager.spec.mjs +0 -802
  654. package/dist/esm/sync/virtualPageManager.spec.mjs.map +0 -1
  655. package/dist/esm/sync/virtualPageManager.spec.native.js +0 -871
  656. package/dist/esm/sync/virtualPageManager.spec.native.js.map +0 -1
  657. package/dist/esm/util.spec.mjs +0 -20
  658. package/dist/esm/util.spec.mjs.map +0 -1
  659. package/dist/esm/util.spec.native.js +0 -22
  660. package/dist/esm/util.spec.native.js.map +0 -1
  661. package/dist/jsx/auth.spec.mjs +0 -323
  662. package/dist/jsx/auth.spec.mjs.map +0 -1
  663. package/dist/jsx/auth.spec.native.js +0 -329
  664. package/dist/jsx/auth.spec.native.js.map +0 -1
  665. package/dist/jsx/call.spec.mjs +0 -428
  666. package/dist/jsx/call.spec.mjs.map +0 -1
  667. package/dist/jsx/call.spec.native.js +0 -430
  668. package/dist/jsx/call.spec.native.js.map +0 -1
  669. package/dist/jsx/collection.spec.mjs +0 -187
  670. package/dist/jsx/collection.spec.mjs.map +0 -1
  671. package/dist/jsx/collection.spec.native.js +0 -216
  672. package/dist/jsx/collection.spec.native.js.map +0 -1
  673. package/dist/jsx/common/types.spec.mjs +0 -267
  674. package/dist/jsx/common/types.spec.mjs.map +0 -1
  675. package/dist/jsx/common/types.spec.native.js +0 -271
  676. package/dist/jsx/common/types.spec.native.js.map +0 -1
  677. package/dist/jsx/core/http.spec.mjs +0 -1260
  678. package/dist/jsx/core/http.spec.mjs.map +0 -1
  679. package/dist/jsx/core/http.spec.native.js +0 -1401
  680. package/dist/jsx/core/http.spec.native.js.map +0 -1
  681. package/dist/jsx/core/wire.spec.mjs +0 -479
  682. package/dist/jsx/core/wire.spec.mjs.map +0 -1
  683. package/dist/jsx/core/wire.spec.native.js +0 -482
  684. package/dist/jsx/core/wire.spec.native.js.map +0 -1
  685. package/dist/jsx/db.spec.mjs +0 -863
  686. package/dist/jsx/db.spec.mjs.map +0 -1
  687. package/dist/jsx/db.spec.native.js +0 -865
  688. package/dist/jsx/db.spec.native.js.map +0 -1
  689. package/dist/jsx/doctype.spec.mjs +0 -461
  690. package/dist/jsx/doctype.spec.mjs.map +0 -1
  691. package/dist/jsx/doctype.spec.native.js +0 -538
  692. package/dist/jsx/doctype.spec.native.js.map +0 -1
  693. package/dist/jsx/file.spec.mjs +0 -316
  694. package/dist/jsx/file.spec.mjs.map +0 -1
  695. package/dist/jsx/file.spec.native.js +0 -342
  696. package/dist/jsx/file.spec.native.js.map +0 -1
  697. package/dist/jsx/frappeApp.spec.mjs +0 -307
  698. package/dist/jsx/frappeApp.spec.mjs.map +0 -1
  699. package/dist/jsx/frappeApp.spec.native.js +0 -308
  700. package/dist/jsx/frappeApp.spec.native.js.map +0 -1
  701. package/dist/jsx/frappeReact.spec.mjs +0 -532
  702. package/dist/jsx/frappeReact.spec.mjs.map +0 -1
  703. package/dist/jsx/frappeReact.spec.native.js +0 -670
  704. package/dist/jsx/frappeReact.spec.native.js.map +0 -1
  705. package/dist/jsx/optimistic.spec.mjs +0 -12
  706. package/dist/jsx/optimistic.spec.mjs.map +0 -1
  707. package/dist/jsx/optimistic.spec.native.js +0 -19
  708. package/dist/jsx/optimistic.spec.native.js.map +0 -1
  709. package/dist/jsx/pacer.spec.mjs +0 -447
  710. package/dist/jsx/pacer.spec.mjs.map +0 -1
  711. package/dist/jsx/pacer.spec.native.js +0 -537
  712. package/dist/jsx/pacer.spec.native.js.map +0 -1
  713. package/dist/jsx/realtime.spec.mjs +0 -327
  714. package/dist/jsx/realtime.spec.mjs.map +0 -1
  715. package/dist/jsx/realtime.spec.native.js +0 -392
  716. package/dist/jsx/realtime.spec.native.js.map +0 -1
  717. package/dist/jsx/sync/backfill.spec.mjs +0 -563
  718. package/dist/jsx/sync/backfill.spec.mjs.map +0 -1
  719. package/dist/jsx/sync/backfill.spec.native.js +0 -712
  720. package/dist/jsx/sync/backfill.spec.native.js.map +0 -1
  721. package/dist/jsx/sync/debug.spec.mjs +0 -102
  722. package/dist/jsx/sync/debug.spec.mjs.map +0 -1
  723. package/dist/jsx/sync/debug.spec.native.js +0 -133
  724. package/dist/jsx/sync/debug.spec.native.js.map +0 -1
  725. package/dist/jsx/sync/filters.spec.mjs +0 -169
  726. package/dist/jsx/sync/filters.spec.mjs.map +0 -1
  727. package/dist/jsx/sync/filters.spec.native.js +0 -173
  728. package/dist/jsx/sync/filters.spec.native.js.map +0 -1
  729. package/dist/jsx/sync/merge.spec.mjs +0 -909
  730. package/dist/jsx/sync/merge.spec.mjs.map +0 -1
  731. package/dist/jsx/sync/merge.spec.native.js +0 -937
  732. package/dist/jsx/sync/merge.spec.native.js.map +0 -1
  733. package/dist/jsx/sync/multiOrderBy.spec.mjs +0 -166
  734. package/dist/jsx/sync/multiOrderBy.spec.mjs.map +0 -1
  735. package/dist/jsx/sync/multiOrderBy.spec.native.js +0 -229
  736. package/dist/jsx/sync/multiOrderBy.spec.native.js.map +0 -1
  737. package/dist/jsx/sync/mutationEngine.spec.mjs +0 -1159
  738. package/dist/jsx/sync/mutationEngine.spec.mjs.map +0 -1
  739. package/dist/jsx/sync/mutationEngine.spec.native.js +0 -1173
  740. package/dist/jsx/sync/mutationEngine.spec.native.js.map +0 -1
  741. package/dist/jsx/sync/mutationJournal.spec.mjs +0 -331
  742. package/dist/jsx/sync/mutationJournal.spec.mjs.map +0 -1
  743. package/dist/jsx/sync/mutationJournal.spec.native.js +0 -333
  744. package/dist/jsx/sync/mutationJournal.spec.native.js.map +0 -1
  745. package/dist/jsx/sync/mutations.spec.mjs +0 -328
  746. package/dist/jsx/sync/mutations.spec.mjs.map +0 -1
  747. package/dist/jsx/sync/mutations.spec.native.js +0 -330
  748. package/dist/jsx/sync/mutations.spec.native.js.map +0 -1
  749. package/dist/jsx/sync/normalizedCache.spec.mjs +0 -303
  750. package/dist/jsx/sync/normalizedCache.spec.mjs.map +0 -1
  751. package/dist/jsx/sync/normalizedCache.spec.native.js +0 -311
  752. package/dist/jsx/sync/normalizedCache.spec.native.js.map +0 -1
  753. package/dist/jsx/sync/persistence.spec.mjs +0 -563
  754. package/dist/jsx/sync/persistence.spec.mjs.map +0 -1
  755. package/dist/jsx/sync/persistence.spec.native.js +0 -572
  756. package/dist/jsx/sync/persistence.spec.native.js.map +0 -1
  757. package/dist/jsx/sync/realtime.spec.mjs +0 -500
  758. package/dist/jsx/sync/realtime.spec.mjs.map +0 -1
  759. package/dist/jsx/sync/realtime.spec.native.js +0 -512
  760. package/dist/jsx/sync/realtime.spec.native.js.map +0 -1
  761. package/dist/jsx/sync/rehydration.spec.mjs +0 -732
  762. package/dist/jsx/sync/rehydration.spec.mjs.map +0 -1
  763. package/dist/jsx/sync/rehydration.spec.native.js +0 -736
  764. package/dist/jsx/sync/rehydration.spec.native.js.map +0 -1
  765. package/dist/jsx/sync/storage.spec.mjs +0 -423
  766. package/dist/jsx/sync/storage.spec.mjs.map +0 -1
  767. package/dist/jsx/sync/storage.spec.native.js +0 -470
  768. package/dist/jsx/sync/storage.spec.native.js.map +0 -1
  769. package/dist/jsx/sync/subscriptionManager.spec.mjs +0 -1079
  770. package/dist/jsx/sync/subscriptionManager.spec.mjs.map +0 -1
  771. package/dist/jsx/sync/subscriptionManager.spec.native.js +0 -1136
  772. package/dist/jsx/sync/subscriptionManager.spec.native.js.map +0 -1
  773. package/dist/jsx/sync/subscriptions.spec.mjs +0 -914
  774. package/dist/jsx/sync/subscriptions.spec.mjs.map +0 -1
  775. package/dist/jsx/sync/subscriptions.spec.native.js +0 -969
  776. package/dist/jsx/sync/subscriptions.spec.native.js.map +0 -1
  777. package/dist/jsx/sync/syncModule.spec.mjs +0 -207
  778. package/dist/jsx/sync/syncModule.spec.mjs.map +0 -1
  779. package/dist/jsx/sync/syncModule.spec.native.js +0 -222
  780. package/dist/jsx/sync/syncModule.spec.native.js.map +0 -1
  781. package/dist/jsx/sync/types.spec.mjs +0 -247
  782. package/dist/jsx/sync/types.spec.mjs.map +0 -1
  783. package/dist/jsx/sync/types.spec.native.js +0 -256
  784. package/dist/jsx/sync/types.spec.native.js.map +0 -1
  785. package/dist/jsx/sync/virtualPageManager.spec.mjs +0 -802
  786. package/dist/jsx/sync/virtualPageManager.spec.mjs.map +0 -1
  787. package/dist/jsx/sync/virtualPageManager.spec.native.js +0 -873
  788. package/dist/jsx/sync/virtualPageManager.spec.native.js.map +0 -1
  789. package/dist/jsx/util.spec.mjs +0 -20
  790. package/dist/jsx/util.spec.mjs.map +0 -1
  791. package/dist/jsx/util.spec.native.js +0 -48
  792. package/dist/jsx/util.spec.native.js.map +0 -1
@@ -67,6 +67,108 @@ describe("NormalizedCache", () => {
67
67
  expect(Object.keys(cache.state.Task.byId)).toHaveLength(0);
68
68
  });
69
69
 
70
+ it("should preserve unprojected fields on narrow-projection upsert", () => {
71
+ const fullDoc = {
72
+ name: "TASK-001",
73
+ doctype: "Task",
74
+ title: "Test Task",
75
+ status: "Open",
76
+ description: "Long description",
77
+ owner: "user@example.com",
78
+ };
79
+ const narrowDoc = {
80
+ name: "TASK-001",
81
+ doctype: "Task",
82
+ title: "Renamed Task",
83
+ };
84
+ cache.upsert(fullDoc);
85
+ cache.upsert(narrowDoc);
86
+ const retrieved = cache.get({ doctype: "Task", name: "TASK-001" });
87
+ expect(retrieved).toEqual({
88
+ name: "TASK-001",
89
+ doctype: "Task",
90
+ title: "Renamed Task",
91
+ status: "Open",
92
+ description: "Long description",
93
+ owner: "user@example.com",
94
+ });
95
+ });
96
+
97
+ it("should overwrite a field present with null (cleared server-side)", () => {
98
+ const fullDoc = {
99
+ name: "TASK-001",
100
+ doctype: "Task",
101
+ title: "Test Task",
102
+ status: "Open",
103
+ description: "Long description",
104
+ };
105
+ const clearedDoc = {
106
+ name: "TASK-001",
107
+ doctype: "Task",
108
+ description: null,
109
+ } as any;
110
+ cache.upsert(fullDoc);
111
+ cache.upsert(clearedDoc);
112
+ const retrieved = cache.get({ doctype: "Task", name: "TASK-001" });
113
+ expect(retrieved?.description).toBeNull();
114
+ expect(retrieved?.title).toBe("Test Task");
115
+ expect(retrieved?.status).toBe("Open");
116
+ });
117
+
118
+ it("should replace values present on a full-doc upsert", () => {
119
+ const originalDoc = {
120
+ name: "TASK-001",
121
+ doctype: "Task",
122
+ title: "Original Task",
123
+ status: "Open",
124
+ description: "Original description",
125
+ };
126
+ const fullUpdate = {
127
+ name: "TASK-001",
128
+ doctype: "Task",
129
+ title: "Updated Task",
130
+ status: "Closed",
131
+ description: "",
132
+ };
133
+ cache.upsert(originalDoc);
134
+ cache.upsert(fullUpdate);
135
+ const retrieved = cache.get({ doctype: "Task", name: "TASK-001" });
136
+ expect(retrieved).toEqual(fullUpdate);
137
+ });
138
+
139
+ it("should drop fields absent from the incoming doc when replace is true", () => {
140
+ const optimisticDoc = {
141
+ name: "TASK-001",
142
+ doctype: "Task",
143
+ title: "Optimistic Task",
144
+ status: "Open",
145
+ extraField: "added optimistically",
146
+ };
147
+ const snapshot = {
148
+ name: "TASK-001",
149
+ doctype: "Task",
150
+ title: "Snapshot Task",
151
+ status: "Open",
152
+ };
153
+ cache.upsert(optimisticDoc);
154
+ cache.upsert(snapshot, { replace: true });
155
+ const retrieved = cache.get({ doctype: "Task", name: "TASK-001" });
156
+ expect(retrieved).toEqual(snapshot);
157
+ expect(retrieved).not.toHaveProperty("extraField");
158
+ });
159
+
160
+ it("should not mutate the previously cached object when merging", () => {
161
+ const originalDoc = {
162
+ name: "TASK-001",
163
+ doctype: "Task",
164
+ title: "Original Task",
165
+ status: "Open",
166
+ };
167
+ cache.upsert(originalDoc);
168
+ cache.upsert({ name: "TASK-001", doctype: "Task", title: "Updated" });
169
+ expect(originalDoc.title).toBe("Original Task");
170
+ });
171
+
70
172
  it("should handle multiple doctypes", () => {
71
173
  const task = {
72
174
  name: "TASK-001",
@@ -12,6 +12,15 @@ export interface NormalizedCacheOptions {
12
12
  onEvict?: (doctype: string, name: string) => void;
13
13
  }
14
14
 
15
+ export interface UpsertOptions {
16
+ /**
17
+ * Replace the cached document wholesale instead of merging fields.
18
+ * Use when the incoming doc is authoritative for its entire shape
19
+ * (e.g. restoring a rollback snapshot).
20
+ */
21
+ replace?: boolean;
22
+ }
23
+
15
24
  /**
16
25
  * Normalized cache with optional LRU eviction.
17
26
  *
@@ -43,7 +52,7 @@ export class NormalizedCache {
43
52
  };
44
53
  }
45
54
 
46
- upsert<Data extends FrappeDocData>(doc: FrappeDoc<Data>) {
55
+ upsert<Data extends FrappeDocData>(doc: FrappeDoc<Data>, options: UpsertOptions = {}) {
47
56
  let bucket = this.state[doc.doctype];
48
57
  if (!bucket) {
49
58
  bucket = { byId: {}, allIds: [] };
@@ -52,11 +61,18 @@ export class NormalizedCache {
52
61
  const id = doc?.name;
53
62
  if (!id) return;
54
63
 
55
- const isNew = !bucket.byId[id];
64
+ const existing = bucket.byId[id];
65
+ const isNew = !existing;
56
66
  if (isNew) {
57
67
  bucket.allIds.push(id);
58
68
  }
59
- bucket.byId[id] = doc;
69
+ // Shallow field merge: only keys PRESENT on the incoming doc overwrite the
70
+ // cached entry, so a narrow-fields fetch (projection) cannot strip fields
71
+ // other live views depend on. A key present with null/"" (genuinely
72
+ // cleared server-side) still overwrites; a key absent from the projection
73
+ // is preserved. Pass `replace: true` for wholesale replacement.
74
+ bucket.byId[id] =
75
+ existing && !options.replace ? ({ ...existing, ...doc } as FrappeDoc<FrappeDocData>) : doc;
60
76
 
61
77
  // Update access time
62
78
  const key = this.makeKey(doc.doctype, id);
@@ -0,0 +1,423 @@
1
+ /**
2
+ * Cold-offline restore behavior: persisted snapshots must serve reads after a
3
+ * reload with no network (cache-first subscribe with re-adoption), restored
4
+ * subscriptions must not accumulate across reloads (adoption + TTL GC), and
5
+ * queued mutations must replay on app focus.
6
+ *
7
+ * These specs simulate "reloads" by creating successive SyncModule instances
8
+ * that share one in-memory KVStorage (standing in for IndexedDB/MMKV).
9
+ */
10
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
11
+ import { SyncModule } from "./index";
12
+ import { BackfillScope, Operation } from "./types";
13
+ import type { KVStorage, SubscriptionQuery } from "./types";
14
+
15
+ /** In-memory KVStorage that survives across simulated reloads. */
16
+ class MemoryKV implements KVStorage {
17
+ store = new Map<string, string>();
18
+ async getItem(key: string) {
19
+ return this.store.get(key) ?? null;
20
+ }
21
+ async setItem(key: string, value: string) {
22
+ this.store.set(key, value);
23
+ }
24
+ async removeItem(key: string) {
25
+ this.store.delete(key);
26
+ }
27
+ }
28
+
29
+ const PERSIST_KEY = "offline-restore-test";
30
+
31
+ const seedDocs = [
32
+ { name: "t1", doctype: "ToDo", modified: "2024-01-01T10:00:00", description: "one" },
33
+ { name: "t2", doctype: "ToDo", modified: "2024-01-01T11:00:00", description: "two" },
34
+ ];
35
+
36
+ // Keep the literal shape/key-order identical everywhere: query-key matching
37
+ // (re-adoption) relies on stable JSON serialization of the query object.
38
+ const todoQuery: SubscriptionQuery = { doctype: "ToDo", fields: ["description"] };
39
+
40
+ function createMockDb() {
41
+ return {
42
+ getDoc: vi.fn().mockResolvedValue(seedDocs[0]),
43
+ getDocList: vi.fn().mockResolvedValue(seedDocs),
44
+ createDoc: vi.fn().mockResolvedValue(seedDocs[0]),
45
+ updateDoc: vi.fn().mockResolvedValue(seedDocs[0]),
46
+ deleteDoc: vi.fn().mockResolvedValue({}),
47
+ backfill: vi.fn().mockResolvedValue({ rows: [], checkpoint: "2024-01-02T00:00:00" }),
48
+ } as any;
49
+ }
50
+
51
+ function snapshotFromStorage(kv: MemoryKV) {
52
+ const raw = kv.store.get(PERSIST_KEY);
53
+ return raw ? JSON.parse(raw) : undefined;
54
+ }
55
+
56
+ describe("offline restore (persistKey)", () => {
57
+ let modules: SyncModule[];
58
+
59
+ beforeEach(() => {
60
+ vi.useFakeTimers();
61
+ modules = [];
62
+ localStorage.clear();
63
+ });
64
+
65
+ afterEach(async () => {
66
+ for (const sync of modules) await sync.dispose();
67
+ vi.useRealTimers();
68
+ vi.restoreAllMocks();
69
+ });
70
+
71
+ function createSync(db: any, options: Record<string, unknown> = {}) {
72
+ const sync = new SyncModule(db, undefined, options);
73
+ modules.push(sync);
74
+ return sync;
75
+ }
76
+
77
+ /** Flushes the 50ms debounced persistence save. */
78
+ async function flushSave() {
79
+ await vi.advanceTimersByTimeAsync(60);
80
+ }
81
+
82
+ /** Session 1: subscribe online and persist a snapshot into `kv`. */
83
+ async function seedSnapshot(kv: MemoryKV) {
84
+ const db = createMockDb();
85
+ const sync = createSync(db, { persistKey: PERSIST_KEY, storage: kv });
86
+ const result = await sync.subscribe(todoQuery);
87
+ await flushSave();
88
+ await sync.dispose();
89
+ return result;
90
+ }
91
+
92
+ describe("cold-offline reads (cache-first subscribe)", () => {
93
+ it("serves restored cache when the reload is offline, keeps checkpoint, and marks the sub stale", async () => {
94
+ const kv = new MemoryKV();
95
+ const first = await seedSnapshot(kv);
96
+ expect(snapshotFromStorage(kv).subs).toHaveLength(1);
97
+
98
+ // Cold reload with no network: every fetch fails
99
+ const offlineDb = createMockDb();
100
+ offlineDb.getDocList.mockRejectedValue(new Error("network down"));
101
+ const sync = createSync(offlineDb, { persistKey: PERSIST_KEY, storage: kv });
102
+
103
+ const result = await sync.subscribe(todoQuery);
104
+
105
+ // The restored subscription was adopted, not replaced
106
+ expect(result.subscriptionId).toBe(first.subscriptionId);
107
+ expect(result.checkpoint).toBe(first.checkpoint);
108
+ // Cached rows render immediately
109
+ expect(result.rows.map((row) => row.name)).toEqual(["t1", "t2"]);
110
+ expect((result.rows[0] as any).description).toBe("one");
111
+
112
+ // The background refresh fails without rejecting and flags staleness
113
+ const refresh = await result.refresh!;
114
+ expect(refresh.ok).toBe(false);
115
+ // The cached membership keeps serving after the failed refresh
116
+ expect(sync.getDocsForSubscription(result.subscriptionId).map((row) => row.name)).toEqual([
117
+ "t1",
118
+ "t2",
119
+ ]);
120
+ const sub = sync.getSubscription(result.subscriptionId);
121
+ expect(sub?.stale).toBe(true);
122
+ // Restored CDC checkpoint is preserved for the next backfill drain
123
+ expect(sub?.checkpoint).toBe(first.checkpoint);
124
+ });
125
+
126
+ it("catches up from the restored checkpoint on the next backfill trigger and clears stale", async () => {
127
+ const kv = new MemoryKV();
128
+ const first = await seedSnapshot(kv);
129
+
130
+ const offlineDb = createMockDb();
131
+ offlineDb.getDocList.mockRejectedValue(new Error("network down"));
132
+ const sync = createSync(offlineDb, { persistKey: PERSIST_KEY, storage: kv });
133
+ const result = await sync.subscribe(todoQuery);
134
+ await result.refresh!;
135
+ expect(sync.getSubscription(result.subscriptionId)?.stale).toBe(true);
136
+
137
+ // Network returns: the CDC drain resumes from the restored checkpoint
138
+ offlineDb.backfill.mockResolvedValue({
139
+ rows: [
140
+ { name: "t3", doctype: "ToDo", modified: "2024-01-01T12:00:00", description: "three" },
141
+ ],
142
+ deleted: [],
143
+ checkpoint: "2024-01-01T12:00:00|t3",
144
+ has_more: false,
145
+ });
146
+ await sync.backfill({ scope: BackfillScope.All });
147
+
148
+ expect(offlineDb.backfill).toHaveBeenCalledWith(
149
+ expect.objectContaining({ doctype: "ToDo", modifiedAfter: first.checkpoint }),
150
+ );
151
+ const sub = sync.getSubscription(result.subscriptionId);
152
+ expect(sub?.stale).toBe(false);
153
+ expect(sub?.checkpoint).toBe("2024-01-01T12:00:00|t3");
154
+ });
155
+
156
+ it("refreshes an adopted subscription from the network when the reload is online", async () => {
157
+ const kv = new MemoryKV();
158
+ const first = await seedSnapshot(kv);
159
+
160
+ const freshDocs = [
161
+ { name: "t2", doctype: "ToDo", modified: "2024-01-01T11:00:00", description: "two" },
162
+ { name: "t9", doctype: "ToDo", modified: "2024-01-03T09:00:00", description: "nine" },
163
+ ];
164
+ const onlineDb = createMockDb();
165
+ onlineDb.getDocList.mockResolvedValue(freshDocs);
166
+ const sync = createSync(onlineDb, { persistKey: PERSIST_KEY, storage: kv });
167
+
168
+ const listener = vi.fn();
169
+ sync.subscribeStore(listener);
170
+ const result = await sync.subscribe(todoQuery);
171
+
172
+ // Immediate render still comes from the cache (stale-while-revalidate)
173
+ expect(result.subscriptionId).toBe(first.subscriptionId);
174
+ expect(result.rows.map((row) => row.name)).toEqual(["t1", "t2"]);
175
+
176
+ listener.mockClear();
177
+ const refresh = await result.refresh!;
178
+ expect(refresh.ok).toBe(true);
179
+ // Store listeners were notified so collections re-read the fresh rows
180
+ expect(listener).toHaveBeenCalled();
181
+
182
+ const sub = sync.getSubscription(result.subscriptionId);
183
+ expect(sub?.stale).toBe(false);
184
+ // Membership replaced by the authoritative fetch, checkpoint recomputed
185
+ expect(sync.getDocsForSubscription(result.subscriptionId).map((row) => row.name)).toEqual([
186
+ "t2",
187
+ "t9",
188
+ ]);
189
+ expect(sub?.checkpoint).toBe("2024-01-03T09:00:00");
190
+ });
191
+
192
+ it("still rejects for queries with no restored subscription (honest error surfacing)", async () => {
193
+ const kv = new MemoryKV();
194
+ await seedSnapshot(kv);
195
+
196
+ const offlineDb = createMockDb();
197
+ offlineDb.getDocList.mockRejectedValue(new Error("network down"));
198
+ const sync = createSync(offlineDb, { persistKey: PERSIST_KEY, storage: kv });
199
+
200
+ await expect(sync.subscribe({ doctype: "Note" })).rejects.toThrow("network down");
201
+ });
202
+
203
+ it("adopts even when subscribe() is called before the async snapshot load finishes", async () => {
204
+ const kv = new MemoryKV();
205
+ const first = await seedSnapshot(kv);
206
+ const raw = kv.store.get(PERSIST_KEY)!;
207
+
208
+ // Storage with a slow (100ms) read, like a busy IndexedDB
209
+ const slowKv: KVStorage = {
210
+ getItem: () => new Promise((resolve) => setTimeout(() => resolve(raw), 100)),
211
+ setItem: async () => {},
212
+ removeItem: async () => {},
213
+ };
214
+ const offlineDb = createMockDb();
215
+ offlineDb.getDocList.mockRejectedValue(new Error("network down"));
216
+ const sync = createSync(offlineDb, { persistKey: PERSIST_KEY, storage: slowKv });
217
+
218
+ const pending = sync.subscribe(todoQuery);
219
+ await vi.advanceTimersByTimeAsync(150);
220
+ const result = await pending;
221
+
222
+ expect(result.subscriptionId).toBe(first.subscriptionId);
223
+ expect(result.rows.map((row) => row.name)).toEqual(["t1", "t2"]);
224
+ });
225
+ });
226
+
227
+ describe("re-adoption and GC (no orphan growth)", () => {
228
+ it("keeps exactly one subscription per query across repeated reload cycles", async () => {
229
+ const kv = new MemoryKV();
230
+ let subscriptionId: string | undefined;
231
+
232
+ for (let cycle = 0; cycle < 3; cycle++) {
233
+ const db = createMockDb();
234
+ const sync = createSync(db, { persistKey: PERSIST_KEY, storage: kv });
235
+ const result = await sync.subscribe(todoQuery);
236
+ if (subscriptionId) expect(result.subscriptionId).toBe(subscriptionId);
237
+ subscriptionId = result.subscriptionId;
238
+ if (result.refresh) await result.refresh;
239
+ await flushSave();
240
+
241
+ // One subscription in memory, one in the snapshot — every cycle
242
+ expect(sync.__debug().subscriptions).toHaveLength(1);
243
+ expect(snapshotFromStorage(kv).subs).toHaveLength(1);
244
+
245
+ await sync.dispose();
246
+ }
247
+ });
248
+
249
+ it("collapses duplicate snapshot entries from pre-fix versions (last wins)", async () => {
250
+ const kv = new MemoryKV();
251
+ // Simulate a legacy snapshot polluted by orphan accumulation
252
+ kv.store.set(
253
+ PERSIST_KEY,
254
+ JSON.stringify({
255
+ subs: [
256
+ { id: "legacy-1", query: todoQuery, checkpoint: "2024-01-01T08:00:00", docIds: ["t1"] },
257
+ { id: "legacy-2", query: todoQuery, checkpoint: "2024-01-01T09:00:00", docIds: ["t1"] },
258
+ {
259
+ id: "legacy-3",
260
+ query: todoQuery,
261
+ checkpoint: "2024-01-01T10:00:00",
262
+ docIds: ["t1", "t2"],
263
+ },
264
+ ],
265
+ cache: {
266
+ ToDo: {
267
+ byId: { t1: seedDocs[0], t2: seedDocs[1] },
268
+ allIds: ["t1", "t2"],
269
+ },
270
+ },
271
+ journal: [],
272
+ temp: [],
273
+ }),
274
+ );
275
+
276
+ const offlineDb = createMockDb();
277
+ offlineDb.getDocList.mockRejectedValue(new Error("network down"));
278
+ const sync = createSync(offlineDb, { persistKey: PERSIST_KEY, storage: kv });
279
+
280
+ const result = await sync.subscribe(todoQuery);
281
+ // Last snapshot entry (most recent session) won the dedupe
282
+ expect(result.subscriptionId).toBe("legacy-3");
283
+ expect(result.checkpoint).toBe("2024-01-01T10:00:00");
284
+ expect(sync.__debug().subscriptions).toHaveLength(1);
285
+
286
+ await flushSave();
287
+ expect(snapshotFromStorage(kv).subs).toHaveLength(1);
288
+ });
289
+
290
+ it("keeps unadopted restored subscriptions within the TTL and GCs them after it", async () => {
291
+ const kv = new MemoryKV();
292
+ await seedSnapshot(kv);
293
+
294
+ const db = createMockDb();
295
+ const sync = createSync(db, {
296
+ persistKey: PERSIST_KEY,
297
+ storage: kv,
298
+ restoredSubscriptionTTL: 1000,
299
+ });
300
+ // Subscribe a DIFFERENT query; the restored ToDo sub stays unadopted
301
+ await sync.subscribe({ doctype: "Note" });
302
+ await flushSave();
303
+
304
+ // Within the TTL the restored sub is retained (and persisted) so a
305
+ // later offline navigation can still adopt it
306
+ let snapshot = snapshotFromStorage(kv);
307
+ expect(snapshot.subs).toHaveLength(2);
308
+ expect(sync.__debug().subscriptions.filter((sub) => sub.restored)).toHaveLength(1);
309
+
310
+ // After the TTL, the next snapshot write GCs it
311
+ await vi.advanceTimersByTimeAsync(1100);
312
+ await sync.subscribe({ doctype: "Comment" });
313
+ await flushSave();
314
+
315
+ snapshot = snapshotFromStorage(kv);
316
+ expect(snapshot.subs).toHaveLength(2); // Note + Comment
317
+ expect(snapshot.subs.map((sub: any) => sub.query.doctype).sort()).toEqual([
318
+ "Comment",
319
+ "Note",
320
+ ]);
321
+ expect(sync.__debug().subscriptions.filter((sub) => sub.restored)).toHaveLength(0);
322
+ });
323
+
324
+ it("excludes unadopted restored subscriptions from backfill fan-out", async () => {
325
+ const kv = new MemoryKV();
326
+ await seedSnapshot(kv);
327
+
328
+ const db = createMockDb();
329
+ const sync = createSync(db, { persistKey: PERSIST_KEY, storage: kv });
330
+ await sync.subscribe({ doctype: "Note" });
331
+
332
+ db.backfill.mockClear();
333
+ await sync.backfill({ scope: BackfillScope.All });
334
+
335
+ // Only the live Note subscription drained; the restored ToDo sub did not
336
+ expect(db.backfill).toHaveBeenCalledTimes(1);
337
+ expect(db.backfill).toHaveBeenCalledWith(expect.objectContaining({ doctype: "Note" }));
338
+ });
339
+ });
340
+
341
+ describe("detach on unsubscribe (persistKey only)", () => {
342
+ it("retains a released subscription for cache-first re-adoption", async () => {
343
+ const kv = new MemoryKV();
344
+ const db = createMockDb();
345
+ const sync = createSync(db, { persistKey: PERSIST_KEY, storage: kv });
346
+
347
+ const first = await sync.subscribe(todoQuery);
348
+ sync.unsubscribe(first.subscriptionId);
349
+
350
+ // Still in memory as a dormant restored subscription
351
+ const debugSubs = sync.__debug().subscriptions;
352
+ expect(debugSubs).toHaveLength(1);
353
+ expect(debugSubs[0].restored).toBe(true);
354
+
355
+ // Excluded from backfill while detached
356
+ db.backfill.mockClear();
357
+ await sync.backfill({ scope: BackfillScope.All });
358
+ expect(db.backfill).not.toHaveBeenCalled();
359
+
360
+ // Remount re-adopts: same id, cached rows immediately
361
+ db.getDocList.mockClear();
362
+ const second = await sync.subscribe(todoQuery);
363
+ expect(second.subscriptionId).toBe(first.subscriptionId);
364
+ expect(second.rows.map((row) => row.name)).toEqual(["t1", "t2"]);
365
+ expect(second.refresh).toBeDefined();
366
+ await second.refresh!;
367
+ expect(db.getDocList).toHaveBeenCalledTimes(1);
368
+ expect(sync.__debug().subscriptions[0].restored).toBe(false);
369
+ });
370
+
371
+ it("without persistKey, unsubscribe deletes the subscription (unchanged behavior)", async () => {
372
+ const db = createMockDb();
373
+ const sync = createSync(db, {});
374
+
375
+ const result = await sync.subscribe(todoQuery);
376
+ expect(result.refresh).toBeUndefined();
377
+ sync.unsubscribe(result.subscriptionId);
378
+
379
+ expect(sync.__debug().subscriptions).toHaveLength(0);
380
+ expect(sync.getSubscription(result.subscriptionId)).toBeUndefined();
381
+ });
382
+ });
383
+
384
+ describe("journal replay on app focus", () => {
385
+ it("replays queued mutations when the app regains focus", async () => {
386
+ const db = createMockDb();
387
+ const sync = createSync(db, {});
388
+ await sync.subscribe(todoQuery);
389
+
390
+ // Mutation fails (server unreachable) and stays queued in the journal
391
+ db.updateDoc.mockRejectedValueOnce(new Error("fetch failed"));
392
+ await expect(
393
+ sync.mutate({
394
+ mutationId: "m-focus-1",
395
+ operation: Operation.Update,
396
+ doc: { doctype: "ToDo", name: "t1", description: "edited" } as any,
397
+ }),
398
+ ).rejects.toThrow();
399
+ expect(db.updateDoc).toHaveBeenCalledTimes(1);
400
+
401
+ // Foreground transition (web focus / RN AppState active) triggers replay
402
+ window.dispatchEvent(new Event("focus"));
403
+ await vi.advanceTimersByTimeAsync(500);
404
+
405
+ expect(db.updateDoc).toHaveBeenCalledTimes(2);
406
+ expect(db.updateDoc.mock.calls[1][0]).toEqual(
407
+ expect.objectContaining({ doctype: "ToDo", name: "t1", client_mutation_id: "m-focus-1" }),
408
+ );
409
+ });
410
+
411
+ it("does not start a replay cycle on focus when the journal is empty", async () => {
412
+ const db = createMockDb();
413
+ const onReplayStart = vi.fn();
414
+ const sync = createSync(db, { onReplayStart });
415
+ await sync.subscribe(todoQuery);
416
+
417
+ window.dispatchEvent(new Event("focus"));
418
+ await vi.advanceTimersByTimeAsync(500);
419
+
420
+ expect(onReplayStart).not.toHaveBeenCalled();
421
+ });
422
+ });
423
+ });
@@ -99,6 +99,8 @@ describe("PersistenceManager", () => {
99
99
  // Mock dependencies
100
100
  mockNormalizedCache = {
101
101
  state: { docs: {}, pages: {} },
102
+ get: vi.fn().mockReturnValue(undefined),
103
+ upsert: vi.fn(),
102
104
  } as any;
103
105
 
104
106
  mockMutationJournal = {
@@ -108,6 +110,8 @@ describe("PersistenceManager", () => {
108
110
 
109
111
  mockSubscriptionManager = {
110
112
  getAllSubscriptions: vi.fn().mockReturnValue(new Map()),
113
+ restoreSubscription: vi.fn(),
114
+ gcRestoredSubscriptions: vi.fn(),
111
115
  } as any;
112
116
 
113
117
  mockMutationEngine = {
@@ -422,6 +426,7 @@ describe("PersistenceManager", () => {
422
426
 
423
427
  describe("load", () => {
424
428
  it("should load and restore persisted state", async () => {
429
+ const cachedUser = { doctype: "User", name: "user1", full_name: "User 1" };
425
430
  const persistedState = {
426
431
  subs: [
427
432
  {
@@ -431,16 +436,14 @@ describe("PersistenceManager", () => {
431
436
  docIds: ["user1", "user2"],
432
437
  },
433
438
  ],
434
- cache: { docs: { user1: { name: "User 1" } } },
439
+ cache: { User: { byId: { user1: cachedUser }, allIds: ["user1"] } },
435
440
  journal: [{ id: "entry1", entry: { type: "create" } }],
436
441
  temp: [["temp1", "real1"]],
437
442
  };
438
443
 
439
444
  mockStorage.getItem.mockResolvedValue(JSON.stringify(persistedState));
440
445
 
441
- const subscriptionsMap = new Map();
442
446
  const tempMap = new Map();
443
- mockSubscriptionManager.getAllSubscriptions.mockReturnValue(subscriptionsMap);
444
447
  mockMutationEngine.getTemporaryIdToRealNameMap.mockReturnValue(tempMap);
445
448
 
446
449
  // Create new instance to trigger load
@@ -454,11 +457,13 @@ describe("PersistenceManager", () => {
454
457
 
455
458
  await vi.advanceTimersByTimeAsync(100);
456
459
 
457
- // Verify cache was restored
458
- expect(mockNormalizedCache.state).toEqual(persistedState.cache);
460
+ // Verify cached docs were merged in per-doc (not wholesale replace)
461
+ expect(mockNormalizedCache.upsert).toHaveBeenCalledWith(cachedUser, { replace: true });
459
462
 
460
- // Verify subscriptions were restored
461
- expect(subscriptionsMap.get("sub1")).toEqual(persistedState.subs[0]);
463
+ // Verify subscriptions were restored as dormant restored entries
464
+ expect(mockSubscriptionManager.restoreSubscription).toHaveBeenCalledWith(
465
+ persistedState.subs[0],
466
+ );
462
467
 
463
468
  // Verify journal was restored
464
469
  expect(mockMutationJournal.add).toHaveBeenCalledWith("entry1", {
@@ -469,6 +474,33 @@ describe("PersistenceManager", () => {
469
474
  expect(tempMap.get("temp1")).toBe("real1");
470
475
  });
471
476
 
477
+ it("should not clobber docs already in memory when merging the snapshot cache", async () => {
478
+ const snapshotDoc = { doctype: "User", name: "user1", full_name: "Old Name" };
479
+ mockStorage.getItem.mockResolvedValue(
480
+ JSON.stringify({
481
+ cache: { User: { byId: { user1: snapshotDoc }, allIds: ["user1"] } },
482
+ }),
483
+ );
484
+ // Doc already exists in memory (e.g. optimistic write raced the load)
485
+ mockNormalizedCache.get.mockReturnValue({
486
+ doctype: "User",
487
+ name: "user1",
488
+ full_name: "Newer Name",
489
+ });
490
+
491
+ new PersistenceManager(
492
+ mockNormalizedCache,
493
+ mockMutationJournal,
494
+ mockSubscriptionManager,
495
+ mockMutationEngine,
496
+ { persistKey: "test-key", storage: mockStorage },
497
+ );
498
+
499
+ await vi.advanceTimersByTimeAsync(100);
500
+
501
+ expect(mockNormalizedCache.upsert).not.toHaveBeenCalled();
502
+ });
503
+
472
504
  it("should handle missing persisted state", async () => {
473
505
  mockStorage.getItem.mockResolvedValue(null);
474
506