@warp-drive/core 5.9.0-alpha.16 → 5.9.0-alpha.18
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/graph/-private/-state.d.ts +1 -0
- package/declarations/reactive/-private/default-mode.d.ts +22 -9
- package/declarations/reactive/-private/kind/belongs-to-field.d.ts +3 -0
- package/declarations/types/runtime.d.ts +16 -0
- package/declarations/types/schema/fields.d.ts +40 -12
- package/dist/graph/-private.js +56 -37
- package/dist/{index-CFwnjldF.js → index-BoY6aNE5.js} +88 -9
- package/dist/index.js +1 -1
- package/dist/reactive.js +1 -1
- package/dist/store/-private.js +1 -1
- package/dist/types/-private.js +1 -1
- package/dist/types/runtime.js +20 -1
- package/dist/unpkg/dev/graph/-private.js +56 -37
- package/dist/unpkg/dev/{index-BZRBBa34.js → index-BZ6PKU-a.js} +88 -9
- package/dist/unpkg/dev/index.js +1 -1
- package/dist/unpkg/dev/reactive.js +1 -1
- package/dist/unpkg/dev/store/-private.js +2 -2
- package/dist/unpkg/dev/types/-private.js +1 -1
- package/dist/unpkg/dev/types/runtime.js +20 -1
- package/dist/unpkg/dev-deprecated/graph/-private.js +56 -37
- package/dist/unpkg/dev-deprecated/{index-Bu52tQ9I.js → index-CDjd631s.js} +88 -9
- package/dist/unpkg/dev-deprecated/index.js +1 -1
- package/dist/unpkg/dev-deprecated/reactive.js +1 -1
- package/dist/unpkg/dev-deprecated/store/-private.js +1 -1
- package/dist/unpkg/dev-deprecated/types/-private.js +1 -1
- package/dist/unpkg/dev-deprecated/types/runtime.js +20 -1
- package/dist/unpkg/prod/{-leaked-BHLmJyaw.js → -leaked-DgjQ5X55.js} +2 -2
- package/dist/unpkg/prod/configure.js +1 -1
- package/dist/unpkg/prod/graph/-private.js +23 -26
- package/dist/unpkg/prod/{schema-BdC3DirM.js → index-BMBm3kYx.js} +2256 -91
- package/dist/unpkg/prod/index.js +5 -483
- package/dist/unpkg/prod/{promise-cache-DIT8Ypjq.js → promise-cache-DUblkX-U.js} +1 -1
- package/dist/unpkg/prod/reactive.js +3 -29
- package/dist/unpkg/prod/{request-BrJSCG6r.js → request-eb7Zm-oS.js} +1 -1
- package/dist/unpkg/prod/request.js +2 -2
- package/dist/unpkg/prod/signals/-leaked.js +1 -1
- package/dist/unpkg/prod/store/-private.js +2 -3
- package/dist/unpkg/prod/types/-private.js +1 -1
- package/dist/unpkg/prod/types/runtime.js +20 -1
- package/dist/unpkg/prod-deprecated/{-leaked-D_5Yrs5c.js → -leaked-BNVttukY.js} +1 -1
- package/dist/unpkg/prod-deprecated/configure.js +1 -1
- package/dist/unpkg/prod-deprecated/graph/-private.js +23 -26
- package/dist/unpkg/prod-deprecated/{schema-h0nuUTCj.js → index-CZkDXZog.js} +890 -7
- package/dist/unpkg/prod-deprecated/index.js +5 -483
- package/dist/unpkg/prod-deprecated/{promise-cache-DIT8Ypjq.js → promise-cache-DUblkX-U.js} +1 -1
- package/dist/unpkg/prod-deprecated/reactive.js +2 -3
- package/dist/unpkg/prod-deprecated/{request-BrJSCG6r.js → request-eb7Zm-oS.js} +1 -1
- package/dist/unpkg/prod-deprecated/request.js +2 -2
- package/dist/unpkg/prod-deprecated/signals/-leaked.js +1 -1
- package/dist/unpkg/prod-deprecated/store/-private.js +1 -2
- package/dist/unpkg/prod-deprecated/types/-private.js +1 -1
- package/dist/unpkg/prod-deprecated/types/runtime.js +20 -1
- package/package.json +3 -3
- package/dist/unpkg/prod/handler-BJogFbfS.js +0 -1619
- package/dist/unpkg/prod-deprecated/handler-kGR8zguj.js +0 -334
- package/dist/unpkg/prod-deprecated/hooks-wJdveHPi.js +0 -26
|
@@ -2,6 +2,7 @@ import { d as defineGate, w as withSignalStore, n as notifyInternalSignal, p as
|
|
|
2
2
|
import { EnableHydration, SkipCache, STRUCTURED } from './types/request.js';
|
|
3
3
|
import { D as Destroy, a as Context, S as SOURCE, C as Checkout, b as Commit } from "./-private-3C1OkYtZ.js";
|
|
4
4
|
import { isResourceSchema } from './types/schema/fields.js';
|
|
5
|
+
import { setLogging, getRuntimeConfig, setIsMaybeMirage } from './types/runtime.js';
|
|
5
6
|
import { a as cloneResponseProperties, I as IS_CACHE_HANDLER, b as assertValidRequest, e as executeNextHandler, d as getRequestResult, u as upgradePromise, s as setPromiseResult, f as clearRequestResult } from "./future-DUuPqyLj.js";
|
|
6
7
|
import { getOrSetGlobal, peekTransient, setTransient, peekUniversalTransient, setUniversalTransient } from './types/-private.js';
|
|
7
8
|
import { DefaultCachePolicy } from './store.js';
|
|
@@ -9,7 +10,6 @@ import { withBrand } from './request.js';
|
|
|
9
10
|
import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_KEY_TYPE, DEBUG_CLIENT_ORIGINATED } from './types/identifier.js';
|
|
10
11
|
import { dasherize } from './utils/string.js';
|
|
11
12
|
import { g as getGlobalConfig } from "./runtime-DfhJzpZH.js";
|
|
12
|
-
import { setLogging, getRuntimeConfig } from './types/runtime.js';
|
|
13
13
|
import { RecordStore, Type } from './types/symbols.js';
|
|
14
14
|
import * as _importSync20 from '@ember/object';
|
|
15
15
|
function urlFromLink(link) {
|
|
@@ -7248,11 +7248,32 @@ function getBelongsToField(context) {
|
|
|
7248
7248
|
}
|
|
7249
7249
|
function setBelongsToField(context) {
|
|
7250
7250
|
const {
|
|
7251
|
+
field,
|
|
7252
|
+
resourceKey,
|
|
7251
7253
|
store
|
|
7252
7254
|
} = context;
|
|
7253
7255
|
const {
|
|
7254
|
-
schema
|
|
7256
|
+
schema,
|
|
7257
|
+
cache
|
|
7255
7258
|
} = store;
|
|
7259
|
+
|
|
7260
|
+
/**
|
|
7261
|
+
* We currently only allow editing sync belongsTo relationships
|
|
7262
|
+
* in PolarisMode
|
|
7263
|
+
*/
|
|
7264
|
+
const isValidPolarisConfig = field.options.linksMode && !field.options.async;
|
|
7265
|
+
if (!context.legacy && isValidPolarisConfig) {
|
|
7266
|
+
const name = context.path.at(-1);
|
|
7267
|
+
cache.mutate({
|
|
7268
|
+
op: 'replaceRelatedRecord',
|
|
7269
|
+
record: resourceKey,
|
|
7270
|
+
field: name,
|
|
7271
|
+
value: getResourceKey(context.value)
|
|
7272
|
+
},
|
|
7273
|
+
// @ts-expect-error
|
|
7274
|
+
true);
|
|
7275
|
+
return true;
|
|
7276
|
+
}
|
|
7256
7277
|
(test => {
|
|
7257
7278
|
if (!test) {
|
|
7258
7279
|
throw new Error(`Can only mutate belongsTo fields when the resource is in legacy mode`);
|
|
@@ -7261,6 +7282,12 @@ function setBelongsToField(context) {
|
|
|
7261
7282
|
schema._kind('@legacy', 'belongsTo').set(store, context.record, context.resourceKey, context.field, context.value);
|
|
7262
7283
|
return true;
|
|
7263
7284
|
}
|
|
7285
|
+
function getResourceKey(record) {
|
|
7286
|
+
if (!record) {
|
|
7287
|
+
return null;
|
|
7288
|
+
}
|
|
7289
|
+
return recordIdentifierFor(record);
|
|
7290
|
+
}
|
|
7264
7291
|
function getCollectionField(context) {
|
|
7265
7292
|
entangleSignal(context.signals, context.record, context.path.at(-1), null);
|
|
7266
7293
|
(test => {
|
|
@@ -7993,6 +8020,17 @@ function setSchemaObjectField(context) {
|
|
|
7993
8020
|
// }
|
|
7994
8021
|
return true;
|
|
7995
8022
|
}
|
|
8023
|
+
|
|
8024
|
+
/**
|
|
8025
|
+
* A ReactiveResource context object passed to
|
|
8026
|
+
* the get/set functions of a field kind implementation.
|
|
8027
|
+
*
|
|
8028
|
+
* This provides all the necessary information for
|
|
8029
|
+
* the field kind to perform its operations.
|
|
8030
|
+
*
|
|
8031
|
+
* @internal
|
|
8032
|
+
*/
|
|
8033
|
+
|
|
7996
8034
|
const DefaultMode = {
|
|
7997
8035
|
'@hash': {
|
|
7998
8036
|
get: getHashField,
|
|
@@ -8786,6 +8824,14 @@ const TypeField = {
|
|
|
8786
8824
|
key: 'type'
|
|
8787
8825
|
}
|
|
8788
8826
|
};
|
|
8827
|
+
const IdentifierField = {
|
|
8828
|
+
type: '@identity',
|
|
8829
|
+
name: '$key',
|
|
8830
|
+
kind: 'derived',
|
|
8831
|
+
options: {
|
|
8832
|
+
key: '^'
|
|
8833
|
+
}
|
|
8834
|
+
};
|
|
8789
8835
|
const DefaultIdentityField = {
|
|
8790
8836
|
name: 'id',
|
|
8791
8837
|
kind: '@id'
|
|
@@ -8974,6 +9020,7 @@ function withDefaults(schema) {
|
|
|
8974
9020
|
// we add TypeField to the beginning so that it will
|
|
8975
9021
|
// appear right next to the identity field
|
|
8976
9022
|
schema.fields.unshift(TypeField);
|
|
9023
|
+
schema.fields.unshift(IdentifierField);
|
|
8977
9024
|
schema.fields.push(ConstructorField);
|
|
8978
9025
|
return schema;
|
|
8979
9026
|
}
|
|
@@ -9490,9 +9537,33 @@ function cloneResponse(response, overrides) {
|
|
|
9490
9537
|
const props = cloneResponseProperties(response);
|
|
9491
9538
|
return new Response(response.body, Object.assign(props, overrides));
|
|
9492
9539
|
}
|
|
9540
|
+
function withDateHeader(response) {
|
|
9541
|
+
const headers = new Headers(response.headers);
|
|
9542
|
+
headers.set('date', new Date().toUTCString());
|
|
9543
|
+
return cloneResponse(response, {
|
|
9544
|
+
headers
|
|
9545
|
+
});
|
|
9546
|
+
}
|
|
9547
|
+
|
|
9548
|
+
// Detects Mirage (or another Pretender-based fetch mock), whose `Response`
|
|
9549
|
+
// may (unlike a spec-compliant `fetch()`, whose Response headers are always
|
|
9550
|
+
// immutable) allow header mutation and may not support streaming reads.
|
|
9551
|
+
//
|
|
9552
|
+
// This is inherently a heuristic - many legitimate tools (APM/monitoring
|
|
9553
|
+
// agents, browser extensions, polyfills) also patch `window.fetch`, and can
|
|
9554
|
+
// produce false positives. `setWarpDriveIsMaybeMirage(value)` lets an app
|
|
9555
|
+
// declare the answer explicitly (`true` or `false`), overriding the
|
|
9556
|
+
// heuristic in either direction; leave it unset to keep the default
|
|
9557
|
+
// detection. See https://github.com/warp-drive-data/warp-drive/issues/10535
|
|
9493
9558
|
let IS_MAYBE_MIRAGE = () => false;
|
|
9494
9559
|
{
|
|
9495
|
-
IS_MAYBE_MIRAGE = () =>
|
|
9560
|
+
IS_MAYBE_MIRAGE = () => {
|
|
9561
|
+
const override = getRuntimeConfig().mirage;
|
|
9562
|
+
if (override !== undefined) {
|
|
9563
|
+
return override;
|
|
9564
|
+
}
|
|
9565
|
+
return Boolean(typeof window !== 'undefined' && (window.server?.pretender || window.fetch.toString().replace(/\s+/g, '') !== 'function fetch() { [native code] }'.replace(/\s+/g, '')));
|
|
9566
|
+
};
|
|
9496
9567
|
}
|
|
9497
9568
|
const MUTATION_OPS = new Set(['updateRecord', 'createRecord', 'deleteRecord']);
|
|
9498
9569
|
const ERROR_STATUS_CODE_FOR = new Map([[400, 'Bad Request'], [401, 'Unauthorized'], [402, 'Payment Required'], [403, 'Forbidden'], [404, 'Not Found'], [405, 'Method Not Allowed'], [406, 'Not Acceptable'], [407, 'Proxy Authentication Required'], [408, 'Request Timeout'], [409, 'Conflict'], [410, 'Gone'], [411, 'Length Required'], [412, 'Precondition Failed'], [413, 'Payload Too Large'], [414, 'URI Too Long'], [415, 'Unsupported Media Type'], [416, 'Range Not Satisfiable'], [417, 'Expectation Failed'], [419, 'Page Expired'], [420, 'Enhance Your Calm'], [421, 'Misdirected Request'], [422, 'Unprocessable Entity'], [423, 'Locked'], [424, 'Failed Dependency'], [425, 'Too Early'], [426, 'Upgrade Required'], [428, 'Precondition Required'], [429, 'Too Many Requests'], [430, 'Request Header Fields Too Large'], [431, 'Request Header Fields Too Large'], [450, 'Blocked By Windows Parental Controls'], [451, 'Unavailable For Legal Reasons'], [500, 'Internal Server Error'], [501, 'Not Implemented'], [502, 'Bad Gateway'], [503, 'Service Unavailable'], [504, 'Gateway Timeout'], [505, 'HTTP Version Not Supported'], [506, 'Variant Also Negotiates'], [507, 'Insufficient Storage'], [508, 'Loop Detected'], [509, 'Bandwidth Limit Exceeded'], [510, 'Not Extended'], [511, 'Network Authentication Required']]);
|
|
@@ -9544,13 +9615,15 @@ const Fetch = {
|
|
|
9544
9615
|
const isMutationOp = Boolean(op && MUTATION_OPS.has(op));
|
|
9545
9616
|
if (!isError && !isMutationOp && response.status !== 204 && !response.headers.has('date')) {
|
|
9546
9617
|
if (IS_MAYBE_MIRAGE()) {
|
|
9547
|
-
|
|
9618
|
+
try {
|
|
9619
|
+
response.headers.set('date', new Date().toUTCString());
|
|
9620
|
+
} catch {
|
|
9621
|
+
// IS_MAYBE_MIRAGE() was a false positive, or the mock's headers
|
|
9622
|
+
// are (correctly) immutable - fall back to cloning.
|
|
9623
|
+
response = withDateHeader(response);
|
|
9624
|
+
}
|
|
9548
9625
|
} else {
|
|
9549
|
-
|
|
9550
|
-
headers.set('date', new Date().toUTCString());
|
|
9551
|
-
response = cloneResponse(response, {
|
|
9552
|
-
headers
|
|
9553
|
-
});
|
|
9626
|
+
response = withDateHeader(response);
|
|
9554
9627
|
}
|
|
9555
9628
|
}
|
|
9556
9629
|
context.setResponse(response);
|
|
@@ -9945,6 +10018,12 @@ class RequestManager {
|
|
|
9945
10018
|
globalThis.getWarpDriveRuntimeConfig = getRuntimeConfig;
|
|
9946
10019
|
}
|
|
9947
10020
|
|
|
10021
|
+
// Mirage (or another Pretender-based fetch mock) may be used outside of a
|
|
10022
|
+
// `TESTING` build (e.g. `ember serve` in dev mode), so this override is
|
|
10023
|
+
// exposed unconditionally rather than gated to the `TESTING` env.
|
|
10024
|
+
// @ts-expect-error adding to globalThis
|
|
10025
|
+
globalThis.setWarpDriveIsMaybeMirage = setIsMaybeMirage;
|
|
10026
|
+
|
|
9948
10027
|
/**
|
|
9949
10028
|
* Options for setting up a Store instance with `useRecommendedStore`.
|
|
9950
10029
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as CacheHandler, F as Fetch, z as RequestManager, S as Store, r as cacheKeyFor, r as recordIdentifierFor, E as setIdentifierForgetMethod, B as setIdentifierGenerationMethod, G as setIdentifierResetMethod, D as setIdentifierUpdateMethod, H as setKeyInfoForResource, s as storeFor, A as useRecommendedStore } from "./index-
|
|
1
|
+
export { C as CacheHandler, F as Fetch, z as RequestManager, S as Store, r as cacheKeyFor, r as recordIdentifierFor, E as setIdentifierForgetMethod, B as setIdentifierGenerationMethod, G as setIdentifierResetMethod, D as setIdentifierUpdateMethod, H as setKeyInfoForResource, s as storeFor, A as useRecommendedStore } from "./index-CDjd631s.js";
|
|
2
2
|
import "./-private-3C1OkYtZ.js";
|
|
3
3
|
import "./-leaked-C40gfiH-.js";
|
|
4
4
|
import './store.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { u as SchemaService, p as checkout, y as commit, v as fromIdentity, q as instantiateRecord, x as registerDerivations, t as teardownRecord, w as withDefaults } from "./index-
|
|
1
|
+
export { u as SchemaService, p as checkout, y as commit, v as fromIdentity, q as instantiateRecord, x as registerDerivations, t as teardownRecord, w as withDefaults } from "./index-CDjd631s.js";
|
|
2
2
|
export { C as Checkout } from "./-private-3C1OkYtZ.js";
|
|
3
3
|
export { c as createRequestSubscription, a as getPromiseState, g as getRequestState } from "./-leaked-C40gfiH-.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as CacheHandler, R as RecordArrayManager, S as Store, k as StoreMap, _ as _clearCaches, n as _deprecatingNormalize, h as assertPrivateCapabilities, d as assertPrivateStore, b as coerceId, c as constructResource, l as createLegacyManyArray, e as ensureStringId, f as fastPush, g as isPrivateStore, a as isRequestKey, i as isResourceKey, m as log, o as logGroup, r as recordIdentifierFor, j as setRecordIdentifier, s as storeFor } from "../index-
|
|
1
|
+
export { C as CacheHandler, R as RecordArrayManager, S as Store, k as StoreMap, _ as _clearCaches, n as _deprecatingNormalize, h as assertPrivateCapabilities, d as assertPrivateStore, b as coerceId, c as constructResource, l as createLegacyManyArray, e as ensureStringId, f as fastPush, g as isPrivateStore, a as isRequestKey, i as isResourceKey, m as log, o as logGroup, r as recordIdentifierFor, j as setRecordIdentifier, s as storeFor } from "../index-CDjd631s.js";
|
|
@@ -31,4 +31,23 @@ function setLogging(config) {
|
|
|
31
31
|
Object.assign(RuntimeConfig.debug, config);
|
|
32
32
|
storage?.setItem('WarpDriveRuntimeConfig', JSON.stringify(RuntimeConfig));
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Explicitly declares whether requests may be served by Mirage (or another
|
|
37
|
+
* Pretender-based fetch mock) instead of a native `fetch` implementation.
|
|
38
|
+
*
|
|
39
|
+
* The `Fetch` request handler otherwise infers this via a heuristic (the
|
|
40
|
+
* presence of `window.server.pretender`, or `window.fetch` appearing to be
|
|
41
|
+
* patched), which can be wrong in either direction: some Mirage setups don't
|
|
42
|
+
* expose `window.server`, while some unrelated tools (APM agents, browser
|
|
43
|
+
* extensions) also patch `fetch`. Call this to override that heuristic:
|
|
44
|
+
* `true` to force Mirage-compatible behavior on, `false` to force it off.
|
|
45
|
+
*
|
|
46
|
+
* globalThis.setWarpDriveIsMaybeMirage(true);
|
|
47
|
+
*
|
|
48
|
+
*/
|
|
49
|
+
function setIsMaybeMirage(value) {
|
|
50
|
+
RuntimeConfig.mirage = value;
|
|
51
|
+
storage?.setItem('WarpDriveRuntimeConfig', JSON.stringify(RuntimeConfig));
|
|
52
|
+
}
|
|
53
|
+
export { getRuntimeConfig, setIsMaybeMirage, setLogging };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { peekTransient, getOrSetGlobal, setTransient } from './types/-private.js';
|
|
2
|
-
import {
|
|
2
|
+
import { g as getPromiseResult, a as setPromiseResult } from "./promise-cache-DUblkX-U.js";
|
|
3
3
|
|
|
4
4
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
5
5
|
|
|
@@ -1673,4 +1673,4 @@ function getPromiseState(promise) {
|
|
|
1673
1673
|
}
|
|
1674
1674
|
return state;
|
|
1675
1675
|
}
|
|
1676
|
-
export { ARRAY_SIGNAL as A, DISPOSE as D, OBJECT_SIGNAL as O, Signals as S,
|
|
1676
|
+
export { ARRAY_SIGNAL as A, DISPOSE as D, OBJECT_SIGNAL as O, Signals as S, willSyncFlushWatchers as a, createInternalSignal as b, consumeInternalSignal as c, defineGate as d, createSignalDescriptor as e, defineSignal as f, getOrCreateInternalSignal as g, entangleSignal as h, entangleInitiallyStaleSignal as i, createInternalMemo as j, createRequestSubscription as k, getRequestState as l, getPromiseState as m, notifyInternalSignal as n, defineNonEnumerableSignal as o, peekInternalSignal as p, makeInitializer as q, signal as r, setupSignals as s, waitFor as t, gate as u, memoized as v, withSignalStore as w };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { s as setupSignals } from "./-leaked-
|
|
1
|
+
export { s as setupSignals } from "./-leaked-DgjQ5X55.js";
|
|
2
2
|
import './types/-private.js';
|
|
@@ -789,8 +789,10 @@ function replaceRelatedRecord(graph, op, isRemote = false) {
|
|
|
789
789
|
if (op.value === existingState) {
|
|
790
790
|
// if we were empty before but now know we are empty this needs to be true
|
|
791
791
|
state.hasReceivedData = true;
|
|
792
|
+
|
|
792
793
|
// if this is a remote update we still sync
|
|
793
794
|
if (isRemote) {
|
|
795
|
+
state.hasReceivedRemoteData = true;
|
|
794
796
|
const {
|
|
795
797
|
localState
|
|
796
798
|
} = relationship;
|
|
@@ -813,6 +815,15 @@ function replaceRelatedRecord(graph, op, isRemote = false) {
|
|
|
813
815
|
// update value to the new value
|
|
814
816
|
relationship[prop] = op.value;
|
|
815
817
|
state.hasReceivedData = true;
|
|
818
|
+
/**
|
|
819
|
+
* Local mutations never give us additional information about
|
|
820
|
+
* whether the relationship has received *remote* data. This is
|
|
821
|
+
* what `getRemoteRelationship` relies on to avoid reflecting
|
|
822
|
+
* local-only edits.
|
|
823
|
+
*/
|
|
824
|
+
if (isRemote) {
|
|
825
|
+
state.hasReceivedRemoteData = true;
|
|
826
|
+
}
|
|
816
827
|
state.isEmpty = op.value === null;
|
|
817
828
|
state.isStale = false;
|
|
818
829
|
state.hasFailedLoadAttempt = false;
|
|
@@ -979,7 +990,12 @@ function diffCollection(finalState, relationship, onAdd, onDel) {
|
|
|
979
990
|
return _compare(priorLocalState, finalState, finalSet, remoteState, remoteMembers, onAdd, onDel, relationship.definition.resetOnRemoteUpdate);
|
|
980
991
|
}
|
|
981
992
|
function computeLocalState(storage) {
|
|
982
|
-
|
|
993
|
+
// When the edge is clean and we already have a materialized localState we can
|
|
994
|
+
// return it directly. A clean edge can still have a `null` localState though:
|
|
995
|
+
// dematerializing an inverse member (e.g. when a route reloads its model)
|
|
996
|
+
// nulls out localState without dirtying the edge. In that case we fall through
|
|
997
|
+
// and recompute from remoteState rather than asserting.
|
|
998
|
+
if (!storage.isDirty && storage.localState) {
|
|
983
999
|
return storage.localState;
|
|
984
1000
|
}
|
|
985
1001
|
const state = storage.remoteState.slice();
|
|
@@ -1201,6 +1217,7 @@ function rollbackRelationship(graph, key, field, relationship) {
|
|
|
1201
1217
|
function createState() {
|
|
1202
1218
|
return {
|
|
1203
1219
|
hasReceivedData: false,
|
|
1220
|
+
hasReceivedRemoteData: false,
|
|
1204
1221
|
isEmpty: true,
|
|
1205
1222
|
isStale: false,
|
|
1206
1223
|
hasFailedLoadAttempt: false,
|
|
@@ -1305,13 +1322,10 @@ function legacyGetResourceRelationshipData(source, getRemoteState) {
|
|
|
1305
1322
|
source.accessed = true;
|
|
1306
1323
|
let data;
|
|
1307
1324
|
const payload = {};
|
|
1308
|
-
if (getRemoteState && source.remoteState) {
|
|
1309
|
-
data = source.remoteState;
|
|
1310
|
-
} else if (!getRemoteState && source.localState) {
|
|
1311
|
-
data = source.localState;
|
|
1312
|
-
}
|
|
1313
|
-
if ((getRemoteState && source.remoteState === null || source.localState === null) && source.state.hasReceivedData) {
|
|
1314
|
-
data = null;
|
|
1325
|
+
if (getRemoteState && (source.remoteState || source.state.hasReceivedRemoteData)) {
|
|
1326
|
+
data = source.remoteState ?? null;
|
|
1327
|
+
} else if (!getRemoteState && (source.localState || source.state.hasReceivedData)) {
|
|
1328
|
+
data = source.localState ?? null;
|
|
1315
1329
|
}
|
|
1316
1330
|
if (source.links) {
|
|
1317
1331
|
payload.links = source.links;
|
|
@@ -1488,7 +1502,6 @@ function updateRelationshipOperation(graph, op) {
|
|
|
1488
1502
|
const relationship = graph.get(op.record, op.field);
|
|
1489
1503
|
const {
|
|
1490
1504
|
definition,
|
|
1491
|
-
state,
|
|
1492
1505
|
identifier
|
|
1493
1506
|
} = relationship;
|
|
1494
1507
|
const {
|
|
@@ -1523,23 +1536,6 @@ function updateRelationshipOperation(graph, op) {
|
|
|
1523
1536
|
value: payload.data ? graph.store.cacheKeyManager.upgradeIdentifier(payload.data) : null
|
|
1524
1537
|
}, true);
|
|
1525
1538
|
}
|
|
1526
|
-
} else if (definition.isAsync === false && !state.hasReceivedData) {
|
|
1527
|
-
hasRelationshipDataProperty = true;
|
|
1528
|
-
if (isCollection) {
|
|
1529
|
-
graph.update({
|
|
1530
|
-
op: 'replaceRelatedRecords',
|
|
1531
|
-
record: identifier,
|
|
1532
|
-
field: op.field,
|
|
1533
|
-
value: []
|
|
1534
|
-
}, true);
|
|
1535
|
-
} else {
|
|
1536
|
-
graph.update({
|
|
1537
|
-
op: 'replaceRelatedRecord',
|
|
1538
|
-
record: identifier,
|
|
1539
|
-
field: op.field,
|
|
1540
|
-
value: null
|
|
1541
|
-
}, true);
|
|
1542
|
-
}
|
|
1543
1539
|
}
|
|
1544
1540
|
if (payload.links) {
|
|
1545
1541
|
const originalLinks = relationship.links;
|
|
@@ -1574,6 +1570,7 @@ function updateRelationshipOperation(graph, op) {
|
|
|
1574
1570
|
// we don't need to notify here as the update op we pushed in above will notify once
|
|
1575
1571
|
// membership is in the correct state.
|
|
1576
1572
|
relationship.state.hasReceivedData = true;
|
|
1573
|
+
relationship.state.hasReceivedRemoteData = true;
|
|
1577
1574
|
relationship.state.isStale = false;
|
|
1578
1575
|
relationship.state.hasDematerializedInverse = false;
|
|
1579
1576
|
relationship.state.isEmpty = relationshipIsEmpty;
|