@noy-db/hub 0.4.0-pre.8 → 0.4.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 (244) hide show
  1. package/dist/{api-3NKVNZPM.js → api-SI2IVBQO.js} +6 -6
  2. package/dist/attestation/index.js +12 -12
  3. package/dist/{backup-PTSVXDDW.js → backup-X7F3TCFV.js} +6 -6
  4. package/dist/blobs/index.js +5 -5
  5. package/dist/broker/index.js +6 -6
  6. package/dist/cargo/index.js +20 -20
  7. package/dist/{chunk-WZ3NCMK6.js → chunk-2BET5QTS.js} +3 -3
  8. package/dist/{chunk-Y6B6HVKC.js → chunk-2J6UEN2V.js} +41 -17
  9. package/dist/chunk-2J6UEN2V.js.map +1 -0
  10. package/dist/{chunk-BYFXLDVV.js → chunk-3ECU57YH.js} +7 -7
  11. package/dist/{chunk-ZWBKDKXC.js → chunk-467SWYT5.js} +2 -2
  12. package/dist/{chunk-MTJLOC3Y.js → chunk-55LKVALY.js} +106 -10
  13. package/dist/chunk-55LKVALY.js.map +1 -0
  14. package/dist/{chunk-XIDQKFZF.js → chunk-5UQ7Y6SQ.js} +2 -2
  15. package/dist/{chunk-GZACYEOB.js → chunk-77AEMXFA.js} +1 -1
  16. package/dist/chunk-77AEMXFA.js.map +1 -0
  17. package/dist/{chunk-IMRB2C4O.js → chunk-7H3WWH6J.js} +3 -3
  18. package/dist/{chunk-OLIWCCFM.js → chunk-CLE3TMIS.js} +2 -2
  19. package/dist/{chunk-ZFUFAHZ3.js → chunk-DAFBJS4Y.js} +2 -2
  20. package/dist/{chunk-ISRKW4YN.js → chunk-DQZXPGGZ.js} +2 -2
  21. package/dist/{chunk-FMNU7IUG.js → chunk-DTFA5DO4.js} +2 -2
  22. package/dist/{chunk-VH6SOCXH.js → chunk-EFJAAFBW.js} +2 -2
  23. package/dist/{chunk-TIVK6PRK.js → chunk-ERGECZEI.js} +5 -5
  24. package/dist/{chunk-BQ6DHN4I.js → chunk-GTYFIVIZ.js} +101 -22
  25. package/dist/chunk-GTYFIVIZ.js.map +1 -0
  26. package/dist/{chunk-KW42W6SV.js → chunk-HLKXPJ4V.js} +4 -4
  27. package/dist/{chunk-MANUDU7I.js → chunk-HZZP2ZIG.js} +4 -4
  28. package/dist/{chunk-DZAF24PG.js → chunk-IFOH7RBI.js} +3 -3
  29. package/dist/{chunk-FRMW23UK.js → chunk-IVYQAVWO.js} +2 -2
  30. package/dist/{chunk-SGQ4N5FS.js → chunk-JEI6JJNI.js} +3 -3
  31. package/dist/{chunk-BN4HRYAZ.js → chunk-JQ2AX4T5.js} +2 -2
  32. package/dist/{chunk-OBPVWOSQ.js → chunk-KD4HGBJV.js} +3 -3
  33. package/dist/{chunk-QADFHRQM.js → chunk-KYRDJI5O.js} +8 -8
  34. package/dist/{chunk-JTR75MKH.js → chunk-LLYIMSQQ.js} +9 -9
  35. package/dist/{chunk-GP3UWP22.js → chunk-LRRX57UA.js} +2 -2
  36. package/dist/{chunk-OLSARBZU.js → chunk-LXRTP3AQ.js} +2 -2
  37. package/dist/{chunk-EBKCYQ2D.js → chunk-NBXFCQX4.js} +3 -3
  38. package/dist/{chunk-BXHMZ2XW.js → chunk-NLYALJMY.js} +24 -14
  39. package/dist/chunk-NLYALJMY.js.map +1 -0
  40. package/dist/{chunk-EZNTORXE.js → chunk-NM5UYF6Q.js} +1 -1
  41. package/dist/chunk-NM5UYF6Q.js.map +1 -0
  42. package/dist/{chunk-NEX7JCMO.js → chunk-OWHP3H5C.js} +3 -3
  43. package/dist/{chunk-WO4T4OD5.js → chunk-P4JO3H6R.js} +2 -2
  44. package/dist/{chunk-CCDP6EPB.js → chunk-PWPYO73B.js} +2 -2
  45. package/dist/{chunk-56IIVAEO.js → chunk-Q2SEJMP2.js} +2 -2
  46. package/dist/{chunk-JIDLU57U.js → chunk-Q36YXK77.js} +2 -2
  47. package/dist/{chunk-KPXM4WO6.js → chunk-Q5YJCVJY.js} +3 -3
  48. package/dist/{chunk-JYV4JJV2.js → chunk-QGIBI6GL.js} +4 -4
  49. package/dist/{chunk-DGBIHDVK.js → chunk-RBTVFPHF.js} +3 -3
  50. package/dist/{chunk-6R6Q3MRN.js → chunk-RQ4ZI4ZI.js} +4 -4
  51. package/dist/{chunk-FO6RNKKW.js → chunk-S7GIXBXV.js} +2 -2
  52. package/dist/chunk-SBHN6QUT.js +25 -0
  53. package/dist/chunk-SBHN6QUT.js.map +1 -0
  54. package/dist/{chunk-3XKESW5E.js → chunk-SF2ZIRD6.js} +2 -2
  55. package/dist/{chunk-TE6LH6J2.js → chunk-SFBYQMZM.js} +3 -3
  56. package/dist/{chunk-RZPOZPZU.js → chunk-SU6SGWXM.js} +3 -3
  57. package/dist/{chunk-6L3DKWRY.js → chunk-T2MOJF76.js} +2 -2
  58. package/dist/{chunk-SKM35Y4Q.js → chunk-TS5XLBZR.js} +3 -3
  59. package/dist/{chunk-HFUAFR6B.js → chunk-TWPK7KUJ.js} +3 -3
  60. package/dist/{chunk-6M2I3DKF.js → chunk-WK7ULBTP.js} +2 -2
  61. package/dist/{chunk-IF6WNGAK.js → chunk-WUHEP3HH.js} +2 -2
  62. package/dist/{chunk-NQSO4UAH.js → chunk-WYUAEZSC.js} +3 -3
  63. package/dist/{chunk-Y6VZQGGH.js → chunk-YGK2HMLR.js} +4 -4
  64. package/dist/{chunk-TWS3S62A.js → chunk-ZBYFMI6D.js} +223 -119
  65. package/dist/chunk-ZBYFMI6D.js.map +1 -0
  66. package/dist/{chunk-N5PLUFH2.js → chunk-ZFG5EBI3.js} +4 -4
  67. package/dist/{chunk-KFRPNHWR.js → chunk-ZHDSUZQU.js} +3 -3
  68. package/dist/{chunk-C25JXSOR.js → chunk-ZNWSG7XC.js} +5 -5
  69. package/dist/classified/index.js +3 -3
  70. package/dist/{classified-marker-EOOSMWFC.js → classified-marker-LE54HWSX.js} +3 -3
  71. package/dist/{collection-facade-TTRF5NFJ.js → collection-facade-DO2AABZT.js} +8 -8
  72. package/dist/consent/index.js +4 -4
  73. package/dist/cover/index.js +2 -2
  74. package/dist/custody/index.js +6 -6
  75. package/dist/{dead-filter-6DYY7S64.js → dead-filter-V3LVWYEJ.js} +2 -2
  76. package/dist/debug/index.js +29 -0
  77. package/dist/debug/index.js.map +1 -0
  78. package/dist/{delegation-ONOZVPIP.js → delegation-JDUMAF6L.js} +4 -4
  79. package/dist/derivations/index.js +3 -3
  80. package/dist/{derive-IGGVSUPH.js → derive-ZPGVLE2Q.js} +4 -4
  81. package/dist/directory/index.js +5 -5
  82. package/dist/{dispatch-RPTLK7LJ.js → dispatch-6TV3DGO6.js} +5 -5
  83. package/dist/{dispatch-7T45NN7C.js → dispatch-W7NWQ637.js} +9 -9
  84. package/dist/{enclave-CLJVSDFG.js → enclave-YFCLPIDR.js} +4 -4
  85. package/dist/{executor-XZYM4KHT.js → executor-FPHKWDWT.js} +8 -8
  86. package/dist/{export-accessible-24XCCD3A.js → export-accessible-EKM3HGB2.js} +7 -7
  87. package/dist/{extract-partition-H2TPEEOF.js → extract-partition-LS4ET5A6.js} +10 -10
  88. package/dist/{fanout-sidecar-TV7CXAJ6.js → fanout-sidecar-273RDMYS.js} +4 -4
  89. package/dist/forget/index.js +4 -4
  90. package/dist/history/index.js +6 -6
  91. package/dist/i18n/index.js +6 -6
  92. package/dist/index.d.ts +7 -7
  93. package/dist/index.js +148 -96
  94. package/dist/index.js.map +1 -1
  95. package/dist/introspection/index.js +5 -5
  96. package/dist/{issue-55HJE7JF.js → issue-LIA7FXBJ.js} +6 -6
  97. package/dist/kernel/best-effort-revert.d.ts +9 -1
  98. package/dist/kernel/collection.d.ts +89 -2
  99. package/dist/kernel/debug.d.ts +11 -0
  100. package/dist/kernel/noydb.d.ts +3 -3
  101. package/dist/kernel/prepared-write.d.ts +70 -0
  102. package/dist/kernel/sync-policy.d.ts +75 -3
  103. package/dist/kernel/types.d.ts +27 -8
  104. package/dist/{ledger-XY6NP3J2.js → ledger-XE7JF2I2.js} +6 -6
  105. package/dist/liberate-WZ3RHVKW.js +24 -0
  106. package/dist/{link-set-POQB7BU5.js → link-set-CGYC3OH5.js} +5 -5
  107. package/dist/materialized-views/index.js +13 -13
  108. package/dist/{noydb-FHZ4ZDBP.js → noydb-ZLPVCDES.js} +30 -31
  109. package/dist/periods/index.js +8 -8
  110. package/dist/pod/index.js +6 -6
  111. package/dist/policy/index.js +3 -3
  112. package/dist/port/with/strategies.d.ts +1 -1
  113. package/dist/portability/index.js +6 -6
  114. package/dist/{post-register-URQANI3B.js → post-register-LY35EDTJ.js} +4 -4
  115. package/dist/{register-5W6CG4RM.js → register-6RIBIT3I.js} +6 -6
  116. package/dist/{registry-UJFP3NWF.js → registry-MUSL4AW6.js} +4 -4
  117. package/dist/{registry-MCSGBZXI.js → registry-RON4WHAP.js} +4 -4
  118. package/dist/{request-withdrawal-IWYDM4SO.js → request-withdrawal-FT3ORAWN.js} +9 -9
  119. package/dist/{reveal-BXZGWIOP.js → reveal-T34ADTPY.js} +3 -3
  120. package/dist/{revoke-TINYPHYY.js → revoke-HC7WG3HE.js} +6 -6
  121. package/dist/sealed-record/index.js +6 -6
  122. package/dist/search/index.js +1 -1
  123. package/dist/{seed-F7YYQTRC.js → seed-JOV54PB3.js} +6 -6
  124. package/dist/seed-JOV54PB3.js.map +1 -0
  125. package/dist/sequence/index.js +4 -4
  126. package/dist/session/index.js +3 -3
  127. package/dist/{signer-WMZKCNKC.js → signer-CTWOH6KT.js} +5 -5
  128. package/dist/snapshots/index.js +5 -5
  129. package/dist/{stale-JOE7GBAE.js → stale-T3V7XEOB.js} +5 -5
  130. package/dist/{storage-B3WBKXKT.js → storage-LLNLPWWB.js} +5 -5
  131. package/dist/{store-coordination-provider-5LX2UFU2.js → store-coordination-provider-AHGFEMFA.js} +3 -3
  132. package/dist/sync/index.js +9 -10
  133. package/dist/sync/index.js.map +1 -1
  134. package/dist/team/index.js +8 -30
  135. package/dist/tiers/index.js +4 -4
  136. package/dist/transactions/index.js +1 -1
  137. package/dist/{walk-6OHAWGBS.js → walk-G3NFEP5L.js} +6 -6
  138. package/dist/with-commit/tx/atomic-eligibility.d.ts +47 -0
  139. package/dist/with-commit/tx/transaction.d.ts +22 -9
  140. package/dist/with-party/broker/seed.d.ts +1 -1
  141. package/dist/with-party/team/index.d.ts +0 -5
  142. package/dist/{with-party/team/sync-active.d.ts → with-sync/active.d.ts} +1 -1
  143. package/dist/{with-party/team/sync-credentials.d.ts → with-sync/credentials.d.ts} +3 -3
  144. package/dist/{with-party/team/sync.d.ts → with-sync/engine.d.ts} +5 -5
  145. package/dist/{with-party/sync → with-sync}/index.d.ts +3 -3
  146. package/dist/{with-party/team/sync-period-scope.d.ts → with-sync/period-scope.d.ts} +2 -2
  147. package/dist/{with-party/team → with-sync}/presence.d.ts +2 -2
  148. package/dist/{with-party/team/sync-strategy.d.ts → with-sync/strategy.d.ts} +6 -6
  149. package/dist/{with-party/team/sync-transaction.d.ts → with-sync/transaction.d.ts} +3 -3
  150. package/dist/{withdraw-accessible-DEUCOO4F.js → withdraw-accessible-ANSVG6XG.js} +8 -8
  151. package/package.json +8 -4
  152. package/dist/chunk-BQ6DHN4I.js.map +0 -1
  153. package/dist/chunk-BXHMZ2XW.js.map +0 -1
  154. package/dist/chunk-EP5L47XV.js +0 -22
  155. package/dist/chunk-EP5L47XV.js.map +0 -1
  156. package/dist/chunk-EZNTORXE.js.map +0 -1
  157. package/dist/chunk-GZACYEOB.js.map +0 -1
  158. package/dist/chunk-MTJLOC3Y.js.map +0 -1
  159. package/dist/chunk-SHYIA73K.js +0 -99
  160. package/dist/chunk-SHYIA73K.js.map +0 -1
  161. package/dist/chunk-TWS3S62A.js.map +0 -1
  162. package/dist/chunk-Y6B6HVKC.js.map +0 -1
  163. package/dist/liberate-LXOJ2EMB.js +0 -24
  164. package/dist/seed-F7YYQTRC.js.map +0 -1
  165. /package/dist/{api-3NKVNZPM.js.map → api-SI2IVBQO.js.map} +0 -0
  166. /package/dist/{backup-PTSVXDDW.js.map → backup-X7F3TCFV.js.map} +0 -0
  167. /package/dist/{chunk-WZ3NCMK6.js.map → chunk-2BET5QTS.js.map} +0 -0
  168. /package/dist/{chunk-BYFXLDVV.js.map → chunk-3ECU57YH.js.map} +0 -0
  169. /package/dist/{chunk-ZWBKDKXC.js.map → chunk-467SWYT5.js.map} +0 -0
  170. /package/dist/{chunk-XIDQKFZF.js.map → chunk-5UQ7Y6SQ.js.map} +0 -0
  171. /package/dist/{chunk-IMRB2C4O.js.map → chunk-7H3WWH6J.js.map} +0 -0
  172. /package/dist/{chunk-OLIWCCFM.js.map → chunk-CLE3TMIS.js.map} +0 -0
  173. /package/dist/{chunk-ZFUFAHZ3.js.map → chunk-DAFBJS4Y.js.map} +0 -0
  174. /package/dist/{chunk-ISRKW4YN.js.map → chunk-DQZXPGGZ.js.map} +0 -0
  175. /package/dist/{chunk-FMNU7IUG.js.map → chunk-DTFA5DO4.js.map} +0 -0
  176. /package/dist/{chunk-VH6SOCXH.js.map → chunk-EFJAAFBW.js.map} +0 -0
  177. /package/dist/{chunk-TIVK6PRK.js.map → chunk-ERGECZEI.js.map} +0 -0
  178. /package/dist/{chunk-KW42W6SV.js.map → chunk-HLKXPJ4V.js.map} +0 -0
  179. /package/dist/{chunk-MANUDU7I.js.map → chunk-HZZP2ZIG.js.map} +0 -0
  180. /package/dist/{chunk-DZAF24PG.js.map → chunk-IFOH7RBI.js.map} +0 -0
  181. /package/dist/{chunk-FRMW23UK.js.map → chunk-IVYQAVWO.js.map} +0 -0
  182. /package/dist/{chunk-SGQ4N5FS.js.map → chunk-JEI6JJNI.js.map} +0 -0
  183. /package/dist/{chunk-BN4HRYAZ.js.map → chunk-JQ2AX4T5.js.map} +0 -0
  184. /package/dist/{chunk-OBPVWOSQ.js.map → chunk-KD4HGBJV.js.map} +0 -0
  185. /package/dist/{chunk-QADFHRQM.js.map → chunk-KYRDJI5O.js.map} +0 -0
  186. /package/dist/{chunk-JTR75MKH.js.map → chunk-LLYIMSQQ.js.map} +0 -0
  187. /package/dist/{chunk-GP3UWP22.js.map → chunk-LRRX57UA.js.map} +0 -0
  188. /package/dist/{chunk-OLSARBZU.js.map → chunk-LXRTP3AQ.js.map} +0 -0
  189. /package/dist/{chunk-EBKCYQ2D.js.map → chunk-NBXFCQX4.js.map} +0 -0
  190. /package/dist/{chunk-NEX7JCMO.js.map → chunk-OWHP3H5C.js.map} +0 -0
  191. /package/dist/{chunk-WO4T4OD5.js.map → chunk-P4JO3H6R.js.map} +0 -0
  192. /package/dist/{chunk-CCDP6EPB.js.map → chunk-PWPYO73B.js.map} +0 -0
  193. /package/dist/{chunk-56IIVAEO.js.map → chunk-Q2SEJMP2.js.map} +0 -0
  194. /package/dist/{chunk-JIDLU57U.js.map → chunk-Q36YXK77.js.map} +0 -0
  195. /package/dist/{chunk-KPXM4WO6.js.map → chunk-Q5YJCVJY.js.map} +0 -0
  196. /package/dist/{chunk-JYV4JJV2.js.map → chunk-QGIBI6GL.js.map} +0 -0
  197. /package/dist/{chunk-DGBIHDVK.js.map → chunk-RBTVFPHF.js.map} +0 -0
  198. /package/dist/{chunk-6R6Q3MRN.js.map → chunk-RQ4ZI4ZI.js.map} +0 -0
  199. /package/dist/{chunk-FO6RNKKW.js.map → chunk-S7GIXBXV.js.map} +0 -0
  200. /package/dist/{chunk-3XKESW5E.js.map → chunk-SF2ZIRD6.js.map} +0 -0
  201. /package/dist/{chunk-TE6LH6J2.js.map → chunk-SFBYQMZM.js.map} +0 -0
  202. /package/dist/{chunk-RZPOZPZU.js.map → chunk-SU6SGWXM.js.map} +0 -0
  203. /package/dist/{chunk-6L3DKWRY.js.map → chunk-T2MOJF76.js.map} +0 -0
  204. /package/dist/{chunk-SKM35Y4Q.js.map → chunk-TS5XLBZR.js.map} +0 -0
  205. /package/dist/{chunk-HFUAFR6B.js.map → chunk-TWPK7KUJ.js.map} +0 -0
  206. /package/dist/{chunk-6M2I3DKF.js.map → chunk-WK7ULBTP.js.map} +0 -0
  207. /package/dist/{chunk-IF6WNGAK.js.map → chunk-WUHEP3HH.js.map} +0 -0
  208. /package/dist/{chunk-NQSO4UAH.js.map → chunk-WYUAEZSC.js.map} +0 -0
  209. /package/dist/{chunk-Y6VZQGGH.js.map → chunk-YGK2HMLR.js.map} +0 -0
  210. /package/dist/{chunk-N5PLUFH2.js.map → chunk-ZFG5EBI3.js.map} +0 -0
  211. /package/dist/{chunk-KFRPNHWR.js.map → chunk-ZHDSUZQU.js.map} +0 -0
  212. /package/dist/{chunk-C25JXSOR.js.map → chunk-ZNWSG7XC.js.map} +0 -0
  213. /package/dist/{classified-marker-EOOSMWFC.js.map → classified-marker-LE54HWSX.js.map} +0 -0
  214. /package/dist/{collection-facade-TTRF5NFJ.js.map → collection-facade-DO2AABZT.js.map} +0 -0
  215. /package/dist/{dead-filter-6DYY7S64.js.map → dead-filter-V3LVWYEJ.js.map} +0 -0
  216. /package/dist/{delegation-ONOZVPIP.js.map → delegation-JDUMAF6L.js.map} +0 -0
  217. /package/dist/{derive-IGGVSUPH.js.map → derive-ZPGVLE2Q.js.map} +0 -0
  218. /package/dist/{dispatch-RPTLK7LJ.js.map → dispatch-6TV3DGO6.js.map} +0 -0
  219. /package/dist/{dispatch-7T45NN7C.js.map → dispatch-W7NWQ637.js.map} +0 -0
  220. /package/dist/{enclave-CLJVSDFG.js.map → enclave-YFCLPIDR.js.map} +0 -0
  221. /package/dist/{executor-XZYM4KHT.js.map → executor-FPHKWDWT.js.map} +0 -0
  222. /package/dist/{export-accessible-24XCCD3A.js.map → export-accessible-EKM3HGB2.js.map} +0 -0
  223. /package/dist/{extract-partition-H2TPEEOF.js.map → extract-partition-LS4ET5A6.js.map} +0 -0
  224. /package/dist/{fanout-sidecar-TV7CXAJ6.js.map → fanout-sidecar-273RDMYS.js.map} +0 -0
  225. /package/dist/{issue-55HJE7JF.js.map → issue-LIA7FXBJ.js.map} +0 -0
  226. /package/dist/{ledger-XY6NP3J2.js.map → ledger-XE7JF2I2.js.map} +0 -0
  227. /package/dist/{liberate-LXOJ2EMB.js.map → liberate-WZ3RHVKW.js.map} +0 -0
  228. /package/dist/{link-set-POQB7BU5.js.map → link-set-CGYC3OH5.js.map} +0 -0
  229. /package/dist/{noydb-FHZ4ZDBP.js.map → noydb-ZLPVCDES.js.map} +0 -0
  230. /package/dist/{post-register-URQANI3B.js.map → post-register-LY35EDTJ.js.map} +0 -0
  231. /package/dist/{register-5W6CG4RM.js.map → register-6RIBIT3I.js.map} +0 -0
  232. /package/dist/{registry-MCSGBZXI.js.map → registry-MUSL4AW6.js.map} +0 -0
  233. /package/dist/{registry-UJFP3NWF.js.map → registry-RON4WHAP.js.map} +0 -0
  234. /package/dist/{request-withdrawal-IWYDM4SO.js.map → request-withdrawal-FT3ORAWN.js.map} +0 -0
  235. /package/dist/{reveal-BXZGWIOP.js.map → reveal-T34ADTPY.js.map} +0 -0
  236. /package/dist/{revoke-TINYPHYY.js.map → revoke-HC7WG3HE.js.map} +0 -0
  237. /package/dist/{signer-WMZKCNKC.js.map → signer-CTWOH6KT.js.map} +0 -0
  238. /package/dist/{stale-JOE7GBAE.js.map → stale-T3V7XEOB.js.map} +0 -0
  239. /package/dist/{storage-B3WBKXKT.js.map → storage-LLNLPWWB.js.map} +0 -0
  240. /package/dist/{store-coordination-provider-5LX2UFU2.js.map → store-coordination-provider-AHGFEMFA.js.map} +0 -0
  241. /package/dist/{walk-6OHAWGBS.js.map → walk-G3NFEP5L.js.map} +0 -0
  242. /package/dist/{with-party → with-sync}/tab-coordination.d.ts +0 -0
  243. /package/dist/{with-party → with-sync}/tab-write-relay.d.ts +0 -0
  244. /package/dist/{withdraw-accessible-DEUCOO4F.js.map → withdraw-accessible-ANSVG6XG.js.map} +0 -0
