bunja 3.0.0-alpha.3 → 3.0.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bunja.ts CHANGED
@@ -3,18 +3,21 @@
3
3
  const __DEV__ = process.env.NODE_ENV !== "production";
4
4
 
5
5
  export interface BunjaFn {
6
- <T>(init: () => T): Bunja<T, NoSeed>;
6
+ <T>(init: () => T): Bunja<T, undefined>;
7
7
  withSeed: BunjaWithSeedFn;
8
8
  use: BunjaUseFn;
9
9
  will: BunjaWillFn;
10
10
  effect: BunjaEffectFn;
11
11
  }
12
12
  export const bunja: BunjaFn = bunjaFn;
13
- function bunjaFn<T>(init: () => T): Bunja<T, NoSeed> {
14
- return new Bunja(() => init(), NO_SEED);
13
+ function bunjaFn<T>(init: () => T): Bunja<T, undefined> {
14
+ return new Bunja(() => init(), undefined);
15
15
  }
16
- const NO_SEED = Symbol("bunja.noSeed");
17
- export type NoSeed = typeof NO_SEED;
16
+
17
+ export type BunjaWithSeedFn = <Seed, T>(
18
+ defaultSeed: Seed,
19
+ init: (seed: Seed) => T,
20
+ ) => Bunja<T, Seed>;
18
21
  bunjaFn.withSeed = function withSeed<Seed, T>(
19
22
  defaultSeed: Seed,
20
23
  init: (seed: Seed) => T,
@@ -43,22 +46,7 @@ bunjaFn.effect =
43
46
  ((callback: BunjaEffectCallback) =>
44
47
  getCurrentFrame("`bunja.effect`").effect(callback)) as BunjaEffectFn;
45
48
 
46
- export type BunjaWithSeedFn = <Seed, T>(
47
- defaultSeed: Seed,
48
- init: (seed: Seed) => T,
49
- ) => Bunja<T, Seed>;
50
49
  export type ScopeValuePairs = ScopeValuePair<any>[];
51
- type BunjaRefBase<T, Seed> = {
52
- bunja: Bunja<T, Seed>;
53
- with?: ScopeValuePairs;
54
- };
55
- export type BunjaGetRef<T, Seed = NoSeed> =
56
- & BunjaRefBase<T, Seed>
57
- & ([Seed] extends [NoSeed] ? { seed?: never } : { seed?: Seed });
58
- export type BunjaRef<T, Seed = NoSeed> = BunjaGetRef<T, Seed>;
59
- type BunjaPrebakeRef<T, Seed = NoSeed> = BunjaRefBase<T, Seed> & {
60
- seed?: never;
61
- };
62
50
  export interface BunjaUseFn {
63
51
  <T>(dep: Scope<T>): T;
64
52
  <T, Seed>(dep: Bunja<T, Seed>): T;
@@ -76,6 +64,18 @@ export interface BunjaWillFn {
76
64
  export type BunjaEffectFn = (callback: BunjaEffectCallback) => void;
77
65
  export type BunjaEffectCallback = () => (() => void) | void;
78
66
 
67
+ export interface BunjaRef<T, Seed = undefined> extends BunjaRefBase<T, Seed> {
68
+ seed?: [Seed] extends [undefined] ? never : Seed;
69
+ }
70
+ export type BunjaGetRef<T, Seed = undefined> = BunjaRef<T, Seed>;
71
+ export interface BunjaPrebakeRef<T, Seed> extends BunjaRefBase<T, Seed> {
72
+ seed?: never;
73
+ }
74
+ interface BunjaRefBase<T, Seed> {
75
+ bunja: Bunja<T, Seed>;
76
+ with?: ScopeValuePairs;
77
+ }
78
+
79
79
  export function createScope<T>(hash?: HashFn<T>): Scope<T> {
80
80
  return new Scope(hash);
81
81
  }
@@ -94,7 +94,6 @@ export type Dep<T> = Bunja<T, any> | Scope<T>;
94
94
 
95
95
  type AnyBunja = Bunja<any, any>;
96
96
  type ScopeInstanceMap = Map<Scope<unknown>, ScopeInstance>;
97
- type BunjaDependencyEdge = "required" | "optional";
98
97
 
99
98
  interface BunjaFrame {
100
99
  use: BunjaUseFn;
@@ -251,11 +250,8 @@ function getBoundScopeSet(
251
250
  function getScopeInstances(
252
251
  scopes: Scope<unknown>[],
253
252
  scopeInstanceMap: ScopeInstanceMap,
254
- excludeScopes: Set<Scope<unknown>> = new Set(),
255
253
  ): ScopeInstance[] {
256
- return scopes
257
- .filter((scope) => !excludeScopes.has(scope))
258
- .map((scope) => scopeInstanceMap.get(scope)!);
254
+ return scopes.map((scope) => scopeInstanceMap.get(scope)!);
259
255
  }
260
256
 
261
257
  function dedupeScopeInstances(
@@ -331,6 +327,7 @@ export class BunjaStore {
331
327
  readScope,
332
328
  new Set(),
333
329
  bunjaRef.seed,
330
+ true,
334
331
  );
335
332
  const result: BunjaStoreGetResult<T> = {
336
333
  value: resolved.value,
@@ -366,6 +363,7 @@ export class BunjaStore {
366
363
  readScope: ReadScope,
367
364
  inProgressBunjas: Set<AnyBunja>,
368
365
  seed: Seed = bunjaRef.bunja.defaultSeed,
366
+ includeBoundScopeDeps: boolean = false,
369
367
  ): ResolvedBunja<T> {
370
368
  const { bunja } = bunjaRef;
371
369
  if (inProgressBunjas.has(bunja)) {
@@ -382,6 +380,7 @@ export class BunjaStore {
382
380
  resolvedReadScope,
383
381
  inProgressBunjas,
384
382
  seed,
383
+ includeBoundScopeDeps,
385
384
  );
386
385
  }
387
386
  const scopeInstanceMap = this.#resolveScopeInstanceMap(
@@ -394,9 +393,10 @@ export class BunjaStore {
394
393
  scopeInstanceMap,
395
394
  );
396
395
  const directDeps = getScopeInstances(
397
- bunja.requiredScopes,
396
+ includeBoundScopeDeps
397
+ ? bunja.requiredScopes
398
+ : bunja.requiredScopes.filter((scope) => !boundScopes.has(scope)),
398
399
  scopeInstanceMap,
399
- boundScopes,
400
400
  );
401
401
  const baseId = bunja.calcBaseInstanceId(scopeInstanceMap);
402
402
  const bucket = this.#bunjaBuckets.get(baseId);
@@ -433,6 +433,7 @@ export class BunjaStore {
433
433
  resolvedReadScope,
434
434
  inProgressBunjas,
435
435
  seed,
436
+ includeBoundScopeDeps,
436
437
  scopeInstanceMap,
437
438
  );
438
439
  } finally {
@@ -444,6 +445,7 @@ export class BunjaStore {
444
445
  readScope: ReadScope,
445
446
  inProgressBunjas: Set<AnyBunja>,
446
447
  seed: Seed,
448
+ includeBoundScopeDeps: boolean,
447
449
  initialScopeInstanceMap: ScopeInstanceMap = new Map(),
448
450
  ): ResolvedBunja<T> {
449
451
  const { bunja } = bunjaRef;
@@ -475,9 +477,10 @@ export class BunjaStore {
475
477
  frame.scopeInstanceMap,
476
478
  );
477
479
  const directDeps = getScopeInstances(
478
- bunja.requiredScopes,
480
+ includeBoundScopeDeps
481
+ ? bunja.requiredScopes
482
+ : bunja.requiredScopes.filter((scope) => !boundScopes.has(scope)),
479
483
  frame.scopeInstanceMap,
480
- boundScopes,
481
484
  );
482
485
  const baseId = bunja.calcBaseInstanceId(frame.scopeInstanceMap);
483
486
  const id = bunja.calcInstanceId(
@@ -560,11 +563,10 @@ export class BunjaStore {
560
563
  return this.#useScopeInFrame(frame, dep as Scope<unknown>);
561
564
  }
562
565
  if (dep instanceof Bunja || isBunjaRef(dep)) {
563
- return this.#useBunjaDependencyInFrame(
564
- frame,
565
- normalizeBunjaRuntimeRef(dep, scopeValuePairs),
566
- "required",
567
- );
566
+ const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
567
+ const graphRef = toBunjaGraphRef(bunjaRef);
568
+ currentBunja.addRequiredBunjaRef(graphRef);
569
+ return this.#useBunjaDependencyInFrame(frame, bunjaRef);
568
570
  }
569
571
  throw new Error("`bunja.use` can only be used with Bunja or Scope.");
570
572
  }) as BunjaUseFn,
@@ -573,18 +575,15 @@ export class BunjaStore {
573
575
  throw new Error("`bunja.will` can only be used with Bunja.");
574
576
  }
575
577
  const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
576
- currentBunja.addOptionalBunjaRef(toBunjaGraphRef(bunjaRef));
578
+ const graphRef = toBunjaGraphRef(bunjaRef);
579
+ currentBunja.addOptionalBunjaRef(graphRef);
577
580
  return () => {
578
581
  if (frameStack[frameStack.length - 1] !== frame) {
579
582
  throw new Error(
580
583
  "A thunk returned by `bunja.will` can only be called inside the same bunja init function.",
581
584
  );
582
585
  }
583
- return this.#useBunjaDependencyInFrame(
584
- frame,
585
- bunjaRef,
586
- "optional",
587
- );
586
+ return this.#useBunjaDependencyInFrame(frame, bunjaRef);
588
587
  };
589
588
  }) as BunjaWillFn,
590
589
  effect: ((callback: BunjaEffectCallback) => {
@@ -615,14 +614,8 @@ export class BunjaStore {
615
614
  #useBunjaDependencyInFrame<T, Seed>(
616
615
  frame: BunjaInitFrame,
617
616
  bunjaRef: NormalizedBunjaRuntimeRef<T, Seed>,
618
- edge: BunjaDependencyEdge,
619
617
  ): T {
620
618
  const graphRef = toBunjaGraphRef(bunjaRef);
621
- if (edge === "optional" || graphRef.scopeValuePairs.length > 0) {
622
- frame.currentBunja.addOptionalBunjaRef(graphRef);
623
- } else if (edge === "required") {
624
- frame.currentBunja.addRequiredBunjaRef(graphRef);
625
- }
626
619
  const resolved = this.#resolveBunjaRef(
627
620
  graphRef,
628
621
  frame.readScope,
@@ -725,11 +718,14 @@ export class BunjaStore {
725
718
  return readScope(dep as Scope<unknown>);
726
719
  }
727
720
  if (dep instanceof Bunja || isBunjaRef(dep)) {
728
- const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
729
- return this.#prebakeBunjaDependencyInFrame(
730
- frame,
731
- toBunjaGraphRef(bunjaRef),
732
- "required",
721
+ const bunjaRef = toBunjaGraphRef(
722
+ normalizeBunjaRuntimeRef(dep, scopeValuePairs),
723
+ );
724
+ currentBunja.addRequiredBunjaRef(bunjaRef);
725
+ return this.#prebakeBunjaRef(
726
+ bunjaRef,
727
+ readScope,
728
+ prebakeContext,
733
729
  );
734
730
  }
735
731
  throw new Error("`bunja.use` can only be used with Bunja or Scope.");
@@ -760,22 +756,6 @@ export class BunjaStore {
760
756
  } satisfies BunjaPrebakeFrame;
761
757
  return frame;
762
758
  }
763
- #prebakeBunjaDependencyInFrame<T, Seed>(
764
- frame: BunjaPrebakeFrame,
765
- bunjaRef: NormalizedBunjaRef<T, Seed>,
766
- edge: BunjaDependencyEdge,
767
- ): T {
768
- if (edge === "optional" || bunjaRef.scopeValuePairs.length > 0) {
769
- frame.currentBunja.addOptionalBunjaRef(bunjaRef);
770
- } else if (edge === "required") {
771
- frame.currentBunja.addRequiredBunjaRef(bunjaRef);
772
- }
773
- return this.#prebakeBunjaRef(
774
- bunjaRef,
775
- frame.readScope,
776
- frame.prebakeContext,
777
- );
778
- }
779
759
  #resolveScopeInstanceMap(
780
760
  bunja: AnyBunja,
781
761
  readScope: ReadScope,
@@ -911,7 +891,7 @@ export function delayUnmount(
911
891
  };
912
892
  }
913
893
 
914
- export class Bunja<T, Seed = NoSeed> {
894
+ export class Bunja<T, Seed = undefined> {
915
895
  private static counter: number = 0;
916
896
  readonly id: string = String(Bunja.counter++);
917
897
  debugLabel: string = "";
@@ -984,8 +964,11 @@ export class Bunja<T, Seed = NoSeed> {
984
964
  const requiredBunjas = this.requiredBunjas;
985
965
  const expandedRequiredBunjas = toposortRequiredBunjas(requiredBunjas);
986
966
  const requiredScopeSet = new Set<Scope<unknown>>();
987
- for (const bunja of expandedRequiredBunjas) {
988
- for (const scope of bunja.requiredScopes) requiredScopeSet.add(scope);
967
+ for (const ref of requiredBunjaRefs) {
968
+ const boundScopes = getBoundScopeSet(ref.scopeValuePairs);
969
+ for (const scope of ref.bunja.requiredScopes) {
970
+ if (!boundScopes.has(scope)) requiredScopeSet.add(scope);
971
+ }
989
972
  }
990
973
  for (const scope of scopes) requiredScopeSet.add(scope);
991
974
  const requiredScopes = Array.from(requiredScopeSet);
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@disjukr/bunja",
3
- "version": "3.0.0-alpha.3",
3
+ "version": "3.0.0-alpha.5",
4
4
  "license": "Zlib",
5
5
  "exports": {
6
6
  ".": "./bunja.ts",
@@ -1,29 +1,14 @@
1
1
  //#region bunja.d.ts
2
2
  interface BunjaFn {
3
- <T>(init: () => T): Bunja<T, NoSeed>;
3
+ <T>(init: () => T): Bunja<T, undefined>;
4
4
  withSeed: BunjaWithSeedFn;
5
5
  use: BunjaUseFn;
6
6
  will: BunjaWillFn;
7
7
  effect: BunjaEffectFn;
8
8
  }
9
9
  declare const bunja: BunjaFn;
10
- declare const NO_SEED: unique symbol;
11
- type NoSeed = typeof NO_SEED;
12
10
  type BunjaWithSeedFn = <Seed, T>(defaultSeed: Seed, init: (seed: Seed) => T) => Bunja<T, Seed>;
13
11
  type ScopeValuePairs = ScopeValuePair<any>[];
14
- type BunjaRefBase<T, Seed> = {
15
- bunja: Bunja<T, Seed>;
16
- with?: ScopeValuePairs;
17
- };
18
- type BunjaGetRef<T, Seed = NoSeed> = BunjaRefBase<T, Seed> & ([Seed] extends [NoSeed] ? {
19
- seed?: never;
20
- } : {
21
- seed?: Seed;
22
- });
23
- type BunjaRef<T, Seed = NoSeed> = BunjaGetRef<T, Seed>;
24
- type BunjaPrebakeRef<T, Seed = NoSeed> = BunjaRefBase<T, Seed> & {
25
- seed?: never;
26
- };
27
12
  interface BunjaUseFn {
28
13
  <T>(dep: Scope<T>): T;
29
14
  <T, Seed>(dep: Bunja<T, Seed>): T;
@@ -37,6 +22,17 @@ interface BunjaWillFn {
37
22
  }
38
23
  type BunjaEffectFn = (callback: BunjaEffectCallback) => void;
39
24
  type BunjaEffectCallback = () => (() => void) | void;
25
+ interface BunjaRef<T, Seed = undefined> extends BunjaRefBase<T, Seed> {
26
+ seed?: [Seed] extends [undefined] ? never : Seed;
27
+ }
28
+ type BunjaGetRef<T, Seed = undefined> = BunjaRef<T, Seed>;
29
+ interface BunjaPrebakeRef<T, Seed> extends BunjaRefBase<T, Seed> {
30
+ seed?: never;
31
+ }
32
+ interface BunjaRefBase<T, Seed> {
33
+ bunja: Bunja<T, Seed>;
34
+ with?: ScopeValuePairs;
35
+ }
40
36
  declare function createScope<T>(hash?: HashFn<T>): Scope<T>;
41
37
  interface CreateBunjaStoreConfig {
42
38
  wrapInstance?: WrapInstanceFn;
@@ -86,7 +82,7 @@ interface BunjaStorePrebakeResult {
86
82
  requiredScopes: Scope<unknown>[];
87
83
  }
88
84
  declare function delayUnmount(mount: () => () => void, ms?: number): () => () => void;
89
- declare class Bunja<T, Seed = NoSeed> {
85
+ declare class Bunja<T, Seed = undefined> {
90
86
  #private;
91
87
  init: (seed: Seed) => T;
92
88
  defaultSeed: Seed;
@@ -193,4 +189,4 @@ interface BunjaDevtoolsEvent {
193
189
  }
194
190
  type BunjaDevtoolsEventType = keyof BunjaDevtoolsEvent;
195
191
  //#endregion
196
- export { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, NoSeed, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
192
+ export { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaPrebakeRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
@@ -2,9 +2,8 @@
2
2
  const __DEV__ = process.env.NODE_ENV !== "production";
3
3
  const bunja = bunjaFn;
4
4
  function bunjaFn(init) {
5
- return new Bunja(() => init(), NO_SEED);
5
+ return new Bunja(() => init(), void 0);
6
6
  }
7
- const NO_SEED = Symbol("bunja.noSeed");
8
7
  bunjaFn.withSeed = function withSeed(defaultSeed, init) {
9
8
  return new Bunja(init, defaultSeed);
10
9
  };
@@ -72,8 +71,8 @@ function isBunjaRef(value) {
72
71
  function getBoundScopeSet(scopeValuePairs) {
73
72
  return new Set(scopeValuePairs.map(([scope]) => scope));
74
73
  }
75
- function getScopeInstances(scopes, scopeInstanceMap, excludeScopes = /* @__PURE__ */ new Set()) {
76
- return scopes.filter((scope) => !excludeScopes.has(scope)).map((scope) => scopeInstanceMap.get(scope));
74
+ function getScopeInstances(scopes, scopeInstanceMap) {
75
+ return scopes.map((scope) => scopeInstanceMap.get(scope));
77
76
  }
78
77
  function dedupeScopeInstances(scopeInstances) {
79
78
  const seen = /* @__PURE__ */ new Set();
@@ -126,7 +125,7 @@ var BunjaStore = class BunjaStore {
126
125
  }
127
126
  get(bunjaOrRef, readScope) {
128
127
  const bunjaRef = normalizeBunjaRuntimeRef(bunjaOrRef);
129
- const resolved = this.#resolveBunjaRef(toBunjaGraphRef(bunjaRef), readScope, /* @__PURE__ */ new Set(), bunjaRef.seed);
128
+ const resolved = this.#resolveBunjaRef(toBunjaGraphRef(bunjaRef), readScope, /* @__PURE__ */ new Set(), bunjaRef.seed, true);
130
129
  const result = {
131
130
  value: resolved.value,
132
131
  mount: resolved.mount,
@@ -149,17 +148,17 @@ var BunjaStore = class BunjaStore {
149
148
  requiredScopes: bunjaRef.bunja.requiredScopes
150
149
  };
151
150
  }
152
- #resolveBunjaRef(bunjaRef, readScope, inProgressBunjas, seed = bunjaRef.bunja.defaultSeed) {
151
+ #resolveBunjaRef(bunjaRef, readScope, inProgressBunjas, seed = bunjaRef.bunja.defaultSeed, includeBoundScopeDeps = false) {
153
152
  const { bunja: bunja$1 } = bunjaRef;
154
153
  if (inProgressBunjas.has(bunja$1)) throw new Error("Circular bunja dependency detected.");
155
154
  const resolvedReadScope = bunjaRef.scopeValuePairs.length > 0 ? createReadScopeFn(bunjaRef.scopeValuePairs, readScope) : readScope;
156
155
  inProgressBunjas.add(bunja$1);
157
156
  try {
158
- if (!bunja$1.baked) return this.#createResolvedBunja(bunjaRef, resolvedReadScope, inProgressBunjas, seed);
157
+ if (!bunja$1.baked) return this.#createResolvedBunja(bunjaRef, resolvedReadScope, inProgressBunjas, seed, includeBoundScopeDeps);
159
158
  const scopeInstanceMap = this.#resolveScopeInstanceMap(bunja$1, resolvedReadScope);
160
159
  const boundScopes = getBoundScopeSet(bunjaRef.scopeValuePairs);
161
160
  const scopeInstances = getScopeInstances(bunja$1.requiredScopes, scopeInstanceMap);
162
- const directDeps = getScopeInstances(bunja$1.requiredScopes, scopeInstanceMap, boundScopes);
161
+ const directDeps = getScopeInstances(includeBoundScopeDeps ? bunja$1.requiredScopes : bunja$1.requiredScopes.filter((scope) => !boundScopes.has(scope)), scopeInstanceMap);
163
162
  const baseId = bunja$1.calcBaseInstanceId(scopeInstanceMap);
164
163
  const bucket = this.#bunjaBuckets.get(baseId);
165
164
  if (bucket) for (const candidateId of Array.from(bucket)) {
@@ -174,12 +173,12 @@ var BunjaStore = class BunjaStore {
174
173
  if (!instance) continue;
175
174
  return this.#toResolvedBunja(instance, scopeInstances, directDeps, activeDeps.deps);
176
175
  }
177
- return this.#createResolvedBunja(bunjaRef, resolvedReadScope, inProgressBunjas, seed, scopeInstanceMap);
176
+ return this.#createResolvedBunja(bunjaRef, resolvedReadScope, inProgressBunjas, seed, includeBoundScopeDeps, scopeInstanceMap);
178
177
  } finally {
179
178
  inProgressBunjas.delete(bunja$1);
180
179
  }
181
180
  }
182
- #createResolvedBunja(bunjaRef, readScope, inProgressBunjas, seed, initialScopeInstanceMap = /* @__PURE__ */ new Map()) {
181
+ #createResolvedBunja(bunjaRef, readScope, inProgressBunjas, seed, includeBoundScopeDeps, initialScopeInstanceMap = /* @__PURE__ */ new Map()) {
183
182
  const { bunja: bunja$1 } = bunjaRef;
184
183
  return this.wrapInstance((dispose) => {
185
184
  let instanceCreated = false;
@@ -196,7 +195,7 @@ var BunjaStore = class BunjaStore {
196
195
  this.#ensureRequiredScopeInstances(bunja$1, frame.scopeInstanceMap, readScope);
197
196
  const boundScopes = getBoundScopeSet(bunjaRef.scopeValuePairs);
198
197
  const scopeInstances = getScopeInstances(bunja$1.requiredScopes, frame.scopeInstanceMap);
199
- const directDeps = getScopeInstances(bunja$1.requiredScopes, frame.scopeInstanceMap, boundScopes);
198
+ const directDeps = getScopeInstances(includeBoundScopeDeps ? bunja$1.requiredScopes : bunja$1.requiredScopes.filter((scope) => !boundScopes.has(scope)), frame.scopeInstanceMap);
200
199
  const baseId = bunja$1.calcBaseInstanceId(frame.scopeInstanceMap);
201
200
  const id = bunja$1.calcInstanceId(frame.scopeInstanceMap, frame.activeDependencyIds);
202
201
  const existing = this.#bunjas[id];
@@ -241,16 +240,22 @@ var BunjaStore = class BunjaStore {
241
240
  activeDependencyDeps: [],
242
241
  use: ((dep, scopeValuePairs) => {
243
242
  if (dep instanceof Scope) return this.#useScopeInFrame(frame, dep);
244
- if (dep instanceof Bunja || isBunjaRef(dep)) return this.#useBunjaDependencyInFrame(frame, normalizeBunjaRuntimeRef(dep, scopeValuePairs), "required");
243
+ if (dep instanceof Bunja || isBunjaRef(dep)) {
244
+ const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
245
+ const graphRef = toBunjaGraphRef(bunjaRef);
246
+ currentBunja.addRequiredBunjaRef(graphRef);
247
+ return this.#useBunjaDependencyInFrame(frame, bunjaRef);
248
+ }
245
249
  throw new Error("`bunja.use` can only be used with Bunja or Scope.");
246
250
  }),
247
251
  will: ((dep, scopeValuePairs) => {
248
252
  if (!(dep instanceof Bunja || isBunjaRef(dep))) throw new Error("`bunja.will` can only be used with Bunja.");
249
253
  const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
250
- currentBunja.addOptionalBunjaRef(toBunjaGraphRef(bunjaRef));
254
+ const graphRef = toBunjaGraphRef(bunjaRef);
255
+ currentBunja.addOptionalBunjaRef(graphRef);
251
256
  return () => {
252
257
  if (frameStack[frameStack.length - 1] !== frame) throw new Error("A thunk returned by `bunja.will` can only be called inside the same bunja init function.");
253
- return this.#useBunjaDependencyInFrame(frame, bunjaRef, "optional");
258
+ return this.#useBunjaDependencyInFrame(frame, bunjaRef);
254
259
  };
255
260
  }),
256
261
  effect: ((callback) => {
@@ -269,10 +274,8 @@ var BunjaStore = class BunjaStore {
269
274
  }
270
275
  return scopeInstance.value;
271
276
  }
272
- #useBunjaDependencyInFrame(frame, bunjaRef, edge) {
277
+ #useBunjaDependencyInFrame(frame, bunjaRef) {
273
278
  const graphRef = toBunjaGraphRef(bunjaRef);
274
- if (edge === "optional" || graphRef.scopeValuePairs.length > 0) frame.currentBunja.addOptionalBunjaRef(graphRef);
275
- else if (edge === "required") frame.currentBunja.addRequiredBunjaRef(graphRef);
276
279
  const resolved = this.#resolveBunjaRef(graphRef, frame.readScope, frame.inProgressBunjas, bunjaRef.seed);
277
280
  frame.activeDependencyIds.add(resolved.instance.id);
278
281
  frame.activeDependencyRecipes.push({
@@ -330,8 +333,9 @@ var BunjaStore = class BunjaStore {
330
333
  return readScope(dep);
331
334
  }
332
335
  if (dep instanceof Bunja || isBunjaRef(dep)) {
333
- const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
334
- return this.#prebakeBunjaDependencyInFrame(frame, toBunjaGraphRef(bunjaRef), "required");
336
+ const bunjaRef = toBunjaGraphRef(normalizeBunjaRuntimeRef(dep, scopeValuePairs));
337
+ currentBunja.addRequiredBunjaRef(bunjaRef);
338
+ return this.#prebakeBunjaRef(bunjaRef, readScope, prebakeContext);
335
339
  }
336
340
  throw new Error("`bunja.use` can only be used with Bunja or Scope.");
337
341
  }),
@@ -349,11 +353,6 @@ var BunjaStore = class BunjaStore {
349
353
  };
350
354
  return frame;
351
355
  }
352
- #prebakeBunjaDependencyInFrame(frame, bunjaRef, edge) {
353
- if (edge === "optional" || bunjaRef.scopeValuePairs.length > 0) frame.currentBunja.addOptionalBunjaRef(bunjaRef);
354
- else if (edge === "required") frame.currentBunja.addRequiredBunjaRef(bunjaRef);
355
- return this.#prebakeBunjaRef(bunjaRef, frame.readScope, frame.prebakeContext);
356
- }
357
356
  #resolveScopeInstanceMap(bunja$1, readScope) {
358
357
  const scopeInstanceMap = /* @__PURE__ */ new Map();
359
358
  this.#ensureRequiredScopeInstances(bunja$1, scopeInstanceMap, readScope);
@@ -484,7 +483,10 @@ var Bunja = class Bunja {
484
483
  const requiredBunjas = this.requiredBunjas;
485
484
  const expandedRequiredBunjas = toposortRequiredBunjas(requiredBunjas);
486
485
  const requiredScopeSet = /* @__PURE__ */ new Set();
487
- for (const bunja$1 of expandedRequiredBunjas) for (const scope of bunja$1.requiredScopes) requiredScopeSet.add(scope);
486
+ for (const ref of requiredBunjaRefs) {
487
+ const boundScopes = getBoundScopeSet(ref.scopeValuePairs);
488
+ for (const scope of ref.bunja.requiredScopes) if (!boundScopes.has(scope)) requiredScopeSet.add(scope);
489
+ }
488
490
  for (const scope of scopes) requiredScopeSet.add(scope);
489
491
  this.#phase = {
490
492
  baked: true,
@@ -3,9 +3,8 @@
3
3
  const __DEV__ = process.env.NODE_ENV !== "production";
4
4
  const bunja = bunjaFn;
5
5
  function bunjaFn(init) {
6
- return new Bunja(() => init(), NO_SEED);
6
+ return new Bunja(() => init(), void 0);
7
7
  }
8
- const NO_SEED = Symbol("bunja.noSeed");
9
8
  bunjaFn.withSeed = function withSeed(defaultSeed, init) {
10
9
  return new Bunja(init, defaultSeed);
11
10
  };
@@ -73,8 +72,8 @@ function isBunjaRef(value) {
73
72
  function getBoundScopeSet(scopeValuePairs) {
74
73
  return new Set(scopeValuePairs.map(([scope]) => scope));
75
74
  }
76
- function getScopeInstances(scopes, scopeInstanceMap, excludeScopes = /* @__PURE__ */ new Set()) {
77
- return scopes.filter((scope) => !excludeScopes.has(scope)).map((scope) => scopeInstanceMap.get(scope));
75
+ function getScopeInstances(scopes, scopeInstanceMap) {
76
+ return scopes.map((scope) => scopeInstanceMap.get(scope));
78
77
  }
79
78
  function dedupeScopeInstances(scopeInstances) {
80
79
  const seen = /* @__PURE__ */ new Set();
@@ -127,7 +126,7 @@ var BunjaStore = class BunjaStore {
127
126
  }
128
127
  get(bunjaOrRef, readScope) {
129
128
  const bunjaRef = normalizeBunjaRuntimeRef(bunjaOrRef);
130
- const resolved = this.#resolveBunjaRef(toBunjaGraphRef(bunjaRef), readScope, /* @__PURE__ */ new Set(), bunjaRef.seed);
129
+ const resolved = this.#resolveBunjaRef(toBunjaGraphRef(bunjaRef), readScope, /* @__PURE__ */ new Set(), bunjaRef.seed, true);
131
130
  const result = {
132
131
  value: resolved.value,
133
132
  mount: resolved.mount,
@@ -150,17 +149,17 @@ var BunjaStore = class BunjaStore {
150
149
  requiredScopes: bunjaRef.bunja.requiredScopes
151
150
  };
152
151
  }
153
- #resolveBunjaRef(bunjaRef, readScope, inProgressBunjas, seed = bunjaRef.bunja.defaultSeed) {
152
+ #resolveBunjaRef(bunjaRef, readScope, inProgressBunjas, seed = bunjaRef.bunja.defaultSeed, includeBoundScopeDeps = false) {
154
153
  const { bunja: bunja$1 } = bunjaRef;
155
154
  if (inProgressBunjas.has(bunja$1)) throw new Error("Circular bunja dependency detected.");
156
155
  const resolvedReadScope = bunjaRef.scopeValuePairs.length > 0 ? createReadScopeFn(bunjaRef.scopeValuePairs, readScope) : readScope;
157
156
  inProgressBunjas.add(bunja$1);
158
157
  try {
159
- if (!bunja$1.baked) return this.#createResolvedBunja(bunjaRef, resolvedReadScope, inProgressBunjas, seed);
158
+ if (!bunja$1.baked) return this.#createResolvedBunja(bunjaRef, resolvedReadScope, inProgressBunjas, seed, includeBoundScopeDeps);
160
159
  const scopeInstanceMap = this.#resolveScopeInstanceMap(bunja$1, resolvedReadScope);
161
160
  const boundScopes = getBoundScopeSet(bunjaRef.scopeValuePairs);
162
161
  const scopeInstances = getScopeInstances(bunja$1.requiredScopes, scopeInstanceMap);
163
- const directDeps = getScopeInstances(bunja$1.requiredScopes, scopeInstanceMap, boundScopes);
162
+ const directDeps = getScopeInstances(includeBoundScopeDeps ? bunja$1.requiredScopes : bunja$1.requiredScopes.filter((scope) => !boundScopes.has(scope)), scopeInstanceMap);
164
163
  const baseId = bunja$1.calcBaseInstanceId(scopeInstanceMap);
165
164
  const bucket = this.#bunjaBuckets.get(baseId);
166
165
  if (bucket) for (const candidateId of Array.from(bucket)) {
@@ -175,12 +174,12 @@ var BunjaStore = class BunjaStore {
175
174
  if (!instance) continue;
176
175
  return this.#toResolvedBunja(instance, scopeInstances, directDeps, activeDeps.deps);
177
176
  }
178
- return this.#createResolvedBunja(bunjaRef, resolvedReadScope, inProgressBunjas, seed, scopeInstanceMap);
177
+ return this.#createResolvedBunja(bunjaRef, resolvedReadScope, inProgressBunjas, seed, includeBoundScopeDeps, scopeInstanceMap);
179
178
  } finally {
180
179
  inProgressBunjas.delete(bunja$1);
181
180
  }
182
181
  }
183
- #createResolvedBunja(bunjaRef, readScope, inProgressBunjas, seed, initialScopeInstanceMap = /* @__PURE__ */ new Map()) {
182
+ #createResolvedBunja(bunjaRef, readScope, inProgressBunjas, seed, includeBoundScopeDeps, initialScopeInstanceMap = /* @__PURE__ */ new Map()) {
184
183
  const { bunja: bunja$1 } = bunjaRef;
185
184
  return this.wrapInstance((dispose) => {
186
185
  let instanceCreated = false;
@@ -197,7 +196,7 @@ var BunjaStore = class BunjaStore {
197
196
  this.#ensureRequiredScopeInstances(bunja$1, frame.scopeInstanceMap, readScope);
198
197
  const boundScopes = getBoundScopeSet(bunjaRef.scopeValuePairs);
199
198
  const scopeInstances = getScopeInstances(bunja$1.requiredScopes, frame.scopeInstanceMap);
200
- const directDeps = getScopeInstances(bunja$1.requiredScopes, frame.scopeInstanceMap, boundScopes);
199
+ const directDeps = getScopeInstances(includeBoundScopeDeps ? bunja$1.requiredScopes : bunja$1.requiredScopes.filter((scope) => !boundScopes.has(scope)), frame.scopeInstanceMap);
201
200
  const baseId = bunja$1.calcBaseInstanceId(frame.scopeInstanceMap);
202
201
  const id = bunja$1.calcInstanceId(frame.scopeInstanceMap, frame.activeDependencyIds);
203
202
  const existing = this.#bunjas[id];
@@ -242,16 +241,22 @@ var BunjaStore = class BunjaStore {
242
241
  activeDependencyDeps: [],
243
242
  use: ((dep, scopeValuePairs) => {
244
243
  if (dep instanceof Scope) return this.#useScopeInFrame(frame, dep);
245
- if (dep instanceof Bunja || isBunjaRef(dep)) return this.#useBunjaDependencyInFrame(frame, normalizeBunjaRuntimeRef(dep, scopeValuePairs), "required");
244
+ if (dep instanceof Bunja || isBunjaRef(dep)) {
245
+ const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
246
+ const graphRef = toBunjaGraphRef(bunjaRef);
247
+ currentBunja.addRequiredBunjaRef(graphRef);
248
+ return this.#useBunjaDependencyInFrame(frame, bunjaRef);
249
+ }
246
250
  throw new Error("`bunja.use` can only be used with Bunja or Scope.");
247
251
  }),
248
252
  will: ((dep, scopeValuePairs) => {
249
253
  if (!(dep instanceof Bunja || isBunjaRef(dep))) throw new Error("`bunja.will` can only be used with Bunja.");
250
254
  const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
251
- currentBunja.addOptionalBunjaRef(toBunjaGraphRef(bunjaRef));
255
+ const graphRef = toBunjaGraphRef(bunjaRef);
256
+ currentBunja.addOptionalBunjaRef(graphRef);
252
257
  return () => {
253
258
  if (frameStack[frameStack.length - 1] !== frame) throw new Error("A thunk returned by `bunja.will` can only be called inside the same bunja init function.");
254
- return this.#useBunjaDependencyInFrame(frame, bunjaRef, "optional");
259
+ return this.#useBunjaDependencyInFrame(frame, bunjaRef);
255
260
  };
256
261
  }),
257
262
  effect: ((callback) => {
@@ -270,10 +275,8 @@ var BunjaStore = class BunjaStore {
270
275
  }
271
276
  return scopeInstance.value;
272
277
  }
273
- #useBunjaDependencyInFrame(frame, bunjaRef, edge) {
278
+ #useBunjaDependencyInFrame(frame, bunjaRef) {
274
279
  const graphRef = toBunjaGraphRef(bunjaRef);
275
- if (edge === "optional" || graphRef.scopeValuePairs.length > 0) frame.currentBunja.addOptionalBunjaRef(graphRef);
276
- else if (edge === "required") frame.currentBunja.addRequiredBunjaRef(graphRef);
277
280
  const resolved = this.#resolveBunjaRef(graphRef, frame.readScope, frame.inProgressBunjas, bunjaRef.seed);
278
281
  frame.activeDependencyIds.add(resolved.instance.id);
279
282
  frame.activeDependencyRecipes.push({
@@ -331,8 +334,9 @@ var BunjaStore = class BunjaStore {
331
334
  return readScope(dep);
332
335
  }
333
336
  if (dep instanceof Bunja || isBunjaRef(dep)) {
334
- const bunjaRef = normalizeBunjaRuntimeRef(dep, scopeValuePairs);
335
- return this.#prebakeBunjaDependencyInFrame(frame, toBunjaGraphRef(bunjaRef), "required");
337
+ const bunjaRef = toBunjaGraphRef(normalizeBunjaRuntimeRef(dep, scopeValuePairs));
338
+ currentBunja.addRequiredBunjaRef(bunjaRef);
339
+ return this.#prebakeBunjaRef(bunjaRef, readScope, prebakeContext);
336
340
  }
337
341
  throw new Error("`bunja.use` can only be used with Bunja or Scope.");
338
342
  }),
@@ -350,11 +354,6 @@ var BunjaStore = class BunjaStore {
350
354
  };
351
355
  return frame;
352
356
  }
353
- #prebakeBunjaDependencyInFrame(frame, bunjaRef, edge) {
354
- if (edge === "optional" || bunjaRef.scopeValuePairs.length > 0) frame.currentBunja.addOptionalBunjaRef(bunjaRef);
355
- else if (edge === "required") frame.currentBunja.addRequiredBunjaRef(bunjaRef);
356
- return this.#prebakeBunjaRef(bunjaRef, frame.readScope, frame.prebakeContext);
357
- }
358
357
  #resolveScopeInstanceMap(bunja$1, readScope) {
359
358
  const scopeInstanceMap = /* @__PURE__ */ new Map();
360
359
  this.#ensureRequiredScopeInstances(bunja$1, scopeInstanceMap, readScope);
@@ -485,7 +484,10 @@ var Bunja = class Bunja {
485
484
  const requiredBunjas = this.requiredBunjas;
486
485
  const expandedRequiredBunjas = toposortRequiredBunjas(requiredBunjas);
487
486
  const requiredScopeSet = /* @__PURE__ */ new Set();
488
- for (const bunja$1 of expandedRequiredBunjas) for (const scope of bunja$1.requiredScopes) requiredScopeSet.add(scope);
487
+ for (const ref of requiredBunjaRefs) {
488
+ const boundScopes = getBoundScopeSet(ref.scopeValuePairs);
489
+ for (const scope of ref.bunja.requiredScopes) if (!boundScopes.has(scope)) requiredScopeSet.add(scope);
490
+ }
489
491
  for (const scope of scopes) requiredScopeSet.add(scope);
490
492
  this.#phase = {
491
493
  baked: true,
@@ -1,29 +1,14 @@
1
1
  //#region bunja.d.ts
2
2
  interface BunjaFn {
3
- <T>(init: () => T): Bunja<T, NoSeed>;
3
+ <T>(init: () => T): Bunja<T, undefined>;
4
4
  withSeed: BunjaWithSeedFn;
5
5
  use: BunjaUseFn;
6
6
  will: BunjaWillFn;
7
7
  effect: BunjaEffectFn;
8
8
  }
9
9
  declare const bunja: BunjaFn;
10
- declare const NO_SEED: unique symbol;
11
- type NoSeed = typeof NO_SEED;
12
10
  type BunjaWithSeedFn = <Seed, T>(defaultSeed: Seed, init: (seed: Seed) => T) => Bunja<T, Seed>;
13
11
  type ScopeValuePairs = ScopeValuePair<any>[];
14
- type BunjaRefBase<T, Seed> = {
15
- bunja: Bunja<T, Seed>;
16
- with?: ScopeValuePairs;
17
- };
18
- type BunjaGetRef<T, Seed = NoSeed> = BunjaRefBase<T, Seed> & ([Seed] extends [NoSeed] ? {
19
- seed?: never;
20
- } : {
21
- seed?: Seed;
22
- });
23
- type BunjaRef<T, Seed = NoSeed> = BunjaGetRef<T, Seed>;
24
- type BunjaPrebakeRef<T, Seed = NoSeed> = BunjaRefBase<T, Seed> & {
25
- seed?: never;
26
- };
27
12
  interface BunjaUseFn {
28
13
  <T>(dep: Scope<T>): T;
29
14
  <T, Seed>(dep: Bunja<T, Seed>): T;
@@ -37,6 +22,17 @@ interface BunjaWillFn {
37
22
  }
38
23
  type BunjaEffectFn = (callback: BunjaEffectCallback) => void;
39
24
  type BunjaEffectCallback = () => (() => void) | void;
25
+ interface BunjaRef<T, Seed = undefined> extends BunjaRefBase<T, Seed> {
26
+ seed?: [Seed] extends [undefined] ? never : Seed;
27
+ }
28
+ type BunjaGetRef<T, Seed = undefined> = BunjaRef<T, Seed>;
29
+ interface BunjaPrebakeRef<T, Seed> extends BunjaRefBase<T, Seed> {
30
+ seed?: never;
31
+ }
32
+ interface BunjaRefBase<T, Seed> {
33
+ bunja: Bunja<T, Seed>;
34
+ with?: ScopeValuePairs;
35
+ }
40
36
  declare function createScope<T>(hash?: HashFn<T>): Scope<T>;
41
37
  interface CreateBunjaStoreConfig {
42
38
  wrapInstance?: WrapInstanceFn;
@@ -86,7 +82,7 @@ interface BunjaStorePrebakeResult {
86
82
  requiredScopes: Scope<unknown>[];
87
83
  }
88
84
  declare function delayUnmount(mount: () => () => void, ms?: number): () => () => void;
89
- declare class Bunja<T, Seed = NoSeed> {
85
+ declare class Bunja<T, Seed = undefined> {
90
86
  #private;
91
87
  init: (seed: Seed) => T;
92
88
  defaultSeed: Seed;
@@ -193,4 +189,4 @@ interface BunjaDevtoolsEvent {
193
189
  }
194
190
  type BunjaDevtoolsEventType = keyof BunjaDevtoolsEvent;
195
191
  //#endregion
196
- export { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, NoSeed, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
192
+ export { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaPrebakeRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
package/dist/bunja.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_bunja = require('./bunja-BJSmIdkQ.cjs');
1
+ const require_bunja = require('./bunja-DJPGfe5j.cjs');
2
2
 
3
3
  exports.Bunja = require_bunja.Bunja;
4
4
  exports.BunjaStore = require_bunja.BunjaStore;
package/dist/bunja.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, NoSeed, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount } from "./bunja-BxbzuHdH.cjs";
2
- export { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, NoSeed, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
1
+ import { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaPrebakeRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount } from "./bunja-B81fiP3K.cjs";
2
+ export { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaPrebakeRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
package/dist/bunja.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, NoSeed, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount } from "./bunja-DEFeIlpt.js";
2
- export { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, NoSeed, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
1
+ import { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaPrebakeRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount } from "./bunja-pdetyCM3.js";
2
+ export { Bunja, BunjaDevtoolsEvent, BunjaDevtoolsEventType, BunjaDevtoolsGlobalHook, BunjaEffectCallback, BunjaEffectFn, BunjaFn, BunjaGetRef, BunjaPrebakeRef, BunjaRef, BunjaStore, BunjaStoreGetResult, BunjaStorePrebakeResult, BunjaUseFn, BunjaWillFn, BunjaWithSeedFn, CreateBunjaStoreConfig, Dep, HashFn, ReadScope, Scope, ScopeValuePair, ScopeValuePairs, WrapInstanceFn, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
package/dist/bunja.js CHANGED
@@ -1,3 +1,3 @@
1
- import { Bunja, BunjaStore, Scope, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount } from "./bunja-CtHOS4_Q.js";
1
+ import { Bunja, BunjaStore, Scope, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount } from "./bunja-BmPnlAec.js";
2
2
 
3
3
  export { Bunja, BunjaStore, Scope, bunja, createBunjaStore, createReadScopeFn, createScope, delayUnmount };
package/dist/react.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
  const require_chunk = require('./chunk-CUT6urMc.cjs');
5
- const require_bunja = require('./bunja-BJSmIdkQ.cjs');
5
+ const require_bunja = require('./bunja-DJPGfe5j.cjs');
6
6
  let react = require("react");
7
7
  react = require_chunk.__toESM(react);
8
8
 
package/dist/react.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Bunja, BunjaGetRef, BunjaStore, HashFn, Scope, ScopeValuePairs } from "./bunja-BxbzuHdH.cjs";
1
+ import { Bunja, BunjaGetRef, BunjaStore, HashFn, Scope, ScopeValuePairs } from "./bunja-B81fiP3K.cjs";
2
2
  import * as React from "react";
3
3
  import { Context, PropsWithChildren } from "react";
4
4
 
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Bunja, BunjaGetRef, BunjaStore, HashFn, Scope, ScopeValuePairs } from "./bunja-DEFeIlpt.js";
1
+ import { Bunja, BunjaGetRef, BunjaStore, HashFn, Scope, ScopeValuePairs } from "./bunja-pdetyCM3.js";
2
2
  import * as React from "react";
3
3
  import { Context, PropsWithChildren } from "react";
4
4
 
package/dist/react.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
 
4
- import { createBunjaStore, createReadScopeFn, createScope, delayUnmount } from "./bunja-CtHOS4_Q.js";
4
+ import { createBunjaStore, createReadScopeFn, createScope, delayUnmount } from "./bunja-BmPnlAec.js";
5
5
  import * as React from "react";
6
6
  import { createContext, createElement, useContext, useEffect, useMemo, useState } from "react";
7
7
 
package/dist/solid.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_bunja = require('./bunja-BJSmIdkQ.cjs');
2
+ const require_bunja = require('./bunja-DJPGfe5j.cjs');
3
3
  let solid_js = require("solid-js");
4
4
  solid_js = require_chunk.__toESM(solid_js);
5
5
 
package/dist/solid.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Bunja, BunjaGetRef, BunjaStore, HashFn, Scope, ScopeValuePairs } from "./bunja-BxbzuHdH.cjs";
1
+ import { Bunja, BunjaGetRef, BunjaStore, HashFn, Scope, ScopeValuePairs } from "./bunja-B81fiP3K.cjs";
2
2
  import { Accessor, Context, JSX, ParentProps } from "solid-js";
3
3
 
4
4
  //#region solid.d.ts
package/dist/solid.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Bunja, BunjaGetRef, BunjaStore, HashFn, Scope, ScopeValuePairs } from "./bunja-DEFeIlpt.js";
1
+ import { Bunja, BunjaGetRef, BunjaStore, HashFn, Scope, ScopeValuePairs } from "./bunja-pdetyCM3.js";
2
2
  import { Accessor, Context, JSX, ParentProps } from "solid-js";
3
3
 
4
4
  //#region solid.d.ts
package/dist/solid.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createBunjaStore, createReadScopeFn, createScope } from "./bunja-CtHOS4_Q.js";
1
+ import { createBunjaStore, createReadScopeFn, createScope } from "./bunja-BmPnlAec.js";
2
2
  import { createComponent, createContext, createEffect, createMemo, createRoot, getOwner, onCleanup, useContext } from "solid-js";
3
3
 
4
4
  //#region solid.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bunja",
3
3
  "type": "module",
4
- "version": "3.0.0-alpha.3",
4
+ "version": "3.0.0-alpha.5",
5
5
  "description": "State Lifetime Manager",
6
6
  "main": "dist/bunja.cjs",
7
7
  "module": "dist/bunja.js",
package/test.ts CHANGED
@@ -207,6 +207,32 @@ Deno.test({
207
207
  },
208
208
  });
209
209
 
210
+ Deno.test({
211
+ name: "root scope value pairs are included in store.get deps",
212
+ fn() {
213
+ const store = createBunjaStore();
214
+ const myScope = createScope<string>();
215
+ const myBunja = bunja(() => {
216
+ const scopeValue = bunja.use(myScope);
217
+ return { scopeValue };
218
+ });
219
+
220
+ const first = store.get(
221
+ { bunja: myBunja, with: [myScope.bind("foo")] },
222
+ readNull,
223
+ );
224
+ const second = store.get(
225
+ { bunja: myBunja, with: [myScope.bind("bar")] },
226
+ readNull,
227
+ );
228
+
229
+ assertEquals(first.value.scopeValue, "foo");
230
+ assertEquals(second.value.scopeValue, "bar");
231
+ assertEquals(first.deps, ["foo"]);
232
+ assertEquals(second.deps, ["bar"]);
233
+ },
234
+ });
235
+
210
236
  Deno.test({
211
237
  name: "bunja.use can override scope value pairs inside a bunja init",
212
238
  fn() {
@@ -272,6 +298,56 @@ Deno.test({
272
298
  },
273
299
  });
274
300
 
301
+ Deno.test({
302
+ name: "bunja.use with scope value pairs propagates unbound required scopes",
303
+ fn() {
304
+ const createGraph = () => {
305
+ const injectedScope = createScope<string>();
306
+ const outerScope = createScope<string>();
307
+ const dependencyBunja = bunja(() => {
308
+ const injected = bunja.use(injectedScope);
309
+ const outer = bunja.use(outerScope);
310
+ return { injected, outer };
311
+ });
312
+ const consumerBunja = bunja(() =>
313
+ bunja.use(dependencyBunja, [injectedScope.bind("injected")])
314
+ );
315
+ return { consumerBunja, injectedScope, outerScope };
316
+ };
317
+ const readScope = <T>() => "outer" as T;
318
+
319
+ const prebakeGraph = createGraph();
320
+ const { requiredScopes } = createBunjaStore().prebake(
321
+ prebakeGraph.consumerBunja,
322
+ readScope,
323
+ );
324
+ assertEquals(requiredScopes.length, 1);
325
+ assertEquals(requiredScopes[0] === prebakeGraph.outerScope, true);
326
+ assertEquals(
327
+ requiredScopes.some((scope) => scope === prebakeGraph.injectedScope),
328
+ false,
329
+ );
330
+
331
+ const getGraph = createGraph();
332
+ const { value, deps } = createBunjaStore().get(
333
+ getGraph.consumerBunja,
334
+ readScope,
335
+ );
336
+ const requiredScopes2 = getGraph.consumerBunja.requiredScopes;
337
+ assertEquals(value, { injected: "injected", outer: "outer" });
338
+ assertEquals(deps, ["outer"]);
339
+ assertEquals(requiredScopes2.length, 1);
340
+ assertEquals(
341
+ requiredScopes2[0] === getGraph.outerScope,
342
+ true,
343
+ );
344
+ assertEquals(
345
+ requiredScopes2.some((scope) => scope === getGraph.injectedScope),
346
+ false,
347
+ );
348
+ },
349
+ });
350
+
275
351
  Deno.test({
276
352
  name: "seed is used only when creating a bunja instance",
277
353
  fn() {
@@ -404,6 +480,29 @@ Deno.test({
404
480
  },
405
481
  });
406
482
 
483
+ Deno.test({
484
+ name: "bunja.will records optional refs once when thunk is used",
485
+ fn() {
486
+ const createConsumer = () => {
487
+ const dependencyBunja = bunja(() => "dependency");
488
+ const consumerBunja = bunja(() => {
489
+ const getDependency = bunja.will(dependencyBunja);
490
+ return getDependency();
491
+ });
492
+ return { consumerBunja };
493
+ };
494
+
495
+ const getGraph = createConsumer();
496
+ createBunjaStore().get(getGraph.consumerBunja, readNull);
497
+
498
+ const prebakeGraph = createConsumer();
499
+ createBunjaStore().prebake(prebakeGraph.consumerBunja, readNull);
500
+
501
+ assertEquals(getGraph.consumerBunja.optionalBunjaRefs.length, 1);
502
+ assertEquals(prebakeGraph.consumerBunja.optionalBunjaRefs.length, 1);
503
+ },
504
+ });
505
+
407
506
  Deno.test({
408
507
  name: "relatedBunjas includes nested bunja.will dependencies",
409
508
  fn() {