storion 0.2.2 → 0.3.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 (88) hide show
  1. package/README.md +721 -456
  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/equality.d.ts +23 -3
  16. package/dist/core/equality.d.ts.map +1 -1
  17. package/dist/core/fnWrapper.d.ts +54 -0
  18. package/dist/core/fnWrapper.d.ts.map +1 -0
  19. package/dist/core/pick.d.ts +6 -6
  20. package/dist/core/pick.d.ts.map +1 -1
  21. package/dist/core/store.d.ts +8 -8
  22. package/dist/core/store.d.ts.map +1 -1
  23. package/dist/core/storeContext.d.ts +63 -0
  24. package/dist/core/storeContext.d.ts.map +1 -0
  25. package/dist/devtools/controller.d.ts +4 -0
  26. package/dist/devtools/controller.d.ts.map +1 -0
  27. package/dist/devtools/index.d.ts +16 -0
  28. package/dist/devtools/index.d.ts.map +1 -0
  29. package/dist/devtools/index.js +229 -0
  30. package/dist/devtools/middleware.d.ts +22 -0
  31. package/dist/devtools/middleware.d.ts.map +1 -0
  32. package/dist/devtools/types.d.ts +116 -0
  33. package/dist/devtools/types.d.ts.map +1 -0
  34. package/dist/devtools-panel/DevtoolsPanel.d.ts +17 -0
  35. package/dist/devtools-panel/DevtoolsPanel.d.ts.map +1 -0
  36. package/dist/devtools-panel/components/CompareModal.d.ts +10 -0
  37. package/dist/devtools-panel/components/CompareModal.d.ts.map +1 -0
  38. package/dist/devtools-panel/components/EventEntry.d.ts +14 -0
  39. package/dist/devtools-panel/components/EventEntry.d.ts.map +1 -0
  40. package/dist/devtools-panel/components/EventFilterBar.d.ts +10 -0
  41. package/dist/devtools-panel/components/EventFilterBar.d.ts.map +1 -0
  42. package/dist/devtools-panel/components/EventsTab.d.ts +15 -0
  43. package/dist/devtools-panel/components/EventsTab.d.ts.map +1 -0
  44. package/dist/devtools-panel/components/ResizeHandle.d.ts +8 -0
  45. package/dist/devtools-panel/components/ResizeHandle.d.ts.map +1 -0
  46. package/dist/devtools-panel/components/StoreEntry.d.ts +13 -0
  47. package/dist/devtools-panel/components/StoreEntry.d.ts.map +1 -0
  48. package/dist/devtools-panel/components/StoresTab.d.ts +12 -0
  49. package/dist/devtools-panel/components/StoresTab.d.ts.map +1 -0
  50. package/dist/devtools-panel/components/TabLayout.d.ts +48 -0
  51. package/dist/devtools-panel/components/TabLayout.d.ts.map +1 -0
  52. package/dist/devtools-panel/components/icons.d.ts +27 -0
  53. package/dist/devtools-panel/components/icons.d.ts.map +1 -0
  54. package/dist/devtools-panel/components/index.d.ts +15 -0
  55. package/dist/devtools-panel/components/index.d.ts.map +1 -0
  56. package/dist/devtools-panel/hooks.d.ts +23 -0
  57. package/dist/devtools-panel/hooks.d.ts.map +1 -0
  58. package/dist/devtools-panel/index.d.ts +25 -0
  59. package/dist/devtools-panel/index.d.ts.map +1 -0
  60. package/dist/devtools-panel/index.js +3326 -0
  61. package/dist/devtools-panel/mount.d.ts +41 -0
  62. package/dist/devtools-panel/mount.d.ts.map +1 -0
  63. package/dist/devtools-panel/styles.d.ts +50 -0
  64. package/dist/devtools-panel/styles.d.ts.map +1 -0
  65. package/dist/devtools-panel/types.d.ts +15 -0
  66. package/dist/devtools-panel/types.d.ts.map +1 -0
  67. package/dist/devtools-panel/utils.d.ts +21 -0
  68. package/dist/devtools-panel/utils.d.ts.map +1 -0
  69. package/dist/index.d.ts +6 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/is.d.ts +69 -0
  72. package/dist/is.d.ts.map +1 -0
  73. package/dist/react/create.d.ts +1 -1
  74. package/dist/react/index.d.ts +1 -0
  75. package/dist/react/index.d.ts.map +1 -1
  76. package/dist/react/index.js +209 -33
  77. package/dist/react/useLocalStore.d.ts.map +1 -1
  78. package/dist/react/useStore.d.ts +2 -2
  79. package/dist/react/useStore.d.ts.map +1 -1
  80. package/dist/react/withStore.d.ts +140 -0
  81. package/dist/react/withStore.d.ts.map +1 -0
  82. package/dist/{index-rLf6DusB.js → store-XP2pujaJ.js} +537 -740
  83. package/dist/storion.js +740 -9
  84. package/dist/trigger.d.ts +40 -0
  85. package/dist/trigger.d.ts.map +1 -0
  86. package/dist/types.d.ts +516 -50
  87. package/dist/types.d.ts.map +1 -1
  88. 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,80 @@ function emitter(initialListeners) {
1911
2156
  }
