@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/dist/store.d.ts.map
DELETED
|
@@ -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"}
|
package/dist/sync/index.d.ts.map
DELETED
|
@@ -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"}
|
package/dist/types.d.ts.map
DELETED
|
@@ -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
|
-
};
|
package/src/async-entry.ts
DELETED
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
|
-
}
|
package/src/computed-entry.ts
DELETED
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
|
-
});
|