@storve/core 1.0.2 → 1.0.4
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.
- package/LICENSE +21 -0
- package/README.md +0 -16
- package/dist/adapters/indexedDB.cjs +0 -1
- package/dist/adapters/indexedDB.mjs +0 -1
- package/dist/adapters/localStorage.cjs +0 -1
- package/dist/adapters/localStorage.mjs +0 -1
- package/dist/adapters/memory.cjs +0 -1
- package/dist/adapters/memory.mjs +0 -1
- package/dist/adapters/sessionStorage.cjs +0 -1
- package/dist/adapters/sessionStorage.mjs +0 -1
- package/dist/async-entry.d.ts +0 -1
- package/dist/async.cjs +0 -1
- package/dist/async.d.ts +0 -1
- package/dist/async.mjs +0 -1
- package/dist/batch.d.ts +0 -1
- package/dist/compose.d.ts +0 -1
- package/dist/computed-entry.d.ts +0 -1
- package/dist/computed.cjs +0 -1
- package/dist/computed.d.ts +0 -1
- package/dist/computed.mjs +0 -1
- package/dist/devtools/history.d.ts +0 -1
- package/dist/devtools/index.d.ts +0 -1
- package/dist/devtools/redux-bridge.d.ts +0 -1
- package/dist/devtools/snapshots.d.ts +0 -1
- package/dist/devtools/withDevtools.d.ts +0 -1
- package/dist/devtools.cjs +0 -1
- package/dist/devtools.mjs +0 -1
- package/dist/extensions/noop.d.ts +0 -1
- package/dist/index.cjs +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +0 -1
- package/dist/persist/adapters/indexedDB.d.ts +0 -1
- package/dist/persist/adapters/localStorage.d.ts +0 -1
- package/dist/persist/adapters/memory.d.ts +0 -1
- package/dist/persist/adapters/sessionStorage.d.ts +0 -1
- package/dist/persist/debounce.d.ts +0 -1
- package/dist/persist/hydrate.d.ts +0 -1
- package/dist/persist/index.d.ts +0 -1
- package/dist/persist/serialize.d.ts +0 -1
- package/dist/persist.cjs +0 -1
- package/dist/persist.mjs +0 -1
- package/dist/proxy.d.ts +0 -1
- package/dist/registry-qtr1UpFU.js +0 -1
- package/dist/registry-zaKZ1P-s.js +0 -1
- package/dist/registry.d.ts +0 -1
- package/dist/signals/createSignal.d.ts +0 -1
- package/dist/signals/index.d.ts +0 -1
- package/dist/signals/useSignal.d.ts +0 -1
- package/dist/signals.cjs +0 -1
- package/dist/signals.mjs +0 -1
- package/dist/store.d.ts +0 -1
- package/dist/sync/channel.d.ts +0 -1
- package/dist/sync/index.d.ts +0 -1
- package/dist/sync/protocol.d.ts +0 -1
- package/dist/sync/withSync.d.ts +0 -1
- package/dist/sync.cjs +0 -1
- package/dist/sync.mjs +0 -1
- package/dist/types.d.ts +0 -1
- package/package.json +10 -3
- package/CHANGELOG.md +0 -151
- package/benchmarks/run.ts +0 -102
- package/benchmarks/week2.md +0 -9
- package/benchmarks/week2.ts +0 -64
- package/benchmarks/week4.md +0 -13
- package/benchmarks/week4.ts +0 -178
- package/benchmarks/week5.md +0 -15
- package/benchmarks/week5.ts +0 -184
- package/coverage/coverage-summary.json +0 -31
- package/dist/adapters/indexedDB.cjs.map +0 -1
- package/dist/adapters/indexedDB.mjs.map +0 -1
- package/dist/adapters/localStorage.cjs.map +0 -1
- package/dist/adapters/localStorage.mjs.map +0 -1
- package/dist/adapters/memory.cjs.map +0 -1
- package/dist/adapters/memory.mjs.map +0 -1
- package/dist/adapters/sessionStorage.cjs.map +0 -1
- package/dist/adapters/sessionStorage.mjs.map +0 -1
- package/dist/async-entry.d.ts.map +0 -1
- package/dist/async.cjs.map +0 -1
- package/dist/async.d.ts.map +0 -1
- package/dist/async.mjs.map +0 -1
- package/dist/batch.d.ts.map +0 -1
- package/dist/compose.d.ts.map +0 -1
- package/dist/computed-entry.d.ts.map +0 -1
- package/dist/computed.cjs.map +0 -1
- package/dist/computed.d.ts.map +0 -1
- package/dist/computed.mjs.map +0 -1
- package/dist/devtools/history.d.ts.map +0 -1
- package/dist/devtools/index.d.ts.map +0 -1
- package/dist/devtools/redux-bridge.d.ts.map +0 -1
- package/dist/devtools/snapshots.d.ts.map +0 -1
- package/dist/devtools/withDevtools.d.ts.map +0 -1
- package/dist/devtools.cjs.map +0 -1
- package/dist/devtools.mjs.map +0 -1
- package/dist/extensions/noop.d.ts.map +0 -1
- package/dist/index.cjs.js +0 -118
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.esm.js +0 -116
- package/dist/index.esm.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/persist/adapters/indexedDB.d.ts.map +0 -1
- package/dist/persist/adapters/localStorage.d.ts.map +0 -1
- package/dist/persist/adapters/memory.d.ts.map +0 -1
- package/dist/persist/adapters/sessionStorage.d.ts.map +0 -1
- package/dist/persist/debounce.d.ts.map +0 -1
- package/dist/persist/hydrate.d.ts.map +0 -1
- package/dist/persist/index.d.ts.map +0 -1
- package/dist/persist/serialize.d.ts.map +0 -1
- package/dist/persist.cjs.map +0 -1
- package/dist/persist.mjs.map +0 -1
- package/dist/proxy.d.ts.map +0 -1
- package/dist/registry-D3X0HSbl.js +0 -26
- package/dist/registry-D3X0HSbl.js.map +0 -1
- package/dist/registry-RDjbeJdx.js +0 -29
- package/dist/registry-RDjbeJdx.js.map +0 -1
- package/dist/registry-qtr1UpFU.js.map +0 -1
- package/dist/registry-zaKZ1P-s.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/signals/createSignal.d.ts.map +0 -1
- package/dist/signals/index.d.ts.map +0 -1
- package/dist/signals/useSignal.d.ts.map +0 -1
- package/dist/signals.cjs.map +0 -1
- package/dist/signals.mjs.map +0 -1
- package/dist/stats.html +0 -4949
- package/dist/store.d.ts.map +0 -1
- package/dist/sync/channel.d.ts.map +0 -1
- package/dist/sync/index.d.ts.map +0 -1
- package/dist/sync/protocol.d.ts.map +0 -1
- package/dist/sync/withSync.d.ts.map +0 -1
- package/dist/sync.cjs.map +0 -1
- package/dist/sync.mjs.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/rollup.config.mjs +0 -44
- package/src/async-entry.ts +0 -6
- package/src/async.ts +0 -240
- package/src/batch.ts +0 -33
- package/src/compose.ts +0 -50
- package/src/computed-entry.ts +0 -6
- package/src/computed.ts +0 -187
- package/src/devtools/history.ts +0 -103
- package/src/devtools/index.ts +0 -5
- package/src/devtools/redux-bridge.ts +0 -70
- package/src/devtools/snapshots.ts +0 -54
- package/src/devtools/withDevtools.ts +0 -196
- package/src/extensions/noop.ts +0 -12
- package/src/index.ts +0 -4
- package/src/persist/adapters/indexedDB.ts +0 -114
- package/src/persist/adapters/localStorage.ts +0 -28
- package/src/persist/adapters/memory.ts +0 -26
- package/src/persist/adapters/sessionStorage.ts +0 -28
- package/src/persist/debounce.ts +0 -28
- package/src/persist/hydrate.ts +0 -60
- package/src/persist/index.ts +0 -141
- package/src/persist/serialize.ts +0 -60
- package/src/proxy.ts +0 -87
- package/src/registry.ts +0 -67
- package/src/signals/createSignal.ts +0 -81
- package/src/signals/index.ts +0 -20
- package/src/signals/useSignal.ts +0 -18
- package/src/store.ts +0 -250
- package/src/sync/channel.ts +0 -15
- package/src/sync/index.ts +0 -3
- package/src/sync/protocol.ts +0 -18
- package/src/sync/withSync.ts +0 -147
- package/src/types.ts +0 -159
- package/tests/async.test.ts +0 -1100
- package/tests/batch.test.ts +0 -41
- package/tests/compose.test.ts +0 -209
- package/tests/computed.test.ts +0 -867
- package/tests/devtools.test.ts +0 -1039
- package/tests/integration/persist.integration.test.ts +0 -258
- package/tests/integration/signals.integration.test.ts +0 -309
- package/tests/integration.test.ts +0 -278
- package/tests/persist/adapters/indexedDB.adapter.test.ts +0 -185
- package/tests/persist/adapters/localStorage.adapter.test.ts +0 -105
- package/tests/persist/adapters/memory.adapter.test.ts +0 -112
- package/tests/persist/adapters/sessionStorage.adapter.test.ts +0 -128
- package/tests/persist/debounce.test.ts +0 -121
- package/tests/persist/hydrate.test.ts +0 -120
- package/tests/persist/migrate.test.ts +0 -208
- package/tests/persist/persist.test.ts +0 -357
- package/tests/persist/serialize.test.ts +0 -128
- package/tests/proxy.test.ts +0 -473
- package/tests/registry.test.ts +0 -67
- package/tests/signals/derived.test.ts +0 -244
- package/tests/signals/inference.test.ts +0 -108
- package/tests/signals/signal.test.ts +0 -348
- package/tests/signals/useSignal.test.tsx +0 -275
- package/tests/store.test.ts +0 -482
- package/tests/stress.test.ts +0 -268
- package/tests/sync.test.ts +0 -576
- package/tests/types.test.ts +0 -32
- package/tests/v0.3.test.ts +0 -813
- package/tree-shake-test.js +0 -1
- package/tsconfig.json +0 -15
- package/vitest.config.ts +0 -22
- package/vitest_play.ts +0 -7
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1013,22 +1013,6 @@ counterStore.increment()
|
|
|
1013
1013
|
|
|
1014
1014
|
---
|
|
1015
1015
|
|
|
1016
|
-
## Roadmap
|
|
1017
|
-
|
|
1018
|
-
| Version | Theme | Status |
|
|
1019
|
-
|---|---|---|
|
|
1020
|
-
| v0.1–v0.3 | Core store, React adapter, Immer, Actions | ✅ Shipped |
|
|
1021
|
-
| v0.4 | Async state — createAsync, TTL, SWR, optimistic | ✅ Shipped |
|
|
1022
|
-
| v0.5 | Computed values + Signals | ✅ Shipped |
|
|
1023
|
-
| v0.6 | DevTools — Time-travel, Undo/Redo, Snapshots | ✅ Shipped |
|
|
1024
|
-
| v0.7 | Cross-tab sync via BroadcastChannel | ✅ Shipped |
|
|
1025
|
-
| v1.0 | Stable API, polished README, StackBlitz demo | ✅ Shipped |
|
|
1026
|
-
| v1.1 | Purpose-built DevTools browser extension | 📋 Planned |
|
|
1027
|
-
| v1.2 | Full docs site (Docusaurus) | 📋 Planned |
|
|
1028
|
-
| v1.3 | Middleware system | 📋 Planned |
|
|
1029
|
-
|
|
1030
|
-
---
|
|
1031
|
-
|
|
1032
1016
|
## License
|
|
1033
1017
|
|
|
1034
1018
|
MIT © 2026 Storve
|
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";exports.indexedDBAdapter=function(e="storve-persist"){const n="keyval",t="undefined"==typeof indexedDB;let o=null;function r(){return t?Promise.resolve(null):(null!==o||(o=new Promise(t=>{try{const o=indexedDB.open(e,1);o.onupgradeneeded=()=>{const e=o.result;e.objectStoreNames.contains(n)||e.createObjectStore(n)},o.onsuccess=()=>{t(o.result)},o.onerror=()=>{console.warn(`[storve] Failed to open IndexedDB "${e}"`),t(null)}}catch(n){console.warn(`[storve] Exception opening IndexedDB "${e}":`,n),t(null)}})),o)}return{async getItem(e){const t=await r();return null===t?null:new Promise(o=>{try{const r=t.transaction(n,"readonly"),s=r.objectStore(n).get(e);s.onsuccess=()=>{const e=s.result;o("string"==typeof e?e:null)},s.onerror=()=>{o(null)}}catch{o(null)}})},async setItem(e,t){const o=await r();if(null!==o)return new Promise(r=>{try{const s=o.transaction(n,"readwrite"),c=s.objectStore(n).put(t,e);c.onsuccess=()=>r(),c.onerror=()=>r()}catch{r()}})},async removeItem(e){const t=await r();if(null!==t)return new Promise(o=>{try{const r=t.transaction(n,"readwrite"),s=r.objectStore(n).delete(e);s.onsuccess=()=>o(),s.onerror=()=>o()}catch{o()}})}}};
|
|
2
|
-
//# sourceMappingURL=indexedDB.cjs.map
|
|
@@ -1,2 +1 @@
|
|
|
1
1
|
function e(e="storve-persist"){const n="keyval",t="undefined"==typeof indexedDB;let o=null;function r(){return t?Promise.resolve(null):(null!==o||(o=new Promise(t=>{try{const o=indexedDB.open(e,1);o.onupgradeneeded=()=>{const e=o.result;e.objectStoreNames.contains(n)||e.createObjectStore(n)},o.onsuccess=()=>{t(o.result)},o.onerror=()=>{console.warn(`[storve] Failed to open IndexedDB "${e}"`),t(null)}}catch(n){console.warn(`[storve] Exception opening IndexedDB "${e}":`,n),t(null)}})),o)}return{async getItem(e){const t=await r();return null===t?null:new Promise(o=>{try{const r=t.transaction(n,"readonly"),s=r.objectStore(n).get(e);s.onsuccess=()=>{const e=s.result;o("string"==typeof e?e:null)},s.onerror=()=>{o(null)}}catch{o(null)}})},async setItem(e,t){const o=await r();if(null!==o)return new Promise(r=>{try{const s=o.transaction(n,"readwrite"),c=s.objectStore(n).put(t,e);c.onsuccess=()=>r(),c.onerror=()=>r()}catch{r()}})},async removeItem(e){const t=await r();if(null!==t)return new Promise(o=>{try{const r=t.transaction(n,"readwrite"),s=r.objectStore(n).delete(e);s.onsuccess=()=>o(),s.onerror=()=>o()}catch{o()}})}}}export{e as indexedDBAdapter};
|
|
2
|
-
//# sourceMappingURL=indexedDB.mjs.map
|
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";exports.localStorageAdapter=function(){const e="undefined"==typeof window;return{getItem:t=>e?null:window.localStorage.getItem(t),setItem(t,o){e||window.localStorage.setItem(t,o)},removeItem(t){e||window.localStorage.removeItem(t)}}};
|
|
2
|
-
//# sourceMappingURL=localStorage.cjs.map
|
|
@@ -1,2 +1 @@
|
|
|
1
1
|
function e(){const e="undefined"==typeof window;return{getItem:t=>e?null:window.localStorage.getItem(t),setItem(t,o){e||window.localStorage.setItem(t,o)},removeItem(t){e||window.localStorage.removeItem(t)}}}export{e as localStorageAdapter};
|
|
2
|
-
//# sourceMappingURL=localStorage.mjs.map
|
package/dist/adapters/memory.cjs
CHANGED
package/dist/adapters/memory.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";exports.sessionStorageAdapter=function(){const e="undefined"==typeof window;return{getItem:t=>e?null:window.sessionStorage.getItem(t),setItem(t,o){e||window.sessionStorage.setItem(t,o)},removeItem(t){e||window.sessionStorage.removeItem(t)}}};
|
|
2
|
-
//# sourceMappingURL=sessionStorage.cjs.map
|
|
@@ -1,2 +1 @@
|
|
|
1
1
|
function e(){const e="undefined"==typeof window;return{getItem:t=>e?null:window.sessionStorage.getItem(t),setItem(t,o){e||window.sessionStorage.setItem(t,o)},removeItem(t){e||window.sessionStorage.removeItem(t)}}}export{e as sessionStorageAdapter};
|
|
2
|
-
//# sourceMappingURL=sessionStorage.mjs.map
|
package/dist/async-entry.d.ts
CHANGED
package/dist/async.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";var t=require("./registry-qtr1UpFU.js");const s="__rf_async";class i{fn;options;onUpdate;lastRequestId=0;lastArgs=[];cache=new Map;status="idle";data=null;error=null;previousData=null;previousStatus="idle";hasPrevious=!1;lastState=null;stableRefetch=()=>this.refetch();constructor(t,s,i){this.fn=t,this.options=s,this.onUpdate=i}getState(){return this.lastState||(this.lastState={data:this.data,error:this.error,status:this.status,loading:"loading"===this.status,refetch:this.stableRefetch}),this.lastState}async fetch(...t){let s,i=t;if(t.length>0){const e=t[t.length-1];e&&"object"==typeof e&&"optimistic"in e&&(s=e,i=t.slice(0,-1))}const e=Date.now(),{ttl:a=0,staleWhileRevalidate:n=!1}=this.options,r=JSON.stringify(i),h=this.cache.get(r);let o=!1;if(s?.optimistic)this.previousData=this.data,this.previousStatus=this.status,this.hasPrevious=!0,this.data=s.optimistic.data,this.status=s.optimistic.status||"success",this.lastArgs=i,this.notify(),o=!0;else{if(a>0&&h&&e<h.expiresAt&&"success"===this.status)return void(this.data!==h.data&&(this.data=h.data,this.lastArgs=i,this.notify()));if(a>0&&h&&e>=h.expiresAt&&"success"===this.status&&n)return this.data=h.data,this.lastArgs=i,this.runFetch(i,!0)}return this.lastArgs=i,this.runFetch(i,o)}async refetch(){return this.runFetch(this.lastArgs,!1)}invalidate(){this.cache.clear()}async runFetch(t,s){const i=++this.lastRequestId;s||(this.status="loading",this.notify());try{const s=await this.fn(...t);if(i!==this.lastRequestId)return;this.data=s,this.error=null,this.status="success",this.hasPrevious=!1;const e=this.options.ttl||0;if(e>0){const i=JSON.stringify(t);this.cache.set(i,{data:s,expiresAt:Date.now()+e})}}catch(t){if(i!==this.lastRequestId)return;this.error=t instanceof Error?t.message:String(t),this.hasPrevious?(this.data=this.previousData,this.status=this.previousStatus,this.hasPrevious=!1):(s||(this.data=null),this.status="error")}this.notify()}notify(){this.lastState=null,this.onUpdate(this.getState())}}t.registerExtension({key:"async",order:0,processDefinition:t=>{const i={},e=[];for(const a of Object.keys(t)){const n=t[a];if(n&&"object"==typeof n&&s in n){const t=n;e.push({key:a,init:t.init})}else i[a]=n}return{state:i,asyncInits:e}},extendStore:t=>{const s=t.engines;return{fetch:async(t,...i)=>{if(!s.has(t))throw new Error(`Storve: no async key "${t}" found in store`);const e=s.get(t);e&&await e.fetch(...i)},refetch:async t=>{const i=s.get(t);i&&await i.refetch()},invalidate:t=>{const i=s.get(t);i&&i.invalidate()},invalidateAll:()=>{s.forEach(t=>t.invalidate())},getAsyncState:t=>{const i=s.get(t);return i?i.getState():void 0}}}}),exports.createAsync=function(t,e={}){return{[s]:!0,init:s=>new i(t,e,s)}};
|
|
2
|
-
//# sourceMappingURL=async.cjs.map
|
package/dist/async.d.ts
CHANGED
package/dist/async.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
import{r as t}from"./registry-zaKZ1P-s.js";const s="__rf_async";function i(t,i={}){return{[s]:!0,init:s=>new e(t,i,s)}}class e{fn;options;onUpdate;lastRequestId=0;lastArgs=[];cache=new Map;status="idle";data=null;error=null;previousData=null;previousStatus="idle";hasPrevious=!1;lastState=null;stableRefetch=()=>this.refetch();constructor(t,s,i){this.fn=t,this.options=s,this.onUpdate=i}getState(){return this.lastState||(this.lastState={data:this.data,error:this.error,status:this.status,loading:"loading"===this.status,refetch:this.stableRefetch}),this.lastState}async fetch(...t){let s,i=t;if(t.length>0){const e=t[t.length-1];e&&"object"==typeof e&&"optimistic"in e&&(s=e,i=t.slice(0,-1))}const e=Date.now(),{ttl:a=0,staleWhileRevalidate:n=!1}=this.options,r=JSON.stringify(i),h=this.cache.get(r);let o=!1;if(s?.optimistic)this.previousData=this.data,this.previousStatus=this.status,this.hasPrevious=!0,this.data=s.optimistic.data,this.status=s.optimistic.status||"success",this.lastArgs=i,this.notify(),o=!0;else{if(a>0&&h&&e<h.expiresAt&&"success"===this.status)return void(this.data!==h.data&&(this.data=h.data,this.lastArgs=i,this.notify()));if(a>0&&h&&e>=h.expiresAt&&"success"===this.status&&n)return this.data=h.data,this.lastArgs=i,this.runFetch(i,!0)}return this.lastArgs=i,this.runFetch(i,o)}async refetch(){return this.runFetch(this.lastArgs,!1)}invalidate(){this.cache.clear()}async runFetch(t,s){const i=++this.lastRequestId;s||(this.status="loading",this.notify());try{const s=await this.fn(...t);if(i!==this.lastRequestId)return;this.data=s,this.error=null,this.status="success",this.hasPrevious=!1;const e=this.options.ttl||0;if(e>0){const i=JSON.stringify(t);this.cache.set(i,{data:s,expiresAt:Date.now()+e})}}catch(t){if(i!==this.lastRequestId)return;this.error=t instanceof Error?t.message:String(t),this.hasPrevious?(this.data=this.previousData,this.status=this.previousStatus,this.hasPrevious=!1):(s||(this.data=null),this.status="error")}this.notify()}notify(){this.lastState=null,this.onUpdate(this.getState())}}t({key:"async",order:0,processDefinition:t=>{const i={},e=[];for(const a of Object.keys(t)){const n=t[a];if(n&&"object"==typeof n&&s in n){const t=n;e.push({key:a,init:t.init})}else i[a]=n}return{state:i,asyncInits:e}},extendStore:t=>{const s=t.engines;return{fetch:async(t,...i)=>{if(!s.has(t))throw new Error(`Storve: no async key "${t}" found in store`);const e=s.get(t);e&&await e.fetch(...i)},refetch:async t=>{const i=s.get(t);i&&await i.refetch()},invalidate:t=>{const i=s.get(t);i&&i.invalidate()},invalidateAll:()=>{s.forEach(t=>t.invalidate())},getAsyncState:t=>{const i=s.get(t);return i?i.getState():void 0}}}});export{i as createAsync};
|
|
2
|
-
//# sourceMappingURL=async.mjs.map
|
package/dist/batch.d.ts
CHANGED
package/dist/compose.d.ts
CHANGED
|
@@ -4,4 +4,3 @@ export declare function compose<D extends object, S extends Store<D>, R1>(store:
|
|
|
4
4
|
export declare function compose<D extends object, S extends Store<D>, R1, R2>(store: S, f1: (store: S) => R1, f2: (store: R1) => R2): R2;
|
|
5
5
|
export declare function compose<D extends object, S extends Store<D>, R1, R2, R3>(store: S, f1: (store: S) => R1, f2: (store: R1) => R2, f3: (store: R2) => R3): R3;
|
|
6
6
|
export declare function compose<D extends object>(store: Store<D>, ...enhancers: Array<(store: unknown) => unknown>): unknown;
|
|
7
|
-
//# sourceMappingURL=compose.d.ts.map
|
package/dist/computed-entry.d.ts
CHANGED
package/dist/computed.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";var e=require("./registry-qtr1UpFU.js");const t="__rf_computed";function n(e,t){const n=new Set;return{result:t(new Proxy(e,{get:(e,t)=>(n.add(t),e[t])})),deps:n}}e.registerExtension({key:"computed",order:1,processDefinition:e=>{const o={...e},s=new Set,r=new Map;for(const c of Object.keys(e)){const f=e[c];if(f&&"object"==typeof f&&t in f){const e=f;s.add(c),delete o[c];const{result:t,deps:d}=n(o,e.fn);r.set(c,{fn:e.fn,value:t,deps:d,dirty:!1})}}const c=Array.from(s);let f=[];if(c.length>0){const e=e=>r.get(e).deps;!function(e,t){const n=new Set(e),o=[],s=new Set;function r(e){if(o.includes(e))throw new Error(`Storve: circular dependency in computed values: ${[...o,e].join(" → ")}`);if(!s.has(e)){o.push(e);for(const o of t(e))n.has(o)&&r(o);o.pop(),s.add(e)}}for(const t of e)s.has(t)||r(t)}(c,e),f=function(e,t){const n=[],o=new Set,s=new Set(e);function r(e){if(!o.has(e)){o.add(e);for(const n of t(e))s.has(n)&&r(n);n.push(e)}}for(const t of e)r(t);return n}(c,e);for(const e of f){const t=r.get(e),{result:s,deps:c}=n(o,t.fn);t.value=s,t.deps=c,o[e]=s}}return{state:o,readOnlyKeys:s,onStateChanged:e=>{return t=e.changedKeys,o=e.getState,s=e.setComputed,f.forEach(e=>{const n=r.get(e);for(const e of n.deps)if(t.has(e)){n.dirty=!0;break}}),void f.forEach(e=>{const t=r.get(e);if(!t.dirty)return;const c=o(),{result:d,deps:i}=n(c,t.fn);t.value=d,t.deps=i,t.dirty=!1,s(e,d),f.forEach(t=>{t!==e&&r.get(t).deps.has(e)&&(r.get(t).dirty=!0)})});var t,o,s}}}}),exports.COMPUTED_MARKER=t,exports.computed=function(e){return{[t]:!0,fn:e}};
|
|
2
|
-
//# sourceMappingURL=computed.cjs.map
|
package/dist/computed.d.ts
CHANGED
package/dist/computed.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
import{r as e}from"./registry-zaKZ1P-s.js";const t="__rf_computed";function n(e){return{[t]:!0,fn:e}}function o(e,t){const n=new Set;return{result:t(new Proxy(e,{get:(e,t)=>(n.add(t),e[t])})),deps:n}}e({key:"computed",order:1,processDefinition:e=>{const n={...e},s=new Set,r=new Map;for(const c of Object.keys(e)){const f=e[c];if(f&&"object"==typeof f&&t in f){const e=f;s.add(c),delete n[c];const{result:t,deps:d}=o(n,e.fn);r.set(c,{fn:e.fn,value:t,deps:d,dirty:!1})}}const c=Array.from(s);let f=[];if(c.length>0){const e=e=>r.get(e).deps;!function(e,t){const n=new Set(e),o=[],s=new Set;function r(e){if(o.includes(e))throw new Error(`Storve: circular dependency in computed values: ${[...o,e].join(" → ")}`);if(!s.has(e)){o.push(e);for(const o of t(e))n.has(o)&&r(o);o.pop(),s.add(e)}}for(const t of e)s.has(t)||r(t)}(c,e),f=function(e,t){const n=[],o=new Set,s=new Set(e);function r(e){if(!o.has(e)){o.add(e);for(const n of t(e))s.has(n)&&r(n);n.push(e)}}for(const t of e)r(t);return n}(c,e);for(const e of f){const t=r.get(e),{result:s,deps:c}=o(n,t.fn);t.value=s,t.deps=c,n[e]=s}}return{state:n,readOnlyKeys:s,onStateChanged:e=>{return t=e.changedKeys,n=e.getState,s=e.setComputed,f.forEach(e=>{const n=r.get(e);for(const e of n.deps)if(t.has(e)){n.dirty=!0;break}}),void f.forEach(e=>{const t=r.get(e);if(!t.dirty)return;const c=n(),{result:d,deps:a}=o(c,t.fn);t.value=d,t.deps=a,t.dirty=!1,s(e,d),f.forEach(t=>{t!==e&&r.get(t).deps.has(e)&&(r.get(t).dirty=!0)})});var t,n,s}}}});export{t as COMPUTED_MARKER,n as computed};
|
|
2
|
-
//# sourceMappingURL=computed.mjs.map
|
package/dist/devtools/index.d.ts
CHANGED
package/dist/devtools.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";var t=require("./registry-qtr1UpFU.js");function e(t=50){return{entries:[],cursor:-1,capacity:t}}function n(t,e,n){const s={state:e,timestamp:Date.now(),actionName:n};let r=[...t.entries.slice(0,t.cursor+1),s],a=r.length-1;return r.length>t.capacity&&(r=r.slice(r.length-t.capacity),a=r.length-1),{...t,entries:r,cursor:a}}const s=new WeakMap;t.registerExtension({key:"devtools",processDefinition:t=>{const e=s.get(t);return e&&e.enabled,{state:{}}},extendStore:t=>{const{store:r,definition:a}=t,o=s.get(a);if(!o||!1===o.enabled)return{};const i=r.getState(),u={buffer:e(o.maxHistory||50),snapshots:new Map,initialState:i,_isInternalUpdate:!1,_lastActionName:null,_applySnapshot:t=>{u._isInternalUpdate=!0,r.setState(t),u._isInternalUpdate=!1}},c=r;c.__devtools=u;let f=!0;r.subscribe(()=>{if(u._isInternalUpdate)return;const t=r.getState();if(f&&null===u._lastActionName){const e=u.initialState,n=t,s=Object.keys(e);if(s.length===Object.keys(n).length&&s.every(t=>n[t]===e[t]))return void(f=!1)}f=!1;const e=u._lastActionName??"setState";u.buffer=n(u.buffer,t,e),u._lastActionName=null});const l=r.actions;return Object.keys(l).forEach(t=>{const e=l[t],n=(...n)=>(u._lastActionName=t,e(...n));l[t]=n;const s=r;s[t]===e&&(s[t]=n)}),"undefined"!=typeof window&&function(t,e){if("undefined"==typeof window)return()=>{};const n=window.__REDUX_DEVTOOLS_EXTENSION__;if(!n)return()=>{};const s=n.connect({name:`Storve | ${e}`,maxAge:t.__devtools.buffer.capacity});s.init(t.getState());const r=t.subscribe(e=>{t.__devtools._isInternalUpdate||s.send({type:t.__devtools._lastActionName??"setState"},e)}),a=s.subscribe(e=>{"DISPATCH"===e.type&&("JUMP_TO_STATE"===e.payload?.type||"JUMP_TO_ACTION"===e.payload?.type?e.state&&t.__devtools._applySnapshot(JSON.parse(e.state)):"RESET"===e.payload?.type&&t.__devtools._applySnapshot(t.__devtools.initialState))})}(c,o.name),{undo:()=>{const{buffer:t,state:e}=function(t){if(t.cursor>0){const e=t.cursor-1;return{buffer:{...t,cursor:e},state:t.entries[e].state}}return{buffer:t,state:null}}(u.buffer);e&&(u.buffer=t,u._applySnapshot(e))},redo:()=>{const{buffer:t,state:e}=function(t){if(t.cursor<t.entries.length-1){const e=t.cursor+1;return{buffer:{...t,cursor:e},state:t.entries[e].state}}return{buffer:t,state:null}}(u.buffer);e&&(u.buffer=t,u._applySnapshot(e))},get canUndo(){return u.buffer.cursor>0},get canRedo(){return(t=u.buffer).cursor<t.entries.length-1;var t},snapshot:t=>{u.snapshots=function(t,e,n){const s=new Map(t);return s.set(e,{state:n,timestamp:Date.now()}),s}(u.snapshots,t,r.getState()),u._isInternalUpdate=!0,r.setState({}),u._isInternalUpdate=!1},restore:t=>{const e=function(t,e){return t.get(e)||null}(u.snapshots,t);if(!e)throw new Error(`Storve DevTools: Snapshot "${t}" not found.`);u._applySnapshot(e.state),u.buffer=n(u.buffer,e.state,`restore('${t}')`)},deleteSnapshot:t=>{u.snapshots=function(t,e){const n=new Map(t);return n.delete(e),n}(u.snapshots,t),u._isInternalUpdate=!0,r.setState({}),u._isInternalUpdate=!1},clearHistory:()=>{u.buffer=e(u.buffer.capacity),u._isInternalUpdate=!0,r.setState({}),u._isInternalUpdate=!1},get history(){return[...u.buffer.entries]},get snapshots(){return t=u.snapshots,Array.from(t.keys());var t}}}}),exports.withDevtools=function(t,e){return s.set(t,e),t};
|
|
2
|
-
//# sourceMappingURL=devtools.cjs.map
|
package/dist/devtools.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
import{r as t}from"./registry-zaKZ1P-s.js";function e(t=50){return{entries:[],cursor:-1,capacity:t}}function n(t,e,n){const s={state:e,timestamp:Date.now(),actionName:n};let r=[...t.entries.slice(0,t.cursor+1),s],a=r.length-1;return r.length>t.capacity&&(r=r.slice(r.length-t.capacity),a=r.length-1),{...t,entries:r,cursor:a}}const s=new WeakMap;function r(t,e){return s.set(t,e),t}t({key:"devtools",processDefinition:t=>{const e=s.get(t);return e&&e.enabled,{state:{}}},extendStore:t=>{const{store:r,definition:a}=t,o=s.get(a);if(!o||!1===o.enabled)return{};const i=r.getState(),u={buffer:e(o.maxHistory||50),snapshots:new Map,initialState:i,_isInternalUpdate:!1,_lastActionName:null,_applySnapshot:t=>{u._isInternalUpdate=!0,r.setState(t),u._isInternalUpdate=!1}},c=r;c.__devtools=u;let f=!0;r.subscribe(()=>{if(u._isInternalUpdate)return;const t=r.getState();if(f&&null===u._lastActionName){const e=u.initialState,n=t,s=Object.keys(e);if(s.length===Object.keys(n).length&&s.every(t=>n[t]===e[t]))return void(f=!1)}f=!1;const e=u._lastActionName??"setState";u.buffer=n(u.buffer,t,e),u._lastActionName=null});const l=r.actions;return Object.keys(l).forEach(t=>{const e=l[t],n=(...n)=>(u._lastActionName=t,e(...n));l[t]=n;const s=r;s[t]===e&&(s[t]=n)}),"undefined"!=typeof window&&function(t,e){if("undefined"==typeof window)return()=>{};const n=window.__REDUX_DEVTOOLS_EXTENSION__;if(!n)return()=>{};const s=n.connect({name:`Storve | ${e}`,maxAge:t.__devtools.buffer.capacity});s.init(t.getState());const r=t.subscribe(e=>{t.__devtools._isInternalUpdate||s.send({type:t.__devtools._lastActionName??"setState"},e)}),a=s.subscribe(e=>{"DISPATCH"===e.type&&("JUMP_TO_STATE"===e.payload?.type||"JUMP_TO_ACTION"===e.payload?.type?e.state&&t.__devtools._applySnapshot(JSON.parse(e.state)):"RESET"===e.payload?.type&&t.__devtools._applySnapshot(t.__devtools.initialState))})}(c,o.name),{undo:()=>{const{buffer:t,state:e}=function(t){if(t.cursor>0){const e=t.cursor-1;return{buffer:{...t,cursor:e},state:t.entries[e].state}}return{buffer:t,state:null}}(u.buffer);e&&(u.buffer=t,u._applySnapshot(e))},redo:()=>{const{buffer:t,state:e}=function(t){if(t.cursor<t.entries.length-1){const e=t.cursor+1;return{buffer:{...t,cursor:e},state:t.entries[e].state}}return{buffer:t,state:null}}(u.buffer);e&&(u.buffer=t,u._applySnapshot(e))},get canUndo(){return u.buffer.cursor>0},get canRedo(){return(t=u.buffer).cursor<t.entries.length-1;var t},snapshot:t=>{u.snapshots=function(t,e,n){const s=new Map(t);return s.set(e,{state:n,timestamp:Date.now()}),s}(u.snapshots,t,r.getState()),u._isInternalUpdate=!0,r.setState({}),u._isInternalUpdate=!1},restore:t=>{const e=function(t,e){return t.get(e)||null}(u.snapshots,t);if(!e)throw new Error(`Storve DevTools: Snapshot "${t}" not found.`);u._applySnapshot(e.state),u.buffer=n(u.buffer,e.state,`restore('${t}')`)},deleteSnapshot:t=>{u.snapshots=function(t,e){const n=new Map(t);return n.delete(e),n}(u.snapshots,t),u._isInternalUpdate=!0,r.setState({}),u._isInternalUpdate=!1},clearHistory:()=>{u.buffer=e(u.buffer.capacity),u._isInternalUpdate=!0,r.setState({}),u._isInternalUpdate=!1},get history(){return[...u.buffer.entries]},get snapshots(){return t=u.snapshots,Array.from(t.keys());var t}}}});export{r as withDevtools};
|
|
2
|
-
//# sourceMappingURL=devtools.mjs.map
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";var e=require("immer"),t=require("./registry-qtr1UpFU.js");const n=new WeakMap,r=new WeakMap;let o=!1;function s(e){if(null===e||"object"!=typeof e)return!1;return Object.getPrototypeOf(e)===Object.prototype||Array.isArray(e)}function c(e,t){if(!s(e))return e;if(n.has(e))return n.get(e);if(r.has(e))return e;const i=new Proxy(e,{get(e,r,c){if(Array.isArray(e)&&"string"==typeof r&&["push","pop","shift","unshift","splice","sort","reverse"].includes(r))return(...n)=>{const s=o;o=!0;const i=Reflect.get(e,r,c),a=Reflect.apply(i,c,n);return o=s,o||t(),a};const i=Reflect.get(e,r,c);return s(i)&&n.has(i)?n.get(i):i},set(e,n,i,a){const f=r.has(i)?r.get(i):i;s(f)&&c(f,t);const l=Reflect.set(e,n,f,a);return o||t(),l},deleteProperty(e,n){const r=Reflect.deleteProperty(e,n);return o||t(),r}});n.set(e,i),r.set(i,e);for(const n in e)if(Object.prototype.hasOwnProperty.call(e,n)){const r=e[n];s(r)&&c(r,t)}return i}let i=0;const a=new Set;function f(){return i>0}exports.batch=function(e){i++;try{e()}finally{i--,0===i&&a.forEach(e=>e())}},exports.compose=function(e,...t){if(0===t.length)return e;let n=e;for(let e=0;e<t.length;e++)n=t[e](n);return n},exports.createStore=function(n,r={}){const{actions:o={},...s}=n;let i={...s};const l=[],u=new Set,y=[];for(const e of t.getExtensions())if(e.processDefinition){const t=e.processDefinition(i);i={...i,...t.state},t.asyncInits&&l.push(...t.asyncInits),t.readOnlyKeys&&t.readOnlyKeys.forEach(e=>u.add(e)),t.onStateChanged&&y.push(t.onStateChanged)}const p={current:null},d=new Map;for(const{key:e,init:t}of l){const n=t(t=>{p.current?.({[e]:t})});d.set(e,n),i[e]=n.getState()}const h=i,g=new Set;let S=h,w=0,O=!1,b=null,j=new Set,E=null,x=null;const P=()=>{w>0||f()?O=!0:(O=!1,g.forEach(e=>e(S)))},k=e=>{const t=(e,t)=>{S[e]=t};for(const n of y)n({changedKeys:e,getState:()=>S,setComputed:t,store:A})},m=c(h,P),v=t=>{let n;if(n="function"==typeof t?r.immer?e.produce(S,t):{...S,...t(S)}:{...S,...t},n===S)return;const o={...n};u.forEach(e=>delete o[e]);const s=S,c=new Set(Object.keys(o).filter(e=>s[e]!==o[e]));S={...S,...o},w>0||f()?(c.forEach(e=>j.add(e)),O=!0):k(c),E=null,x=null,w++;try{for(const e in S)Object.prototype.hasOwnProperty.call(S,e)&&S[e]!==s[e]&&(m[e]=S[e])}finally{w--}w>0?O=!0:P()};p.current=v;const A={getState:()=>{if(null!==E&&x===S)return E;const e={...S};return E=e,x=S,e},setState:v,subscribe:e=>{var t;return g.add(e),1===g.size&&(t=()=>{O&&(O=!1,k(j),j=new Set,P())},a.add(t),b=()=>{a.delete(t)},O&&(O=!1,k(j),j=new Set,P())),()=>{g.delete(e),0===g.size&&(b?.(),b=null)}},batch:e=>{w++;try{e()}finally{w--,0===w&&O&&(O=!1,k(j),j=new Set,P())}},actions:{},fetch:async e=>{throw new Error(`Storve: no async key "${e}" found in store. Import "storve/async" to use createAsync.`)},refetch:async()=>{},invalidate:()=>{},invalidateAll:()=>{},getAsyncState:()=>{}};for(const e of t.getExtensions())if(e.extendStore){const t=e.extendStore({engines:d,store:A,definition:n});Object.defineProperties(A,Object.getOwnPropertyDescriptors(t))}k(new Set(Object.keys(S)));const R={};return Object.keys(o).forEach(e=>{R[e]=(...t)=>o[e](...t)}),Object.assign(A,R),A.actions=R,A};
|
|
2
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,3 @@ export { createStore } from './store';
|
|
|
2
2
|
export { batch } from './batch';
|
|
3
3
|
export { compose } from './compose';
|
|
4
4
|
export type { Store, StoreDefinition, Listener, Unsubscribe, StoreOptions, StoreState, StoreActions, AsyncState, AsyncOptions, AsyncStatus, ComputedValue, WritableStoreState, ComputedKeys } from './types';
|
|
5
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
import{produce as t}from"immer";import{g as e}from"./registry-zaKZ1P-s.js";const n=new WeakMap,r=new WeakMap;let o=!1;function s(t){if(null===t||"object"!=typeof t)return!1;return Object.getPrototypeOf(t)===Object.prototype||Array.isArray(t)}function c(t,e){if(!s(t))return t;if(n.has(t))return n.get(t);if(r.has(t))return t;const i=new Proxy(t,{get(t,r,c){if(Array.isArray(t)&&"string"==typeof r&&["push","pop","shift","unshift","splice","sort","reverse"].includes(r))return(...n)=>{const s=o;o=!0;const i=Reflect.get(t,r,c),a=Reflect.apply(i,c,n);return o=s,o||e(),a};const i=Reflect.get(t,r,c);return s(i)&&n.has(i)?n.get(i):i},set(t,n,i,a){const f=r.has(i)?r.get(i):i;s(f)&&c(f,e);const l=Reflect.set(t,n,f,a);return o||e(),l},deleteProperty(t,n){const r=Reflect.deleteProperty(t,n);return o||e(),r}});n.set(t,i),r.set(i,t);for(const n in t)if(Object.prototype.hasOwnProperty.call(t,n)){const r=t[n];s(r)&&c(r,e)}return i}let i=0;const a=new Set;function f(t){i++;try{t()}finally{i--,0===i&&a.forEach(t=>t())}}function l(){return i>0}function u(n,r={}){const{actions:o={},...s}=n;let i={...s};const f=[],u=new Set,y=[];for(const t of e())if(t.processDefinition){const e=t.processDefinition(i);i={...i,...e.state},e.asyncInits&&f.push(...e.asyncInits),e.readOnlyKeys&&e.readOnlyKeys.forEach(t=>u.add(t)),e.onStateChanged&&y.push(e.onStateChanged)}const p={current:null},d=new Map;for(const{key:t,init:e}of f){const n=e(e=>{p.current?.({[t]:e})});d.set(t,n),i[t]=n.getState()}const h=i,g=new Set;let S=h,w=0,O=!1,b=null,j=new Set,m=null,P=null;const k=()=>{w>0||l()?O=!0:(O=!1,g.forEach(t=>t(S)))},A=t=>{const e=(t,e)=>{S[t]=e};for(const n of y)n({changedKeys:t,getState:()=>S,setComputed:e,store:R})},E=c(h,k),v=e=>{let n;if(n="function"==typeof e?r.immer?t(S,e):{...S,...e(S)}:{...S,...e},n===S)return;const o={...n};u.forEach(t=>delete o[t]);const s=S,c=new Set(Object.keys(o).filter(t=>s[t]!==o[t]));S={...S,...o},w>0||l()?(c.forEach(t=>j.add(t)),O=!0):A(c),m=null,P=null,w++;try{for(const t in S)Object.prototype.hasOwnProperty.call(S,t)&&S[t]!==s[t]&&(E[t]=S[t])}finally{w--}w>0?O=!0:k()};p.current=v;const R={getState:()=>{if(null!==m&&P===S)return m;const t={...S};return m=t,P=S,t},setState:v,subscribe:t=>{var e;return g.add(t),1===g.size&&(e=()=>{O&&(O=!1,A(j),j=new Set,k())},a.add(e),b=()=>{a.delete(e)},O&&(O=!1,A(j),j=new Set,k())),()=>{g.delete(t),0===g.size&&(b?.(),b=null)}},batch:t=>{w++;try{t()}finally{w--,0===w&&O&&(O=!1,A(j),j=new Set,k())}},actions:{},fetch:async t=>{throw new Error(`Storve: no async key "${t}" found in store. Import "storve/async" to use createAsync.`)},refetch:async()=>{},invalidate:()=>{},invalidateAll:()=>{},getAsyncState:()=>{}};for(const t of e())if(t.extendStore){const e=t.extendStore({engines:d,store:R,definition:n});Object.defineProperties(R,Object.getOwnPropertyDescriptors(e))}A(new Set(Object.keys(S)));const x={};return Object.keys(o).forEach(t=>{x[t]=(...e)=>o[t](...e)}),Object.assign(R,x),R.actions=x,R}function y(t,...e){if(0===e.length)return t;let n=t;for(let t=0;t<e.length;t++)n=e[t](n);return n}export{f as batch,y as compose,u as createStore};
|
|
2
|
-
//# sourceMappingURL=index.mjs.map
|
|
@@ -12,4 +12,3 @@ import type { PersistAdapter } from './index.js';
|
|
|
12
12
|
* @returns {Promise<Partial<T>>} A promise that resolves to the hydrated partial state (or an empty object).
|
|
13
13
|
*/
|
|
14
14
|
export declare function hydrate<T extends object>(adapter: PersistAdapter, key: string, currentState: T, version: number, migrate?: (persisted: Partial<T>, version: number) => Partial<T>): Promise<Partial<T>>;
|
|
15
|
-
//# sourceMappingURL=hydrate.d.ts.map
|
package/dist/persist/index.d.ts
CHANGED
|
@@ -31,4 +31,3 @@ export declare function withPersist<D extends object>(store: Store<D>, options:
|
|
|
31
31
|
export declare function withPersist<D extends object>(options: PersistOptions<StoreState<D>>): (store: Store<D>) => Store<D> & {
|
|
32
32
|
hydrated: Promise<void>;
|
|
33
33
|
};
|
|
34
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/persist.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";function t(t,e){if(void 0===e||0===e.length)return{...t};const r={};for(let n=0;n<e.length;n++){const o=e[n];o in t&&(r[o]=t[o])}return r}function e(t){try{return JSON.stringify(t)}catch(t){throw new Error(`[storve] Failed to serialize state to JSON: ${t instanceof Error?t.message:String(t)}`)}}async function r(t,e,r,n,o){const i=await t.getItem(e);if(!i)return{};let s;try{s=function(t){if(!t)throw new Error("[storve] Cannot parse empty or null/undefined JSON string.");try{return JSON.parse(t)}catch(t){throw new Error(`[storve] Failed to parse JSON state: ${t instanceof Error?t.message:String(t)}`)}}(i)}catch(t){return console.warn(`[storve] Hydration failed for key "${e}":`,t),{}}const c=void 0!==s.__version?s.__version:0;let a;if(c!==n){if(void 0===o)return console.warn(`Storve: persisted state version mismatch (stored: ${c}, expected: ${n}). No migrate function provided — falling back to default state.`),{};a=o(s,c)}else a=s;const u={...a};return delete u.__version,u}function n(t){return null!==t&&"object"==typeof t&&"adapter"in t&&"key"in t}function o(n,o){let i;const s=new Promise(t=>{i=t}),c=void 0!==o.version?o.version:1,a=void 0!==o.debounce?o.debounce:100;r(o.adapter,o.key,n.getState(),c,o.migrate).then(t=>{n.setState(t),i()}).catch(t=>{console.warn(`[storve] withPersist hydrate error for key "${o.key}":`,t),i()});const u=function(t,e){let r;return function(...n){0!==e?(void 0!==r&&clearTimeout(r),r=setTimeout(()=>{t(...n)},e)):t(...n)}}(t=>{const e=o.adapter.setItem(o.key,t);e&&"function"==typeof e.catch&&e.catch(t=>{console.warn(`[storve] Failed to persist state for key "${o.key}":`,t)})},a);let f=e({...o.pick&&o.pick.length>0?t(n.getState(),o.pick):{...n.getState()},__version:c});return n.subscribe(r=>{const n=e({...o.pick&&o.pick.length>0?t(r,o.pick):{...r},__version:c});n!==f&&(f=n,u(n))}),{...n,hydrated:s}}exports.withPersist=function(t,e){if(void 0!==e&&!n(t))return o(t,e);if(n(t))return e=>o(e,t);throw new Error("[storve] Invalid withPersist arguments")};
|
|
2
|
-
//# sourceMappingURL=persist.cjs.map
|
package/dist/persist.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
function t(t,e){if(void 0===e||0===e.length)return{...t};const r={};for(let n=0;n<e.length;n++){const o=e[n];o in t&&(r[o]=t[o])}return r}function e(t){try{return JSON.stringify(t)}catch(t){throw new Error(`[storve] Failed to serialize state to JSON: ${t instanceof Error?t.message:String(t)}`)}}async function r(t,e,r,n,o){const i=await t.getItem(e);if(!i)return{};let s;try{s=function(t){if(!t)throw new Error("[storve] Cannot parse empty or null/undefined JSON string.");try{return JSON.parse(t)}catch(t){throw new Error(`[storve] Failed to parse JSON state: ${t instanceof Error?t.message:String(t)}`)}}(i)}catch(t){return console.warn(`[storve] Hydration failed for key "${e}":`,t),{}}const a=void 0!==s.__version?s.__version:0;let c;if(a!==n){if(void 0===o)return console.warn(`Storve: persisted state version mismatch (stored: ${a}, expected: ${n}). No migrate function provided — falling back to default state.`),{};c=o(s,a)}else c=s;const u={...c};return delete u.__version,u}function n(t){return null!==t&&"object"==typeof t&&"adapter"in t&&"key"in t}function o(n,o){let i;const s=new Promise(t=>{i=t}),a=void 0!==o.version?o.version:1,c=void 0!==o.debounce?o.debounce:100;r(o.adapter,o.key,n.getState(),a,o.migrate).then(t=>{n.setState(t),i()}).catch(t=>{console.warn(`[storve] withPersist hydrate error for key "${o.key}":`,t),i()});const u=function(t,e){let r;return function(...n){0!==e?(void 0!==r&&clearTimeout(r),r=setTimeout(()=>{t(...n)},e)):t(...n)}}(t=>{const e=o.adapter.setItem(o.key,t);e&&"function"==typeof e.catch&&e.catch(t=>{console.warn(`[storve] Failed to persist state for key "${o.key}":`,t)})},c);let f=e({...o.pick&&o.pick.length>0?t(n.getState(),o.pick):{...n.getState()},__version:a});return n.subscribe(r=>{const n=e({...o.pick&&o.pick.length>0?t(r,o.pick):{...r},__version:a});n!==f&&(f=n,u(n))}),{...n,hydrated:s}}function i(t,e){if(void 0!==e&&!n(t))return o(t,e);if(n(t))return e=>o(e,t);throw new Error("[storve] Invalid withPersist arguments")}export{i as withPersist};
|
|
2
|
-
//# sourceMappingURL=persist.mjs.map
|
package/dist/proxy.d.ts
CHANGED
package/dist/registry.d.ts
CHANGED
|
@@ -16,4 +16,3 @@ export declare function signal<D extends object, K extends keyof StoreState<D>>(
|
|
|
16
16
|
* const doubleSignal = signal(store, 'count', v => v * 2);
|
|
17
17
|
*/
|
|
18
18
|
export declare function signal<D extends object, K extends keyof StoreState<D>, R>(store: Store<D>, key: K, transform: (value: StoreState<D>[K]) => R): Signal<R>;
|
|
19
|
-
//# sourceMappingURL=createSignal.d.ts.map
|
package/dist/signals/index.d.ts
CHANGED
package/dist/signals.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";var e=require("react");exports.signal=function(e,t,r){const n=!!r;return new Proxy({get:()=>{const n=e.getState()[t];return r?r(n):n},set(r){if(n)throw new Error("Storve: cannot call set() on a derived signal. Derived signals are read-only.");const s="function"==typeof r?r(e.getState()[t]):r;e.setState({[t]:s})},subscribe(n){let s=r?r(e.getState()[t]):e.getState()[t];return e.subscribe(()=>{const a=r?r(e.getState()[t]):e.getState()[t];Object.is(s,a)||(s=a,n(a))})},_derived:n},{set:(e,t,r)=>"_derived"===t||Reflect.set(e,t,r)})},exports.useSignal=function(t){return e.useSyncExternalStore(e=>t.subscribe(e),()=>t.get(),()=>t.get())};
|
|
2
|
-
//# sourceMappingURL=signals.cjs.map
|
package/dist/signals.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
import{useSyncExternalStore as t}from"react";function e(t,e,r){const n=!!r;return new Proxy({get:()=>{const n=t.getState()[e];return r?r(n):n},set(r){if(n)throw new Error("Storve: cannot call set() on a derived signal. Derived signals are read-only.");const s="function"==typeof r?r(t.getState()[e]):r;t.setState({[e]:s})},subscribe(n){let s=r?r(t.getState()[e]):t.getState()[e];return t.subscribe(()=>{const o=r?r(t.getState()[e]):t.getState()[e];Object.is(s,o)||(s=o,n(o))})},_derived:n},{set:(t,e,r)=>"_derived"===e||Reflect.set(t,e,r)})}function r(e){return t(t=>e.subscribe(t),()=>e.get(),()=>e.get())}export{e as signal,r as useSignal};
|
|
2
|
-
//# sourceMappingURL=signals.mjs.map
|
package/dist/store.d.ts
CHANGED
|
@@ -9,4 +9,3 @@ import { Store, StoreDefinition, StoreOptions } from './types';
|
|
|
9
9
|
* @returns A generic store instance with getState, setState, subscribe, batch, and actions.
|
|
10
10
|
*/
|
|
11
11
|
export declare function createStore<D extends object>(definition: StoreDefinition<D>, options?: StoreOptions): Store<D>;
|
|
12
|
-
//# sourceMappingURL=store.d.ts.map
|
package/dist/sync/channel.d.ts
CHANGED
package/dist/sync/index.d.ts
CHANGED
package/dist/sync/protocol.d.ts
CHANGED
package/dist/sync/withSync.d.ts
CHANGED
package/dist/sync.cjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
"use strict";var t=require("./registry-qtr1UpFU.js");const e="undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():Math.random().toString(36).substring(2,11),n=Symbol("storve_sync_options");t.registerExtension({key:"sync",extendStore:t=>{const{store:o,definition:a}=t,s=a[n];if(!s||!1===s.enabled)return{};const r=function(t){if("undefined"==typeof window)return null;if("undefined"==typeof BroadcastChannel)return null;try{return new BroadcastChannel(t)}catch{return null}}(s.channel);if(!r)return{};let c=!1,y=!1;const i=o.setState.bind(o);return o.setState=t=>{const n={...o.getState()};if(i(t),!c){const t=((t,e)=>{const n=s.keys||Object.keys(t),o={};let a=!1;for(const s of n)"symbol"!=typeof s&&t[s]!==e[s]&&(o[s]=t[s],a=!0);return a?o:null})(o.getState(),n);t&&r.postMessage({type:"STATE_UPDATE",payload:t,tabId:e})}},r.onmessage=t=>{const n=t.data;if(n.tabId!==e)switch(n.type){case"STATE_UPDATE":c=!0,o.setState(n.payload),c=!1;break;case"REQUEST_STATE":{const t=o.getState(),a={},c=s.keys||Object.keys(t);for(const e of c)"symbol"!=typeof e&&e in t&&(a[e]=t[e]);r.postMessage({type:"PROVIDE_STATE",payload:a,targetTabId:n.tabId,tabId:e});break}case"PROVIDE_STATE":n.targetTabId!==e||y||(y=!0,c=!0,o.setState(n.payload),c=!1)}},r.postMessage({type:"REQUEST_STATE",tabId:e}),{__sync_channel:r}}}),exports.withSync=function(t,e){return Object.defineProperty(t,n,{value:e,enumerable:!1,configurable:!0}),t};
|
|
2
|
-
//# sourceMappingURL=sync.cjs.map
|
package/dist/sync.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
import{r as t}from"./registry-zaKZ1P-s.js";const e="undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():Math.random().toString(36).substring(2,11),n=Symbol("storve_sync_options");function o(t,e){return Object.defineProperty(t,n,{value:e,enumerable:!1,configurable:!0}),t}t({key:"sync",extendStore:t=>{const{store:o,definition:a}=t,s=a[n];if(!s||!1===s.enabled)return{};const r=function(t){if("undefined"==typeof window)return null;if("undefined"==typeof BroadcastChannel)return null;try{return new BroadcastChannel(t)}catch{return null}}(s.channel);if(!r)return{};let c=!1,y=!1;const d=o.setState.bind(o);return o.setState=t=>{const n={...o.getState()};if(d(t),!c){const t=((t,e)=>{const n=s.keys||Object.keys(t),o={};let a=!1;for(const s of n)"symbol"!=typeof s&&t[s]!==e[s]&&(o[s]=t[s],a=!0);return a?o:null})(o.getState(),n);t&&r.postMessage({type:"STATE_UPDATE",payload:t,tabId:e})}},r.onmessage=t=>{const n=t.data;if(n.tabId!==e)switch(n.type){case"STATE_UPDATE":c=!0,o.setState(n.payload),c=!1;break;case"REQUEST_STATE":{const t=o.getState(),a={},c=s.keys||Object.keys(t);for(const e of c)"symbol"!=typeof e&&e in t&&(a[e]=t[e]);r.postMessage({type:"PROVIDE_STATE",payload:a,targetTabId:n.tabId,tabId:e});break}case"PROVIDE_STATE":n.targetTabId!==e||y||(y=!0,c=!0,o.setState(n.payload),c=!1)}},r.postMessage({type:"REQUEST_STATE",tabId:e}),{__sync_channel:r}}});export{o as withSync};
|
|
2
|
-
//# sourceMappingURL=sync.mjs.map
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "https://github.com/Nam1001/React-Flux.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "1.0.
|
|
7
|
+
"version": "1.0.4",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
8
14
|
"main": "dist/index.cjs",
|
|
9
15
|
"module": "dist/index.mjs",
|
|
10
16
|
"types": "dist/index.d.ts",
|
|
@@ -74,7 +80,8 @@
|
|
|
74
80
|
"bench:week5": "npx tsx benchmarks/week5.ts",
|
|
75
81
|
"lint": "eslint src --ext .ts",
|
|
76
82
|
"build": "rollup -c",
|
|
77
|
-
"build:analyze": "rollup -c --environment ANALYZE:true"
|
|
83
|
+
"build:analyze": "rollup -c --environment ANALYZE:true",
|
|
84
|
+
"prepack": "rm -f dist/index.cjs.js dist/index.cjs.js.map dist/index.esm.js dist/index.esm.js.map dist/stats.html"
|
|
78
85
|
},
|
|
79
86
|
"devDependencies": {
|
|
80
87
|
"@rollup/plugin-terser": "^0.4.4",
|
|
@@ -92,4 +99,4 @@
|
|
|
92
99
|
"immer": ">=10.0.0",
|
|
93
100
|
"react": ">=18.0.0"
|
|
94
101
|
}
|
|
95
|
-
}
|
|
102
|
+
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
## [1.0.0] - 2026-03-14
|
|
6
|
-
|
|
7
|
-
### Added
|
|
8
|
-
- Getting Started in 5 minutes section in README
|
|
9
|
-
- Migration guides — Redux → Storve, Zustand → Storve
|
|
10
|
-
- StackBlitz interactive demo (Counter, Todo, Async)
|
|
11
|
-
- Bundle size and test count badges
|
|
12
|
-
|
|
13
|
-
### Changed
|
|
14
|
-
- Roadmap updated to reflect shipped features and planned v1.1–v1.3
|
|
15
|
-
- Test count updated to 937 across 29 test files
|
|
16
|
-
- Coverage badge updated to 99%
|
|
17
|
-
|
|
18
|
-
### Notes
|
|
19
|
-
- Stable API — no breaking changes planned until v2.0
|
|
20
|
-
- All subpath imports locked: storve, storve/async, storve/computed,
|
|
21
|
-
storve/persist, storve/signals, storve/devtools, storve/sync
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## [0.7.0] - 2026-03-14
|
|
30
|
-
|
|
31
|
-
### Added — `storve/sync`
|
|
32
|
-
- `withSync` — cross-tab state synchronization using `BroadcastChannel`.
|
|
33
|
-
- Automatic state rehydration across tabs on initialization.
|
|
34
|
-
- Selective key synchronization via `SyncOptions`.
|
|
35
|
-
- Tree-shakable subpath import: `storve/sync`.
|
|
36
|
-
- Full integration with existing extensions (DevTools, Persist).
|
|
37
|
-
- 100% test coverage for sync logic.
|
|
38
|
-
|
|
39
|
-
## [0.6.0] - 2026-03-14
|
|
40
|
-
|
|
41
|
-
### Added
|
|
42
|
-
- `storve/devtools` entry point for time-travel debugging.
|
|
43
|
-
- `withDevtools` store enhancer for ring-buffer history and Redux DevTools integration.
|
|
44
|
-
- `undo()` and `redo()` API on stores.
|
|
45
|
-
- `canUndo` and `canRedo` flags.
|
|
46
|
-
- `snapshot()` and `restore()` for named state checkpoints.
|
|
47
|
-
- `useDevtools` React hook for reactive access to devtools state.
|
|
48
|
-
- Redux DevTools extension support (JUMP_TO_STATE, RESET).
|
|
49
|
-
|
|
50
|
-
### Fixed
|
|
51
|
-
- Internal: extensions now receive the store instance and original definition.
|
|
52
|
-
- Internal: added `Object.defineProperties` support for extension method merging.
|
|
53
|
-
- Internal: triggered initial state change notification for early extension initialization.
|
|
54
|
-
|
|
55
|
-
## [0.5.0] - 2026-03-14
|
|
56
|
-
|
|
57
|
-
### Added — `storve/signals`
|
|
58
|
-
- `signal(store, key)` — fine-grained reactivity for individual store keys
|
|
59
|
-
- `signal(store, key, transform)` — read-only derived signals with automatic dependency filtering
|
|
60
|
-
- `useSignal(signal)` — React hook for zero-overhead subscription to specific state slices
|
|
61
|
-
- `Object.is` value filtering — zero re-renders unless the specific signal value actually changes
|
|
62
|
-
- 100% test coverage for signals package
|
|
63
|
-
- Tree-shakable subpath import: `storve/signals`
|
|
64
|
-
- Bundle size: < 0.6KB for signals entry point
|
|
65
|
-
|
|
66
|
-
## [0.4.0] - 2026-03-12
|
|
67
|
-
|
|
68
|
-
### Added — `storve/persist`
|
|
69
|
-
- `withPersist` — persist store state with pluggable adapters
|
|
70
|
-
- `localStorageAdapter`, `sessionStorageAdapter`, `memoryAdapter`, `indexedDBAdapter`.
|
|
71
|
-
- `compose()` — compose multiple store enhancers cleanly.
|
|
72
|
-
- Version + migration support for schema changes.
|
|
73
|
-
- Configurable debounce on writes.
|
|
74
|
-
- SSR safe — all adapters guard against missing window/indexedDB.
|
|
75
|
-
|
|
76
|
-
### Added — `storve/async`
|
|
77
|
-
- `createAsync(fetcher, options)` — core engine for async state management.
|
|
78
|
-
- Lifecycle management — automatic tracking of `idle`, `loading`, `success`, and `error` states.
|
|
79
|
-
- Advanced caching — TTL (Time-To-Live) and SWR (Stale-While-Revalidate) support.
|
|
80
|
-
- Optimistic updates — immediate UI feedback with automatic rollback on failure.
|
|
81
|
-
- Argument-aware fetching — separate cache entries based on fetcher arguments.
|
|
82
|
-
|
|
83
|
-
### Changed — BREAKING
|
|
84
|
-
- **Barrel import removed.** Use subpath imports:
|
|
85
|
-
- `import { createStore, batch } from 'storve'` — core only (~1.4KB gzipped)
|
|
86
|
-
- `import { createAsync } from 'storve/async'` — async support (~1.1KB gzipped)
|
|
87
|
-
- `import { computed } from 'storve/computed'` — computed support (~0.8KB gzipped)
|
|
88
|
-
- Store without async extension: `fetch()` throws with message to import `storve/async`
|
|
89
|
-
|
|
90
|
-
### Fixed
|
|
91
|
-
- Bundle sizes: core 1.4KB, async 1.1KB, computed 0.8KB (gzipped, with Terser).
|
|
92
|
-
- ESLint: Replaced `@ts-ignore` with `@ts-expect-error` across benchmarks.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## [0.3.0] - 2026-03-01
|
|
97
|
-
### Added — `storve-core`
|
|
98
|
-
- `actions` support inside `createStore()` — define methods inline, auto-bound, excluded from state
|
|
99
|
-
- Async action support — actions can be `async` and notify subscribers on completion
|
|
100
|
-
- Immer integration — `setState(draft => { ... })` mutation style via `{ immer: true }` store option
|
|
101
|
-
- `store.batch(fn)` — multiple `setState()` calls inside a batch fire exactly one subscriber notification
|
|
102
|
-
- Nested batch support via internal `batchCount` counter
|
|
103
|
-
- `batchDirty` flag — empty batch fires zero notifications
|
|
104
|
-
- `store.actions` stable reference — same object across renders, safe to spread in hooks
|
|
105
|
-
- Added types: `StoreState<D>`, `StoreActions<D>`, `StoreOptions`
|
|
106
|
-
- Updated `Store<D>` interface — `getState()` returns state only, actions excluded from state type
|
|
107
|
-
- Added `immer` to `peerDependencies` — not bundled, tree-shaken when unused
|
|
108
|
-
- 85+ new tests across `actions.test.ts`, `immer.test.ts`, `batch.test.ts`
|
|
109
|
-
- Week 4 performance benchmarks: action calls, Immer mutations, batch notification overhead
|
|
110
|
-
|
|
111
|
-
### Fixed — `storve-react`
|
|
112
|
-
- `useStore` regression — hook was merging actions into result even when a selector was provided, causing React to throw "Objects are not valid as a React child" for primitive selector returns
|
|
113
|
-
- Moved selector logic into `getSnapshot` so React correctly detects value changes
|
|
114
|
-
- Selector path now returns selected value directly — no action merging
|
|
115
|
-
- No-selector path merges actions at return time only, after `useSyncExternalStore`
|
|
116
|
-
- Shallow copy in no-selector snapshot fixes Proxy same-reference issue
|
|
117
|
-
- `shallowEqual` on object selector results prevents unnecessary re-renders
|
|
118
|
-
- Store reference change correctly invalidates snapshot cache
|
|
119
|
-
- Confirmed zero hook rule violations — no conditional hook calls
|
|
120
|
-
|
|
121
|
-
### Fixed — `storve-react` (ESLint)
|
|
122
|
-
- Removed unused `useState` import in `lifecycle.test.tsx`
|
|
123
|
-
- Replaced `any` with typed alternatives across `selector.test.tsx` and `useStore.test.tsx`
|
|
124
|
-
- Fixed `no-unused-vars` in `benchmarks/week3.ts` — replaced `const _ = ...` with `void`
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
## [0.2.0] - 2026-02-28
|
|
129
|
-
### Added — `storve-react`
|
|
130
|
-
- `useStore()` hook using `useSyncExternalStore` (React 18)
|
|
131
|
-
- Selector support as optional second argument to `useStore()`
|
|
132
|
-
- Concurrent mode safety — verified with React 18 concurrent test suite
|
|
133
|
-
- Auto-cleanup of subscriptions on component unmount
|
|
134
|
-
- Integration tests with React Testing Library
|
|
135
|
-
- Performance benchmarks for subscription setup, cleanup, selector execution
|
|
136
|
-
- 55 tests passing across 6 test files
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## [0.1.0] - 2026-02-28
|
|
141
|
-
### Added — `storve-core`
|
|
142
|
-
- Initial `createStore()` implementation
|
|
143
|
-
- Proxy-based auto-tracking for state mutations with eager wrapping for deep paths
|
|
144
|
-
- Proper interception of arrays (`push`, `pop`, `splice`, index sets)
|
|
145
|
-
- Store subscription mechanism via `subscribe()`
|
|
146
|
-
- `getState()` and `setState()` — plain object and updater function forms
|
|
147
|
-
- Added types: `StoreDefinition`, `Listener`, `Unsubscribe`, `Store`
|
|
148
|
-
- Full test coverage for core store (100% functions, 95%+ statements)
|
|
149
|
-
- Week 3 performance benchmarks and limits verification
|
|
150
|
-
(100% functions, 95%+ statements)
|
|
151
|
-
- Week 3 performance benchmarks and limits verification
|