@storve/core 1.0.1 → 1.0.3

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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +993 -26
  3. package/dist/adapters/indexedDB.cjs +0 -1
  4. package/dist/adapters/indexedDB.mjs +0 -1
  5. package/dist/adapters/localStorage.cjs +0 -1
  6. package/dist/adapters/localStorage.mjs +0 -1
  7. package/dist/adapters/memory.cjs +0 -1
  8. package/dist/adapters/memory.mjs +0 -1
  9. package/dist/adapters/sessionStorage.cjs +0 -1
  10. package/dist/adapters/sessionStorage.mjs +0 -1
  11. package/dist/async-entry.d.ts +0 -1
  12. package/dist/async.cjs +0 -1
  13. package/dist/async.d.ts +0 -1
  14. package/dist/async.mjs +0 -1
  15. package/dist/batch.d.ts +0 -1
  16. package/dist/compose.d.ts +0 -1
  17. package/dist/computed-entry.d.ts +0 -1
  18. package/dist/computed.cjs +0 -1
  19. package/dist/computed.d.ts +0 -1
  20. package/dist/computed.mjs +0 -1
  21. package/dist/devtools/history.d.ts +0 -1
  22. package/dist/devtools/index.d.ts +0 -1
  23. package/dist/devtools/redux-bridge.d.ts +0 -1
  24. package/dist/devtools/snapshots.d.ts +0 -1
  25. package/dist/devtools/withDevtools.d.ts +0 -1
  26. package/dist/devtools.cjs +0 -1
  27. package/dist/devtools.mjs +0 -1
  28. package/dist/extensions/noop.d.ts +0 -1
  29. package/dist/index.cjs +0 -1
  30. package/dist/index.d.ts +0 -1
  31. package/dist/index.mjs +0 -1
  32. package/dist/persist/adapters/indexedDB.d.ts +0 -1
  33. package/dist/persist/adapters/localStorage.d.ts +0 -1
  34. package/dist/persist/adapters/memory.d.ts +0 -1
  35. package/dist/persist/adapters/sessionStorage.d.ts +0 -1
  36. package/dist/persist/debounce.d.ts +0 -1
  37. package/dist/persist/hydrate.d.ts +0 -1
  38. package/dist/persist/index.d.ts +0 -1
  39. package/dist/persist/serialize.d.ts +0 -1
  40. package/dist/persist.cjs +0 -1
  41. package/dist/persist.mjs +0 -1
  42. package/dist/proxy.d.ts +0 -1
  43. package/dist/registry-qtr1UpFU.js +0 -1
  44. package/dist/registry-zaKZ1P-s.js +0 -1
  45. package/dist/registry.d.ts +0 -1
  46. package/dist/signals/createSignal.d.ts +0 -1
  47. package/dist/signals/index.d.ts +0 -1
  48. package/dist/signals/useSignal.d.ts +0 -1
  49. package/dist/signals.cjs +0 -1
  50. package/dist/signals.mjs +0 -1
  51. package/dist/store.d.ts +0 -1
  52. package/dist/sync/channel.d.ts +0 -1
  53. package/dist/sync/index.d.ts +0 -1
  54. package/dist/sync/protocol.d.ts +0 -1
  55. package/dist/sync/withSync.d.ts +0 -1
  56. package/dist/sync.cjs +0 -1
  57. package/dist/sync.mjs +0 -1
  58. package/dist/types.d.ts +0 -1
  59. package/package.json +9 -3
  60. package/CHANGELOG.md +0 -151
  61. package/benchmarks/run.ts +0 -102
  62. package/benchmarks/week2.md +0 -9
  63. package/benchmarks/week2.ts +0 -64
  64. package/benchmarks/week4.md +0 -13
  65. package/benchmarks/week4.ts +0 -178
  66. package/benchmarks/week5.md +0 -15
  67. package/benchmarks/week5.ts +0 -184
  68. package/coverage/coverage-summary.json +0 -31
  69. package/dist/adapters/indexedDB.cjs.map +0 -1
  70. package/dist/adapters/indexedDB.mjs.map +0 -1
  71. package/dist/adapters/localStorage.cjs.map +0 -1
  72. package/dist/adapters/localStorage.mjs.map +0 -1
  73. package/dist/adapters/memory.cjs.map +0 -1
  74. package/dist/adapters/memory.mjs.map +0 -1
  75. package/dist/adapters/sessionStorage.cjs.map +0 -1
  76. package/dist/adapters/sessionStorage.mjs.map +0 -1
  77. package/dist/async-entry.d.ts.map +0 -1
  78. package/dist/async.cjs.map +0 -1
  79. package/dist/async.d.ts.map +0 -1
  80. package/dist/async.mjs.map +0 -1
  81. package/dist/batch.d.ts.map +0 -1
  82. package/dist/compose.d.ts.map +0 -1
  83. package/dist/computed-entry.d.ts.map +0 -1
  84. package/dist/computed.cjs.map +0 -1
  85. package/dist/computed.d.ts.map +0 -1
  86. package/dist/computed.mjs.map +0 -1
  87. package/dist/devtools/history.d.ts.map +0 -1
  88. package/dist/devtools/index.d.ts.map +0 -1
  89. package/dist/devtools/redux-bridge.d.ts.map +0 -1
  90. package/dist/devtools/snapshots.d.ts.map +0 -1
  91. package/dist/devtools/withDevtools.d.ts.map +0 -1
  92. package/dist/devtools.cjs.map +0 -1
  93. package/dist/devtools.mjs.map +0 -1
  94. package/dist/extensions/noop.d.ts.map +0 -1
  95. package/dist/index.cjs.js +0 -118
  96. package/dist/index.cjs.js.map +0 -1
  97. package/dist/index.cjs.map +0 -1
  98. package/dist/index.d.ts.map +0 -1
  99. package/dist/index.esm.js +0 -116
  100. package/dist/index.esm.js.map +0 -1
  101. package/dist/index.mjs.map +0 -1
  102. package/dist/persist/adapters/indexedDB.d.ts.map +0 -1
  103. package/dist/persist/adapters/localStorage.d.ts.map +0 -1
  104. package/dist/persist/adapters/memory.d.ts.map +0 -1
  105. package/dist/persist/adapters/sessionStorage.d.ts.map +0 -1
  106. package/dist/persist/debounce.d.ts.map +0 -1
  107. package/dist/persist/hydrate.d.ts.map +0 -1
  108. package/dist/persist/index.d.ts.map +0 -1
  109. package/dist/persist/serialize.d.ts.map +0 -1
  110. package/dist/persist.cjs.map +0 -1
  111. package/dist/persist.mjs.map +0 -1
  112. package/dist/proxy.d.ts.map +0 -1
  113. package/dist/registry-D3X0HSbl.js +0 -26
  114. package/dist/registry-D3X0HSbl.js.map +0 -1
  115. package/dist/registry-RDjbeJdx.js +0 -29
  116. package/dist/registry-RDjbeJdx.js.map +0 -1
  117. package/dist/registry-qtr1UpFU.js.map +0 -1
  118. package/dist/registry-zaKZ1P-s.js.map +0 -1
  119. package/dist/registry.d.ts.map +0 -1
  120. package/dist/signals/createSignal.d.ts.map +0 -1
  121. package/dist/signals/index.d.ts.map +0 -1
  122. package/dist/signals/useSignal.d.ts.map +0 -1
  123. package/dist/signals.cjs.map +0 -1
  124. package/dist/signals.mjs.map +0 -1
  125. package/dist/stats.html +0 -4949
  126. package/dist/store.d.ts.map +0 -1
  127. package/dist/sync/channel.d.ts.map +0 -1
  128. package/dist/sync/index.d.ts.map +0 -1
  129. package/dist/sync/protocol.d.ts.map +0 -1
  130. package/dist/sync/withSync.d.ts.map +0 -1
  131. package/dist/sync.cjs.map +0 -1
  132. package/dist/sync.mjs.map +0 -1
  133. package/dist/types.d.ts.map +0 -1
  134. package/rollup.config.mjs +0 -44
  135. package/src/async-entry.ts +0 -6
  136. package/src/async.ts +0 -240
  137. package/src/batch.ts +0 -33
  138. package/src/compose.ts +0 -50
  139. package/src/computed-entry.ts +0 -6
  140. package/src/computed.ts +0 -187
  141. package/src/devtools/history.ts +0 -103
  142. package/src/devtools/index.ts +0 -5
  143. package/src/devtools/redux-bridge.ts +0 -70
  144. package/src/devtools/snapshots.ts +0 -54
  145. package/src/devtools/withDevtools.ts +0 -196
  146. package/src/extensions/noop.ts +0 -12
  147. package/src/index.ts +0 -4
  148. package/src/persist/adapters/indexedDB.ts +0 -114
  149. package/src/persist/adapters/localStorage.ts +0 -28
  150. package/src/persist/adapters/memory.ts +0 -26
  151. package/src/persist/adapters/sessionStorage.ts +0 -28
  152. package/src/persist/debounce.ts +0 -28
  153. package/src/persist/hydrate.ts +0 -60
  154. package/src/persist/index.ts +0 -141
  155. package/src/persist/serialize.ts +0 -60
  156. package/src/proxy.ts +0 -87
  157. package/src/registry.ts +0 -67
  158. package/src/signals/createSignal.ts +0 -81
  159. package/src/signals/index.ts +0 -20
  160. package/src/signals/useSignal.ts +0 -18
  161. package/src/store.ts +0 -250
  162. package/src/sync/channel.ts +0 -15
  163. package/src/sync/index.ts +0 -3
  164. package/src/sync/protocol.ts +0 -18
  165. package/src/sync/withSync.ts +0 -147
  166. package/src/types.ts +0 -159
  167. package/tests/async.test.ts +0 -1100
  168. package/tests/batch.test.ts +0 -41
  169. package/tests/compose.test.ts +0 -209
  170. package/tests/computed.test.ts +0 -867
  171. package/tests/devtools.test.ts +0 -1039
  172. package/tests/integration/persist.integration.test.ts +0 -258
  173. package/tests/integration/signals.integration.test.ts +0 -309
  174. package/tests/integration.test.ts +0 -278
  175. package/tests/persist/adapters/indexedDB.adapter.test.ts +0 -185
  176. package/tests/persist/adapters/localStorage.adapter.test.ts +0 -105
  177. package/tests/persist/adapters/memory.adapter.test.ts +0 -112
  178. package/tests/persist/adapters/sessionStorage.adapter.test.ts +0 -128
  179. package/tests/persist/debounce.test.ts +0 -121
  180. package/tests/persist/hydrate.test.ts +0 -120
  181. package/tests/persist/migrate.test.ts +0 -208
  182. package/tests/persist/persist.test.ts +0 -357
  183. package/tests/persist/serialize.test.ts +0 -128
  184. package/tests/proxy.test.ts +0 -473
  185. package/tests/registry.test.ts +0 -67
  186. package/tests/signals/derived.test.ts +0 -244
  187. package/tests/signals/inference.test.ts +0 -108
  188. package/tests/signals/signal.test.ts +0 -348
  189. package/tests/signals/useSignal.test.tsx +0 -275
  190. package/tests/store.test.ts +0 -482
  191. package/tests/stress.test.ts +0 -268
  192. package/tests/sync.test.ts +0 -576
  193. package/tests/types.test.ts +0 -32
  194. package/tests/v0.3.test.ts +0 -813
  195. package/tree-shake-test.js +0 -1
  196. package/tsconfig.json +0 -15
  197. package/vitest.config.ts +0 -22
  198. package/vitest_play.ts +0 -7
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAY,YAAY,EAA4B,MAAM,SAAS,CAAA;AAMlG;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EACxC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,EAC9B,OAAO,GAAE,YAAiB,GAC3B,KAAK,CAAC,CAAC,CAAC,CAuOV"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/sync/channel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CASjE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/sync/protocol.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,KAAK,QAKd,CAAC;AAEL;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IACnB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"withSync.d.ts","sourceRoot":"","sources":["../../src/sync/withSync.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAKD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EACrC,UAAU,EAAE,CAAC,EACb,OAAO,EAAE,WAAW,GACrB,CAAC,CAOH"}
package/dist/sync.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"sync.cjs","sources":["../src/sync/protocol.ts","../src/sync/withSync.ts","../src/sync/channel.ts"],"sourcesContent":[null,null,null],"names":["tabId","crypto","randomUUID","Math","random","toString","substring","SYNC_OPTIONS","Symbol","registerExtension","key","extendStore","context","store","definition","options","enabled","channel","name","window","BroadcastChannel","openChannel","isSyncUpdate","rehydrated","originalSetState","setState","bind","updater","prevState","getState","payload","nextState","keysToSync","keys","Object","hasChanges","buildPayload","postMessage","type","onmessage","event","data","currentState","targetTabId","__sync_channel","defineProperty","value","enumerable","configurable"],"mappings":"qDAGO,MAAMA,EACa,oBAAXC,QAAuD,mBAAtBA,OAAOC,WACxCD,OAAOC,aAEXC,KAAKC,SAASC,SAAS,IAAIC,UAAU,EAAG,ICW7CC,EAAeC,OAAO,uBAkB5BC,EAAAA,kBAAkB,CACdC,IAAK,OACLC,YAAcC,IACV,MAAMC,MAAEA,EAAKC,WAAEA,GAAeF,EACxBG,EAAWD,EAAuCP,GAExD,IAAKQ,IAA+B,IAApBA,EAAQC,QAAmB,MAAO,CAAA,EAElD,MAAMC,ECvCR,SAAsBC,GACxB,GAAsB,oBAAXC,OAAwB,OAAO,KAC1C,GAAgC,oBAArBC,iBAAkC,OAAO,KACpD,IACI,OAAO,IAAIA,iBAAiBF,EAChC,CAAE,MAEE,OAAO,IACX,CACJ,CD8BwBG,CAAYN,EAAQE,SACpC,IAAKA,EAAS,MAAO,CAAA,EAErB,IAAIK,GAAe,EACfC,GAAa,EAGjB,MAkBMC,EAAmBX,EAAMY,SAASC,KAAKb,GAyE7C,OAxEAA,EAAMY,SAAYE,IACd,MAAMC,EAAY,IAAKf,EAAMgB,YAE7B,GADAL,EAAiBG,IACZL,EAAc,CACf,MACMQ,EAxBO,EAACC,EAAoCH,KACtD,MAAMI,EAAajB,EAAQkB,MAAQC,OAAOD,KAAKF,GACzCD,EAAmC,CAAA,EACzC,IAAIK,GAAa,EAEjB,IAAK,MAAMzB,KAAOsB,EAEK,iBAARtB,GAEPqB,EAAUrB,KAASkB,EAAUlB,KAC7BoB,EAAQpB,GAAOqB,EAAUrB,GACzByB,GAAa,GAGrB,OAAOA,EAAaL,EAAU,MAUVM,CADEvB,EAAMgB,WACgBD,GACpCE,GACAb,EAAQoB,YAAY,CAChBC,KAAM,eACNR,UACA9B,SAGZ,GAIJiB,EAAQsB,UAAaC,IACjB,MAAMC,EAAOD,EAAMC,KAGnB,GAAIA,EAAKzC,QAAUA,EAEnB,OAAQyC,EAAKH,MACT,IAAK,eACDhB,GAAe,EACfT,EAAMY,SAASgB,EAAKX,SACpBR,GAAe,EACf,MAEJ,IAAK,gBAAiB,CAElB,MAAMoB,EAAe7B,EAAMgB,WACrBC,EAAmC,CAAA,EACnCE,EAAajB,EAAQkB,MAAQC,OAAOD,KAAKS,GAE/C,IAAK,MAAMhC,KAAOsB,EACK,iBAARtB,GACPA,KAAOgC,IACPZ,EAAQpB,GAAOgC,EAAahC,IAIpCO,EAAQoB,YAAY,CAChBC,KAAM,gBACNR,UACAa,YAAaF,EAAKzC,MAClBA,UAEJ,KACJ,CACA,IAAK,gBAEGyC,EAAKE,cAAgB3C,GAAUuB,IAC/BA,GAAa,EACbD,GAAe,EACfT,EAAMY,SAASgB,EAAKX,SACpBR,GAAe,KAQ/BL,EAAQoB,YAAY,CAAEC,KAAM,gBAAiBtC,UAOtC,CACH4C,eAAgB3B,uBAvHtB,SACFH,EACAC,GAOA,OALAmB,OAAOW,eAAe/B,EAAYP,EAAc,CAC5CuC,MAAO/B,EACPgC,YAAY,EACZC,cAAc,IAEXlC,CACX"}
package/dist/sync.mjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"sync.mjs","sources":["../src/sync/protocol.ts","../src/sync/withSync.ts","../src/sync/channel.ts"],"sourcesContent":[null,null,null],"names":["tabId","crypto","randomUUID","Math","random","toString","substring","SYNC_OPTIONS","Symbol","withSync","definition","options","Object","defineProperty","value","enumerable","configurable","registerExtension","key","extendStore","context","store","enabled","channel","name","window","BroadcastChannel","openChannel","isSyncUpdate","rehydrated","originalSetState","setState","bind","updater","prevState","getState","payload","nextState","keysToSync","keys","hasChanges","buildPayload","postMessage","type","onmessage","event","data","currentState","targetTabId","__sync_channel"],"mappings":"2CAGO,MAAMA,EACa,oBAAXC,QAAuD,mBAAtBA,OAAOC,WACxCD,OAAOC,aAEXC,KAAKC,SAASC,SAAS,IAAIC,UAAU,EAAG,ICW7CC,EAAeC,OAAO,uBAMtB,SAAUC,EACZC,EACAC,GAOA,OALAC,OAAOC,eAAeH,EAAYH,EAAc,CAC5CO,MAAOH,EACPI,YAAY,EACZC,cAAc,IAEXN,CACX,CAEAO,EAAkB,CACdC,IAAK,OACLC,YAAcC,IACV,MAAMC,MAAEA,EAAKX,WAAEA,GAAeU,EACxBT,EAAWD,EAAuCH,GAExD,IAAKI,IAA+B,IAApBA,EAAQW,QAAmB,MAAO,CAAA,EAElD,MAAMC,ECvCR,SAAsBC,GACxB,GAAsB,oBAAXC,OAAwB,OAAO,KAC1C,GAAgC,oBAArBC,iBAAkC,OAAO,KACpD,IACI,OAAO,IAAIA,iBAAiBF,EAChC,CAAE,MAEE,OAAO,IACX,CACJ,CD8BwBG,CAAYhB,EAAQY,SACpC,IAAKA,EAAS,MAAO,CAAA,EAErB,IAAIK,GAAe,EACfC,GAAa,EAGjB,MAkBMC,EAAmBT,EAAMU,SAASC,KAAKX,GAyE7C,OAxEAA,EAAMU,SAAYE,IACd,MAAMC,EAAY,IAAKb,EAAMc,YAE7B,GADAL,EAAiBG,IACZL,EAAc,CACf,MACMQ,EAxBO,EAACC,EAAoCH,KACtD,MAAMI,EAAa3B,EAAQ4B,MAAQ3B,OAAO2B,KAAKF,GACzCD,EAAmC,CAAA,EACzC,IAAII,GAAa,EAEjB,IAAK,MAAMtB,KAAOoB,EAEK,iBAARpB,GAEPmB,EAAUnB,KAASgB,EAAUhB,KAC7BkB,EAAQlB,GAAOmB,EAAUnB,GACzBsB,GAAa,GAGrB,OAAOA,EAAaJ,EAAU,MAUVK,CADEpB,EAAMc,WACgBD,GACpCE,GACAb,EAAQmB,YAAY,CAChBC,KAAM,eACNP,UACApC,SAGZ,GAIJuB,EAAQqB,UAAaC,IACjB,MAAMC,EAAOD,EAAMC,KAGnB,GAAIA,EAAK9C,QAAUA,EAEnB,OAAQ8C,EAAKH,MACT,IAAK,eACDf,GAAe,EACfP,EAAMU,SAASe,EAAKV,SACpBR,GAAe,EACf,MAEJ,IAAK,gBAAiB,CAElB,MAAMmB,EAAe1B,EAAMc,WACrBC,EAAmC,CAAA,EACnCE,EAAa3B,EAAQ4B,MAAQ3B,OAAO2B,KAAKQ,GAE/C,IAAK,MAAM7B,KAAOoB,EACK,iBAARpB,GACPA,KAAO6B,IACPX,EAAQlB,GAAO6B,EAAa7B,IAIpCK,EAAQmB,YAAY,CAChBC,KAAM,gBACNP,UACAY,YAAaF,EAAK9C,MAClBA,UAEJ,KACJ,CACA,IAAK,gBAEG8C,EAAKE,cAAgBhD,GAAU6B,IAC/BA,GAAa,EACbD,GAAe,EACfP,EAAMU,SAASe,EAAKV,SACpBR,GAAe,KAQ/BL,EAAQmB,YAAY,CAAEC,KAAM,gBAAiB3C,UAOtC,CACHiD,eAAgB1B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/rollup.config.mjs DELETED
@@ -1,44 +0,0 @@
1
- import typescript from '@rollup/plugin-typescript';
2
- import terser from '@rollup/plugin-terser';
3
- import { visualizer } from 'rollup-plugin-visualizer';
4
-
5
- const analyze = process.env.ANALYZE === 'true';
6
-
7
- export default {
8
- input: {
9
- index: 'src/index.ts',
10
- async: 'src/async-entry.ts',
11
- computed: 'src/computed-entry.ts',
12
- persist: 'src/persist/index.ts',
13
- 'adapters/localStorage': 'src/persist/adapters/localStorage.ts',
14
- 'adapters/sessionStorage': 'src/persist/adapters/sessionStorage.ts',
15
- 'adapters/memory': 'src/persist/adapters/memory.ts',
16
- 'adapters/indexedDB': 'src/persist/adapters/indexedDB.ts',
17
- signals: 'src/signals/index.ts',
18
- devtools: 'src/devtools/index.ts',
19
- sync: 'src/sync/index.ts',
20
- },
21
- output: [
22
- {
23
- dir: 'dist',
24
- format: 'es',
25
- entryFileNames: '[name].mjs',
26
- sourcemap: true,
27
- },
28
- {
29
- dir: 'dist',
30
- format: 'cjs',
31
- entryFileNames: '[name].cjs',
32
- sourcemap: true,
33
- },
34
- ],
35
- plugins: [
36
- typescript({
37
- tsconfig: './tsconfig.json',
38
- declaration: true,
39
- declarationDir: 'dist',
40
- }),
41
- terser(),
42
- analyze && visualizer({ filename: 'dist/stats.html', gzipSize: true }),
43
- ].filter(Boolean),
44
- };
@@ -1,6 +0,0 @@
1
- /**
2
- * Async entry point. Import from 'storve/async'.
3
- * Side-effect: registers async extension so createStore handles createAsync values.
4
- */
5
- export { createAsync } from './async';
6
- export type { AsyncState, AsyncOptions, AsyncStatus } from './types';
package/src/async.ts DELETED
@@ -1,240 +0,0 @@
1
- import { AsyncValue, AsyncOptions, AsyncState, AsyncStatus, ASYNC_VALUE_MARKER, IAsyncEngine } from './types';
2
- import { registerExtension } from './registry';
3
-
4
- /**
5
- * Creates an async value definition for use in createStore.
6
- *
7
- * @param fn - The async function to execute.
8
- * @param options - Optional configuration (ttl, staleWhileRevalidate).
9
- */
10
- export function createAsync<T, Args extends unknown[] = unknown[]>(
11
- fn: (...args: Args) => Promise<T>,
12
- options: AsyncOptions = {}
13
- ): AsyncValue<T> {
14
- return {
15
- [ASYNC_VALUE_MARKER]: true,
16
- init: (onUpdate: (s: AsyncState<T>) => void) =>
17
- new AsyncEngine(fn as unknown as (...args: unknown[]) => Promise<T>, options, onUpdate)
18
- };
19
- }
20
-
21
- /**
22
- * Internal engine that manages the state of a single async key.
23
- * Handles fetching, caching, and race condition protection.
24
- * @internal
25
- */
26
- export class AsyncEngine<T> implements IAsyncEngine<T> {
27
- private lastRequestId = 0;
28
- private lastArgs: unknown[] = [];
29
- private cache = new Map<string, { data: T; expiresAt: number }>();
30
- private status: AsyncStatus = 'idle';
31
- private data: T | null = null;
32
- private error: string | null = null;
33
-
34
- // Rollback state for optimistic updates
35
- private previousData: T | null = null;
36
- private previousStatus: AsyncStatus = 'idle';
37
- private hasPrevious = false;
38
-
39
- // Stable state result to maintain identity
40
- private lastState: AsyncState<T> | null = null;
41
- private stableRefetch = () => this.refetch();
42
-
43
- constructor(
44
- private fn: (...args: unknown[]) => Promise<T>,
45
- private options: AsyncOptions,
46
- private onUpdate: (state: AsyncState<T>) => void
47
- ) { }
48
-
49
- /**
50
- * Returns the current public state shape for this async key.
51
- */
52
- getState(): AsyncState<T> {
53
- if (!this.lastState) {
54
- this.lastState = {
55
- data: this.data,
56
- error: this.error,
57
- status: this.status,
58
- loading: this.status === 'loading',
59
- refetch: this.stableRefetch,
60
- };
61
- }
62
- return this.lastState;
63
- }
64
-
65
- /**
66
- * Triggers a fetch. Handles TTL caching and SWR.
67
- */
68
- async fetch(...args: unknown[]): Promise<void> {
69
- // Handle optional options as last argument if it looks like { optimistic: ... }
70
- let fetchOptions: { optimistic?: { data: T, status?: AsyncStatus } } | undefined;
71
- let actualArgs = args;
72
-
73
- if (args.length > 0) {
74
- const lastArg = args[args.length - 1];
75
- if (lastArg && typeof lastArg === 'object' && 'optimistic' in lastArg) {
76
- fetchOptions = lastArg as { optimistic?: { data: T, status?: AsyncStatus } };
77
- actualArgs = args.slice(0, -1);
78
- }
79
- }
80
-
81
- const now = Date.now();
82
- const { ttl = 0, staleWhileRevalidate = false } = this.options;
83
-
84
- // Argument-based cache key. v0.5+: replace JSON.stringify with a more robust stable hash
85
- const cacheKey = JSON.stringify(actualArgs);
86
- const cached = this.cache.get(cacheKey);
87
-
88
- let fromOptimistic = false;
89
- if (fetchOptions?.optimistic) {
90
- this.previousData = this.data;
91
- this.previousStatus = this.status;
92
- this.hasPrevious = true;
93
- this.data = fetchOptions.optimistic.data;
94
- this.status = fetchOptions.optimistic.status || 'success';
95
- this.lastArgs = actualArgs;
96
- this.notify();
97
- fromOptimistic = true;
98
- // Fall through to runFetch which will handle result or rollback
99
- } else {
100
- // Cache hit logic (only if NOT optimistic)
101
- if (ttl > 0 && cached && now < cached.expiresAt && this.status === 'success') {
102
- if (this.data !== cached.data) {
103
- this.data = cached.data;
104
- this.lastArgs = actualArgs;
105
- this.notify();
106
- }
107
- return;
108
- }
109
-
110
- // Stale-While-Revalidate logic
111
- const isStale = ttl > 0 && cached && now >= cached.expiresAt && this.status === 'success';
112
-
113
- if (isStale && staleWhileRevalidate) {
114
- this.data = cached.data;
115
- this.lastArgs = actualArgs;
116
- return this.runFetch(actualArgs, true);
117
- }
118
- }
119
-
120
- this.lastArgs = actualArgs;
121
- return this.runFetch(actualArgs, fromOptimistic);
122
- }
123
-
124
- /**
125
- * Re-runs the operation with last used arguments. Bypasses TTL.
126
- */
127
- async refetch(): Promise<void> {
128
- return this.runFetch(this.lastArgs, false);
129
- }
130
-
131
- /**
132
- * Clears the cache for this key.
133
- */
134
- invalidate(): void {
135
- this.cache.clear();
136
- }
137
-
138
- /**
139
- * Internal runner for the async function with race protection.
140
- */
141
- private async runFetch(args: unknown[], background: boolean): Promise<void> {
142
- const requestId = ++this.lastRequestId;
143
-
144
- // If not a background SWR fetch and NOT already optimistic, show loading
145
- if (!background) {
146
- this.status = 'loading';
147
- this.notify();
148
- }
149
-
150
- try {
151
- const result = await this.fn(...args);
152
-
153
- // Race condition protection: only the latest request wins
154
- if (requestId !== this.lastRequestId) return;
155
-
156
- this.data = result;
157
- this.error = null;
158
- this.status = 'success';
159
- this.hasPrevious = false; // Resolved, no need to rollback anymore
160
-
161
- const ttl = this.options.ttl || 0;
162
- if (ttl > 0) {
163
- const cacheKey = JSON.stringify(args);
164
- this.cache.set(cacheKey, { data: result, expiresAt: Date.now() + ttl });
165
- }
166
- } catch (err: unknown) {
167
- if (requestId !== this.lastRequestId) return;
168
-
169
- this.error = err instanceof Error ? err.message : String(err);
170
-
171
- // Rollback if we had previous data (likely from optimistic update)
172
- if (this.hasPrevious) {
173
- this.data = this.previousData;
174
- this.status = this.previousStatus;
175
- this.hasPrevious = false;
176
- } else if (background) {
177
- // Keep data but set error status
178
- this.status = 'error';
179
- } else {
180
- this.data = null;
181
- this.status = 'error';
182
- }
183
- }
184
-
185
- this.notify();
186
- }
187
-
188
- private notify() {
189
- this.lastState = null; // Invalidate cached state object
190
- this.onUpdate(this.getState());
191
- }
192
- }
193
-
194
- // Register async extension when module is imported (order 0 = runs before computed)
195
- registerExtension({
196
- key: 'async',
197
- order: 0,
198
- processDefinition: (definition) => {
199
- const state: Record<string, unknown> = {};
200
- const asyncInits: Array<{ key: string; init: (onUpdate: (state: unknown) => void) => unknown }> = [];
201
- for (const key of Object.keys(definition)) {
202
- const val = definition[key];
203
- if (val && typeof val === 'object' && ASYNC_VALUE_MARKER in val) {
204
- const asyncVal = val as unknown as AsyncValue<unknown>;
205
- asyncInits.push({ key, init: asyncVal.init });
206
- } else {
207
- state[key] = val;
208
- }
209
- }
210
- return { state, asyncInits };
211
- },
212
- extendStore: (ctx) => {
213
- const engines = ctx.engines as Map<string, IAsyncEngine<unknown>>;
214
- return {
215
- fetch: async (key: string, ...args: unknown[]) => {
216
- if (!engines.has(key)) {
217
- throw new Error(`Storve: no async key "${key}" found in store`);
218
- }
219
- const engine = engines.get(key);
220
- if (engine) await engine.fetch(...args);
221
- },
222
- refetch: async (key: string) => {
223
- const engine = engines.get(key);
224
- if (engine) await engine.refetch();
225
- },
226
- invalidate: (key: string) => {
227
- const engine = engines.get(key);
228
- if (engine) engine.invalidate();
229
- },
230
- invalidateAll: () => {
231
- engines.forEach((engine) => engine.invalidate());
232
- },
233
- getAsyncState: (key: string) => {
234
- const engine = engines.get(key);
235
- return engine ? engine.getState() : undefined;
236
- },
237
- };
238
- },
239
- });
240
-
package/src/batch.ts DELETED
@@ -1,33 +0,0 @@
1
- let batchCount = 0;
2
- const subscribers = new Set<() => void>();
3
-
4
- /**
5
- * Batches multiple state updates across any number of stores.
6
- * Listeners will only be notified once after the batch function completes.
7
- *
8
- * @param fn - The function containing state updates to batch.
9
- */
10
- export function batch(fn: () => void): void {
11
- batchCount++;
12
- try {
13
- fn();
14
- } finally {
15
- batchCount--;
16
- if (batchCount === 0) {
17
- subscribers.forEach((s) => s());
18
- }
19
- }
20
- }
21
-
22
- /** @internal */
23
- export function isBatching(): boolean {
24
- return batchCount > 0;
25
- }
26
-
27
- /** @internal */
28
- export function subscribeToBatch(cb: () => void): () => void {
29
- subscribers.add(cb);
30
- return () => {
31
- subscribers.delete(cb);
32
- };
33
- }
package/src/compose.ts DELETED
@@ -1,50 +0,0 @@
1
- import type { Store } from './types.js'
2
-
3
- export function compose<D extends object, S extends Store<D>>(store: S): S
4
-
5
- export function compose<D extends object, S extends Store<D>, R1>(
6
- store: S,
7
- f1: (store: S) => R1
8
- ): R1
9
-
10
- export function compose<D extends object, S extends Store<D>, R1, R2>(
11
- store: S,
12
- f1: (store: S) => R1,
13
- f2: (store: R1) => R2
14
- ): R2
15
-
16
- export function compose<D extends object, S extends Store<D>, R1, R2, R3>(
17
- store: S,
18
- f1: (store: S) => R1,
19
- f2: (store: R1) => R2,
20
- f3: (store: R2) => R3
21
- ): R3
22
-
23
- export function compose<D extends object>(
24
- store: Store<D>,
25
- ...enhancers: Array<(store: unknown) => unknown>
26
- ): unknown
27
-
28
- /**
29
- * Pipes a Storve store through one or more enhancer functions left to right.
30
- * Each enhancer receives the output of the previous one.
31
- *
32
- * @template D - The generic parameter for the base store definition object.
33
- * @param {Store<D>} store - The base store to enhance.
34
- * @param {...Array<Function>} enhancers - The enhancer functions applied left to right.
35
- * @returns {unknown} The enhanced store instance.
36
- */
37
- export function compose<D extends object>(
38
- store: Store<D>,
39
- ...enhancers: Array<(store: unknown) => unknown>
40
- ): unknown {
41
- if (enhancers.length === 0) {
42
- return store
43
- }
44
-
45
- let currentStore: unknown = store
46
- for (let i = 0; i < enhancers.length; i++) {
47
- currentStore = enhancers[i](currentStore)
48
- }
49
- return currentStore
50
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Computed entry point. Import from 'storve/computed'.
3
- * Side-effect: registers computed extension so createStore handles computed values.
4
- */
5
- export { computed, COMPUTED_MARKER } from './computed';
6
- export type { ComputedValue } from './types';
package/src/computed.ts DELETED
@@ -1,187 +0,0 @@
1
- /**
2
- * Computed values implementation for Storve.
3
- * Provides synchronous derived state with automatic dependency tracking.
4
- */
5
-
6
- import { registerExtension } from './registry';
7
-
8
- /** Marker constant used to identify computed definitions in store definitions. */
9
- export const COMPUTED_MARKER = '__rf_computed' as const;
10
-
11
- /**
12
- * Type representing a computed value definition.
13
- * Used as a value in the store definition; the store unwraps it to the computed result type T.
14
- */
15
- export type ComputedValue<T> = {
16
- [COMPUTED_MARKER]: true;
17
- fn: (state: unknown) => T;
18
- };
19
-
20
- /**
21
- * Internal engine shape for a single computed value.
22
- * @internal
23
- */
24
- export interface ComputedEngine<T> {
25
- fn: (state: unknown) => T;
26
- value: T;
27
- deps: Set<string>;
28
- dirty: boolean;
29
- }
30
-
31
- /**
32
- * Creates a computed value definition. When used in a store definition, the store
33
- * will run the function against the current state, track which keys were read,
34
- * and recompute when those dependencies change. Supports chaining (computed can
35
- * depend on other computeds). Circular dependencies are detected and throw at creation.
36
- *
37
- * @param fn - Function that receives the current state and returns the derived value.
38
- * @returns A marker object that the store recognizes as a computed definition.
39
- *
40
- * @example
41
- * const store = createStore({
42
- * a: 1,
43
- * b: 2,
44
- * sum: computed((s) => s.a + s.b),
45
- * });
46
- * store.getState().sum; // 3
47
- */
48
- export function computed<T>(fn: (state: unknown) => T): ComputedValue<T> {
49
- return {
50
- [COMPUTED_MARKER]: true,
51
- fn,
52
- };
53
- }
54
-
55
- /**
56
- * Tracks which top-level state keys are accessed during the execution of a computed function.
57
- * Runs the function against a shallow Proxy of the state and returns the result plus the set of keys read.
58
- * Used internally by the store for dependency tracking and dirty marking.
59
- *
60
- * @param state - Current state object (base + resolved computeds).
61
- * @param fn - The computed function to run.
62
- * @returns The computed result and a Set of dependency keys (top-level only).
63
- */
64
- export function trackDependencies<S extends object, T>(
65
- state: S,
66
- fn: (state: S) => T
67
- ): { result: T; deps: Set<string> } {
68
- const deps = new Set<string>();
69
- const proxy = new Proxy(state, {
70
- get(target, key) {
71
- deps.add(key as string);
72
- return (target as Record<string, unknown>)[key as string];
73
- },
74
- });
75
- const result = fn(proxy as S);
76
- return { result, deps };
77
- }
78
-
79
- function detectCircular(computedKeys: string[], getDeps: (key: string) => Set<string>): void {
80
- const keySet = new Set(computedKeys);
81
- const path: string[] = [];
82
- const visited = new Set<string>();
83
- function visit(key: string): void {
84
- if (path.includes(key)) {
85
- throw new Error(`Storve: circular dependency in computed values: ${[...path, key].join(' → ')}`);
86
- }
87
- if (visited.has(key)) return;
88
- path.push(key);
89
- for (const d of getDeps(key)) {
90
- if (keySet.has(d)) visit(d);
91
- }
92
- path.pop();
93
- visited.add(key);
94
- }
95
- for (const k of computedKeys) {
96
- if (!visited.has(k)) visit(k);
97
- }
98
- }
99
-
100
- function topologicalSort(computedKeys: string[], getDeps: (key: string) => Set<string>): string[] {
101
- const result: string[] = [];
102
- const visited = new Set<string>();
103
- const keySet = new Set(computedKeys);
104
- function visit(k: string): void {
105
- if (visited.has(k)) return;
106
- visited.add(k);
107
- for (const d of getDeps(k)) {
108
- if (keySet.has(d)) visit(d);
109
- }
110
- result.push(k);
111
- }
112
- for (const k of computedKeys) visit(k);
113
- return result;
114
- }
115
-
116
- // Register computed extension when module is imported (order 1 = runs after async)
117
- registerExtension({
118
- key: 'computed',
119
- order: 1,
120
- processDefinition: (definition) => {
121
- const state = { ...definition };
122
- const computedKeys = new Set<string>();
123
- const computedEngines = new Map<string, ComputedEngine<unknown>>();
124
-
125
- for (const key of Object.keys(definition)) {
126
- const val = definition[key];
127
- if (val && typeof val === 'object' && COMPUTED_MARKER in val) {
128
- const comp = val as { [COMPUTED_MARKER]: true; fn: (state: unknown) => unknown };
129
- computedKeys.add(key);
130
- delete state[key];
131
- const { result, deps } = trackDependencies(state, comp.fn);
132
- computedEngines.set(key, { fn: comp.fn, value: result, deps, dirty: false });
133
- }
134
- }
135
-
136
- const computedKeysList = Array.from(computedKeys);
137
- let topoOrder: string[] = [];
138
- if (computedKeysList.length > 0) {
139
- const getDeps = (k: string) => computedEngines.get(k)!.deps;
140
- detectCircular(computedKeysList, getDeps);
141
- topoOrder = topologicalSort(computedKeysList, getDeps);
142
- for (const key of topoOrder) {
143
- const engine = computedEngines.get(key)!;
144
- const { result, deps } = trackDependencies(state, engine.fn);
145
- engine.value = result;
146
- engine.deps = deps;
147
- state[key] = result;
148
- }
149
- }
150
-
151
- const runRecompute = (
152
- changedKeys: Set<string>,
153
- getState: () => Record<string, unknown>,
154
- setComputed: (key: string, value: unknown) => void
155
- ) => {
156
- topoOrder.forEach((key) => {
157
- const engine = computedEngines.get(key)!;
158
- for (const d of engine.deps) {
159
- if (changedKeys.has(d)) {
160
- engine.dirty = true;
161
- break;
162
- }
163
- }
164
- });
165
- topoOrder.forEach((key) => {
166
- const engine = computedEngines.get(key)!;
167
- if (!engine.dirty) return;
168
- const currentState = getState();
169
- const { result, deps } = trackDependencies(currentState, engine.fn);
170
- engine.value = result;
171
- engine.deps = deps;
172
- engine.dirty = false;
173
- setComputed(key, result);
174
- topoOrder.forEach((other) => {
175
- if (other === key) return;
176
- if (computedEngines.get(other)!.deps.has(key)) computedEngines.get(other)!.dirty = true;
177
- });
178
- });
179
- };
180
-
181
- return {
182
- state,
183
- readOnlyKeys: computedKeys,
184
- onStateChanged: (ctx) => runRecompute(ctx.changedKeys, ctx.getState, ctx.setComputed),
185
- };
186
- },
187
- });