@warp-drive/core 5.6.0-alpha.13 → 5.6.0-alpha.15

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.
Files changed (54) hide show
  1. package/declarations/configure.d.ts +1 -1
  2. package/declarations/configure.d.ts.map +1 -1
  3. package/declarations/reactive/-private/fields/compute.d.ts.map +1 -1
  4. package/declarations/reactive/-private/fields/extension.d.ts +9 -0
  5. package/declarations/reactive/-private/fields/extension.d.ts.map +1 -0
  6. package/declarations/reactive/-private/fields/managed-array.d.ts.map +1 -1
  7. package/declarations/reactive/-private/fields/managed-object.d.ts.map +1 -1
  8. package/declarations/reactive/-private/record.d.ts +4 -3
  9. package/declarations/reactive/-private/record.d.ts.map +1 -1
  10. package/declarations/reactive/-private/schema.d.ts +73 -0
  11. package/declarations/reactive/-private/schema.d.ts.map +1 -1
  12. package/declarations/reactive/-private/symbols.d.ts +1 -1
  13. package/declarations/reactive/-private/symbols.d.ts.map +1 -1
  14. package/declarations/reactive.d.ts +1 -1
  15. package/declarations/reactive.d.ts.map +1 -1
  16. package/declarations/store/-private/new-core-tmp/promise-state.d.ts.map +1 -1
  17. package/declarations/store/-private/new-core-tmp/reactivity/configure.d.ts +86 -2
  18. package/declarations/store/-private/new-core-tmp/reactivity/configure.d.ts.map +1 -1
  19. package/declarations/store/-private/new-core-tmp/request-subscription.d.ts +231 -0
  20. package/declarations/store/-private/new-core-tmp/request-subscription.d.ts.map +1 -0
  21. package/declarations/store/-private/record-arrays/identifier-array.d.ts +2 -0
  22. package/declarations/store/-private/record-arrays/identifier-array.d.ts.map +1 -1
  23. package/declarations/store/-private/record-arrays/many-array.d.ts +2 -0
  24. package/declarations/store/-private/record-arrays/many-array.d.ts.map +1 -1
  25. package/declarations/store/-private.d.ts +1 -0
  26. package/declarations/store/-private.d.ts.map +1 -1
  27. package/declarations/store/-types/q/schema-service.d.ts +20 -0
  28. package/declarations/store/-types/q/schema-service.d.ts.map +1 -1
  29. package/declarations/types/-private.d.ts +1 -1
  30. package/declarations/types/-private.d.ts.map +1 -1
  31. package/declarations/types/schema/fields.d.ts +133 -7
  32. package/declarations/types/schema/fields.d.ts.map +1 -1
  33. package/dist/{configure-BgaZESRo.js → configure-B48bFHOl.js} +38 -2
  34. package/dist/configure-B48bFHOl.js.map +1 -0
  35. package/dist/configure.js +1 -1
  36. package/dist/graph/-private.js +2 -2
  37. package/dist/{handler-cHghx9Y9.js → handler-D1C3Innj.js} +1 -1
  38. package/dist/{handler-cHghx9Y9.js.map → handler-D1C3Innj.js.map} +1 -1
  39. package/dist/index.js +3 -3
  40. package/dist/reactive/-private.js +1 -1
  41. package/dist/reactive.js +248 -31
  42. package/dist/reactive.js.map +1 -1
  43. package/dist/{request-state-DgwTEXLU.js → request-state-CCOJIj5i.js} +778 -11
  44. package/dist/request-state-CCOJIj5i.js.map +1 -0
  45. package/dist/store/-private.js +3 -3
  46. package/dist/{symbols-BmDcn6hS.js → symbols-epHW0Vm9.js} +2 -2
  47. package/dist/{symbols-BmDcn6hS.js.map → symbols-epHW0Vm9.js.map} +1 -1
  48. package/dist/types/-private.js +1 -1
  49. package/dist/types/-private.js.map +1 -1
  50. package/dist/types/schema/fields.js +4 -4
  51. package/dist/types/schema/fields.js.map +1 -1
  52. package/package.json +3 -3
  53. package/dist/configure-BgaZESRo.js.map +0 -1
  54. package/dist/request-state-DgwTEXLU.js.map +0 -1
@@ -1,11 +1,11 @@
1
+ import { withBrand, EnableHydration, SkipCache } from './types/request.js';
1
2
  import { deprecate, warn } from '@ember/debug';
2
3
  import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
3
- import { withBrand, EnableHydration, SkipCache } from './types/request.js';
4
4
  import { setLogging, getRuntimeConfig } from './types/runtime.js';
5
5
  import { getOrSetGlobal, peekTransient, setTransient } from './types/-private.js';
6
- import { a as createSignal, b as consumeSignal, n as notifySignal, c as createMemo, d as willSyncFlushWatchers, A as ARRAY_SIGNAL } from "./configure-BgaZESRo.js";
7
6
  import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_IDENTIFIER_BUCKET, DEBUG_CLIENT_ORIGINATED } from './types/identifier.js';
