@warp-drive-mirror/json-api 5.10.0-alpha.6 → 5.10.0-alpha.8
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 +6 -6
package/dist/index.js
CHANGED
|
@@ -2136,20 +2136,89 @@ function getDefaultValue(schema, identifier, store) {
|
|
|
2136
2136
|
if (transform?.defaultValue) return transform.defaultValue(options || null, identifier);
|
|
2137
2137
|
}
|
|
2138
2138
|
}
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2139
|
+
/**
|
|
2140
|
+
* Narrow `subset` to the members that survived {@link patchLocalAttributes}' pruning. Only called
|
|
2141
|
+
* when that pruning actually removed something, so the allocation is skipped on the common path
|
|
2142
|
+
* where a resource has no local edits at all.
|
|
2143
|
+
*/
|
|
2144
|
+
function retainSurviving(subset, survivors) {
|
|
2145
|
+
if (!subset?.size) return subset;
|
|
2146
|
+
const result = /* @__PURE__ */ new Set();
|
|
2147
|
+
for (const key of subset) if (survivors.has(key)) result.add(key);
|
|
2148
|
+
return result.size ? result : void 0;
|
|
2149
|
+
}
|
|
2150
|
+
/**
|
|
2151
|
+
* Which projection each changed key moved, so the caller can notify on the matching channel:
|
|
2152
|
+
* `localOnly` and `remoteOnly` on theirs, `both` unscoped. `remoteChanged` is the union
|
|
2153
|
+
* {@link patchLocalAttributes} reconciles against.
|
|
2154
|
+
*
|
|
2155
|
+
* `undefined` rather than empty Sets: this runs on every `upsert`, and a resource where nothing
|
|
2156
|
+
* moved should cost no allocation.
|
|
2157
|
+
*/
|
|
2158
|
+
const NO_PROJECTION_CHANGES = Object.freeze({
|
|
2159
|
+
localOnly: void 0,
|
|
2160
|
+
remoteOnly: void 0,
|
|
2161
|
+
both: void 0,
|
|
2162
|
+
remoteChanged: void 0
|
|
2163
|
+
});
|
|
2164
|
+
/**
|
|
2165
|
+
* The keys a merge could move: everything the payload carries, plus anything being promoted that
|
|
2166
|
+
* the payload did not mention. `null` when there is nothing to examine.
|
|
2167
|
+
*
|
|
2168
|
+
* `upsert` promotes nothing, so it gets the `Object.keys` array back unchanged. Only a commit
|
|
2169
|
+
* carrying both a payload and promoted attrs pays for a copy, and that is once per save rather
|
|
2170
|
+
* than once per resource in a document.
|
|
2171
|
+
*/
|
|
2172
|
+
function candidateKeys(updates, promoted) {
|
|
2173
|
+
const updateKeys = updates ? Object.keys(updates) : null;
|
|
2174
|
+
const promotedKeys = promoted ? Object.keys(promoted) : null;
|
|
2175
|
+
if (!promotedKeys?.length) return updateKeys?.length ? updateKeys : null;
|
|
2176
|
+
if (!updateKeys?.length) return promotedKeys;
|
|
2177
|
+
const keys = updateKeys.slice();
|
|
2178
|
+
for (let i = 0; i < promotedKeys.length; i++) if (!(promotedKeys[i] in updates)) keys.push(promotedKeys[i]);
|
|
2179
|
+
return keys;
|
|
2180
|
+
}
|
|
2181
|
+
/**
|
|
2182
|
+
* Partition the keys an incoming payload touches by which projection each one moves.
|
|
2183
|
+
*
|
|
2184
|
+
* Takes the values rather than the `CachedResource` so it cannot observe the merge it is
|
|
2185
|
+
* describing: `prevRemote` is the remote state as it stands *before* `promoted` and `updates` are
|
|
2186
|
+
* applied, and the two callers merge different things. Reading them off `cached` would make the
|
|
2187
|
+
* result depend on whether the caller had already mutated it.
|
|
2188
|
+
*/
|
|
2189
|
+
function calculateChangedKeys(prevRemote, localAttrs, updates, promoted, fields) {
|
|
2190
|
+
const keys = candidateKeys(updates, promoted);
|
|
2191
|
+
if (keys === null) return NO_PROJECTION_CHANGES;
|
|
2192
|
+
let localOnly;
|
|
2193
|
+
let remoteOnly;
|
|
2194
|
+
let both;
|
|
2195
|
+
let remoteChanged;
|
|
2196
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2146
2197
|
const key = keys[i];
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2198
|
+
const field = fields.get(key);
|
|
2199
|
+
if (!field || isRelationship(field)) continue;
|
|
2200
|
+
const isPromoted = promoted !== null && key in promoted;
|
|
2201
|
+
const isUpdated = updates !== void 0 && key in updates;
|
|
2202
|
+
const wasRemote = prevRemote ? prevRemote[key] : void 0;
|
|
2203
|
+
const nowRemote = isUpdated ? updates[key] : isPromoted ? promoted[key] : wasRemote;
|
|
2204
|
+
const localEdit = localAttrs ? localAttrs[key] : void 0;
|
|
2205
|
+
const isEdited = localEdit !== void 0;
|
|
2206
|
+
const wasLocal = isEdited ? localEdit : isPromoted ? promoted[key] : wasRemote;
|
|
2207
|
+
const nowLocal = isEdited ? localEdit : nowRemote;
|
|
2208
|
+
const remoteMoved = wasRemote !== nowRemote;
|
|
2209
|
+
const localMoved = wasLocal !== nowLocal;
|
|
2210
|
+
if (remoteMoved) {
|
|
2211
|
+
(remoteChanged ??= /* @__PURE__ */ new Set()).add(key);
|
|
2212
|
+
if (localMoved) (both ??= /* @__PURE__ */ new Set()).add(key);
|
|
2213
|
+
else (remoteOnly ??= /* @__PURE__ */ new Set()).add(key);
|
|
2214
|
+
} else if (localMoved) (localOnly ??= /* @__PURE__ */ new Set()).add(key);
|
|
2215
|
+
}
|
|
2216
|
+
return remoteChanged || localOnly ? {
|
|
2217
|
+
localOnly,
|
|
2218
|
+
remoteOnly,
|
|
2219
|
+
both,
|
|
2220
|
+
remoteChanged
|
|
2221
|
+
} : NO_PROJECTION_CHANGES;
|
|
2153
2222
|
}
|
|
2154
2223
|
function cacheIsEmpty(cached) {
|
|
2155
2224
|
return !cached || cached.remoteAttrs === null && cached.inflightAttrs === null && cached.localAttrs === null;
|
|
@@ -2323,7 +2392,7 @@ function cacheUpsert(cache, identifier, data, calculateChanges) {
|
|
|
2323
2392
|
cache._capabilities.notifyChange(identifier, "state", null);
|
|
2324
2393
|
}
|
|
2325
2394
|
const fields = getCacheFields(cache, identifier);
|
|
2326
|
-
if (calculateChanges && existed && data.attributes) changedKeys = calculateChangedKeys(cached, data.attributes, fields);
|
|
2395
|
+
if (calculateChanges && existed && data.attributes) changedKeys = calculateChangedKeys(cached.remoteAttrs, cached.localAttrs, data.attributes, null, fields).remoteChanged;
|
|
2327
2396
|
cached.remoteAttrs = Object.assign(cached.remoteAttrs || Object.create(null), data.attributes);
|
|
2328
2397
|
if (cached.localAttrs) {
|
|
2329
2398
|
if (patchLocalAttributes(cached, changedKeys)) cache._capabilities.notifyChange(identifier, "state", null);
|
|
@@ -2503,15 +2572,21 @@ function didCommit(cache, committedIdentifier, data, op) {
|
|
|
2503
2572
|
}
|
|
2504
2573
|
newCanonicalAttributes = data.attributes;
|
|
2505
2574
|
}
|
|
2506
|
-
const
|
|
2575
|
+
const changes = calculateChangedKeys(cached.remoteAttrs, cached.localAttrs, newCanonicalAttributes, cached.inflightAttrs, fields);
|
|
2507
2576
|
cached.remoteAttrs = Object.assign(cached.remoteAttrs || Object.create(null), cached.inflightAttrs, newCanonicalAttributes);
|
|
2508
2577
|
cached.inflightAttrs = null;
|
|
2509
|
-
patchLocalAttributes(cached,
|
|
2578
|
+
const pruned = patchLocalAttributes(cached, changes.remoteChanged);
|
|
2510
2579
|
if (cached.errors) {
|
|
2511
2580
|
cached.errors = null;
|
|
2512
2581
|
cache._capabilities.notifyChange(identifier, "errors", null);
|
|
2513
2582
|
}
|
|
2514
|
-
|
|
2583
|
+
const { remoteChanged, localOnly } = changes;
|
|
2584
|
+
const reprune = pruned && remoteChanged !== void 0;
|
|
2585
|
+
const both = reprune ? retainSurviving(changes.both, remoteChanged) : changes.both;
|
|
2586
|
+
const remoteOnly = reprune ? retainSurviving(changes.remoteOnly, remoteChanged) : changes.remoteOnly;
|
|
2587
|
+
if (both?.size) cache._capabilities.notifyChange(identifier, "attributes", both);
|
|
2588
|
+
if (remoteOnly?.size) cache._capabilities.notifyChange(identifier, "attributes", remoteOnly, "remote");
|
|
2589
|
+
if (localOnly?.size) cache._capabilities.notifyChange(identifier, "attributes", localOnly, "local");
|
|
2515
2590
|
cache._capabilities.notifyChange(identifier, "state", null);
|
|
2516
2591
|
}
|
|
2517
2592
|
function willCommit(cache, identifier) {
|