1912
2157
  };
1913
2158
  }
2159
+ function collection(createItem, initialItems) {
2160
+ const map = /* @__PURE__ */ new Map([]);
2161
+ return {
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
+ }
2210
+ };
2211
+ }
1914
2212
  function store(options) {
1915
2213
  const name = options.name ?? generateSpecName();
1916
- return {
1917
- name,
1918
- options
2214
+ const spec = function(resolver) {
2215
+ return createStoreInstance(spec, resolver, {});
1919
2216
  };
2217
+ Object.defineProperties(spec, {
2218
+ [STORION_TYPE]: { value: "store.spec", enumerable: false },
2219
+ name: { value: name, enumerable: true, writable: false },
2220
+ options: { value: options, enumerable: true, writable: false }
2221
+ });
2222
+ return spec;
1920
2223
  }
1921
2224
  function createStoreInstance(spec, resolver, instanceOptions = {}) {
2225
+ var _a;
1922
2226
  const options = spec.options;
1923
2227
  const storeId = generateStoreId(spec.name);
1924
2228
  let disposed = false;
1925
2229
  let currentState = { ...options.state };
1926
2230
  let initialState = currentState;
1927
2231
  const isAutoDispose = options.lifetime === "autoDispose";
1928
- const gracePeriodMs = instanceOptions.gracePeriodMs ?? 100;
2232
+ const gracePeriodMs = ((_a = instanceOptions.autoDispose) == null ? void 0 : _a.gracePeriodMs) ?? 100;
1929
2233
  let refCount = 0;
1930
2234
  let disposeTimeout = null;
1931
2235
  const incrementRef = () => {
@@ -1942,39 +2246,26 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
1942
2246
  if (!isAutoDispose || isSetupPhase) {
1943
2247
  return;
1944
2248
  }
2249
+ disposeTimeout && clearTimeout(disposeTimeout);
1945
2250
  refCount--;
1946
- if (refCount <= 0 && instanceOptions.onUnused) {
2251
+ if (refCount <= 0) {
1947
2252
  disposeTimeout = setTimeout(() => {
1948
2253
  disposeTimeout = null;
1949
- if (refCount <= 0 && !disposed) {
1950
- instanceOptions.onUnused();
2254
+ if (refCount <= 0) {
2255
+ instance == null ? void 0 : instance.dispose();
1951
2256
  }
1952
2257
  }, gracePeriodMs);
1953
2258
  }
1954
2259
  };
1955
2260
  const changeEmitter = emitter();
1956
2261
  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
- };
2262
+ const propertyEmitters = collection(() => emitter());
1966
2263
  const actionInvocations = /* @__PURE__ */ new Map();
1967
2264
  const actionNthCounters = /* @__PURE__ */ new Map();
1968
- const actionEmitters = /* @__PURE__ */ new Map();
2265
+ const actionEmitters = collection(
2266
+ () => emitter()
2267
+ );
1969
2268
  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
2269
  const disposeEffectsEmitter = emitter();
1979
2270
  const equalityOption = options.equality;
1980
2271
  const propertyEquality = /* @__PURE__ */ new Map();
@@ -1998,45 +2289,21 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
1998
2289
  }
1999
2290
  const getEquality = (key) => propertyEquality.get(key) ?? defaultEquality ?? strictEqual;
2000
2291
  const isEqual2 = hasCustomEquality ? (key, a, b) => getEquality(key)(a, b) : (_key, a, b) => a === b;
2292
+ let isSetupPhase = true;
2001
2293
  function handlePropertyChange(key, oldValue, newValue) {
2002
- const propEmitter = propertyEmitters.get(key);
2003
- if (propEmitter) {
2004
- propEmitter.emit({ newValue, oldValue });
2294
+ if (isSetupPhase) {
2295
+ return;
2005
2296
  }
2297
+ propertyEmitters.with(
2298
+ key,
2299
+ (em) => em.emit({ newValue, oldValue })
2300
+ );
2006
2301
  scheduleNotification(() => {
2007
2302
  changeEmitter.emit();
2008
2303
  });
2009
2304
  }
2010
2305
  let instance = null;
2011
2306
  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
2307
  function getActionLastInvocation(actionName) {
2041
2308
  const propKey = `@${String(actionName)}`;
2042
2309
  const invocation = actionInvocations.get(String(actionName));
@@ -2048,6 +2315,7 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2048
2315
  }
2049
2316
  let instanceActions = {};
2050
2317
  instance = {
2318
+ [STORION_TYPE]: "store",
2051
2319
  id: storeId,
2052
2320
  spec,
2053
2321
  deps: [],
@@ -2077,15 +2345,14 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2077
2345
  }
2078
2346
  if (key.startsWith("@")) {
2079
2347
  const actionName = key.slice(1);
2080
- const actionEmitter = getActionEmitter(actionName);
2081
- const unsub2 = actionEmitter.on(propListener);
2348
+ const unsub2 = actionEmitters.get(actionName).on(propListener);
2082
2349
  return () => {
2083
2350
  unsub2();
2084
2351
  decrementRef();
2085
2352
  };
2086
2353
  }
2087
2354
  const propKey = listenerOrPropKey;
2088
- const propEmitter = getPropertyEmitter(propKey);
2355
+ const propEmitter = propertyEmitters.get(propKey);
2089
2356
  const unsub = propEmitter.on(({ newValue, oldValue }) => {
2090
2357
  propListener({ next: newValue, prev: oldValue });
2091
2358
  });
@@ -2099,11 +2366,9 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2099
2366
  const key = propKey;
2100
2367
  if (key.startsWith("@")) {
2101
2368
  const actionName = key.slice(1);
2102
- const actionEmitter = getActionEmitter(actionName);
2103
- return actionEmitter.on(listener);
2369
+ return actionEmitters.get(actionName).on(listener);
2104
2370
  }
2105
- const propEmitter = getPropertyEmitter(propKey);
2106
- return propEmitter.on(listener);
2371
+ return propertyEmitters.get(propKey).on(listener);
2107
2372
  },
2108
2373
  dispose() {
2109
2374
  if (disposed) return;
@@ -2203,97 +2468,76 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2203
2468
  }
2204
2469
  const mutableState = createReactiveState(true);
2205
2470
  const readonlyState = createReactiveState(false);
2206
- let isSetupPhase = true;
2207
2471
  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
- }
2472
+ function updateState(updaterOrPartial) {
2473
+ let nextState = currentState;
2474
+ if (typeof updaterOrPartial === "function") {
2475
+ const updater = updaterOrPartial;
2476
+ nextState = produce(currentState, updater);
2477
+ } else {
2478
+ nextState = produce(currentState, (draft) => {
2479
+ Object.assign(draft, updaterOrPartial);
2480
+ });
2481
+ }
2482
+ if (nextState === currentState) return;
2483
+ const prevState = currentState;
2484
+ const changedProps = [];
2485
+ if (!hasCustomEquality) {
2486
+ for (const key of Object.keys(nextState)) {
2487
+ if (prevState[key] !== nextState[key]) {
2488
+ changedProps.push({
2489
+ key,
2490
+ oldValue: prevState[key],
2491
+ newValue: nextState[key]
2492
+ });
2251
2493
  }
2252
- if (changedProps.length > 0) {
2253
- currentState = nextState;
2494
+ }
2495
+ if (changedProps.length > 0) {
2496
+ currentState = nextState;
2497
+ batch(() => {
2254
2498
  for (const { key, oldValue, newValue } of changedProps) {
2255
2499
  handlePropertyChange(key, oldValue, newValue);
2256
2500
  }
2257
- }
2258
- return;
2501
+ });
2259
2502
  }
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
- }
2503
+ return;
2504
+ }
2505
+ const stableState = { ...nextState };
2506
+ for (const key of Object.keys(nextState)) {
2507
+ if (prevState[key] !== nextState[key]) {
2508
+ const equality2 = getEquality(key);
2509
+ if (equality2(prevState[key], nextState[key])) {
2510
+ stableState[key] = prevState[key];
2511
+ } else {
2512
+ changedProps.push({
2513
+ key,
2514
+ oldValue: prevState[key],
2515
+ newValue: nextState[key]
2516
+ });
2273
2517
  }
2274
2518
  }
2275
- if (changedProps.length > 0) {
2276
- currentState = stableState;
2519
+ }
2520
+ if (changedProps.length > 0) {
2521
+ currentState = stableState;
2522
+ batch(() => {
2277
2523
  for (const { key, oldValue, newValue } of changedProps) {
2278
2524
  handlePropertyChange(key, oldValue, newValue);
2279
2525
  }
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);
2526
+ });
2295
2527
  }
2296
- };
2528
+ }
2529
+ const setupContext = createStoreContext({
2530
+ spec,
2531
+ resolver,
2532
+ getMutableState: () => mutableState,
2533
+ update: updateState,
2534
+ subscribe: (listener) => changeEmitter.on(listener),
2535
+ dirty: (prop) => instance.dirty(prop),
2536
+ reset: () => instance.reset(),
2537
+ onDependency: (depInstance) => deps.add(depInstance),
2538
+ onDispose: (callback) => disposeEmitter.on(callback),
2539
+ isSetupPhase: () => isSetupPhase
2540
+ });
2297
2541
  let actions;