8
7
  import { dasherize } from './utils/string.js';
8
+ import { a as createSignal, b as consumeSignal, n as notifySignal, c as createMemo, d as willSyncFlushWatchers, A as ARRAY_SIGNAL } from "./configure-B48bFHOl.js";
9
9
  import { g as getPromiseResult, s as setPromiseResult } from "./context-COmAnXUQ.js";
10
10
  function coerceId(id) {
11
11
  if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_NON_STRICT_ID)) {
@@ -3178,6 +3178,142 @@ class NotificationManager {
3178
3178
  this._cache.clear();
3179
3179
  }
3180
3180
  }
3181
+ function isExtensionProp(extensions, prop) {
3182
+ return Boolean(extensions && typeof prop !== 'number' && extensions.has(prop));
3183
+ }
3184
+ function performObjectExtensionGet(receiver, extensions, signals, prop) {
3185
+ const desc = extensions.get(prop);
3186
+ switch (desc.kind) {
3187
+ case 'method':
3188
+ {
3189
+ return desc.fn;
3190
+ }
3191
+ case 'readonly-value':
3192
+ {
3193
+ return desc.value;
3194
+ }
3195
+ case 'mutable-value':
3196
+ {
3197
+ const signal = getOrCreateInternalSignal(signals, receiver, prop, desc.value);
3198
+ // we don't consume this signal, since its not a true local.
3199
+ return signal.value;
3200
+ }
3201
+ case 'readonly-field':
3202
+ case 'mutable-field':
3203
+ {
3204
+ return desc.get.call(receiver);
3205
+ }
3206
+ case 'writeonly-field':
3207
+ {
3208
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3209
+ {
3210
+ throw new Error(`Cannot get extended field ${String(prop)} as its definition has only a setter`);
3211
+ }
3212
+ })() : {};
3213
+ return undefined;
3214
+ }
3215
+ default:
3216
+ {
3217
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3218
+ {
3219
+ throw new Error(`Unhandled extension kind ${desc.kind}`);
3220
+ }
3221
+ })() : {};
3222
+ return undefined;
3223
+ }
3224
+ }
3225
+ }
3226
+ function performExtensionSet(receiver, extensions, signals, prop, value) {
3227
+ const desc = extensions.get(prop);
3228
+ switch (desc.kind) {
3229
+ case 'method':
3230
+ case 'readonly-value':
3231
+ case 'readonly-field':
3232
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3233
+ {
3234
+ throw new Error(`Cannot set extension field ${String(prop)} as it is a ${desc.kind}`);
3235
+ }
3236
+ })() : {};
3237
+ return false;
3238
+ case 'mutable-value':
3239
+ {
3240
+ const signal = getOrCreateInternalSignal(signals, receiver, prop, desc.value);
3241
+ if (signal.value !== value) {
3242
+ // we don't notify this signal, since its not a true local.
3243
+ signal.value = value;
3244
+ }
3245
+ return true;
3246
+ }
3247
+ case 'writeonly-field':
3248
+ case 'mutable-field':
3249
+ {
3250
+ desc.set.call(receiver, value);
3251
+ return true;
3252
+ }
3253
+ default:
3254
+ {
3255
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3256
+ {
3257
+ throw new Error(`Unhandled extension kind ${desc.kind}`);
3258
+ }
3259
+ })() : {};
3260
+ return false;
3261
+ }
3262
+ }
3263
+ }
3264
+ function performArrayExtensionGet(receiver, extensions, signals, prop, _SIGNAL, boundFns, transaction) {
3265
+ const desc = extensions.get(prop);
3266
+ switch (desc.kind) {
3267
+ case 'method':
3268
+ {
3269
+ let fn = boundFns.get(prop);
3270
+ if (fn === undefined) {
3271
+ fn = function () {
3272
+ consumeInternalSignal(_SIGNAL);
3273
+ transaction(true);
3274
+ const result = Reflect.apply(desc.fn, receiver, arguments);
3275
+ transaction(false);
3276
+ return result;
3277
+ };
3278
+ boundFns.set(prop, fn);
3279
+ }
3280
+ return fn;
3281
+ }
3282
+ case 'mutable-field':
3283
+ case 'readonly-field':
3284
+ {
3285
+ return desc.get.call(receiver);
3286
+ }
3287
+ case 'readonly-value':
3288
+ {
3289
+ return desc.value;
3290
+ }
3291
+ case 'mutable-value':
3292
+ {
3293
+ const signal = getOrCreateInternalSignal(signals, receiver, prop, desc.value);
3294
+ // we don't consume this signal, since its not a true local.
3295
+ return signal.value;
3296
+ }
3297
+ case 'writeonly-field':
3298
+ {
3299
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3300
+ {
3301
+ throw new Error(`Cannot get extended field ${String(prop)} as its definition has only a setter`);
3302
+ }
3303
+ })() : {};
3304
+ return undefined;
3305
+ }
3306
+ default:
3307
+ {
3308
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3309
+ {
3310
+ throw new Error(`Unhandled extension kind ${desc.kind}`);
3311
+ }
3312
+ })() : {};
3313
+ return undefined;
3314
+ }
3315
+ }
3316
+ }
3181
3317
 
