@darajs/core 1.29.6 → 1.29.8
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/dist/api/http.d.ts.map +1 -1
- package/dist/api/http.js +14 -0
- package/dist/api/http.js.map +1 -1
- package/dist/{dara_core-1.29.6-py3-none-any.whl → dara_core-1.29.8-py3-none-any.whl} +0 -0
- package/dist/router/fetching.d.ts.map +1 -1
- package/dist/router/fetching.js +57 -32
- package/dist/router/fetching.js.map +1 -1
- package/dist/shared/context/variable-context.d.ts +5 -0
- package/dist/shared/context/variable-context.d.ts.map +1 -1
- package/dist/shared/context/variable-context.js.map +1 -1
- package/dist/shared/dynamic-component/dynamic-component.d.ts.map +1 -1
- package/dist/shared/dynamic-component/dynamic-component.js +10 -5
- package/dist/shared/dynamic-component/dynamic-component.js.map +1 -1
- package/dist/shared/interactivity/derived-variable.d.ts +14 -8
- package/dist/shared/interactivity/derived-variable.d.ts.map +1 -1
- package/dist/shared/interactivity/derived-variable.js +175 -126
- package/dist/shared/interactivity/derived-variable.js.map +1 -1
- package/dist/shared/interactivity/polling.d.ts +116 -0
- package/dist/shared/interactivity/polling.d.ts.map +1 -0
- package/dist/shared/interactivity/polling.js +723 -0
- package/dist/shared/interactivity/polling.js.map +1 -0
- package/dist/shared/interactivity/store.d.ts +6 -0
- package/dist/shared/interactivity/store.d.ts.map +1 -1
- package/dist/shared/interactivity/store.js +21 -1
- package/dist/shared/interactivity/store.js.map +1 -1
- package/dist/shared/interactivity/stream-variable.d.ts +1 -1
- package/dist/shared/interactivity/stream-variable.d.ts.map +1 -1
- package/dist/shared/interactivity/stream-variable.js +106 -41
- package/dist/shared/interactivity/stream-variable.js.map +1 -1
- package/dist/shared/interactivity/use-server-component.d.ts +9 -0
- package/dist/shared/interactivity/use-server-component.d.ts.map +1 -1
- package/dist/shared/interactivity/use-server-component.js +130 -77
- package/dist/shared/interactivity/use-server-component.js.map +1 -1
- package/dist/shared/interactivity/use-variable.d.ts.map +1 -1
- package/dist/shared/interactivity/use-variable.js +2 -2
- package/dist/shared/interactivity/use-variable.js.map +1 -1
- package/dist/umd/dara.core.umd.cjs +1064 -387
- package/package.json +9 -9
|
@@ -2992,7 +2992,7 @@
|
|
|
2992
2992
|
var { applyAtomValueWrites: applyAtomValueWrites$1 } = Recoil_RecoilValueInterface;
|
|
2993
2993
|
var { releaseScheduledRetainablesNow: releaseScheduledRetainablesNow$1 } = Recoil_Retention;
|
|
2994
2994
|
var { freshSnapshot: freshSnapshot$1 } = Recoil_Snapshot$1;
|
|
2995
|
-
var { useCallback: useCallback$27, useContext: useContext$16, useEffect: useEffect$
|
|
2995
|
+
var { useCallback: useCallback$27, useContext: useContext$16, useEffect: useEffect$55, useMemo: useMemo$32, useRef: useRef$1$2, useState: useState$48 } = react.default;
|
|
2996
2996
|
function notInAContext() {
|
|
2997
2997
|
throw Recoil_err$2("This component must be used inside a <RecoilRoot> component.");
|
|
2998
2998
|
}
|
|
@@ -3079,13 +3079,13 @@
|
|
|
3079
3079
|
const storeRef = useStoreRef();
|
|
3080
3080
|
const [, setState] = useState$48([]);
|
|
3081
3081
|
setNotifyBatcherOfChange(() => setState({}));
|
|
3082
|
-
useEffect$
|
|
3082
|
+
useEffect$55(() => {
|
|
3083
3083
|
setNotifyBatcherOfChange(() => setState({}));
|
|
3084
3084
|
return () => {
|
|
3085
3085
|
setNotifyBatcherOfChange(() => {});
|
|
3086
3086
|
};
|
|
3087
3087
|
}, [setNotifyBatcherOfChange]);
|
|
3088
|
-
useEffect$
|
|
3088
|
+
useEffect$55(() => {
|
|
3089
3089
|
Recoil_Queue.enqueueExecution("Batcher", () => {
|
|
3090
3090
|
endBatch(storeRef.current);
|
|
3091
3091
|
});
|
|
@@ -3190,7 +3190,7 @@
|
|
|
3190
3190
|
if (storeProp != null) storeRef.current = storeProp;
|
|
3191
3191
|
storeStateRef = Recoil_useRefInitOnce(() => initializeState_DEPRECATED != null ? initialStoreState_DEPRECATED(storeRef.current, initializeState_DEPRECATED) : initializeState != null ? initialStoreState(initializeState) : makeEmptyStoreState$2());
|
|
3192
3192
|
const mutableSource = useMemo$32(() => createMutableSource$1 === null || createMutableSource$1 === void 0 ? void 0 : createMutableSource$1(storeStateRef, () => storeStateRef.current.currentTree.version), [storeStateRef]);
|
|
3193
|
-
useEffect$
|
|
3193
|
+
useEffect$55(() => {
|
|
3194
3194
|
const store = storeRef.current;
|
|
3195
3195
|
for (const atomKey of new Set(store.getState().knownAtoms)) initializeNode$2(store, atomKey, "get");
|
|
3196
3196
|
return () => {
|
|
@@ -11932,48 +11932,6 @@
|
|
|
11932
11932
|
return isFunction(resultSelector) ? mergeMap(project, resultSelector, 1) : mergeMap(project, 1);
|
|
11933
11933
|
}
|
|
11934
11934
|
//#endregion
|
|
11935
|
-
//#region ../../node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/dist/esm5/internal/operators/debounceTime.js
|
|
11936
|
-
function debounceTime(dueTime, scheduler) {
|
|
11937
|
-
if (scheduler === void 0) scheduler = asyncScheduler;
|
|
11938
|
-
return operate(function(source, subscriber) {
|
|
11939
|
-
var activeTask = null;
|
|
11940
|
-
var lastValue = null;
|
|
11941
|
-
var lastTime = null;
|
|
11942
|
-
var emit = function() {
|
|
11943
|
-
if (activeTask) {
|
|
11944
|
-
activeTask.unsubscribe();
|
|
11945
|
-
activeTask = null;
|
|
11946
|
-
var value = lastValue;
|
|
11947
|
-
lastValue = null;
|
|
11948
|
-
subscriber.next(value);
|
|
11949
|
-
}
|
|
11950
|
-
};
|
|
11951
|
-
function emitWhenIdle() {
|
|
11952
|
-
var targetTime = lastTime + dueTime;
|
|
11953
|
-
var now = scheduler.now();
|
|
11954
|
-
if (now < targetTime) {
|
|
11955
|
-
activeTask = this.schedule(void 0, targetTime - now);
|
|
11956
|
-
subscriber.add(activeTask);
|
|
11957
|
-
return;
|
|
11958
|
-
}
|
|
11959
|
-
emit();
|
|
11960
|
-
}
|
|
11961
|
-
source.subscribe(createOperatorSubscriber(subscriber, function(value) {
|
|
11962
|
-
lastValue = value;
|
|
11963
|
-
lastTime = scheduler.now();
|
|
11964
|
-
if (!activeTask) {
|
|
11965
|
-
activeTask = scheduler.schedule(emitWhenIdle, dueTime);
|
|
11966
|
-
subscriber.add(activeTask);
|
|
11967
|
-
}
|
|
11968
|
-
}, function() {
|
|
11969
|
-
emit();
|
|
11970
|
-
subscriber.complete();
|
|
11971
|
-
}, void 0, function() {
|
|
11972
|
-
lastValue = activeTask = null;
|
|
11973
|
-
}));
|
|
11974
|
-
});
|
|
11975
|
-
}
|
|
11976
|
-
//#endregion
|
|
11977
11935
|
//#region ../../node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/dist/esm5/internal/operators/take.js
|
|
11978
11936
|
function take(count) {
|
|
11979
11937
|
return count <= 0 ? function() {
|
|
@@ -12022,106 +11980,6 @@
|
|
|
12022
11980
|
});
|
|
12023
11981
|
}
|
|
12024
11982
|
//#endregion
|
|
12025
|
-
//#region ../../node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/dist/esm5/internal/operators/share.js
|
|
12026
|
-
function share(options) {
|
|
12027
|
-
if (options === void 0) options = {};
|
|
12028
|
-
var _a = options.connector, connector = _a === void 0 ? function() {
|
|
12029
|
-
return new Subject();
|
|
12030
|
-
} : _a, _b = options.resetOnError, resetOnError = _b === void 0 ? true : _b, _c = options.resetOnComplete, resetOnComplete = _c === void 0 ? true : _c, _d = options.resetOnRefCountZero, resetOnRefCountZero = _d === void 0 ? true : _d;
|
|
12031
|
-
return function(wrapperSource) {
|
|
12032
|
-
var connection;
|
|
12033
|
-
var resetConnection;
|
|
12034
|
-
var subject;
|
|
12035
|
-
var refCount = 0;
|
|
12036
|
-
var hasCompleted = false;
|
|
12037
|
-
var hasErrored = false;
|
|
12038
|
-
var cancelReset = function() {
|
|
12039
|
-
resetConnection === null || resetConnection === void 0 || resetConnection.unsubscribe();
|
|
12040
|
-
resetConnection = void 0;
|
|
12041
|
-
};
|
|
12042
|
-
var reset = function() {
|
|
12043
|
-
cancelReset();
|
|
12044
|
-
connection = subject = void 0;
|
|
12045
|
-
hasCompleted = hasErrored = false;
|
|
12046
|
-
};
|
|
12047
|
-
var resetAndUnsubscribe = function() {
|
|
12048
|
-
var conn = connection;
|
|
12049
|
-
reset();
|
|
12050
|
-
conn === null || conn === void 0 || conn.unsubscribe();
|
|
12051
|
-
};
|
|
12052
|
-
return operate(function(source, subscriber) {
|
|
12053
|
-
refCount++;
|
|
12054
|
-
if (!hasErrored && !hasCompleted) cancelReset();
|
|
12055
|
-
var dest = subject = subject !== null && subject !== void 0 ? subject : connector();
|
|
12056
|
-
subscriber.add(function() {
|
|
12057
|
-
refCount--;
|
|
12058
|
-
if (refCount === 0 && !hasErrored && !hasCompleted) resetConnection = handleReset(resetAndUnsubscribe, resetOnRefCountZero);
|
|
12059
|
-
});
|
|
12060
|
-
dest.subscribe(subscriber);
|
|
12061
|
-
if (!connection && refCount > 0) {
|
|
12062
|
-
connection = new SafeSubscriber({
|
|
12063
|
-
next: function(value) {
|
|
12064
|
-
return dest.next(value);
|
|
12065
|
-
},
|
|
12066
|
-
error: function(err) {
|
|
12067
|
-
hasErrored = true;
|
|
12068
|
-
cancelReset();
|
|
12069
|
-
resetConnection = handleReset(reset, resetOnError, err);
|
|
12070
|
-
dest.error(err);
|
|
12071
|
-
},
|
|
12072
|
-
complete: function() {
|
|
12073
|
-
hasCompleted = true;
|
|
12074
|
-
cancelReset();
|
|
12075
|
-
resetConnection = handleReset(reset, resetOnComplete);
|
|
12076
|
-
dest.complete();
|
|
12077
|
-
}
|
|
12078
|
-
});
|
|
12079
|
-
innerFrom(source).subscribe(connection);
|
|
12080
|
-
}
|
|
12081
|
-
})(wrapperSource);
|
|
12082
|
-
};
|
|
12083
|
-
}
|
|
12084
|
-
function handleReset(reset, on) {
|
|
12085
|
-
var args = [];
|
|
12086
|
-
for (var _i = 2; _i < arguments.length; _i++) args[_i - 2] = arguments[_i];
|
|
12087
|
-
if (on === true) {
|
|
12088
|
-
reset();
|
|
12089
|
-
return;
|
|
12090
|
-
}
|
|
12091
|
-
if (on === false) return;
|
|
12092
|
-
var onSubscriber = new SafeSubscriber({ next: function() {
|
|
12093
|
-
onSubscriber.unsubscribe();
|
|
12094
|
-
reset();
|
|
12095
|
-
} });
|
|
12096
|
-
return innerFrom(on.apply(void 0, __spreadArray([], __read(args)))).subscribe(onSubscriber);
|
|
12097
|
-
}
|
|
12098
|
-
//#endregion
|
|
12099
|
-
//#region ../../node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/dist/esm5/internal/operators/switchMap.js
|
|
12100
|
-
function switchMap(project, resultSelector) {
|
|
12101
|
-
return operate(function(source, subscriber) {
|
|
12102
|
-
var innerSubscriber = null;
|
|
12103
|
-
var index = 0;
|
|
12104
|
-
var isComplete = false;
|
|
12105
|
-
var checkComplete = function() {
|
|
12106
|
-
return isComplete && !innerSubscriber && subscriber.complete();
|
|
12107
|
-
};
|
|
12108
|
-
source.subscribe(createOperatorSubscriber(subscriber, function(value) {
|
|
12109
|
-
innerSubscriber === null || innerSubscriber === void 0 || innerSubscriber.unsubscribe();
|
|
12110
|
-
var innerIndex = 0;
|
|
12111
|
-
var outerIndex = index++;
|
|
12112
|
-
innerFrom(project(value, outerIndex)).subscribe(innerSubscriber = createOperatorSubscriber(subscriber, function(innerValue) {
|
|
12113
|
-
return subscriber.next(resultSelector ? resultSelector(value, innerValue, outerIndex, innerIndex++) : innerValue);
|
|
12114
|
-
}, function() {
|
|
12115
|
-
innerSubscriber = null;
|
|
12116
|
-
checkComplete();
|
|
12117
|
-
}));
|
|
12118
|
-
}, function() {
|
|
12119
|
-
isComplete = true;
|
|
12120
|
-
checkComplete();
|
|
12121
|
-
}));
|
|
12122
|
-
});
|
|
12123
|
-
}
|
|
12124
|
-
//#endregion
|
|
12125
11983
|
//#region ../../node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/dist/esm5/internal/operators/takeWhile.js
|
|
12126
11984
|
function takeWhile(predicate, inclusive) {
|
|
12127
11985
|
if (inclusive === void 0) inclusive = false;
|
|
@@ -17646,14 +17504,14 @@
|
|
|
17646
17504
|
* earlier React versions.
|
|
17647
17505
|
* @see https://floating-ui.com/docs/react-utils#useid
|
|
17648
17506
|
*/
|
|
17649
|
-
var useId$
|
|
17507
|
+
var useId$2 = SafeReact.useId || useFloatingId;
|
|
17650
17508
|
/**
|
|
17651
17509
|
* Renders a pointing arrow triangle.
|
|
17652
17510
|
* @see https://floating-ui.com/docs/FloatingArrow
|
|
17653
17511
|
*/
|
|
17654
17512
|
var FloatingArrow = /*#__PURE__*/ react$3.forwardRef(function FloatingArrow(props, ref) {
|
|
17655
17513
|
const { context: { placement, elements: { floating }, middlewareData: { arrow, shift } }, width = 14, height = 7, tipRadius = 0, strokeWidth = 0, staticOffset, stroke, d, style: { transform, ...restStyle } = {}, ...rest } = props;
|
|
17656
|
-
const clipPathId = useId$
|
|
17514
|
+
const clipPathId = useId$2();
|
|
17657
17515
|
const [isRTL, setIsRTL] = react$3.useState(false);
|
|
17658
17516
|
index(() => {
|
|
17659
17517
|
if (!floating) return;
|
|
@@ -18142,7 +18000,7 @@
|
|
|
18142
18000
|
function useFloatingPortalNode(props) {
|
|
18143
18001
|
if (props === void 0) props = {};
|
|
18144
18002
|
const { id, root } = props;
|
|
18145
|
-
const uniqueId = useId$
|
|
18003
|
+
const uniqueId = useId$2();
|
|
18146
18004
|
const portalContext = usePortalContext();
|
|
18147
18005
|
const [portalNode, setPortalNode] = react$3.useState(null);
|
|
18148
18006
|
const portalNodeRef = react$3.useRef(null);
|
|
@@ -18571,7 +18429,7 @@
|
|
|
18571
18429
|
}
|
|
18572
18430
|
function useFloatingRootContext(options) {
|
|
18573
18431
|
const { open = false, onOpenChange: onOpenChangeProp, elements: elementsProp } = options;
|
|
18574
|
-
const floatingId = useId$
|
|
18432
|
+
const floatingId = useId$2();
|
|
18575
18433
|
const dataRef = react$3.useRef({});
|
|
18576
18434
|
const [events] = react$3.useState(() => createPubSub());
|
|
18577
18435
|
const nested = useFloatingParentNodeId() != null;
|
|
@@ -18874,7 +18732,7 @@
|
|
|
18874
18732
|
const { open, floatingId } = context;
|
|
18875
18733
|
const { enabled = true, role = "dialog" } = props;
|
|
18876
18734
|
const ariaRole = (_componentRoleToAriaR = componentRoleToAriaRoleMap.get(role)) != null ? _componentRoleToAriaR : role;
|
|
18877
|
-
const referenceId = useId$
|
|
18735
|
+
const referenceId = useId$2();
|
|
18878
18736
|
const isNested = useFloatingParentNodeId() != null;
|
|
18879
18737
|
const reference = react$3.useMemo(() => {
|
|
18880
18738
|
if (ariaRole === "tooltip" || role === "label") return { ["aria-" + (role === "label" ? "labelledby" : "describedby")]: open ? floatingId : void 0 };
|
|
@@ -51835,6 +51693,17 @@
|
|
|
51835
51693
|
//#endregion
|
|
51836
51694
|
//#region js/api/http.tsx
|
|
51837
51695
|
var import_cloneDeep = /* @__PURE__ */ __toESM(require_cloneDeep(), 1);
|
|
51696
|
+
var signalIds = /* @__PURE__ */ new WeakMap();
|
|
51697
|
+
var nextSignalId = 1;
|
|
51698
|
+
function getSignalId(signal) {
|
|
51699
|
+
let id = signalIds.get(signal);
|
|
51700
|
+
if (id === void 0) {
|
|
51701
|
+
id = nextSignalId;
|
|
51702
|
+
nextSignalId += 1;
|
|
51703
|
+
signalIds.set(signal, id);
|
|
51704
|
+
}
|
|
51705
|
+
return id;
|
|
51706
|
+
}
|
|
51838
51707
|
/**
|
|
51839
51708
|
* Serializable form of RequestExtras.
|
|
51840
51709
|
* Required to use for e.g. recoil params as they need to be serializable.
|
|
@@ -51863,6 +51732,10 @@
|
|
|
51863
51732
|
toJSON() {
|
|
51864
51733
|
const serializable = this.toSerializable();
|
|
51865
51734
|
if (!serializable) return null;
|
|
51735
|
+
if (this.extras.signal) return JSON.stringify({
|
|
51736
|
+
...serializable,
|
|
51737
|
+
signal: getSignalId(this.extras.signal)
|
|
51738
|
+
});
|
|
51866
51739
|
return JSON.stringify(serializable);
|
|
51867
51740
|
}
|
|
51868
51741
|
};
|
|
@@ -69856,11 +69729,611 @@
|
|
|
69856
69729
|
return identifier;
|
|
69857
69730
|
}
|
|
69858
69731
|
//#endregion
|
|
69732
|
+
//#region js/shared/interactivity/polling.tsx
|
|
69733
|
+
var DEFAULT_JITTER_RATIO = .1;
|
|
69734
|
+
var MAX_BACKOFF_MS = 6e4;
|
|
69735
|
+
var POLL_FORCE_KEY_PREFIX = "__dara_poll__:";
|
|
69736
|
+
var retryAfterByError = /* @__PURE__ */ new WeakMap();
|
|
69737
|
+
/** Throw an AbortError when an old run attempts to publish a result. */
|
|
69738
|
+
function assertCurrentRun(handle) {
|
|
69739
|
+
if (!handle.isCurrent() || handle.signal.aborted) throw new DOMException("The request was superseded", "AbortError");
|
|
69740
|
+
}
|
|
69741
|
+
/** Check whether an error represents intentional request cancellation. */
|
|
69742
|
+
function isAbortError(error) {
|
|
69743
|
+
return error instanceof DOMException && error.name === "AbortError" || typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
69744
|
+
}
|
|
69745
|
+
/** Read Retry-After saved at the HTTP response seam. */
|
|
69746
|
+
function getRetryAfterMs(error) {
|
|
69747
|
+
return typeof error === "object" && error !== null ? retryAfterByError.get(error) : void 0;
|
|
69748
|
+
}
|
|
69749
|
+
/**
|
|
69750
|
+
* Coordinates non-overlapping, fixed-delay polling for request identities.
|
|
69751
|
+
*
|
|
69752
|
+
* A request identity includes the rendered variable/component identity and its
|
|
69753
|
+
* serialized request extras. Multiple React consumers of the same identity
|
|
69754
|
+
* share one timer and one active request generation.
|
|
69755
|
+
*/
|
|
69756
|
+
var Poller = class {
|
|
69757
|
+
#clearTimeout;
|
|
69758
|
+
#entries = /* @__PURE__ */ new Map();
|
|
69759
|
+
#getVisibilityState;
|
|
69760
|
+
#jitterRatio;
|
|
69761
|
+
#now;
|
|
69762
|
+
#random;
|
|
69763
|
+
#setTimeout;
|
|
69764
|
+
#visibilityTarget;
|
|
69765
|
+
#owners = /* @__PURE__ */ new Map();
|
|
69766
|
+
#listeningForVisibility = false;
|
|
69767
|
+
constructor(options = {}) {
|
|
69768
|
+
this.#clearTimeout = options.clearTimeout ?? ((timer) => clearTimeout(timer));
|
|
69769
|
+
this.#getVisibilityState = options.getVisibilityState ?? (() => typeof document === "undefined" ? "visible" : document.visibilityState);
|
|
69770
|
+
this.#jitterRatio = options.jitterRatio ?? DEFAULT_JITTER_RATIO;
|
|
69771
|
+
this.#now = options.now ?? (() => Date.now());
|
|
69772
|
+
this.#random = options.random ?? (() => Math.random());
|
|
69773
|
+
this.#setTimeout = options.setTimeout ?? ((callback, delay) => setTimeout(callback, delay));
|
|
69774
|
+
this.#visibilityTarget = options.visibilityTarget ?? (typeof document === "undefined" ? void 0 : document);
|
|
69775
|
+
}
|
|
69776
|
+
/**
|
|
69777
|
+
* Register one rendered polling consumer.
|
|
69778
|
+
*
|
|
69779
|
+
* The returned cleanup releases the consumer. The final cleanup aborts the
|
|
69780
|
+
* owned request on the next macrotask so React StrictMode can immediately
|
|
69781
|
+
* reacquire the same identity without cancelling useful work.
|
|
69782
|
+
*/
|
|
69783
|
+
subscribe(key, intervalSeconds, refresh) {
|
|
69784
|
+
const intervalMs = (intervalSeconds ?? 0) * 1e3;
|
|
69785
|
+
if (!Number.isFinite(intervalMs) || !(intervalMs > 0)) return () => {};
|
|
69786
|
+
const entry = this.#getOrCreateEntry(key);
|
|
69787
|
+
const oldIntervalMs = entry.subscribers.size > 0 ? this.#getIntervalMs(entry) : void 0;
|
|
69788
|
+
if (entry.disposeTimer !== void 0) {
|
|
69789
|
+
this.#clearTimeout(entry.disposeTimer);
|
|
69790
|
+
entry.disposeTimer = void 0;
|
|
69791
|
+
}
|
|
69792
|
+
const subscriberId = Symbol(key);
|
|
69793
|
+
entry.subscribers.set(subscriberId, {
|
|
69794
|
+
intervalMs,
|
|
69795
|
+
refresh
|
|
69796
|
+
});
|
|
69797
|
+
this.#startVisibilityListener();
|
|
69798
|
+
if (entry.subscribers.size === 1 && entry.state.kind === "idle" && entry.timer === void 0) this.#schedulePoll(key, entry);
|
|
69799
|
+
else if (entry.timer !== void 0 && entry.failureCount === 0 && oldIntervalMs !== void 0 && intervalMs < oldIntervalMs) {
|
|
69800
|
+
const remaining = Math.max(0, (entry.nextRunAt ?? this.#now()) - this.#now());
|
|
69801
|
+
this.#schedule(key, entry, Math.min(remaining, this.#withJitter(intervalMs)));
|
|
69802
|
+
}
|
|
69803
|
+
return () => {
|
|
69804
|
+
const removedIntervalMs = this.#getIntervalMs(entry);
|
|
69805
|
+
entry.subscribers.delete(subscriberId);
|
|
69806
|
+
if (entry.subscribers.size > 0) {
|
|
69807
|
+
if (entry.timer !== void 0 && entry.failureCount === 0 && this.#getIntervalMs(entry) > removedIntervalMs) this.#schedulePoll(key, entry);
|
|
69808
|
+
return;
|
|
69809
|
+
}
|
|
69810
|
+
this.#clearTimer(entry);
|
|
69811
|
+
entry.disposeTimer = this.#setTimeout(() => {
|
|
69812
|
+
entry.disposeTimer = void 0;
|
|
69813
|
+
if (entry.subscribers.size > 0) return;
|
|
69814
|
+
if (entry.owners.size > 0) return;
|
|
69815
|
+
if (this.#entries.get(key) !== entry) return;
|
|
69816
|
+
if (entry.state.kind === "running") {
|
|
69817
|
+
entry.state.run.controller.abort();
|
|
69818
|
+
entry.state.run.detachExternalSignal?.();
|
|
69819
|
+
entry.state.run.end();
|
|
69820
|
+
}
|
|
69821
|
+
this.#entries.delete(key);
|
|
69822
|
+
this.#stopVisibilityListenerIfIdle();
|
|
69823
|
+
}, 0);
|
|
69824
|
+
};
|
|
69825
|
+
}
|
|
69826
|
+
/**
|
|
69827
|
+
* Claim a key during render so Suspense cannot skip its ownership effect.
|
|
69828
|
+
*
|
|
69829
|
+
* A later owner commit prunes claims left by an abandoned render.
|
|
69830
|
+
*/
|
|
69831
|
+
claimKey(ownerId, hookId, key) {
|
|
69832
|
+
const owner = this.#getOrCreateOwner(ownerId);
|
|
69833
|
+
if (owner.hooks.get(hookId) === key) return;
|
|
69834
|
+
const oldKey = owner.claims.get(hookId);
|
|
69835
|
+
owner.claims.set(hookId, key);
|
|
69836
|
+
this.#getOrCreateEntry(key).owners.add(ownerId);
|
|
69837
|
+
if (oldKey !== void 0 && oldKey !== key && !this.#ownerHasKey(owner, oldKey)) this.#dropOwnedKey(ownerId, oldKey);
|
|
69838
|
+
}
|
|
69839
|
+
/** Apply the hook claims collected by one committed owner render. */
|
|
69840
|
+
commitOwner(ownerId, claims) {
|
|
69841
|
+
const owner = this.#getOrCreateOwner(ownerId);
|
|
69842
|
+
if (owner.disposeTimer !== void 0) {
|
|
69843
|
+
this.#clearTimeout(owner.disposeTimer);
|
|
69844
|
+
owner.disposeTimer = void 0;
|
|
69845
|
+
}
|
|
69846
|
+
const droppedClaims = /* @__PURE__ */ new Set();
|
|
69847
|
+
for (const [hookId, key] of owner.claims) if (claims.get(hookId) !== key) {
|
|
69848
|
+
owner.claims.delete(hookId);
|
|
69849
|
+
droppedClaims.add(key);
|
|
69850
|
+
}
|
|
69851
|
+
const nextRenderKeys = /* @__PURE__ */ new Set();
|
|
69852
|
+
for (const key of new Set(claims.values())) {
|
|
69853
|
+
this.#getOrCreateEntry(key).owners.add(ownerId);
|
|
69854
|
+
if (!this.#hasHookForKey(owner, key) && !this.#hasClaimForKey(owner, key)) nextRenderKeys.add(key);
|
|
69855
|
+
}
|
|
69856
|
+
const oldRenderKeys = owner.renderKeys;
|
|
69857
|
+
owner.renderKeys = nextRenderKeys;
|
|
69858
|
+
for (const key of oldRenderKeys) if (!nextRenderKeys.has(key) && !this.#hasHookForKey(owner, key)) this.#dropOwnedKey(ownerId, key);
|
|
69859
|
+
for (const key of droppedClaims) if (!this.#ownerHasKey(owner, key)) this.#dropOwnedKey(ownerId, key);
|
|
69860
|
+
}
|
|
69861
|
+
/** Keep one key after its hook commits. */
|
|
69862
|
+
mountKey(ownerId, hookId, key) {
|
|
69863
|
+
const owner = this.#getOrCreateOwner(ownerId);
|
|
69864
|
+
if (owner.disposeTimer !== void 0) {
|
|
69865
|
+
this.#clearTimeout(owner.disposeTimer);
|
|
69866
|
+
owner.disposeTimer = void 0;
|
|
69867
|
+
}
|
|
69868
|
+
const timer = owner.timers.get(hookId);
|
|
69869
|
+
if (timer !== void 0) {
|
|
69870
|
+
this.#clearTimeout(timer);
|
|
69871
|
+
owner.timers.delete(hookId);
|
|
69872
|
+
}
|
|
69873
|
+
const oldKey = owner.hooks.get(hookId);
|
|
69874
|
+
owner.hooks.set(hookId, key);
|
|
69875
|
+
owner.claims.delete(hookId);
|
|
69876
|
+
owner.renderKeys.delete(key);
|
|
69877
|
+
this.#getOrCreateEntry(key).owners.add(ownerId);
|
|
69878
|
+
if (oldKey !== void 0 && oldKey !== key && !this.#ownerHasKey(owner, oldKey)) this.#dropOwnedKey(ownerId, oldKey);
|
|
69879
|
+
}
|
|
69880
|
+
/** Drop a committed hook key after the StrictMode remount window. */
|
|
69881
|
+
unmountKey(ownerId, hookId, key) {
|
|
69882
|
+
const owner = this.#owners.get(ownerId);
|
|
69883
|
+
if (!owner || owner.timers.has(hookId)) return;
|
|
69884
|
+
const timer = this.#setTimeout(() => {
|
|
69885
|
+
owner.timers.delete(hookId);
|
|
69886
|
+
if (owner.hooks.get(hookId) !== key) return;
|
|
69887
|
+
owner.hooks.delete(hookId);
|
|
69888
|
+
if (!this.#ownerHasKey(owner, key)) this.#dropOwnedKey(ownerId, key);
|
|
69889
|
+
this.#stopVisibilityListenerIfIdle();
|
|
69890
|
+
}, 0);
|
|
69891
|
+
owner.timers.set(hookId, timer);
|
|
69892
|
+
}
|
|
69893
|
+
/** Release a rendered owner after the StrictMode remount window. */
|
|
69894
|
+
releaseOwner(ownerId) {
|
|
69895
|
+
const owner = this.#owners.get(ownerId);
|
|
69896
|
+
if (!owner || owner.disposeTimer !== void 0) return;
|
|
69897
|
+
owner.disposeTimer = this.#setTimeout(() => this.#dropOwner(ownerId, owner), 0);
|
|
69898
|
+
}
|
|
69899
|
+
/**
|
|
69900
|
+
* Run one request for a polling identity.
|
|
69901
|
+
*
|
|
69902
|
+
* Matching callers share one promise. Dependency runs replace older work,
|
|
69903
|
+
* while a poll that arrives during a run leaves one follow-up refresh.
|
|
69904
|
+
*/
|
|
69905
|
+
run({ cause, inputKey, key, read, signal, work, write }) {
|
|
69906
|
+
const entry = this.#entries.get(key);
|
|
69907
|
+
const running = entry?.state.kind === "running" ? entry.state.run : void 0;
|
|
69908
|
+
if (running?.cause === cause && running.inputKey === inputKey && running.result) return running.result;
|
|
69909
|
+
const handle = this.#start(key, cause, signal, inputKey);
|
|
69910
|
+
const result = this.#runWork({
|
|
69911
|
+
cause,
|
|
69912
|
+
handle,
|
|
69913
|
+
read,
|
|
69914
|
+
work,
|
|
69915
|
+
write
|
|
69916
|
+
});
|
|
69917
|
+
const state = this.#entries.get(key)?.state;
|
|
69918
|
+
if (state?.kind === "running" && handle.isCurrent()) state.run.result = result;
|
|
69919
|
+
return result;
|
|
69920
|
+
}
|
|
69921
|
+
#start(key, cause, externalSignal, inputKey) {
|
|
69922
|
+
const entry = this.#getOrCreateEntry(key);
|
|
69923
|
+
if (entry.state.kind === "running") {
|
|
69924
|
+
const running = entry.state.run;
|
|
69925
|
+
if (cause === "poll") {
|
|
69926
|
+
entry.runAgain = true;
|
|
69927
|
+
const abortedController = new AbortController();
|
|
69928
|
+
abortedController.abort();
|
|
69929
|
+
return {
|
|
69930
|
+
signal: abortedController.signal,
|
|
69931
|
+
finish: () => {},
|
|
69932
|
+
isCurrent: () => false,
|
|
69933
|
+
waitForNewer: () => this.#waitForNewer(key, entry.generation)
|
|
69934
|
+
};
|
|
69935
|
+
}
|
|
69936
|
+
running.controller.abort();
|
|
69937
|
+
running.detachExternalSignal?.();
|
|
69938
|
+
running.end();
|
|
69939
|
+
}
|
|
69940
|
+
this.#clearTimer(entry);
|
|
69941
|
+
const generation = ++entry.generation;
|
|
69942
|
+
const controller = new AbortController();
|
|
69943
|
+
let end = () => {};
|
|
69944
|
+
const activeRun = {
|
|
69945
|
+
cause,
|
|
69946
|
+
controller,
|
|
69947
|
+
done: new Promise((resolve) => {
|
|
69948
|
+
end = resolve;
|
|
69949
|
+
}),
|
|
69950
|
+
end,
|
|
69951
|
+
generation,
|
|
69952
|
+
inputKey
|
|
69953
|
+
};
|
|
69954
|
+
entry.state = {
|
|
69955
|
+
kind: "running",
|
|
69956
|
+
run: activeRun
|
|
69957
|
+
};
|
|
69958
|
+
if (externalSignal && typeof externalSignal.addEventListener === "function") if (externalSignal.aborted) controller.abort(externalSignal.reason);
|
|
69959
|
+
else {
|
|
69960
|
+
const abortFromExternalSignal = () => controller.abort(externalSignal.reason);
|
|
69961
|
+
externalSignal.addEventListener("abort", abortFromExternalSignal, { once: true });
|
|
69962
|
+
activeRun.detachExternalSignal = () => externalSignal.removeEventListener("abort", abortFromExternalSignal);
|
|
69963
|
+
}
|
|
69964
|
+
return this.#createRunHandle(key, activeRun);
|
|
69965
|
+
}
|
|
69966
|
+
#createRunHandle(key, activeRun) {
|
|
69967
|
+
let finished = false;
|
|
69968
|
+
return {
|
|
69969
|
+
signal: activeRun.controller.signal,
|
|
69970
|
+
finish: (outcome) => {
|
|
69971
|
+
if (finished) return;
|
|
69972
|
+
finished = true;
|
|
69973
|
+
this.#finishRun(key, activeRun.generation, outcome);
|
|
69974
|
+
},
|
|
69975
|
+
isCurrent: () => {
|
|
69976
|
+
const state = this.#entries.get(key)?.state;
|
|
69977
|
+
return state?.kind === "running" && state.run.generation === activeRun.generation;
|
|
69978
|
+
},
|
|
69979
|
+
waitForNewer: () => this.#waitForNewer(key, activeRun.generation)
|
|
69980
|
+
};
|
|
69981
|
+
}
|
|
69982
|
+
async #runWork({ cause, handle, read, work, write }) {
|
|
69983
|
+
let outcome = { status: "success" };
|
|
69984
|
+
try {
|
|
69985
|
+
assertCurrentRun(handle);
|
|
69986
|
+
const value = await work(handle.signal);
|
|
69987
|
+
assertCurrentRun(handle);
|
|
69988
|
+
write(value);
|
|
69989
|
+
return value;
|
|
69990
|
+
} catch (error) {
|
|
69991
|
+
outcome = isAbortError(error) ? { status: "aborted" } : {
|
|
69992
|
+
status: "error",
|
|
69993
|
+
retryAfterMs: getRetryAfterMs(error)
|
|
69994
|
+
};
|
|
69995
|
+
const previous = read?.();
|
|
69996
|
+
if (isAbortError(error) && previous?.found) {
|
|
69997
|
+
await handle.waitForNewer();
|
|
69998
|
+
const latest = read?.();
|
|
69999
|
+
return latest?.found ? latest.value : previous.value;
|
|
70000
|
+
}
|
|
70001
|
+
if (cause === "poll" && previous?.found) return previous.value;
|
|
70002
|
+
throw error;
|
|
70003
|
+
} finally {
|
|
70004
|
+
handle.finish(outcome);
|
|
70005
|
+
}
|
|
70006
|
+
}
|
|
70007
|
+
/** Refresh now, or keep one refresh while busy. */
|
|
70008
|
+
runNow(key) {
|
|
70009
|
+
const entry = this.#entries.get(key);
|
|
70010
|
+
if (!entry || entry.subscribers.size === 0) return;
|
|
70011
|
+
if (this.#getVisibilityState() === "hidden") {
|
|
70012
|
+
entry.runOnShow = true;
|
|
70013
|
+
return;
|
|
70014
|
+
}
|
|
70015
|
+
if (entry.state.kind !== "idle") {
|
|
70016
|
+
entry.runAgain = true;
|
|
70017
|
+
return;
|
|
70018
|
+
}
|
|
70019
|
+
this.#clearTimer(entry);
|
|
70020
|
+
entry.state = { kind: "starting" };
|
|
70021
|
+
this.#getSubscriber(entry)?.refresh();
|
|
70022
|
+
}
|
|
70023
|
+
/** Abort and remove every polling identity. Intended for test isolation. */
|
|
70024
|
+
clear() {
|
|
70025
|
+
for (const entry of this.#entries.values()) {
|
|
70026
|
+
this.#clearTimer(entry);
|
|
70027
|
+
if (entry.disposeTimer !== void 0) this.#clearTimeout(entry.disposeTimer);
|
|
70028
|
+
if (entry.state.kind === "running") {
|
|
70029
|
+
entry.state.run.controller.abort();
|
|
70030
|
+
entry.state.run.detachExternalSignal?.();
|
|
70031
|
+
entry.state.run.end();
|
|
70032
|
+
}
|
|
70033
|
+
}
|
|
70034
|
+
for (const owner of this.#owners.values()) {
|
|
70035
|
+
if (owner.disposeTimer !== void 0) this.#clearTimeout(owner.disposeTimer);
|
|
70036
|
+
for (const timer of owner.timers.values()) this.#clearTimeout(timer);
|
|
70037
|
+
}
|
|
70038
|
+
this.#owners.clear();
|
|
70039
|
+
this.#entries.clear();
|
|
70040
|
+
this.#stopVisibilityListenerIfIdle();
|
|
70041
|
+
}
|
|
70042
|
+
/** Current time according to the injected clock. */
|
|
70043
|
+
now() {
|
|
70044
|
+
return this.#now();
|
|
70045
|
+
}
|
|
70046
|
+
#finishRun(key, generation, outcome) {
|
|
70047
|
+
const entry = this.#entries.get(key);
|
|
70048
|
+
if (!entry || entry.state.kind !== "running" || entry.state.run.generation !== generation) return;
|
|
70049
|
+
entry.state.run.detachExternalSignal?.();
|
|
70050
|
+
entry.state.run.end();
|
|
70051
|
+
entry.state = { kind: "idle" };
|
|
70052
|
+
if (entry.subscribers.size === 0) {
|
|
70053
|
+
if (entry.owners.size === 0) {
|
|
70054
|
+
this.#entries.delete(key);
|
|
70055
|
+
this.#stopVisibilityListenerIfIdle();
|
|
70056
|
+
}
|
|
70057
|
+
return;
|
|
70058
|
+
}
|
|
70059
|
+
if (outcome.status === "success") {
|
|
70060
|
+
entry.failureCount = 0;
|
|
70061
|
+
entry.nextRunAt = void 0;
|
|
70062
|
+
} else if (outcome.status === "error") {
|
|
70063
|
+
entry.failureCount += 1;
|
|
70064
|
+
entry.runAgain = false;
|
|
70065
|
+
const baseDelay = this.#getIntervalMs(entry);
|
|
70066
|
+
const exponentialDelay = Math.min(baseDelay * 2 ** (entry.failureCount - 1), MAX_BACKOFF_MS);
|
|
70067
|
+
const jitteredDelay = Math.min(this.#withJitter(exponentialDelay), MAX_BACKOFF_MS);
|
|
70068
|
+
const backoffDelay = Math.max(jitteredDelay, outcome.retryAfterMs ?? 0);
|
|
70069
|
+
this.#schedule(key, entry, backoffDelay);
|
|
70070
|
+
}
|
|
70071
|
+
if (this.#getVisibilityState() === "hidden") {
|
|
70072
|
+
entry.runOnShow = true;
|
|
70073
|
+
return;
|
|
70074
|
+
}
|
|
70075
|
+
if (outcome.status === "success") {
|
|
70076
|
+
if (entry.runAgain || entry.runOnShow) {
|
|
70077
|
+
entry.runAgain = false;
|
|
70078
|
+
entry.runOnShow = false;
|
|
70079
|
+
this.runNow(key);
|
|
70080
|
+
return;
|
|
70081
|
+
}
|
|
70082
|
+
this.#schedulePoll(key, entry);
|
|
70083
|
+
return;
|
|
70084
|
+
}
|
|
70085
|
+
if (outcome.status === "aborted") if (entry.runAgain) {
|
|
70086
|
+
entry.runAgain = false;
|
|
70087
|
+
this.runNow(key);
|
|
70088
|
+
} else this.#schedulePoll(key, entry);
|
|
70089
|
+
}
|
|
70090
|
+
async #waitForNewer(key, generation) {
|
|
70091
|
+
let seenGeneration = generation;
|
|
70092
|
+
while (true) {
|
|
70093
|
+
const state = this.#entries.get(key)?.state;
|
|
70094
|
+
const activeRun = state?.kind === "running" ? state.run : void 0;
|
|
70095
|
+
if (!activeRun || activeRun.generation <= seenGeneration) return;
|
|
70096
|
+
seenGeneration = activeRun.generation;
|
|
70097
|
+
await activeRun.done;
|
|
70098
|
+
}
|
|
70099
|
+
}
|
|
70100
|
+
#getIntervalMs(entry) {
|
|
70101
|
+
return Math.min(...Array.from(entry.subscribers.values(), (subscriber) => subscriber.intervalMs));
|
|
70102
|
+
}
|
|
70103
|
+
#getOrCreateEntry(key) {
|
|
70104
|
+
let entry = this.#entries.get(key);
|
|
70105
|
+
if (!entry) {
|
|
70106
|
+
entry = {
|
|
70107
|
+
failureCount: 0,
|
|
70108
|
+
generation: 0,
|
|
70109
|
+
owners: /* @__PURE__ */ new Set(),
|
|
70110
|
+
runAgain: false,
|
|
70111
|
+
runOnShow: false,
|
|
70112
|
+
state: { kind: "idle" },
|
|
70113
|
+
subscribers: /* @__PURE__ */ new Map()
|
|
70114
|
+
};
|
|
70115
|
+
this.#entries.set(key, entry);
|
|
70116
|
+
}
|
|
70117
|
+
return entry;
|
|
70118
|
+
}
|
|
70119
|
+
#getSubscriber(entry) {
|
|
70120
|
+
return Array.from(entry.subscribers.values()).sort((a, b) => a.intervalMs - b.intervalMs)[0];
|
|
70121
|
+
}
|
|
70122
|
+
#getOrCreateOwner(ownerId) {
|
|
70123
|
+
let owner = this.#owners.get(ownerId);
|
|
70124
|
+
if (!owner) {
|
|
70125
|
+
const newOwner = {
|
|
70126
|
+
claims: /* @__PURE__ */ new Map(),
|
|
70127
|
+
hooks: /* @__PURE__ */ new Map(),
|
|
70128
|
+
renderKeys: /* @__PURE__ */ new Set(),
|
|
70129
|
+
timers: /* @__PURE__ */ new Map()
|
|
70130
|
+
};
|
|
70131
|
+
owner = newOwner;
|
|
70132
|
+
this.#owners.set(ownerId, newOwner);
|
|
70133
|
+
}
|
|
70134
|
+
return owner;
|
|
70135
|
+
}
|
|
70136
|
+
#dropOwnedKey(ownerId, key) {
|
|
70137
|
+
const entry = this.#entries.get(key);
|
|
70138
|
+
if (!entry) return;
|
|
70139
|
+
entry.owners.delete(ownerId);
|
|
70140
|
+
if (entry.owners.size > 0 || entry.subscribers.size > 0) return;
|
|
70141
|
+
this.#clearTimer(entry);
|
|
70142
|
+
if (entry.state.kind === "running") {
|
|
70143
|
+
entry.state.run.controller.abort();
|
|
70144
|
+
entry.state.run.detachExternalSignal?.();
|
|
70145
|
+
entry.state.run.end();
|
|
70146
|
+
}
|
|
70147
|
+
this.#entries.delete(key);
|
|
70148
|
+
}
|
|
70149
|
+
#dropOwner(ownerId, owner) {
|
|
70150
|
+
if (this.#owners.get(ownerId) !== owner) return;
|
|
70151
|
+
this.#owners.delete(ownerId);
|
|
70152
|
+
for (const timer of owner.timers.values()) this.#clearTimeout(timer);
|
|
70153
|
+
const keys = /* @__PURE__ */ new Set([
|
|
70154
|
+
...owner.claims.values(),
|
|
70155
|
+
...owner.renderKeys,
|
|
70156
|
+
...owner.hooks.values()
|
|
70157
|
+
]);
|
|
70158
|
+
for (const key of keys) this.#dropOwnedKey(ownerId, key);
|
|
70159
|
+
this.#stopVisibilityListenerIfIdle();
|
|
70160
|
+
}
|
|
70161
|
+
#hasClaimForKey(owner, key) {
|
|
70162
|
+
return Array.from(owner.claims.values()).some((claimKey) => claimKey === key);
|
|
70163
|
+
}
|
|
70164
|
+
#hasHookForKey(owner, key) {
|
|
70165
|
+
return Array.from(owner.hooks.values()).some((hookKey) => hookKey === key);
|
|
70166
|
+
}
|
|
70167
|
+
#ownerHasKey(owner, key) {
|
|
70168
|
+
return owner.renderKeys.has(key) || this.#hasHookForKey(owner, key) || this.#hasClaimForKey(owner, key);
|
|
70169
|
+
}
|
|
70170
|
+
#schedulePoll(key, entry) {
|
|
70171
|
+
this.#schedule(key, entry, this.#withJitter(this.#getIntervalMs(entry)));
|
|
70172
|
+
}
|
|
70173
|
+
#schedule(key, entry, delay) {
|
|
70174
|
+
this.#clearTimer(entry);
|
|
70175
|
+
entry.nextRunAt = this.#now() + delay;
|
|
70176
|
+
if (this.#getVisibilityState() === "hidden") {
|
|
70177
|
+
entry.runOnShow = true;
|
|
70178
|
+
return;
|
|
70179
|
+
}
|
|
70180
|
+
entry.timer = this.#setTimeout(() => {
|
|
70181
|
+
entry.timer = void 0;
|
|
70182
|
+
entry.nextRunAt = void 0;
|
|
70183
|
+
this.runNow(key);
|
|
70184
|
+
}, delay);
|
|
70185
|
+
}
|
|
70186
|
+
#clearTimer(entry, clearNextRun = true) {
|
|
70187
|
+
if (entry.timer !== void 0) {
|
|
70188
|
+
this.#clearTimeout(entry.timer);
|
|
70189
|
+
entry.timer = void 0;
|
|
70190
|
+
}
|
|
70191
|
+
if (clearNextRun) entry.nextRunAt = void 0;
|
|
70192
|
+
}
|
|
70193
|
+
#withJitter(delay) {
|
|
70194
|
+
const multiplier = 1 - this.#jitterRatio + this.#random() * this.#jitterRatio * 2;
|
|
70195
|
+
return Math.max(0, delay * multiplier);
|
|
70196
|
+
}
|
|
70197
|
+
#handleVisibilityChange = () => {
|
|
70198
|
+
const hidden = this.#getVisibilityState() === "hidden";
|
|
70199
|
+
for (const [key, entry] of this.#entries) {
|
|
70200
|
+
if (hidden) {
|
|
70201
|
+
entry.runOnShow = entry.subscribers.size > 0;
|
|
70202
|
+
if (entry.timer !== void 0) this.#clearTimer(entry, entry.failureCount === 0);
|
|
70203
|
+
continue;
|
|
70204
|
+
}
|
|
70205
|
+
if (!entry.runOnShow || entry.subscribers.size === 0) continue;
|
|
70206
|
+
entry.runOnShow = false;
|
|
70207
|
+
const delay = Math.max(0, (entry.nextRunAt ?? this.#now()) - this.#now());
|
|
70208
|
+
if (delay > 0) this.#schedule(key, entry, delay);
|
|
70209
|
+
else this.runNow(key);
|
|
70210
|
+
}
|
|
70211
|
+
};
|
|
70212
|
+
#startVisibilityListener() {
|
|
70213
|
+
if (this.#listeningForVisibility || !this.#visibilityTarget) return;
|
|
70214
|
+
this.#visibilityTarget.addEventListener("visibilitychange", this.#handleVisibilityChange);
|
|
70215
|
+
this.#listeningForVisibility = true;
|
|
70216
|
+
}
|
|
70217
|
+
#stopVisibilityListenerIfIdle() {
|
|
70218
|
+
if (!this.#listeningForVisibility || this.#entries.size > 0 || !this.#visibilityTarget) return;
|
|
70219
|
+
this.#visibilityTarget.removeEventListener("visibilitychange", this.#handleVisibilityChange);
|
|
70220
|
+
this.#listeningForVisibility = false;
|
|
70221
|
+
}
|
|
70222
|
+
};
|
|
70223
|
+
var poller = new Poller();
|
|
70224
|
+
/**
|
|
70225
|
+
* Register fixed-delay polling for a request identity.
|
|
70226
|
+
*
|
|
70227
|
+
* `refresh` only invalidates the corresponding selector. Request lifecycle,
|
|
70228
|
+
* backpressure, retries, and cancellation remain owned by the poller.
|
|
70229
|
+
*/
|
|
70230
|
+
function usePolling(key, intervalSeconds, refresh) {
|
|
70231
|
+
const refreshRef = useLatestRef$3(refresh);
|
|
70232
|
+
(0, react$3.useEffect)(() => poller.subscribe(key, intervalSeconds, () => refreshRef.current()), [
|
|
70233
|
+
intervalSeconds,
|
|
70234
|
+
key,
|
|
70235
|
+
refreshRef
|
|
70236
|
+
]);
|
|
70237
|
+
}
|
|
70238
|
+
/**
|
|
70239
|
+
* Create a render-local map of hooks to polling keys.
|
|
70240
|
+
*
|
|
70241
|
+
* The commit drops claims left by hooks that did not render.
|
|
70242
|
+
*/
|
|
70243
|
+
function usePollScope() {
|
|
70244
|
+
const id = (0, react$3.useId)();
|
|
70245
|
+
const claims = /* @__PURE__ */ new Map();
|
|
70246
|
+
(0, react$3.useLayoutEffect)(() => {
|
|
70247
|
+
poller.commitOwner(id, claims);
|
|
70248
|
+
});
|
|
70249
|
+
(0, react$3.useLayoutEffect)(() => () => poller.releaseOwner(id), [id]);
|
|
70250
|
+
return {
|
|
70251
|
+
claims,
|
|
70252
|
+
id
|
|
70253
|
+
};
|
|
70254
|
+
}
|
|
70255
|
+
/**
|
|
70256
|
+
* Keep one request key for a rendered hook.
|
|
70257
|
+
*
|
|
70258
|
+
* The hook must claim the key during render because an initial suspended render
|
|
70259
|
+
* runs no effect. The claim only marks ownership; it starts no work. The passive
|
|
70260
|
+
* effect keeps the claim after commit and stays mounted when Suspense hides an
|
|
70261
|
+
* existing tree.
|
|
70262
|
+
*/
|
|
70263
|
+
function usePollKey(scope, key) {
|
|
70264
|
+
const hookId = (0, react$3.useId)();
|
|
70265
|
+
scope?.claims.set(hookId, key);
|
|
70266
|
+
const ownerId = scope?.id;
|
|
70267
|
+
if (ownerId) poller.claimKey(ownerId, hookId, key);
|
|
70268
|
+
(0, react$3.useEffect)(() => {
|
|
70269
|
+
if (!ownerId) return;
|
|
70270
|
+
poller.mountKey(ownerId, hookId, key);
|
|
70271
|
+
return () => poller.unmountKey(ownerId, hookId, key);
|
|
70272
|
+
}, [
|
|
70273
|
+
hookId,
|
|
70274
|
+
key,
|
|
70275
|
+
ownerId
|
|
70276
|
+
]);
|
|
70277
|
+
}
|
|
70278
|
+
/** Run one request using the production poller. */
|
|
70279
|
+
function runPoll(run) {
|
|
70280
|
+
return poller.run(run);
|
|
70281
|
+
}
|
|
70282
|
+
/** Create a force key that identifies a poller-owned refresh. */
|
|
70283
|
+
function createPollForceKey() {
|
|
70284
|
+
return `${POLL_FORCE_KEY_PREFIX}${globalThis.crypto?.randomUUID?.() ?? String(Math.random())}`;
|
|
70285
|
+
}
|
|
70286
|
+
/** Check whether a selector force key originated from the poller. */
|
|
70287
|
+
function isPollForceKey(forceKey) {
|
|
70288
|
+
return forceKey?.startsWith(POLL_FORCE_KEY_PREFIX) ?? false;
|
|
70289
|
+
}
|
|
70290
|
+
/** Extract Retry-After as a non-negative delay in milliseconds. */
|
|
70291
|
+
function parseRetryAfter(response, now = poller.now()) {
|
|
70292
|
+
const value = response.headers.get("Retry-After");
|
|
70293
|
+
if (!value) return;
|
|
70294
|
+
const seconds = Number(value);
|
|
70295
|
+
if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
|
|
70296
|
+
const retryAt = Date.parse(value);
|
|
70297
|
+
if (Number.isNaN(retryAt)) return;
|
|
70298
|
+
return Math.max(0, retryAt - now);
|
|
70299
|
+
}
|
|
70300
|
+
/** Keep Retry-After beside an error without changing the error object. */
|
|
70301
|
+
function markRetryAfter(error, response) {
|
|
70302
|
+
const delay = parseRetryAfter(response);
|
|
70303
|
+
if (delay !== void 0 && typeof error === "object" && error !== null) retryAfterByError.set(error, delay);
|
|
70304
|
+
return error;
|
|
70305
|
+
}
|
|
70306
|
+
/** Await a promise while preserving ownership of request cancellation. */
|
|
70307
|
+
async function waitOrAbort(promise, signal) {
|
|
70308
|
+
if (!signal) return promise;
|
|
70309
|
+
if (signal.aborted) throw new DOMException("The request was aborted", "AbortError");
|
|
70310
|
+
return new Promise((resolve, reject) => {
|
|
70311
|
+
const abort = () => {
|
|
70312
|
+
signal.removeEventListener("abort", abort);
|
|
70313
|
+
reject(new DOMException("The request was aborted", "AbortError"));
|
|
70314
|
+
};
|
|
70315
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
70316
|
+
promise.then((value) => {
|
|
70317
|
+
signal.removeEventListener("abort", abort);
|
|
70318
|
+
resolve(value);
|
|
70319
|
+
}, (error) => {
|
|
70320
|
+
signal.removeEventListener("abort", abort);
|
|
70321
|
+
reject(error);
|
|
70322
|
+
});
|
|
70323
|
+
});
|
|
70324
|
+
}
|
|
70325
|
+
/** Clear production polling state. Intended for test isolation. */
|
|
70326
|
+
function clearPolling_TEST() {
|
|
70327
|
+
poller.clear();
|
|
70328
|
+
}
|
|
70329
|
+
//#endregion
|
|
69859
70330
|
//#region js/shared/interactivity/store.tsx
|
|
69860
70331
|
/**
|
|
69861
70332
|
* Key -> atom
|
|
69862
70333
|
*/
|
|
69863
70334
|
var atomRegistry = /* @__PURE__ */ new Map();
|
|
70335
|
+
/** Request identity -> polling-only trigger atom. */
|
|
70336
|
+
var pollingTriggerRegistry = /* @__PURE__ */ new Map();
|
|
69864
70337
|
/**
|
|
69865
70338
|
* Key -> atom family
|
|
69866
70339
|
*/
|
|
@@ -69896,6 +70369,19 @@
|
|
|
69896
70369
|
*/
|
|
69897
70370
|
var depsRegistry = /* @__PURE__ */ new Map();
|
|
69898
70371
|
/**
|
|
70372
|
+
* Get the trigger used to refresh exactly one selector/request-extras identity.
|
|
70373
|
+
*/
|
|
70374
|
+
function getOrRegisterPollingTrigger(requestKey) {
|
|
70375
|
+
if (!pollingTriggerRegistry.has(requestKey)) pollingTriggerRegistry.set(requestKey, Recoil_index_8({
|
|
70376
|
+
default: {
|
|
70377
|
+
force_key: null,
|
|
70378
|
+
inc: 0
|
|
70379
|
+
},
|
|
70380
|
+
key: `_POLLING_TRIGGER_${requestKey}`
|
|
70381
|
+
}));
|
|
70382
|
+
return pollingTriggerRegistry.get(requestKey);
|
|
70383
|
+
}
|
|
70384
|
+
/**
|
|
69899
70385
|
* Registry key types that do not use 'nested' in their key
|
|
69900
70386
|
*/
|
|
69901
70387
|
var SHARED_KEY_TYPES = ["result-selector", "derived-selector"];
|
|
@@ -69914,8 +70400,10 @@
|
|
|
69914
70400
|
* Clear registries - to be used in tests only.
|
|
69915
70401
|
*/
|
|
69916
70402
|
function clearRegistries_TEST() {
|
|
70403
|
+
clearPolling_TEST();
|
|
69917
70404
|
for (const registry of [
|
|
69918
70405
|
atomRegistry,
|
|
70406
|
+
pollingTriggerRegistry,
|
|
69919
70407
|
atomFamilyRegistry,
|
|
69920
70408
|
atomFamilyMembersRegistry,
|
|
69921
70409
|
selectorRegistry,
|
|
@@ -86223,24 +86711,8 @@ ${String(error)}`;
|
|
|
86223
86711
|
module.exports = set;
|
|
86224
86712
|
}));
|
|
86225
86713
|
//#endregion
|
|
86226
|
-
//#region js/shared/utils/use-interval.tsx
|
|
86227
|
-
var import_set = /* @__PURE__ */ __toESM(require_set(), 1);
|
|
86228
|
-
/**
|
|
86229
|
-
* Helper hook that runs a function after given intervals
|
|
86230
|
-
*
|
|
86231
|
-
* @param callback the function to run after each interval
|
|
86232
|
-
* @param delay the delay in seconds between each interval
|
|
86233
|
-
*/
|
|
86234
|
-
function useInterval(callback, delay) {
|
|
86235
|
-
(0, react$3.useEffect)(() => {
|
|
86236
|
-
if (delay) {
|
|
86237
|
-
const id = setInterval(callback, delay * 1e3);
|
|
86238
|
-
return () => clearInterval(id);
|
|
86239
|
-
}
|
|
86240
|
-
}, useDeepCompare([delay, callback]));
|
|
86241
|
-
}
|
|
86242
|
-
//#endregion
|
|
86243
86714
|
//#region js/shared/utils/deferred.tsx
|
|
86715
|
+
var import_set = /* @__PURE__ */ __toESM(require_set(), 1);
|
|
86244
86716
|
var DeferredImpl = class {
|
|
86245
86717
|
#resolve;
|
|
86246
86718
|
#reject;
|
|
@@ -86382,7 +86854,7 @@ ${String(error)}`;
|
|
|
86382
86854
|
* - `values`, values to pass in the request
|
|
86383
86855
|
* - `wsClient`, websocket client
|
|
86384
86856
|
*/
|
|
86385
|
-
async function fetchDerivedVariable({ cache, extras, force_key, variableUid, values, wsClient }) {
|
|
86857
|
+
async function fetchDerivedVariable({ cache, extras, force_key, signal, variableUid, values, wsClient }) {
|
|
86386
86858
|
const cacheControl = cache === null ? { "cache-control": "none" } : void 0;
|
|
86387
86859
|
const ws_channel = await wsClient.getChannel();
|
|
86388
86860
|
const res = await request(`/api/core/derived-variable/${variableUid}`, {
|
|
@@ -86393,34 +86865,50 @@ ${String(error)}`;
|
|
|
86393
86865
|
}),
|
|
86394
86866
|
headers: { ...cacheControl },
|
|
86395
86867
|
method: HTTP_METHOD.POST
|
|
86396
|
-
}, extras);
|
|
86868
|
+
}, extras, { signal });
|
|
86397
86869
|
await handleAuthErrors(res, { authenticationFailureRedirect: "login" });
|
|
86398
|
-
|
|
86870
|
+
try {
|
|
86871
|
+
await validateResponse(res, `Failed to fetch the derived variable with uid: ${variableUid}`);
|
|
86872
|
+
} catch (error) {
|
|
86873
|
+
throw markRetryAfter(error, res);
|
|
86874
|
+
}
|
|
86399
86875
|
return res.json();
|
|
86400
86876
|
}
|
|
86877
|
+
var pendingFetches = /* @__PURE__ */ new Map();
|
|
86401
86878
|
/**
|
|
86402
|
-
*
|
|
86403
|
-
* so that we only debounce calls to the same DerivedVariable. Debouncing is done with rxjs as everything here is
|
|
86404
|
-
* promise based and async
|
|
86879
|
+
* Wait 10 ms so matching selector reads share one fetch. A running fetch stays separate.
|
|
86405
86880
|
*/
|
|
86406
|
-
|
|
86407
|
-
|
|
86408
|
-
|
|
86409
|
-
|
|
86410
|
-
|
|
86411
|
-
|
|
86412
|
-
|
|
86413
|
-
debouncedFetchSubjects[selectorKey].next({
|
|
86414
|
-
cache,
|
|
86415
|
-
extras,
|
|
86416
|
-
force_key,
|
|
86417
|
-
selectorKey,
|
|
86418
|
-
values,
|
|
86419
|
-
variableUid,
|
|
86420
|
-
wsClient
|
|
86881
|
+
function startPendingFetch(selectorKey, pending) {
|
|
86882
|
+
if (pendingFetches.get(selectorKey) !== pending) return;
|
|
86883
|
+
pendingFetches.delete(selectorKey);
|
|
86884
|
+
fetchDerivedVariable(pending.args).then((response) => {
|
|
86885
|
+
for (const waiter of pending.waiters) waiter.resolve(response);
|
|
86886
|
+
}, (error) => {
|
|
86887
|
+
for (const waiter of pending.waiters) waiter.reject(error);
|
|
86421
86888
|
});
|
|
86889
|
+
}
|
|
86890
|
+
async function debouncedFetchDerivedVariable(args) {
|
|
86422
86891
|
return new Promise((resolve, reject) => {
|
|
86423
|
-
|
|
86892
|
+
const pending = pendingFetches.get(args.selectorKey);
|
|
86893
|
+
if (pending) {
|
|
86894
|
+
if (pending.timer !== void 0) clearTimeout(pending.timer);
|
|
86895
|
+
pending.args = args;
|
|
86896
|
+
pending.waiters.push({
|
|
86897
|
+
reject,
|
|
86898
|
+
resolve
|
|
86899
|
+
});
|
|
86900
|
+
pending.timer = setTimeout(() => startPendingFetch(args.selectorKey, pending), 10);
|
|
86901
|
+
return;
|
|
86902
|
+
}
|
|
86903
|
+
const next = {
|
|
86904
|
+
args,
|
|
86905
|
+
waiters: [{
|
|
86906
|
+
reject,
|
|
86907
|
+
resolve
|
|
86908
|
+
}]
|
|
86909
|
+
};
|
|
86910
|
+
next.timer = setTimeout(() => startPendingFetch(args.selectorKey, next), 10);
|
|
86911
|
+
pendingFetches.set(args.selectorKey, next);
|
|
86424
86912
|
});
|
|
86425
86913
|
}
|
|
86426
86914
|
/**
|
|
@@ -86502,9 +86990,11 @@ ${String(error)}`;
|
|
|
86502
86990
|
* @param resolvedVariables resolved values of dependant variables - turned into primitives and Resolved forms
|
|
86503
86991
|
* @param get getter function to resolve atoms to values
|
|
86504
86992
|
* @param triggerList list of trigger info objects
|
|
86505
|
-
* @param
|
|
86993
|
+
* @param selfTriggers triggers owned by this request identity
|
|
86994
|
+
* @param childTriggers triggers owned by nested variables
|
|
86506
86995
|
*/
|
|
86507
|
-
function resolveDerivedValue({ key, variables, deps, resolvedVariables, resolutionStrategy, triggerList,
|
|
86996
|
+
function resolveDerivedValue({ key, variables, deps, resolvedVariables, resolutionStrategy, triggerList, selfTriggers, childTriggers }) {
|
|
86997
|
+
const triggers = [...selfTriggers, ...childTriggers];
|
|
86508
86998
|
/**
|
|
86509
86999
|
* Array of values:
|
|
86510
87000
|
* - primitive values are resolved to themselves
|
|
@@ -86565,16 +87055,17 @@ ${String(error)}`;
|
|
|
86565
87055
|
};
|
|
86566
87056
|
}
|
|
86567
87057
|
const previousTriggerCounters = previousEntry.args.slice(previousEntry.args.length - triggers.length);
|
|
87058
|
+
const dependenciesChanged = !(0, import_isEqual.default)(previousEntry.args.slice(0, -triggers.length), relevantValues.slice(0, -triggers.length));
|
|
86568
87059
|
let selfTriggerForceKey = null;
|
|
86569
|
-
for (const [idx, triggerValue] of triggers.entries())
|
|
87060
|
+
for (const [idx, triggerValue] of dependenciesChanged ? [] : triggers.entries())
|
|
86570
87061
|
/**
|
|
86571
87062
|
* If any of the nested trigger value has changed (this execution was caused by a trigger)
|
|
86572
87063
|
* handle the force_key appropriately
|
|
86573
87064
|
*/
|
|
86574
87065
|
if (triggerValue.inc !== previousTriggerCounters[idx]) {
|
|
86575
|
-
if (idx
|
|
87066
|
+
if (idx < selfTriggers.length) selfTriggerForceKey = triggerValue.force_key;
|
|
86576
87067
|
else if (triggerValue.force_key) {
|
|
86577
|
-
const triggerInfo = triggerList[idx -
|
|
87068
|
+
const triggerInfo = triggerList[idx - selfTriggers.length];
|
|
86578
87069
|
if (triggerInfo.path.length === 0) selfTriggerForceKey = triggerValue.force_key;
|
|
86579
87070
|
else (0, import_set.default)(values, [...triggerInfo.path, "force_key"], triggerValue.force_key);
|
|
86580
87071
|
}
|
|
@@ -86622,9 +87113,9 @@ ${String(error)}`;
|
|
|
86622
87113
|
}));
|
|
86623
87114
|
const selfTrigger = get(getOrRegisterTrigger(variable));
|
|
86624
87115
|
const selectorKey = key + extrasSerializable.toJSON();
|
|
87116
|
+
const pollingTrigger = get(getOrRegisterPollingTrigger(getRegistryKey(variable, "derived-selector") + extrasSerializable.toJSON()));
|
|
86625
87117
|
const triggerList = buildTriggerList(variable.variables);
|
|
86626
|
-
const
|
|
86627
|
-
triggers.unshift(selfTrigger);
|
|
87118
|
+
const childTriggers = registerChildTriggers(triggerList, get);
|
|
86628
87119
|
return resolveDerivedValue({
|
|
86629
87120
|
key: selectorKey,
|
|
86630
87121
|
variables: variable.variables,
|
|
@@ -86635,7 +87126,8 @@ ${String(error)}`;
|
|
|
86635
87126
|
get
|
|
86636
87127
|
},
|
|
86637
87128
|
triggerList,
|
|
86638
|
-
|
|
87129
|
+
selfTriggers: [selfTrigger, pollingTrigger],
|
|
87130
|
+
childTriggers
|
|
86639
87131
|
});
|
|
86640
87132
|
},
|
|
86641
87133
|
key: nanoid$1()
|
|
@@ -86669,68 +87161,104 @@ ${String(error)}`;
|
|
|
86669
87161
|
error.selectorExtras = extrasSerializable.toJSON();
|
|
86670
87162
|
throw error;
|
|
86671
87163
|
};
|
|
86672
|
-
const handleError = (func) => {
|
|
86673
|
-
try {
|
|
86674
|
-
return func();
|
|
86675
|
-
} catch (e) {
|
|
86676
|
-
throwError(e);
|
|
86677
|
-
}
|
|
86678
|
-
};
|
|
86679
87164
|
let derivedResult = get(getOrRegisterDerivedVariableResult(variable, wsClient, taskContext, extrasSerializable.extras));
|
|
86680
87165
|
if (derivedResult.type === "previous") return derivedResult.entry.result;
|
|
86681
87166
|
const { extras } = extrasSerializable;
|
|
86682
|
-
|
|
86683
|
-
|
|
86684
|
-
|
|
86685
|
-
|
|
86686
|
-
|
|
86687
|
-
|
|
86688
|
-
|
|
86689
|
-
|
|
86690
|
-
|
|
86691
|
-
|
|
86692
|
-
|
|
86693
|
-
|
|
86694
|
-
|
|
86695
|
-
|
|
86696
|
-
|
|
86697
|
-
|
|
86698
|
-
|
|
86699
|
-
|
|
86700
|
-
|
|
86701
|
-
|
|
86702
|
-
|
|
86703
|
-
|
|
86704
|
-
|
|
86705
|
-
|
|
86706
|
-
|
|
86707
|
-
|
|
86708
|
-
|
|
86709
|
-
} catch (e) {
|
|
86710
|
-
throwError(e);
|
|
87167
|
+
const currentResult = derivedResult.type === "current" ? derivedResult : void 0;
|
|
87168
|
+
const pollRequest = isPollForceKey(currentResult?.selfTriggerForceKey);
|
|
87169
|
+
const inputKey = currentResult ? JSON.stringify({
|
|
87170
|
+
forceKey: currentResult.selfTriggerForceKey,
|
|
87171
|
+
values: currentResult.values
|
|
87172
|
+
}) : void 0;
|
|
87173
|
+
const fetchValue = async (signal) => {
|
|
87174
|
+
let variableResponse = null;
|
|
87175
|
+
let shouldFetchTask = false;
|
|
87176
|
+
if (derivedResult.type === "cached") {
|
|
87177
|
+
const response = await derivedResult.response.getValue();
|
|
87178
|
+
shouldFetchTask = true;
|
|
87179
|
+
if (!response.ok) throwError(new Error(response.value));
|
|
87180
|
+
variableResponse = response.value;
|
|
87181
|
+
derivedResult = derivedResult.currentResult;
|
|
87182
|
+
} else {
|
|
87183
|
+
signal.addEventListener("abort", () => taskContext.cleanupRunningTasks(variable.uid), { once: true });
|
|
87184
|
+
variableResponse = await debouncedFetchDerivedVariable({
|
|
87185
|
+
cache: variable.cache,
|
|
87186
|
+
extras,
|
|
87187
|
+
force_key: currentResult.selfTriggerForceKey,
|
|
87188
|
+
selectorKey,
|
|
87189
|
+
signal,
|
|
87190
|
+
values: normalizeRequest(cleanArgs(currentResult.values), variable.variables),
|
|
87191
|
+
variableUid: variable.uid,
|
|
87192
|
+
wsClient
|
|
87193
|
+
});
|
|
86711
87194
|
}
|
|
86712
|
-
|
|
86713
|
-
|
|
86714
|
-
|
|
86715
|
-
|
|
86716
|
-
|
|
86717
|
-
|
|
86718
|
-
|
|
86719
|
-
|
|
86720
|
-
|
|
87195
|
+
signal?.throwIfAborted();
|
|
87196
|
+
let variableValue = NOT_SET$1;
|
|
87197
|
+
taskContext.cleanupRunningTasks(variable.uid);
|
|
87198
|
+
if (isTaskResponse(variableResponse)) {
|
|
87199
|
+
const taskId = variableResponse.task_id;
|
|
87200
|
+
if (shouldFetchTask) {
|
|
87201
|
+
const taskResult = await fetchTaskResult(taskId, {
|
|
87202
|
+
...extras,
|
|
87203
|
+
signal
|
|
87204
|
+
});
|
|
87205
|
+
if (taskResult.status === "ok") variableValue = taskResult.result;
|
|
86721
87206
|
}
|
|
86722
|
-
variableValue
|
|
86723
|
-
|
|
87207
|
+
if (variableValue === NOT_SET$1) {
|
|
87208
|
+
taskContext.startTask(taskId, variable.uid, getRegistryKey(variable, "trigger"));
|
|
87209
|
+
try {
|
|
87210
|
+
await waitOrAbort(wsClient.waitForTask(taskId), signal);
|
|
87211
|
+
} catch (e) {
|
|
87212
|
+
if (e instanceof TaskError || isAbortError(e)) throw e;
|
|
87213
|
+
return null;
|
|
87214
|
+
} finally {
|
|
87215
|
+
taskContext.endTask(taskId);
|
|
87216
|
+
}
|
|
87217
|
+
const result = await fetchTaskResult(taskId, {
|
|
87218
|
+
...extras,
|
|
87219
|
+
signal
|
|
87220
|
+
});
|
|
86724
87221
|
if (result.status === "not_found") throw new Error("Task result not found");
|
|
86725
|
-
|
|
86726
|
-
}
|
|
86727
|
-
}
|
|
86728
|
-
|
|
86729
|
-
|
|
86730
|
-
|
|
86731
|
-
|
|
86732
|
-
|
|
86733
|
-
|
|
87222
|
+
variableValue = result.result;
|
|
87223
|
+
}
|
|
87224
|
+
} else variableValue = variableResponse.value;
|
|
87225
|
+
return variableValue;
|
|
87226
|
+
};
|
|
87227
|
+
if (!currentResult) try {
|
|
87228
|
+
const variableValue = await fetchValue();
|
|
87229
|
+
depsRegistry.set(derivedResult.depsKey, {
|
|
87230
|
+
args: derivedResult.relevantValues,
|
|
87231
|
+
result: variableValue
|
|
87232
|
+
});
|
|
87233
|
+
return variableValue;
|
|
87234
|
+
} catch (error) {
|
|
87235
|
+
return throwError(error);
|
|
87236
|
+
}
|
|
87237
|
+
const runResult = currentResult;
|
|
87238
|
+
try {
|
|
87239
|
+
return await runPoll({
|
|
87240
|
+
cause: pollRequest ? "poll" : "dependency",
|
|
87241
|
+
inputKey,
|
|
87242
|
+
key: selectorKey,
|
|
87243
|
+
read: () => {
|
|
87244
|
+
const saved = depsRegistry.get(runResult.depsKey);
|
|
87245
|
+
return saved ? {
|
|
87246
|
+
found: true,
|
|
87247
|
+
value: saved.result
|
|
87248
|
+
} : { found: false };
|
|
87249
|
+
},
|
|
87250
|
+
signal: extras.signal ?? void 0,
|
|
87251
|
+
work: fetchValue,
|
|
87252
|
+
write: (variableValue) => {
|
|
87253
|
+
depsRegistry.set(runResult.depsKey, {
|
|
87254
|
+
args: runResult.relevantValues,
|
|
87255
|
+
result: variableValue
|
|
87256
|
+
});
|
|
87257
|
+
}
|
|
87258
|
+
});
|
|
87259
|
+
} catch (error) {
|
|
87260
|
+
return throwError(error);
|
|
87261
|
+
}
|
|
86734
87262
|
},
|
|
86735
87263
|
key: nanoid$1()
|
|
86736
87264
|
}));
|
|
@@ -86782,7 +87310,7 @@ ${String(error)}`;
|
|
|
86782
87310
|
* Otherwise, returns an object with values so be sent to the backend
|
|
86783
87311
|
* and handles to resolve the cached promise to the result.
|
|
86784
87312
|
*/
|
|
86785
|
-
function preloadDerivedValue({ key, variables, deps, triggerList,
|
|
87313
|
+
function preloadDerivedValue({ key, variables, deps, triggerList, selfTriggers, childTriggers, snapshot, params }) {
|
|
86786
87314
|
const derivedResult = resolveDerivedValue({
|
|
86787
87315
|
key,
|
|
86788
87316
|
variables,
|
|
@@ -86794,7 +87322,8 @@ ${String(error)}`;
|
|
|
86794
87322
|
params
|
|
86795
87323
|
},
|
|
86796
87324
|
triggerList,
|
|
86797
|
-
|
|
87325
|
+
selfTriggers,
|
|
87326
|
+
childTriggers
|
|
86798
87327
|
});
|
|
86799
87328
|
if (derivedResult.type === "previous") return null;
|
|
86800
87329
|
return {
|
|
@@ -86807,16 +87336,16 @@ ${String(error)}`;
|
|
|
86807
87336
|
*/
|
|
86808
87337
|
function preloadDerivedVariable(variable, snapshot, params) {
|
|
86809
87338
|
const key = getRegistryKey(variable, "result-selector") + new RequestExtrasSerializable({}).toJSON();
|
|
86810
|
-
const
|
|
86811
|
-
|
|
86812
|
-
|
|
86813
|
-
|
|
86814
|
-
const triggers = triggerList.map((ti) => resolveTriggerStatic(getOrRegisterTrigger(ti.variable), snapshot));
|
|
87339
|
+
const requestKey = getRegistryKey(variable, "derived-selector") + new RequestExtrasSerializable({}).toJSON();
|
|
87340
|
+
const triggerList = buildTriggerList(variable.variables);
|
|
87341
|
+
const selfTriggers = [resolveTriggerStatic(getOrRegisterTrigger(variable), snapshot), resolveTriggerStatic(getOrRegisterPollingTrigger(requestKey), snapshot)];
|
|
87342
|
+
const childTriggers = triggerList.map((ti) => resolveTriggerStatic(getOrRegisterTrigger(ti.variable), snapshot));
|
|
86815
87343
|
return preloadDerivedValue({
|
|
86816
87344
|
key,
|
|
86817
87345
|
variables: variable.variables,
|
|
86818
87346
|
deps: variable.deps,
|
|
86819
|
-
|
|
87347
|
+
selfTriggers,
|
|
87348
|
+
childTriggers,
|
|
86820
87349
|
triggerList,
|
|
86821
87350
|
snapshot,
|
|
86822
87351
|
params
|
|
@@ -86830,14 +87359,17 @@ ${String(error)}`;
|
|
|
86830
87359
|
* @param taskContext global task context
|
|
86831
87360
|
* @param search search query
|
|
86832
87361
|
* @param extras request extras to be merged into the options
|
|
87362
|
+
* @param pollScope render-local scope for requests started before commit
|
|
86833
87363
|
*/
|
|
86834
|
-
function useDerivedVariable(variable, WsClient, taskContext, extras, pollingInterval) {
|
|
87364
|
+
function useDerivedVariable(variable, WsClient, taskContext, extras, pollingInterval, pollScope) {
|
|
86835
87365
|
const dvSelector = getOrRegisterDerivedVariable(variable, WsClient, taskContext, extras);
|
|
86836
|
-
const
|
|
86837
|
-
|
|
86838
|
-
|
|
87366
|
+
const pollingKey = getRegistryKey(variable, "derived-selector") + new RequestExtrasSerializable(extras).toJSON();
|
|
87367
|
+
usePollKey(pollScope, pollingKey);
|
|
87368
|
+
const triggerUpdates = Recoil_index_24((0, react$3.useMemo)(() => getOrRegisterPollingTrigger(pollingKey), [pollingKey]));
|
|
87369
|
+
usePolling(pollingKey, pollingInterval, (0, react$3.useCallback)(() => triggerUpdates((val) => ({
|
|
87370
|
+
force_key: createPollForceKey(),
|
|
86839
87371
|
inc: val.inc + 1
|
|
86840
|
-
})), [triggerUpdates])
|
|
87372
|
+
})), [triggerUpdates]));
|
|
86841
87373
|
return dvSelector;
|
|
86842
87374
|
}
|
|
86843
87375
|
//#endregion
|
|
@@ -87856,6 +88388,37 @@ ${String(error)}`;
|
|
|
87856
88388
|
* This allows Recoil to properly release instances when components unmount.
|
|
87857
88389
|
*/
|
|
87858
88390
|
var streamSelectorFamilyRegistry = /* @__PURE__ */ new Map();
|
|
88391
|
+
var STREAM_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
88392
|
+
"add",
|
|
88393
|
+
"remove",
|
|
88394
|
+
"clear",
|
|
88395
|
+
"replace",
|
|
88396
|
+
"json_snapshot",
|
|
88397
|
+
"json_patch",
|
|
88398
|
+
"reconnect",
|
|
88399
|
+
"error"
|
|
88400
|
+
]);
|
|
88401
|
+
/**
|
|
88402
|
+
* Parse an SSE message into a supported StreamEvent.
|
|
88403
|
+
*
|
|
88404
|
+
* Comment-only SSE frames are delivered by fetch-event-source as messages with
|
|
88405
|
+
* empty data. They are transport heartbeats rather than application events.
|
|
88406
|
+
*/
|
|
88407
|
+
function parseStreamEventMessage(message) {
|
|
88408
|
+
if (message.data.trim() === "") return null;
|
|
88409
|
+
let parsed;
|
|
88410
|
+
try {
|
|
88411
|
+
parsed = JSON.parse(message.data);
|
|
88412
|
+
} catch (parseError) {
|
|
88413
|
+
console.error("Failed to parse SSE event:", parseError, message.data);
|
|
88414
|
+
return null;
|
|
88415
|
+
}
|
|
88416
|
+
if (parsed === null || typeof parsed !== "object" || !("type" in parsed) || typeof parsed.type !== "string" || !STREAM_EVENT_TYPES.has(parsed.type)) {
|
|
88417
|
+
console.error("Unsupported SSE event:", parsed);
|
|
88418
|
+
return null;
|
|
88419
|
+
}
|
|
88420
|
+
return parsed;
|
|
88421
|
+
}
|
|
87859
88422
|
/**
|
|
87860
88423
|
* Extract a key from an item using the key_accessor path.
|
|
87861
88424
|
*
|
|
@@ -87997,12 +88560,17 @@ ${String(error)}`;
|
|
|
87997
88560
|
* @returns The value to expose to components
|
|
87998
88561
|
*/
|
|
87999
88562
|
function getStreamValue(state, keyAccessor) {
|
|
88563
|
+
if (state.status === "error") throw new UserError(state.error ?? "Stream failed");
|
|
88000
88564
|
if (keyAccessor !== null && state.data !== null && typeof state.data === "object" && !Array.isArray(state.data)) return Object.values(state.data);
|
|
88001
88565
|
return state.data;
|
|
88002
88566
|
}
|
|
88003
88567
|
var MAX_RETRIES = 5;
|
|
88004
88568
|
var BASE_DELAY_MS = 1e3;
|
|
88005
88569
|
var MAX_DELAY_MS = 3e4;
|
|
88570
|
+
/** Error that should stop the SSE connection rather than be retried. */
|
|
88571
|
+
var FatalStreamError = class extends Error {};
|
|
88572
|
+
/** Error that should be handled by the SSE retry policy. */
|
|
88573
|
+
var RetriableStreamError = class extends Error {};
|
|
88006
88574
|
/**
|
|
88007
88575
|
* Calculate exponential backoff delay.
|
|
88008
88576
|
*/
|
|
@@ -88032,52 +88600,62 @@ ${String(error)}`;
|
|
|
88032
88600
|
let retryCount = 0;
|
|
88033
88601
|
let isFirstMessage = true;
|
|
88034
88602
|
let currentState = INITIAL_CONNECTED_STATE;
|
|
88603
|
+
let terminalErrorReported = false;
|
|
88035
88604
|
const normalizedValues = normalizeRequest(params.resolvedValues, params.variables);
|
|
88605
|
+
const reportTerminalError = (error) => {
|
|
88606
|
+
if (terminalErrorReported) return;
|
|
88607
|
+
terminalErrorReported = true;
|
|
88608
|
+
callbacks.onError(error instanceof Error ? error.message : String(error));
|
|
88609
|
+
};
|
|
88036
88610
|
fetchEventSource(`/api/core/stream/${params.uid}`, {
|
|
88611
|
+
...params.extras,
|
|
88037
88612
|
method: HTTP_METHOD.POST,
|
|
88038
88613
|
body: JSON.stringify({ values: normalizedValues }),
|
|
88039
88614
|
signal: controller.signal,
|
|
88040
88615
|
onopen: async (response) => {
|
|
88041
|
-
if (response.ok)
|
|
88042
|
-
retryCount = 0;
|
|
88043
|
-
return;
|
|
88044
|
-
}
|
|
88616
|
+
if (response.ok) return;
|
|
88045
88617
|
if (await handleAuthErrors(response, { authenticationFailureRedirect: "login" })) controller.abort();
|
|
88046
88618
|
throw /* @__PURE__ */ new Error(`Stream request failed: ${response.status} ${response.statusText}`);
|
|
88047
88619
|
},
|
|
88048
88620
|
onmessage: (msg) => {
|
|
88049
|
-
|
|
88050
|
-
|
|
88051
|
-
event = JSON.parse(msg.data);
|
|
88052
|
-
} catch (parseError) {
|
|
88053
|
-
console.error("Failed to parse SSE event:", parseError, msg.data);
|
|
88054
|
-
return;
|
|
88055
|
-
}
|
|
88621
|
+
const event = parseStreamEventMessage(msg);
|
|
88622
|
+
if (event === null) return;
|
|
88056
88623
|
if (event.type === "reconnect") {
|
|
88057
88624
|
console.info("StreamVariable: Server requested reconnect, reconnecting...");
|
|
88058
|
-
throw new
|
|
88625
|
+
throw new RetriableStreamError("Server requested reconnect");
|
|
88059
88626
|
}
|
|
88060
|
-
|
|
88627
|
+
if (event.type === "error") throw new FatalStreamError(typeof event.data === "string" ? event.data : "Unknown error");
|
|
88628
|
+
const nextState = applyStreamEvent(currentState, event, params.keyAccessor);
|
|
88629
|
+
if (nextState === currentState || nextState.status === "error") throw new FatalStreamError(nextState.error ?? `Stream event "${event.type}" could not be applied`);
|
|
88630
|
+
retryCount = 0;
|
|
88631
|
+
currentState = nextState;
|
|
88061
88632
|
if (isFirstMessage) {
|
|
88062
88633
|
isFirstMessage = false;
|
|
88063
88634
|
callbacks.onFirstData(currentState);
|
|
88064
88635
|
} else callbacks.onUpdate(currentState);
|
|
88065
88636
|
},
|
|
88066
88637
|
onerror: (err) => {
|
|
88067
|
-
if (controller.signal.aborted)
|
|
88638
|
+
if (controller.signal.aborted) throw err;
|
|
88639
|
+
if (err instanceof FatalStreamError) {
|
|
88640
|
+
reportTerminalError(err);
|
|
88641
|
+
throw err;
|
|
88642
|
+
}
|
|
88068
88643
|
retryCount++;
|
|
88069
88644
|
if (retryCount > MAX_RETRIES) {
|
|
88070
|
-
|
|
88071
|
-
|
|
88645
|
+
reportTerminalError(err);
|
|
88646
|
+
throw err;
|
|
88072
88647
|
}
|
|
88073
88648
|
const delay = getBackoffDelay(retryCount - 1);
|
|
88074
88649
|
console.warn(`Stream connection failed, retrying in ${delay}ms (attempt ${retryCount}/${MAX_RETRIES})...`);
|
|
88075
88650
|
return delay;
|
|
88076
88651
|
},
|
|
88077
|
-
onclose: () => {
|
|
88652
|
+
onclose: () => {
|
|
88653
|
+
throw new RetriableStreamError("Stream closed unexpectedly");
|
|
88654
|
+
},
|
|
88078
88655
|
fetch: request,
|
|
88079
|
-
...params.extras,
|
|
88080
88656
|
headers: params.extras.headers
|
|
88657
|
+
}).catch((error) => {
|
|
88658
|
+
if (!controller.signal.aborted) reportTerminalError(error);
|
|
88081
88659
|
});
|
|
88082
88660
|
return {
|
|
88083
88661
|
cleanup: () => {
|
|
@@ -88098,10 +88676,8 @@ ${String(error)}`;
|
|
|
88098
88676
|
return ({ setSelf }) => {
|
|
88099
88677
|
const params = deserializeAtomParams(atomKey);
|
|
88100
88678
|
let resolveInitialData = null;
|
|
88101
|
-
|
|
88102
|
-
setSelf(new Promise((resolve, reject) => {
|
|
88679
|
+
setSelf(new Promise((resolve) => {
|
|
88103
88680
|
resolveInitialData = resolve;
|
|
88104
|
-
rejectInitialData = reject;
|
|
88105
88681
|
}));
|
|
88106
88682
|
const startConnection = () => {
|
|
88107
88683
|
return startStreamConnection(params, {
|
|
@@ -88109,7 +88685,6 @@ ${String(error)}`;
|
|
|
88109
88685
|
if (resolveInitialData) {
|
|
88110
88686
|
resolveInitialData(state);
|
|
88111
88687
|
resolveInitialData = null;
|
|
88112
|
-
rejectInitialData = null;
|
|
88113
88688
|
}
|
|
88114
88689
|
setSelf(state);
|
|
88115
88690
|
},
|
|
@@ -88117,15 +88692,16 @@ ${String(error)}`;
|
|
|
88117
88692
|
setSelf(state);
|
|
88118
88693
|
},
|
|
88119
88694
|
onError: (error) => {
|
|
88120
|
-
|
|
88121
|
-
rejectInitialData(new Error(error));
|
|
88122
|
-
resolveInitialData = null;
|
|
88123
|
-
rejectInitialData = null;
|
|
88124
|
-
} else setSelf({
|
|
88695
|
+
const errorState = {
|
|
88125
88696
|
data: void 0,
|
|
88126
88697
|
status: "error",
|
|
88127
88698
|
error
|
|
88128
|
-
}
|
|
88699
|
+
};
|
|
88700
|
+
if (resolveInitialData) {
|
|
88701
|
+
resolveInitialData(errorState);
|
|
88702
|
+
resolveInitialData = null;
|
|
88703
|
+
}
|
|
88704
|
+
setSelf(errorState);
|
|
88129
88705
|
}
|
|
88130
88706
|
});
|
|
88131
88707
|
};
|
|
@@ -89599,6 +90175,22 @@ ${String(error)}`;
|
|
|
89599
90175
|
return theme;
|
|
89600
90176
|
}
|
|
89601
90177
|
//#endregion
|
|
90178
|
+
//#region js/shared/utils/use-interval.tsx
|
|
90179
|
+
/**
|
|
90180
|
+
* Helper hook that runs a function after given intervals
|
|
90181
|
+
*
|
|
90182
|
+
* @param callback the function to run after each interval
|
|
90183
|
+
* @param delay the delay in seconds between each interval
|
|
90184
|
+
*/
|
|
90185
|
+
function useInterval(callback, delay) {
|
|
90186
|
+
(0, react$3.useEffect)(() => {
|
|
90187
|
+
if (delay) {
|
|
90188
|
+
const id = setInterval(callback, delay * 1e3);
|
|
90189
|
+
return () => clearInterval(id);
|
|
90190
|
+
}
|
|
90191
|
+
}, useDeepCompare([delay, callback]));
|
|
90192
|
+
}
|
|
90193
|
+
//#endregion
|
|
89602
90194
|
//#region js/shared/utils/use-previous.tsx
|
|
89603
90195
|
/**
|
|
89604
90196
|
* A helper hook to keep track of the previous value of a variable.
|
|
@@ -90571,6 +91163,12 @@ ${String(error)}`;
|
|
|
90571
91163
|
return key;
|
|
90572
91164
|
}
|
|
90573
91165
|
/**
|
|
91166
|
+
* Generate the request identity used for polling and cancellation.
|
|
91167
|
+
*/
|
|
91168
|
+
function getServerComponentRequestKey(uid, loopInstanceUid, extras) {
|
|
91169
|
+
return getComponentRegistryKey(uid, false, loopInstanceUid) + new RequestExtrasSerializable(extras).toJSON();
|
|
91170
|
+
}
|
|
91171
|
+
/**
|
|
90574
91172
|
* Fetch a component from the backend, expects a component instance to be returned.
|
|
90575
91173
|
*
|
|
90576
91174
|
* @param component the component to fetch
|
|
@@ -90579,7 +91177,7 @@ ${String(error)}`;
|
|
|
90579
91177
|
* @param extras request extras to be merged into the options
|
|
90580
91178
|
* @param wsClient websocket client
|
|
90581
91179
|
*/
|
|
90582
|
-
async function fetchFunctionComponent(component, values, uid, extras, wsClient) {
|
|
91180
|
+
async function fetchFunctionComponent(component, values, uid, extras, wsClient, signal) {
|
|
90583
91181
|
const ws_channel = await wsClient.getChannel();
|
|
90584
91182
|
const res = await request(`/api/core/components/${component}`, {
|
|
90585
91183
|
body: JSON.stringify({
|
|
@@ -90588,9 +91186,13 @@ ${String(error)}`;
|
|
|
90588
91186
|
ws_channel
|
|
90589
91187
|
}),
|
|
90590
91188
|
method: HTTP_METHOD.POST
|
|
90591
|
-
}, extras);
|
|
91189
|
+
}, extras, { signal });
|
|
90592
91190
|
await handleAuthErrors(res, { authenticationFailureRedirect: "login" });
|
|
90593
|
-
|
|
91191
|
+
try {
|
|
91192
|
+
await validateResponse(res, `Failed to fetch the component: ${component}`);
|
|
91193
|
+
} catch (error) {
|
|
91194
|
+
throw markRetryAfter(error, res);
|
|
91195
|
+
}
|
|
90594
91196
|
return await res.json();
|
|
90595
91197
|
}
|
|
90596
91198
|
function getOrRegisterComponentTrigger(uid, loop_instance_uid) {
|
|
@@ -90626,25 +91228,19 @@ ${String(error)}`;
|
|
|
90626
91228
|
error.selectorExtras = extrasSerializable.toJSON();
|
|
90627
91229
|
throw error;
|
|
90628
91230
|
};
|
|
90629
|
-
const
|
|
90630
|
-
try {
|
|
90631
|
-
return func();
|
|
90632
|
-
} catch (e) {
|
|
90633
|
-
throwError(e);
|
|
90634
|
-
}
|
|
90635
|
-
};
|
|
91231
|
+
const selectorKey = key + extrasSerializable.toJSON();
|
|
90636
91232
|
const resolvedKwargs = await Promise.all(Object.entries(dynamicKwargs).map(async ([k, value]) => {
|
|
90637
91233
|
return [k, isVariable(value) ? await resolveVariable(value, wsClient, taskContext, currentExtras) : value];
|
|
90638
91234
|
})).then((entries) => Object.fromEntries(entries));
|
|
90639
91235
|
const resolvedKwargsList = Object.values(resolvedKwargs);
|
|
90640
91236
|
const kwargsList = Object.values(dynamicKwargs);
|
|
90641
91237
|
const selfTrigger = get(getOrRegisterComponentTrigger(uid, loop_instance_uid));
|
|
91238
|
+
const pollingTrigger = get(getOrRegisterPollingTrigger(selectorKey));
|
|
90642
91239
|
const triggerList = buildTriggerList(kwargsList);
|
|
90643
|
-
const
|
|
90644
|
-
triggers.unshift(selfTrigger);
|
|
91240
|
+
const childTriggers = registerChildTriggers(triggerList, get);
|
|
90645
91241
|
const { extras } = extrasSerializable;
|
|
90646
91242
|
let derivedResult = resolveDerivedValue({
|
|
90647
|
-
key,
|
|
91243
|
+
key: selectorKey,
|
|
90648
91244
|
variables: kwargsList,
|
|
90649
91245
|
deps: kwargsList,
|
|
90650
91246
|
resolvedVariables: resolvedKwargsList,
|
|
@@ -90653,59 +91249,97 @@ ${String(error)}`;
|
|
|
90653
91249
|
get
|
|
90654
91250
|
},
|
|
90655
91251
|
triggerList,
|
|
90656
|
-
|
|
91252
|
+
selfTriggers: [selfTrigger, pollingTrigger],
|
|
91253
|
+
childTriggers
|
|
90657
91254
|
});
|
|
90658
91255
|
if (derivedResult.type === "previous") return derivedResult.entry.result;
|
|
90659
|
-
|
|
90660
|
-
|
|
90661
|
-
|
|
90662
|
-
|
|
90663
|
-
|
|
90664
|
-
|
|
90665
|
-
|
|
90666
|
-
|
|
90667
|
-
|
|
90668
|
-
|
|
90669
|
-
|
|
90670
|
-
|
|
90671
|
-
|
|
90672
|
-
|
|
90673
|
-
|
|
90674
|
-
}
|
|
90675
|
-
|
|
90676
|
-
|
|
90677
|
-
|
|
90678
|
-
|
|
90679
|
-
|
|
90680
|
-
|
|
90681
|
-
|
|
90682
|
-
|
|
90683
|
-
|
|
90684
|
-
|
|
90685
|
-
|
|
90686
|
-
|
|
90687
|
-
|
|
90688
|
-
|
|
90689
|
-
|
|
90690
|
-
|
|
90691
|
-
|
|
90692
|
-
|
|
90693
|
-
|
|
90694
|
-
taskContext.
|
|
91256
|
+
const currentResult = derivedResult.type === "current" ? derivedResult : void 0;
|
|
91257
|
+
const pollRequest = isPollForceKey(currentResult?.selfTriggerForceKey);
|
|
91258
|
+
const inputKey = currentResult ? JSON.stringify({
|
|
91259
|
+
forceKey: currentResult.selfTriggerForceKey,
|
|
91260
|
+
values: currentResult.values
|
|
91261
|
+
}) : void 0;
|
|
91262
|
+
const fetchComponent = async (signal) => {
|
|
91263
|
+
let result = NOT_SET;
|
|
91264
|
+
let shouldFetchTask = false;
|
|
91265
|
+
if (derivedResult.type === "cached") {
|
|
91266
|
+
const response = await derivedResult.response.getValue();
|
|
91267
|
+
shouldFetchTask = true;
|
|
91268
|
+
if (!response.ok) throwError(new Error(response.value));
|
|
91269
|
+
result = response.value;
|
|
91270
|
+
derivedResult = derivedResult.currentResult;
|
|
91271
|
+
} else {
|
|
91272
|
+
signal.addEventListener("abort", () => taskContext.cleanupRunningTasks(key), { once: true });
|
|
91273
|
+
result = await fetchFunctionComponent(name, normalizeRequest(cleanKwargs(Object.keys(dynamicKwargs).reduce((acc, k, idx) => {
|
|
91274
|
+
acc[k] = currentResult.values[idx];
|
|
91275
|
+
return acc;
|
|
91276
|
+
}, {})), dynamicKwargs), uid, extras, wsClient, signal);
|
|
91277
|
+
}
|
|
91278
|
+
signal?.throwIfAborted();
|
|
91279
|
+
taskContext.cleanupRunningTasks(key);
|
|
91280
|
+
if (isTaskResponse$1(result)) {
|
|
91281
|
+
const taskId = result.task_id;
|
|
91282
|
+
result = NOT_SET;
|
|
91283
|
+
if (shouldFetchTask) {
|
|
91284
|
+
const taskResult = await fetchTaskResult(taskId, {
|
|
91285
|
+
...extras,
|
|
91286
|
+
signal
|
|
91287
|
+
});
|
|
91288
|
+
if (taskResult.status === "ok") result = taskResult.result;
|
|
91289
|
+
}
|
|
91290
|
+
if (result === NOT_SET) {
|
|
91291
|
+
taskContext.startTask(taskId, key, getComponentRegistryKey(uid, true));
|
|
91292
|
+
try {
|
|
91293
|
+
await waitOrAbort(wsClient.waitForTask(taskId), signal);
|
|
91294
|
+
} finally {
|
|
91295
|
+
taskContext.endTask(taskId);
|
|
91296
|
+
}
|
|
91297
|
+
const response = await fetchTaskResult(taskId, {
|
|
91298
|
+
...extras,
|
|
91299
|
+
signal
|
|
91300
|
+
});
|
|
91301
|
+
if (response.status === "not_found") throw new Error("Task result not found");
|
|
91302
|
+
result = response.result;
|
|
90695
91303
|
}
|
|
90696
|
-
result = await handleError(async () => {
|
|
90697
|
-
const res = await fetchTaskResult(taskId, extras);
|
|
90698
|
-
if (res.status === "not_found") throw new Error("Task result not found");
|
|
90699
|
-
return res.result;
|
|
90700
|
-
});
|
|
90701
91304
|
}
|
|
91305
|
+
if (result !== NOT_SET && result !== null) result = denormalize(result.data, result.lookup);
|
|
91306
|
+
return result;
|
|
91307
|
+
};
|
|
91308
|
+
if (!currentResult) try {
|
|
91309
|
+
const result = await fetchComponent();
|
|
91310
|
+
depsRegistry.set(derivedResult.depsKey, {
|
|
91311
|
+
args: derivedResult.relevantValues,
|
|
91312
|
+
result
|
|
91313
|
+
});
|
|
91314
|
+
return result;
|
|
91315
|
+
} catch (error) {
|
|
91316
|
+
return throwError(error);
|
|
91317
|
+
}
|
|
91318
|
+
const runResult = currentResult;
|
|
91319
|
+
try {
|
|
91320
|
+
return await runPoll({
|
|
91321
|
+
cause: pollRequest ? "poll" : "dependency",
|
|
91322
|
+
inputKey,
|
|
91323
|
+
key: selectorKey,
|
|
91324
|
+
read: () => {
|
|
91325
|
+
const saved = depsRegistry.get(runResult.depsKey);
|
|
91326
|
+
return saved ? {
|
|
91327
|
+
found: true,
|
|
91328
|
+
value: saved.result
|
|
91329
|
+
} : { found: false };
|
|
91330
|
+
},
|
|
91331
|
+
signal: extras.signal ?? void 0,
|
|
91332
|
+
work: fetchComponent,
|
|
91333
|
+
write: (result) => {
|
|
91334
|
+
depsRegistry.set(runResult.depsKey, {
|
|
91335
|
+
args: runResult.relevantValues,
|
|
91336
|
+
result
|
|
91337
|
+
});
|
|
91338
|
+
}
|
|
91339
|
+
});
|
|
91340
|
+
} catch (error) {
|
|
91341
|
+
return throwError(error);
|
|
90702
91342
|
}
|
|
90703
|
-
if (result !== NOT_SET && result !== null) result = denormalize(result.data, result.lookup);
|
|
90704
|
-
depsRegistry.set(key, {
|
|
90705
|
-
args: derivedResult.relevantValues,
|
|
90706
|
-
result
|
|
90707
|
-
});
|
|
90708
|
-
return result;
|
|
90709
91343
|
},
|
|
90710
91344
|
key
|
|
90711
91345
|
}));
|
|
@@ -90717,7 +91351,7 @@ ${String(error)}`;
|
|
|
90717
91351
|
return selectorInstance;
|
|
90718
91352
|
}
|
|
90719
91353
|
function preloadServerComponent(component, snapshot, params) {
|
|
90720
|
-
const key =
|
|
91354
|
+
const key = getServerComponentRequestKey(component.uid, component.loop_instance_uid, {});
|
|
90721
91355
|
const kwargsList = Object.values(component.props.dynamic_kwargs);
|
|
90722
91356
|
const triggerList = buildTriggerList(kwargsList);
|
|
90723
91357
|
return preloadDerivedValue({
|
|
@@ -90725,7 +91359,8 @@ ${String(error)}`;
|
|
|
90725
91359
|
variables: kwargsList,
|
|
90726
91360
|
deps: kwargsList,
|
|
90727
91361
|
triggerList,
|
|
90728
|
-
|
|
91362
|
+
selfTriggers: [resolveTriggerStatic(getOrRegisterComponentTrigger(component.uid, component.loop_instance_uid), snapshot), resolveTriggerStatic(getOrRegisterPollingTrigger(key), snapshot)],
|
|
91363
|
+
childTriggers: triggerList.map((ti) => resolveTriggerStatic(getOrRegisterTrigger(ti.variable), snapshot)),
|
|
90729
91364
|
snapshot,
|
|
90730
91365
|
params
|
|
90731
91366
|
});
|
|
@@ -90743,6 +91378,8 @@ ${String(error)}`;
|
|
|
90743
91378
|
const { client: wsClient } = (0, react$3.useContext)(websocketCtx);
|
|
90744
91379
|
const taskContext = useTaskContext();
|
|
90745
91380
|
const variablesContext = (0, react$3.useContext)(variablesCtx);
|
|
91381
|
+
const requestKey = getServerComponentRequestKey(uid, loop_instance_uid, extras);
|
|
91382
|
+
usePollKey(variablesContext?.pollScope, requestKey);
|
|
90746
91383
|
const bus = useEventBus();
|
|
90747
91384
|
variablesContext?.variables.current.add(getComponentRegistryKey(uid));
|
|
90748
91385
|
(0, react$3.useEffect)(() => {
|
|
@@ -90782,6 +91419,18 @@ ${String(error)}`;
|
|
|
90782
91419
|
}));
|
|
90783
91420
|
}, [uid]);
|
|
90784
91421
|
}
|
|
91422
|
+
/**
|
|
91423
|
+
* Refresh one server-component/request-extras identity for polling.
|
|
91424
|
+
*/
|
|
91425
|
+
function usePollServerComponent(uid, loopInstanceUid, extras) {
|
|
91426
|
+
const requestKey = getServerComponentRequestKey(uid, loopInstanceUid, extras);
|
|
91427
|
+
return Recoil_index_31(({ set }) => () => {
|
|
91428
|
+
set(getOrRegisterPollingTrigger(requestKey), (triggerIndexValue) => ({
|
|
91429
|
+
force_key: createPollForceKey(),
|
|
91430
|
+
inc: triggerIndexValue.inc + 1
|
|
91431
|
+
}));
|
|
91432
|
+
}, [requestKey]);
|
|
91433
|
+
}
|
|
90785
91434
|
//#endregion
|
|
90786
91435
|
//#region js/shared/center/center.tsx
|
|
90787
91436
|
var Center = dist_default.div`
|
|
@@ -91477,6 +92126,10 @@ ${String(error)}`;
|
|
|
91477
92126
|
}
|
|
91478
92127
|
const { hasRunningTasks, cleanupRunningTasks } = useTaskContext();
|
|
91479
92128
|
const variables = (0, react$3.useRef)(/* @__PURE__ */ new Set());
|
|
92129
|
+
const variableContext = {
|
|
92130
|
+
pollScope: usePollScope(),
|
|
92131
|
+
variables
|
|
92132
|
+
};
|
|
91480
92133
|
(0, react$3.useEffect)(() => {
|
|
91481
92134
|
return () => {
|
|
91482
92135
|
if (variables.current.size > 0 && hasRunningTasks()) cleanupRunningTasks(...variables.current.values());
|
|
@@ -91491,7 +92144,7 @@ ${String(error)}`;
|
|
|
91491
92144
|
...fallbackProps
|
|
91492
92145
|
}),
|
|
91493
92146
|
onReset: onResetErrorBoundary
|
|
91494
|
-
}, /* @__PURE__ */ React.createElement(fallbackCtx.Provider, { value: { suspend } }, /* @__PURE__ */ React.createElement(variablesCtx.Provider, { value:
|
|
92147
|
+
}, /* @__PURE__ */ React.createElement(fallbackCtx.Provider, { value: { suspend } }, /* @__PURE__ */ React.createElement(variablesCtx.Provider, { value: variableContext }, /* @__PURE__ */ React.createElement(react$3.Suspense, { fallback }, component))));
|
|
91495
92148
|
}
|
|
91496
92149
|
function useResolveDynamicKwargPollingIntervals(dynamicKwargs) {
|
|
91497
92150
|
return (0, react$3.useMemo)(() => {
|
|
@@ -91516,9 +92169,12 @@ ${String(error)}`;
|
|
|
91516
92169
|
function PythonWrapper(props) {
|
|
91517
92170
|
const component = useServerComponent(props.name, props.uid, props.dynamic_kwargs, props.component.loop_instance_uid);
|
|
91518
92171
|
const refresh = useRefreshServerComponent(props.uid, props.component.loop_instance_uid);
|
|
92172
|
+
const extras = useRequestExtras();
|
|
92173
|
+
const poll = usePollServerComponent(props.uid, props.component.loop_instance_uid, extras);
|
|
91519
92174
|
const [componentPollingInterval] = useVariable(props.polling_interval ?? null);
|
|
91520
92175
|
const resolvedKwargPollingIntervals = useResolveDynamicKwargPollingIntervals(props.dynamic_kwargs);
|
|
91521
|
-
|
|
92176
|
+
const pollingInterval = (0, react$3.useMemo)(() => computePollingInterval(resolvedKwargPollingIntervals, componentPollingInterval), [resolvedKwargPollingIntervals, componentPollingInterval]);
|
|
92177
|
+
usePolling(getServerComponentRequestKey(props.uid, props.component.loop_instance_uid, extras), pollingInterval, poll);
|
|
91522
92178
|
if (component === null) return null;
|
|
91523
92179
|
if (isRawString(component)) return /* @__PURE__ */ React.createElement(React.Fragment, null, component.props.content);
|
|
91524
92180
|
if (isInvalidComponent(component)) return /* @__PURE__ */ React.createElement(ErrorDisplay$1, {
|
|
@@ -92289,24 +92945,49 @@ ${String(error)}`;
|
|
|
92289
92945
|
* @param signal AbortSignal to abort the generator
|
|
92290
92946
|
*/
|
|
92291
92947
|
async function* ndjson(response, signal) {
|
|
92948
|
+
if (!response.body) throw new Error("Route response body is missing");
|
|
92292
92949
|
const reader = response.body.getReader();
|
|
92293
92950
|
const newline = /\r?\n/;
|
|
92294
92951
|
const decoder = new TextDecoder();
|
|
92295
92952
|
let buffer = "";
|
|
92296
|
-
|
|
92297
|
-
|
|
92298
|
-
|
|
92299
|
-
|
|
92300
|
-
|
|
92301
|
-
|
|
92953
|
+
let cancelPromise;
|
|
92954
|
+
const abortError = () => new DOMException("The operation was aborted", "AbortError");
|
|
92955
|
+
const cancel = (reason) => {
|
|
92956
|
+
cancelPromise ??= reader.cancel(reason).catch(() => void 0);
|
|
92957
|
+
return cancelPromise;
|
|
92958
|
+
};
|
|
92959
|
+
const abort = () => {
|
|
92960
|
+
cancel(signal?.reason ?? abortError());
|
|
92961
|
+
};
|
|
92962
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
92963
|
+
try {
|
|
92964
|
+
while (true) {
|
|
92965
|
+
if (signal?.aborted) throw abortError();
|
|
92966
|
+
const { done, value } = await reader.read();
|
|
92967
|
+
if (signal?.aborted) throw abortError();
|
|
92968
|
+
if (done) {
|
|
92969
|
+
if (buffer.length > 0) yield JSON.parse(buffer);
|
|
92970
|
+
return;
|
|
92971
|
+
}
|
|
92972
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
92973
|
+
buffer += chunk;
|
|
92974
|
+
const parts = buffer.split(newline);
|
|
92975
|
+
buffer = parts.pop();
|
|
92976
|
+
for (const part of parts) yield JSON.parse(part);
|
|
92302
92977
|
}
|
|
92303
|
-
|
|
92304
|
-
|
|
92305
|
-
|
|
92306
|
-
|
|
92307
|
-
|
|
92978
|
+
} catch (error) {
|
|
92979
|
+
await cancel(error);
|
|
92980
|
+
throw error;
|
|
92981
|
+
} finally {
|
|
92982
|
+
signal?.removeEventListener("abort", abort);
|
|
92983
|
+
reader.releaseLock();
|
|
92308
92984
|
}
|
|
92309
92985
|
}
|
|
92986
|
+
function rejectPending(handle, error) {
|
|
92987
|
+
if (handle.status !== "pending") return;
|
|
92988
|
+
handle.getValue().catch(() => void 0);
|
|
92989
|
+
handle.reject(error);
|
|
92990
|
+
}
|
|
92310
92991
|
/**
|
|
92311
92992
|
* Fetch route data from the server.
|
|
92312
92993
|
*
|
|
@@ -92394,8 +93075,6 @@ ${String(error)}`;
|
|
|
92394
93075
|
if (!response.ok) throw new LoaderError((await response.json()).detail);
|
|
92395
93076
|
const template = deferred();
|
|
92396
93077
|
const onLoadActions = deferred();
|
|
92397
|
-
const resolvedDvs = /* @__PURE__ */ new Set();
|
|
92398
|
-
const resolvedPyComponents = /* @__PURE__ */ new Set();
|
|
92399
93078
|
queueMicrotask(async () => {
|
|
92400
93079
|
try {
|
|
92401
93080
|
for await (const data of ndjson(response, signal)) {
|
|
@@ -92405,20 +93084,14 @@ ${String(error)}`;
|
|
|
92405
93084
|
template.resolve(component);
|
|
92406
93085
|
}
|
|
92407
93086
|
if (chunk.type === "actions") onLoadActions.resolve(actions.flatMap((a) => isAnnotatedAction(a) ? chunk.actions[a.uid] : a));
|
|
92408
|
-
if (chunk.type === "derived_variable")
|
|
92409
|
-
|
|
92410
|
-
resolvedDvs.add(chunk.uid);
|
|
92411
|
-
}
|
|
92412
|
-
if (chunk.type === "py_component") {
|
|
92413
|
-
pyHandlesByUid[chunk.uid]?.handle.resolve(chunk.result);
|
|
92414
|
-
resolvedPyComponents.add(chunk.uid);
|
|
92415
|
-
}
|
|
93087
|
+
if (chunk.type === "derived_variable") dvHandlesByUid[chunk.uid]?.handle.resolve(chunk.result);
|
|
93088
|
+
if (chunk.type === "py_component") pyHandlesByUid[chunk.uid]?.handle.resolve(chunk.result);
|
|
92416
93089
|
}
|
|
92417
93090
|
} catch (e) {
|
|
92418
|
-
template
|
|
92419
|
-
onLoadActions
|
|
92420
|
-
for (const
|
|
92421
|
-
for (const
|
|
93091
|
+
rejectPending(template, e);
|
|
93092
|
+
rejectPending(onLoadActions, e);
|
|
93093
|
+
for (const handle of Object.values(dvHandlesByUid)) rejectPending(handle.handle, e);
|
|
93094
|
+
for (const handle of Object.values(pyHandlesByUid)) rejectPending(handle.handle, e);
|
|
92422
93095
|
}
|
|
92423
93096
|
});
|
|
92424
93097
|
const [templateValue, onLoadActionsValue] = await Promise.all([template.getValue(), onLoadActions.getValue()]);
|
|
@@ -92951,7 +93624,7 @@ ${String(error)}`;
|
|
|
92951
93624
|
useStreamSubscription((0, react$3.useMemo)(() => findStreamVariables(variable).map((s) => s.uid), [variable.uid]), extras);
|
|
92952
93625
|
if (isDerivedVariable(variable)) {
|
|
92953
93626
|
const [pollingInterval] = useVariable(variable.polling_interval ?? null, { suspend: false });
|
|
92954
|
-
const selectorLoadable = Recoil_index_28(useDerivedVariable(variable, wsClient, taskContext, extras, pollingInterval ?? void 0));
|
|
93627
|
+
const selectorLoadable = Recoil_index_28(useDerivedVariable(variable, wsClient, taskContext, extras, pollingInterval ?? void 0, variablesContext?.pollScope));
|
|
92955
93628
|
(0, react$3.useEffect)(() => {
|
|
92956
93629
|
if (selectorLoadable.state !== "loading") bus.publish("DERIVED_VARIABLE_LOADED", {
|
|
92957
93630
|
variable,
|
|
@@ -92962,7 +93635,7 @@ ${String(error)}`;
|
|
|
92962
93635
|
}
|
|
92963
93636
|
if (isSwitchVariable(variable)) return [useSwitchVariable(variable), warnUpdateOnDerivedState];
|
|
92964
93637
|
if (isStateVariable(variable)) {
|
|
92965
|
-
const parentLoadable = Recoil_index_28(useDerivedVariable(variable.parent_variable, wsClient, taskContext, extras));
|
|
93638
|
+
const parentLoadable = Recoil_index_28(useDerivedVariable(variable.parent_variable, wsClient, taskContext, extras, void 0, variablesContext?.pollScope));
|
|
92966
93639
|
let stateValue;
|
|
92967
93640
|
switch (variable.property_name) {
|
|
92968
93641
|
case "loading":
|
|
@@ -128015,8 +128688,10 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
|
|
|
128015
128688
|
exports.getOrRegisterDerivedVariable = getOrRegisterDerivedVariable;
|
|
128016
128689
|
exports.getOrRegisterDerivedVariableResult = getOrRegisterDerivedVariableResult;
|
|
128017
128690
|
exports.getOrRegisterDerivedVariableValue = getOrRegisterDerivedVariableValue;
|
|
128691
|
+
exports.getOrRegisterPollingTrigger = getOrRegisterPollingTrigger;
|
|
128018
128692
|
exports.getOrRegisterServerVariable = getOrRegisterServerVariable;
|
|
128019
128693
|
exports.getRegistryKey = getRegistryKey;
|
|
128694
|
+
exports.getServerComponentRequestKey = getServerComponentRequestKey;
|
|
128020
128695
|
exports.getSessionIdentifier = getSessionIdentifier;
|
|
128021
128696
|
exports.getTabularVariableValue = getTabularVariableValue;
|
|
128022
128697
|
exports.getVariableHookSignature = getVariableHookSignature;
|
|
@@ -128053,6 +128728,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
|
|
|
128053
128728
|
exports.onSessionIdChange = onSessionIdChange;
|
|
128054
128729
|
exports.parseLoginReferrer = parseLoginReferrer;
|
|
128055
128730
|
exports.parseRawCss = parseRawCss;
|
|
128731
|
+
exports.pollingTriggerRegistry = pollingTriggerRegistry;
|
|
128056
128732
|
exports.preloadDerivedValue = preloadDerivedValue;
|
|
128057
128733
|
exports.preloadDerivedVariable = preloadDerivedVariable;
|
|
128058
128734
|
exports.preloadServerComponent = preloadServerComponent;
|
|
@@ -128086,6 +128762,7 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
|
|
|
128086
128762
|
exports.useFetchTabularDerivedVariable = useFetchTabularDerivedVariable;
|
|
128087
128763
|
exports.useFetchTabularServerVariable = useFetchTabularServerVariable;
|
|
128088
128764
|
exports.useInterval = useInterval;
|
|
128765
|
+
exports.usePollServerComponent = usePollServerComponent;
|
|
128089
128766
|
exports.usePreloadRoute = usePreloadRoute;
|
|
128090
128767
|
exports.usePrevious = usePrevious;
|
|
128091
128768
|
exports.useRefreshSelector = useRefreshSelector;
|