@@ -8,6 +8,35 @@ var POD_STORE_POLICY = {
8
8
  pull: { mode: "interval", intervalMs: 6e4 }
9
9
  };
10
10
  var BUNDLE_STORE_POLICY = POD_STORE_POLICY;
11
+ function validatePullPolicy(pull) {
12
+ if (pull.mode !== "phased") {
13
+ if (pull.sequence !== void 0) {
14
+ throw new Error(
15
+ `syncPolicy.pull.sequence is only meaningful with mode: 'phased' (got '${pull.mode}'). Set mode: 'phased' to run the sequence, or drop the field.`
16
+ );
17
+ }
18
+ return;
19
+ }
20
+ const { sequence } = pull;
21
+ if (!sequence || sequence.length === 0) {
22
+ throw new Error(
23
+ `syncPolicy.pull.mode: 'phased' requires a non-empty 'sequence' of collection names.`
24
+ );
25
+ }
26
+ for (const name of sequence) {
27
+ if (typeof name !== "string" || name.length === 0) {
28
+ throw new Error(
29
+ `syncPolicy.pull.sequence entries must be non-empty collection names (got ${JSON.stringify(name)}).`
30
+ );
31
+ }
32
+ }
33
+ const duplicate = sequence.find((name, i) => sequence.indexOf(name) !== i);
34
+ if (duplicate !== void 0) {
35
+ throw new Error(
36
+ `syncPolicy.pull.sequence lists "${duplicate}" more than once. Each collection is pulled whole, so a repeat does no additional work.`
37
+ );
38
+ }
39
+ }
11
40
  var SyncScheduler = class {
12
41
  policy;
13
42
  callbacks;
@@ -17,6 +46,10 @@ var SyncScheduler = class {
17
46
  _lastError = null;
18
47
  _lastPushTime = 0;
19
48
  // monotonic ms for minIntervalMs enforcement
49
+ // Phased-pull progress. Empty for every other mode, so non-adopters carry
50
+ // an empty Map and a null — no per-read cost, nothing to interpret.
51
+ _readiness = /* @__PURE__ */ new Map();
52
+ _phase = null;
20
53
  // Timers
21
54
  debounceTimer = null;
22
55
  pushIntervalTimer = null;
@@ -27,6 +60,7 @@ var SyncScheduler = class {
27
60
  boundOnPageHide = null;
28
61
  started = false;
29
62
  constructor(policy, callbacks) {
63
+ validatePullPolicy(policy.pull);
30
64
  this.policy = policy;
31
65
  this.callbacks = callbacks;
32
66
  if (this.shouldRegisterUnload()) {
@@ -42,7 +76,10 @@ var SyncScheduler = class {
42
76
  lastPushAt: this._lastPushAt,
43
77
  lastPullAt: this._lastPullAt,
44
78
  lastError: this._lastError,
45
- pendingWrites: this.callbacks.getDirtyCount()
79
+ pendingWrites: this.callbacks.getDirtyCount(),
80
+ // Copied, not aliased — a status snapshot must not mutate under its reader.
81
+ readiness: new Map(this._readiness),
82
+ phase: this._phase
46
83
  };
47
84
  }
48
85
  /** Start the scheduler — registers timers, event listeners. */
@@ -54,10 +91,13 @@ var SyncScheduler = class {
54
91
  void this.executePush();
55
92
  }, this.policy.push.intervalMs);
56
93
  }
57
- if (this.policy.pull.mode === "interval" && this.policy.pull.intervalMs) {
58
- this.pullIntervalTimer = setInterval(() => {
59
- void this.executePull();
60
- }, this.policy.pull.intervalMs);
94
+ if (this.policy.pull.mode === "interval") {
95
+ this.startPullInterval();
96
+ }
97
+ if (this.policy.pull.mode === "phased") {
98
+ const sequence = this.policy.pull.sequence ?? [];
99
+ for (const collection of sequence) this._readiness.set(collection, "cold");
100
+ void this.runSequence(sequence);
61
101
  }
62
102
  if (this.policy.pull.mode === "on-focus" && typeof document !== "undefined") {
63
103
  document.addEventListener("visibilitychange", this.handleFocusPull);
@@ -78,6 +118,10 @@ var SyncScheduler = class {
78
118
  stop() {
79
119
  if (!this.started) return;
80
120
  this.started = false;
121
+ for (const [collection, state] of this._readiness) {
122
+ if (state === "pulling") this._readiness.set(collection, "cold");
123
+ }
124
+ this._phase = null;
81
125
  if (this.debounceTimer) {
82
126
  clearTimeout(this.debounceTimer);
83
127
  this.debounceTimer = null;
@@ -126,6 +170,37 @@ var SyncScheduler = class {
126
170
  await this.executePull();
127
171
  }
128
172
  // ─── Internal ─────────────────────────────────────────────────────
173
+ /**
174
+ * Arm the steady-state pull timer, if the policy specifies a cadence.
175
+ * Shared by `'interval'` mode and by `'phased'` once its sequence drains.
176
+ */
177
+ startPullInterval() {
178
+ if (this.pullIntervalTimer || !this.policy.pull.intervalMs) return;
179
+ this.pullIntervalTimer = setInterval(() => {
180
+ void this.executePull();
181
+ }, this.policy.pull.intervalMs);
182
+ }
183
+ /**
184
+ * Pull each collection in turn, then hand over to steady state.
185
+ *
186
+ * Strictly sequential — running phases concurrently would defeat the
187
+ * prioritisation that is the entire point of a sequence. Each phase is an
188
+ * ordinary scoped pull, so a phase that reports errors does not abort the
189
+ * ones behind it; `executePull` records the failure and the walk continues.
190
+ * `started` is re-checked between phases so `stop()` cuts a sequence short
191
+ * instead of letting it run on against a closed vault.
192
+ */
193
+ async runSequence(sequence) {
194
+ for (const [i, collection] of sequence.entries()) {
195
+ if (!this.started) return;
196
+ this._readiness.set(collection, "pulling");
197
+ this._phase = { index: i + 1, total: sequence.length };
198
+ const outcome = await this.executePull([collection]);
199
+ this._readiness.set(collection, outcome === "complete" ? "live" : "cold");
200
+ }
201
+ this._phase = null;
202
+ if (this.started) this.startPullInterval();
203
+ }
129
204
  async executePush() {
130
205
  if (this._state === "pushing") return;
131
206
  const minInterval = this.policy.push.minIntervalMs ?? 0;
@@ -154,18 +229,20 @@ var SyncScheduler = class {
154
229
  this._state = "error";
155
230
  }
156
231
  }
157
- async executePull() {
158
- if (this._state === "pulling") return;
232
+ async executePull(collections) {
233
+ if (this._state === "pulling") return "incomplete";
159
234
  const previousState = this._state;
160
235
  this._state = "pulling";
161
236
  try {
162
- await this.callbacks.pull();
237
+ const outcome = await this.callbacks.pull(collections);
163
238
  this._lastPullAt = (/* @__PURE__ */ new Date()).toISOString();
164
239
  this._lastError = null;
165
240
  this._state = previousState === "pending" ? "pending" : "idle";
241
+ return outcome ?? "complete";
166
242
  } catch (err) {
167
243
  this._lastError = err instanceof Error ? err : new Error(String(err));
168
244
  this._state = "error";
245
+ return "incomplete";
169
246
  }
170
247
  }
171
248
  resetDebounce() {
@@ -210,10 +287,29 @@ var SyncScheduler = class {
210
287
  }
211
288
  };
212
289
 
290
+ // src/with-sync/strategy.ts
291
+ function notEnabled(op) {
292
+ return new Error(
293
+ `${op} requires the sync strategy. Import \`{ withSync }\` from "@noy-db/hub/sync" and pass it to \`createNoydb({ syncStrategy: withSync() })\`.`
294
+ );
295
+ }
296
+ var NO_SYNC = {
297
+ buildSyncEngine() {
298
+ throw notEnabled("SyncEngine");
299
+ },
300
+ buildSyncTransaction() {
301
+ throw notEnabled("SyncTransaction");
302
+ },
303
+ buildPresence() {
304
+ throw notEnabled("collection.presence()");
305
+ }
306
+ };
307
+
213
308
  export {
214
309
  INDEXED_STORE_POLICY,
215
310
  POD_STORE_POLICY,
216
311
  BUNDLE_STORE_POLICY,
217
- SyncScheduler
312
+ SyncScheduler,
313
+ NO_SYNC
218
314
  };
219
- //# sourceMappingURL=chunk-MTJLOC3Y.js.map
315
+ //# sourceMappingURL=chunk-55LKVALY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kernel/sync-policy.ts","../src/with-sync/strategy.ts"],"sourcesContent":["/**\n * Sync scheduling policy.\n *\n * ## What it controls\n *\n * A {@link SyncPolicy} has two halves:\n * - **push** ({@link PushPolicy}) — when dirty local writes are sent to the remote.\n * - **pull** ({@link PullPolicy}) — when the remote is polled for new data.\n *\n * ## Choosing a policy\n *\n * The right policy depends on the backend's operational characteristics:\n *\n * | Backend type | Recommended policy |\n * |---|---|\n * | Per-record (DynamoDB, S3, IDB) | {@link INDEXED_STORE_POLICY} — `on-change` push, `manual` pull |\n * | Bundle (Drive, WebDAV, Git) | {@link POD_STORE_POLICY} — `debounce` push, `interval` pull |\n *\n * Consumers can override via `createNoydb({ syncPolicy: { ... } })`:\n *\n * ```ts\n * const db = await createNoydb({\n * store: toFile({ dir: './data' }),\n * syncPolicy: {\n * push: { mode: 'debounce', debounceMs: 5_000 },\n * pull: { mode: 'on-focus' },\n * },\n * })\n * ```\n *\n * ## Scheduler lifecycle\n *\n * {@link SyncScheduler} owns all timers, debounce logic, and browser lifecycle\n * hooks (`visibilitychange`, `pagehide`, `beforeExit`). Call `scheduler.start()`\n * after opening a vault and `scheduler.stop()` when closing it. The scheduler\n * delegates actual push/pull work to {@link SyncSchedulerCallbacks} provided\n * by the {@link SyncEngine}.\n *\n * @module\n */\n\n// ─── Policy types ───────────────────────────────────────────────────────\n\n/**\n * When push operations are triggered automatically.\n *\n * - `'manual'` — only on explicit `sync.push()` calls.\n * - `'on-change'` — immediately after every local write (respecting `minIntervalMs`).\n * - `'debounce'` — after `debounceMs` of inactivity following a write.\n * - `'interval'` — on a fixed timer regardless of writes.\n */\nexport type PushMode = 'manual' | 'on-change' | 'debounce' | 'interval'\n\n/**\n * When pull operations are triggered automatically.\n *\n * - `'manual'` — only on explicit `sync.pull()` calls.\n * - `'interval'` — on a fixed `intervalMs` timer.\n * - `'on-focus'` — when the browser tab regains visibility.\n * - `'phased'` — pull the collections named in `sequence`, in order, one at a\n * time, then settle into steady state. For thin clients that need their\n * navigation-critical collections before bulk history.\n */\nexport type PullMode = 'manual' | 'interval' | 'on-focus' | 'phased'\n\n/**\n * Push half of a sync policy. Controls the trigger mode and timing guards\n * for outbound sync operations.\n */\nexport interface PushPolicy {\n /** Push trigger mode. */\n readonly mode: PushMode\n /** Debounce delay in ms. Only used when `mode: 'debounce'`. Default: 30_000. */\n readonly debounceMs?: number\n /** Interval in ms between automatic pushes. Used by `'interval'` and as floor for `'debounce'`. */\n readonly intervalMs?: number\n /**\n * Hard floor between pushes regardless of mode. Prevents burst writes\n * from hammering the remote. Default: 0 (no floor).\n */\n readonly minIntervalMs?: number\n /**\n * Force a push on page unload (`pagehide` / `visibilitychange → hidden`)\n * in browsers, `beforeExit` in Node. Default: true for non-manual modes.\n */\n readonly onUnload?: boolean\n}\n\n/**\n * Pull half of a sync policy. Controls when and how often inbound sync\n * operations are triggered.\n */\nexport interface PullPolicy {\n /** Pull trigger mode. */\n readonly mode: PullMode\n /**\n * Interval in ms between automatic pulls. Used by `'interval'` mode. Default: 60_000.\n * Under `'phased'` it is the steady-state cadence adopted *after* the sequence\n * completes; omit it to go idle instead.\n */\n readonly intervalMs?: number\n /**\n * Collection names to pull in order, one at a time. Required when\n * `mode: 'phased'` and rejected otherwise. Entries must be non-empty and\n * unique — without period narrowing a repeated collection can only be a\n * mistake, so it is rejected rather than silently merged.\n *\n * Period-scoped phases (`collection@period`) are deferred to `partitions`;\n * use `db.pull(vault, { periods })` explicitly meanwhile.\n */\n readonly sequence?: readonly string[]\n}\n\n/**\n * Combined push + pull sync scheduling policy for a vault.\n *\n * Pass via `createNoydb({ syncPolicy })` to override the default policy\n * derived from the active store type. Pre-built defaults are available\n * as `INDEXED_STORE_POLICY` and `POD_STORE_POLICY`.\n */\nexport interface SyncPolicy {\n readonly push: PushPolicy\n readonly pull: PullPolicy\n}\n\n// ─── Default policies by store category ─────────────────────────────────\n\n/** Default for per-record stores (DynamoDB, S3, file, IDB). */\nexport const INDEXED_STORE_POLICY: SyncPolicy = {\n push: { mode: 'on-change', minIntervalMs: 0, onUnload: true },\n pull: { mode: 'manual' },\n}\n\n/** Default for bundle stores (Drive, WebDAV, Git). */\nexport const POD_STORE_POLICY: SyncPolicy = {\n push: { mode: 'debounce', debounceMs: 30_000, minIntervalMs: 120_000, onUnload: true },\n pull: { mode: 'interval', intervalMs: 60_000 },\n}\n\n/** @deprecated Use `POD_STORE_POLICY`. */\nexport const BUNDLE_STORE_POLICY = POD_STORE_POLICY\n\n// ─── Sync scheduler ─────────────────────────────────────────────────────\n\n/**\n * Current operational state of the `SyncScheduler`.\n *\n * - `'idle'` — no pending or active sync operations.\n * - `'pending'` — local writes are queued, waiting for debounce/interval to fire.\n * - `'pushing'` — push in progress.\n * - `'pulling'` — pull in progress.\n * - `'error'` — last sync operation failed; `lastError` holds the cause.\n */\nexport type SyncSchedulerState = 'idle' | 'pending' | 'pushing' | 'pulling' | 'error'\n\n/**\n * How much of a collection a caller may rely on, under a `'phased'` pull.\n *\n * - `'cold'` — not pulled yet, or its phase did not complete cleanly. A miss\n * from `get()` proves nothing.\n * - `'pulling'` — its phase is in flight. Never terminal: a phase always ends\n * in `'live'` or back in `'cold'`, because a stuck `'pulling'` would leave a\n * permanent skeleton in the UI.\n * - `'live'` — its phase completed cleanly, so a miss is a real absence.\n */\nexport type ReadinessState = 'cold' | 'pulling' | 'live'\n\n/**\n * What a scheduler-initiated pull achieved, as reported by the callback.\n *\n * `'incomplete'` covers both a pull that reported errors (`PullResult.errors`\n * accumulates without throwing) and one that was skipped — e.g. role-gated on a\n * backup target. Either way nothing may be claimed about completeness.\n */\nexport type PullPhaseOutcome = 'complete' | 'incomplete'\n\n/**\n * Snapshot of the sync scheduler's state, returned by `SyncScheduler.status`.\n * Safe to expose in a reactive UI status indicator.\n */\nexport interface SyncSchedulerStatus {\n readonly state: SyncSchedulerState\n readonly lastPushAt: string | null\n readonly lastPullAt: string | null\n readonly lastError: Error | null\n readonly pendingWrites: number\n /**\n * Per-collection readiness. Empty unless `pull.mode === 'phased'`.\n *\n * A collection the sequence never names is **absent** from the map, and\n * `undefined` means *\"no claim made\"* — never a reason to gate a UI.\n */\n readonly readiness: ReadonlyMap<string, ReadinessState>\n /** 1-based position in the sequence, or `null` outside a phased run. */\n readonly phase: { readonly index: number; readonly total: number } | null\n}\n\n/**\n * Callbacks injected into `SyncScheduler` by the SyncEngine.\n *\n * The scheduler owns timers and lifecycle hooks; it delegates actual push/pull\n * work to these callbacks to stay decoupled from the sync implementation.\n */\nexport interface SyncSchedulerCallbacks {\n push(): Promise<void>\n /**\n * @param collections - Narrow the pull to these collections. Passed by a\n * `'phased'` sequence, one collection per phase; omitted for a whole-vault pull.\n * @returns Whether the pull may be treated as complete. Returning `void` reads\n * as `'complete'`, so callers with nothing to report need not opt in.\n */\n pull(collections?: readonly string[]): Promise<PullPhaseOutcome | void>\n getDirtyCount(): number\n}\n\n/**\n * Reject a policy that cannot mean anything, at construction rather than on\n * the first tick. Module-private: `SyncScheduler` is the choke point every\n * policy that can actually schedule must pass through — primary and per-target\n * alike — so validating here needs no new public surface and costs the kernel\n * floor nothing.\n */\nfunction validatePullPolicy(pull: PullPolicy): void {\n if (pull.mode !== 'phased') {\n if (pull.sequence !== undefined) {\n throw new Error(\n `syncPolicy.pull.sequence is only meaningful with mode: 'phased' (got '${pull.mode}'). ` +\n `Set mode: 'phased' to run the sequence, or drop the field.`,\n )\n }\n return\n }\n\n const { sequence } = pull\n if (!sequence || sequence.length === 0) {\n throw new Error(\n `syncPolicy.pull.mode: 'phased' requires a non-empty 'sequence' of collection names.`,\n )\n }\n for (const name of sequence) {\n if (typeof name !== 'string' || name.length === 0) {\n throw new Error(\n `syncPolicy.pull.sequence entries must be non-empty collection names (got ${JSON.stringify(name)}).`,\n )\n }\n }\n const duplicate = sequence.find((name, i) => sequence.indexOf(name) !== i)\n if (duplicate !== undefined) {\n throw new Error(\n `syncPolicy.pull.sequence lists \"${duplicate}\" more than once. ` +\n `Each collection is pulled whole, so a repeat does no additional work.`,\n )\n }\n}\n\n/**\n * Manages sync timing according to a `SyncPolicy`.\n *\n * The scheduler owns all timers and lifecycle hooks. It delegates actual\n * push/pull work to callbacks provided by the SyncEngine.\n */\nexport class SyncScheduler {\n private readonly policy: SyncPolicy\n private readonly callbacks: SyncSchedulerCallbacks\n\n private _state: SyncSchedulerState = 'idle'\n private _lastPushAt: string | null = null\n private _lastPullAt: string | null = null\n private _lastError: Error | null = null\n private _lastPushTime = 0 // monotonic ms for minIntervalMs enforcement\n\n // Phased-pull progress. Empty for every other mode, so non-adopters carry\n // an empty Map and a null — no per-read cost, nothing to interpret.\n private readonly _readiness = new Map<string, ReadinessState>()\n private _phase: { readonly index: number; readonly total: number } | null = null\n\n // Timers\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n private pushIntervalTimer: ReturnType<typeof setInterval> | null = null\n private pullIntervalTimer: ReturnType<typeof setInterval> | null = null\n\n // Bound handlers for cleanup\n private readonly boundOnVisibilityChange: (() => void) | null = null\n private readonly boundOnBeforeExit: (() => void) | null = null\n private readonly boundOnPageHide: (() => void) | null = null\n\n private started = false\n\n constructor(policy: SyncPolicy, callbacks: SyncSchedulerCallbacks) {\n validatePullPolicy(policy.pull)\n this.policy = policy\n this.callbacks = callbacks\n\n // Pre-bind handlers\n if (this.shouldRegisterUnload()) {\n this.boundOnVisibilityChange = this.handleVisibilityChange.bind(this)\n this.boundOnPageHide = this.handlePageHide.bind(this)\n this.boundOnBeforeExit = this.handleBeforeExit.bind(this)\n }\n }\n\n /** Current scheduler status snapshot. */\n get status(): SyncSchedulerStatus {\n return {\n state: this._state,\n lastPushAt: this._lastPushAt,\n lastPullAt: this._lastPullAt,\n lastError: this._lastError,\n pendingWrites: this.callbacks.getDirtyCount(),\n // Copied, not aliased — a status snapshot must not mutate under its reader.\n readiness: new Map(this._readiness),\n phase: this._phase,\n }\n }\n\n /** Start the scheduler — registers timers, event listeners. */\n start(): void {\n if (this.started) return\n this.started = true\n\n // Push: interval mode\n if (this.policy.push.mode === 'interval' && this.policy.push.intervalMs) {\n this.pushIntervalTimer = setInterval(() => {\n void this.executePush()\n }, this.policy.push.intervalMs)\n }\n\n // Pull: interval mode\n if (this.policy.pull.mode === 'interval') {\n this.startPullInterval()\n }\n\n // Pull: phased mode — walk the sequence in order, then settle into steady\n // state. Unawaited by design: start() is synchronous and the caller\n // (vault open) must not block on a bootstrap pull.\n if (this.policy.pull.mode === 'phased') {\n const sequence = this.policy.pull.sequence ?? []\n // Every named collection is 'cold' from the moment we start, so a reader\n // that races the first phase sees \"not ready\", never a missing entry.\n for (const collection of sequence) this._readiness.set(collection, 'cold')\n void this.runSequence(sequence)\n }\n\n // Pull: on-focus mode\n if (this.policy.pull.mode === 'on-focus' && typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', this.handleFocusPull)\n }\n\n // Unload hooks\n if (this.shouldRegisterUnload()) {\n if (typeof document !== 'undefined' && this.boundOnVisibilityChange) {\n document.addEventListener('visibilitychange', this.boundOnVisibilityChange)\n }\n if (typeof globalThis.addEventListener === 'function' && this.boundOnPageHide) {\n globalThis.addEventListener('pagehide', this.boundOnPageHide)\n }\n if (typeof process !== 'undefined' && this.boundOnBeforeExit) {\n process.on('beforeExit', this.boundOnBeforeExit)\n }\n }\n }\n\n /** Stop the scheduler — clears timers, removes event listeners. */\n stop(): void {\n if (!this.started) return\n this.started = false\n\n // A sequence cut mid-phase must not leave that collection 'pulling' —\n // a reader would show a skeleton that never resolves.\n for (const [collection, state] of this._readiness) {\n if (state === 'pulling') this._readiness.set(collection, 'cold')\n }\n this._phase = null\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer)\n this.debounceTimer = null\n }\n if (this.pushIntervalTimer) {\n clearInterval(this.pushIntervalTimer)\n this.pushIntervalTimer = null\n }\n if (this.pullIntervalTimer) {\n clearInterval(this.pullIntervalTimer)\n this.pullIntervalTimer = null\n }\n\n // Focus pull\n if (this.policy.pull.mode === 'on-focus' && typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', this.handleFocusPull)\n }\n\n // Unload hooks\n if (typeof document !== 'undefined' && this.boundOnVisibilityChange) {\n document.removeEventListener('visibilitychange', this.boundOnVisibilityChange)\n }\n if (typeof globalThis.removeEventListener === 'function' && this.boundOnPageHide) {\n globalThis.removeEventListener('pagehide', this.boundOnPageHide)\n }\n if (typeof process !== 'undefined' && this.boundOnBeforeExit) {\n process.removeListener('beforeExit', this.boundOnBeforeExit)\n }\n }\n\n /**\n * Notify the scheduler that a local write occurred.\n * For `on-change` mode: triggers immediate push (respecting minIntervalMs).\n * For `debounce` mode: resets the debounce timer.\n * For `manual` / `interval`: no-op.\n */\n notifyChange(): void {\n if (!this.started) return\n\n if (this.policy.push.mode === 'on-change') {\n void this.executePush()\n } else if (this.policy.push.mode === 'debounce') {\n this.resetDebounce()\n }\n }\n\n /** Force an immediate push, bypassing the scheduler. */\n async forcePush(): Promise<void> {\n await this.executePush()\n }\n\n /** Force an immediate pull, bypassing the scheduler. */\n async forcePull(): Promise<void> {\n await this.executePull()\n }\n\n // ─── Internal ─────────────────────────────────────────────────────\n\n /**\n * Arm the steady-state pull timer, if the policy specifies a cadence.\n * Shared by `'interval'` mode and by `'phased'` once its sequence drains.\n */\n private startPullInterval(): void {\n if (this.pullIntervalTimer || !this.policy.pull.intervalMs) return\n this.pullIntervalTimer = setInterval(() => {\n void this.executePull()\n }, this.policy.pull.intervalMs)\n }\n\n /**\n * Pull each collection in turn, then hand over to steady state.\n *\n * Strictly sequential — running phases concurrently would defeat the\n * prioritisation that is the entire point of a sequence. Each phase is an\n * ordinary scoped pull, so a phase that reports errors does not abort the\n * ones behind it; `executePull` records the failure and the walk continues.\n * `started` is re-checked between phases so `stop()` cuts a sequence short\n * instead of letting it run on against a closed vault.\n */\n private async runSequence(sequence: readonly string[]): Promise<void> {\n for (const [i, collection] of sequence.entries()) {\n if (!this.started) return\n this._readiness.set(collection, 'pulling')\n this._phase = { index: i + 1, total: sequence.length }\n\n const outcome = await this.executePull([collection])\n\n // 'live' only on a clean phase. Anything else — reported errors, a\n // role-gated skip, a throw — goes back to 'cold', because 'live' is a\n // promise that a miss from get() is a real absence.\n this._readiness.set(collection, outcome === 'complete' ? 'live' : 'cold')\n }\n this._phase = null\n if (this.started) this.startPullInterval()\n }\n\n private async executePush(): Promise<void> {\n if (this._state === 'pushing') return // already in progress\n\n // minIntervalMs enforcement\n const minInterval = this.policy.push.minIntervalMs ?? 0\n if (minInterval > 0) {\n const elapsed = Date.now() - this._lastPushTime\n if (elapsed < minInterval) {\n // Schedule for later if debounce mode\n if (this.policy.push.mode === 'debounce') {\n this.scheduleDebounce(minInterval - elapsed)\n }\n return\n }\n }\n\n // Nothing to push\n if (this.callbacks.getDirtyCount() === 0) {\n this._state = 'idle'\n return\n }\n\n this._state = 'pushing'\n try {\n await this.callbacks.push()\n this._lastPushAt = new Date().toISOString()\n this._lastPushTime = Date.now()\n this._lastError = null\n this._state = this.callbacks.getDirtyCount() > 0 ? 'pending' : 'idle'\n } catch (err) {\n this._lastError = err instanceof Error ? err : new Error(String(err))\n this._state = 'error'\n }\n }\n\n private async executePull(collections?: readonly string[]): Promise<PullPhaseOutcome> {\n if (this._state === 'pulling') return 'incomplete'\n\n const previousState = this._state\n this._state = 'pulling'\n try {\n const outcome = await this.callbacks.pull(collections)\n this._lastPullAt = new Date().toISOString()\n this._lastError = null\n this._state = previousState === 'pending' ? 'pending' : 'idle'\n return outcome ?? 'complete'\n } catch (err) {\n this._lastError = err instanceof Error ? err : new Error(String(err))\n this._state = 'error'\n return 'incomplete'\n }\n }\n\n private resetDebounce(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n const ms = this.policy.push.debounceMs ?? 30_000\n this._state = 'pending'\n this.scheduleDebounce(ms)\n }\n\n private scheduleDebounce(ms: number): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null\n void this.executePush()\n }, ms)\n }\n\n private shouldRegisterUnload(): boolean {\n const onUnload = this.policy.push.onUnload\n if (onUnload !== undefined) return onUnload\n return this.policy.push.mode !== 'manual'\n }\n\n // ─── Event handlers ───────────────────────────────────────────────\n\n private handleVisibilityChange(): void {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') {\n this.fireUnloadPush()\n }\n }\n\n private handlePageHide(): void {\n this.fireUnloadPush()\n }\n\n private handleBeforeExit(): void {\n this.fireUnloadPush()\n }\n\n private handleFocusPull = (): void => {\n if (typeof document !== 'undefined' && document.visibilityState === 'visible') {\n void this.executePull()\n }\n }\n\n private fireUnloadPush(): void {\n if (this.callbacks.getDirtyCount() === 0) return\n // Best-effort synchronous-ish push on unload\n void this.callbacks.push().catch(() => {})\n }\n}\n","/**\n * Strategy seam for the optional sync engine + presence service.\n * Core imports `SyncStrategy` type-only + `NO_SYNC` stub; the real\n * `SyncEngine`, `SyncTransaction`, and `PresenceHandle` constructors\n * are only reachable via `withSync()` in `./sync-active.ts`.\n *\n * Solo apps that never configure `sync` and never call\n * `collection.presence()` ship none of the ~856 LOC behind this seam\n * (`sync.ts` + `sync-transaction.ts` + `presence.ts`).\n *\n * Note: `keyring.ts` (~746 LOC) stays in core because it's required\n * for any multi-user vault — even single-owner vaults use a keyring\n * to wrap the DEK. The team package's grant/revoke/magic-link/\n * delegation modules tree-shake naturally via direct named imports.\n *\n * Behavior under NO_SYNC:\n *\n * - **buildSyncEngine** — throws. Only fires when `createNoydb({ sync })`\n * passes a remote target.\n * - **buildSyncTransaction** — throws. Only fires when `db.transaction(vault)`\n * is called on a vault with sync configured.\n * - **buildPresence** — throws. Only fires when user code calls\n * `collection.presence()`.\n *\n * @internal\n */\n\nimport type {\n NoydbStore,\n ConflictStrategy,\n SyncTargetRole,\n} from '../kernel/types.js'\nimport type { NoydbEventEmitter } from '../kernel/events.js'\nimport type { SyncPolicy } from '../kernel/sync-policy.js'\nimport type { SyncEngine } from './engine.js'\nimport type { SyncTransaction } from './transaction.js'\nimport type { PresenceHandle, PresenceHandleOpts } from './presence.js'\nimport type { Vault } from '../kernel/vault.js'\n\n/**\n * Options accepted by `SyncStrategy.buildSyncEngine`. Mirrors the\n * `SyncEngine` constructor verbatim — kept here so core code never\n * imports the sync module at runtime.\n *\n * @internal\n */\nexport interface BuildSyncEngineOptions {\n local: NoydbStore\n remote: NoydbStore\n vault: string\n strategy: ConflictStrategy\n emitter: NoydbEventEmitter\n syncPolicy?: SyncPolicy\n role?: SyncTargetRole\n label?: string\n}\n\n/**\n * @internal\n */\nexport interface SyncStrategy {\n buildSyncEngine(opts: BuildSyncEngineOptions): SyncEngine\n buildSyncTransaction(vault: Vault, engine: SyncEngine): SyncTransaction\n buildPresence<P>(opts: PresenceHandleOpts): PresenceHandle<P>\n}\n\nfunction notEnabled(op: string): Error {\n return new Error(\n `${op} requires the sync strategy. Import ` +\n '`{ withSync }` from \"@noy-db/hub/sync\" and pass it to ' +\n '`createNoydb({ syncStrategy: withSync() })`.',\n )\n}\n\n/**\n * No-sync stub. Every constructor throws with an actionable pointer\n * — there is no useful \"off\" mode for sync engine / presence /\n * sync-transaction; if the consumer reached one of these surfaces,\n * they intended to use it.\n *\n * @internal\n */\nexport const NO_SYNC: SyncStrategy = {\n buildSyncEngine() { throw notEnabled('SyncEngine') },\n buildSyncTransaction() { throw notEnabled('SyncTransaction') },\n buildPresence() { throw notEnabled('collection.presence()') },\n}\n"],"mappings":"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","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-ZJADGNYF.js";
4
4
  import {
5
5
  openEnvelopeJson
6
- } from "./chunk-RZPOZPZU.js";
6
+ } from "./chunk-SU6SGWXM.js";
7
7
  import {
8
8
  encrypt
9
9
  } from "./chunk-AKKRXT23.js";
@@ -72,4 +72,4 @@ export {
72
72
  writeConsentEntry,
73
73
  loadConsentEntries
74
74
  };
75
- //# sourceMappingURL=chunk-XIDQKFZF.js.map
75
+ //# sourceMappingURL=chunk-5UQ7Y6SQ.js.map
@@ -29,4 +29,4 @@ export {
29
29
  SealedHandle,
30
30
  createStore
31
31
  };
32
- //# sourceMappingURL=chunk-GZACYEOB.js.map
32
+ //# sourceMappingURL=chunk-77AEMXFA.js.map