3182
3318
  /* eslint-disable @typescript-eslint/no-explicit-any */
3183
3319
  /*
@@ -3246,6 +3382,12 @@ function safeForEach(instance, arr, store, callback, target) {
3246
3382
  @public
3247
3383
  */
3248
3384
 
3385
+ // these are "internally" mutable, they should not be mutated by consumers
3386
+ // though this is not currently enforced.
3387
+ //
3388
+ // all of these should become gated by field-type as they shouldn't be available
3389
+ // on request results or non-legacy relationships.
3390
+ const MUTABLE_PROPS = ['_updatingPromise', 'isDestroying', 'isDestroyed', 'query', 'isUpdating', 'isLoaded', 'meta', 'links', 'isAsync', 'isPolymorphic', 'identifier', 'cache', '_inverseIsAsync', 'key', 'DEPRECATED_CLASS_NAME'];
3249
3391
  class IdentifierArray {
3250
3392
  /**
3251
3393
  The flag to signal a `RecordArray` is currently loading data.
@@ -3307,6 +3449,7 @@ class IdentifierArray {
3307
3449
  // we track all mutations within the call
3308
3450
  // and forward them as one
3309
3451
  let _SIGNAL = null;
3452
+ const extensions = options.field && this.store.schema.CAUTION_MEGA_DANGER_ZONE_arrayExtensions ? this.store.schema.CAUTION_MEGA_DANGER_ZONE_arrayExtensions(options.field) : null;
3310
3453
  const proxy = new NativeProxy(this[SOURCE], {
3311
3454
  get(target, prop, receiver) {
3312
3455
  const index = convertToInt(prop);
@@ -3404,10 +3547,21 @@ class IdentifierArray {
3404
3547
  }
3405
3548
  return consumeInternalSignal(_SIGNAL), outcome;
3406
3549
  }
3550
+ if (isExtensionProp(extensions, prop)) {
3551
+ return performArrayExtensionGet(receiver, extensions, signals, prop, _SIGNAL, boundFns, v => void (transaction = v));
3552
+ }
3407
3553
  return target[prop];
3408
3554
  },
3409
3555
  // FIXME: Should this get a generic like get above?
3410
3556
  set(target, prop, value, receiver) {
3557
+ if (!options.allowMutation && !MUTABLE_PROPS.includes(prop)) {
3558
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3559
+ if (!test) {
3560
+ throw new Error(`Mutating ${String(prop)} on this Array is not allowed.`);
3561
+ }
3562
+ })(options.allowMutation) : {};
3563
+ return false;
3564
+ }
3411
3565
  if (prop === 'length') {
3412
3566
  if (!transaction && value === 0) {
3413
3567
  transaction = true;
@@ -3432,6 +3586,9 @@ class IdentifierArray {
3432
3586
  PrivateState.meta = value || null;
3433
3587
  return true;
3434
3588
  }
3589
+ if (isExtensionProp(extensions, prop)) {
3590
+ return performExtensionSet(receiver, extensions, signals, prop, value);
3591
+ }
3435
3592
  const index = convertToInt(prop);
3436
3593
 
3437
3594
  // we do not allow "holey" arrays and so if the index is
@@ -3458,14 +3615,6 @@ class IdentifierArray {
3458
3615
  }
3459
3616
  return false;
3460
3617
  }
3461
- if (!options.allowMutation) {
3462
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3463
- if (!test) {
3464
- throw new Error(`Mutating ${String(prop)} on this Array is not allowed.`);
3465
- }
3466
- })(options.allowMutation) : {};
3467
- return false;
3468
- }
3469
3618
  const original = target[index];
3470
3619
  const newIdentifier = extractIdentifierFromRecord$2(value);
3471
3620
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
@@ -6953,6 +7102,11 @@ function getPromise(promise) {
6953
7102
  *
6954
7103
  */
6955
7104
  function getPromiseState(promise) {
7105
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
7106
+ if (!test) {
7107
+ throw new Error(`getPromiseState expects to be called with a promise: called with ${String(promise)}`);
7108
+ }
7109
+ })(promise) : {};
6956
7110
  const _promise = getPromise(promise);
6957
7111
  let state = PromiseCache.get(_promise);
6958
7112
  if (!state) {
@@ -6961,6 +7115,619 @@ function getPromiseState(promise) {
6961
7115
  }
6962
7116
  return state;
6963
7117
  }
