@pumped-fn/lite 2.1.3 → 2.1.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/CHANGELOG.md +70 -0
- package/dist/cli.cjs +249 -64
- package/dist/cli.mjs +249 -64
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +176 -157
- package/dist/index.d.cts +15 -15
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +15 -15
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +176 -157
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
package/dist/index.cjs
CHANGED
|
@@ -587,9 +587,8 @@ var ControllerImpl = class {
|
|
|
587
587
|
get() {
|
|
588
588
|
const entry = this.scope.getEntry(this.atom);
|
|
589
589
|
if (!entry || entry.state === "idle") throw new Error("Atom not resolved");
|
|
590
|
-
if (entry.state === "failed"
|
|
591
|
-
if (entry.
|
|
592
|
-
if (entry.state === "resolved" && entry.hasValue) return entry.value;
|
|
590
|
+
if (entry.state === "failed") throw entry.error;
|
|
591
|
+
if (entry.hasValue) return entry.value;
|
|
593
592
|
throw new Error("Atom not resolved");
|
|
594
593
|
}
|
|
595
594
|
async resolve() {
|
|
@@ -617,8 +616,7 @@ var ScopeImpl = class {
|
|
|
617
616
|
resolving = /* @__PURE__ */ new Set();
|
|
618
617
|
pending = /* @__PURE__ */ new Map();
|
|
619
618
|
stateListeners = /* @__PURE__ */ new Map();
|
|
620
|
-
invalidationQueue =
|
|
621
|
-
invalidationScheduled = false;
|
|
619
|
+
invalidationQueue = [];
|
|
622
620
|
invalidationChain = null;
|
|
623
621
|
chainPromise = null;
|
|
624
622
|
chainError = null;
|
|
@@ -631,48 +629,33 @@ var ScopeImpl = class {
|
|
|
631
629
|
resolveExts;
|
|
632
630
|
execExts;
|
|
633
631
|
ready;
|
|
634
|
-
scheduleInvalidation(atom$1) {
|
|
635
|
-
|
|
636
|
-
|
|
632
|
+
scheduleInvalidation(atom$1, entry) {
|
|
633
|
+
if (!entry) {
|
|
634
|
+
entry = this.cache.get(atom$1);
|
|
635
|
+
if (!entry || entry.state === "idle") return;
|
|
636
|
+
}
|
|
637
637
|
if (entry.state === "resolving") {
|
|
638
638
|
entry.pendingInvalidate = true;
|
|
639
639
|
return;
|
|
640
640
|
}
|
|
641
|
-
this.invalidationQueue.
|
|
641
|
+
if (!this.invalidationQueue.includes(atom$1)) this.invalidationQueue.push(atom$1);
|
|
642
642
|
if (!this.chainPromise) {
|
|
643
|
-
this.invalidationChain = /* @__PURE__ */ new Set();
|
|
644
|
-
this.invalidationScheduled = true;
|
|
645
643
|
this.chainError = null;
|
|
646
|
-
this.chainPromise = (
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
});
|
|
650
|
-
try {
|
|
651
|
-
await this.processInvalidationChain();
|
|
652
|
-
} catch (error) {
|
|
653
|
-
if (this.chainError === null) this.chainError = error;
|
|
654
|
-
}
|
|
655
|
-
})();
|
|
644
|
+
this.chainPromise = Promise.resolve().then(() => this.processInvalidationChain().catch((error) => {
|
|
645
|
+
if (this.chainError === null) this.chainError = error;
|
|
646
|
+
}));
|
|
656
647
|
}
|
|
657
648
|
}
|
|
658
649
|
async processInvalidationChain() {
|
|
659
650
|
try {
|
|
660
|
-
while (this.invalidationQueue.
|
|
661
|
-
const atom$1 = this.invalidationQueue.
|
|
662
|
-
this.
|
|
663
|
-
if (
|
|
664
|
-
const chainAtoms = Array.from(this.invalidationChain);
|
|
665
|
-
chainAtoms.push(atom$1);
|
|
666
|
-
const path = chainAtoms.map((a) => a.factory?.name || "<anonymous>").join(" → ");
|
|
667
|
-
throw new Error(`Infinite invalidation loop detected: ${path}`);
|
|
668
|
-
}
|
|
669
|
-
this.invalidationChain.add(atom$1);
|
|
670
|
-
await this.doInvalidateSequential(atom$1);
|
|
651
|
+
while (this.invalidationQueue.length > 0 && !this.disposed) {
|
|
652
|
+
const atom$1 = this.invalidationQueue.shift();
|
|
653
|
+
const result = this.doInvalidateSequential(atom$1);
|
|
654
|
+
if (result) await result;
|
|
671
655
|
}
|
|
672
656
|
} finally {
|
|
673
657
|
this.invalidationChain = null;
|
|
674
658
|
this.chainPromise = null;
|
|
675
|
-
this.invalidationScheduled = false;
|
|
676
659
|
}
|
|
677
660
|
}
|
|
678
661
|
constructor(options) {
|
|
@@ -715,79 +698,68 @@ var ScopeImpl = class {
|
|
|
715
698
|
return entry;
|
|
716
699
|
}
|
|
717
700
|
addListener(atom$1, event, listener) {
|
|
718
|
-
this.
|
|
719
|
-
|
|
701
|
+
const entry = this.getOrCreateEntry(atom$1);
|
|
702
|
+
if (entry.gcScheduled) {
|
|
703
|
+
clearTimeout(entry.gcScheduled);
|
|
704
|
+
entry.gcScheduled = null;
|
|
705
|
+
}
|
|
706
|
+
const listeners = entry.listeners.get(event);
|
|
720
707
|
listeners.add(listener);
|
|
721
708
|
return () => {
|
|
722
709
|
listeners.delete(listener);
|
|
723
|
-
this.
|
|
710
|
+
this.maybeScheduleGCEntry(atom$1, entry);
|
|
724
711
|
};
|
|
725
712
|
}
|
|
726
|
-
|
|
727
|
-
const
|
|
728
|
-
|
|
729
|
-
let count = 0;
|
|
730
|
-
for (const listeners of entry.listeners.values()) count += listeners.size;
|
|
731
|
-
return count;
|
|
713
|
+
hasSubscribers(entry) {
|
|
714
|
+
for (const listeners of entry.listeners.values()) if (listeners.size > 0) return true;
|
|
715
|
+
return false;
|
|
732
716
|
}
|
|
733
|
-
|
|
717
|
+
maybeScheduleGCEntry(atom$1, entry) {
|
|
734
718
|
if (!this.gcOptions.enabled) return;
|
|
735
719
|
if (atom$1.keepAlive) return;
|
|
736
|
-
const entry = this.cache.get(atom$1);
|
|
737
|
-
if (!entry) return;
|
|
738
720
|
if (entry.state === "idle") return;
|
|
739
|
-
if (this.
|
|
721
|
+
if (this.hasSubscribers(entry)) return;
|
|
740
722
|
if (entry.dependents.size > 0) return;
|
|
741
723
|
if (entry.gcScheduled) return;
|
|
742
724
|
entry.gcScheduled = setTimeout(() => {
|
|
743
725
|
this.executeGC(atom$1);
|
|
744
726
|
}, this.gcOptions.graceMs);
|
|
745
727
|
}
|
|
746
|
-
cancelScheduledGC(atom$1) {
|
|
747
|
-
const entry = this.cache.get(atom$1);
|
|
748
|
-
if (entry?.gcScheduled) {
|
|
749
|
-
clearTimeout(entry.gcScheduled);
|
|
750
|
-
entry.gcScheduled = null;
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
728
|
async executeGC(atom$1) {
|
|
754
729
|
const entry = this.cache.get(atom$1);
|
|
755
730
|
if (!entry) return;
|
|
756
731
|
entry.gcScheduled = null;
|
|
757
|
-
if (this.
|
|
732
|
+
if (this.hasSubscribers(entry)) return;
|
|
758
733
|
if (entry.dependents.size > 0) return;
|
|
759
734
|
if (atom$1.keepAlive) return;
|
|
760
735
|
await this.release(atom$1);
|
|
761
|
-
if (atom$1.deps) for (const
|
|
736
|
+
if (atom$1.deps) for (const key in atom$1.deps) {
|
|
737
|
+
const dep = atom$1.deps[key];
|
|
762
738
|
const depAtom = isAtom(dep) ? dep : isControllerDep(dep) ? dep.atom : null;
|
|
763
739
|
if (!depAtom) continue;
|
|
764
740
|
const depEntry = this.cache.get(depAtom);
|
|
765
741
|
if (depEntry) {
|
|
766
742
|
depEntry.dependents.delete(atom$1);
|
|
767
|
-
this.
|
|
743
|
+
this.maybeScheduleGCEntry(depAtom, depEntry);
|
|
768
744
|
}
|
|
769
745
|
}
|
|
770
746
|
}
|
|
771
|
-
|
|
772
|
-
const entry = this.cache.get(atom$1);
|
|
773
|
-
if (!entry) return;
|
|
747
|
+
notifyEntry(entry, event) {
|
|
774
748
|
const eventListeners = entry.listeners.get(event);
|
|
775
749
|
if (eventListeners?.size) for (const listener of [...eventListeners]) listener();
|
|
776
750
|
const allListeners = entry.listeners.get("*");
|
|
777
|
-
if (allListeners?.size) for (const listener of
|
|
751
|
+
if (allListeners?.size) for (const listener of allListeners) listener();
|
|
778
752
|
}
|
|
779
|
-
|
|
780
|
-
const entry = this.cache.get(atom$1);
|
|
781
|
-
if (!entry) return;
|
|
753
|
+
notifyEntryAll(entry) {
|
|
782
754
|
const allListeners = entry.listeners.get("*");
|
|
783
|
-
if (allListeners?.size) for (const listener of
|
|
755
|
+
if (allListeners?.size) for (const listener of allListeners) listener();
|
|
784
756
|
}
|
|
785
757
|
emitStateChange(state, atom$1) {
|
|
758
|
+
if (this.stateListeners.size === 0) return;
|
|
786
759
|
const stateMap = this.stateListeners.get(state);
|
|
787
|
-
if (stateMap)
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
}
|
|
760
|
+
if (!stateMap) return;
|
|
761
|
+
const listeners = stateMap.get(atom$1);
|
|
762
|
+
if (listeners?.size) for (const listener of [...listeners]) listener();
|
|
791
763
|
}
|
|
792
764
|
on(event, atom$1, listener) {
|
|
793
765
|
let stateMap = this.stateListeners.get(event);
|
|
@@ -811,14 +783,17 @@ var ScopeImpl = class {
|
|
|
811
783
|
}
|
|
812
784
|
};
|
|
813
785
|
}
|
|
814
|
-
|
|
815
|
-
if (this.disposed)
|
|
816
|
-
if (!this.initialized)
|
|
786
|
+
resolve(atom$1) {
|
|
787
|
+
if (this.disposed) return Promise.reject(/* @__PURE__ */ new Error("Scope is disposed"));
|
|
788
|
+
if (!this.initialized) {
|
|
789
|
+
if (!this.ready) return this.resolveAndTrack(atom$1);
|
|
790
|
+
return this.ready.then(() => this.resolve(atom$1));
|
|
791
|
+
}
|
|
817
792
|
const entry = this.cache.get(atom$1);
|
|
818
|
-
if (entry?.state === "resolved") return entry.value;
|
|
793
|
+
if (entry?.state === "resolved") return entry.resolvedPromise ?? (entry.resolvedPromise = Promise.resolve(entry.value));
|
|
819
794
|
const pendingPromise = this.pending.get(atom$1);
|
|
820
795
|
if (pendingPromise) return pendingPromise;
|
|
821
|
-
if (this.resolving.has(atom$1))
|
|
796
|
+
if (this.resolving.has(atom$1)) return Promise.reject(/* @__PURE__ */ new Error("Circular dependency detected"));
|
|
822
797
|
if (this.presets.has(atom$1)) {
|
|
823
798
|
const presetValue = this.presets.get(atom$1);
|
|
824
799
|
if (isAtom(presetValue)) return this.resolve(presetValue);
|
|
@@ -827,9 +802,12 @@ var ScopeImpl = class {
|
|
|
827
802
|
newEntry.value = presetValue;
|
|
828
803
|
newEntry.hasValue = true;
|
|
829
804
|
this.emitStateChange("resolved", atom$1);
|
|
830
|
-
this.
|
|
831
|
-
return newEntry.value;
|
|
805
|
+
this.notifyEntry(newEntry, "resolved");
|
|
806
|
+
return Promise.resolve(newEntry.value);
|
|
832
807
|
}
|
|
808
|
+
return this.resolveAndTrack(atom$1);
|
|
809
|
+
}
|
|
810
|
+
async resolveAndTrack(atom$1) {
|
|
833
811
|
this.resolving.add(atom$1);
|
|
834
812
|
const promise = this.doResolve(atom$1);
|
|
835
813
|
this.pending.set(atom$1, promise);
|
|
@@ -849,7 +827,7 @@ var ScopeImpl = class {
|
|
|
849
827
|
entry.cleanups = [];
|
|
850
828
|
entry.state = "resolving";
|
|
851
829
|
this.emitStateChange("resolving", atom$1);
|
|
852
|
-
this.
|
|
830
|
+
this.notifyEntry(entry, "resolving");
|
|
853
831
|
}
|
|
854
832
|
const resolvedDeps = await this.resolveDeps(atom$1.deps, void 0, atom$1);
|
|
855
833
|
const ctx = {
|
|
@@ -864,23 +842,25 @@ var ScopeImpl = class {
|
|
|
864
842
|
}
|
|
865
843
|
};
|
|
866
844
|
const factory = atom$1.factory;
|
|
867
|
-
const doResolve = async () => {
|
|
868
|
-
if (atom$1.deps) return factory(ctx, resolvedDeps);
|
|
869
|
-
else return factory(ctx);
|
|
870
|
-
};
|
|
871
845
|
try {
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
846
|
+
let value;
|
|
847
|
+
if (this.resolveExts.length === 0) value = atom$1.deps ? await factory(ctx, resolvedDeps) : await factory(ctx);
|
|
848
|
+
else {
|
|
849
|
+
const doResolve = async () => atom$1.deps ? factory(ctx, resolvedDeps) : factory(ctx);
|
|
850
|
+
const event = {
|
|
851
|
+
kind: "atom",
|
|
852
|
+
target: atom$1,
|
|
853
|
+
scope: this
|
|
854
|
+
};
|
|
855
|
+
value = await this.applyResolveExtensions(event, doResolve);
|
|
856
|
+
}
|
|
878
857
|
entry.state = "resolved";
|
|
879
858
|
entry.value = value;
|
|
880
859
|
entry.hasValue = true;
|
|
881
860
|
entry.error = void 0;
|
|
861
|
+
entry.resolvedPromise = Promise.resolve(value);
|
|
882
862
|
this.emitStateChange("resolved", atom$1);
|
|
883
|
-
this.
|
|
863
|
+
this.notifyEntry(entry, "resolved");
|
|
884
864
|
if (entry.pendingInvalidate) {
|
|
885
865
|
entry.pendingInvalidate = false;
|
|
886
866
|
this.invalidationChain?.delete(atom$1);
|
|
@@ -896,7 +876,7 @@ var ScopeImpl = class {
|
|
|
896
876
|
entry.value = void 0;
|
|
897
877
|
entry.hasValue = false;
|
|
898
878
|
this.emitStateChange("failed", atom$1);
|
|
899
|
-
this.
|
|
879
|
+
this.notifyEntryAll(entry);
|
|
900
880
|
if (entry.pendingInvalidate) {
|
|
901
881
|
entry.pendingInvalidate = false;
|
|
902
882
|
this.invalidationChain?.delete(atom$1);
|
|
@@ -924,39 +904,61 @@ var ScopeImpl = class {
|
|
|
924
904
|
const deferredResources = [];
|
|
925
905
|
for (const key in deps) {
|
|
926
906
|
const dep = deps[key];
|
|
927
|
-
if (isAtom(dep))
|
|
928
|
-
|
|
929
|
-
if (
|
|
930
|
-
|
|
931
|
-
if (
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
|
|
907
|
+
if (isAtom(dep)) {
|
|
908
|
+
const cachedEntry = this.cache.get(dep);
|
|
909
|
+
if (cachedEntry?.state === "resolved") {
|
|
910
|
+
result[key] = cachedEntry.value;
|
|
911
|
+
if (dependentAtom) cachedEntry.dependents.add(dependentAtom);
|
|
912
|
+
} else parallel.push(this.resolve(dep).then((value) => {
|
|
913
|
+
result[key] = value;
|
|
914
|
+
if (dependentAtom) {
|
|
915
|
+
const depEntry = this.getEntry(dep);
|
|
916
|
+
if (depEntry) depEntry.dependents.add(dependentAtom);
|
|
917
|
+
}
|
|
918
|
+
}));
|
|
919
|
+
} else if (isControllerDep(dep)) {
|
|
935
920
|
if (dep.watch) {
|
|
936
921
|
if (!dependentAtom) throw new Error("controller({ watch: true }) is only supported in atom dependencies");
|
|
937
922
|
if (!dep.resolve) throw new Error("controller({ watch: true }) requires resolve: true");
|
|
938
923
|
}
|
|
939
924
|
const ctrl = this.controller(dep.atom);
|
|
940
|
-
if (dep.resolve)
|
|
941
|
-
|
|
942
|
-
if (
|
|
943
|
-
|
|
944
|
-
if (
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
|
|
925
|
+
if (dep.resolve) {
|
|
926
|
+
const cachedCtrlEntry = this.cache.get(dep.atom);
|
|
927
|
+
if (cachedCtrlEntry?.state === "resolved") {
|
|
928
|
+
result[key] = ctrl;
|
|
929
|
+
if (dependentAtom) cachedCtrlEntry.dependents.add(dependentAtom);
|
|
930
|
+
if (dep.watch) {
|
|
931
|
+
const eq = dep.eq ?? shallowEqual;
|
|
932
|
+
let prev = ctrl.get();
|
|
933
|
+
const unsub = this.on("resolved", dep.atom, () => {
|
|
934
|
+
const next = ctrl.get();
|
|
935
|
+
if (!eq(prev, next)) this.scheduleInvalidation(dependentAtom);
|
|
936
|
+
prev = next;
|
|
937
|
+
});
|
|
938
|
+
const depEntry = this.getEntry(dependentAtom);
|
|
939
|
+
if (depEntry) depEntry.cleanups.push(unsub);
|
|
940
|
+
else unsub();
|
|
941
|
+
}
|
|
942
|
+
} else parallel.push(ctrl.resolve().then(() => {
|
|
943
|
+
result[key] = ctrl;
|
|
944
|
+
if (dependentAtom) {
|
|
945
|
+
const depEntry = this.getEntry(dep.atom);
|
|
946
|
+
if (depEntry) depEntry.dependents.add(dependentAtom);
|
|
947
|
+
}
|
|
948
|
+
if (dep.watch) {
|
|
949
|
+
const eq = dep.eq ?? shallowEqual;
|
|
950
|
+
let prev = ctrl.get();
|
|
951
|
+
const unsub = this.on("resolved", dep.atom, () => {
|
|
952
|
+
const next = ctrl.get();
|
|
953
|
+
if (!eq(prev, next)) this.scheduleInvalidation(dependentAtom);
|
|
954
|
+
prev = next;
|
|
955
|
+
});
|
|
956
|
+
const depEntry = this.getEntry(dependentAtom);
|
|
957
|
+
if (depEntry) depEntry.cleanups.push(unsub);
|
|
958
|
+
else unsub();
|
|
959
|
+
}
|
|
960
|
+
}));
|
|
961
|
+
} else {
|
|
960
962
|
result[key] = ctrl;
|
|
961
963
|
if (dependentAtom) {
|
|
962
964
|
const depEntry = this.getEntry(dep.atom);
|
|
@@ -1016,17 +1018,18 @@ var ScopeImpl = class {
|
|
|
1016
1018
|
localResolvingResources.add(resourceKey);
|
|
1017
1019
|
try {
|
|
1018
1020
|
const resourceDeps = await this.resolveDeps(resource$1.deps, ctx);
|
|
1019
|
-
const
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1021
|
+
const factory = resource$1.factory;
|
|
1022
|
+
let value;
|
|
1023
|
+
if (this.resolveExts.length === 0) value = resource$1.deps ? await factory(storeCtx, resourceDeps) : await factory(storeCtx);
|
|
1024
|
+
else {
|
|
1025
|
+
const event = {
|
|
1026
|
+
kind: "resource",
|
|
1027
|
+
target: resource$1,
|
|
1028
|
+
ctx: storeCtx
|
|
1029
|
+
};
|
|
1030
|
+
const doResolve = async () => resource$1.deps ? factory(storeCtx, resourceDeps) : factory(storeCtx);
|
|
1031
|
+
value = await this.applyResolveExtensions(event, doResolve);
|
|
1032
|
+
}
|
|
1030
1033
|
storeCtx.data.set(resourceKey, value);
|
|
1031
1034
|
return value;
|
|
1032
1035
|
} finally {
|
|
@@ -1088,7 +1091,7 @@ var ScopeImpl = class {
|
|
|
1088
1091
|
return;
|
|
1089
1092
|
}
|
|
1090
1093
|
entry.pendingSet = { value };
|
|
1091
|
-
this.scheduleInvalidation(atom$1);
|
|
1094
|
+
this.scheduleInvalidation(atom$1, entry);
|
|
1092
1095
|
}
|
|
1093
1096
|
scheduleUpdate(atom$1, fn) {
|
|
1094
1097
|
const entry = this.cache.get(atom$1);
|
|
@@ -1099,9 +1102,9 @@ var ScopeImpl = class {
|
|
|
1099
1102
|
return;
|
|
1100
1103
|
}
|
|
1101
1104
|
entry.pendingSet = { fn };
|
|
1102
|
-
this.scheduleInvalidation(atom$1);
|
|
1105
|
+
this.scheduleInvalidation(atom$1, entry);
|
|
1103
1106
|
}
|
|
1104
|
-
|
|
1107
|
+
doInvalidateSequential(atom$1) {
|
|
1105
1108
|
const entry = this.cache.get(atom$1);
|
|
1106
1109
|
if (!entry) return;
|
|
1107
1110
|
if (entry.state === "idle") return;
|
|
@@ -1109,23 +1112,27 @@ var ScopeImpl = class {
|
|
|
1109
1112
|
const pendingSet = entry.pendingSet;
|
|
1110
1113
|
entry.pendingSet = void 0;
|
|
1111
1114
|
if (pendingSet) {
|
|
1112
|
-
entry.
|
|
1113
|
-
entry.value = previousValue;
|
|
1114
|
-
entry.error = void 0;
|
|
1115
|
-
entry.pendingInvalidate = false;
|
|
1116
|
-
this.pending.delete(atom$1);
|
|
1117
|
-
this.resolving.delete(atom$1);
|
|
1118
|
-
this.emitStateChange("resolving", atom$1);
|
|
1119
|
-
this.notifyListeners(atom$1, "resolving");
|
|
1120
|
-
if ("value" in pendingSet) entry.value = pendingSet.value;
|
|
1121
|
-
else entry.value = pendingSet.fn(previousValue);
|
|
1115
|
+
entry.value = "value" in pendingSet ? pendingSet.value : pendingSet.fn(previousValue);
|
|
1122
1116
|
entry.state = "resolved";
|
|
1123
1117
|
entry.hasValue = true;
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1118
|
+
entry.error = void 0;
|
|
1119
|
+
entry.pendingInvalidate = false;
|
|
1120
|
+
entry.resolvedPromise = void 0;
|
|
1121
|
+
if (this.stateListeners.size) this.emitStateChange("resolved", atom$1);
|
|
1122
|
+
this.notifyEntry(entry, "resolved");
|
|
1127
1123
|
return;
|
|
1128
1124
|
}
|
|
1125
|
+
if (!this.invalidationChain) this.invalidationChain = /* @__PURE__ */ new Set();
|
|
1126
|
+
if (this.invalidationChain.has(atom$1)) {
|
|
1127
|
+
const chainAtoms = Array.from(this.invalidationChain);
|
|
1128
|
+
chainAtoms.push(atom$1);
|
|
1129
|
+
const path = chainAtoms.map((a) => a.factory?.name || "<anonymous>").join(" → ");
|
|
1130
|
+
throw new Error(`Infinite invalidation loop detected: ${path}`);
|
|
1131
|
+
}
|
|
1132
|
+
this.invalidationChain.add(atom$1);
|
|
1133
|
+
return this.doInvalidateAsync(atom$1, entry, previousValue);
|
|
1134
|
+
}
|
|
1135
|
+
async doInvalidateAsync(atom$1, entry, previousValue) {
|
|
1129
1136
|
for (let i = entry.cleanups.length - 1; i >= 0; i--) try {
|
|
1130
1137
|
await entry.cleanups[i]?.();
|
|
1131
1138
|
} catch {}
|
|
@@ -1137,7 +1144,7 @@ var ScopeImpl = class {
|
|
|
1137
1144
|
this.pending.delete(atom$1);
|
|
1138
1145
|
this.resolving.delete(atom$1);
|
|
1139
1146
|
this.emitStateChange("resolving", atom$1);
|
|
1140
|
-
this.
|
|
1147
|
+
this.notifyEntry(entry, "resolving");
|
|
1141
1148
|
try {
|
|
1142
1149
|
await this.resolve(atom$1);
|
|
1143
1150
|
} catch (e) {
|
|
@@ -1154,15 +1161,17 @@ var ScopeImpl = class {
|
|
|
1154
1161
|
for (let i = entry.cleanups.length - 1; i >= 0; i--) try {
|
|
1155
1162
|
await entry.cleanups[i]?.();
|
|
1156
1163
|
} catch {}
|
|
1157
|
-
if (atom$1.deps) for (const
|
|
1164
|
+
if (atom$1.deps) for (const key in atom$1.deps) {
|
|
1165
|
+
const dep = atom$1.deps[key];
|
|
1158
1166
|
const depAtom = isAtom(dep) ? dep : isControllerDep(dep) ? dep.atom : null;
|
|
1159
1167
|
if (!depAtom) continue;
|
|
1160
1168
|
const depEntry = this.cache.get(depAtom);
|
|
1161
1169
|
if (depEntry) {
|
|
1162
1170
|
depEntry.dependents.delete(atom$1);
|
|
1163
|
-
this.
|
|
1171
|
+
this.maybeScheduleGCEntry(depAtom, depEntry);
|
|
1164
1172
|
}
|
|
1165
1173
|
}
|
|
1174
|
+
this.notifyEntryAll(entry);
|
|
1166
1175
|
this.cache.delete(atom$1);
|
|
1167
1176
|
this.controllers.delete(atom$1);
|
|
1168
1177
|
for (const [state, stateMap] of this.stateListeners) {
|
|
@@ -1175,7 +1184,7 @@ var ScopeImpl = class {
|
|
|
1175
1184
|
await this.chainPromise;
|
|
1176
1185
|
} catch {}
|
|
1177
1186
|
this.disposed = true;
|
|
1178
|
-
this.invalidationQueue.
|
|
1187
|
+
this.invalidationQueue.length = 0;
|
|
1179
1188
|
this.invalidationChain = null;
|
|
1180
1189
|
this.chainPromise = null;
|
|
1181
1190
|
for (const ext of this.extensions) if (ext.dispose) await ext.dispose(this);
|
|
@@ -1197,8 +1206,11 @@ var ScopeImpl = class {
|
|
|
1197
1206
|
createContext(options) {
|
|
1198
1207
|
if (this.disposed) throw new Error("Scope is disposed");
|
|
1199
1208
|
const ctx = new ExecutionContextImpl(this, options);
|
|
1200
|
-
|
|
1201
|
-
|
|
1209
|
+
const ctxTags = options?.tags;
|
|
1210
|
+
if (ctxTags && ctxTags.length > 0) for (let i = 0; i < ctxTags.length; i++) ctx.data.set(ctxTags[i].key, ctxTags[i].value);
|
|
1211
|
+
if (this.tags.length > 0) {
|
|
1212
|
+
for (let i = 0; i < this.tags.length; i++) if (!ctx.data.has(this.tags[i].key)) ctx.data.set(this.tags[i].key, this.tags[i].value);
|
|
1213
|
+
}
|
|
1202
1214
|
return ctx;
|
|
1203
1215
|
}
|
|
1204
1216
|
};
|
|
@@ -1252,8 +1264,11 @@ var ExecutionContextImpl = class ExecutionContextImpl {
|
|
|
1252
1264
|
execName,
|
|
1253
1265
|
flowName: flow$1.name
|
|
1254
1266
|
});
|
|
1255
|
-
for (
|
|
1256
|
-
|
|
1267
|
+
if (execTags && execTags.length > 0) for (let i = 0; i < execTags.length; i++) childCtx.data.set(execTags[i].key, execTags[i].value);
|
|
1268
|
+
const flowTags = flow$1.tags;
|
|
1269
|
+
if (flowTags && flowTags.length > 0) {
|
|
1270
|
+
for (let i = 0; i < flowTags.length; i++) if (!childCtx.data.has(flowTags[i].key)) childCtx.data.set(flowTags[i].key, flowTags[i].value);
|
|
1271
|
+
}
|
|
1257
1272
|
try {
|
|
1258
1273
|
const result = presetValue !== void 0 && typeof presetValue === "function" ? await childCtx.execPresetFn(flow$1, presetValue) : await childCtx.execFlowInternal(flow$1);
|
|
1259
1274
|
await childCtx.close({ ok: true });
|
|
@@ -1288,18 +1303,18 @@ var ExecutionContextImpl = class ExecutionContextImpl {
|
|
|
1288
1303
|
async execFlowInternal(flow$1) {
|
|
1289
1304
|
const resolvedDeps = await this.scope.resolveDeps(flow$1.deps, this);
|
|
1290
1305
|
const factory = flow$1.factory;
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
else return factory(this);
|
|
1294
|
-
};
|
|
1306
|
+
if (this.scope.execExts.length === 0) return flow$1.deps ? factory(this, resolvedDeps) : factory(this);
|
|
1307
|
+
const doExec = async () => flow$1.deps ? factory(this, resolvedDeps) : factory(this);
|
|
1295
1308
|
return this.applyExecExtensions(flow$1, doExec);
|
|
1296
1309
|
}
|
|
1297
1310
|
async execFnInternal(options) {
|
|
1298
1311
|
const { fn, params } = options;
|
|
1312
|
+
if (this.scope.execExts.length === 0) return fn(this, ...params);
|
|
1299
1313
|
const doExec = () => Promise.resolve(fn(this, ...params));
|
|
1300
1314
|
return this.applyExecExtensions(fn, doExec);
|
|
1301
1315
|
}
|
|
1302
1316
|
async execPresetFn(flow$1, fn) {
|
|
1317
|
+
if (this.scope.execExts.length === 0) return fn(this);
|
|
1303
1318
|
const doExec = () => Promise.resolve(fn(this));
|
|
1304
1319
|
return this.applyExecExtensions(flow$1, doExec);
|
|
1305
1320
|
}
|
|
@@ -1315,9 +1330,13 @@ var ExecutionContextImpl = class ExecutionContextImpl {
|
|
|
1315
1330
|
onClose(fn) {
|
|
1316
1331
|
this.cleanups.push(fn);
|
|
1317
1332
|
}
|
|
1318
|
-
|
|
1319
|
-
if (this.closed) return;
|
|
1333
|
+
close(result = { ok: true }) {
|
|
1334
|
+
if (this.closed) return Promise.resolve();
|
|
1320
1335
|
this.closed = true;
|
|
1336
|
+
if (this.cleanups.length === 0) return Promise.resolve();
|
|
1337
|
+
return this.runCleanups(result);
|
|
1338
|
+
}
|
|
1339
|
+
async runCleanups(result) {
|
|
1321
1340
|
for (let i = this.cleanups.length - 1; i >= 0; i--) try {
|
|
1322
1341
|
await this.cleanups[i]?.(result);
|
|
1323
1342
|
} catch {}
|
package/dist/index.d.cts
CHANGED
|
@@ -238,6 +238,14 @@ declare namespace Lite {
|
|
|
238
238
|
readonly watch?: boolean;
|
|
239
239
|
readonly eq?: (a: any, b: any) => boolean;
|
|
240
240
|
}
|
|
241
|
+
type WatchControllerDep<T> = ControllerDep<T> & {
|
|
242
|
+
readonly resolve: true;
|
|
243
|
+
readonly watch: true;
|
|
244
|
+
};
|
|
245
|
+
type NonWatchControllerDep<T> = ControllerDep<T> & {
|
|
246
|
+
readonly watch?: never;
|
|
247
|
+
readonly eq?: never;
|
|
248
|
+
};
|
|
241
249
|
interface ControllerOptions {
|
|
242
250
|
resolve?: boolean;
|
|
243
251
|
}
|
|
@@ -301,6 +309,8 @@ declare namespace Lite {
|
|
|
301
309
|
dispose?(scope: Scope): MaybePromise<void>;
|
|
302
310
|
}
|
|
303
311
|
type Dependency = Atom<unknown> | ControllerDep<unknown> | TagExecutor<any> | Resource<unknown>;
|
|
312
|
+
type AtomDependency = Atom<unknown> | ControllerDep<unknown> | TagExecutor<any, any>;
|
|
313
|
+
type ExecutionDependency = Atom<unknown> | NonWatchControllerDep<unknown> | TagExecutor<any, any> | Resource<unknown, Record<string, Dependency>>;
|
|
304
314
|
type InferDep<D> = D extends Atom<infer T> ? T : D extends ControllerDep<infer T> ? Controller<T> : D extends TagExecutor<infer TOutput, infer _TTag> ? TOutput : D extends Resource<infer T> ? T : never;
|
|
305
315
|
type InferDeps<D> = { [K in keyof D]: InferDep<D[K]> };
|
|
306
316
|
type AtomFactory<T, D extends Record<string, Dependency>> = keyof D extends never ? (ctx: ResolveContext) => MaybePromise<T> : (ctx: ResolveContext, deps: InferDeps<D>) => MaybePromise<T>;
|
|
@@ -569,9 +579,7 @@ declare function atom<T>(config: {
|
|
|
569
579
|
tags?: Lite.Tagged<any>[];
|
|
570
580
|
keepAlive?: boolean;
|
|
571
581
|
}): Lite.Atom<T>;
|
|
572
|
-
declare function atom<T, const D extends Record<string, Lite.
|
|
573
|
-
mode: string;
|
|
574
|
-
}>>(config: {
|
|
582
|
+
declare function atom<T, const D extends Record<string, Lite.AtomDependency>>(config: {
|
|
575
583
|
deps: D;
|
|
576
584
|
factory: (ctx: Lite.ResolveContext, deps: Lite.InferDeps<D>) => MaybePromise<T>;
|
|
577
585
|
tags?: Lite.Tagged<any>[];
|
|
@@ -700,18 +708,14 @@ declare function flow<TOutput, TInput>(config: {
|
|
|
700
708
|
}) => MaybePromise<TOutput>;
|
|
701
709
|
tags?: Lite.Tagged<any>[];
|
|
702
710
|
}): Lite.Flow<TOutput, TInput>;
|
|
703
|
-
declare function flow<TOutput, const D extends Record<string, Lite.
|
|
704
|
-
mode: string;
|
|
705
|
-
}>>(config: {
|
|
711
|
+
declare function flow<TOutput, const D extends Record<string, Lite.ExecutionDependency>>(config: {
|
|
706
712
|
name?: string;
|
|
707
713
|
parse?: undefined;
|
|
708
714
|
deps: D;
|
|
709
715
|
factory: (ctx: Lite.ExecutionContext, deps: Lite.InferDeps<D>) => MaybePromise<TOutput>;
|
|
710
716
|
tags?: Lite.Tagged<any>[];
|
|
711
717
|
}): Lite.Flow<TOutput, void>;
|
|
712
|
-
declare function flow<TOutput, TInput, const D extends Record<string, Lite.
|
|
713
|
-
mode: string;
|
|
714
|
-
}>>(config: {
|
|
718
|
+
declare function flow<TOutput, TInput, const D extends Record<string, Lite.ExecutionDependency>>(config: {
|
|
715
719
|
name?: string;
|
|
716
720
|
parse: (raw: unknown) => MaybePromise<TInput>;
|
|
717
721
|
deps: D;
|
|
@@ -720,9 +724,7 @@ declare function flow<TOutput, TInput, const D extends Record<string, Lite.Atom<
|
|
|
720
724
|
}, deps: Lite.InferDeps<D>) => MaybePromise<TOutput>;
|
|
721
725
|
tags?: Lite.Tagged<any>[];
|
|
722
726
|
}): Lite.Flow<TOutput, TInput>;
|
|
723
|
-
declare function flow<TOutput, TInput, const D extends Record<string, Lite.
|
|
724
|
-
mode: string;
|
|
725
|
-
}>>(config: {
|
|
727
|
+
declare function flow<TOutput, TInput, const D extends Record<string, Lite.ExecutionDependency>>(config: {
|
|
726
728
|
name?: string;
|
|
727
729
|
parse: Lite.Typed<TInput>;
|
|
728
730
|
deps: D;
|
|
@@ -825,9 +827,7 @@ declare function resource<T>(config: {
|
|
|
825
827
|
deps?: undefined;
|
|
826
828
|
factory: (ctx: Lite.ExecutionContext) => MaybePromise<T>;
|
|
827
829
|
}): Lite.Resource<T>;
|
|
828
|
-
declare function resource<T, const D extends Record<string, Lite.
|
|
829
|
-
mode: string;
|
|
830
|
-
}>>(config: {
|
|
830
|
+
declare function resource<T, const D extends Record<string, Lite.ExecutionDependency>>(config: {
|
|
831
831
|
name?: string;
|
|
832
832
|
deps: D;
|
|
833
833
|
factory: (ctx: Lite.ExecutionContext, deps: Lite.InferDeps<D>) => MaybePromise<T>;
|