@warp-drive/core 5.7.0-alpha.35 → 5.7.0-alpha.37
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/declarations/store/-private/new-core-tmp/request-state.d.ts +4 -0
- package/dist/index.js +1 -1
- package/dist/reactive.js +2 -2
- package/dist/{request-state-Un5kBcmR.js → request-subscription-CjHGziEX.js} +989 -981
- package/dist/store/-private.js +1 -1
- package/dist/types/-private.js +1 -1
- package/package.json +3 -3
|
@@ -3,10 +3,10 @@ import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from
|
|
|
3
3
|
import { deprecate, warn } from '@ember/debug';
|
|
4
4
|
import { setLogging, getRuntimeConfig } from './types/runtime.js';
|
|
5
5
|
import { getOrSetGlobal, peekTransient, setTransient } from './types/-private.js';
|
|
6
|
+
import { c as createSignal, a as consumeSignal, n as notifySignal, b as createMemo, A as ARRAY_SIGNAL, O as OBJECT_SIGNAL, d as willSyncFlushWatchers } from "./configure-C3x8YXzL.js";
|
|
6
7
|
import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_KEY_TYPE, DEBUG_CLIENT_ORIGINATED } from './types/identifier.js';
|
|
7
8
|
import { dasherize } from './utils/string.js';
|
|
8
9
|
import { S as SOURCE, C as Context, D as Destroy, a as Checkout, b as Commit } from "./symbols-sql1_mdx.js";
|
|
9
|
-
import { c as createSignal, a as consumeSignal, n as notifySignal, b as createMemo, A as ARRAY_SIGNAL, O as OBJECT_SIGNAL, d as willSyncFlushWatchers } from "./configure-C3x8YXzL.js";
|
|
10
10
|
import { g as getPromiseResult, s as setPromiseResult } from "./context-C_7OLieY.js";
|
|
11
11
|
import { RecordStore } from './types/symbols.js';
|
|
12
12
|
const INITIALIZER_PROTO = {
|
|
@@ -9451,84 +9451,76 @@ function getPromiseState(promise) {
|
|
|
9451
9451
|
}
|
|
9452
9452
|
return state;
|
|
9453
9453
|
}
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
...origDesc
|
|
9458
|
-
};
|
|
9459
|
-
for (let decorator of decorators) {
|
|
9460
|
-
desc = decorator(prototype, prop, desc) || desc;
|
|
9461
|
-
}
|
|
9462
|
-
if (desc.initializer !== void 0) {
|
|
9463
|
-
desc.value = desc.initializer ? desc.initializer.call(prototype) : void 0;
|
|
9464
|
-
desc.initializer = void 0;
|
|
9465
|
-
}
|
|
9466
|
-
Object.defineProperty(prototype, prop, desc);
|
|
9454
|
+
const RequestCache = new WeakMap();
|
|
9455
|
+
function isAbortError(error) {
|
|
9456
|
+
return error instanceof DOMException && error.name === 'AbortError';
|
|
9467
9457
|
}
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
function isNeverString(val) {
|
|
9471
|
-
return val;
|
|
9458
|
+
function upgradeLoadingState(state) {
|
|
9459
|
+
return state;
|
|
9472
9460
|
}
|
|
9461
|
+
async function watchStream(stream, loadingState) {
|
|
9462
|
+
const state = upgradeLoadingState(loadingState);
|
|
9463
|
+
const reader = stream.getReader();
|
|
9464
|
+
let bytesLoaded = 0;
|
|
9465
|
+
let shouldForward = state._stream !== null && state._stream.readable.locked;
|
|
9466
|
+
let isForwarding = shouldForward;
|
|
9467
|
+
let writer = state._stream?.writable.getWriter();
|
|
9468
|
+
const buffer = [];
|
|
9469
|
+
state._isPending = false;
|
|
9470
|
+
state._isStarted = true;
|
|
9471
|
+
state._startTime = performance.now();
|
|
9472
|
+
while (true) {
|
|
9473
|
+
const {
|
|
9474
|
+
value,
|
|
9475
|
+
done
|
|
9476
|
+
} = await reader.read();
|
|
9477
|
+
if (done) {
|
|
9478
|
+
break;
|
|
9479
|
+
}
|
|
9480
|
+
bytesLoaded += value.byteLength;
|
|
9481
|
+
state._bytesLoaded = bytesLoaded;
|
|
9482
|
+
state._lastPacketTime = performance.now();
|
|
9483
|
+
shouldForward = shouldForward || state._stream !== null && state._stream.readable.locked;
|
|
9484
|
+
if (shouldForward) {
|
|
9485
|
+
if (!isForwarding) {
|
|
9486
|
+
isForwarding = true;
|
|
9487
|
+
writer = state._stream.writable.getWriter();
|
|
9488
|
+
for (const item of buffer) {
|
|
9489
|
+
await writer.ready;
|
|
9490
|
+
await writer.write(item);
|
|
9491
|
+
}
|
|
9492
|
+
buffer.length = 0;
|
|
9493
|
+
}
|
|
9494
|
+
await writer.ready;
|
|
9495
|
+
await writer.write(value);
|
|
9496
|
+
} else {
|
|
9497
|
+
buffer.push(value);
|
|
9498
|
+
}
|
|
9499
|
+
}
|
|
9473
9500
|
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
-
|
|
9479
|
-
|
|
9480
|
-
|
|
9481
|
-
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9501
|
+
// if we are still forwarding, we need to close the writer
|
|
9502
|
+
if (isForwarding) {
|
|
9503
|
+
await writer.ready;
|
|
9504
|
+
await writer.close();
|
|
9505
|
+
} else if (state._stream) {
|
|
9506
|
+
// if we are not forwarding, we need to cancel the stream
|
|
9507
|
+
await state._stream.readable.cancel('The Stream Has Already Ended');
|
|
9508
|
+
state._stream = null;
|
|
9509
|
+
}
|
|
9510
|
+
const endTime = performance.now();
|
|
9511
|
+
state._endTime = endTime;
|
|
9512
|
+
state._isComplete = true;
|
|
9513
|
+
state._isStarted = false;
|
|
9514
|
+
}
|
|
9487
9515
|
|
|
9488
9516
|
/**
|
|
9489
|
-
*
|
|
9517
|
+
* Lazily consumes the stream of a request, providing a number of
|
|
9518
|
+
* reactive properties that can be used to build UIs that respond
|
|
9519
|
+
* to the progress of a request.
|
|
9490
9520
|
*
|
|
9491
9521
|
* @hideconstructor
|
|
9492
9522
|
*/
|
|
9493
|
-
class
|
|
9494
|
-
/**
|
|
9495
|
-
* Whether the browser reports that the network is online.
|
|
9496
|
-
*/
|
|
9497
|
-
|
|
9498
|
-
/**
|
|
9499
|
-
* Whether the browser reports that the tab is hidden.
|
|
9500
|
-
*/
|
|
9501
|
-
|
|
9502
|
-
/**
|
|
9503
|
-
* Whether the component is currently refreshing the request.
|
|
9504
|
-
*/
|
|
9505
|
-
|
|
9506
|
-
/**
|
|
9507
|
-
* The most recent blocking request that was made, typically
|
|
9508
|
-
* the result of a reload.
|
|
9509
|
-
*
|
|
9510
|
-
* This will never be the original request passed as an arg to
|
|
9511
|
-
* the component.
|
|
9512
|
-
*
|
|
9513
|
-
* @internal
|
|
9514
|
-
*/
|
|
9515
|
-
|
|
9516
|
-
/**
|
|
9517
|
-
* The most recent request that was made, typically due to either a
|
|
9518
|
-
* reload or a refresh.
|
|
9519
|
-
*
|
|
9520
|
-
* This will never be the original request passed as an arg to
|
|
9521
|
-
* the component.
|
|
9522
|
-
*
|
|
9523
|
-
* @internal
|
|
9524
|
-
*/
|
|
9525
|
-
|
|
9526
|
-
/**
|
|
9527
|
-
* The time at which the network was reported as offline.
|
|
9528
|
-
*
|
|
9529
|
-
* @internal
|
|
9530
|
-
*/
|
|
9531
|
-
|
|
9523
|
+
class RequestLoadingState {
|
|
9532
9524
|
/** @internal */
|
|
9533
9525
|
|
|
9534
9526
|
/** @internal */
|
|
@@ -9539,33 +9531,7 @@ class RequestSubscription {
|
|
|
9539
9531
|
|
|
9540
9532
|
/** @internal */
|
|
9541
9533
|
|
|
9542
|
-
/**
|
|
9543
|
-
* The event listener for network status changes,
|
|
9544
|
-
* cached to use the reference for removal.
|
|
9545
|
-
*
|
|
9546
|
-
* @internal
|
|
9547
|
-
*/
|
|
9548
|
-
|
|
9549
|
-
/**
|
|
9550
|
-
* The event listener for visibility status changes,
|
|
9551
|
-
* cached to use the reference for removal.
|
|
9552
|
-
*
|
|
9553
|
-
* @internal
|
|
9554
|
-
*/
|
|
9555
|
-
|
|
9556
|
-
/**
|
|
9557
|
-
* The last request passed as an arg to the component,
|
|
9558
|
-
* cached for comparison.
|
|
9559
|
-
*
|
|
9560
|
-
* @internal
|
|
9561
|
-
*/
|
|
9562
|
-
|
|
9563
|
-
/**
|
|
9564
|
-
* The last query passed as an arg to the component,
|
|
9565
|
-
* cached for comparison.
|
|
9566
|
-
*
|
|
9567
|
-
* @internal
|
|
9568
|
-
*/
|
|
9534
|
+
/** @internal */
|
|
9569
9535
|
|
|
9570
9536
|
/** @internal */
|
|
9571
9537
|
|
|
@@ -9573,997 +9539,1039 @@ class RequestSubscription {
|
|
|
9573
9539
|
|
|
9574
9540
|
/** @internal */
|
|
9575
9541
|
|
|
9576
|
-
/**
|
|
9577
|
-
* The Store this subscription subscribes to or the RequestManager
|
|
9578
|
-
* which issues this request.
|
|
9579
|
-
*/
|
|
9542
|
+
/** @internal */
|
|
9580
9543
|
|
|
9581
|
-
/**
|
|
9582
|
-
* The Store or RequestManager that the last subscription is attached to.
|
|
9583
|
-
*
|
|
9584
|
-
* This differs from 'store' because a <Request /> may be passed a
|
|
9585
|
-
* request originating from a different store than the <Request />
|
|
9586
|
-
* component would use if it were to issue the request itself.
|
|
9587
|
-
*
|
|
9588
|
-
* @internal
|
|
9589
|
-
*/
|
|
9590
|
-
_requester;
|
|
9591
|
-
constructor(store, args) {
|
|
9592
|
-
this._args = args;
|
|
9593
|
-
this.store = store;
|
|
9594
|
-
this._subscribedTo = null;
|
|
9595
|
-
this._subscription = null;
|
|
9596
|
-
this._intervalStart = null;
|
|
9597
|
-
this._invalidated = false;
|
|
9598
|
-
this._nextInterval = null;
|
|
9599
|
-
this._requester = null;
|
|
9600
|
-
this.isDestroyed = false;
|
|
9601
|
-
this[DISPOSE] = _DISPOSE;
|
|
9602
|
-
this._installListeners();
|
|
9603
|
-
void this._beginPolling();
|
|
9604
|
-
}
|
|
9544
|
+
/** @internal */
|
|
9605
9545
|
|
|
9606
|
-
/**
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9546
|
+
/** @internal */
|
|
9547
|
+
_stream = null;
|
|
9548
|
+
/** @internal */
|
|
9549
|
+
_future;
|
|
9550
|
+
/** @internal */
|
|
9551
|
+
_triggered = false;
|
|
9552
|
+
/** @internal */
|
|
9553
|
+
_trigger() {
|
|
9554
|
+
if (this._triggered) {
|
|
9555
|
+
return;
|
|
9556
|
+
}
|
|
9557
|
+
this._triggered = true;
|
|
9558
|
+
const future = this._future;
|
|
9559
|
+
const promise = future.getStream();
|
|
9560
|
+
if (promise.sizeHint) {
|
|
9561
|
+
this._sizeHint = promise.sizeHint;
|
|
9562
|
+
}
|
|
9563
|
+
this.promise = promise.then(stream => {
|
|
9564
|
+
if (!stream) {
|
|
9565
|
+
this._isPending = false;
|
|
9566
|
+
this._isComplete = true;
|
|
9567
|
+
return;
|
|
9614
9568
|
}
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
|
|
9569
|
+
return watchStream(stream, this);
|
|
9570
|
+
}, error => {
|
|
9571
|
+
this._isPending = false;
|
|
9572
|
+
this._isStarted = false;
|
|
9573
|
+
if (isAbortError(error)) {
|
|
9574
|
+
this._isCancelled = true;
|
|
9575
|
+
this._isComplete = true;
|
|
9620
9576
|
}
|
|
9621
|
-
|
|
9577
|
+
this._isErrored = true;
|
|
9578
|
+
this._error = error;
|
|
9579
|
+
});
|
|
9622
9580
|
}
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
} = this._args;
|
|
9628
|
-
return Boolean(!request && !query);
|
|
9581
|
+
promise = null;
|
|
9582
|
+
get isPending() {
|
|
9583
|
+
this._trigger();
|
|
9584
|
+
return this._isPending;
|
|
9629
9585
|
}
|
|
9630
|
-
|
|
9631
|
-
|
|
9586
|
+
get sizeHint() {
|
|
9587
|
+
this._trigger();
|
|
9588
|
+
return this._sizeHint;
|
|
9632
9589
|
}
|
|
9633
|
-
get
|
|
9634
|
-
|
|
9635
|
-
|
|
9636
|
-
|
|
9637
|
-
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
} else if (typeof autorefresh === 'string') {
|
|
9641
|
-
types = autorefresh.split(',');
|
|
9642
|
-
} else {
|
|
9643
|
-
types = [];
|
|
9590
|
+
get stream() {
|
|
9591
|
+
this._trigger();
|
|
9592
|
+
if (!this._stream) {
|
|
9593
|
+
if (this._isComplete || this._isCancelled || this._isErrored) {
|
|
9594
|
+
return null;
|
|
9595
|
+
}
|
|
9596
|
+
this._stream = new TransformStream();
|
|
9644
9597
|
}
|
|
9645
|
-
return
|
|
9598
|
+
return this._stream.readable;
|
|
9646
9599
|
}
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
// react to changes in the autorefreshThreshold
|
|
9651
|
-
// or autorefresh args.
|
|
9652
|
-
//
|
|
9653
|
-
// if we need to react to those changes, we can
|
|
9654
|
-
// use a modifier or internal component or some
|
|
9655
|
-
// such to trigger a re-run of this function.
|
|
9656
|
-
/** @internal */
|
|
9657
|
-
static {
|
|
9658
|
-
decorateMethodV2(this.prototype, "autorefreshTypes", [memoized]);
|
|
9600
|
+
get isStarted() {
|
|
9601
|
+
this._trigger();
|
|
9602
|
+
return this._isStarted;
|
|
9659
9603
|
}
|
|
9660
|
-
|
|
9661
|
-
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
this.
|
|
9674
|
-
|
|
9675
|
-
|
|
9604
|
+
get bytesLoaded() {
|
|
9605
|
+
this._trigger();
|
|
9606
|
+
return this._bytesLoaded;
|
|
9607
|
+
}
|
|
9608
|
+
get startTime() {
|
|
9609
|
+
this._trigger();
|
|
9610
|
+
return this._startTime;
|
|
9611
|
+
}
|
|
9612
|
+
get endTime() {
|
|
9613
|
+
this._trigger();
|
|
9614
|
+
return this._endTime;
|
|
9615
|
+
}
|
|
9616
|
+
get lastPacketTime() {
|
|
9617
|
+
this._trigger();
|
|
9618
|
+
return this._lastPacketTime;
|
|
9619
|
+
}
|
|
9620
|
+
get isComplete() {
|
|
9621
|
+
this._trigger();
|
|
9622
|
+
return this._isComplete;
|
|
9623
|
+
}
|
|
9624
|
+
get isCancelled() {
|
|
9625
|
+
this._trigger();
|
|
9626
|
+
return this._isCancelled;
|
|
9627
|
+
}
|
|
9628
|
+
get isErrored() {
|
|
9629
|
+
this._trigger();
|
|
9630
|
+
return this._isErrored;
|
|
9631
|
+
}
|
|
9632
|
+
get error() {
|
|
9633
|
+
this._trigger();
|
|
9634
|
+
return this._error;
|
|
9635
|
+
}
|
|
9636
|
+
get elapsedTime() {
|
|
9637
|
+
return (this.endTime || this.lastPacketTime) - this.startTime;
|
|
9638
|
+
}
|
|
9639
|
+
get completedRatio() {
|
|
9640
|
+
return this.sizeHint ? this.bytesLoaded / this.sizeHint : 0;
|
|
9641
|
+
}
|
|
9642
|
+
get remainingRatio() {
|
|
9643
|
+
return 1 - this.completedRatio;
|
|
9644
|
+
}
|
|
9645
|
+
get duration() {
|
|
9646
|
+
return this.endTime - this.startTime;
|
|
9647
|
+
}
|
|
9648
|
+
get speed() {
|
|
9649
|
+
// bytes per second
|
|
9650
|
+
return this.bytesLoaded / (this.elapsedTime / 1000);
|
|
9651
|
+
}
|
|
9652
|
+
constructor(future) {
|
|
9653
|
+
this._future = future;
|
|
9654
|
+
}
|
|
9655
|
+
abort = () => {
|
|
9656
|
+
this._future.abort();
|
|
9657
|
+
};
|
|
9658
|
+
}
|
|
9659
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isPending', true);
|
|
9660
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isStarted', false);
|
|
9661
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isComplete', false);
|
|
9662
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isCancelled', false);
|
|
9663
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isErrored', false);
|
|
9664
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_error', null);
|
|
9665
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_sizeHint', 0);
|
|
9666
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_bytesLoaded', 0);
|
|
9667
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_startTime', 0);
|
|
9668
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_endTime', 0);
|
|
9669
|
+
defineNonEnumerableSignal(RequestLoadingState.prototype, '_lastPacketTime', 0);
|
|
9676
9670
|
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
}
|
|
9685
|
-
if (this.isDestroyed) {
|
|
9686
|
-
return;
|
|
9687
|
-
}
|
|
9688
|
-
}
|
|
9671
|
+
/**
|
|
9672
|
+
* The state of a request in the "pending"
|
|
9673
|
+
* state. This is the default initial state.
|
|
9674
|
+
*
|
|
9675
|
+
* Extends the {@link PendingPromise} interface.
|
|
9676
|
+
*
|
|
9677
|
+
*/
|
|
9689
9678
|
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9679
|
+
/**
|
|
9680
|
+
* The state of a request in the "fulfilled" state.
|
|
9681
|
+
* This is the state of a request that has resolved
|
|
9682
|
+
* successfully.
|
|
9683
|
+
*
|
|
9684
|
+
* Extends the {@link ResolvedPromise} interface.
|
|
9685
|
+
*
|
|
9686
|
+
*/
|
|
9687
|
+
|
|
9688
|
+
/**
|
|
9689
|
+
* The state of a request in the "rejected" state.
|
|
9690
|
+
* This is the state of a request that has rejected
|
|
9691
|
+
* with an error.
|
|
9692
|
+
*
|
|
9693
|
+
* Extends the {@link RejectedPromise} interface.
|
|
9694
|
+
*
|
|
9695
|
+
*/
|
|
9696
|
+
|
|
9697
|
+
/**
|
|
9698
|
+
* The state of a request in the "cancelled" state.
|
|
9699
|
+
* This is the state of a promise that has been
|
|
9700
|
+
* cancelled.
|
|
9701
|
+
*
|
|
9702
|
+
*/
|
|
9703
|
+
|
|
9704
|
+
/**
|
|
9705
|
+
* RequestState extends the concept of {@link PromiseState} to provide a reactive
|
|
9706
|
+
* wrapper for a request {@link Future} which allows you write declarative code
|
|
9707
|
+
* around a Future's control flow.
|
|
9708
|
+
*
|
|
9709
|
+
* It is useful in both Template and JavaScript contexts, allowing you
|
|
9710
|
+
* to quickly derive behaviors and data from pending, error and success
|
|
9711
|
+
* states.
|
|
9712
|
+
*
|
|
9713
|
+
* The key difference between a {@link Promise} and a Future is that Futures provide
|
|
9714
|
+
* access to a {@link ReadableStream | stream} of their content, the {@link RequestKey} of the request (if any)
|
|
9715
|
+
* as well as the ability to attempt to {@link Future.abort | abort} the request.
|
|
9716
|
+
*
|
|
9717
|
+
* ```ts
|
|
9718
|
+
* interface Future<T> extends Promise<T>> {
|
|
9719
|
+
* getStream(): Promise<ReadableStream>;
|
|
9720
|
+
* abort(): void;
|
|
9721
|
+
* lid: RequestKey | null;
|
|
9722
|
+
* }
|
|
9723
|
+
* ```
|
|
9724
|
+
*
|
|
9725
|
+
* These additional APIs allow us to craft even richer state experiences.
|
|
9726
|
+
*
|
|
9727
|
+
* To get the state of a request, use {@link getRequestState}.
|
|
9728
|
+
*
|
|
9729
|
+
* See also:
|
|
9730
|
+
* - {@link PendingRequest}
|
|
9731
|
+
* - {@link ResolvedRequest}
|
|
9732
|
+
* - {@link RejectedRequest}
|
|
9733
|
+
* - {@link CancelledRequest}
|
|
9734
|
+
*
|
|
9735
|
+
*/
|
|
9736
|
+
|
|
9737
|
+
const RequestStateProto = {};
|
|
9738
|
+
function performRefresh(requester, request, isReload) {
|
|
9739
|
+
const req = Object.assign({}, request);
|
|
9740
|
+
const cacheOptions = Object.assign({}, req.cacheOptions);
|
|
9741
|
+
if (isReload) {
|
|
9742
|
+
// force direct to network
|
|
9743
|
+
cacheOptions.reload = true;
|
|
9744
|
+
} else if (isReload === false) {
|
|
9745
|
+
// delete reload to ensure we use backgroundReload / policy
|
|
9746
|
+
delete cacheOptions.reload;
|
|
9747
|
+
cacheOptions.backgroundReload = true;
|
|
9748
|
+
} else {
|
|
9749
|
+
// delete props to ensure we use the policy
|
|
9750
|
+
delete cacheOptions.backgroundReload;
|
|
9751
|
+
delete cacheOptions.reload;
|
|
9695
9752
|
}
|
|
9753
|
+
req.cacheOptions = cacheOptions;
|
|
9754
|
+
return requester.request(req);
|
|
9755
|
+
}
|
|
9696
9756
|
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9757
|
+
// TODO introduce a new mechanism for defining multiple properties
|
|
9758
|
+
// that share a common signal
|
|
9759
|
+
defineSignal(RequestStateProto, 'reason', null);
|
|
9760
|
+
defineSignal(RequestStateProto, 'value', null);
|
|
9761
|
+
defineSignal(RequestStateProto, 'result', null);
|
|
9762
|
+
defineSignal(RequestStateProto, 'error', null);
|
|
9763
|
+
defineSignal(RequestStateProto, 'status', 'pending');
|
|
9764
|
+
defineSignal(RequestStateProto, 'isPending', true);
|
|
9765
|
+
defineSignal(RequestStateProto, 'isLoading', true);
|
|
9766
|
+
defineSignal(RequestStateProto, 'isSuccess', false);
|
|
9767
|
+
defineSignal(RequestStateProto, 'isError', false);
|
|
9768
|
+
defineSignal(RequestStateProto, 'request', null);
|
|
9769
|
+
defineSignal(RequestStateProto, 'response', null);
|
|
9770
|
+
Object.defineProperty(RequestStateProto, 'isCancelled', {
|
|
9771
|
+
get() {
|
|
9772
|
+
return this.isError && isAbortError(this.reason);
|
|
9703
9773
|
}
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
return;
|
|
9774
|
+
});
|
|
9775
|
+
Object.defineProperty(RequestStateProto, 'loadingState', {
|
|
9776
|
+
get() {
|
|
9777
|
+
if (!this._loadingState) {
|
|
9778
|
+
this._loadingState = new RequestLoadingState(this._request);
|
|
9710
9779
|
}
|
|
9711
|
-
|
|
9780
|
+
return this._loadingState;
|
|
9781
|
+
}
|
|
9782
|
+
});
|
|
9783
|
+
function createRequestState(future) {
|
|
9784
|
+
const state = getPromiseResult(future);
|
|
9785
|
+
const promiseState = Object.create(RequestStateProto);
|
|
9786
|
+
promiseState._request = future;
|
|
9787
|
+
// @ts-expect-error - we still attach it for PendingState
|
|
9788
|
+
promiseState.reload = () => {
|
|
9789
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
9790
|
+
if (!test) {
|
|
9791
|
+
throw new Error(`Cannot reload a request that is still pending. Await or abort the original request first.`);
|
|
9792
|
+
}
|
|
9793
|
+
})(!promiseState.isPending) : {};
|
|
9794
|
+
return performRefresh(future.requester, promiseState.request, true);
|
|
9795
|
+
};
|
|
9712
9796
|
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9797
|
+
// @ts-expect-error - we still attach it for PendingState
|
|
9798
|
+
promiseState.refresh = (usePolicy = false) => {
|
|
9799
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
9800
|
+
if (!test) {
|
|
9801
|
+
throw new Error(`Cannot refresh a request that is still pending. Await or abort the original request first.`);
|
|
9802
|
+
}
|
|
9803
|
+
})(!promiseState.isPending) : {};
|
|
9804
|
+
return performRefresh(future.requester, promiseState.request, usePolicy === true ? null : false);
|
|
9805
|
+
};
|
|
9806
|
+
if (state) {
|
|
9807
|
+
if (state.isError) {
|
|
9808
|
+
promiseState.error = state.result;
|
|
9809
|
+
promiseState.reason = state.result;
|
|
9810
|
+
promiseState.status = 'rejected';
|
|
9811
|
+
promiseState.isError = true;
|
|
9812
|
+
promiseState.isPending = false;
|
|
9813
|
+
promiseState.isLoading = false;
|
|
9814
|
+
promiseState.request = state.result.request;
|
|
9815
|
+
promiseState.response = state.result.response;
|
|
9816
|
+
} else {
|
|
9817
|
+
promiseState.result = state.result.content;
|
|
9818
|
+
promiseState.value = state.result.content;
|
|
9819
|
+
promiseState.status = 'fulfilled';
|
|
9820
|
+
promiseState.isSuccess = true;
|
|
9821
|
+
promiseState.isPending = false;
|
|
9822
|
+
promiseState.isLoading = false;
|
|
9823
|
+
promiseState.request = state.result.request;
|
|
9824
|
+
promiseState.response = state.result.response;
|
|
9716
9825
|
}
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
const store = this._getRequester();
|
|
9723
|
-
this._requester = store;
|
|
9724
|
-
if (requestId && isStore(store)) {
|
|
9725
|
-
this._subscribedTo = requestId;
|
|
9726
|
-
this._subscription = store.notifications.subscribe(requestId, (_id, op) => {
|
|
9727
|
-
// ignore subscription events that occur while our own component's request
|
|
9728
|
-
// is occurring
|
|
9729
|
-
if (this._isUpdating) {
|
|
9730
|
-
return;
|
|
9731
|
-
}
|
|
9732
|
-
switch (op) {
|
|
9733
|
-
case 'invalidated':
|
|
9734
|
-
{
|
|
9735
|
-
// if we're subscribed to invalidations, we need to update
|
|
9736
|
-
if (this.autorefreshTypes.has('invalid')) {
|
|
9737
|
-
this._invalidated = true;
|
|
9738
|
-
this._maybeUpdate();
|
|
9739
|
-
}
|
|
9740
|
-
break;
|
|
9741
|
-
}
|
|
9742
|
-
case 'state':
|
|
9743
|
-
{
|
|
9744
|
-
const latest = store.requestManager._deduped.get(requestId);
|
|
9745
|
-
const priority = latest?.priority;
|
|
9746
|
-
const state = this.reqState;
|
|
9747
|
-
if (!priority) {
|
|
9748
|
-
// if there is no priority, we have completed whatever request
|
|
9749
|
-
// was occurring and so we are no longer refreshing (if we were)
|
|
9750
|
-
this.isRefreshing = false;
|
|
9751
|
-
} else if (priority.blocking && !state.isLoading) {
|
|
9752
|
-
// if we are blocking, there is an active request for this identity
|
|
9753
|
-
// that MUST be fulfilled from network (not cache).
|
|
9754
|
-
// Thus this is not "refreshing" because we should clear out and
|
|
9755
|
-
// block on this request.
|
|
9756
|
-
//
|
|
9757
|
-
// we receive state notifications when either a request initiates
|
|
9758
|
-
// or completes.
|
|
9759
|
-
//
|
|
9760
|
-
// In the completes case: we may receive the state notification
|
|
9761
|
-
// slightly before the request is finalized because the NotificationManager
|
|
9762
|
-
// may sync flush it (and thus deliver it before the microtask completes)
|
|
9763
|
-
//
|
|
9764
|
-
// In the initiates case: we aren't supposed to receive one unless there
|
|
9765
|
-
// is no other request in flight for this identity.
|
|
9766
|
-
//
|
|
9767
|
-
// However, there is a race condition here where the completed
|
|
9768
|
-
// notification can trigger an update that generates a new request
|
|
9769
|
-
// thus giving us an initiated notification before the older request
|
|
9770
|
-
// finalizes.
|
|
9771
|
-
//
|
|
9772
|
-
// When this occurs, if the triggered update happens to have caused
|
|
9773
|
-
// a new request to be made for the same identity AND that request
|
|
9774
|
-
// is the one passed into this component as the @request arg, then
|
|
9775
|
-
// getRequestState will return the state of the new request.
|
|
9776
|
-
// We can detect this by checking if the request state is "loading"
|
|
9777
|
-
// as outside of this case we would have a completed request.
|
|
9778
|
-
//
|
|
9779
|
-
// That is the reason for the `&& !state.isLoading` check above.
|
|
9780
|
-
|
|
9781
|
-
// TODO should we just treat this as refreshing?
|
|
9782
|
-
this.isRefreshing = false;
|
|
9783
|
-
this._maybeUpdate('policy', true);
|
|
9784
|
-
} else {
|
|
9785
|
-
this.isRefreshing = true;
|
|
9786
|
-
}
|
|
9787
|
-
}
|
|
9788
|
-
}
|
|
9826
|
+
} else {
|
|
9827
|
+
void future.then(result => {
|
|
9828
|
+
setPromiseResult(future, {
|
|
9829
|
+
isError: false,
|
|
9830
|
+
result
|
|
9789
9831
|
});
|
|
9790
|
-
|
|
9832
|
+
promiseState.result = result.content;
|
|
9833
|
+
promiseState.value = result.content;
|
|
9834
|
+
promiseState.status = 'fulfilled';
|
|
9835
|
+
promiseState.isSuccess = true;
|
|
9836
|
+
promiseState.isPending = false;
|
|
9837
|
+
promiseState.isLoading = false;
|
|
9838
|
+
promiseState.request = result.request;
|
|
9839
|
+
promiseState.response = result.response;
|
|
9840
|
+
}, error => {
|
|
9841
|
+
setPromiseResult(future, {
|
|
9842
|
+
isError: true,
|
|
9843
|
+
result: error
|
|
9844
|
+
});
|
|
9845
|
+
promiseState.error = error;
|
|
9846
|
+
promiseState.reason = error;
|
|
9847
|
+
promiseState.status = 'rejected';
|
|
9848
|
+
promiseState.isError = true;
|
|
9849
|
+
promiseState.isPending = false;
|
|
9850
|
+
promiseState.isLoading = false;
|
|
9851
|
+
promiseState.request = error.request;
|
|
9852
|
+
promiseState.response = error.response;
|
|
9853
|
+
});
|
|
9854
|
+
}
|
|
9855
|
+
return promiseState;
|
|
9856
|
+
}
|
|
9857
|
+
|
|
9858
|
+
/**
|
|
9859
|
+
* `getRequestState` can be used in both JavaScript and Template contexts.
|
|
9860
|
+
*
|
|
9861
|
+
* ```ts
|
|
9862
|
+
* import { getRequestState } from '@warp-drive/ember';
|
|
9863
|
+
*
|
|
9864
|
+
* const state = getRequestState(future);
|
|
9865
|
+
* ```
|
|
9866
|
+
*
|
|
9867
|
+
* For instance, we could write a getter on a component that updates whenever
|
|
9868
|
+
* the request state advances or the future changes, by combining the function
|
|
9869
|
+
* with the use of `@cached`
|
|
9870
|
+
*
|
|
9871
|
+
* ```ts
|
|
9872
|
+
* class Component {
|
|
9873
|
+
* @cached
|
|
9874
|
+
* get title() {
|
|
9875
|
+
* const state = getRequestState(this.args.request);
|
|
9876
|
+
* if (state.isPending) {
|
|
9877
|
+
* return 'loading...';
|
|
9878
|
+
* }
|
|
9879
|
+
* if (state.isError) { return null; }
|
|
9880
|
+
* return state.result.title;
|
|
9881
|
+
* }
|
|
9882
|
+
* }
|
|
9883
|
+
* ```
|
|
9884
|
+
*
|
|
9885
|
+
* Or in a template as a helper:
|
|
9886
|
+
*
|
|
9887
|
+
* ```gjs
|
|
9888
|
+
* import { getRequestState } from '@warp-drive/ember';
|
|
9889
|
+
*
|
|
9890
|
+
* <template>
|
|
9891
|
+
* {{#let (getRequestState @request) as |state|}}
|
|
9892
|
+
* {{#if state.isPending}}
|
|
9893
|
+
* <Spinner />
|
|
9894
|
+
* {{else if state.isError}}
|
|
9895
|
+
* <ErrorForm @error={{state.error}} />
|
|
9896
|
+
* {{else}}
|
|
9897
|
+
* <h1>{{state.result.title}}</h1>
|
|
9898
|
+
* {{/if}}
|
|
9899
|
+
* {{/let}}
|
|
9900
|
+
* </template>
|
|
9901
|
+
* ```
|
|
9902
|
+
*
|
|
9903
|
+
* If looking to use in a template, consider also the `<Request />` component
|
|
9904
|
+
* which offers a numbe of additional capabilities for requests *beyond* what
|
|
9905
|
+
* `RequestState` provides.
|
|
9906
|
+
*
|
|
9907
|
+
*/
|
|
9908
|
+
function getRequestState(future) {
|
|
9909
|
+
let state = RequestCache.get(future);
|
|
9910
|
+
if (!state) {
|
|
9911
|
+
state = createRequestState(future);
|
|
9912
|
+
RequestCache.set(future, state);
|
|
9913
|
+
}
|
|
9914
|
+
return state;
|
|
9915
|
+
}
|
|
9916
|
+
function decorateMethodV2(prototype, prop, decorators) {
|
|
9917
|
+
const origDesc = Object.getOwnPropertyDescriptor(prototype, prop);
|
|
9918
|
+
let desc = {
|
|
9919
|
+
...origDesc
|
|
9920
|
+
};
|
|
9921
|
+
for (let decorator of decorators) {
|
|
9922
|
+
desc = decorator(prototype, prop, desc) || desc;
|
|
9923
|
+
}
|
|
9924
|
+
if (desc.initializer !== void 0) {
|
|
9925
|
+
desc.value = desc.initializer ? desc.initializer.call(prototype) : void 0;
|
|
9926
|
+
desc.initializer = void 0;
|
|
9791
9927
|
}
|
|
9928
|
+
Object.defineProperty(prototype, prop, desc);
|
|
9929
|
+
}
|
|
9930
|
+
const DEFAULT_DEADLINE = 30_000;
|
|
9931
|
+
const DISPOSE = Symbol.dispose || Symbol.for('dispose');
|
|
9932
|
+
function isNeverString(val) {
|
|
9933
|
+
return val;
|
|
9934
|
+
}
|
|
9935
|
+
|
|
9936
|
+
/**
|
|
9937
|
+
* Utilities to assist in recovering from the error.
|
|
9938
|
+
*/
|
|
9939
|
+
|
|
9940
|
+
/** @deprecated use {@link RecoveryFeatures} */
|
|
9941
|
+
|
|
9942
|
+
/**
|
|
9943
|
+
* Utilities for keeping the request fresh
|
|
9944
|
+
*/
|
|
9945
|
+
|
|
9946
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9947
|
+
|
|
9948
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9949
|
+
|
|
9950
|
+
/**
|
|
9951
|
+
* A reactive class
|
|
9952
|
+
*
|
|
9953
|
+
* @hideconstructor
|
|
9954
|
+
*/
|
|
9955
|
+
class RequestSubscription {
|
|
9956
|
+
/**
|
|
9957
|
+
* Whether the browser reports that the network is online.
|
|
9958
|
+
*/
|
|
9792
9959
|
|
|
9793
9960
|
/**
|
|
9794
|
-
*
|
|
9961
|
+
* Whether the browser reports that the tab is hidden.
|
|
9795
9962
|
*/
|
|
9796
|
-
_removeSubscriptions() {
|
|
9797
|
-
const store = this._requester;
|
|
9798
|
-
if (this._subscription && store && isStore(store)) {
|
|
9799
|
-
store.notifications.unsubscribe(this._subscription);
|
|
9800
|
-
this._subscribedTo = null;
|
|
9801
|
-
this._subscription = null;
|
|
9802
|
-
this._requester = null;
|
|
9803
|
-
}
|
|
9804
|
-
}
|
|
9805
9963
|
|
|
9806
9964
|
/**
|
|
9807
|
-
*
|
|
9808
|
-
|
|
9965
|
+
* Whether the component is currently refreshing the request.
|
|
9966
|
+
*/
|
|
9967
|
+
|
|
9968
|
+
/**
|
|
9969
|
+
* The most recent blocking request that was made, typically
|
|
9970
|
+
* the result of a reload.
|
|
9971
|
+
*
|
|
9972
|
+
* This will never be the original request passed as an arg to
|
|
9973
|
+
* the component.
|
|
9809
9974
|
*
|
|
9810
9975
|
* @internal
|
|
9811
9976
|
*/
|
|
9812
|
-
_installListeners() {
|
|
9813
|
-
if (typeof window === 'undefined') {
|
|
9814
|
-
return;
|
|
9815
|
-
}
|
|
9816
|
-
this.isOnline = window.navigator.onLine;
|
|
9817
|
-
this._unavailableStart = this.isOnline ? null : Date.now();
|
|
9818
|
-
this.isHidden = document.visibilityState === 'hidden';
|
|
9819
|
-
this._onlineChanged = event => {
|
|
9820
|
-
this.isOnline = event.type === 'online';
|
|
9821
|
-
if (event.type === 'offline' && this._unavailableStart === null) {
|
|
9822
|
-
this._unavailableStart = Date.now();
|
|
9823
|
-
}
|
|
9824
|
-
this._maybeUpdate();
|
|
9825
|
-
};
|
|
9826
|
-
this._backgroundChanged = () => {
|
|
9827
|
-
const isHidden = document.visibilityState === 'hidden';
|
|
9828
|
-
this.isHidden = isHidden;
|
|
9829
|
-
if (isHidden && this._unavailableStart === null) {
|
|
9830
|
-
this._unavailableStart = Date.now();
|
|
9831
|
-
}
|
|
9832
|
-
this._maybeUpdate();
|
|
9833
|
-
};
|
|
9834
|
-
window.addEventListener('online', this._onlineChanged, {
|
|
9835
|
-
passive: true,
|
|
9836
|
-
capture: true
|
|
9837
|
-
});
|
|
9838
|
-
window.addEventListener('offline', this._onlineChanged, {
|
|
9839
|
-
passive: true,
|
|
9840
|
-
capture: true
|
|
9841
|
-
});
|
|
9842
|
-
document.addEventListener('visibilitychange', this._backgroundChanged, {
|
|
9843
|
-
passive: true,
|
|
9844
|
-
capture: true
|
|
9845
|
-
});
|
|
9846
|
-
}
|
|
9847
9977
|
|
|
9848
9978
|
/**
|
|
9849
|
-
*
|
|
9850
|
-
*
|
|
9979
|
+
* The most recent request that was made, typically due to either a
|
|
9980
|
+
* reload or a refresh.
|
|
9851
9981
|
*
|
|
9852
|
-
*
|
|
9982
|
+
* This will never be the original request passed as an arg to
|
|
9983
|
+
* the component.
|
|
9853
9984
|
*
|
|
9854
|
-
*
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9985
|
+
* @internal
|
|
9986
|
+
*/
|
|
9987
|
+
|
|
9988
|
+
/**
|
|
9989
|
+
* The time at which the network was reported as offline.
|
|
9858
9990
|
*
|
|
9859
9991
|
* @internal
|
|
9860
9992
|
*/
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
const canAttempt = Boolean(this.isOnline && !this.isHidden && (mode || this.autorefreshTypes.size));
|
|
9872
|
-
if (!canAttempt) {
|
|
9873
|
-
if (!silent && mode && mode !== '_invalidated') {
|
|
9874
|
-
throw new Error(`Reload not available: the network is not online or the tab is hidden`);
|
|
9875
|
-
}
|
|
9876
|
-
return;
|
|
9877
|
-
}
|
|
9878
|
-
const {
|
|
9879
|
-
autorefreshTypes
|
|
9880
|
-
} = this;
|
|
9881
|
-
let shouldAttempt = this._invalidated || Boolean(mode);
|
|
9882
|
-
if (!shouldAttempt && autorefreshTypes.has('online')) {
|
|
9883
|
-
const {
|
|
9884
|
-
_unavailableStart
|
|
9885
|
-
} = this;
|
|
9886
|
-
const {
|
|
9887
|
-
autorefreshThreshold
|
|
9888
|
-
} = this._args;
|
|
9889
|
-
const deadline = typeof autorefreshThreshold === 'number' ? autorefreshThreshold : DEFAULT_DEADLINE;
|
|
9890
|
-
shouldAttempt = Boolean(_unavailableStart && Date.now() - _unavailableStart > deadline);
|
|
9891
|
-
}
|
|
9892
|
-
if (!shouldAttempt && autorefreshTypes.has('interval')) {
|
|
9893
|
-
const {
|
|
9894
|
-
_intervalStart
|
|
9895
|
-
} = this;
|
|
9896
|
-
const {
|
|
9897
|
-
autorefreshThreshold
|
|
9898
|
-
} = this._args;
|
|
9899
|
-
if (_intervalStart && typeof autorefreshThreshold === 'number' && autorefreshThreshold > 0) {
|
|
9900
|
-
shouldAttempt = Boolean(Date.now() - _intervalStart >= autorefreshThreshold);
|
|
9901
|
-
}
|
|
9902
|
-
}
|
|
9903
|
-
this._unavailableStart = null;
|
|
9904
|
-
this._invalidated = false;
|
|
9905
|
-
if (shouldAttempt) {
|
|
9906
|
-
this._clearInterval();
|
|
9907
|
-
this._isUpdating = true;
|
|
9908
|
-
const realMode = mode === '_invalidated' ? null : mode;
|
|
9909
|
-
const val = realMode ?? this._args.autorefreshBehavior ?? 'policy';
|
|
9910
|
-
switch (val) {
|
|
9911
|
-
case 'reload':
|
|
9912
|
-
this._latestRequest = reqState.reload();
|
|
9913
|
-
break;
|
|
9914
|
-
case 'refresh':
|
|
9915
|
-
this._latestRequest = reqState.refresh();
|
|
9916
|
-
break;
|
|
9917
|
-
case 'policy':
|
|
9918
|
-
this._latestRequest = reqState.refresh(true);
|
|
9919
|
-
break;
|
|
9920
|
-
default:
|
|
9921
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
9922
|
-
{
|
|
9923
|
-
throw new Error(`Invalid ${mode ? 'update mode' : '@autorefreshBehavior'} for <Request />: ${isNeverString(val)}`);
|
|
9924
|
-
}
|
|
9925
|
-
})() : {};
|
|
9926
|
-
}
|
|
9927
|
-
if (val !== 'refresh') {
|
|
9928
|
-
this._localRequest = this._latestRequest;
|
|
9929
|
-
}
|
|
9930
|
-
void this._scheduleInterval();
|
|
9931
|
-
void this._latestRequest.finally(() => {
|
|
9932
|
-
this._isUpdating = false;
|
|
9933
|
-
});
|
|
9934
|
-
}
|
|
9935
|
-
}
|
|
9993
|
+
|
|
9994
|
+
/** @internal */
|
|
9995
|
+
|
|
9996
|
+
/** @internal */
|
|
9997
|
+
|
|
9998
|
+
/** @internal */
|
|
9999
|
+
|
|
10000
|
+
/** @internal */
|
|
10001
|
+
|
|
10002
|
+
/** @internal */
|
|
9936
10003
|
|
|
9937
10004
|
/**
|
|
10005
|
+
* The event listener for network status changes,
|
|
10006
|
+
* cached to use the reference for removal.
|
|
10007
|
+
*
|
|
9938
10008
|
* @internal
|
|
9939
10009
|
*/
|
|
9940
|
-
_getRequester() {
|
|
9941
|
-
// Note: we check for the requester's presence
|
|
9942
|
-
// as well as the request's presence because we may
|
|
9943
|
-
// be subscribed to a request issued by a store from an older
|
|
9944
|
-
// version of the library that didn't yet set requester.
|
|
9945
|
-
if (this._args.request?.requester) {
|
|
9946
|
-
return this._args.request.requester;
|
|
9947
|
-
}
|
|
9948
|
-
return this.store;
|
|
9949
|
-
}
|
|
9950
10010
|
|
|
9951
10011
|
/**
|
|
9952
|
-
*
|
|
10012
|
+
* The event listener for visibility status changes,
|
|
10013
|
+
* cached to use the reference for removal.
|
|
10014
|
+
*
|
|
10015
|
+
* @internal
|
|
10016
|
+
*/
|
|
10017
|
+
|
|
10018
|
+
/**
|
|
10019
|
+
* The last request passed as an arg to the component,
|
|
10020
|
+
* cached for comparison.
|
|
10021
|
+
*
|
|
10022
|
+
* @internal
|
|
9953
10023
|
*/
|
|
9954
|
-
retry = async () => {
|
|
9955
|
-
this._maybeUpdate('reload');
|
|
9956
|
-
await this._localRequest;
|
|
9957
|
-
};
|
|
9958
10024
|
|
|
9959
10025
|
/**
|
|
9960
|
-
*
|
|
10026
|
+
* The last query passed as an arg to the component,
|
|
10027
|
+
* cached for comparison.
|
|
10028
|
+
*
|
|
10029
|
+
* @internal
|
|
9961
10030
|
*/
|
|
9962
|
-
|
|
9963
|
-
|
|
9964
|
-
|
|
9965
|
-
|
|
10031
|
+
|
|
10032
|
+
/** @internal */
|
|
10033
|
+
|
|
10034
|
+
/** @internal */
|
|
10035
|
+
|
|
10036
|
+
/** @internal */
|
|
9966
10037
|
|
|
9967
10038
|
/**
|
|
9968
|
-
*
|
|
10039
|
+
* The Store this subscription subscribes to or the RequestManager
|
|
10040
|
+
* which issues this request.
|
|
9969
10041
|
*/
|
|
9970
|
-
get errorFeatures() {
|
|
9971
|
-
return {
|
|
9972
|
-
isHidden: this.isHidden,
|
|
9973
|
-
isOnline: this.isOnline,
|
|
9974
|
-
retry: this.retry
|
|
9975
|
-
};
|
|
9976
|
-
}
|
|
9977
10042
|
|
|
9978
10043
|
/**
|
|
9979
|
-
*
|
|
10044
|
+
* The Store or RequestManager that the last subscription is attached to.
|
|
10045
|
+
*
|
|
10046
|
+
* This differs from 'store' because a <Request /> may be passed a
|
|
10047
|
+
* request originating from a different store than the <Request />
|
|
10048
|
+
* component would use if it were to issue the request itself.
|
|
10049
|
+
*
|
|
10050
|
+
* @internal
|
|
9980
10051
|
*/
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
this._latestRequest?.abort();
|
|
9996
|
-
};
|
|
9997
|
-
}
|
|
9998
|
-
return feat;
|
|
10052
|
+
_requester;
|
|
10053
|
+
constructor(store, args) {
|
|
10054
|
+
this._args = args;
|
|
10055
|
+
this.store = store;
|
|
10056
|
+
this._subscribedTo = null;
|
|
10057
|
+
this._subscription = null;
|
|
10058
|
+
this._intervalStart = null;
|
|
10059
|
+
this._invalidated = false;
|
|
10060
|
+
this._nextInterval = null;
|
|
10061
|
+
this._requester = null;
|
|
10062
|
+
this.isDestroyed = false;
|
|
10063
|
+
this[DISPOSE] = _DISPOSE;
|
|
10064
|
+
this._installListeners();
|
|
10065
|
+
void this._beginPolling();
|
|
9999
10066
|
}
|
|
10000
10067
|
|
|
10001
10068
|
/**
|
|
10002
10069
|
* @internal
|
|
10003
10070
|
*/
|
|
10004
|
-
|
|
10005
|
-
|
|
10071
|
+
async _beginPolling() {
|
|
10072
|
+
// await the initial request
|
|
10073
|
+
try {
|
|
10074
|
+
if (!this.isIdle) {
|
|
10075
|
+
await this.request;
|
|
10076
|
+
}
|
|
10077
|
+
} catch {
|
|
10078
|
+
// ignore errors here, we just want to wait for the request to finish
|
|
10079
|
+
} finally {
|
|
10080
|
+
if (!this.isDestroyed) {
|
|
10081
|
+
void this._scheduleInterval();
|
|
10082
|
+
}
|
|
10083
|
+
}
|
|
10006
10084
|
}
|
|
10007
|
-
get
|
|
10085
|
+
get isIdle() {
|
|
10008
10086
|
const {
|
|
10009
10087
|
request,
|
|
10010
10088
|
query
|
|
10011
10089
|
} = this._args;
|
|
10012
|
-
|
|
10013
|
-
if (!test) {
|
|
10014
|
-
throw new Error(`Cannot use both @request and @query args with the <Request> component`);
|
|
10015
|
-
}
|
|
10016
|
-
})(!request || !query) : {};
|
|
10017
|
-
const {
|
|
10018
|
-
_localRequest,
|
|
10019
|
-
_originalRequest,
|
|
10020
|
-
_originalQuery
|
|
10021
|
-
} = this;
|
|
10022
|
-
const isOriginalRequest = request === _originalRequest && query === _originalQuery;
|
|
10023
|
-
if (_localRequest && isOriginalRequest) {
|
|
10024
|
-
return _localRequest;
|
|
10025
|
-
}
|
|
10026
|
-
|
|
10027
|
-
// update state checks for the next time
|
|
10028
|
-
this._originalQuery = query;
|
|
10029
|
-
this._originalRequest = request;
|
|
10030
|
-
if (request) {
|
|
10031
|
-
return request;
|
|
10032
|
-
}
|
|
10033
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
10034
|
-
if (!test) {
|
|
10035
|
-
throw new Error(`You must provide either @request or an @query arg with the <Request> component`);
|
|
10036
|
-
}
|
|
10037
|
-
})(query) : {};
|
|
10038
|
-
return this.store.request(query);
|
|
10039
|
-
}
|
|
10040
|
-
static {
|
|
10041
|
-
decorateMethodV2(this.prototype, "_request", [memoized]);
|
|
10042
|
-
}
|
|
10043
|
-
get request() {
|
|
10044
|
-
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
10045
|
-
try {
|
|
10046
|
-
const request = this._request;
|
|
10047
|
-
this._updateSubscriptions();
|
|
10048
|
-
return request;
|
|
10049
|
-
} catch (e) {
|
|
10050
|
-
// eslint-disable-next-line no-console
|
|
10051
|
-
console.log(e);
|
|
10052
|
-
throw new Error(`Unable to initialize the request`, {
|
|
10053
|
-
cause: e
|
|
10054
|
-
});
|
|
10055
|
-
}
|
|
10056
|
-
} else {
|
|
10057
|
-
const request = this._request;
|
|
10058
|
-
this._updateSubscriptions();
|
|
10059
|
-
return request;
|
|
10060
|
-
}
|
|
10090
|
+
return Boolean(!request && !query);
|
|
10061
10091
|
}
|
|
10062
10092
|
static {
|
|
10063
|
-
decorateMethodV2(this.prototype, "
|
|
10064
|
-
}
|
|
10065
|
-
get reqState() {
|
|
10066
|
-
return getRequestState(this.request);
|
|
10067
|
-
}
|
|
10068
|
-
get result() {
|
|
10069
|
-
return this.reqState.result;
|
|
10070
|
-
}
|
|
10071
|
-
}
|
|
10072
|
-
defineSignal(RequestSubscription.prototype, 'isOnline', true);
|
|
10073
|
-
defineSignal(RequestSubscription.prototype, 'isHidden', false);
|
|
10074
|
-
defineSignal(RequestSubscription.prototype, 'isRefreshing', false);
|
|
10075
|
-
defineSignal(RequestSubscription.prototype, '_localRequest', undefined);
|
|
10076
|
-
defineSignal(RequestSubscription.prototype, '_latestRequest', undefined);
|
|
10077
|
-
function isStore(store) {
|
|
10078
|
-
return 'requestManager' in store;
|
|
10079
|
-
}
|
|
10080
|
-
function createRequestSubscription(store, args) {
|
|
10081
|
-
return new RequestSubscription(store, args);
|
|
10082
|
-
}
|
|
10083
|
-
function upgradeSubscription(sub) {
|
|
10084
|
-
return sub;
|
|
10085
|
-
}
|
|
10086
|
-
function _DISPOSE() {
|
|
10087
|
-
const self = upgradeSubscription(this);
|
|
10088
|
-
self.isDestroyed = true;
|
|
10089
|
-
self._removeSubscriptions();
|
|
10090
|
-
if (typeof window === 'undefined') {
|
|
10091
|
-
return;
|
|
10093
|
+
decorateMethodV2(this.prototype, "isIdle", [memoized]);
|
|
10092
10094
|
}
|
|
10093
|
-
|
|
10094
|
-
window.removeEventListener('online', self._onlineChanged, {
|
|
10095
|
-
passive: true,
|
|
10096
|
-
capture: true
|
|
10097
|
-
});
|
|
10098
|
-
window.removeEventListener('offline', self._onlineChanged, {
|
|
10099
|
-
passive: true,
|
|
10100
|
-
capture: true
|
|
10101
|
-
});
|
|
10102
|
-
document.removeEventListener('visibilitychange', self._backgroundChanged, {
|
|
10103
|
-
passive: true,
|
|
10104
|
-
capture: true
|
|
10105
|
-
});
|
|
10106
|
-
}
|
|
10107
|
-
const RequestCache = new WeakMap();
|
|
10108
|
-
function isAbortError(error) {
|
|
10109
|
-
return error instanceof DOMException && error.name === 'AbortError';
|
|
10110
|
-
}
|
|
10111
|
-
function upgradeLoadingState(state) {
|
|
10112
|
-
return state;
|
|
10113
|
-
}
|
|
10114
|
-
async function watchStream(stream, loadingState) {
|
|
10115
|
-
const state = upgradeLoadingState(loadingState);
|
|
10116
|
-
const reader = stream.getReader();
|
|
10117
|
-
let bytesLoaded = 0;
|
|
10118
|
-
let shouldForward = state._stream !== null && state._stream.readable.locked;
|
|
10119
|
-
let isForwarding = shouldForward;
|
|
10120
|
-
let writer = state._stream?.writable.getWriter();
|
|
10121
|
-
const buffer = [];
|
|
10122
|
-
state._isPending = false;
|
|
10123
|
-
state._isStarted = true;
|
|
10124
|
-
state._startTime = performance.now();
|
|
10125
|
-
while (true) {
|
|
10095
|
+
get autorefreshTypes() {
|
|
10126
10096
|
const {
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
if (
|
|
10131
|
-
|
|
10132
|
-
}
|
|
10133
|
-
|
|
10134
|
-
state._bytesLoaded = bytesLoaded;
|
|
10135
|
-
state._lastPacketTime = performance.now();
|
|
10136
|
-
shouldForward = shouldForward || state._stream !== null && state._stream.readable.locked;
|
|
10137
|
-
if (shouldForward) {
|
|
10138
|
-
if (!isForwarding) {
|
|
10139
|
-
isForwarding = true;
|
|
10140
|
-
writer = state._stream.writable.getWriter();
|
|
10141
|
-
for (const item of buffer) {
|
|
10142
|
-
await writer.ready;
|
|
10143
|
-
await writer.write(item);
|
|
10144
|
-
}
|
|
10145
|
-
buffer.length = 0;
|
|
10146
|
-
}
|
|
10147
|
-
await writer.ready;
|
|
10148
|
-
await writer.write(value);
|
|
10097
|
+
autorefresh
|
|
10098
|
+
} = this._args;
|
|
10099
|
+
let types;
|
|
10100
|
+
if (autorefresh === true) {
|
|
10101
|
+
types = ['online', 'invalid'];
|
|
10102
|
+
} else if (typeof autorefresh === 'string') {
|
|
10103
|
+
types = autorefresh.split(',');
|
|
10149
10104
|
} else {
|
|
10150
|
-
|
|
10105
|
+
types = [];
|
|
10151
10106
|
}
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
// if we are still forwarding, we need to close the writer
|
|
10155
|
-
if (isForwarding) {
|
|
10156
|
-
await writer.ready;
|
|
10157
|
-
await writer.close();
|
|
10158
|
-
} else if (state._stream) {
|
|
10159
|
-
// if we are not forwarding, we need to cancel the stream
|
|
10160
|
-
await state._stream.readable.cancel('The Stream Has Already Ended');
|
|
10161
|
-
state._stream = null;
|
|
10162
|
-
}
|
|
10163
|
-
const endTime = performance.now();
|
|
10164
|
-
state._endTime = endTime;
|
|
10165
|
-
state._isComplete = true;
|
|
10166
|
-
state._isStarted = false;
|
|
10167
|
-
}
|
|
10168
|
-
|
|
10169
|
-
/**
|
|
10170
|
-
* Lazily consumes the stream of a request, providing a number of
|
|
10171
|
-
* reactive properties that can be used to build UIs that respond
|
|
10172
|
-
* to the progress of a request.
|
|
10173
|
-
*
|
|
10174
|
-
* @hideconstructor
|
|
10175
|
-
*/
|
|
10176
|
-
class RequestLoadingState {
|
|
10177
|
-
/** @internal */
|
|
10107
|
+
return new Set(types);
|
|
10108
|
+
}
|
|
10178
10109
|
|
|
10110
|
+
// we only run this function on component creation
|
|
10111
|
+
// and when an update is triggered, so it does not
|
|
10112
|
+
// react to changes in the autorefreshThreshold
|
|
10113
|
+
// or autorefresh args.
|
|
10114
|
+
//
|
|
10115
|
+
// if we need to react to those changes, we can
|
|
10116
|
+
// use a modifier or internal component or some
|
|
10117
|
+
// such to trigger a re-run of this function.
|
|
10179
10118
|
/** @internal */
|
|
10119
|
+
static {
|
|
10120
|
+
decorateMethodV2(this.prototype, "autorefreshTypes", [memoized]);
|
|
10121
|
+
}
|
|
10122
|
+
async _scheduleInterval() {
|
|
10123
|
+
const {
|
|
10124
|
+
autorefreshThreshold
|
|
10125
|
+
} = this._args;
|
|
10126
|
+
const hasValidThreshold = typeof autorefreshThreshold === 'number' && autorefreshThreshold > 0;
|
|
10127
|
+
if (
|
|
10128
|
+
// dont schedule in SSR
|
|
10129
|
+
typeof window === 'undefined' ||
|
|
10130
|
+
// dont schedule without a threshold
|
|
10131
|
+
!hasValidThreshold ||
|
|
10132
|
+
// dont schedule if we weren't told to
|
|
10133
|
+
!this.autorefreshTypes.has('interval') ||
|
|
10134
|
+
// dont schedule if we're already scheduled
|
|
10135
|
+
this._intervalStart !== null) {
|
|
10136
|
+
return;
|
|
10137
|
+
}
|
|
10180
10138
|
|
|
10181
|
-
|
|
10139
|
+
// if we have a current request, wait for it to finish
|
|
10140
|
+
// before scheduling the next one
|
|
10141
|
+
if (this._latestRequest) {
|
|
10142
|
+
try {
|
|
10143
|
+
await this._latestRequest;
|
|
10144
|
+
} catch {
|
|
10145
|
+
// ignore errors here, we just want to wait for the request to finish
|
|
10146
|
+
}
|
|
10147
|
+
if (this.isDestroyed) {
|
|
10148
|
+
return;
|
|
10149
|
+
}
|
|
10150
|
+
}
|
|
10182
10151
|
|
|
10183
|
-
|
|
10152
|
+
// setup the next interval
|
|
10153
|
+
this._intervalStart = Date.now();
|
|
10154
|
+
this._nextInterval = setTimeout(() => {
|
|
10155
|
+
this._maybeUpdate();
|
|
10156
|
+
}, autorefreshThreshold);
|
|
10157
|
+
}
|
|
10184
10158
|
|
|
10185
10159
|
/** @internal */
|
|
10160
|
+
_clearInterval() {
|
|
10161
|
+
if (this._nextInterval) {
|
|
10162
|
+
clearTimeout(this._nextInterval);
|
|
10163
|
+
this._intervalStart = null;
|
|
10164
|
+
}
|
|
10165
|
+
}
|
|
10166
|
+
/**
|
|
10167
|
+
* @internal
|
|
10168
|
+
*/
|
|
10169
|
+
_updateSubscriptions() {
|
|
10170
|
+
if (this.isIdle) {
|
|
10171
|
+
return;
|
|
10172
|
+
}
|
|
10173
|
+
const requestId = this._request.lid;
|
|
10186
10174
|
|
|
10187
|
-
|
|
10175
|
+
// if we're already subscribed to this request, we don't need to do anything
|
|
10176
|
+
if (this._subscribedTo === requestId) {
|
|
10177
|
+
return;
|
|
10178
|
+
}
|
|
10188
10179
|
|
|
10189
|
-
|
|
10180
|
+
// if we're subscribed to a different request, we need to unsubscribe
|
|
10181
|
+
this._removeSubscriptions();
|
|
10190
10182
|
|
|
10191
|
-
|
|
10183
|
+
// if we have a request, we need to subscribe to it
|
|
10184
|
+
const store = this._getRequester();
|
|
10185
|
+
this._requester = store;
|
|
10186
|
+
if (requestId && isStore(store)) {
|
|
10187
|
+
this._subscribedTo = requestId;
|
|
10188
|
+
this._subscription = store.notifications.subscribe(requestId, (_id, op) => {
|
|
10189
|
+
// ignore subscription events that occur while our own component's request
|
|
10190
|
+
// is occurring
|
|
10191
|
+
if (this._isUpdating) {
|
|
10192
|
+
return;
|
|
10193
|
+
}
|
|
10194
|
+
switch (op) {
|
|
10195
|
+
case 'invalidated':
|
|
10196
|
+
{
|
|
10197
|
+
// if we're subscribed to invalidations, we need to update
|
|
10198
|
+
if (this.autorefreshTypes.has('invalid')) {
|
|
10199
|
+
this._invalidated = true;
|
|
10200
|
+
this._maybeUpdate();
|
|
10201
|
+
}
|
|
10202
|
+
break;
|
|
10203
|
+
}
|
|
10204
|
+
case 'state':
|
|
10205
|
+
{
|
|
10206
|
+
const latest = store.requestManager._deduped.get(requestId);
|
|
10207
|
+
const priority = latest?.priority;
|
|
10208
|
+
const state = this.reqState;
|
|
10209
|
+
if (!priority) {
|
|
10210
|
+
// if there is no priority, we have completed whatever request
|
|
10211
|
+
// was occurring and so we are no longer refreshing (if we were)
|
|
10212
|
+
this.isRefreshing = false;
|
|
10213
|
+
} else if (priority.blocking && !state.isLoading) {
|
|
10214
|
+
// if we are blocking, there is an active request for this identity
|
|
10215
|
+
// that MUST be fulfilled from network (not cache).
|
|
10216
|
+
// Thus this is not "refreshing" because we should clear out and
|
|
10217
|
+
// block on this request.
|
|
10218
|
+
//
|
|
10219
|
+
// we receive state notifications when either a request initiates
|
|
10220
|
+
// or completes.
|
|
10221
|
+
//
|
|
10222
|
+
// In the completes case: we may receive the state notification
|
|
10223
|
+
// slightly before the request is finalized because the NotificationManager
|
|
10224
|
+
// may sync flush it (and thus deliver it before the microtask completes)
|
|
10225
|
+
//
|
|
10226
|
+
// In the initiates case: we aren't supposed to receive one unless there
|
|
10227
|
+
// is no other request in flight for this identity.
|
|
10228
|
+
//
|
|
10229
|
+
// However, there is a race condition here where the completed
|
|
10230
|
+
// notification can trigger an update that generates a new request
|
|
10231
|
+
// thus giving us an initiated notification before the older request
|
|
10232
|
+
// finalizes.
|
|
10233
|
+
//
|
|
10234
|
+
// When this occurs, if the triggered update happens to have caused
|
|
10235
|
+
// a new request to be made for the same identity AND that request
|
|
10236
|
+
// is the one passed into this component as the @request arg, then
|
|
10237
|
+
// getRequestState will return the state of the new request.
|
|
10238
|
+
// We can detect this by checking if the request state is "loading"
|
|
10239
|
+
// as outside of this case we would have a completed request.
|
|
10240
|
+
//
|
|
10241
|
+
// That is the reason for the `&& !state.isLoading` check above.
|
|
10192
10242
|
|
|
10193
|
-
|
|
10243
|
+
// TODO should we just treat this as refreshing?
|
|
10244
|
+
this.isRefreshing = false;
|
|
10245
|
+
this._maybeUpdate('policy', true);
|
|
10246
|
+
} else {
|
|
10247
|
+
this.isRefreshing = true;
|
|
10248
|
+
}
|
|
10249
|
+
}
|
|
10250
|
+
}
|
|
10251
|
+
});
|
|
10252
|
+
}
|
|
10253
|
+
}
|
|
10194
10254
|
|
|
10195
|
-
/**
|
|
10255
|
+
/**
|
|
10256
|
+
* @internal
|
|
10257
|
+
*/
|
|
10258
|
+
_removeSubscriptions() {
|
|
10259
|
+
const store = this._requester;
|
|
10260
|
+
if (this._subscription && store && isStore(store)) {
|
|
10261
|
+
store.notifications.unsubscribe(this._subscription);
|
|
10262
|
+
this._subscribedTo = null;
|
|
10263
|
+
this._subscription = null;
|
|
10264
|
+
this._requester = null;
|
|
10265
|
+
}
|
|
10266
|
+
}
|
|
10196
10267
|
|
|
10197
|
-
/**
|
|
10268
|
+
/**
|
|
10269
|
+
* Install the event listeners for network and visibility changes.
|
|
10270
|
+
* This is only done in browser environments with a global `window`.
|
|
10271
|
+
*
|
|
10272
|
+
* @internal
|
|
10273
|
+
*/
|
|
10274
|
+
_installListeners() {
|
|
10275
|
+
if (typeof window === 'undefined') {
|
|
10276
|
+
return;
|
|
10277
|
+
}
|
|
10278
|
+
this.isOnline = window.navigator.onLine;
|
|
10279
|
+
this._unavailableStart = this.isOnline ? null : Date.now();
|
|
10280
|
+
this.isHidden = document.visibilityState === 'hidden';
|
|
10281
|
+
this._onlineChanged = event => {
|
|
10282
|
+
this.isOnline = event.type === 'online';
|
|
10283
|
+
if (event.type === 'offline' && this._unavailableStart === null) {
|
|
10284
|
+
this._unavailableStart = Date.now();
|
|
10285
|
+
}
|
|
10286
|
+
this._maybeUpdate();
|
|
10287
|
+
};
|
|
10288
|
+
this._backgroundChanged = () => {
|
|
10289
|
+
const isHidden = document.visibilityState === 'hidden';
|
|
10290
|
+
this.isHidden = isHidden;
|
|
10291
|
+
if (isHidden && this._unavailableStart === null) {
|
|
10292
|
+
this._unavailableStart = Date.now();
|
|
10293
|
+
}
|
|
10294
|
+
this._maybeUpdate();
|
|
10295
|
+
};
|
|
10296
|
+
window.addEventListener('online', this._onlineChanged, {
|
|
10297
|
+
passive: true,
|
|
10298
|
+
capture: true
|
|
10299
|
+
});
|
|
10300
|
+
window.addEventListener('offline', this._onlineChanged, {
|
|
10301
|
+
passive: true,
|
|
10302
|
+
capture: true
|
|
10303
|
+
});
|
|
10304
|
+
document.addEventListener('visibilitychange', this._backgroundChanged, {
|
|
10305
|
+
passive: true,
|
|
10306
|
+
capture: true
|
|
10307
|
+
});
|
|
10308
|
+
}
|
|
10198
10309
|
|
|
10199
|
-
/**
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10310
|
+
/**
|
|
10311
|
+
* If the network is online and the tab is visible, either reload or refresh the request
|
|
10312
|
+
* based on the component's configuration and the requested update mode.
|
|
10313
|
+
*
|
|
10314
|
+
* Valid modes are:
|
|
10315
|
+
*
|
|
10316
|
+
* - `'reload'`: Force a reload of the request.
|
|
10317
|
+
* - `'refresh'`: Refresh the request in the background.
|
|
10318
|
+
* - `'policy'`: Make the request, letting the store's configured CachePolicy decide whether to reload, refresh, or do nothing.
|
|
10319
|
+
* - `undefined`: Make the request using the component's autorefreshBehavior setting if the autorefreshThreshold has passed.
|
|
10320
|
+
*
|
|
10321
|
+
* @internal
|
|
10322
|
+
*/
|
|
10323
|
+
_maybeUpdate(mode, silent) {
|
|
10324
|
+
if (this.isIdle) {
|
|
10208
10325
|
return;
|
|
10209
10326
|
}
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
if (
|
|
10214
|
-
|
|
10327
|
+
const {
|
|
10328
|
+
reqState
|
|
10329
|
+
} = this;
|
|
10330
|
+
if (reqState.isPending) {
|
|
10331
|
+
return;
|
|
10332
|
+
}
|
|
10333
|
+
const canAttempt = Boolean(this.isOnline && !this.isHidden && (mode || this.autorefreshTypes.size));
|
|
10334
|
+
if (!canAttempt) {
|
|
10335
|
+
if (!silent && mode && mode !== '_invalidated') {
|
|
10336
|
+
throw new Error(`Reload not available: the network is not online or the tab is hidden`);
|
|
10337
|
+
}
|
|
10338
|
+
return;
|
|
10339
|
+
}
|
|
10340
|
+
const {
|
|
10341
|
+
autorefreshTypes
|
|
10342
|
+
} = this;
|
|
10343
|
+
let shouldAttempt = this._invalidated || Boolean(mode);
|
|
10344
|
+
if (!shouldAttempt && autorefreshTypes.has('online')) {
|
|
10345
|
+
const {
|
|
10346
|
+
_unavailableStart
|
|
10347
|
+
} = this;
|
|
10348
|
+
const {
|
|
10349
|
+
autorefreshThreshold
|
|
10350
|
+
} = this._args;
|
|
10351
|
+
const deadline = typeof autorefreshThreshold === 'number' ? autorefreshThreshold : DEFAULT_DEADLINE;
|
|
10352
|
+
shouldAttempt = Boolean(_unavailableStart && Date.now() - _unavailableStart > deadline);
|
|
10353
|
+
}
|
|
10354
|
+
if (!shouldAttempt && autorefreshTypes.has('interval')) {
|
|
10355
|
+
const {
|
|
10356
|
+
_intervalStart
|
|
10357
|
+
} = this;
|
|
10358
|
+
const {
|
|
10359
|
+
autorefreshThreshold
|
|
10360
|
+
} = this._args;
|
|
10361
|
+
if (_intervalStart && typeof autorefreshThreshold === 'number' && autorefreshThreshold > 0) {
|
|
10362
|
+
shouldAttempt = Boolean(Date.now() - _intervalStart >= autorefreshThreshold);
|
|
10363
|
+
}
|
|
10215
10364
|
}
|
|
10216
|
-
this.
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10365
|
+
this._unavailableStart = null;
|
|
10366
|
+
this._invalidated = false;
|
|
10367
|
+
if (shouldAttempt) {
|
|
10368
|
+
this._clearInterval();
|
|
10369
|
+
this._isUpdating = true;
|
|
10370
|
+
const realMode = mode === '_invalidated' ? null : mode;
|
|
10371
|
+
const val = realMode ?? this._args.autorefreshBehavior ?? 'policy';
|
|
10372
|
+
|
|
10373
|
+
// if the future was generated by an older store version, it may not have
|
|
10374
|
+
// a requester set. In this case we append it to ensure that reload and
|
|
10375
|
+
// refresh will work appropriately.
|
|
10376
|
+
const requester = this._getRequester();
|
|
10377
|
+
if (!reqState._request.requester) {
|
|
10378
|
+
reqState._request.requester = requester;
|
|
10221
10379
|
}
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10380
|
+
switch (val) {
|
|
10381
|
+
case 'reload':
|
|
10382
|
+
this._latestRequest = reqState.reload();
|
|
10383
|
+
break;
|
|
10384
|
+
case 'refresh':
|
|
10385
|
+
this._latestRequest = reqState.refresh();
|
|
10386
|
+
break;
|
|
10387
|
+
case 'policy':
|
|
10388
|
+
this._latestRequest = reqState.refresh(true);
|
|
10389
|
+
break;
|
|
10390
|
+
default:
|
|
10391
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
10392
|
+
{
|
|
10393
|
+
throw new Error(`Invalid ${mode ? 'update mode' : '@autorefreshBehavior'} for <Request />: ${isNeverString(val)}`);
|
|
10394
|
+
}
|
|
10395
|
+
})() : {};
|
|
10229
10396
|
}
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
});
|
|
10233
|
-
}
|
|
10234
|
-
promise = null;
|
|
10235
|
-
get isPending() {
|
|
10236
|
-
this._trigger();
|
|
10237
|
-
return this._isPending;
|
|
10238
|
-
}
|
|
10239
|
-
get sizeHint() {
|
|
10240
|
-
this._trigger();
|
|
10241
|
-
return this._sizeHint;
|
|
10242
|
-
}
|
|
10243
|
-
get stream() {
|
|
10244
|
-
this._trigger();
|
|
10245
|
-
if (!this._stream) {
|
|
10246
|
-
if (this._isComplete || this._isCancelled || this._isErrored) {
|
|
10247
|
-
return null;
|
|
10397
|
+
if (val !== 'refresh') {
|
|
10398
|
+
this._localRequest = this._latestRequest;
|
|
10248
10399
|
}
|
|
10249
|
-
this.
|
|
10400
|
+
void this._scheduleInterval();
|
|
10401
|
+
void this._latestRequest.finally(() => {
|
|
10402
|
+
this._isUpdating = false;
|
|
10403
|
+
});
|
|
10250
10404
|
}
|
|
10251
|
-
return this._stream.readable;
|
|
10252
|
-
}
|
|
10253
|
-
get isStarted() {
|
|
10254
|
-
this._trigger();
|
|
10255
|
-
return this._isStarted;
|
|
10256
|
-
}
|
|
10257
|
-
get bytesLoaded() {
|
|
10258
|
-
this._trigger();
|
|
10259
|
-
return this._bytesLoaded;
|
|
10260
|
-
}
|
|
10261
|
-
get startTime() {
|
|
10262
|
-
this._trigger();
|
|
10263
|
-
return this._startTime;
|
|
10264
|
-
}
|
|
10265
|
-
get endTime() {
|
|
10266
|
-
this._trigger();
|
|
10267
|
-
return this._endTime;
|
|
10268
|
-
}
|
|
10269
|
-
get lastPacketTime() {
|
|
10270
|
-
this._trigger();
|
|
10271
|
-
return this._lastPacketTime;
|
|
10272
|
-
}
|
|
10273
|
-
get isComplete() {
|
|
10274
|
-
this._trigger();
|
|
10275
|
-
return this._isComplete;
|
|
10276
|
-
}
|
|
10277
|
-
get isCancelled() {
|
|
10278
|
-
this._trigger();
|
|
10279
|
-
return this._isCancelled;
|
|
10280
|
-
}
|
|
10281
|
-
get isErrored() {
|
|
10282
|
-
this._trigger();
|
|
10283
|
-
return this._isErrored;
|
|
10284
|
-
}
|
|
10285
|
-
get error() {
|
|
10286
|
-
this._trigger();
|
|
10287
|
-
return this._error;
|
|
10288
|
-
}
|
|
10289
|
-
get elapsedTime() {
|
|
10290
|
-
return (this.endTime || this.lastPacketTime) - this.startTime;
|
|
10291
|
-
}
|
|
10292
|
-
get completedRatio() {
|
|
10293
|
-
return this.sizeHint ? this.bytesLoaded / this.sizeHint : 0;
|
|
10294
|
-
}
|
|
10295
|
-
get remainingRatio() {
|
|
10296
|
-
return 1 - this.completedRatio;
|
|
10297
|
-
}
|
|
10298
|
-
get duration() {
|
|
10299
|
-
return this.endTime - this.startTime;
|
|
10300
|
-
}
|
|
10301
|
-
get speed() {
|
|
10302
|
-
// bytes per second
|
|
10303
|
-
return this.bytesLoaded / (this.elapsedTime / 1000);
|
|
10304
|
-
}
|
|
10305
|
-
constructor(future) {
|
|
10306
|
-
this._future = future;
|
|
10307
10405
|
}
|
|
10308
|
-
abort = () => {
|
|
10309
|
-
this._future.abort();
|
|
10310
|
-
};
|
|
10311
|
-
}
|
|
10312
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isPending', true);
|
|
10313
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isStarted', false);
|
|
10314
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isComplete', false);
|
|
10315
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isCancelled', false);
|
|
10316
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_isErrored', false);
|
|
10317
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_error', null);
|
|
10318
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_sizeHint', 0);
|
|
10319
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_bytesLoaded', 0);
|
|
10320
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_startTime', 0);
|
|
10321
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_endTime', 0);
|
|
10322
|
-
defineNonEnumerableSignal(RequestLoadingState.prototype, '_lastPacketTime', 0);
|
|
10323
|
-
|
|
10324
|
-
/**
|
|
10325
|
-
* The state of a request in the "pending"
|
|
10326
|
-
* state. This is the default initial state.
|
|
10327
|
-
*
|
|
10328
|
-
* Extends the {@link PendingPromise} interface.
|
|
10329
|
-
*
|
|
10330
|
-
*/
|
|
10331
|
-
|
|
10332
|
-
/**
|
|
10333
|
-
* The state of a request in the "fulfilled" state.
|
|
10334
|
-
* This is the state of a request that has resolved
|
|
10335
|
-
* successfully.
|
|
10336
|
-
*
|
|
10337
|
-
* Extends the {@link ResolvedPromise} interface.
|
|
10338
|
-
*
|
|
10339
|
-
*/
|
|
10340
10406
|
|
|
10341
|
-
/**
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
|
|
10345
|
-
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
|
|
10407
|
+
/**
|
|
10408
|
+
* @internal
|
|
10409
|
+
*/
|
|
10410
|
+
_getRequester() {
|
|
10411
|
+
// Note: we check for the requester's presence
|
|
10412
|
+
// as well as the request's presence because we may
|
|
10413
|
+
// be subscribed to a request issued by a store from an older
|
|
10414
|
+
// version of the library that didn't yet set requester.
|
|
10415
|
+
if (this._args.request?.requester) {
|
|
10416
|
+
return this._args.request.requester;
|
|
10417
|
+
}
|
|
10418
|
+
return this.store;
|
|
10419
|
+
}
|
|
10349
10420
|
|
|
10350
|
-
/**
|
|
10351
|
-
|
|
10352
|
-
|
|
10353
|
-
|
|
10354
|
-
|
|
10355
|
-
|
|
10421
|
+
/**
|
|
10422
|
+
* Retry the request, reloading it from the server.
|
|
10423
|
+
*/
|
|
10424
|
+
retry = async () => {
|
|
10425
|
+
this._maybeUpdate('reload');
|
|
10426
|
+
await this._localRequest;
|
|
10427
|
+
};
|
|
10356
10428
|
|
|
10357
|
-
/**
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
|
|
10364
|
-
* states.
|
|
10365
|
-
*
|
|
10366
|
-
* The key difference between a {@link Promise} and a Future is that Futures provide
|
|
10367
|
-
* access to a {@link ReadableStream | stream} of their content, the {@link RequestKey} of the request (if any)
|
|
10368
|
-
* as well as the ability to attempt to {@link Future.abort | abort} the request.
|
|
10369
|
-
*
|
|
10370
|
-
* ```ts
|
|
10371
|
-
* interface Future<T> extends Promise<T>> {
|
|
10372
|
-
* getStream(): Promise<ReadableStream>;
|
|
10373
|
-
* abort(): void;
|
|
10374
|
-
* lid: RequestKey | null;
|
|
10375
|
-
* }
|
|
10376
|
-
* ```
|
|
10377
|
-
*
|
|
10378
|
-
* These additional APIs allow us to craft even richer state experiences.
|
|
10379
|
-
*
|
|
10380
|
-
* To get the state of a request, use {@link getRequestState}.
|
|
10381
|
-
*
|
|
10382
|
-
* See also:
|
|
10383
|
-
* - {@link PendingRequest}
|
|
10384
|
-
* - {@link ResolvedRequest}
|
|
10385
|
-
* - {@link RejectedRequest}
|
|
10386
|
-
* - {@link CancelledRequest}
|
|
10387
|
-
*
|
|
10388
|
-
*/
|
|
10429
|
+
/**
|
|
10430
|
+
* Refresh the request, updating it in the background.
|
|
10431
|
+
*/
|
|
10432
|
+
refresh = async () => {
|
|
10433
|
+
this._maybeUpdate('refresh');
|
|
10434
|
+
await this._latestRequest;
|
|
10435
|
+
};
|
|
10389
10436
|
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
10394
|
-
|
|
10395
|
-
|
|
10396
|
-
|
|
10397
|
-
|
|
10398
|
-
|
|
10399
|
-
delete cacheOptions.reload;
|
|
10400
|
-
cacheOptions.backgroundReload = true;
|
|
10401
|
-
} else {
|
|
10402
|
-
// delete props to ensure we use the policy
|
|
10403
|
-
delete cacheOptions.backgroundReload;
|
|
10404
|
-
delete cacheOptions.reload;
|
|
10437
|
+
/**
|
|
10438
|
+
* features to yield to the error slot of a component
|
|
10439
|
+
*/
|
|
10440
|
+
get errorFeatures() {
|
|
10441
|
+
return {
|
|
10442
|
+
isHidden: this.isHidden,
|
|
10443
|
+
isOnline: this.isOnline,
|
|
10444
|
+
retry: this.retry
|
|
10445
|
+
};
|
|
10405
10446
|
}
|
|
10406
|
-
req.cacheOptions = cacheOptions;
|
|
10407
|
-
return requester.request(req);
|
|
10408
|
-
}
|
|
10409
10447
|
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
defineSignal(RequestStateProto, 'error', null);
|
|
10416
|
-
defineSignal(RequestStateProto, 'status', 'pending');
|
|
10417
|
-
defineSignal(RequestStateProto, 'isPending', true);
|
|
10418
|
-
defineSignal(RequestStateProto, 'isLoading', true);
|
|
10419
|
-
defineSignal(RequestStateProto, 'isSuccess', false);
|
|
10420
|
-
defineSignal(RequestStateProto, 'isError', false);
|
|
10421
|
-
defineSignal(RequestStateProto, 'request', null);
|
|
10422
|
-
defineSignal(RequestStateProto, 'response', null);
|
|
10423
|
-
Object.defineProperty(RequestStateProto, 'isCancelled', {
|
|
10424
|
-
get() {
|
|
10425
|
-
return this.isError && isAbortError(this.reason);
|
|
10448
|
+
/**
|
|
10449
|
+
* features to yield to the content slot of a component
|
|
10450
|
+
*/
|
|
10451
|
+
static {
|
|
10452
|
+
decorateMethodV2(this.prototype, "errorFeatures", [memoized]);
|
|
10426
10453
|
}
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
10430
|
-
|
|
10431
|
-
|
|
10454
|
+
get contentFeatures() {
|
|
10455
|
+
const feat = {
|
|
10456
|
+
isHidden: this.isHidden,
|
|
10457
|
+
isOnline: this.isOnline,
|
|
10458
|
+
reload: this.retry,
|
|
10459
|
+
refresh: this.refresh,
|
|
10460
|
+
isRefreshing: this.isRefreshing,
|
|
10461
|
+
latestRequest: this._latestRequest
|
|
10462
|
+
};
|
|
10463
|
+
if (feat.isRefreshing) {
|
|
10464
|
+
feat.abort = () => {
|
|
10465
|
+
this._latestRequest?.abort();
|
|
10466
|
+
};
|
|
10432
10467
|
}
|
|
10433
|
-
return
|
|
10468
|
+
return feat;
|
|
10434
10469
|
}
|
|
10435
|
-
|
|
10436
|
-
|
|
10437
|
-
|
|
10438
|
-
|
|
10439
|
-
|
|
10440
|
-
|
|
10441
|
-
|
|
10470
|
+
|
|
10471
|
+
/**
|
|
10472
|
+
* @internal
|
|
10473
|
+
*/
|
|
10474
|
+
static {
|
|
10475
|
+
decorateMethodV2(this.prototype, "contentFeatures", [memoized]);
|
|
10476
|
+
}
|
|
10477
|
+
get _request() {
|
|
10478
|
+
const {
|
|
10479
|
+
request,
|
|
10480
|
+
query
|
|
10481
|
+
} = this._args;
|
|
10442
10482
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
10443
10483
|
if (!test) {
|
|
10444
|
-
throw new Error(`Cannot
|
|
10484
|
+
throw new Error(`Cannot use both @request and @query args with the <Request> component`);
|
|
10445
10485
|
}
|
|
10446
|
-
})(!
|
|
10447
|
-
|
|
10448
|
-
|
|
10486
|
+
})(!request || !query) : {};
|
|
10487
|
+
const {
|
|
10488
|
+
_localRequest,
|
|
10489
|
+
_originalRequest,
|
|
10490
|
+
_originalQuery
|
|
10491
|
+
} = this;
|
|
10492
|
+
const isOriginalRequest = request === _originalRequest && query === _originalQuery;
|
|
10493
|
+
if (_localRequest && isOriginalRequest) {
|
|
10494
|
+
return _localRequest;
|
|
10495
|
+
}
|
|
10449
10496
|
|
|
10450
|
-
|
|
10451
|
-
|
|
10497
|
+
// update state checks for the next time
|
|
10498
|
+
this._originalQuery = query;
|
|
10499
|
+
this._originalRequest = request;
|
|
10500
|
+
if (request) {
|
|
10501
|
+
return request;
|
|
10502
|
+
}
|
|
10452
10503
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
10453
10504
|
if (!test) {
|
|
10454
|
-
throw new Error(`
|
|
10505
|
+
throw new Error(`You must provide either @request or an @query arg with the <Request> component`);
|
|
10506
|
+
}
|
|
10507
|
+
})(query) : {};
|
|
10508
|
+
return this.store.request(query);
|
|
10509
|
+
}
|
|
10510
|
+
static {
|
|
10511
|
+
decorateMethodV2(this.prototype, "_request", [memoized]);
|
|
10512
|
+
}
|
|
10513
|
+
get request() {
|
|
10514
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
10515
|
+
try {
|
|
10516
|
+
const request = this._request;
|
|
10517
|
+
this._updateSubscriptions();
|
|
10518
|
+
return request;
|
|
10519
|
+
} catch (e) {
|
|
10520
|
+
// eslint-disable-next-line no-console
|
|
10521
|
+
console.log(e);
|
|
10522
|
+
throw new Error(`Unable to initialize the request`, {
|
|
10523
|
+
cause: e
|
|
10524
|
+
});
|
|
10455
10525
|
}
|
|
10456
|
-
})(!promiseState.isPending) : {};
|
|
10457
|
-
return performRefresh(future.requester, promiseState.request, usePolicy === true ? null : false);
|
|
10458
|
-
};
|
|
10459
|
-
if (state) {
|
|
10460
|
-
if (state.isError) {
|
|
10461
|
-
promiseState.error = state.result;
|
|
10462
|
-
promiseState.reason = state.result;
|
|
10463
|
-
promiseState.status = 'rejected';
|
|
10464
|
-
promiseState.isError = true;
|
|
10465
|
-
promiseState.isPending = false;
|
|
10466
|
-
promiseState.isLoading = false;
|
|
10467
|
-
promiseState.request = state.result.request;
|
|
10468
|
-
promiseState.response = state.result.response;
|
|
10469
10526
|
} else {
|
|
10470
|
-
|
|
10471
|
-
|
|
10472
|
-
|
|
10473
|
-
promiseState.isSuccess = true;
|
|
10474
|
-
promiseState.isPending = false;
|
|
10475
|
-
promiseState.isLoading = false;
|
|
10476
|
-
promiseState.request = state.result.request;
|
|
10477
|
-
promiseState.response = state.result.response;
|
|
10527
|
+
const request = this._request;
|
|
10528
|
+
this._updateSubscriptions();
|
|
10529
|
+
return request;
|
|
10478
10530
|
}
|
|
10479
|
-
} else {
|
|
10480
|
-
void future.then(result => {
|
|
10481
|
-
setPromiseResult(future, {
|
|
10482
|
-
isError: false,
|
|
10483
|
-
result
|
|
10484
|
-
});
|
|
10485
|
-
promiseState.result = result.content;
|
|
10486
|
-
promiseState.value = result.content;
|
|
10487
|
-
promiseState.status = 'fulfilled';
|
|
10488
|
-
promiseState.isSuccess = true;
|
|
10489
|
-
promiseState.isPending = false;
|
|
10490
|
-
promiseState.isLoading = false;
|
|
10491
|
-
promiseState.request = result.request;
|
|
10492
|
-
promiseState.response = result.response;
|
|
10493
|
-
}, error => {
|
|
10494
|
-
setPromiseResult(future, {
|
|
10495
|
-
isError: true,
|
|
10496
|
-
result: error
|
|
10497
|
-
});
|
|
10498
|
-
promiseState.error = error;
|
|
10499
|
-
promiseState.reason = error;
|
|
10500
|
-
promiseState.status = 'rejected';
|
|
10501
|
-
promiseState.isError = true;
|
|
10502
|
-
promiseState.isPending = false;
|
|
10503
|
-
promiseState.isLoading = false;
|
|
10504
|
-
promiseState.request = error.request;
|
|
10505
|
-
promiseState.response = error.response;
|
|
10506
|
-
});
|
|
10507
10531
|
}
|
|
10508
|
-
|
|
10532
|
+
static {
|
|
10533
|
+
decorateMethodV2(this.prototype, "request", [memoized]);
|
|
10534
|
+
}
|
|
10535
|
+
get reqState() {
|
|
10536
|
+
return getRequestState(this.request);
|
|
10537
|
+
}
|
|
10538
|
+
get result() {
|
|
10539
|
+
return this.reqState.result;
|
|
10540
|
+
}
|
|
10509
10541
|
}
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
|
|
10526
|
-
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
|
|
10530
|
-
* return 'loading...';
|
|
10531
|
-
* }
|
|
10532
|
-
* if (state.isError) { return null; }
|
|
10533
|
-
* return state.result.title;
|
|
10534
|
-
* }
|
|
10535
|
-
* }
|
|
10536
|
-
* ```
|
|
10537
|
-
*
|
|
10538
|
-
* Or in a template as a helper:
|
|
10539
|
-
*
|
|
10540
|
-
* ```gjs
|
|
10541
|
-
* import { getRequestState } from '@warp-drive/ember';
|
|
10542
|
-
*
|
|
10543
|
-
* <template>
|
|
10544
|
-
* {{#let (getRequestState @request) as |state|}}
|
|
10545
|
-
* {{#if state.isPending}}
|
|
10546
|
-
* <Spinner />
|
|
10547
|
-
* {{else if state.isError}}
|
|
10548
|
-
* <ErrorForm @error={{state.error}} />
|
|
10549
|
-
* {{else}}
|
|
10550
|
-
* <h1>{{state.result.title}}</h1>
|
|
10551
|
-
* {{/if}}
|
|
10552
|
-
* {{/let}}
|
|
10553
|
-
* </template>
|
|
10554
|
-
* ```
|
|
10555
|
-
*
|
|
10556
|
-
* If looking to use in a template, consider also the `<Request />` component
|
|
10557
|
-
* which offers a numbe of additional capabilities for requests *beyond* what
|
|
10558
|
-
* `RequestState` provides.
|
|
10559
|
-
*
|
|
10560
|
-
*/
|
|
10561
|
-
function getRequestState(future) {
|
|
10562
|
-
let state = RequestCache.get(future);
|
|
10563
|
-
if (!state) {
|
|
10564
|
-
state = createRequestState(future);
|
|
10565
|
-
RequestCache.set(future, state);
|
|
10542
|
+
defineSignal(RequestSubscription.prototype, 'isOnline', true);
|
|
10543
|
+
defineSignal(RequestSubscription.prototype, 'isHidden', false);
|
|
10544
|
+
defineSignal(RequestSubscription.prototype, 'isRefreshing', false);
|
|
10545
|
+
defineSignal(RequestSubscription.prototype, '_localRequest', undefined);
|
|
10546
|
+
defineSignal(RequestSubscription.prototype, '_latestRequest', undefined);
|
|
10547
|
+
function isStore(store) {
|
|
10548
|
+
return 'requestManager' in store;
|
|
10549
|
+
}
|
|
10550
|
+
function createRequestSubscription(store, args) {
|
|
10551
|
+
return new RequestSubscription(store, args);
|
|
10552
|
+
}
|
|
10553
|
+
function upgradeSubscription(sub) {
|
|
10554
|
+
return sub;
|
|
10555
|
+
}
|
|
10556
|
+
function _DISPOSE() {
|
|
10557
|
+
const self = upgradeSubscription(this);
|
|
10558
|
+
self.isDestroyed = true;
|
|
10559
|
+
self._removeSubscriptions();
|
|
10560
|
+
if (typeof window === 'undefined') {
|
|
10561
|
+
return;
|
|
10566
10562
|
}
|
|
10567
|
-
|
|
10563
|
+
self._clearInterval();
|
|
10564
|
+
window.removeEventListener('online', self._onlineChanged, {
|
|
10565
|
+
passive: true,
|
|
10566
|
+
capture: true
|
|
10567
|
+
});
|
|
10568
|
+
window.removeEventListener('offline', self._onlineChanged, {
|
|
10569
|
+
passive: true,
|
|
10570
|
+
capture: true
|
|
10571
|
+
});
|
|
10572
|
+
document.removeEventListener('visibilitychange', self._backgroundChanged, {
|
|
10573
|
+
passive: true,
|
|
10574
|
+
capture: true
|
|
10575
|
+
});
|
|
10568
10576
|
}
|
|
10569
10577
|
export { defineGate as A, defineNonEnumerableSignal as B, CacheHandler as C, DISPOSE as D, Signals as E, peekInternalSignal as F, createInternalMemo as G, withSignalStore as H, notifyInternalSignal as I, consumeInternalSignal as J, getOrCreateInternalSignal as K, ReactiveResource as L, isNonIdentityCacheableField as M, getFieldCacheKeyStrict as N, checkout as O, commit as P, setIdentifierGenerationMethod as Q, RecordArrayManager as R, Store as S, setIdentifierUpdateMethod as T, setIdentifierForgetMethod as U, setIdentifierResetMethod as V, setKeyInfoForResource as W, _clearCaches as _, isRequestKey as a, coerceId as b, constructResource as c, assertPrivateStore as d, ensureStringId as e, fastPush as f, isPrivateStore as g, assertPrivateCapabilities as h, isResourceKey as i, setRecordIdentifier as j, StoreMap as k, createLegacyManyArray as l, log as m, normalizeModelName as n, logGroup as o, getPromiseState as p, createRequestSubscription as q, recordIdentifierFor as r, storeFor as s, getRequestState as t, signal as u, memoized as v, gate as w, entangleSignal as x, entangleInitiallyStaleSignal as y, defineSignal as z };
|