Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(graphcache) - Enable more cache.keyOfEntity parent cases and deprecate cache.resolveFieldByKey #1219

Merged
merged 5 commits into from
Dec 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tough-keys-visit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@urql/exchange-graphcache': patch
---

Update `cache.resolve(parent, ...)` case to enable _even more_ cases, for instance where `parent.__typename` isn't set yet. This was intended to be enabled in the previous patch but has been forgotten.
5 changes: 5 additions & 0 deletions .changeset/wild-pandas-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@urql/exchange-graphcache': patch
---

Deprecate `cache.resolveFieldByKey` in favour of `cache.resolve`, which functionally was already able to do the same.
11 changes: 6 additions & 5 deletions docs/api/graphcache.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,16 @@ an entity key, which makes it possible to pass a key from `cache.keyOfEntity` or
> be dangerous to use in some cases. It's a good idea to make sure first whether the field you're
> reading will be a key or a value.

There's an alternative method, `cache.resolveFieldByKey` which accepts a field key that may be
generated using `cache.keyOfField`.
The `cache.resolve` method may also be called with a field key as generated by `cache.keyOfField`.

```js
cache.resolveFieldByKey({ __typename: 'Query' }, cache.keyOfField('todo', { id: 1 })); // 'Todo:1'
cache.resolve({ __typename: 'Query' }, cache.keyOfField('todo', { id: 1 })); // 'Todo:1'
```

This specialized method is likely only going to be useful in combination with
[`cache.inspectFields`](#inspectfields).
This specialized case is likely only going to be useful in combination with
[`cache.inspectFields`](#inspectfields). Previously a specialised method existed for this
case specifically and was called `cache.resolveFieldByKey`, which is now deprecated, since
`cache.resolve` may be called with a field key and no extra arguments.

### inspectFields

Expand Down
2 changes: 1 addition & 1 deletion exchanges/graphcache/default-storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"./package.json": "./package.json"
},
"dependencies": {
"@urql/core": ">=1.15.2",
"@urql/core": ">=1.16.0",
"wonka": "^4.0.14"
}
}
2 changes: 1 addition & 1 deletion exchanges/graphcache/src/extras/relayPagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const getPage = (
entityKey: string,
fieldKey: string
): Page | null => {
const link = ensureKey(cache.resolveFieldByKey(entityKey, fieldKey));
const link = ensureKey(cache.resolve(entityKey, fieldKey));
if (!link) return null;

const typename = cache.resolve(link, '__typename') as string;
Expand Down
2 changes: 1 addition & 1 deletion exchanges/graphcache/src/extras/simplePagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const simplePagination = ({
continue;
}

const links = cache.resolveFieldByKey(entityKey, fieldKey) as string[];
const links = cache.resolve(entityKey, fieldKey) as string[];
const currentOffset = args[offsetArgument];

if (
Expand Down
4 changes: 4 additions & 0 deletions exchanges/graphcache/src/store/store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,10 @@ describe('Store with OptimisticMutationConfig', () => {

expect(store.keyOfEntity(randomData)).toBe(context.parentKey);
expect(store.keyOfEntity({})).not.toBe(context.parentKey);

// Should work without a __typename field
delete (randomData as any).__typename;
expect(store.keyOfEntity(randomData)).toBe(context.parentKey);
});

it('should resolve with a key as first argument', () => {
Expand Down
40 changes: 19 additions & 21 deletions exchanges/graphcache/src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,45 +105,43 @@ export class Store implements Cache {
keyOfField = keyOfField;

keyOfEntity(data: Data | null | string) {
if (data == null || typeof data === 'string') return data || null;
const { __typename: typename, id, _id } = data;
if (!typename) return null;
if (this.rootNames[typename]) return typename;

// In resolvers and updaters we may have a specific parent
// object available that can be used to skip to a specific parent
// key directly without looking at its incomplete properties
if (contextRef.current && data === contextRef.current.parent)
return contextRef.current!.parentKey;

if (data == null || typeof data === 'string') return data || null;
if (!data.__typename) return null;
if (this.rootNames[data.__typename]) return data.__typename;

let key: string | null | void;
if (this.keys[typename]) {
key = this.keys[typename](data);
} else if (id !== undefined && id !== null) {
key = `${id}`;
} else if (_id !== undefined && _id !== null) {
key = `${_id}`;
if (this.keys[data.__typename]) {
key = this.keys[data.__typename](data);
} else if (data.id != null) {
key = `${data.id}`;
} else if (data._id != null) {
key = `${data._id}`;
}

return key ? `${typename}:${key}` : null;
return key ? `${data.__typename}:${key}` : null;
}

resolveFieldByKey(entity: Data | string | null, fieldKey: string): DataField {
resolve(
entity: Data | string | null,
field: string,
args?: Variables
): DataField {
const fieldKey = keyOfField(field, args);
const entityKey = this.keyOfEntity(entity);
if (!entityKey) return null;
const fieldValue = InMemoryData.readRecord(entityKey, fieldKey);
if (fieldValue !== undefined) return fieldValue;
const link = InMemoryData.readLink(entityKey, fieldKey);
return link ? link : null;
return link || null;
}

resolve(
entity: Data | string | null,
field: string,
args?: Variables
): DataField {
return this.resolveFieldByKey(entity, keyOfField(field, args));
}
resolveFieldByKey = this.resolve;

invalidate(entity: Data | string | null, field?: string, args?: Variables) {
const entityKey = this.keyOfEntity(entity);
Expand Down
2 changes: 1 addition & 1 deletion exchanges/graphcache/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export interface Cache {
args?: Variables
): DataField;

/** resolveFieldByKey() returns a field's value on an entity, given that field's key */
/** @deprecated use resolve() instead */
resolveFieldByKey(entity: Data | string | null, fieldKey: string): DataField;

/** inspectFields() retrieves all known fields for a given entity */
Expand Down