Skip to content

Commit

Permalink
Users can configure a type to always be embedded by setting keys to [] (
Browse files Browse the repository at this point in the history
  • Loading branch information
AlecAivazis committed Jun 28, 2023
1 parent 6f9eeb6 commit 91b445f
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/silver-fans-speak.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'houdini': patch
---

Users can specify that a type is always embedded by setting keys to []
32 changes: 15 additions & 17 deletions packages/houdini/src/runtime/cache/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -560,17 +560,13 @@ class CacheInternal {
}
}

// figure out if this is an embedded object or a linked one by looking for all of the fields marked as
// required to compute the entity's id
const embedded =
this.idFields(linkedType)?.filter(
(field) => typeof value[field] === 'undefined'
).length > 0

// figure out the new target of the object link
let linkedID: string | null = null
if (value !== null) {
linkedID = !embedded ? this.id(linkedType, value) : `${parent}.${key}`
// if the value is embedded then the id needs to be keyed by the field
linkedID = !this.isEmbedded(linkedType, value)
? this.id(linkedType, value)
: `${parent}.${key}`
}
let linkChange = linkedID !== previousValue

Expand Down Expand Up @@ -1219,6 +1215,16 @@ class CacheInternal {
return computeID(this.config, type, data)
}

// figure out if this is an embedded object or a linked one by looking for all of the fields marked as
// required to compute the entity's id
isEmbedded(linkedType: string, value: GraphQLObject) {
const idFields = this.idFields(linkedType)
return (
idFields.length === 0 ||
idFields.filter((field) => typeof value[field] === 'undefined').length > 0
)
}

hydrateNestedList({
fields,
variables,
Expand Down Expand Up @@ -1375,14 +1381,6 @@ class CacheInternal {
// start off building up the embedded id
// @ts-ignore
let linkedID = `${recordID}.${key}[${this.storage.nextRank}]`

// figure out if this is an embedded list or a linked one by looking for all of the fields marked as
// required to compute the entity's id
const embedded =
this.idFields(linkedType)?.filter(
(field) => typeof (entry as GraphQLObject)[field] === 'undefined'
).length > 0

let innerType = linkedType

const typename = entryObj.__typename as string | undefined
Expand All @@ -1394,7 +1392,7 @@ class CacheInternal {
}

// if this isn't an embedded reference, use the entry's id in the link list
if (!embedded) {
if (!this.isEmbedded(linkedType, entry as GraphQLObject)) {
const id = this.id(innerType, entry as {})
if (id) {
linkedID = id
Expand Down
88 changes: 88 additions & 0 deletions packages/houdini/src/runtime/cache/tests/readwrite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2330,3 +2330,91 @@ test('can perform full query check while retrieving masked value', function () {
},
})
})

test('embedded types can be configured with an empty list', function () {
// instantiate the cache
const cache = new Cache({
...config,
types: {
Embedded: {
keys: [],
},
},
})

const selection = {
fields: {
viewer: {
type: 'User',
visible: true,
keyRaw: 'viewer',
selection: {
fields: {
embedded: {
type: 'Embedded',
keyRaw: 'embedded',
visible: true,
selection: {
fields: {
id: {
type: 'ID',
visible: true,
keyRaw: 'id',
},
firstName: {
type: 'String',
visible: true,
keyRaw: 'firstName',
},
},
},
},
},
},
},
},
}

// write the user data without the nested value
cache.write({
selection,
data: {
viewer: {
embedded: [
{
id: '1',
firstName: 'John',
},
{
id: '1',
firstName: 'Jacob',
},
],
},
},
})

expect(
cache.read({
selection,
fullCheck: true,
})
).toEqual({
partial: false,
stale: false,
data: {
viewer: {
embedded: [
{
id: '1',
firstName: 'John',
},
{
id: '1',
firstName: 'Jacob',
},
],
},
},
})
})

0 comments on commit 91b445f

Please sign in to comment.