storion 0.2.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +771 -561
  2. package/dist/async/async.d.ts +87 -0
  3. package/dist/async/async.d.ts.map +1 -0
  4. package/dist/async/index.d.ts +13 -0
  5. package/dist/async/index.d.ts.map +1 -0
  6. package/dist/async/index.js +451 -0
  7. package/dist/async/types.d.ts +275 -0
  8. package/dist/async/types.d.ts.map +1 -0
  9. package/dist/collection.d.ts +42 -0
  10. package/dist/collection.d.ts.map +1 -0
  11. package/dist/core/container.d.ts +33 -2
  12. package/dist/core/container.d.ts.map +1 -1
  13. package/dist/core/createResolver.d.ts +47 -0
  14. package/dist/core/createResolver.d.ts.map +1 -0
  15. package/dist/core/effect.d.ts.map +1 -1
  16. package/dist/core/equality.d.ts +23 -3
  17. package/dist/core/equality.d.ts.map +1 -1
  18. package/dist/core/fnWrapper.d.ts +54 -0
  19. package/dist/core/fnWrapper.d.ts.map +1 -0
  20. package/dist/core/middleware.d.ts +10 -10
  21. package/dist/core/middleware.d.ts.map +1 -1
  22. package/dist/core/pick.d.ts +6 -6
  23. package/dist/core/pick.d.ts.map +1 -1
  24. package/dist/core/store.d.ts +8 -8
  25. package/dist/core/store.d.ts.map +1 -1
  26. package/dist/core/storeContext.d.ts +63 -0
  27. package/dist/core/storeContext.d.ts.map +1 -0
  28. package/dist/devtools/controller.d.ts +4 -0
  29. package/dist/devtools/controller.d.ts.map +1 -0
  30. package/dist/devtools/index.d.ts +16 -0
  31. package/dist/devtools/index.d.ts.map +1 -0
  32. package/dist/devtools/index.js +239 -0
  33. package/dist/devtools/middleware.d.ts +22 -0
  34. package/dist/devtools/middleware.d.ts.map +1 -0
  35. package/dist/devtools/types.d.ts +116 -0
  36. package/dist/devtools/types.d.ts.map +1 -0
  37. package/dist/devtools-panel/DevtoolsPanel.d.ts +17 -0
  38. package/dist/devtools-panel/DevtoolsPanel.d.ts.map +1 -0
  39. package/dist/devtools-panel/components/CompareModal.d.ts +10 -0
  40. package/dist/devtools-panel/components/CompareModal.d.ts.map +1 -0
  41. package/dist/devtools-panel/components/EventEntry.d.ts +14 -0
  42. package/dist/devtools-panel/components/EventEntry.d.ts.map +1 -0
  43. package/dist/devtools-panel/components/EventFilterBar.d.ts +10 -0
  44. package/dist/devtools-panel/components/EventFilterBar.d.ts.map +1 -0
  45. package/dist/devtools-panel/components/EventsTab.d.ts +15 -0
  46. package/dist/devtools-panel/components/EventsTab.d.ts.map +1 -0
  47. package/dist/devtools-panel/components/ResizeHandle.d.ts +8 -0
  48. package/dist/devtools-panel/components/ResizeHandle.d.ts.map +1 -0
  49. package/dist/devtools-panel/components/StoreEntry.d.ts +13 -0
  50. package/dist/devtools-panel/components/StoreEntry.d.ts.map +1 -0
  51. package/dist/devtools-panel/components/StoresTab.d.ts +12 -0
  52. package/dist/devtools-panel/components/StoresTab.d.ts.map +1 -0
  53. package/dist/devtools-panel/components/TabLayout.d.ts +48 -0
  54. package/dist/devtools-panel/components/TabLayout.d.ts.map +1 -0
  55. package/dist/devtools-panel/components/icons.d.ts +27 -0
  56. package/dist/devtools-panel/components/icons.d.ts.map +1 -0
  57. package/dist/devtools-panel/components/index.d.ts +15 -0
  58. package/dist/devtools-panel/components/index.d.ts.map +1 -0
  59. package/dist/devtools-panel/hooks.d.ts +23 -0
  60. package/dist/devtools-panel/hooks.d.ts.map +1 -0
  61. package/dist/devtools-panel/index.d.ts +25 -0
  62. package/dist/devtools-panel/index.d.ts.map +1 -0
  63. package/dist/devtools-panel/index.js +3326 -0
  64. package/dist/devtools-panel/mount.d.ts +41 -0
  65. package/dist/devtools-panel/mount.d.ts.map +1 -0
  66. package/dist/devtools-panel/styles.d.ts +50 -0
  67. package/dist/devtools-panel/styles.d.ts.map +1 -0
  68. package/dist/devtools-panel/types.d.ts +15 -0
  69. package/dist/devtools-panel/types.d.ts.map +1 -0
  70. package/dist/devtools-panel/utils.d.ts +21 -0
  71. package/dist/devtools-panel/utils.d.ts.map +1 -0
  72. package/dist/index.d.ts +6 -1
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/is.d.ts +69 -0
  75. package/dist/is.d.ts.map +1 -0
  76. package/dist/react/create.d.ts +1 -1
  77. package/dist/react/index.d.ts +1 -0
  78. package/dist/react/index.d.ts.map +1 -1
  79. package/dist/react/index.js +210 -34
  80. package/dist/react/useLocalStore.d.ts.map +1 -1
  81. package/dist/react/useStore.d.ts +2 -2
  82. package/dist/react/useStore.d.ts.map +1 -1
  83. package/dist/react/withStore.d.ts +140 -0
  84. package/dist/react/withStore.d.ts.map +1 -0
  85. package/dist/{index-rLf6DusB.js → store-Yv-9gPVf.js} +543 -742
  86. package/dist/storion.js +809 -9
  87. package/dist/trigger.d.ts +40 -0
  88. package/dist/trigger.d.ts.map +1 -0
  89. package/dist/types.d.ts +538 -71
  90. package/dist/types.d.ts.map +1 -1
  91. package/package.json +13 -1
@@ -1,3 +1,34 @@
1
+ const STORION_TYPE = Symbol("STORION");
2
+ function is$1(value, kind) {
3
+ return value !== null && (typeof value === "object" || typeof value === "function") && STORION_TYPE in value && value[STORION_TYPE] === kind;
4
+ }
5
+ function isStorion(value) {
6
+ return value !== null && (typeof value === "object" || typeof value === "function") && STORION_TYPE in value && typeof value[STORION_TYPE] === "string";
7
+ }
8
+ function getKind(value) {
9
+ return value[STORION_TYPE];
10
+ }
11
+ function isSpec(value) {
12
+ return is$1(value, "store.spec");
13
+ }
14
+ function isContainer(value) {
15
+ return is$1(value, "container");
16
+ }
17
+ function isStore(value) {
18
+ return is$1(value, "store");
19
+ }
20
+ function isFocus(value) {
21
+ return is$1(value, "focus");
22
+ }
23
+ function isStoreContext(value) {
24
+ return is$1(value, "store.context");
25
+ }
26
+ function isSelectorContext(value) {
27
+ return is$1(value, "selector.context");
28
+ }
29
+ function isAction(value) {
30
+ return is$1(value, "store.action");
31
+ }
1
32
  var NOTHING = Symbol.for("immer-nothing");
2
33
  var DRAFTABLE = Symbol.for("immer-draftable");
3
34
  var DRAFT_STATE = Symbol.for("immer-state");
@@ -797,75 +828,6 @@ function currentImpl(value) {
797
828
  }
798
829
  var immer = new Immer2();
799
830
  var produce = immer.produce;