7118
+ function decorateMethodV2(prototype, prop, decorators) {
7119
+ const origDesc = Object.getOwnPropertyDescriptor(prototype, prop);
7120
+ let desc = {
7121
+ ...origDesc
7122
+ };
7123
+ for (let decorator of decorators) {
7124
+ desc = decorator(prototype, prop, desc) || desc;
7125
+ }
7126
+ if (desc.initializer !== void 0) {
7127
+ desc.value = desc.initializer ? desc.initializer.call(prototype) : void 0;
7128
+ desc.initializer = void 0;
7129
+ }
7130
+ Object.defineProperty(prototype, prop, desc);
7131
+ }
7132
+ const DEFAULT_DEADLINE = 30_000;
7133
+ const DISPOSE = Symbol.dispose || Symbol.for('dispose');
7134
+ function isNeverString(val) {
7135
+ return val;
7136
+ }
7137
+
7138
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
7139
+
7140
+ /**
7141
+ * A reactive class
7142
+ *
7143
+ * @hideconstructor
7144
+ */
7145
+ class RequestSubscription {
7146
+ /**
7147
+ * Whether the browser reports that the network is online.
7148
+ */
7149
+
7150
+ /**
7151
+ * Whether the browser reports that the tab is hidden.
7152
+ */
7153
+
7154
+ /**
7155
+ * Whether the component is currently refreshing the request.
7156
+ */
7157
+
7158
+ /**
7159
+ * The most recent blocking request that was made, typically
7160
+ * the result of a reload.
7161
+ *
7162
+ * This will never be the original request passed as an arg to
7163
+ * the component.
7164
+ *
7165
+ * @internal
7166
+ */
7167
+
7168
+ /**
7169
+ * The most recent request that was made, typically due to either a
7170
+ * reload or a refresh.
7171
+ *
7172
+ * This will never be the original request passed as an arg to
7173
+ * the component.
7174
+ *
7175
+ * @internal
7176
+ */
7177
+
7178
+ /**
7179
+ * The time at which the network was reported as offline.
7180
+ *
7181
+ * @internal
7182
+ */
7183
+
7184
+ /** @internal */
7185
+
7186
+ /** @internal */
7187
+
7188
+ /** @internal */
7189
+
7190
+ /** @internal */
7191
+
7192
+ /** @internal */
7193
+
7194
+ /**
7195
+ * The event listener for network status changes,
7196
+ * cached to use the reference for removal.
7197
+ *
7198
+ * @internal
7199
+ */
7200
+
7201
+ /**
7202
+ * The event listener for visibility status changes,
7203
+ * cached to use the reference for removal.
7204
+ *
7205
+ * @internal
7206
+ */
7207
+
7208
+ /**
7209
+ * The last request passed as an arg to the component,
7210
+ * cached for comparison.
7211
+ *
7212
+ * @internal
7213
+ */
7214
+
7215
+ /**
7216
+ * The last query passed as an arg to the component,
7217
+ * cached for comparison.
7218
+ *
7219
+ * @internal
7220
+ */
7221
+
7222
+ /** @internal */
7223
+
7224
+ /** @internal */
7225
+
7226
+ /** @internal */
7227
+
7228
+ /** @internal */
7229
+
7230
+ constructor(store, args) {
7231
+ this._args = args;
7232
+ this.store = store;
7233
+ this._subscribedTo = null;
7234
+ this._subscription = null;
7235
+ this._intervalStart = null;
7236
+ this._invalidated = false;
7237
+ this._nextInterval = null;
7238
+ this.isDestroyed = false;
7239
+ this._installListeners();
7240
+ void this._beginPolling();
7241
+ }
7242
+
7243
+ /**
7244
+ * @internal
7245
+ */
7246
+ async _beginPolling() {
7247
+ // await the initial request
7248
+ try {
7249
+ if (!this.isIdle) {
7250
+ await this.request;
7251
+ }
7252
+ } catch {
7253
+ // ignore errors here, we just want to wait for the request to finish
7254
+ } finally {
7255
+ if (!this.isDestroyed) {
7256
+ void this._scheduleInterval();
7257
+ }
7258
+ }
7259
+ }
7260
+ get isIdle() {
7261
+ const {
7262
+ request,
7263
+ query
7264
+ } = this._args;
7265
+ return Boolean(!request && !query);
7266
+ }
7267
+ static {
7268
+ decorateMethodV2(this.prototype, "isIdle", [memoized]);
7269
+ }
7270
+ get autorefreshTypes() {
7271
+ const {
7272
+ autorefresh
7273
+ } = this._args;
7274
+ let types;
7275
+ if (autorefresh === true) {
7276
+ types = ['online', 'invalid'];
7277
+ } else if (typeof autorefresh === 'string') {
7278
+ types = autorefresh.split(',');
7279
+ } else {
7280
+ types = [];
7281
+ }
7282
+ return new Set(types);
7283
+ }
7284
+
7285
+ // we only run this function on component creation
7286
+ // and when an update is triggered, so it does not
7287
+ // react to changes in the autorefreshThreshold
7288
+ // or autorefresh args.
7289
+ //
7290
+ // if we need to react to those changes, we can
7291
+ // use a modifier or internal component or some
7292
+ // such to trigger a re-run of this function.
7293
+ static {
7294
+ decorateMethodV2(this.prototype, "autorefreshTypes", [memoized]);
7295
+ }
7296
+ async _scheduleInterval() {
7297
+ const {
7298
+ autorefreshThreshold
7299
+ } = this._args;
7300
+ const hasValidThreshold = typeof autorefreshThreshold === 'number' && autorefreshThreshold > 0;
7301
+ if (
7302
+ // dont schedule in SSR
7303
+ typeof window === 'undefined' ||
7304
+ // dont schedule without a threshold
7305
+ !hasValidThreshold ||
7306
+ // dont schedule if we weren't told to
7307
+ !this.autorefreshTypes.has('interval') ||
7308
+ // dont schedule if we're already scheduled
7309
+ this._intervalStart !== null) {
7310
+ return;
7311
+ }
7312
+
7313
+ // if we have a current request, wait for it to finish
7314
+ // before scheduling the next one
7315
+ if (this._latestRequest) {
7316
+ try {
7317
+ await this._latestRequest;
7318
+ } catch {
7319
+ // ignore errors here, we just want to wait for the request to finish
7320
+ }
7321
+ if (this.isDestroyed) {
7322
+ return;
7323
+ }
7324
+ }
7325
+
7326
+ // setup the next interval
7327
+ this._intervalStart = Date.now();
7328
+ this._nextInterval = setTimeout(() => {
7329
+ this._maybeUpdate();
7330
+ }, autorefreshThreshold);
7331
+ }
7332
+ _clearInterval() {
7333
+ if (this._nextInterval) {
7334
+ clearTimeout(this._nextInterval);
7335
+ this._intervalStart = null;
7336
+ }
7337
+ }
7338
+ /**
7339
+ * @internal
7340
+ */
7341
+ _updateSubscriptions() {
7342
+ if (this.isIdle) {
7343
+ return;
7344
+ }
7345
+ const requestId = this._request.lid;
7346
+
7347
+ // if we're already subscribed to this request, we don't need to do anything
7348
+ if (this._subscribedTo === requestId) {
7349
+ return;
7350
+ }
7351
+
7352
+ // if we're subscribed to a different request, we need to unsubscribe
7353
+ this._removeSubscriptions();
7354
+
7355
+ // if we have a request, we need to subscribe to it
7356
+ const {
7357
+ store
7358
+ } = this;
7359
+ if (requestId && isStore(store)) {
7360
+ this._subscribedTo = requestId;
7361
+ this._subscription = store.notifications.subscribe(requestId, (_id, op) => {
7362
+ // ignore subscription events that occur while our own component's request
7363
+ // is ocurring
7364
+ if (this._isUpdating) {
7365
+ return;
7366
+ }
7367
+ switch (op) {
7368
+ case 'invalidated':
7369
+ {
7370
+ // if we're subscribed to invalidations, we need to update
7371
+ if (this.autorefreshTypes.has('invalid')) {
7372
+ this._invalidated = true;
7373
+ this._maybeUpdate();
7374
+ }
7375
+ break;
7376
+ }
7377
+ case 'state':
7378
+ {
7379
+ const latest = store.requestManager._deduped.get(requestId);
7380
+ const priority = latest?.priority;
7381
+ const state = this.reqState;
7382
+ if (!priority) {
7383
+ // if there is no priority, we have completed whatever request
7384
+ // was occurring and so we are no longer refreshing (if we were)
7385
+ this.isRefreshing = false;
7386
+ } else if (priority.blocking && !state.isLoading) {
7387
+ // if we are blocking, there is an active request for this identity
7388
+ // that MUST be fulfilled from network (not cache).
7389
+ // Thus this is not "refreshing" because we should clear out and
7390
+ // block on this request.
7391
+ //
7392
+ // we receive state notifications when either a request initiates
7393
+ // or completes.
7394
+ //
7395
+ // In the completes case: we may receive the state notification
7396
+ // slightly before the request is finalized because the NotificationManager
7397
+ // may sync flush it (and thus deliver it before the microtask completes)
7398
+ //
7399
+ // In the initiates case: we aren't supposed to receive one unless there
7400
+ // is no other request in flight for this identity.
7401
+ //
7402
+ // However, there is a race condition here where the completed
7403
+ // notification can trigger an update that generates a new request
7404
+ // thus giving us an initiated notification before the older request
7405
+ // finalizes.
7406
+ //
7407
+ // When this occurs, if the triggered update happens to have caused
7408
+ // a new request to be made for the same identity AND that request
7409
+ // is the one passed into this component as the @request arg, then
7410
+ // getRequestState will return the state of the new request.
7411
+ // We can detect this by checking if the request state is "loading"
7412
+ // as outside of this case we would have a completed request.
7413
+ //
7414
+ // That is the reason for the `&& !state.isLoading` check above.
7415
+
7416
+ // TODO should we just treat this as refreshing?
7417
+ this.isRefreshing = false;
7418
+ this._maybeUpdate('policy', true);
7419
+ } else {
7420
+ this.isRefreshing = true;
7421
+ }
7422
+ }
7423
+ }
7424
+ });
7425
+ }
7426
+ }
7427
+
7428
+ /**
7429
+ * @internal
7430
+ */
7431
+ _removeSubscriptions() {
7432
+ if (this._subscription && isStore(this.store)) {
7433
+ this.store.notifications.unsubscribe(this._subscription);
7434
+ this._subscribedTo = null;
7435
+ this._subscription = null;
7436
+ }
7437
+ }
7438
+
7439
+ /**
7440
+ * Install the event listeners for network and visibility changes.
7441
+ * This is only done in browser environments with a global `window`.
7442
+ *
7443
+ * @internal
7444
+ */
7445
+ _installListeners() {
7446
+ if (typeof window === 'undefined') {
7447
+ return;
7448
+ }
7449
+ this.isOnline = window.navigator.onLine;
7450
+ this._unavailableStart = this.isOnline ? null : Date.now();
7451
+ this.isHidden = document.visibilityState === 'hidden';
7452
+ this._onlineChanged = event => {
7453
+ this.isOnline = event.type === 'online';
7454
+ if (event.type === 'offline' && this._unavailableStart === null) {
7455
+ this._unavailableStart = Date.now();
7456
+ }
7457
+ this._maybeUpdate();
7458
+ };
7459
+ this._backgroundChanged = () => {
7460
+ const isHidden = document.visibilityState === 'hidden';
7461
+ this.isHidden = isHidden;
7462
+ if (isHidden && this._unavailableStart === null) {
7463
+ this._unavailableStart = Date.now();
7464
+ }
7465
+ this._maybeUpdate();
7466
+ };
7467
+ window.addEventListener('online', this._onlineChanged, {
7468
+ passive: true,
7469
+ capture: true
7470
+ });
7471
+ window.addEventListener('offline', this._onlineChanged, {
7472
+ passive: true,
7473
+ capture: true
7474
+ });
7475
+ document.addEventListener('visibilitychange', this._backgroundChanged, {
7476
+ passive: true,
7477
+ capture: true
7478
+ });
7479
+ }
7480
+
7481
+ /**
7482
+ * If the network is online and the tab is visible, either reload or refresh the request
7483
+ * based on the component's configuration and the requested update mode.
7484
+ *
7485
+ * Valid modes are:
7486
+ *
7487
+ * - `'reload'`: Force a reload of the request.
7488
+ * - `'refresh'`: Refresh the request in the background.
7489
+ * - `'policy'`: Make the request, letting the store's configured CachePolicy decide whether to reload, refresh, or do nothing.
7490
+ * - `undefined`: Make the request using the component's autorefreshBehavior setting if the autorefreshThreshold has passed.
7491
+ *
7492
+ * @internal
7493
+ */
7494
+ _maybeUpdate(mode, silent) {
7495
+ if (this.isIdle) {
7496
+ return;
7497
+ }
7498
+ const canAttempt = Boolean(this.isOnline && !this.isHidden && (mode || this.autorefreshTypes.size));
7499
+ if (!canAttempt) {
7500
+ if (!silent && mode && mode !== '_invalidated') {
7501
+ throw new Error(`Reload not available: the network is not online or the tab is hidden`);
7502
+ }
7503
+ return;
7504
+ }
7505
+ const {
7506
+ autorefreshTypes
7507
+ } = this;
7508
+ let shouldAttempt = this._invalidated || Boolean(mode);
7509
+ if (!shouldAttempt && autorefreshTypes.has('online')) {
7510
+ const {
7511
+ _unavailableStart
7512
+ } = this;
7513
+ const {
7514
+ autorefreshThreshold
7515
+ } = this._args;
7516
+ const deadline = typeof autorefreshThreshold === 'number' ? autorefreshThreshold : DEFAULT_DEADLINE;
7517
+ shouldAttempt = Boolean(_unavailableStart && Date.now() - _unavailableStart > deadline);
7518
+ }
7519
+ if (!shouldAttempt && autorefreshTypes.has('interval')) {
7520
+ const {
7521
+ _intervalStart
7522
+ } = this;
7523
+ const {
7524
+ autorefreshThreshold
7525
+ } = this._args;
7526
+ if (_intervalStart && typeof autorefreshThreshold === 'number' && autorefreshThreshold > 0) {
7527
+ shouldAttempt = Boolean(Date.now() - _intervalStart >= autorefreshThreshold);
7528
+ }
7529
+ }
7530
+ this._unavailableStart = null;
7531
+ this._invalidated = false;
7532
+ if (shouldAttempt) {
7533
+ this._clearInterval();
7534
+ const request = Object.assign({}, this.reqState.request);
7535
+ const realMode = mode === '_invalidated' ? null : mode;
7536
+ const val = realMode ?? this._args.autorefreshBehavior ?? 'policy';
7537
+ switch (val) {
7538
+ case 'reload':
7539
+ request.cacheOptions = Object.assign({}, request.cacheOptions, {
7540
+ reload: true
7541
+ });
7542
+ break;
7543
+ case 'refresh':
7544
+ request.cacheOptions = Object.assign({}, request.cacheOptions, {
7545
+ backgroundReload: true
7546
+ });
7547
+ break;
7548
+ case 'policy':
7549
+ break;
7550
+ default:
7551
+ throw new Error(`Invalid ${mode ? 'update mode' : '@autorefreshBehavior'} for <Request />: ${isNeverString(val)}`);
7552
+ }
7553
+ const wasStoreRequest = request[EnableHydration] === true;
7554
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
7555
+ if (!test) {
7556
+ throw new Error(`Cannot supply a different store than was used to create the request`);
7557
+ }
7558
+ })(!request.store || request.store === this.store) : {};
7559
+ const store = request.store || this.store;
7560
+ const requester = wasStoreRequest && 'requestManager' in store ? store.requestManager : store;
7561
+ this._isUpdating = true;
7562
+ this._latestRequest = requester.request(request);
7563
+ if (val !== 'refresh') {
7564
+ this._localRequest = this._latestRequest;
7565
+ }
7566
+ void this._scheduleInterval();
7567
+ void this._latestRequest.finally(() => {
7568
+ this._isUpdating = false;
7569
+ });
7570
+ }
7571
+ }
7572
+
7573
+ /**
7574
+ * Retry the request, reloading it from the server.
7575
+ */
7576
+ retry = async () => {
7577
+ this._maybeUpdate('reload');
7578
+ await this._localRequest;
7579
+ };
7580
+
7581
+ /**
7582
+ * Refresh the request, updating it in the background.
7583
+ */
7584
+ refresh = async () => {
7585
+ this._maybeUpdate('refresh');
7586
+ await this._latestRequest;
7587
+ };
7588
+
7589
+ /**
7590
+ * features to yield to the error slot of a component
7591
+ */
7592
+ get errorFeatures() {
7593
+ return {
7594
+ isHidden: this.isHidden,
7595
+ isOnline: this.isOnline,
7596
+ retry: this.retry
7597
+ };
7598
+ }
7599
+
7600
+ /**
7601
+ * features to yield to the content slot of a component
7602
+ */
7603
+ static {
7604
+ decorateMethodV2(this.prototype, "errorFeatures", [memoized]);
7605
+ }
7606
+ get contentFeatures() {
7607
+ const feat = {
7608
+ isHidden: this.isHidden,
7609
+ isOnline: this.isOnline,
7610
+ reload: this.retry,
7611
+ refresh: this.refresh,
7612
+ isRefreshing: this.isRefreshing,
7613
+ latestRequest: this._latestRequest
7614
+ };
7615
+ if (feat.isRefreshing) {
7616
+ feat.abort = () => {
7617
+ this._latestRequest?.abort();
7618
+ };
7619
+ }
7620
+ return feat;
7621
+ }
7622
+
7623
+ /**
7624
+ * The method to call when the component this subscription is attached to
7625
+ * unmounts.
7626
+ */
7627
+ static {
7628
+ decorateMethodV2(this.prototype, "contentFeatures", [memoized]);
7629
+ }
7630
+ [DISPOSE]() {
7631
+ this.isDestroyed = true;
7632
+ this._removeSubscriptions();
7633
+ if (typeof window === 'undefined') {
7634
+ return;
7635
+ }
7636
+ this._clearInterval();
7637
+ window.removeEventListener('online', this._onlineChanged, {
7638
+ passive: true,
7639
+ capture: true
7640
+ });
7641
+ window.removeEventListener('offline', this._onlineChanged, {
7642
+ passive: true,
7643
+ capture: true
7644
+ });
7645
+ document.removeEventListener('visibilitychange', this._backgroundChanged, {
7646
+ passive: true,
7647
+ capture: true
7648
+ });
7649
+ }
7650
+
7651
+ /**
7652
+ * @internal
7653
+ */
7654
+ get _request() {
7655
+ const {
7656
+ request,
7657
+ query
7658
+ } = this._args;
7659
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
7660
+ if (!test) {
7661
+ throw new Error(`Cannot use both @request and @query args with the <Request> component`);
7662
+ }
7663
+ })(!request || !query) : {};
7664
+ const {
7665
+ _localRequest,
7666
+ _originalRequest,
7667
+ _originalQuery
7668
+ } = this;
7669
+ const isOriginalRequest = request === _originalRequest && query === _originalQuery;
7670
+ if (_localRequest && isOriginalRequest) {
7671
+ return _localRequest;
7672
+ }
7673
+
7674
+ // update state checks for the next time
7675
+ this._originalQuery = query;
7676
+ this._originalRequest = request;
7677
+ if (request) {
7678
+ return request;
7679
+ }
7680
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
7681
+ if (!test) {
7682
+ throw new Error(`You must provide either @request or an @query arg with the <Request> component`);
7683
+ }
7684
+ })(query) : {};
7685
+ // @ts-expect-error TODO investigate this
7686
+ return this.store.request(query);
7687
+ }
7688
+ static {
7689
+ decorateMethodV2(this.prototype, "_request", [memoized]);
7690
+ }
7691
+ get request() {
7692
+ if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
7693
+ try {
7694
+ const request = this._request;
7695
+ this._updateSubscriptions();
7696
+ return request;
7697
+ } catch (e) {
7698
+ // eslint-disable-next-line no-console
7699
+ console.log(e);
7700
+ throw new Error(`Unable to initialize the request`, {
7701
+ cause: e
7702
+ });
7703
+ }
7704
+ } else {
7705
+ const request = this._request;
7706
+ this._updateSubscriptions();
7707
+ return request;
7708
+ }
7709
+ }
7710
+ static {
7711
+ decorateMethodV2(this.prototype, "request", [memoized]);
7712
+ }
7713
+ get reqState() {
7714
+ return getRequestState(this.request);
7715
+ }
7716
+ get result() {
7717
+ return this.reqState.result;
7718
+ }
7719
+ }
7720
+ defineSignal(RequestSubscription.prototype, 'isOnline', true);
7721
+ defineSignal(RequestSubscription.prototype, 'isHidden', false);
7722
+ defineSignal(RequestSubscription.prototype, 'isRefreshing', false);
7723
+ defineSignal(RequestSubscription.prototype, '_localRequest', undefined);
7724
+ defineSignal(RequestSubscription.prototype, '_latestRequest', undefined);
7725
+ function isStore(store) {
7726
+ return 'requestManager' in store;
7727
+ }
7728
+ function createRequestSubscription(store, args) {
7729
+ return new RequestSubscription(store, args);
7730
+ }
6964
7731
  const RequestCache = new WeakMap();
