@warp-drive-mirror/json-api 5.10.0-alpha.7 → 5.10.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +92 -17
- package/dist/index.js.map +1 -1
- package/dist/unpkg/dev/index.js +93 -18
- package/dist/unpkg/dev/index.js.map +1 -1
- package/dist/unpkg/dev-deprecated/index.js +93 -18
- package/dist/unpkg/dev-deprecated/index.js.map +1 -1
- package/dist/unpkg/prod/index.js +91 -16
- package/dist/unpkg/prod/index.js.map +1 -1
- package/dist/unpkg/prod-deprecated/index.js +91 -16
- package/dist/unpkg/prod-deprecated/index.js.map +1 -1
- package/package.json +7 -7
package/dist/unpkg/prod/index.js
CHANGED
|
@@ -1035,20 +1035,89 @@ function getDefaultValue(schema, identifier, store) {
|
|
|
1035
1035
|
if (transform?.defaultValue) return transform.defaultValue(options || null, identifier);
|
|
1036
1036
|
}
|
|
1037
1037
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1038
|
+
/**
|
|
1039
|
+
* Narrow `subset` to the members that survived {@link patchLocalAttributes}' pruning. Only called
|
|
1040
|
+
* when that pruning actually removed something, so the allocation is skipped on the common path
|
|
1041
|
+
* where a resource has no local edits at all.
|
|
1042
|
+
*/
|
|
1043
|
+
function retainSurviving(subset, survivors) {
|
|
1044
|
+
if (!subset?.size) return subset;
|
|
1045
|
+
const result = /* @__PURE__ */ new Set();
|
|
1046
|
+
for (const key of subset) if (survivors.has(key)) result.add(key);
|
|
1047
|
+
return result.size ? result : void 0;
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Which projection each changed key moved, so the caller can notify on the matching channel:
|
|
1051
|
+
* `localOnly` and `remoteOnly` on theirs, `both` unscoped. `remoteChanged` is the union
|
|
1052
|
+
* {@link patchLocalAttributes} reconciles against.
|
|
1053
|
+
*
|
|
1054
|
+
* `undefined` rather than empty Sets: this runs on every `upsert`, and a resource where nothing
|
|
1055
|
+
* moved should cost no allocation.
|
|
1056
|
+
*/
|
|
1057
|
+
const NO_PROJECTION_CHANGES = Object.freeze({
|
|
1058
|
+
localOnly: void 0,
|
|
1059
|
+
remoteOnly: void 0,
|
|
1060
|
+
both: void 0,
|
|
1061
|
+
remoteChanged: void 0
|
|
1062
|
+
});
|
|
1063
|
+
/**
|
|
1064
|
+
* The keys a merge could move: everything the payload carries, plus anything being promoted that
|
|
1065
|
+
* the payload did not mention. `null` when there is nothing to examine.
|
|
1066
|
+
*
|
|
1067
|
+
* `upsert` promotes nothing, so it gets the `Object.keys` array back unchanged. Only a commit
|
|
1068
|
+
* carrying both a payload and promoted attrs pays for a copy, and that is once per save rather
|
|
1069
|
+
* than once per resource in a document.
|
|
1070
|
+
*/
|
|
1071
|
+
function candidateKeys(updates, promoted) {
|
|
1072
|
+
const updateKeys = updates ? Object.keys(updates) : null;
|
|
1073
|
+
const promotedKeys = promoted ? Object.keys(promoted) : null;
|
|
1074
|
+
if (!promotedKeys?.length) return updateKeys?.length ? updateKeys : null;
|
|
1075
|
+
if (!updateKeys?.length) return promotedKeys;
|
|
1076
|
+
const keys = updateKeys.slice();
|
|
1077
|
+
for (let i = 0; i < promotedKeys.length; i++) if (!(promotedKeys[i] in updates)) keys.push(promotedKeys[i]);
|
|
1078
|
+
return keys;
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* Partition the keys an incoming payload touches by which projection each one moves.
|
|
1082
|
+
*
|
|
1083
|
+
* Takes the values rather than the `CachedResource` so it cannot observe the merge it is
|
|
1084
|
+
* describing: `prevRemote` is the remote state as it stands *before* `promoted` and `updates` are
|
|
1085
|
+
* applied, and the two callers merge different things. Reading them off `cached` would make the
|
|
1086
|
+
* result depend on whether the caller had already mutated it.
|
|
1087
|
+
*/
|
|
1088
|
+
function calculateChangedKeys(prevRemote, localAttrs, updates, promoted, fields) {
|
|
1089
|
+
const keys = candidateKeys(updates, promoted);
|
|
1090
|
+
if (keys === null) return NO_PROJECTION_CHANGES;
|
|
1091
|
+
let localOnly;
|
|
1092
|
+
let remoteOnly;
|
|
1093
|
+
let both;
|
|
1094
|
+
let remoteChanged;
|
|
1095
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1045
1096
|
const key = keys[i];
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1097
|
+
const field = fields.get(key);
|
|
1098
|
+
if (!field || isRelationship(field)) continue;
|
|
1099
|
+
const isPromoted = promoted !== null && key in promoted;
|
|
1100
|
+
const isUpdated = updates !== void 0 && key in updates;
|
|
1101
|
+
const wasRemote = prevRemote ? prevRemote[key] : void 0;
|
|
1102
|
+
const nowRemote = isUpdated ? updates[key] : isPromoted ? promoted[key] : wasRemote;
|
|
1103
|
+
const localEdit = localAttrs ? localAttrs[key] : void 0;
|
|
1104
|
+
const isEdited = localEdit !== void 0;
|
|
1105
|
+
const wasLocal = isEdited ? localEdit : isPromoted ? promoted[key] : wasRemote;
|
|
1106
|
+
const nowLocal = isEdited ? localEdit : nowRemote;
|
|
1107
|
+
const remoteMoved = wasRemote !== nowRemote;
|
|
1108
|
+
const localMoved = wasLocal !== nowLocal;
|
|
1109
|
+
if (remoteMoved) {
|
|
1110
|
+
(remoteChanged ??= /* @__PURE__ */ new Set()).add(key);
|
|
1111
|
+
if (localMoved) (both ??= /* @__PURE__ */ new Set()).add(key);
|
|
1112
|
+
else (remoteOnly ??= /* @__PURE__ */ new Set()).add(key);
|
|
1113
|
+
} else if (localMoved) (localOnly ??= /* @__PURE__ */ new Set()).add(key);
|
|
1050
1114
|
}
|
|
1051
|
-
return
|
|
1115
|
+
return remoteChanged || localOnly ? {
|
|
1116
|
+
localOnly,
|
|
1117
|
+
remoteOnly,
|
|
1118
|
+
both,
|
|
1119
|
+
remoteChanged
|
|
1120
|
+
} : NO_PROJECTION_CHANGES;
|
|
1052
1121
|
}
|
|
1053
1122
|
function cacheIsEmpty(cached) {
|
|
1054
1123
|
return !cached || cached.remoteAttrs === null && cached.inflightAttrs === null && cached.localAttrs === null;
|
|
@@ -1205,7 +1274,7 @@ function cacheUpsert(cache, identifier, data, calculateChanges) {
|
|
|
1205
1274
|
cache._capabilities.notifyChange(identifier, "state", null);
|
|
1206
1275
|
}
|
|
1207
1276
|
const fields = getCacheFields(cache, identifier);
|
|
1208
|
-
if (calculateChanges && existed && data.attributes) changedKeys = calculateChangedKeys(cached, data.attributes, fields);
|
|
1277
|
+
if (calculateChanges && existed && data.attributes) changedKeys = calculateChangedKeys(cached.remoteAttrs, cached.localAttrs, data.attributes, null, fields).remoteChanged;
|
|
1209
1278
|
cached.remoteAttrs = Object.assign(cached.remoteAttrs || Object.create(null), data.attributes);
|
|
1210
1279
|
if (cached.localAttrs) {
|
|
1211
1280
|
if (patchLocalAttributes(cached, changedKeys)) cache._capabilities.notifyChange(identifier, "state", null);
|
|
@@ -1309,15 +1378,21 @@ function didCommit(cache, committedIdentifier, data, op) {
|
|
|
1309
1378
|
if (data.relationships) setupRelationships(cache.__graph, fields, identifier, data);
|
|
1310
1379
|
newCanonicalAttributes = data.attributes;
|
|
1311
1380
|
}
|
|
1312
|
-
const
|
|
1381
|
+
const changes = calculateChangedKeys(cached.remoteAttrs, cached.localAttrs, newCanonicalAttributes, cached.inflightAttrs, fields);
|
|
1313
1382
|
cached.remoteAttrs = Object.assign(cached.remoteAttrs || Object.create(null), cached.inflightAttrs, newCanonicalAttributes);
|
|
1314
1383
|
cached.inflightAttrs = null;
|
|
1315
|
-
patchLocalAttributes(cached,
|
|
1384
|
+
const pruned = patchLocalAttributes(cached, changes.remoteChanged);
|
|
1316
1385
|
if (cached.errors) {
|
|
1317
1386
|
cached.errors = null;
|
|
1318
1387
|
cache._capabilities.notifyChange(identifier, "errors", null);
|
|
1319
1388
|
}
|
|
1320
|
-
|
|
1389
|
+
const { remoteChanged, localOnly } = changes;
|
|
1390
|
+
const reprune = pruned && remoteChanged !== void 0;
|
|
1391
|
+
const both = reprune ? retainSurviving(changes.both, remoteChanged) : changes.both;
|
|
1392
|
+
const remoteOnly = reprune ? retainSurviving(changes.remoteOnly, remoteChanged) : changes.remoteOnly;
|
|
1393
|
+
if (both?.size) cache._capabilities.notifyChange(identifier, "attributes", both);
|
|
1394
|
+
if (remoteOnly?.size) cache._capabilities.notifyChange(identifier, "attributes", remoteOnly, "remote");
|
|
1395
|
+
if (localOnly?.size) cache._capabilities.notifyChange(identifier, "attributes", localOnly, "local");
|
|
1321
1396
|
cache._capabilities.notifyChange(identifier, "state", null);
|
|
1322
1397
|
}
|
|
1323
1398
|
function willCommit(cache, identifier) {
|