houdini-core 2.0.0-next.28 → 2.0.0-next.31

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "houdini-core",
3
- "version": "2.0.0-next.28",
3
+ "version": "2.0.0-next.31",
4
4
  "description": "The core GraphQL client for Houdini",
5
5
  "keywords": [
6
6
  "graphql",
@@ -21,13 +21,13 @@
21
21
  "minimatch": "^10.2.5"
22
22
  },
23
23
  "optionalDependencies": {
24
- "houdini-core-darwin-x64": "2.0.0-next.28",
25
- "houdini-core-darwin-arm64": "2.0.0-next.28",
26
- "houdini-core-linux-x64": "2.0.0-next.28",
27
- "houdini-core-linux-arm64": "2.0.0-next.28",
28
- "houdini-core-win32-x64": "2.0.0-next.28",
29
- "houdini-core-win32-arm64": "2.0.0-next.28",
30
- "houdini-core-wasm": "2.0.0-next.28"
24
+ "houdini-core-darwin-x64": "2.0.0-next.31",
25
+ "houdini-core-darwin-arm64": "2.0.0-next.31",
26
+ "houdini-core-linux-x64": "2.0.0-next.31",
27
+ "houdini-core-linux-arm64": "2.0.0-next.31",
28
+ "houdini-core-win32-x64": "2.0.0-next.31",
29
+ "houdini-core-win32-arm64": "2.0.0-next.31",
30
+ "houdini-core-wasm": "2.0.0-next.31"
31
31
  },
32
32
  "files": [
33
33
  "bin",
package/postInstall.js CHANGED
@@ -5,7 +5,7 @@ const https = require('https')
5
5
  const child_process = require('child_process')
6
6
 
7
7
  // Adjust the version you want to install. You can also make this dynamic.
8
- const BINARY_DISTRIBUTION_VERSION = '2.0.0-next.28'
8
+ const BINARY_DISTRIBUTION_VERSION = '2.0.0-next.31'
9
9
 
10
10
  // Windows binaries end with .exe so we need to special case them.
11
11
  const binaryName = process.platform === 'win32' ? 'houdini-core.exe' : 'houdini-core'
@@ -6,6 +6,32 @@ import cache from '../cache.js'
6
6
 
7
7
  const serverSide = typeof globalThis.window === 'undefined'
8
8
 
9
+ // walk the response data along a path collecting the record object(s) at the end.
10
+ // a path segment can resolve to a list (eg a @refetch field nested under a list)
11
+ // so each step may fan out to multiple records.
12
+ export function recordsAtPath(
13
+ data: GraphQLObject | null,
14
+ path: readonly string[]
15
+ ): GraphQLObject[] {
16
+ let current: any[] = data ? [data] : []
17
+ for (const key of path) {
18
+ const next: any[] = []
19
+ for (const entry of current) {
20
+ if (entry == null) {
21
+ continue
22
+ }
23
+ const value = entry[key]
24
+ if (Array.isArray(value)) {
25
+ next.push(...value.flat(Infinity))
26
+ } else if (value != null) {
27
+ next.push(value)
28
+ }
29
+ }
30
+ current = next
31
+ }
32
+ return current.filter((entry) => entry && typeof entry === 'object')
33
+ }
34
+
9
35
  export const cachePolicy =
10
36
  ({
11
37
  enabled,
@@ -160,6 +186,40 @@ export const cachePolicy =
160
186
  variables: marshalVariables(ctx),
161
187
  })
162
188
 
189
+ // document-level operations run once the response has been written.
190
+ // @refetch asks every document that depends on a record to reload
191
+ // itself. only mutations and subscriptions trigger this so a query
192
+ // can't refetch itself.
193
+ if (
194
+ (ctx.artifact.kind === ArtifactKind.Mutation ||
195
+ ctx.artifact.kind === ArtifactKind.Subscription) &&
196
+ ctx.artifact.operations?.length &&
197
+ !ctx.cacheParams?.disableWrite
198
+ ) {
199
+ // gather every record id tagged with @refetch, deduped, so a
200
+ // document that depends on several of them only refetches once
201
+ const refreshIDs = new Set<string>()
202
+ for (const operation of ctx.artifact.operations) {
203
+ if (operation.action !== 'refetch') {
204
+ continue
205
+ }
206
+
207
+ for (const record of recordsAtPath(value.data, operation.path)) {
208
+ const id = targetCache._internal_unstable.id(
209
+ (record.__typename as string) ?? operation.type,
210
+ record
211
+ )
212
+ if (id) {
213
+ refreshIDs.add(id)
214
+ }
215
+ }
216
+ }
217
+
218
+ if (refreshIDs.size > 0) {
219
+ targetCache.refresh([...refreshIDs])
220
+ }
221
+ }
222
+
163
223
  // we need to embed the fragment context values in our response
164
224
  // and apply masking other value transforms. In order to do that,
165
225
  // we're going to read back what we just wrote. This only incurs
@@ -45,6 +45,7 @@ export const fragment = (cache: Cache) =>
45
45
  // save the new subscription spec
46
46
  subscriptionSpec = {
47
47
  rootType: ctx.artifact.rootType,
48
+ kind: ctx.artifact.kind,
48
49
  selection: ctx.artifact.selection,
49
50
  variables: () => variables,
50
51
  parentID: ctx.stuff.parentID,
@@ -70,6 +70,7 @@ export const query = (cache: Cache) =>
70
70
  // save the new subscription spec
71
71
  subscriptionSpec = {
72
72
  rootType: ctx.artifact.rootType,
73
+ kind: ctx.artifact.kind,
73
74
  selection: ctx.artifact.selection,
74
75
  variables: () => variables,
75
76
  onMessage: (message) => {