2298
2542
  const scheduledEffects = [];
2299
2543
  try {
@@ -2321,541 +2565,94 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2321
2565
  deps.clear();
2322
2566
  const wrappedActions = {};
2323
2567
  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";
2568
+ if (typeof action !== "function") {
2399
2569
  throw new Error(
2400
- `Circular dependency detected: "${name}" is being created while it's already in the creation stack.`
2570
+ `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
2571
  );
2402
2572
  }
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);
2573
+ const wrappedAction = wrapFn(action, (originalAction) => {
2574
+ const wrapper = (...args) => {
2575
+ if (disposed) {
2576
+ throw new Error(`Cannot call action on disposed store: ${storeId}`);
2415
2577
  }
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
- );
2578
+ const actionNameKey = name;
2579
+ const nthKey = name;
2580
+ const nth = (actionNthCounters.get(nthKey) ?? 0) + 1;
2581
+ actionNthCounters.set(nthKey, nth);
2582
+ const prev = actionInvocations.get(nthKey);
2583
+ const next = Object.freeze({
2584
+ name: actionNameKey,
2585
+ args,
2586
+ nth,
2587
+ timestamp: Date.now()
2572
2588
  });
2573
- }
2574
- return (...args) => {
2575
- if (!isStale()) {
2576
- return promiseOrCallback(...args);
2589
+ actionInvocations.set(nthKey, next);
2590
+ const actionEmitter = actionEmitters.get(nthKey);
2591
+ if (actionEmitter.size > 0) {
2592
+ actionEmitter.emit({
2593
+ next,
2594
+ prev
2595
+ });
2577
2596
  }
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
2597
+ if (options.onDispatch) {
2598
+ options.onDispatch(next);
2599
+ }
2600
+ try {
2601
+ const result = originalAction(...args);
2602
+ if (wildcardActionEmitter.size > 0) {
2603
+ wildcardActionEmitter.emit({
2604
+ next,
2605
+ prev
2691
2606
  });
2692
2607
  }
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);
2608
+ return result;
2609
+ } catch (error) {
2610
+ if (wildcardActionEmitter.size > 0) {
2611
+ wildcardActionEmitter.emit({
2612
+ next,
2613
+ prev
2614
+ });
2615
+ }
2616
+ if (options.onError) {
2617
+ options.onError(error);
2618
+ }
2619
+ throw error;
2724
2620
  }
2725
- return lazyContext;
2726
2621
  };
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];
2622
+ wrapper.last = () => getActionLastInvocation(name);
2623
+ return wrapper;
2624
+ });
2625
+ wrappedActions[name] = wrappedAction;
2824
2626
  }
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);
2627
+ instanceActions = wrappedActions;
2628
+ return instance;
2849
2629
  }
2850
2630
  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,
2631
+ STORION_TYPE as S,
2632
+ is$1 as a,
2633
+ isStorion as b,
2634
+ createStoreInstance as c,
2635
+ isContainer as d,
2636
+ emitter as e,
2637
+ isStore as f,
2638
+ getKind as g,
2639
+ isFocus as h,
2640
+ isSpec as i,
2641
+ isAction as j,
2642
+ isStoreContext as k,
2643
+ isSelectorContext as l,
2644
+ batch as m,
2645
+ equality as n,
2646
+ shallowEqual as o,
2647
+ deepEqual as p,
2648
+ strictEqual as q,
2649
+ resolveEquality as r,
2858
2650
  store as s,
2651
+ wrapFn as t,
2859
2652
  untrack as u,
2860
- withHooks as w
2653
+ unwrapFn as v,
2654
+ withHooks as w,
2655
+ isWrappedFn as x,
2656
+ getHooks as y,
2657
+ scheduleNotification as z
2861
2658
  };