Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
richgt committed Apr 26, 2024
1 parent 1deb474 commit e5dc1b8
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
20 changes: 15 additions & 5 deletions packages/json-api/src/-private/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1209,17 +1209,27 @@ export default class JSONAPICache implements Cache {

if (existingAttr !== value) {
cached.localAttrs = cached.localAttrs || (Object.create(null) as Record<string, Value>);
cached.localAttrs[basePath] = cached.localAttrs[basePath] || (Object.create(null) as ObjectValue);
cached.localAttrs[basePath] = cached.localAttrs[basePath] || structuredClone(existing);
cached.changes = cached.changes || (Object.create(null) as Record<string, [Value, Value]>);
let currentLocal = cached.localAttrs[basePath] as ObjectValue;
let nextLink = 1;

for (let i = 1; i < path.length; i++) {
currentLocal[path[i]] = currentLocal[path[i]] || (Object.create(null) as ObjectValue);
currentLocal = currentLocal[path[i]] as ObjectValue;
while (nextLink < path.length - 1) {
currentLocal = currentLocal[path[nextLink++]] as ObjectValue;
}
currentLocal = value as ObjectValue;
currentLocal[path[nextLink]] = value as ObjectValue;

cached.changes[basePath] = [existing, cached.localAttrs[basePath] as ObjectValue];

// since we initiaize the value as basePath as a clone of the value at the remote basePath
// then in theory we can use JSON.stringify to compare the two values as key insertion order
// ought to be consistent.
// we try/catch this because users have a habit of doing "Bad Things"TM wherein the cache contains
// stateful values that are not JSON serializable correctly such as Dates.
// in the case that we error, we fallback to not removing the local value
// so that any changes we don't understand are preserved. Thse objects would then sometimes
// appear to be dirty unnecessarily, and for folks that open an issue we can guide them
// to make their cache data less stateful.
} else if (cached.localAttrs) {
delete cached.localAttrs[basePath];
delete cached.changes![basePath];
Expand Down
29 changes: 17 additions & 12 deletions packages/schema-record/src/managed-array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,15 @@ export class ManagedArray {
);
Object.assign(record, val);
return record;
}
if (field.type !== null) {
const transform = schema.transforms.get(field.type);
if (!transform) {
throw new Error(`No '${field.type}' transform defined for use by ${address.type}.${String(prop)}`);
} else {
if (field.type !== null) {
const transform = schema.transforms.get(field.type);
if (!transform) {
debugger;
throw new Error(`No '${field.type}' transform defined for use by ${address.type}.${String(prop)}`);
}
return transform.hydrate(val as Value, field.options ?? null, self.owner);
}
return transform.hydrate(val as Value, field.options ?? null, self.owner);
}
return val;
}
Expand Down Expand Up @@ -245,13 +247,16 @@ export class ManagedArray {
return true;
}

const transform = schema.transforms.get(field.type);
if (!transform) {
throw new Error(`No '${field.type}' transform defined for use by ${address.type}.${String(prop)}`);
let rawValue = self[SOURCE] as ArrayValue;
if (!isSchemaArray) {
const transform = schema.transforms.get(field.type);
if (!transform) {
throw new Error(`No '${field.type}' transform defined for use by ${address.type}.${String(prop)}`);
}
rawValue = (self[SOURCE] as ArrayValue).map((item) =>
transform.serialize(item, field.options ?? null, self.owner)
);
}
const rawValue = (self[SOURCE] as ArrayValue).map((item) =>
transform.serialize(item, field.options ?? null, self.owner)
);
cache.setAttr(self.address, self.key, rawValue as Value);
_SIGNAL.shouldReset = true;
}
Expand Down
1 change: 1 addition & 0 deletions packages/schema-record/src/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ export class SchemaRecord {
}
},
set(target: SchemaRecord, prop: string | number | symbol, value: unknown, receiver: typeof Proxy<SchemaRecord>) {
debugger;
if (!IS_EDITABLE) {
throw new Error(`Cannot set ${String(prop)} on ${identifier.type} because the record is not editable`);
}
Expand Down

0 comments on commit e5dc1b8

Please sign in to comment.