@warp-drive-mirror/core 5.9.0-alpha.17 → 5.9.0-alpha.19
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/index.d.ts +10 -1
- 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 +67 -52
- package/dist/{index-CFwnjldF.js → index-LI2ckwf9.js} +332 -10
- 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 +67 -52
- package/dist/unpkg/dev/{index-BZRBBa34.js → index-DU_HLpg-.js} +332 -10
- 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 +67 -52
- package/dist/unpkg/dev-deprecated/{index-Bu52tQ9I.js → index-BYFUHVPd.js} +332 -10
- 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 +17 -25
- package/dist/unpkg/prod/{schema-BdC3DirM.js → index-C-AhVafS.js} +2383 -73
- 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 +17 -25
- package/dist/unpkg/prod-deprecated/{schema-h0nuUTCj.js → index-CplZl2hv.js} +1035 -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
package/declarations/index.d.ts
CHANGED
|
@@ -39,8 +39,17 @@ export interface StoreSetupOptions<T extends Cache = Cache> {
|
|
|
39
39
|
* The request handlers to use. {@link Fetch} will automatically
|
|
40
40
|
* be added to the end of the handler chain and {@link CacheHandler}
|
|
41
41
|
* will automatically be added as the cache handler.
|
|
42
|
+
*
|
|
43
|
+
* May also be given as a function that receives the {@link Store} instance
|
|
44
|
+
* and returns the handlers to use. This is useful when a handler needs
|
|
45
|
+
* access to the store (e.g. to look up its owner for injections) or when
|
|
46
|
+
* the set of handlers should be decided lazily (e.g. based on a feature
|
|
47
|
+
* flag service that may not be ready until after the store is constructed).
|
|
48
|
+
*
|
|
49
|
+
* The function is invoked lazily, the first time the store's `requestManager`
|
|
50
|
+
* is accessed, and only once per store instance.
|
|
42
51
|
*/
|
|
43
|
-
handlers?: Handler[];
|
|
52
|
+
handlers?: Handler[] | ((store: Store) => Handler[]);
|
|
44
53
|
/**
|
|
45
54
|
* Schemas describing the structure of your resource data.
|
|
46
55
|
*
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import type { SignalStore } from "../../signals/-private.js";
|
|
2
1
|
import type { Store } from "../../store/-private.js";
|
|
3
2
|
import type { ResourceKey } from "../../types.js";
|
|
4
3
|
import type { FieldSchema, HashField, IdentityField, SchemaArrayField, SchemaObjectField } from "../../types/schema/fields.js";
|
|
5
|
-
import type { ReactiveResource } from "./record.js";
|
|
6
4
|
export type PathLike = string | symbol | Array<string | symbol>;
|
|
7
5
|
export type ModeName = "polaris" | "legacy";
|
|
8
6
|
export interface ModeInfo {
|
|
@@ -11,10 +9,32 @@ export interface ModeInfo {
|
|
|
11
9
|
editable: boolean;
|
|
12
10
|
}
|
|
13
11
|
export interface BaseContext {
|
|
12
|
+
/**
|
|
13
|
+
* The {@link Store} instance that owns
|
|
14
|
+
* the reactive context we are within.
|
|
15
|
+
*/
|
|
14
16
|
store: Store;
|
|
17
|
+
/**
|
|
18
|
+
* The {@link ResourceKey} of the resource that
|
|
19
|
+
* the reactive context we are within is for.
|
|
20
|
+
*/
|
|
15
21
|
resourceKey: ResourceKey;
|
|
22
|
+
/**
|
|
23
|
+
* The name of the {@link ModeName | mode} that the
|
|
24
|
+
* reactive context we are within is operating in.
|
|
25
|
+
*/
|
|
16
26
|
modeName: ModeName;
|
|
27
|
+
/**
|
|
28
|
+
* Whether we are in legacy {@link ModeName | mode}
|
|
29
|
+
* or not.
|
|
30
|
+
*/
|
|
17
31
|
legacy: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Whether the ReactiveResource instance we are operating
|
|
34
|
+
* in is currently editable or not. This should be true if the
|
|
35
|
+
* record is currently checked out for editing or is in legacy mode
|
|
36
|
+
* and false if the record is currently in a read-only state.
|
|
37
|
+
*/
|
|
18
38
|
editable: boolean;
|
|
19
39
|
}
|
|
20
40
|
export interface ResourceContext extends BaseContext {
|
|
@@ -27,13 +47,6 @@ export interface ObjectContext extends BaseContext {
|
|
|
27
47
|
field: SchemaObjectField | SchemaArrayField;
|
|
28
48
|
value: string;
|
|
29
49
|
}
|
|
30
|
-
export interface KindContext<T extends FieldSchema | IdentityField | HashField> extends BaseContext {
|
|
31
|
-
path: string[];
|
|
32
|
-
field: T;
|
|
33
|
-
value: unknown;
|
|
34
|
-
record: ReactiveResource;
|
|
35
|
-
signals: SignalStore;
|
|
36
|
-
}
|
|
37
50
|
export interface KindImpl<T extends FieldSchema | IdentityField | HashField> {
|
|
38
51
|
/**
|
|
39
52
|
* A function which produces the value for the field when invoked.
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { ResourceKey } from "../../../types.js";
|
|
1
2
|
import type { LegacyBelongsToField } from "../../../types/schema/fields.js";
|
|
2
3
|
import type { KindContext } from "../default-mode.js";
|
|
4
|
+
import type { ReactiveResource } from "../record.js";
|
|
3
5
|
export declare function getBelongsToField(context: KindContext<LegacyBelongsToField>): unknown;
|
|
4
6
|
export declare function setBelongsToField(context: KindContext<LegacyBelongsToField>): boolean;
|
|
7
|
+
export declare function getResourceKey(record: ReactiveResource | null): ResourceKey | null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { LOG_CONFIG } from "@warp-drive-mirror/build-config/-private/utils/logging";
|
|
2
2
|
declare const RuntimeConfig: {
|
|
3
3
|
debug: Partial<LOG_CONFIG>;
|
|
4
|
+
mirage?: boolean;
|
|
4
5
|
};
|
|
5
6
|
export declare function getRuntimeConfig(): typeof RuntimeConfig;
|
|
6
7
|
/**
|
|
@@ -11,4 +12,19 @@ export declare function getRuntimeConfig(): typeof RuntimeConfig;
|
|
|
11
12
|
*
|
|
12
13
|
*/
|
|
13
14
|
export declare function setLogging(config: Partial<LOG_CONFIG>): void;
|
|
15
|
+
/**
|
|
16
|
+
* Explicitly declares whether requests may be served by Mirage (or another
|
|
17
|
+
* Pretender-based fetch mock) instead of a native `fetch` implementation.
|
|
18
|
+
*
|
|
19
|
+
* The `Fetch` request handler otherwise infers this via a heuristic (the
|
|
20
|
+
* presence of `window.server.pretender`, or `window.fetch` appearing to be
|
|
21
|
+
* patched), which can be wrong in either direction: some Mirage setups don't
|
|
22
|
+
* expose `window.server`, while some unrelated tools (APM agents, browser
|
|
23
|
+
* extensions) also patch `fetch`. Call this to override that heuristic:
|
|
24
|
+
* `true` to force Mirage-compatible behavior on, `false` to force it off.
|
|
25
|
+
*
|
|
26
|
+
* globalThis.setWarpDriveIsMaybeMirage(true);
|
|
27
|
+
*
|
|
28
|
+
*/
|
|
29
|
+
export declare function setIsMaybeMirage(value: boolean): void;
|
|
14
30
|
export {};
|
|
@@ -1315,9 +1315,16 @@ export interface LegacyBelongsToField {
|
|
|
1315
1315
|
* adapters and serializers.
|
|
1316
1316
|
*
|
|
1317
1317
|
* When true, none of the legacy support will be utilized. Sync relationships
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1318
|
+
* (`async: false`, currently the only supported combination) must satisfy
|
|
1319
|
+
* one of the following whenever pushed to the cache:
|
|
1320
|
+
*
|
|
1321
|
+
* - a `links.related` link is present, **or**
|
|
1322
|
+
* - the relationship is fully linked: `data` is `null`, or `data` points
|
|
1323
|
+
* to a resource present in the document's `included` array
|
|
1324
|
+
*
|
|
1325
|
+
* A related link lets you omit the related resource from `included`; a
|
|
1326
|
+
* `data` key that is missing entirely, or explicitly `undefined`, is never
|
|
1327
|
+
* valid unless a `links.related` link is present.
|
|
1321
1328
|
*
|
|
1322
1329
|
* ```ts
|
|
1323
1330
|
* {
|
|
@@ -1468,9 +1475,16 @@ export interface LinksModeBelongsToField {
|
|
|
1468
1475
|
* MUST be true for PolarisMode + LinksMode
|
|
1469
1476
|
*
|
|
1470
1477
|
* When true, none of the legacy support will be utilized. Sync relationships
|
|
1471
|
-
*
|
|
1472
|
-
*
|
|
1473
|
-
*
|
|
1478
|
+
* (`async: false`, currently the only supported combination) must satisfy
|
|
1479
|
+
* one of the following whenever pushed to the cache:
|
|
1480
|
+
*
|
|
1481
|
+
* - a `links.related` link is present, **or**
|
|
1482
|
+
* - the relationship is fully linked: `data` is `null`, or `data` points
|
|
1483
|
+
* to a resource present in the document's `included` array
|
|
1484
|
+
*
|
|
1485
|
+
* A related link lets you omit the related resource from `included`; a
|
|
1486
|
+
* `data` key that is missing entirely, or explicitly `undefined`, is never
|
|
1487
|
+
* valid unless a `links.related` link is present.
|
|
1474
1488
|
*
|
|
1475
1489
|
* ```ts
|
|
1476
1490
|
* {
|
|
@@ -1640,9 +1654,16 @@ export interface LegacyHasManyField {
|
|
|
1640
1654
|
* from @warp-drive-mirror/legacy/model and the LegacyNetworkMiddleware for adapters and serializers.
|
|
1641
1655
|
*
|
|
1642
1656
|
* When true, none of the legacy support will be utilized. Sync relationships
|
|
1643
|
-
*
|
|
1644
|
-
*
|
|
1645
|
-
*
|
|
1657
|
+
* (`async: false`, currently the only supported combination) must satisfy
|
|
1658
|
+
* one of the following whenever pushed to the cache:
|
|
1659
|
+
*
|
|
1660
|
+
* - a `links.related` link is present, **or**
|
|
1661
|
+
* - the relationship is fully linked: `data` is `[]`, or every resource
|
|
1662
|
+
* identifier in `data` is present in the document's `included` array
|
|
1663
|
+
*
|
|
1664
|
+
* A related link lets you omit the related resources from `included`; a
|
|
1665
|
+
* `data` key that is missing entirely, or explicitly `undefined`, is never
|
|
1666
|
+
* valid unless a `links.related` link is present.
|
|
1646
1667
|
*
|
|
1647
1668
|
* ```ts
|
|
1648
1669
|
* {
|
|
@@ -1818,9 +1839,16 @@ export interface LinksModeHasManyField {
|
|
|
1818
1839
|
* MUST be true for PolarisMode + LinksMode
|
|
1819
1840
|
*
|
|
1820
1841
|
* When true, none of the legacy support will be utilized. Sync relationships
|
|
1821
|
-
*
|
|
1822
|
-
*
|
|
1823
|
-
*
|
|
1842
|
+
* (`async: false`, currently the only supported combination) must satisfy
|
|
1843
|
+
* one of the following whenever pushed to the cache:
|
|
1844
|
+
*
|
|
1845
|
+
* - a `links.related` link is present, **or**
|
|
1846
|
+
* - the relationship is fully linked: `data` is `[]`, or every resource
|
|
1847
|
+
* identifier in `data` is present in the document's `included` array
|
|
1848
|
+
*
|
|
1849
|
+
* A related link lets you omit the related resources from `included`; a
|
|
1850
|
+
* `data` key that is missing entirely, or explicitly `undefined`, is never
|
|
1851
|
+
* valid unless a `links.related` link is present.
|
|
1824
1852
|
*
|
|
1825
1853
|
* ```ts
|
|
1826
1854
|
* {
|
package/dist/graph/-private.js
CHANGED
|
@@ -67,9 +67,14 @@ function assertValidRelationshipPayload(graph, op) {
|
|
|
67
67
|
kind
|
|
68
68
|
} = definition;
|
|
69
69
|
if (payload.links) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
// once JSON_API_CACHE_VALIDATION_ERRORS is active, this warning is instead
|
|
71
|
+
// the responsibility of the new document validator (see validateResourceRelationships
|
|
72
|
+
// in warp-drive-packages/json-api/src/-private/validator/1.1/7.2_resource-objects.ts)
|
|
73
|
+
if (macroCondition(!getGlobalConfig().WarpDriveMirror.features.JSON_API_CACHE_VALIDATION_ERRORS)) {
|
|
74
|
+
warn(`You pushed a record of type '${type}' with a relationship '${field}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload. WarpDrive will treat this relationship as known-to-be-empty.`, isAsync || payload.data === null || !!payload.data || state.hasReceivedData, {
|
|
75
|
+
id: 'ds.store.push-link-for-sync-relationship'
|
|
76
|
+
});
|
|
77
|
+
}
|
|
73
78
|
} else if (payload.data) {
|
|
74
79
|
if (kind === 'belongsTo') {
|
|
75
80
|
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
@@ -748,7 +753,7 @@ if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
|
|
|
748
753
|
errors.set('type', ` <---- should be '${definition.inverseType}'`);
|
|
749
754
|
}
|
|
750
755
|
if (definition.inverseKind !== meta.kind) {
|
|
751
|
-
errors.set('
|
|
756
|
+
errors.set('kind', ` <---- should be '${definition.inverseKind}'`);
|
|
752
757
|
}
|
|
753
758
|
if (definition.inverseIsAsync !== meta.options.async) {
|
|
754
759
|
errors.set('async', ` <---- should be ${definition.inverseIsAsync}`);
|
|
@@ -759,7 +764,12 @@ if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
|
|
|
759
764
|
if (definition.key !== meta.options.inverse) {
|
|
760
765
|
errors.set('inverse', ` <---- should be '${definition.key}'`);
|
|
761
766
|
}
|
|
762
|
-
|
|
767
|
+
// `as` is only meaningful when `definition` itself is polymorphic (i.e. it
|
|
768
|
+
// points at an abstract type that `meta` is expected to implement). When
|
|
769
|
+
// `definition` isn't polymorphic, there's no abstract type for `meta` to
|
|
770
|
+
// declare `as` against, so `meta.options.as` is correctly absent - that's
|
|
771
|
+
// not an error to report.
|
|
772
|
+
if (definition.isPolymorphic && definition.type !== meta.options.as) {
|
|
763
773
|
errors.set('as', ` <---- should be '${definition.type}'`);
|
|
764
774
|
}
|
|
765
775
|
return errors;
|
|
@@ -798,18 +808,6 @@ if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
|
|
|
798
808
|
|
|
799
809
|
`;
|
|
800
810
|
}
|
|
801
|
-
function metaFrom(definition) {
|
|
802
|
-
return {
|
|
803
|
-
name: definition.key,
|
|
804
|
-
type: definition.type,
|
|
805
|
-
kind: definition.kind,
|
|
806
|
-
options: {
|
|
807
|
-
async: definition.isAsync,
|
|
808
|
-
polymorphic: definition.isPolymorphic,
|
|
809
|
-
inverse: definition.inverseKey
|
|
810
|
-
}
|
|
811
|
-
};
|
|
812
|
-
}
|
|
813
811
|
function inverseMetaFrom(definition) {
|
|
814
812
|
return {
|
|
815
813
|
name: definition.inverseKey,
|
|
@@ -852,15 +850,18 @@ if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
|
|
|
852
850
|
});
|
|
853
851
|
}
|
|
854
852
|
assertInheritedSchema = function assertInheritedSchema(definition, type) {
|
|
855
|
-
|
|
853
|
+
// `definition` is the only source of truth we have here - there is no
|
|
854
|
+
// second, independently-declared schema available to diff it against.
|
|
855
|
+
// That means the only thing we can actually verify is internal: does
|
|
856
|
+
// `definition`'s own resolved inverse agree that this relationship is
|
|
857
|
+
// polymorphic? Every other field of `meta2` below (name/type/kind/async/
|
|
858
|
+
// inverse) is derived directly from `definition` itself, so comparing
|
|
859
|
+
// them back to `definition` can never disagree - only the polymorphic
|
|
860
|
+
// flag is independently meaningful, because `definitionWithPolymorphic`
|
|
861
|
+
// asserts what it *should* be rather than mirroring what it already is.
|
|
856
862
|
const meta2 = inverseMetaFrom(definition);
|
|
857
|
-
const errors1 = validateSchema(inverseDefinition(definition), meta1);
|
|
858
863
|
const errors2 = validateSchema(definitionWithPolymorphic(definition), meta2);
|
|
859
|
-
if (errors2.size
|
|
860
|
-
throw new Error(`The schema for the relationship '${type}.${definition.key}' is not configured to satisfy '${definition.inverseType}' and thus cannot utilize the '${definition.inverseType}.${definition.key}' relationship to connect with '${definition.type}.${definition.inverseKey}'\n\nIf using this relationship in a polymorphic manner is desired, the relationships schema definition for '${type}' should include:${printSchema(meta1, errors1)}`);
|
|
861
|
-
} else if (errors1.size > 0) {
|
|
862
|
-
throw new Error(`The schema for the relationship '${type}.${definition.key}' is not configured to satisfy '${definition.inverseType}' and thus cannot utilize the '${definition.inverseType}.${definition.key}' relationship to connect with '${definition.type}.${definition.inverseKey}'\n\nIf using this relationship in a polymorphic manner is desired, the relationships schema definition for '${type}' should include:${printSchema(meta1, errors1)} and the relationships schema definition for '${definition.type}' should include:${printSchema(meta2, errors2)}`);
|
|
863
|
-
} else if (errors2.size > 0) {
|
|
864
|
+
if (errors2.size > 0) {
|
|
864
865
|
throw new Error(`The schema for the relationship '${type}.${definition.key}' satisfies '${definition.inverseType}' but cannot utilize the '${definition.inverseType}.${definition.key}' relationship to connect with '${definition.type}.${definition.inverseKey}' because that relationship is not polymorphic.\n\nIf using this relationship in a polymorphic manner is desired, the relationships schema definition for '${definition.type}' should include:${printSchema(meta2, errors2)}`);
|
|
865
866
|
}
|
|
866
867
|
};
|
|
@@ -1414,8 +1415,10 @@ function replaceRelatedRecord(graph, op, isRemote = false) {
|
|
|
1414
1415
|
if (op.value === existingState) {
|
|
1415
1416
|
// if we were empty before but now know we are empty this needs to be true
|
|
1416
1417
|
state.hasReceivedData = true;
|
|
1418
|
+
|
|
1417
1419
|
// if this is a remote update we still sync
|
|
1418
1420
|
if (isRemote) {
|
|
1421
|
+
state.hasReceivedRemoteData = true;
|
|
1419
1422
|
const {
|
|
1420
1423
|
localState
|
|
1421
1424
|
} = relationship;
|
|
@@ -1455,6 +1458,15 @@ function replaceRelatedRecord(graph, op, isRemote = false) {
|
|
|
1455
1458
|
// update value to the new value
|
|
1456
1459
|
relationship[prop] = op.value;
|
|
1457
1460
|
state.hasReceivedData = true;
|
|
1461
|
+
/**
|
|
1462
|
+
* Local mutations never give us additional information about
|
|
1463
|
+
* whether the relationship has received *remote* data. This is
|
|
1464
|
+
* what `getRemoteRelationship` relies on to avoid reflecting
|
|
1465
|
+
* local-only edits.
|
|
1466
|
+
*/
|
|
1467
|
+
if (isRemote) {
|
|
1468
|
+
state.hasReceivedRemoteData = true;
|
|
1469
|
+
}
|
|
1458
1470
|
state.isEmpty = op.value === null;
|
|
1459
1471
|
state.isStale = false;
|
|
1460
1472
|
state.hasFailedLoadAttempt = false;
|
|
@@ -2133,8 +2145,30 @@ function rollbackRelationship(graph, key, field, relationship) {
|
|
|
2133
2145
|
}
|
|
2134
2146
|
}
|
|
2135
2147
|
function createState() {
|
|
2148
|
+
if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
|
|
2149
|
+
if (macroCondition(getGlobalConfig().WarpDriveMirror.activeLogging.LOG_GRAPH)) {
|
|
2150
|
+
if (getGlobalConfig().WarpDriveMirror.debug.LOG_GRAPH || globalThis.getWarpDriveRuntimeConfig().debug.LOG_GRAPH) {
|
|
2151
|
+
let hasReceivedData = false;
|
|
2152
|
+
return {
|
|
2153
|
+
get hasReceivedData() {
|
|
2154
|
+
return hasReceivedData;
|
|
2155
|
+
},
|
|
2156
|
+
set hasReceivedData(value) {
|
|
2157
|
+
hasReceivedData = value;
|
|
2158
|
+
},
|
|
2159
|
+
hasReceivedRemoteData: false,
|
|
2160
|
+
isEmpty: true,
|
|
2161
|
+
isStale: false,
|
|
2162
|
+
hasFailedLoadAttempt: false,
|
|
2163
|
+
shouldForceReload: false,
|
|
2164
|
+
hasDematerializedInverse: false
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2136
2169
|
return {
|
|
2137
2170
|
hasReceivedData: false,
|
|
2171
|
+
hasReceivedRemoteData: false,
|
|
2138
2172
|
isEmpty: true,
|
|
2139
2173
|
isStale: false,
|
|
2140
2174
|
hasFailedLoadAttempt: false,
|
|
@@ -2239,13 +2273,10 @@ function legacyGetResourceRelationshipData(source, getRemoteState) {
|
|
|
2239
2273
|
source.accessed = true;
|
|
2240
2274
|
let data;
|
|
2241
2275
|
const payload = {};
|
|
2242
|
-
if (getRemoteState && source.remoteState) {
|
|
2243
|
-
data = source.remoteState;
|
|
2244
|
-
} else if (!getRemoteState && source.localState) {
|
|
2245
|
-
data = source.localState;
|
|
2246
|
-
}
|
|
2247
|
-
if ((getRemoteState && source.remoteState === null || source.localState === null) && source.state.hasReceivedData) {
|
|
2248
|
-
data = null;
|
|
2276
|
+
if (getRemoteState && (source.remoteState || source.state.hasReceivedRemoteData)) {
|
|
2277
|
+
data = source.remoteState ?? null;
|
|
2278
|
+
} else if (!getRemoteState && (source.localState || source.state.hasReceivedData)) {
|
|
2279
|
+
data = source.localState ?? null;
|
|
2249
2280
|
}
|
|
2250
2281
|
if (source.links) {
|
|
2251
2282
|
payload.links = source.links;
|
|
@@ -2459,7 +2490,6 @@ function updateRelationshipOperation(graph, op) {
|
|
|
2459
2490
|
})(isHasMany(relationship) || isBelongsTo(relationship)) : {};
|
|
2460
2491
|
const {
|
|
2461
2492
|
definition,
|
|
2462
|
-
state,
|
|
2463
2493
|
identifier
|
|
2464
2494
|
} = relationship;
|
|
2465
2495
|
const {
|
|
@@ -2499,23 +2529,6 @@ function updateRelationshipOperation(graph, op) {
|
|
|
2499
2529
|
value: payload.data ? graph.store.cacheKeyManager.upgradeIdentifier(payload.data) : null
|
|
2500
2530
|
}, true);
|
|
2501
2531
|
}
|
|
2502
|
-
} else if (definition.isAsync === false && !state.hasReceivedData) {
|
|
2503
|
-
hasRelationshipDataProperty = true;
|
|
2504
|
-
if (isCollection) {
|
|
2505
|
-
graph.update({
|
|
2506
|
-
op: 'replaceRelatedRecords',
|
|
2507
|
-
record: identifier,
|
|
2508
|
-
field: op.field,
|
|
2509
|
-
value: []
|
|
2510
|
-
}, true);
|
|
2511
|
-
} else {
|
|
2512
|
-
graph.update({
|
|
2513
|
-
op: 'replaceRelatedRecord',
|
|
2514
|
-
record: identifier,
|
|
2515
|
-
field: op.field,
|
|
2516
|
-
value: null
|
|
2517
|
-
}, true);
|
|
2518
|
-
}
|
|
2519
2532
|
}
|
|
2520
2533
|
if (payload.links) {
|
|
2521
2534
|
const originalLinks = relationship.links;
|
|
@@ -2525,9 +2538,10 @@ function updateRelationshipOperation(graph, op) {
|
|
|
2525
2538
|
const currentLink = originalLinks && originalLinks.related ? _normalizeLink(originalLinks.related) : null;
|
|
2526
2539
|
const currentLinkHref = currentLink ? currentLink.href : null;
|
|
2527
2540
|
if (relatedLink && relatedLink.href && relatedLink.href !== currentLinkHref) {
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2541
|
+
// Note: the equivalent warning for this case is issued eagerly (and with a more
|
|
2542
|
+
// complete condition, since it also accounts for `payload.data` being present) by
|
|
2543
|
+
// `assertValidRelationshipPayload` in `-utils.ts`, which always runs immediately
|
|
2544
|
+
// before this operation in DEBUG builds. Warning here too would double-warn.
|
|
2531
2545
|
macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
|
|
2532
2546
|
if (!test) {
|
|
2533
2547
|
throw new Error(`You have pushed a record of type '${identifier.type}' with '${definition.key}' as a link, but the value of that link is not a string.`);
|
|
@@ -2558,6 +2572,7 @@ function updateRelationshipOperation(graph, op) {
|
|
|
2558
2572
|
// we don't need to notify here as the update op we pushed in above will notify once
|
|
2559
2573
|
// membership is in the correct state.
|
|
2560
2574
|
relationship.state.hasReceivedData = true;
|
|
2575
|
+
relationship.state.hasReceivedRemoteData = true;
|
|
2561
2576
|
relationship.state.isStale = false;
|
|
2562
2577
|
relationship.state.hasDematerializedInverse = false;
|
|
2563
2578
|
relationship.state.isEmpty = relationshipIsEmpty;
|