800
- let globalHooks = {
801
- scheduleNotification(notify) {
802
- notify();
803
- },
804
- scheduleEffect(runEffect) {
805
- runEffect();
806
- }
807
- };
808
- function getHooks() {
809
- return globalHooks;
810
- }
811
- function hasReadHook() {
812
- return globalHooks.onRead !== void 0;
813
- }
814
- function hasWriteHook() {
815
- return globalHooks.onWrite !== void 0;
816
- }
817
- function withHooks(hooksOrSetup, fn, onFinish) {
818
- const prev = globalHooks;
819
- if (typeof hooksOrSetup === "function") {
820
- globalHooks = {
821
- ...globalHooks,
822
- ...hooksOrSetup(prev)
823
- };
824
- } else {
825
- globalHooks = { ...prev, ...hooksOrSetup };
826
- }
827
- try {
828
- return fn();
829
- } finally {
830
- globalHooks = prev;
831
- onFinish == null ? void 0 : onFinish();
832
- }
833
- }
834
- function trackRead(storeId, prop, value, subscribe) {
835
- var _a;
836
- const key = `${storeId}.${prop}`;
837
- (_a = globalHooks.onRead) == null ? void 0 : _a.call(globalHooks, { key, value, subscribe });
838
- }
839
- function trackWrite(storeId, prop, next, prev) {
840
- var _a;
841
- const key = `${storeId}.${prop}`;
842
- (_a = globalHooks.onWrite) == null ? void 0 : _a.call(globalHooks, { key, next, prev });
843
- }
844
- function untrack(fn) {
845
- return withHooks({ onRead: void 0, onWrite: void 0 }, fn);
846
- }
847
- function scheduleNotification(notify, key) {
848
- globalHooks.scheduleNotification(notify, key);
849
- }
850
- function batch(fn) {
851
- const pending = /* @__PURE__ */ new Map();
852
- return withHooks(
853
- (current2) => ({
854
- ...current2,
855
- scheduleNotification: (notify, key) => {
856
- const actualKey = key ?? notify;
857
- pending.set(actualKey, notify);
858
- }
859
- }),
860
- fn,
861
- // Flush on finish
862
- () => {
863
- for (const notify of pending.values()) {
864
- notify();
865
- }
866
- }
867
- );
868
- }
869
831
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
870
832
  function getDefaultExportFromCjs(x) {
871
833
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
@@ -1736,7 +1698,7 @@ const isEqual$1 = /* @__PURE__ */ getDefaultExportFromCjs(isEqual_1);
1736
1698
  function strictEqual(a, b) {
1737
1699
  return Object.is(a, b);
1738
1700
  }
1739
- function shallowEqual(a, b) {
1701
+ function shallowEqual(a, b, itemEqual = Object.is) {
1740
1702
  if (Object.is(a, b)) return true;
1741
1703
  if (typeof a !== "object" || a === null) return false;
1742
1704
  if (typeof b !== "object" || b === null) return false;
@@ -1745,16 +1707,286 @@ function shallowEqual(a, b) {
1745
1707
  if (keysA.length !== keysB.length) return false;
1746
1708
  for (const key of keysA) {
1747
1709
  if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
1748
- if (!Object.is(a[key], b[key])) return false;
1710
+ if (!itemEqual(a[key], b[key])) return false;
1749
1711
  }
1750
1712
  return true;
1751
1713
  }
1714
+ function shallow2Equal(a, b) {
1715
+ return shallowEqual(a, b, shallowEqual);
1716
+ }
1717
+ function shallow3Equal(a, b) {
1718
+ return shallowEqual(a, b, shallow2Equal);
1719
+ }
1752
1720
  const deepEqual = isEqual$1;
1753
- function resolveEquality(equality) {
1754
- if (!equality || equality === "strict") return strictEqual;
1755
- if (equality === "shallow") return shallowEqual;
1756
- if (equality === "deep") return deepEqual;
1757
- return equality;
1721
+ function resolveEquality(e) {
1722
+ if (!e || e === "strict") return strictEqual;
1723
+ if (e === "shallow") return shallowEqual;
1724
+ if (e === "shallow2") return shallow2Equal;
1725
+ if (e === "shallow3") return shallow3Equal;
1726
+ if (e === "deep") return deepEqual;
1727
+ return e;
1728
+ }
1729
+ function equality(shorthand) {
1730
+ return resolveEquality(shorthand);
1731
+ }
1732
+ function getAtPath(obj, segments) {
1733
+ let current2 = obj;
1734
+ for (const key of segments) {
1735
+ if (current2 == null) return current2;
1736
+ current2 = current2[key];
1737
+ }
1738
+ return current2;
1739
+ }
1740
+ function createFocus(focusCtx, path, options) {
1741
+ const segments = path.split(".");
1742
+ const { fallback, equality: equalityOption } = options ?? {};
1743
+ const equalityFn = resolveEquality(equalityOption);
1744
+ const getter = () => {
1745
+ const state = focusCtx.getState();
1746
+ const value = getAtPath(state, segments);
1747
+ if ((value === null || value === void 0) && fallback) {
1748
+ return fallback();
1749
+ }
1750
+ return value;
1751
+ };
1752
+ const setter = (valueOrReducerOrProduce) => {
1753
+ focusCtx.update((draft) => {
1754
+ let current2 = draft;
1755
+ for (let i = 0; i < segments.length - 1; i++) {
1756
+ const key = segments[i];
1757
+ if (current2[key] == null) {
1758
+ current2[key] = {};
1759
+ }
1760
+ current2 = current2[key];
1761
+ }
1762
+ const lastKey = segments[segments.length - 1];
1763
+ let currentValue = current2[lastKey];
1764
+ if ((currentValue === null || currentValue === void 0) && fallback) {
1765
+ currentValue = fallback();
1766
+ current2[lastKey] = currentValue;
1767
+ }
1768
+ if (typeof valueOrReducerOrProduce === "function") {
1769
+ const fn = valueOrReducerOrProduce;
1770
+ const result = fn(currentValue);
1771
+ if (result !== void 0) {
1772
+ current2[lastKey] = result;
1773
+ }
1774
+ } else {
1775
+ current2[lastKey] = valueOrReducerOrProduce;
1776
+ }
1777
+ });
1778
+ };
1779
+ const on = (listener) => {
1780
+ let prevValue = getter();
1781
+ return focusCtx.subscribe(() => {
1782
+ const nextValue = getter();
1783
+ if (!equalityFn(prevValue, nextValue)) {
1784
+ const prev = prevValue;
1785
+ prevValue = nextValue;
1786
+ listener({ next: nextValue, prev });
1787
+ }
1788
+ });
1789
+ };
1790
+ const to = (relativePath, childOptions) => {
1791
+ const combinedPath = `${path}.${relativePath}`;
1792
+ return createFocus(focusCtx, combinedPath, childOptions);
1793
+ };
1794
+ const focus = [getter, setter];
1795
+ const focusObj = focus;
1796
+ focusObj[STORION_TYPE] = "focus";
1797
+ focusObj.on = on;
1798
+ focusObj.to = to;
1799
+ return focus;
1800
+ }
1801
+ function createUpdateFn(update) {
1802
+ const updateFn = (updaterOrPartial) => {
1803
+ if (typeof updaterOrPartial === "function") {
1804
+ update(updaterOrPartial);
1805
+ } else {
1806
+ update((draft) => {
1807
+ Object.assign(draft, updaterOrPartial);
1808
+ });
1809
+ }
1810
+ };
1811
+ updateFn.action = (updater) => {
1812
+ return (...args) => {
1813
+ update((draft) => {
1814
+ updater(draft, ...args);
1815
+ });
1816
+ };
1817
+ };
1818
+ return updateFn;
1819
+ }
1820
+ function createStoreContext(options) {
1821
+ const {
1822
+ spec,
1823
+ resolver,
1824
+ getMutableState,
1825
+ update,
1826
+ subscribe,
1827
+ dirty,
1828
+ reset,
1829
+ // getInstance - reserved for future use
1830
+ onDependency,
1831
+ onDispose,
1832
+ isSetupPhase
1833
+ } = options;
1834
+ const currentLifetime = spec.options.lifetime ?? "keepAlive";
1835
+ const ctx = {
1836
+ [STORION_TYPE]: "store.context",
1837
+ get state() {
1838
+ return getMutableState();
1839
+ },
1840
+ // Implementation handles both StoreSpec and Factory overloads
1841
+ get(specOrFactory) {
1842
+ if (!isSetupPhase()) {
1843
+ throw new Error(
1844
+ `get() can only be called during setup phase. Do not call get() inside actions or async callbacks. Declare all dependencies at the top of your setup function.`
1845
+ );
1846
+ }
1847
+ if (!isSpec(specOrFactory)) {
1848
+ return resolver.get(specOrFactory);
1849
+ }
1850
+ const depSpec = specOrFactory;
1851
+ const depLifetime = depSpec.options.lifetime ?? "keepAlive";
1852
+ if (currentLifetime === "keepAlive" && depLifetime === "autoDispose") {
1853
+ const currentName = spec.options.name ?? "unknown";
1854
+ const depName = depSpec.name ?? "unknown";
1855
+ throw new Error(
1856
+ `Lifetime mismatch: Store "${currentName}" (keepAlive) cannot depend on store "${depName}" (autoDispose). A long-lived store cannot depend on a store that may be disposed. Either change "${currentName}" to autoDispose, or change "${depName}" to keepAlive.`
1857
+ );
1858
+ }
1859
+ const instance = resolver.get(depSpec);
1860
+ onDependency == null ? void 0 : onDependency(instance);
1861
+ const tuple = [instance.state, instance.actions];
1862
+ return Object.assign(tuple, {
1863
+ state: instance.state,
1864
+ actions: instance.actions
1865
+ });
1866
+ },
1867
+ // Implementation handles both StoreSpec and Factory overloads
1868
+ create(specOrFactory) {
1869
+ if (!isSetupPhase()) {
1870
+ throw new Error(
1871
+ `create() can only be called during setup phase. Do not call create() inside actions or async callbacks. Declare all child stores at the top of your setup function.`
1872
+ );
1873
+ }
1874
+ if (!isSpec(specOrFactory)) {
1875
+ const instance2 = specOrFactory(resolver);
1876
+ if (instance2 && typeof instance2.dispose === "function") {
1877
+ onDispose == null ? void 0 : onDispose(instance2.dispose);
1878
+ }
1879
+ return instance2;
1880
+ }
1881
+ const childSpec = specOrFactory;
1882
+ const childLifetime = childSpec.options.lifetime ?? "keepAlive";
1883
+ if (currentLifetime === "keepAlive" && childLifetime === "autoDispose") {
1884
+ const currentName = spec.options.name ?? "unknown";
1885
+ const childName = childSpec.name ?? "unknown";
1886
+ throw new Error(
1887
+ `Lifetime mismatch: Store "${currentName}" (keepAlive) cannot create child store "${childName}" (autoDispose). A long-lived store cannot create a store that may be disposed before it. Either change "${currentName}" to autoDispose, or change "${childName}" to keepAlive.`
1888
+ );
1889
+ }
1890
+ const instance = resolver.create(childSpec);
1891
+ onDispose == null ? void 0 : onDispose(instance.dispose);
1892
+ return instance;
1893
+ },
1894
+ update: createUpdateFn(update),
1895
+ dirty(prop) {
1896
+ return dirty(prop);
1897
+ },
1898
+ reset() {
1899
+ reset();
1900
+ },
1901
+ mixin(mixin, ...args) {
1902
+ if (!isSetupPhase()) {
1903
+ throw new Error(
1904
+ `mixin() can only be called during setup phase. Do not call mixin() inside actions or async callbacks.`
1905
+ );
1906
+ }
1907
+ return mixin(ctx, ...args);
1908
+ },
1909
+ focus(path, options2) {
1910
+ const focusCtx = {
1911
+ getState: getMutableState,
1912
+ update: (updater) => {
1913
+ ctx.update(updater);
1914
+ },
1915
+ subscribe
1916
+ };
1917
+ return createFocus(focusCtx, path, options2);
1918
+ }
1919
+ };
1920
+ return ctx;
1921
+ }
1922
+ let globalHooks = {
1923
+ scheduleNotification(notify) {
1924
+ notify();
1925
+ },
1926
+ scheduleEffect(runEffect) {
1927
+ runEffect();
1928
+ }
1929
+ };
1930
+ function getHooks() {
1931
+ return globalHooks;
1932
+ }
1933
+ function hasReadHook() {
1934
+ return globalHooks.onRead !== void 0;
1935
+ }
1936
+ function hasWriteHook() {
1937
+ return globalHooks.onWrite !== void 0;
1938
+ }
1939
+ function withHooks(hooksOrSetup, fn, onFinish) {
1940
+ const prev = globalHooks;
1941
+ if (typeof hooksOrSetup === "function") {
1942
+ globalHooks = {
1943
+ ...globalHooks,
1944
+ ...hooksOrSetup(prev)
1945
+ };
1946
+ } else {
1947
+ globalHooks = { ...prev, ...hooksOrSetup };
1948
+ }
1949
+ try {
1950
+ return fn();
1951
+ } finally {
1952
+ globalHooks = prev;
1953
+ onFinish == null ? void 0 : onFinish();
1954
+ }
1955
+ }
1956
+ function trackRead(storeId, prop, value, subscribe) {
1957
+ var _a;
1958
+ const key = `${storeId}.${prop}`;
1959
+ (_a = globalHooks.onRead) == null ? void 0 : _a.call(globalHooks, { key, value, subscribe });
1960
+ }
1961
+ function trackWrite(storeId, prop, next, prev) {
1962
+ var _a;
1963
+ const key = `${storeId}.${prop}`;
1964
+ (_a = globalHooks.onWrite) == null ? void 0 : _a.call(globalHooks, { key, next, prev });
1965
+ }
1966
+ function untrack(fn) {
1967
+ return withHooks({ onRead: void 0, onWrite: void 0 }, fn);
1968
+ }
1969
+ function scheduleNotification(notify, key) {
1970
+ globalHooks.scheduleNotification(notify, key);
1971
+ }
1972
+ function batch(fn) {
1973
+ const pending = /* @__PURE__ */ new Map();
1974
+ return withHooks(
1975
+ (current2) => ({
1976
+ ...current2,
1977
+ scheduleNotification: (notify, key) => {
1978
+ const actualKey = key ?? notify;
1979
+ pending.set(actualKey, notify);
1980
+ }
1981
+ }),
1982
+ fn,
1983
+ // Flush on finish
1984
+ () => {
1985
+ for (const notify of pending.values()) {
1986
+ notify();
1987
+ }
1988
+ }
1989
+ );
1758
1990
  }
1759
1991
  let specIdCounter = 0;
1760
1992
  function generateSpecName() {
@@ -1764,6 +1996,19 @@ let instanceIdCounter = 0;
1764
1996
  function generateStoreId(specName) {
1765
1997
  return `${specName}:${++instanceIdCounter}`;
1766
1998
  }
1999
+ const ORIGINAL_FN = Symbol.for("storion.originalFn");
2000
+ function wrapFn(originalFn, createWrapper) {
2001
+ const wrapper = createWrapper(originalFn);
2002
+ wrapper[ORIGINAL_FN] = originalFn;
2003
+ return wrapper;
2004
+ }
2005
+ function unwrapFn(fn) {
2006
+ const original = fn[ORIGINAL_FN];
2007
+ return original ?? fn;
2008
+ }
2009
+ function isWrappedFn(fn) {
2010
+ return ORIGINAL_FN in fn;
2011
+ }
1767
2012
  function emitter(initialListeners) {
1768
2013
  const listeners = /* @__PURE__ */ new Set([]);
1769
2014
  let settledPayload;
@@ -1911,21 +2156,84 @@ function emitter(initialListeners) {
1911
2156
  }
1912
2157
  };
1913
2158
  }
1914
- function store(options) {
1915
- const name = options.name ?? generateSpecName();
2159
+ function collection(createItem, initialItems) {
2160
+ const map = /* @__PURE__ */ new Map([]);
1916
2161
  return {
1917
- name,
1918
- options
2162
+ with(key, callback) {
2163
+ if (map.has(key)) {
2164
+ callback(map.get(key));
2165
+ }
2166
+ return this;
2167
+ },
2168
+ /** Check if key exists (does NOT create item) */
2169
+ has(key) {
2170
+ return map.has(key);
2171
+ },
2172
+ /** Get item by key, creating it if it doesn't exist */
2173
+ get(key) {
2174
+ if (!map.has(key)) {
2175
+ map.set(key, createItem(key));
2176
+ }
2177
+ return map.get(key);
2178
+ },
2179
+ /** Explicitly set an item */
2180
+ set(key, value) {
2181
+ map.set(key, value);
2182
+ return this;
2183
+ },
2184
+ /** Number of items in the collection */
2185
+ get size() {
2186
+ return map.size;
2187
+ },
2188
+ /** Remove all items */
2189
+ clear() {
2190
+ map.clear();
2191
+ return this;
2192
+ },
2193
+ /** Remove a specific item */
2194
+ delete(key) {
2195
+ map.delete(key);
2196
+ return this;
2197
+ },
2198
+ /** Iterate over keys */
2199
+ keys() {
2200
+ return map.keys();
2201
+ },
2202
+ /** Iterate over values */
2203
+ values() {
2204
+ return map.values();
2205
+ },
2206
+ /** Iterate over [key, value] pairs */
2207
+ entries() {
2208
+ return map.entries();
2209
+ }
1919
2210
  };
1920
2211
  }
2212
+ function store(options) {
2213
+ const displayName = options.name ?? generateSpecName();
2214
+ const spec = function(resolver) {
2215
+ return createStoreInstance(
2216
+ spec,
2217
+ resolver,
2218
+ {}
2219
+ );
2220
+ };
2221
+ Object.defineProperties(spec, {
2222
+ [STORION_TYPE]: { value: "store.spec", enumerable: false },
2223
+ displayName: { value: displayName, enumerable: true, writable: false },
2224
+ options: { value: options, enumerable: true, writable: false }
2225
+ });
2226
+ return spec;
2227
+ }
1921
2228
  function createStoreInstance(spec, resolver, instanceOptions = {}) {
2229
+ var _a;
1922
2230
  const options = spec.options;
1923
- const storeId = generateStoreId(spec.name);
2231
+ const storeId = generateStoreId(spec.displayName);
1924
2232
  let disposed = false;
1925
2233
  let currentState = { ...options.state };
1926
2234
  let initialState = currentState;
1927
2235
  const isAutoDispose = options.lifetime === "autoDispose";
1928
- const gracePeriodMs = instanceOptions.gracePeriodMs ?? 100;
2236
+ const gracePeriodMs = ((_a = instanceOptions.autoDispose) == null ? void 0 : _a.gracePeriodMs) ?? 100;
1929
2237
  let refCount = 0;
1930
2238
  let disposeTimeout = null;
1931
2239
  const incrementRef = () => {
@@ -1942,39 +2250,26 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
1942
2250
  if (!isAutoDispose || isSetupPhase) {
1943
2251
  return;
1944
2252
  }
2253
+ disposeTimeout && clearTimeout(disposeTimeout);
1945
2254
  refCount--;
1946
- if (refCount <= 0 && instanceOptions.onUnused) {
2255
+ if (refCount <= 0) {
1947
2256
  disposeTimeout = setTimeout(() => {
1948
2257
  disposeTimeout = null;
1949
- if (refCount <= 0 && !disposed) {
1950
- instanceOptions.onUnused();
2258
+ if (refCount <= 0) {
2259
+ instance == null ? void 0 : instance.dispose();
1951
2260
  }
1952
2261
  }, gracePeriodMs);
1953
2262
  }
1954
2263
  };
1955
2264
  const changeEmitter = emitter();
1956
2265
  const disposeEmitter = emitter();
1957
- const propertyEmitters = /* @__PURE__ */ new Map();
1958
- const getPropertyEmitter = (key) => {
1959
- let em = propertyEmitters.get(key);
1960
- if (!em) {
1961
- em = emitter();
1962
- propertyEmitters.set(key, em);
1963
- }
1964
- return em;
1965
- };
2266
+ const propertyEmitters = collection(() => emitter());
1966
2267
  const actionInvocations = /* @__PURE__ */ new Map();
1967
2268
  const actionNthCounters = /* @__PURE__ */ new Map();
1968
- const actionEmitters = /* @__PURE__ */ new Map();
2269
+ const actionEmitters = collection(
2270
+ () => emitter()
2271
+ );
1969
2272
  const wildcardActionEmitter = emitter();
1970
- const getActionEmitter = (actionName) => {
1971
- let em = actionEmitters.get(actionName);
1972
- if (!em) {
1973
- em = emitter();
1974
- actionEmitters.set(actionName, em);
1975
- }
1976
- return em;
1977
- };
1978
2273
  const disposeEffectsEmitter = emitter();
1979
2274
  const equalityOption = options.equality;
1980
2275
  const propertyEquality = /* @__PURE__ */ new Map();
@@ -1998,45 +2293,21 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
1998
2293
  }
1999
2294
  const getEquality = (key) => propertyEquality.get(key) ?? defaultEquality ?? strictEqual;
2000
2295
  const isEqual2 = hasCustomEquality ? (key, a, b) => getEquality(key)(a, b) : (_key, a, b) => a === b;
2296
+ let isSetupPhase = true;
2001
2297
  function handlePropertyChange(key, oldValue, newValue) {
2002
- const propEmitter = propertyEmitters.get(key);
2003
- if (propEmitter) {
2004
- propEmitter.emit({ newValue, oldValue });
2298
+ if (isSetupPhase) {
2299
+ return;
2005
2300
  }
2301
+ propertyEmitters.with(
2302
+ key,
2303
+ (em) => em.emit({ newValue, oldValue })
2304
+ );
2006
2305
  scheduleNotification(() => {
2007
2306
  changeEmitter.emit();
2008
2307
  });
2009
2308
  }
2010
2309
  let instance = null;
2011
2310
  const getInst = () => instance;
2012
- function handleActionDispatch(actionName, args) {
2013
- const name = actionName;
2014
- const nth = (actionNthCounters.get(name) ?? 0) + 1;
2015
- actionNthCounters.set(name, nth);
2016
- const prev = actionInvocations.get(name);
2017
- const next = Object.freeze({
2018
- name: actionName,
2019
- args,
2020
- nth
2021
- });
2022
- actionInvocations.set(
2023
- name,
2024
- next
2025
- );
2026
- const actionEmitter = actionEmitters.get(name);
2027
- if (actionEmitter) {
2028
- actionEmitter.emit({
2029
- next,
2030
- prev
2031
- });
2032
- }
2033
- if (wildcardActionEmitter.size > 0) {
2034
- wildcardActionEmitter.emit({
2035
- next,
2036
- prev
2037
- });
2038
- }
2039
- }
2040
2311
  function getActionLastInvocation(actionName) {
2041
2312
  const propKey = `@${String(actionName)}`;
2042
2313
  const invocation = actionInvocations.get(String(actionName));
@@ -2048,6 +2319,7 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2048
2319
  }
2049
2320
  let instanceActions = {};
2050
2321
  instance = {
2322
+ [STORION_TYPE]: "store",
2051
2323
  id: storeId,
2052
2324
  spec,
2053
2325
  deps: [],
@@ -2077,15 +2349,14 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2077
2349
  }
2078
2350
  if (key.startsWith("@")) {
2079
2351
  const actionName = key.slice(1);
2080
- const actionEmitter = getActionEmitter(actionName);
2081
- const unsub2 = actionEmitter.on(propListener);
2352
+ const unsub2 = actionEmitters.get(actionName).on(propListener);
2082
2353
  return () => {
2083
2354
  unsub2();
2084
2355
  decrementRef();
2085
2356
  };
2086
2357
  }
2087
2358
  const propKey = listenerOrPropKey;
2088
- const propEmitter = getPropertyEmitter(propKey);
2359
+ const propEmitter = propertyEmitters.get(propKey);
2089
2360
  const unsub = propEmitter.on(({ newValue, oldValue }) => {
2090
2361
  propListener({ next: newValue, prev: oldValue });
2091
2362
  });
@@ -2099,11 +2370,9 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2099
2370
  const key = propKey;
2100
2371
  if (key.startsWith("@")) {
2101
2372
  const actionName = key.slice(1);
2102
- const actionEmitter = getActionEmitter(actionName);
2103
- return actionEmitter.on(listener);
2373
+ return actionEmitters.get(actionName).on(listener);
2104
2374
  }
2105
- const propEmitter = getPropertyEmitter(propKey);
2106
- return propEmitter.on(listener);
2375
+ return propertyEmitters.get(propKey).on(listener);
2107
2376
  },
2108
2377
  dispose() {
2109
2378
  if (disposed) return;
@@ -2203,97 +2472,76 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2203
2472
  }
2204
2473
  const mutableState = createReactiveState(true);
2205
2474
  const readonlyState = createReactiveState(false);
2206
- let isSetupPhase = true;
2207
2475
  const deps = /* @__PURE__ */ new Set();
2208
- const currentLifetime = options.lifetime ?? "keepAlive";
2209
- const setupContext = {
2210
- state: mutableState,
2211
- resolve(depSpec) {
2212
- if (!isSetupPhase) {
2213
- throw new Error(
2214
- `get() can only be called during setup phase. Do not call get() inside actions or async callbacks. Declare all dependencies at the top of your setup function.`
2215
- );
2216
- }
2217
- const depLifetime = depSpec.options.lifetime ?? "keepAlive";
2218
- if (currentLifetime === "keepAlive" && depLifetime === "autoDispose") {
2219
- const currentName = options.name ?? "unknown";
2220
- const depName = depSpec.name ?? "unknown";
2221
- throw new Error(
2222
- `Lifetime mismatch: Store "${currentName}" (keepAlive) cannot depend on store "${depName}" (autoDispose). A long-lived store cannot depend on a store that may be disposed. Either change "${currentName}" to autoDispose, or change "${depName}" to keepAlive.`
2223
- );
2224
- }
2225
- const instance2 = resolver.get(depSpec);
2226
- deps.add(instance2);
2227
- return [instance2.state, instance2.actions];
2228
- },
2229
- update(updaterOrPartial) {
2230
- let nextState = currentState;
2231
- if (typeof updaterOrPartial === "function") {
2232
- const updater = updaterOrPartial;
2233
- nextState = produce(currentState, updater);
2234
- } else {
2235
- nextState = produce(currentState, (draft) => {
2236
- Object.assign(draft, updaterOrPartial);
2237
- });
2238
- }
2239
- if (nextState === currentState) return;
2240
- const prevState = currentState;
2241
- const changedProps = [];
2242
- if (!hasCustomEquality) {
2243
- for (const key of Object.keys(nextState)) {
2244
- if (prevState[key] !== nextState[key]) {
2245
- changedProps.push({
2246
- key,
2247
- oldValue: prevState[key],
2248
- newValue: nextState[key]
2249
- });
2250
- }
2476
+ function updateState(updaterOrPartial) {
2477
+ let nextState = currentState;
2478
+ if (typeof updaterOrPartial === "function") {
2479
+ const updater = updaterOrPartial;
2480
+ nextState = produce(currentState, updater);
2481
+ } else {
2482
+ nextState = produce(currentState, (draft) => {
2483
+ Object.assign(draft, updaterOrPartial);
2484
+ });
2485
+ }
2486
+ if (nextState === currentState) return;
2487
+ const prevState = currentState;
2488
+ const changedProps = [];
2489
+ if (!hasCustomEquality) {
2490
+ for (const key of Object.keys(nextState)) {
2491
+ if (prevState[key] !== nextState[key]) {
2492
+ changedProps.push({
2493
+ key,
2494
+ oldValue: prevState[key],
2495
+ newValue: nextState[key]
2496
+ });
2251
2497
  }
2252
- if (changedProps.length > 0) {
2253
- currentState = nextState;
2498
+ }
2499
+ if (changedProps.length > 0) {
2500
+ currentState = nextState;
2501
+ batch(() => {
2254
2502
  for (const { key, oldValue, newValue } of changedProps) {
2255
2503
  handlePropertyChange(key, oldValue, newValue);
2256
2504
  }
2257
- }
2258
- return;
2505
+ });
2259
2506
  }
2260
- const stableState = { ...nextState };
2261
- for (const key of Object.keys(nextState)) {
2262
- if (prevState[key] !== nextState[key]) {
2263
- const equality = getEquality(key);
2264
- if (equality(prevState[key], nextState[key])) {
2265
- stableState[key] = prevState[key];
2266
- } else {
2267
- changedProps.push({
2268
- key,
2269
- oldValue: prevState[key],
2270
- newValue: nextState[key]
2271
- });
2272
- }
2507
+ return;
2508
+ }
2509
+ const stableState = { ...nextState };
2510
+ for (const key of Object.keys(nextState)) {
2511
+ if (prevState[key] !== nextState[key]) {
2512
+ const equality2 = getEquality(key);
2513
+ if (equality2(prevState[key], nextState[key])) {
2514
+ stableState[key] = prevState[key];
2515
+ } else {
2516
+ changedProps.push({
2517
+ key,
2518
+ oldValue: prevState[key],
2519
+ newValue: nextState[key]
2520
+ });
2273
2521
  }
2274
2522
  }
2275
- if (changedProps.length > 0) {
2276
- currentState = stableState;
2523
+ }
2524
+ if (changedProps.length > 0) {
2525
+ currentState = stableState;
2526
+ batch(() => {
2277
2527
  for (const { key, oldValue, newValue } of changedProps) {
2278
2528
  handlePropertyChange(key, oldValue, newValue);
2279
2529
  }
2280
- }
2281
- },
2282
- dirty(prop) {
2283
- return instance.dirty(prop);
2284
- },
2285
- reset() {
2286
- instance.reset();
2287
- },
2288
- use(mixin, ...args) {
2289
- if (!isSetupPhase) {
2290
- throw new Error(
2291
- `use() can only be called during setup phase. Do not call use() inside actions or async callbacks.`
2292
- );
2293
- }
2294
- return mixin(setupContext, ...args);
2530
+ });
2295
2531
  }
2296
- };
2532
+ }
2533
+ const setupContext = createStoreContext({
2534
+ spec,
2535
+ resolver,
2536
+ getMutableState: () => mutableState,
2537
+ update: updateState,
2538
+ subscribe: (listener) => changeEmitter.on(listener),
2539
+ dirty: (prop) => instance.dirty(prop),
2540
+ reset: () => instance.reset(),
2541
+ onDependency: (depInstance) => deps.add(depInstance),
2542
+ onDispose: (callback) => disposeEmitter.on(callback),
2543
+ isSetupPhase: () => isSetupPhase
2544
+ });
2297
2545
  let actions;
2298
2546
  const scheduledEffects = [];
2299
2547
  try {
@@ -2321,541 +2569,94 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2321
2569
  deps.clear();
2322
2570
  const wrappedActions = {};
2323
2571
  for (const [name, action] of Object.entries(actions)) {
2324
- const wrappedAction = (...args) => {
2325
- if (disposed) {
2326
- throw new Error(`Cannot call action on disposed store: ${storeId}`);
2327
- }
2328
- handleActionDispatch(
2329
- name,
2330
- args
2331
- );
2332
- if (options.onDispatch) {
2333
- const invocation = actionInvocations.get(name);
2334
- if (invocation) {
2335
- options.onDispatch(invocation);
2336
- }
2337
- }
2338
- try {
2339
- return action(...args);
2340
- } catch (error) {
2341
- if (options.onError) {
2342
- options.onError(error);
2343
- }
2344
- throw error;
2345
- }
2346
- };
2347
- wrappedAction.last = () => getActionLastInvocation(name);
2348
- wrappedActions[name] = wrappedAction;
2349
- }
2350
- instanceActions = wrappedActions;
2351
- return instance;
2352
- }
2353
- function container(options = {}) {
2354
- const { middleware = [] } = options;
2355
- const instancesBySpec = /* @__PURE__ */ new Map();
2356
- const instancesById = /* @__PURE__ */ new Map();
2357
- const creationOrder = [];
2358
- const createEmitter = emitter();
2359
- const disposeEmitter = emitter();
2360
- const creating = /* @__PURE__ */ new Set();
2361
- const resolver = {
2362
- get(specOrId) {
2363
- if (typeof specOrId === "string") {
2364
- return instancesById.get(specOrId);
2365
- }
2366
- return containerApi.get(specOrId);
2367
- },
2368
- has(spec) {
2369
- return instancesBySpec.has(spec);
2370
- }
2371
- };
2372
- function createInstance(spec) {
2373
- const instanceOptions = {};
2374
- if (spec.options.lifetime === "autoDispose") {
2375
- instanceOptions.onUnused = () => {
2376
- containerApi.dispose(spec);
2377
- };
2378
- }
2379
- return createStoreInstance(spec, resolver, instanceOptions);
2380
- }
2381
- function buildMiddlewareChain() {
2382
- let chain = (_spec, next) => next(_spec);
2383
- for (let i = middleware.length - 1; i >= 0; i--) {
2384
- const currentMiddleware = middleware[i];
2385
- const nextInChain = chain;
2386
- chain = (spec, next) => currentMiddleware(spec, (s) => nextInChain(s, next));
2387
- }
2388
- return (spec) => chain(spec, createInstance);
2389
- }
2390
- const createWithMiddleware = buildMiddlewareChain();
2391
- function getOrCreateInstance(spec) {
2392
- var _a;
2393
- let instance = instancesBySpec.get(spec);
2394
- if (instance) {
2395
- return instance;
2396
- }
2397
- if (creating.has(spec)) {
2398
- const name = spec.name ?? "unknown";
2572
+ if (typeof action !== "function") {
2399
2573
  throw new Error(
2400
- `Circular dependency detected: "${name}" is being created while it's already in the creation stack.`
2574
+ `Action "${name}" must be a function, got ${typeof action}. If using focus(), destructure it and return the getter/setter separately: const [get, set] = focus("path"); return { get, set };`
2401
2575
  );
2402
2576
  }
2403
- creating.add(spec);
2404
- try {
2405
- instance = untrack(() => createWithMiddleware(spec));
2406
- instancesBySpec.set(spec, instance);
2407
- instancesById.set(instance.id, instance);
2408
- creationOrder.push(spec);
2409
- (_a = instance.onDispose) == null ? void 0 : _a.call(instance, () => {
2410
- instancesBySpec.delete(spec);
2411
- instancesById.delete(instance.id);
2412
- const index = creationOrder.indexOf(spec);
2413
- if (index !== -1) {
2414
- creationOrder.splice(index, 1);
2577
+ const wrappedAction = wrapFn(action, (originalAction) => {
2578
+ const wrapper = (...args) => {
2579
+ if (disposed) {
2580
+ throw new Error(`Cannot call action on disposed store: ${storeId}`);
2415
2581
  }
2416
- });
2417
- createEmitter.emit(instance);
2418
- return instance;
2419
- } finally {
2420
- creating.delete(spec);
2421
- }
2422
- }
2423
- const containerApi = {
2424
- get(specOrId) {
2425
- if (typeof specOrId === "string") {
2426
- return instancesById.get(specOrId);
2427
- }
2428
- return getOrCreateInstance(specOrId);
2429
- },
2430
- has(spec) {
2431
- return instancesBySpec.has(spec);
2432
- },
2433
- clear() {
2434
- const specs = [...creationOrder].reverse();
2435
- for (const spec of specs) {
2436
- const instance = instancesBySpec.get(spec);
2437
- if (instance) {
2438
- disposeEmitter.emit(instance);
2439
- instance.dispose();
2440
- instancesById.delete(instance.id);
2441
- }
2442
- }
2443
- instancesBySpec.clear();
2444
- creationOrder.length = 0;
2445
- },
2446
- dispose(spec) {
2447
- const instance = instancesBySpec.get(spec);
2448
- if (!instance) return false;
2449
- disposeEmitter.emit(instance);
2450
- instance.dispose();
2451
- instancesBySpec.delete(spec);
2452
- instancesById.delete(instance.id);
2453
- const index = creationOrder.indexOf(spec);
2454
- if (index !== -1) {
2455
- creationOrder.splice(index, 1);
2456
- }
2457
- return true;
2458
- },
2459
- onCreate(listener) {
2460
- return createEmitter.on(listener);
2461
- },
2462
- onDispose(listener) {
2463
- return disposeEmitter.on(listener);
2464
- }
2465
- };
2466
- return containerApi;
2467
- }
2468
- let pickIdCounter = 0;
2469
- function pick(selector, equality) {
2470
- var _a;
2471
- const parentHooks = getHooks();
2472
- if (!parentHooks.onRead) {
2473
- throw new Error(
2474
- "pick() must be called inside an effect or useStore selector. It requires an active hooks.onRead context."
2475
- );
2476
- }
2477
- const equalityFn = resolveEquality(equality);
2478
- const currentReads = [];
2479
- const evaluate = () => {
2480
- currentReads.length = 0;
2481
- const value = withHooks(
2482
- {
2483
- onRead: (event) => {
2484
- currentReads.push(event);
2485
- }
2486
- },
2487
- selector
2488
- );
2489
- return value;
2490
- };
2491
- let currentValue = evaluate();
2492
- if (!currentReads.length) {
2493
- return currentValue;
2494
- }
2495
- const pickKey = `pick:${++pickIdCounter}`;
2496
- const subscribe = (listener) => {
2497
- const onCleanup = emitter();
2498
- const setupSubscriptions = () => {
2499
- for (const read of currentReads) {
2500
- const unsub = read.subscribe(handleChange);
2501
- onCleanup.on(unsub);
2502
- }
2503
- };
2504
- const clearSubscriptions = () => {
2505
- onCleanup.emitAndClear();
2506
- };
2507
- const handleChange = () => {
2508
- try {
2509
- const prevValue = currentValue;
2510
- clearSubscriptions();
2511
- currentValue = evaluate();
2512
- setupSubscriptions();
2513
- if (!equalityFn(prevValue, currentValue)) {
2514
- listener();
2515
- }
2516
- } catch (error) {
2517
- clearSubscriptions();
2518
- throw error;
2519
- }
2520
- };
2521
- setupSubscriptions();
2522
- return clearSubscriptions;
2523
- };
2524
- (_a = parentHooks.onRead) == null ? void 0 : _a.call(parentHooks, {
2525
- key: pickKey,
2526
- value: currentValue,
2527
- subscribe
2528
- });
2529
- return currentValue;
2530
- }
2531
- function createEffectContext(nth, isStale) {
2532
- let cleanupEmitter = null;
2533
- let abortController = null;
2534
- const runCleanups = () => {
2535
- if (abortController) {
2536
- abortController.abort();
2537
- abortController = null;
2538
- }
2539
- if (cleanupEmitter && cleanupEmitter.size > 0) {
2540
- cleanupEmitter.emitAndClearLifo();
2541
- }
2542
- };
2543
- const context = {
2544
- nth,
2545
- get signal() {
2546
- if (!abortController) {
2547
- abortController = new AbortController();
2548
- }
2549
- return abortController.signal;
2550
- },
2551
- onCleanup(listener) {
2552
- if (!cleanupEmitter) {
2553
- cleanupEmitter = emitter();
2554
- }
2555
- return cleanupEmitter.on(listener);
2556
- },
2557
- safe(promiseOrCallback) {
2558
- if (promiseOrCallback instanceof Promise) {
2559
- return new Promise((resolve, reject) => {
2560
- promiseOrCallback.then(
2561
- (value) => {
2562
- if (!isStale()) {
2563
- resolve(value);
2564
- }
2565
- },
2566
- (error) => {
2567
- if (!isStale()) {
2568
- reject(error);
2569
- }
2570
- }
2571
- );
2582
+ const actionNameKey = name;
2583
+ const nthKey = name;
2584
+ const nth = (actionNthCounters.get(nthKey) ?? 0) + 1;
2585
+ actionNthCounters.set(nthKey, nth);
2586
+ const prev = actionInvocations.get(nthKey);
2587
+ const next = Object.freeze({
2588
+ name: actionNameKey,
2589
+ args,
2590
+ nth,
2591
+ timestamp: Date.now()
2572
2592
  });
2573
- }
2574
- return (...args) => {
2575
- if (!isStale()) {
2576
- return promiseOrCallback(...args);
2593
+ actionInvocations.set(nthKey, next);
2594
+ const actionEmitter = actionEmitters.get(nthKey);
2595
+ if (actionEmitter.size > 0) {
2596
+ actionEmitter.emit({
2597
+ next,
2598
+ prev
2599
+ });
2577
2600
  }
2578
- return void 0;
2579
- };
2580
- }
2581
- };
2582
- return Object.assign(context, { _runCleanups: runCleanups });
2583
- }
2584
- function resolveErrorStrategy(effectOptions) {
2585
- return (effectOptions == null ? void 0 : effectOptions.onError) ?? "keepAlive";
2586
- }
2587
- function getRetryDelay(config, attempt) {
2588
- if (typeof config.delay === "function") {
2589
- return config.delay(attempt);
2590
- }
2591
- return config.delay ?? 100 * Math.pow(2, attempt);
2592
- }
2593
- function effect(fn, options) {
2594
- let currentContext = null;
2595
- let subscriptionEmitter = null;
2596
- let isStarted = false;
2597
- let isRunning = false;
2598
- let isDisposed = false;
2599
- let runGeneration = 0;
2600
- let retryCount = 0;
2601
- let retryTimeout = null;
2602
- let errorStrategy = "keepAlive";
2603
- let onErrorCallback = null;
2604
- let prevTrackedDeps = /* @__PURE__ */ new Map();
2605
- let prevSubscriptionEmitter = null;
2606
- let trackedDeps = /* @__PURE__ */ new Map();
2607
- const writtenProps = /* @__PURE__ */ new Set();
2608
- let newTrackedDeps = null;
2609
- const getSubscriptionEmitter = () => {
2610
- if (!subscriptionEmitter) {
2611
- subscriptionEmitter = emitter();
2612
- }
2613
- return subscriptionEmitter;
2614
- };
2615
- const clearSubscriptions = () => {
2616
- if (subscriptionEmitter && subscriptionEmitter.size > 0) {
2617
- subscriptionEmitter.emitAndClear();
2618
- }
2619
- };
2620
- const areDepsChanged = (prev, next) => {
2621
- if (prev.size !== next.size) return true;
2622
- for (const key of next.keys()) {
2623
- if (!prev.has(key)) return true;
2624
- }
2625
- return false;
2626
- };
2627
- const subscribeToTrackedDeps = () => {
2628
- for (const [key, dep] of trackedDeps) {
2629
- if (writtenProps.has(key)) continue;
2630
- const unsub = dep.subscribe(() => {
2631
- scheduleNotification(execute, fn);
2632
- });
2633
- getSubscriptionEmitter().on(unsub);
2634
- }
2635
- };
2636
- const handleError = (error) => {
2637
- onErrorCallback == null ? void 0 : onErrorCallback(error);
2638
- if (errorStrategy === "failFast") {
2639
- throw error;
2640
- }
2641
- if (errorStrategy === "keepAlive") {
2642
- console.error("Effect error (keepAlive):", error);
2643
- if (prevSubscriptionEmitter && prevSubscriptionEmitter.size > 0) {
2644
- trackedDeps = new Map(prevTrackedDeps);
2645
- subscriptionEmitter = prevSubscriptionEmitter;
2646
- prevSubscriptionEmitter = null;
2647
- return;
2648
- }
2649
- if (newTrackedDeps && newTrackedDeps.size > 0) {
2650
- trackedDeps = newTrackedDeps;
2651
- }
2652
- subscribeToTrackedDeps();
2653
- return;
2654
- }
2655
- if (typeof errorStrategy === "function") {
2656
- const retry = () => {
2657
- retryCount++;
2658
- execute();
2659
- };
2660
- errorStrategy({ error, retry, retryCount });
2661
- return;
2662
- }
2663
- const retryConfig = errorStrategy;
2664
- if (retryCount < retryConfig.maxRetries) {
2665
- const delay = getRetryDelay(retryConfig, retryCount);
2666
- retryCount++;
2667
- retryTimeout = setTimeout(() => {
2668
- retryTimeout = null;
2669
- execute();
2670
- }, delay);
2671
- } else {
2672
- console.error(
2673
- `Effect failed after ${retryConfig.maxRetries} retries:`,
2674
- error
2675
- );
2676
- }
2677
- };
2678
- let cachedHooks = null;
2679
- const getTrackingHooks = (current2) => {
2680
- if (!cachedHooks) {
2681
- cachedHooks = {
2682
- ...current2,
2683
- onRead: (event) => {
2684
- var _a;
2685
- (_a = current2.onRead) == null ? void 0 : _a.call(current2, event);
2686
- if (!newTrackedDeps.has(event.key)) {
2687
- newTrackedDeps.set(event.key, {
2688
- key: event.key,
2689
- value: event.value,
2690
- subscribe: event.subscribe
2601
+ if (options.onDispatch) {
2602
+ options.onDispatch(next);
2603
+ }
2604
+ try {
2605
+ const result = originalAction(...args);
2606
+ if (wildcardActionEmitter.size > 0) {
2607
+ wildcardActionEmitter.emit({
2608
+ next,
2609
+ prev
2691
2610
  });
2692
2611
  }
2693
- },
2694
- onWrite: (event) => {
2695
- var _a;
2696
- (_a = current2.onWrite) == null ? void 0 : _a.call(current2, event);
2697
- writtenProps.add(event.key);
2698
- },
2699
- scheduleNotification: current2.scheduleNotification,
2700
- scheduleEffect: current2.scheduleEffect
2701
- };
2702
- }
2703
- return cachedHooks;
2704
- };
2705
- const execute = () => {
2706
- if (isDisposed || isRunning) return;
2707
- isRunning = true;
2708
- const currentGeneration = ++runGeneration;
2709
- try {
2710
- currentContext == null ? void 0 : currentContext._runCleanups();
2711
- currentContext = null;
2712
- if (subscriptionEmitter && subscriptionEmitter.size > 0) {
2713
- prevTrackedDeps = new Map(trackedDeps);
2714
- prevSubscriptionEmitter = subscriptionEmitter;
2715
- subscriptionEmitter = null;
2716
- }
2717
- newTrackedDeps = /* @__PURE__ */ new Map();
2718
- writtenProps.clear();
2719
- const isStale = () => isDisposed || runGeneration !== currentGeneration;
2720
- let lazyContext = null;
2721
- const getOrCreateContext = () => {
2722
- if (!lazyContext) {
2723
- lazyContext = createEffectContext(currentGeneration, isStale);
2612
+ return result;
2613
+ } catch (error) {
2614
+ if (wildcardActionEmitter.size > 0) {
2615
+ wildcardActionEmitter.emit({
2616
+ next,
2617
+ prev
2618
+ });
2619
+ }
2620
+ if (options.onError) {
2621
+ options.onError(error);
2622
+ }
2623
+ throw error;
2724
2624
  }
2725
- return lazyContext;
2726
2625
  };
2727
- const lazyContextProxy = new Proxy({}, {
2728
- get(_, prop) {
2729
- return getOrCreateContext()[prop];
2730
- }
2731
- });
2732
- withHooks(getTrackingHooks, () => {
2733
- const result = fn(lazyContextProxy);
2734
- if (result !== null && result !== void 0 && typeof result.then === "function") {
2735
- throw new Error(
2736
- "Effect function must be synchronous. Use ctx.safe(promise) for async operations instead of returning a Promise."
2737
- );
2738
- }
2739
- });
2740
- currentContext = lazyContext;
2741
- retryCount = 0;
2742
- const depsChanged = areDepsChanged(trackedDeps, newTrackedDeps);
2743
- if (depsChanged) {
2744
- if (prevSubscriptionEmitter && prevSubscriptionEmitter.size > 0) {
2745
- prevSubscriptionEmitter.emitAndClear();
2746
- }
2747
- trackedDeps = newTrackedDeps;
2748
- subscribeToTrackedDeps();
2749
- } else {
2750
- if (prevSubscriptionEmitter) {
2751
- subscriptionEmitter = prevSubscriptionEmitter;
2752
- }
2753
- }
2754
- prevTrackedDeps.clear();
2755
- prevSubscriptionEmitter = null;
2756
- } catch (error) {
2757
- handleError(error);
2758
- } finally {
2759
- isRunning = false;
2760
- }
2761
- };
2762
- const dispose = () => {
2763
- if (isDisposed) return;
2764
- isDisposed = true;
2765
- runGeneration++;
2766
- if (retryTimeout) {
2767
- clearTimeout(retryTimeout);
2768
- retryTimeout = null;
2769
- }
2770
- currentContext == null ? void 0 : currentContext._runCleanups();
2771
- currentContext = null;
2772
- clearSubscriptions();
2773
- if (prevSubscriptionEmitter && prevSubscriptionEmitter.size > 0) {
2774
- prevSubscriptionEmitter.emitAndClear();
2775
- }
2776
- };
2777
- const start = (runOptions) => {
2778
- if (isStarted) return;
2779
- isStarted = true;
2780
- errorStrategy = resolveErrorStrategy(options);
2781
- onErrorCallback = (runOptions == null ? void 0 : runOptions.onError) ?? null;
2782
- execute();
2783
- };
2784
- getHooks().scheduleEffect((runOptions) => {
2785
- start(runOptions);
2786
- return dispose;
2787
- });
2788
- return dispose;
2789
- }
2790
- function patternToPredicate(pattern) {
2791
- if (pattern instanceof RegExp) {
2792
- return (name) => pattern.test(name);
2793
- }
2794
- const startsWithWildcard = pattern.startsWith("*");
2795
- const endsWithWildcard = pattern.endsWith("*");
2796
- if (startsWithWildcard && endsWithWildcard) {
2797
- const substr = pattern.slice(1, -1);
2798
- return (name) => name.includes(substr);
2799
- }
2800
- if (startsWithWildcard) {
2801
- const suffix = pattern.slice(1);
2802
- return (name) => name.endsWith(suffix);
2803
- }
2804
- if (endsWithWildcard) {
2805
- const prefix = pattern.slice(0, -1);
2806
- return (name) => name.startsWith(prefix);
2807
- }
2808
- return (name) => name === pattern;
2809
- }
2810
- function patternsToPredicate(patterns) {
2811
- if (Array.isArray(patterns)) {
2812
- const predicates = patterns.map(patternToPredicate);
2813
- return (spec) => predicates.some((p) => p(spec.name));
2814
- }
2815
- const predicate = patternToPredicate(patterns);
2816
- return (spec) => predicate(spec.name);
2817
- }
2818
- function compose(...middlewares) {
2819
- if (middlewares.length === 0) {
2820
- return (spec, next) => next(spec);
2821
- }
2822
- if (middlewares.length === 1) {
2823
- return middlewares[0];
2626
+ wrapper.last = () => getActionLastInvocation(name);
2627
+ return wrapper;
2628
+ });
2629
+ wrappedActions[name] = wrappedAction;
2824
2630
  }
2825
- return (spec, next) => {
2826
- let chain = next;
2827
- for (let i = middlewares.length - 1; i >= 0; i--) {
2828
- const middleware = middlewares[i];
2829
- const prevChain = chain;
2830
- chain = (s) => middleware(s, prevChain);
2831
- }
2832
- return chain(spec);
2833
- };
2834
- }
2835
- function applyFor(predicateOrPatterns, middleware) {
2836
- const predicate = typeof predicateOrPatterns === "function" ? predicateOrPatterns : patternsToPredicate(predicateOrPatterns);
2837
- const composedMiddleware = Array.isArray(middleware) ? compose(...middleware) : middleware;
2838
- return (spec, next) => {
2839
- if (predicate(spec)) {
2840
- return composedMiddleware(spec, next);
2841
- }
2842
- return next(spec);
2843
- };
2844
- }
2845
- function applyExcept(predicateOrPatterns, middleware) {
2846
- const matchPredicate = typeof predicateOrPatterns === "function" ? predicateOrPatterns : patternsToPredicate(predicateOrPatterns);
2847
- const invertedPredicate = (spec) => !matchPredicate(spec);
2848
- return applyFor(invertedPredicate, middleware);
2631
+ instanceActions = wrappedActions;
2632
+ return instance;
2849
2633
  }
2850
2634
  export {
2851
- applyFor as a,
2852
- batch as b,
2853
- container as c,
2854
- applyExcept as d,
2855
- effect as e,
2856
- compose as f,
2857
- pick as p,
2635
+ STORION_TYPE as S,
2636
+ is$1 as a,
2637
+ isStorion as b,
2638
+ createStoreInstance as c,
2639
+ isContainer as d,
2640
+ emitter as e,
2641
+ isStore as f,
2642
+ getKind as g,
2643
+ isFocus as h,
2644
+ isSpec as i,
2645
+ isAction as j,
2646
+ isStoreContext as k,
2647
+ isSelectorContext as l,
2648
+ batch as m,
2649
+ equality as n,
2650
+ shallowEqual as o,
2651
+ deepEqual as p,
2652
+ strictEqual as q,
2653
+ resolveEquality as r,
2858
2654
  store as s,
2655
+ wrapFn as t,
2859
2656
  untrack as u,
2860
- withHooks as w
2657
+ unwrapFn as v,
2658
+ withHooks as w,
2659
+ isWrappedFn as x,
2660
+ getHooks as y,
2661
+ scheduleNotification as z
2861
2662
  };