storion 0.4.0 → 0.6.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.
@@ -1729,6 +1729,28 @@ function resolveEquality(e) {
1729
1729
  function equality(shorthand) {
1730
1730
  return resolveEquality(shorthand);
1731
1731
  }
1732
+ function tryDispose(value) {
1733
+ if (isDisposable(value)) {
1734
+ const dispose = value.dispose;
1735
+ if (Array.isArray(dispose)) {
1736
+ for (const item of dispose) {
1737
+ if (typeof item === "function") {
1738
+ item();
1739
+ } else {
1740
+ tryDispose(item);
1741
+ }
1742
+ }
1743
+ } else if (typeof dispose === "function") {
1744
+ dispose();
1745
+ }
1746
+ }
1747
+ }
1748
+ function isDisposable(value) {
1749
+ return (typeof value === "object" || typeof value === "function") && !!value && "dispose" in value;
1750
+ }
1751
+ function willDispose(value) {
1752
+ return () => tryDispose(value);
1753
+ }
1732
1754
  function getAtPath(obj, segments) {
1733
1755
  let current2 = obj;
1734
1756
  for (const key of segments) {
@@ -1864,18 +1886,16 @@ function createStoreContext(options) {
1864
1886
  actions: instance.actions
1865
1887
  });
1866
1888
  },
1867
- // Implementation handles both StoreSpec and Factory overloads
1868
- create(specOrFactory) {
1889
+ // Implementation handles StoreSpec, Factory, and parameterized Factory overloads
1890
+ create(specOrFactory, ...args) {
1869
1891
  if (!isSetupPhase()) {
1870
1892
  throw new Error(
1871
1893
  `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
1894
  );
1873
1895
  }
1874
1896
  if (!isSpec(specOrFactory)) {
1875
- const instance2 = specOrFactory(resolver);
1876
- if (instance2 && typeof instance2.dispose === "function") {
1877
- onDispose == null ? void 0 : onDispose(instance2.dispose);
1878
- }
1897
+ const instance2 = specOrFactory(resolver, ...args);
1898
+ onDispose == null ? void 0 : onDispose(willDispose(instance2));
1879
1899
  return instance2;
1880
1900
  }
1881
1901
  const childSpec = specOrFactory;
@@ -1888,7 +1908,7 @@ function createStoreContext(options) {
1888
1908
  );
1889
1909
  }
1890
1910
  const instance = resolver.create(childSpec);
1891
- onDispose == null ? void 0 : onDispose(instance.dispose);
1911
+ onDispose == null ? void 0 : onDispose(willDispose(instance));
1892
1912
  return instance;
1893
1913
  },
1894
1914
  update: createUpdateFn(update),
@@ -1898,6 +1918,9 @@ function createStoreContext(options) {
1898
1918
  reset() {
1899
1919
  reset();
1900
1920
  },
1921
+ onDispose(callback) {
1922
+ onDispose == null ? void 0 : onDispose(callback);
1923
+ },
1901
1924
  mixin(mixin, ...args) {
1902
1925
  if (!isSetupPhase()) {
1903
1926
  throw new Error(
@@ -2632,6 +2655,7 @@ function createStoreInstance(spec, resolver, instanceOptions = {}) {
2632
2655
  return instance;
2633
2656
  }
2634
2657
  export {
2658
+ scheduleNotification as A,
2635
2659
  STORION_TYPE as S,
2636
2660
  is$1 as a,
2637
2661
  isStorion as b,
@@ -2657,6 +2681,6 @@ export {
2657
2681
  unwrapFn as v,
2658
2682
  withHooks as w,
2659
2683
  isWrappedFn as x,
2660
- getHooks as y,
2661
- scheduleNotification as z
2684
+ tryDispose as y,
2685
+ getHooks as z
2662
2686
  };
package/dist/storion.js CHANGED
@@ -1,201 +1,5 @@
1
- import { e as emitter, i as isSpec, S as STORION_TYPE, u as untrack, y as getHooks, w as withHooks, r as resolveEquality, z as scheduleNotification, v as unwrapFn, o as shallowEqual } from "./store-Yv-9gPVf.js";
2
- import { m, p, n, g, a, j, d, h, l, f, k, b, x, s, q, t } from "./store-Yv-9gPVf.js";
3
- let defaultMiddlewareConfig = {};
4
- const container = function(options = {}) {
5
- const middleware = [
6
- ...defaultMiddlewareConfig.pre ?? [],
7
- ...options.middleware ?? [],
8
- ...defaultMiddlewareConfig.post ?? []
9
- ];
10
- const cache2 = /* @__PURE__ */ new Map();
11
- const factoryCache = /* @__PURE__ */ new Map();
12
- const instancesById = /* @__PURE__ */ new Map();
13
- const overrides = /* @__PURE__ */ new Map();
14
- const factoryOverrides = /* @__PURE__ */ new Map();
15
- const creationOrder = [];
16
- const createEmitter = emitter();
17
- const disposeEmitter = emitter();
18
- const creating = /* @__PURE__ */ new Set();
19
- const creatingFactories = /* @__PURE__ */ new Set();
20
- const parent = options._parent;
21
- const resolve = (spec) => overrides.get(spec) ?? spec;
22
- function buildMiddlewareChain() {
23
- return (spec) => {
24
- let index = 0;
25
- const executeNext = () => {
26
- if (index >= middleware.length) {
27
- return spec(containerApi);
28
- }
29
- const currentMiddleware = middleware[index];
30
- index++;
31
- const ctx = {
32
- spec,
33
- factory: spec,
34
- resolver: containerApi,
35
- next: executeNext,
36
- displayName: spec.displayName
37
- };
38
- return currentMiddleware(ctx);
39
- };
40
- return executeNext();
41
- };
42
- }
43
- const createWithMiddleware = buildMiddlewareChain();
44
- function createInstance(spec) {
45
- const instance = untrack(() => createWithMiddleware(spec));
46
- if (typeof instance.onDispose === "function") {
47
- instance.onDispose(() => {
48
- disposeEmitter.emit(instance);
49
- cache2.delete(spec);
50
- instancesById.delete(instance.id);
51
- const index = creationOrder.indexOf(spec);
52
- if (index !== -1) {
53
- creationOrder.splice(index, 1);
54
- }
55
- });
56
- }
57
- return instance;
58
- }
59
- const containerApi = {
60
- [STORION_TYPE]: "container",
61
- // ========================================================================
62
- // Resolver Methods
63
- // ========================================================================
64
- // Implementation handles multiple overloads
65
- get(specOrIdOrFactory) {
66
- if (typeof specOrIdOrFactory === "string") {
67
- return instancesById.get(specOrIdOrFactory);
68
- }
69
- if (!isSpec(specOrIdOrFactory)) {
70
- const factory = specOrIdOrFactory;
71
- if (factoryCache.has(factory)) {
72
- return factoryCache.get(factory);
73
- }
74
- if (parent && factoryOverrides.size === 0 && "tryGet" in parent && typeof parent.tryGet === "function") {
75
- const parentInstance = parent.tryGet(factory);
76
- if (parentInstance !== void 0) {
77
- return parentInstance;
78
- }
79
- }
80
- if (creatingFactories.has(factory)) {
81
- const name = factory.name || "anonymous";
82
- throw new Error(
83
- `Circular dependency detected: factory "${name}" is being created while already in creation stack.`
84
- );
85
- }
86
- creatingFactories.add(factory);
87
- try {
88
- const mapped = factoryOverrides.get(factory) ?? factory;
89
- const instance = mapped(containerApi);
90
- factoryCache.set(factory, instance);
91
- return instance;
92
- } finally {
93
- creatingFactories.delete(factory);
94
- }
95
- }
96
- const spec = specOrIdOrFactory;
97
- if (cache2.has(spec)) {
98
- return cache2.get(spec);
99
- }
100
- if (parent && overrides.size === 0 && parent.has(spec)) {
101
- return parent.get(spec);
102
- }
103
- if (creating.has(spec)) {
104
- const name = spec.displayName ?? "unknown";
105
- throw new Error(
106
- `Circular dependency detected: "${name}" is being created while already in creation stack.`
107
- );
108
- }
109
- creating.add(spec);
110
- try {
111
- const mapped = resolve(spec);
112
- const instance = createInstance(mapped);
113
- cache2.set(spec, instance);
114
- instancesById.set(instance.id, instance);
115
- creationOrder.push(spec);
116
- createEmitter.emit(instance);
117
- return instance;
118
- } finally {
119
- creating.delete(spec);
120
- }
121
- },
122
- // Implementation handles both StoreSpec and Factory overloads
123
- create(specOrFactory) {
124
- if (!isSpec(specOrFactory)) {
125
- const factory = specOrFactory;
126
- const mapped2 = factoryOverrides.get(factory) ?? factory;
127
- return mapped2(containerApi);
128
- }
129
- const mapped = resolve(specOrFactory);
130
- return createInstance(mapped);
131
- },
132
- set(spec, override) {
133
- overrides.set(spec, override);
134
- const existing = cache2.get(spec);
135
- if (existing) {
136
- existing.dispose();
137
- }
138
- },
139
- has(spec) {
140
- const inParent = parent && overrides.size === 0 && parent.has(spec);
141
- return cache2.has(spec) || (inParent ?? false);
142
- },
143
- tryGet(spec) {
144
- if (cache2.has(spec)) {
145
- return cache2.get(spec);
146
- }
147
- if (parent && overrides.size === 0) {
148
- return parent.tryGet(spec);
149
- }
150
- return void 0;
151
- },
152
- delete(spec) {
153
- const instance = cache2.get(spec);
154
- if (instance) {
155
- instance.dispose();
156
- return true;
157
- }
158
- return false;
159
- },
160
- // ========================================================================
161
- // Container-Specific Methods
162
- // ========================================================================
163
- clear() {
164
- const specs = [...creationOrder].reverse();
165
- for (const spec of specs) {
166
- const instance = cache2.get(spec);
167
- if (instance) {
168
- instance.dispose();
169
- }
170
- }
171
- cache2.clear();
172
- instancesById.clear();
173
- creationOrder.length = 0;
174
- },
175
- dispose(spec) {
176
- return containerApi.delete(spec);
177
- },
178
- scope(scopeOptions = {}) {
179
- return container({
180
- middleware: scopeOptions.middleware ?? middleware,
181
- _parent: containerApi
182
- });
183
- },
184
- onCreate: createEmitter.on,
185
- onDispose: disposeEmitter.on
186
- };
187
- return containerApi;
188
- };
189
- const defaultsFn = (config = {}) => {
190
- defaultMiddlewareConfig = {
191
- pre: [...defaultMiddlewareConfig.pre ?? [], ...config.pre ?? []],
192
- post: [...defaultMiddlewareConfig.post ?? [], ...config.post ?? []]
193
- };
194
- };
195
- defaultsFn.clear = () => {
196
- defaultMiddlewareConfig = {};
197
- };
198
- container.defaults = defaultsFn;
1
+ import { y as tryDispose, i as isSpec, e as emitter, u as untrack, S as STORION_TYPE, z as getHooks, w as withHooks, r as resolveEquality, A as scheduleNotification, v as unwrapFn, o as shallowEqual } from "./store-DS-4XdM6.js";
2
+ import { m, p, n, g, a, j, d, h, l, f, k, b, x, s, q, t } from "./store-DS-4XdM6.js";
199
3
  function extractDisplayName(factory) {
200
4
  if (isSpec(factory)) {
201
5
  return factory.displayName;
@@ -209,20 +13,41 @@ function extractDisplayName(factory) {
209
13
  return void 0;
210
14
  }
211
15
  function createResolver(options = {}) {
212
- const { middleware = [], parent } = options;
16
+ const {
17
+ middleware = [],
18
+ parent,
19
+ invokeResolver: invokeResolverOption
20
+ } = options;
213
21
  const cache2 = /* @__PURE__ */ new Map();
214
22
  const overrides = /* @__PURE__ */ new Map();
215
23
  const resolve = (factory) => overrides.get(factory) ?? factory;
216
- const invoke = (factory, resolver2) => {
24
+ const invoke = (factory, resolverForCtx) => {
25
+ const isStoreSpec = isSpec(factory);
217
26
  const displayName = extractDisplayName(factory);
218
27
  const chain = middleware.reduceRight(
219
- (next, mw) => () => mw({
220
- factory,
221
- resolver: resolver2,
222
- next,
223
- displayName
224
- }),
225
- () => factory(resolver2)
28
+ (next, mw) => () => {
29
+ if (isStoreSpec) {
30
+ const ctx = {
31
+ type: "store",
32
+ factory,
33
+ resolver: resolverForCtx,
34
+ next,
35
+ displayName,
36
+ spec: factory
37
+ };
38
+ return mw(ctx);
39
+ } else {
40
+ const ctx = {
41
+ type: "factory",
42
+ factory,
43
+ resolver: resolverForCtx,
44
+ next,
45
+ displayName
46
+ };
47
+ return mw(ctx);
48
+ }
49
+ },
50
+ () => factory(resolverForCtx)
226
51
  );
227
52
  return chain();
228
53
  };
@@ -234,12 +59,19 @@ function createResolver(options = {}) {
234
59
  if (parent && overrides.size === 0 && parent.has(factory)) {
235
60
  return parent.get(factory);
236
61
  }
237
- const instance = invoke(resolve(factory), resolver);
62
+ const instance = invoke(
63
+ resolve(factory),
64
+ invokeResolverOption ?? resolver
65
+ );
238
66
  cache2.set(factory, instance);
239
67
  return instance;
240
68
  },
241
- create(factory) {
242
- return invoke(resolve(factory), resolver);
69
+ create(factory, ...args) {
70
+ const resolverForCtx = invokeResolverOption ?? resolver;
71
+ if (args.length > 0) {
72
+ return factory(resolverForCtx, ...args);
73
+ }
74
+ return invoke(resolve(factory), resolverForCtx);
243
75
  },
244
76
  set(factory, override) {
245
77
  overrides.set(factory, override);
@@ -261,9 +93,7 @@ function createResolver(options = {}) {
261
93
  delete(factory) {
262
94
  const instance = cache2.get(factory);
263
95
  if (instance) {
264
- if (instance && typeof instance === "object" && "dispose" in instance && typeof instance.dispose === "function") {
265
- instance.dispose();
266
- }
96
+ tryDispose(instance);
267
97
  cache2.delete(factory);
268
98
  return true;
269
99
  }
@@ -271,9 +101,7 @@ function createResolver(options = {}) {
271
101
  },
272
102
  clear() {
273
103
  for (const instance of cache2.values()) {
274
- if (instance && typeof instance === "object" && "dispose" in instance && typeof instance.dispose === "function") {
275
- instance.dispose();
276
- }
104
+ tryDispose(instance);
277
105
  }
278
106
  cache2.clear();
279
107
  },
@@ -313,6 +141,125 @@ function createValidationMiddleware(validate) {
313
141
  return result;
314
142
  };
315
143
  }
144
+ let defaultMiddlewareConfig = {};
145
+ const container = function(options = {}) {
146
+ const middleware = [
147
+ ...defaultMiddlewareConfig.pre ?? [],
148
+ ...options.middleware ?? [],
149
+ ...defaultMiddlewareConfig.post ?? []
150
+ ];
151
+ const instancesById = /* @__PURE__ */ new Map();
152
+ const creationOrder = [];
153
+ const createEmitter = emitter();
154
+ const disposeEmitter = emitter();
155
+ const parent = options._parent;
156
+ let containerApi;
157
+ const internalResolver = createResolver({
158
+ middleware,
159
+ parent,
160
+ get invokeResolver() {
161
+ return containerApi;
162
+ }
163
+ });
164
+ function trackStore(spec, instance) {
165
+ instancesById.set(instance.id, instance);
166
+ creationOrder.push(spec);
167
+ if (typeof instance.onDispose === "function") {
168
+ instance.onDispose(() => {
169
+ disposeEmitter.emit(instance);
170
+ instancesById.delete(instance.id);
171
+ internalResolver.delete(spec);
172
+ const index = creationOrder.indexOf(spec);
173
+ if (index !== -1) {
174
+ creationOrder.splice(index, 1);
175
+ }
176
+ });
177
+ }
178
+ createEmitter.emit(instance);
179
+ }
180
+ containerApi = {
181
+ [STORION_TYPE]: "container",
182
+ // Get by ID or factory/spec
183
+ get(specOrIdOrFactory) {
184
+ if (typeof specOrIdOrFactory === "string") {
185
+ return instancesById.get(specOrIdOrFactory);
186
+ }
187
+ const wasCached = internalResolver.has(specOrIdOrFactory);
188
+ const instance = untrack(() => internalResolver.get(specOrIdOrFactory));
189
+ if (!wasCached && isSpec(specOrIdOrFactory)) {
190
+ trackStore(specOrIdOrFactory, instance);
191
+ }
192
+ return instance;
193
+ },
194
+ create(specOrFactory, ...args) {
195
+ const instance = untrack(
196
+ () => internalResolver.create(specOrFactory, ...args)
197
+ );
198
+ if (isSpec(specOrFactory)) {
199
+ const storeInstance = instance;
200
+ instancesById.set(storeInstance.id, storeInstance);
201
+ if (typeof storeInstance.onDispose === "function") {
202
+ storeInstance.onDispose(() => {
203
+ disposeEmitter.emit(storeInstance);
204
+ instancesById.delete(storeInstance.id);
205
+ });
206
+ }
207
+ }
208
+ return instance;
209
+ },
210
+ set(spec, override) {
211
+ const existing = internalResolver.tryGet(spec);
212
+ tryDispose(existing);
213
+ internalResolver.set(spec, override);
214
+ },
215
+ has(spec) {
216
+ return internalResolver.has(spec);
217
+ },
218
+ tryGet(spec) {
219
+ return internalResolver.tryGet(spec);
220
+ },
221
+ delete(spec) {
222
+ const instance = internalResolver.tryGet(spec);
223
+ if (instance) {
224
+ tryDispose(instance);
225
+ return true;
226
+ }
227
+ return false;
228
+ },
229
+ clear() {
230
+ const specs = [...creationOrder].reverse();
231
+ for (const spec of specs) {
232
+ const instance = internalResolver.tryGet(spec);
233
+ tryDispose(instance);
234
+ }
235
+ internalResolver.clear();
236
+ instancesById.clear();
237
+ creationOrder.length = 0;
238
+ },
239
+ dispose(spec) {
240
+ return containerApi.delete(spec);
241
+ },
242
+ scope(scopeOptions = {}) {
243
+ return container({
244
+ middleware: scopeOptions.middleware ?? middleware,
245
+ _parent: containerApi
246
+ });
247
+ },
248
+ onCreate: createEmitter.on,
249
+ onDispose: disposeEmitter.on
250
+ };
251
+ return containerApi;
252
+ };
253
+ const defaultsFn = (config = {}) => {
254
+ defaultMiddlewareConfig = {
255
+ pre: [...defaultMiddlewareConfig.pre ?? [], ...config.pre ?? []],
256
+ post: [...defaultMiddlewareConfig.post ?? [], ...config.post ?? []]
257
+ };
258
+ };
259
+ defaultsFn.clear = () => {
260
+ defaultMiddlewareConfig = {};
261
+ };
262
+ container.defaults = defaultsFn;
316
263
  let pickIdCounter = 0;
317
264
  function pick(selector, equality) {
318
265
  var _a;
@@ -672,10 +619,10 @@ function patternToPredicate(pattern) {
672
619
  function patternsToPredicate(patterns) {
673
620
  if (Array.isArray(patterns)) {
674
621
  const predicates = patterns.map(patternToPredicate);
675
- return (ctx) => predicates.some((p2) => p2(ctx.displayName));
622
+ return (ctx) => ctx.displayName !== void 0 && predicates.some((p2) => p2(ctx.displayName));
676
623
  }
677
624
  const predicate = patternToPredicate(patterns);
678
- return (ctx) => predicate(ctx.displayName);
625
+ return (ctx) => ctx.displayName !== void 0 && predicate(ctx.displayName);
679
626
  }
680
627
  function compose(...middlewares) {
681
628
  if (middlewares.length === 0) {
@@ -692,10 +639,7 @@ function compose(...middlewares) {
692
639
  }
693
640
  const currentMiddleware = middlewares[index];
694
641
  index++;
695
- const wrappedCtx = {
696
- ...ctx,
697
- next: executeNext
698
- };
642
+ const wrappedCtx = ctx.type === "store" ? { ...ctx, next: executeNext } : { ...ctx, next: executeNext };
699
643
  return currentMiddleware(wrappedCtx);
700
644
  };
701
645
  return executeNext();
@@ -705,17 +649,8 @@ function applyFor(predicateOrPatterns, middleware) {
705
649
  const predicate = typeof predicateOrPatterns === "function" ? predicateOrPatterns : patternsToPredicate(predicateOrPatterns);
706
650
  const composedMiddleware = Array.isArray(middleware) ? compose(...middleware) : middleware;
707
651
  return (ctx) => {
708
- if (isSpec(ctx.factory)) {
709
- const spec = ctx.factory;
710
- const storeMiddlewareCtx = {
711
- ...ctx,
712
- spec
713
- };
714
- if (predicate(storeMiddlewareCtx)) {
715
- return composedMiddleware(
716
- storeMiddlewareCtx
717
- );
718
- }
652
+ if (predicate(ctx)) {
653
+ return composedMiddleware(ctx);
719
654
  }
720
655
  return ctx.next();
721
656
  };
@@ -725,6 +660,14 @@ function applyExcept(predicateOrPatterns, middleware) {
725
660
  const invertedPredicate = (ctx) => !matchPredicate(ctx);
726
661
  return applyFor(invertedPredicate, middleware);
727
662
  }
663
+ function forStores(storeMiddleware) {
664
+ return (ctx) => {
665
+ if (ctx.type === "store") {
666
+ return storeMiddleware(ctx);
667
+ }
668
+ return ctx.next();
669
+ };
670
+ }
728
671
  const DEFAULT_KEY = {};
729
672
  const cache = /* @__PURE__ */ new Map();
730
673
  function getKeyCache(key) {
@@ -789,6 +732,7 @@ export {
789
732
  p as deepEqual,
790
733
  effect,
791
734
  n as equality,
735
+ forStores,
792
736
  g as getKind,
793
737
  a as is,
794
738
  j as isAction,
@@ -0,0 +1,2 @@
1
+ export declare function fake<T>(): T | undefined;
2
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/test/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,SAAS,CAEvC"}