6965
7732
  function isAbortError(error) {
6966
7733
  return error instanceof DOMException && error.name === 'AbortError';
@@ -7355,4 +8122,4 @@ function getRequestState(future) {
7355
8122
  }
7356
8123
  return state;
7357
8124
  }
7358
- export { peekInternalSignal as A, withSignalStore as B, Collection as C, notifyInternalSignal as D, consumeInternalSignal as E, getOrCreateInternalSignal as F, ReactiveDocument as G, setIdentifierGenerationMethod as H, IdentifierArray as I, setIdentifierUpdateMethod as J, setIdentifierForgetMethod as K, setIdentifierResetMethod as L, MUTATE as M, setKeyInfoForResource as N, RecordArrayManager as R, Store as S, _clearCaches as _, isDocumentIdentifier as a, coerceId as b, constructResource as c, SOURCE as d, ensureStringId as e, fastPush as f, removeRecordDataFor as g, setRecordIdentifier as h, isStableIdentifier as i, StoreMap as j, setCacheFor as k, RelatedCollection as l, log as m, normalizeModelName as n, logGroup as o, peekCache as p, getPromiseState as q, recordIdentifierFor as r, storeFor as s, getRequestState as t, memoized as u, gate as v, entangleSignal as w, defineSignal as x, defineNonEnumerableSignal as y, Signals as z };
8125
+ export { Signals as A, peekInternalSignal as B, Collection as C, DISPOSE as D, withSignalStore as E, notifyInternalSignal as F, consumeInternalSignal as G, getOrCreateInternalSignal as H, IdentifierArray as I, ReactiveDocument as J, setIdentifierGenerationMethod as K, setIdentifierUpdateMethod as L, MUTATE as M, setIdentifierForgetMethod as N, setIdentifierResetMethod as O, setKeyInfoForResource as P, isExtensionProp as Q, RecordArrayManager as R, Store as S, performExtensionSet as T, performArrayExtensionGet as U, performObjectExtensionGet as V, _clearCaches as _, isDocumentIdentifier as a, coerceId as b, constructResource as c, SOURCE as d, ensureStringId as e, fastPush as f, removeRecordDataFor as g, setRecordIdentifier as h, isStableIdentifier as i, StoreMap as j, setCacheFor as k, RelatedCollection as l, log as m, normalizeModelName as n, logGroup as o, peekCache as p, getPromiseState as q, recordIdentifierFor as r, storeFor as s, createRequestSubscription as t, getRequestState as u, memoized as v, gate as w, entangleSignal as x, defineSignal as y, defineNonEnumerableSignal as z };