houdini 0.17.9 → 0.17.10

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.
Files changed (121) hide show
  1. package/README.md +33 -0
  2. package/build/cmd-cjs/index.js +2 -2
  3. package/build/cmd-esm/index.js +2 -2
  4. package/package.json +16 -1
  5. package/.turbo/turbo-compile.log +0 -5
  6. package/.turbo/turbo-typedefs.log +0 -5
  7. package/CHANGELOG.md +0 -377
  8. package/src/cmd/generate.ts +0 -54
  9. package/src/cmd/index.ts +0 -60
  10. package/src/cmd/init.ts +0 -637
  11. package/src/cmd/pullSchema.ts +0 -40
  12. package/src/codegen/generators/artifacts/artifacts.test.ts +0 -3246
  13. package/src/codegen/generators/artifacts/fieldKey.ts +0 -60
  14. package/src/codegen/generators/artifacts/index.ts +0 -330
  15. package/src/codegen/generators/artifacts/indexFile.ts +0 -24
  16. package/src/codegen/generators/artifacts/inputs.ts +0 -81
  17. package/src/codegen/generators/artifacts/operations.ts +0 -281
  18. package/src/codegen/generators/artifacts/pagination.test.ts +0 -664
  19. package/src/codegen/generators/artifacts/policy.test.ts +0 -298
  20. package/src/codegen/generators/artifacts/selection.ts +0 -208
  21. package/src/codegen/generators/artifacts/utils.test.ts +0 -118
  22. package/src/codegen/generators/artifacts/utils.ts +0 -108
  23. package/src/codegen/generators/definitions/enums.test.ts +0 -61
  24. package/src/codegen/generators/definitions/enums.ts +0 -68
  25. package/src/codegen/generators/definitions/index.ts +0 -11
  26. package/src/codegen/generators/definitions/schema.test.ts +0 -236
  27. package/src/codegen/generators/index.ts +0 -6
  28. package/src/codegen/generators/indexFile/index.ts +0 -63
  29. package/src/codegen/generators/indexFile/indexFile.test.ts +0 -72
  30. package/src/codegen/generators/persistedQueries/index.ts +0 -55
  31. package/src/codegen/generators/persistedQueries/persistedQuery.test.ts +0 -26
  32. package/src/codegen/generators/runtime/index.test.ts +0 -74
  33. package/src/codegen/generators/runtime/index.ts +0 -64
  34. package/src/codegen/generators/runtime/runtime.test.ts +0 -25
  35. package/src/codegen/generators/typescript/addReferencedInputTypes.ts +0 -77
  36. package/src/codegen/generators/typescript/index.ts +0 -412
  37. package/src/codegen/generators/typescript/inlineType.ts +0 -409
  38. package/src/codegen/generators/typescript/typeReference.ts +0 -44
  39. package/src/codegen/generators/typescript/types.ts +0 -81
  40. package/src/codegen/generators/typescript/typescript.test.ts +0 -1434
  41. package/src/codegen/index.ts +0 -406
  42. package/src/codegen/transforms/addID.test.ts +0 -93
  43. package/src/codegen/transforms/addID.ts +0 -86
  44. package/src/codegen/transforms/composeQueries.test.ts +0 -50
  45. package/src/codegen/transforms/composeQueries.ts +0 -154
  46. package/src/codegen/transforms/fragmentVariables.test.ts +0 -636
  47. package/src/codegen/transforms/fragmentVariables.ts +0 -417
  48. package/src/codegen/transforms/index.ts +0 -7
  49. package/src/codegen/transforms/list.ts +0 -484
  50. package/src/codegen/transforms/lists.test.ts +0 -530
  51. package/src/codegen/transforms/paginate.test.ts +0 -1528
  52. package/src/codegen/transforms/paginate.ts +0 -770
  53. package/src/codegen/transforms/schema.test.ts +0 -136
  54. package/src/codegen/transforms/schema.ts +0 -109
  55. package/src/codegen/transforms/typename.test.ts +0 -125
  56. package/src/codegen/transforms/typename.ts +0 -55
  57. package/src/codegen/utils/commonjs.ts +0 -26
  58. package/src/codegen/utils/flattenSelections.ts +0 -179
  59. package/src/codegen/utils/graphql.test.ts +0 -35
  60. package/src/codegen/utils/graphql.ts +0 -79
  61. package/src/codegen/utils/index.ts +0 -5
  62. package/src/codegen/utils/moduleExport.ts +0 -27
  63. package/src/codegen/utils/murmur.ts +0 -79
  64. package/src/codegen/validators/index.ts +0 -4
  65. package/src/codegen/validators/noIDAlias.test.ts +0 -71
  66. package/src/codegen/validators/noIDAlias.ts +0 -39
  67. package/src/codegen/validators/plugins.ts +0 -25
  68. package/src/codegen/validators/typeCheck.test.ts +0 -960
  69. package/src/codegen/validators/typeCheck.ts +0 -1086
  70. package/src/codegen/validators/uniqueNames.test.ts +0 -59
  71. package/src/codegen/validators/uniqueNames.ts +0 -39
  72. package/src/lib/cleanupFiles.ts +0 -20
  73. package/src/lib/config.test.ts +0 -13
  74. package/src/lib/config.ts +0 -954
  75. package/src/lib/constants.ts +0 -11
  76. package/src/lib/error.ts +0 -24
  77. package/src/lib/fs.ts +0 -285
  78. package/src/lib/graphql.test.ts +0 -211
  79. package/src/lib/graphql.ts +0 -200
  80. package/src/lib/imports.ts +0 -82
  81. package/src/lib/index.ts +0 -17
  82. package/src/lib/introspection.ts +0 -39
  83. package/src/lib/parse.test.ts +0 -75
  84. package/src/lib/parse.ts +0 -23
  85. package/src/lib/path.ts +0 -49
  86. package/src/lib/pipeline.ts +0 -17
  87. package/src/lib/types.ts +0 -34
  88. package/src/lib/walk.ts +0 -104
  89. package/src/runtime/cache/cache.ts +0 -1026
  90. package/src/runtime/cache/gc.ts +0 -56
  91. package/src/runtime/cache/index.ts +0 -3
  92. package/src/runtime/cache/lists.ts +0 -516
  93. package/src/runtime/cache/storage.ts +0 -574
  94. package/src/runtime/cache/stuff.ts +0 -77
  95. package/src/runtime/cache/subscription.ts +0 -329
  96. package/src/runtime/cache/tests/availability.test.ts +0 -408
  97. package/src/runtime/cache/tests/gc.test.ts +0 -319
  98. package/src/runtime/cache/tests/keys.test.ts +0 -36
  99. package/src/runtime/cache/tests/list.test.ts +0 -3854
  100. package/src/runtime/cache/tests/readwrite.test.ts +0 -1201
  101. package/src/runtime/cache/tests/scalars.test.ts +0 -218
  102. package/src/runtime/cache/tests/storage.test.ts +0 -426
  103. package/src/runtime/cache/tests/subscriptions.test.ts +0 -1757
  104. package/src/runtime/index.ts +0 -29
  105. package/src/runtime/lib/config.ts +0 -211
  106. package/src/runtime/lib/constants.ts +0 -17
  107. package/src/runtime/lib/deepEquals.ts +0 -32
  108. package/src/runtime/lib/errors.ts +0 -8
  109. package/src/runtime/lib/index.ts +0 -8
  110. package/src/runtime/lib/log.ts +0 -69
  111. package/src/runtime/lib/network.ts +0 -303
  112. package/src/runtime/lib/networkUtils.ts +0 -151
  113. package/src/runtime/lib/scalars.test.ts +0 -877
  114. package/src/runtime/lib/scalars.ts +0 -195
  115. package/src/runtime/lib/types.ts +0 -195
  116. package/src/test/index.ts +0 -294
  117. package/src/vite/ast.ts +0 -107
  118. package/src/vite/houdini.ts +0 -113
  119. package/src/vite/imports.ts +0 -129
  120. package/src/vite/index.ts +0 -55
  121. package/src/vite/schema.ts +0 -80
@@ -1,329 +0,0 @@
1
- import type { SubscriptionSpec, SubscriptionSelection, GraphQLObject } from '../lib/types'
2
- import type { GraphQLValue } from '../lib/types'
3
- import { Cache, LinkedList } from './cache'
4
- import { evaluateKey, flattenList } from './stuff'
5
-
6
- // manage the subscriptions
7
- export class InMemorySubscriptions {
8
- private cache: Cache
9
-
10
- constructor(cache: Cache) {
11
- this.cache = cache
12
- }
13
-
14
- private subscribers: { [id: string]: { [fieldName: string]: SubscriptionSpec[] } } = {}
15
- private referenceCounts: {
16
- [id: string]: { [fieldName: string]: Map<SubscriptionSpec['set'], number> }
17
- } = {}
18
- private keyVersions: { [key: string]: Set<string> } = {}
19
-
20
- add({
21
- parent,
22
- spec,
23
- selection,
24
- variables,
25
- parentType,
26
- }: {
27
- parent: string
28
- parentType?: string
29
- spec: SubscriptionSpec
30
- selection: SubscriptionSelection
31
- variables: { [key: string]: GraphQLValue }
32
- }) {
33
- for (const fieldSelection of Object.values(selection)) {
34
- const { keyRaw, fields, type } = fieldSelection
35
-
36
- const key = evaluateKey(keyRaw, variables)
37
-
38
- // add the subscriber to the field
39
- this.addFieldSubscription({
40
- id: parent,
41
- key,
42
- selection: fieldSelection,
43
- spec,
44
- parentType: parentType || spec.rootType,
45
- variables,
46
- })
47
-
48
- // if the field points to a link, we need to subscribe to any fields of that
49
- // linked record
50
- if (fields) {
51
- // if the link points to a record then we just have to add it to the one
52
- const { value: linkedRecord } = this.cache._internal_unstable.storage.get(
53
- parent,
54
- key
55
- )
56
- let children = !Array.isArray(linkedRecord)
57
- ? [linkedRecord]
58
- : flattenList(linkedRecord) || []
59
-
60
- // add the subscriber to every child
61
- for (const child of children) {
62
- // avoid null children
63
- if (!child) {
64
- continue
65
- }
66
- // make sure the children update this subscription
67
- this.add({
68
- parent: child as string,
69
- spec,
70
- selection: fields,
71
- variables,
72
- parentType: type,
73
- })
74
- }
75
- }
76
- }
77
- }
78
-
79
- addFieldSubscription({
80
- id,
81
- key,
82
- selection,
83
- spec,
84
- parentType,
85
- variables,
86
- }: {
87
- id: string
88
- key: string
89
- selection: SubscriptionSelection[string]
90
- spec: SubscriptionSpec
91
- parentType: string
92
- variables: GraphQLObject
93
- }) {
94
- // if we haven't seen the id or field before, create a list we can add to
95
- if (!this.subscribers[id]) {
96
- this.subscribers[id] = {}
97
- }
98
- if (!this.subscribers[id][key]) {
99
- this.subscribers[id][key] = []
100
- }
101
-
102
- // if this is the first time we've seen the raw key
103
- if (!this.keyVersions[key]) {
104
- this.keyVersions[key] = new Set()
105
- }
106
-
107
- // add this version of the key if we need to
108
- this.keyVersions[key].add(key)
109
-
110
- if (!this.subscribers[id][key].map(({ set }) => set).includes(spec.set)) {
111
- this.subscribers[id][key].push(spec)
112
- }
113
-
114
- // if this is the first time we've seen this key
115
- if (!this.referenceCounts[id]) {
116
- this.referenceCounts[id] = {}
117
- }
118
- if (!this.referenceCounts[id][key]) {
119
- this.referenceCounts[id][key] = new Map()
120
- }
121
- const counts = this.referenceCounts[id][key]
122
-
123
- // we're going to increment the current value by one
124
- counts.set(spec.set, (counts.get(spec.set) || 0) + 1)
125
-
126
- // reset the lifetime for the key
127
- this.cache._internal_unstable.lifetimes.resetLifetime(id, key)
128
-
129
- // if this field is marked as a list, register it. this will overwrite existing list handlers
130
- // so that they can get up to date filters
131
- const { fields, list, filters } = selection
132
- if (fields && list) {
133
- this.cache._internal_unstable.lists.add({
134
- name: list.name,
135
- connection: list.connection,
136
- recordID: id,
137
- recordType:
138
- (this.cache._internal_unstable.storage.get(id, '__typename')
139
- ?.value as string) || parentType,
140
- listType: list.type,
141
- key,
142
- selection: fields,
143
- filters: Object.entries(filters || {}).reduce((acc, [key, { kind, value }]) => {
144
- return {
145
- ...acc,
146
- [key]: kind !== 'Variable' ? value : variables[value as string],
147
- }
148
- }, {}),
149
- })
150
- }
151
- }
152
-
153
- // this is different from add because of the treatment of lists
154
- addMany({
155
- parent,
156
- selection,
157
- variables,
158
- subscribers,
159
- parentType,
160
- }: {
161
- parent: string
162
- selection: SubscriptionSelection
163
- variables: {}
164
- subscribers: SubscriptionSpec[]
165
- parentType: string
166
- }) {
167
- // look at every field in the selection and add the subscribers
168
- for (const fieldSelection of Object.values(selection)) {
169
- const { type: linkedType, keyRaw, fields } = fieldSelection
170
- const key = evaluateKey(keyRaw, variables)
171
-
172
- // add the subscriber to the
173
- for (const spec of subscribers) {
174
- this.addFieldSubscription({
175
- id: parent,
176
- key,
177
- selection: fieldSelection,
178
- spec,
179
- parentType,
180
- variables,
181
- })
182
- }
183
-
184
- // if there are fields under this
185
- if (fields) {
186
- const { value: link } = this.cache._internal_unstable.storage.get(parent, key)
187
-
188
- // figure out who else needs subscribers
189
- const children = !Array.isArray(link)
190
- ? ([link] as string[])
191
- : flattenList(link as string[])
192
- for (const linkedRecord of children) {
193
- // avoid null records
194
- if (!linkedRecord) {
195
- continue
196
- }
197
- // insert the subscriber
198
- this.addMany({
199
- parent: linkedRecord,
200
- selection: fields,
201
- variables,
202
- subscribers,
203
- parentType: linkedType,
204
- })
205
- }
206
- }
207
- }
208
- }
209
-
210
- get(id: string, field: string): SubscriptionSpec[] {
211
- return this.subscribers[id]?.[field] || []
212
- }
213
-
214
- remove(
215
- id: string,
216
- fields: SubscriptionSelection,
217
- targets: SubscriptionSpec[],
218
- variables: {},
219
- visited: string[] = []
220
- ) {
221
- visited.push(id)
222
-
223
- // walk down to every record we know about
224
- const linkedIDs: [string, SubscriptionSelection][] = []
225
-
226
- // look at the fields for ones corresponding to links
227
- for (const selection of Object.values(fields)) {
228
- const key = evaluateKey(selection.keyRaw, variables)
229
-
230
- // remove the subscribers for the field
231
- this.removeSubscribers(id, key, targets)
232
-
233
- // if there is no subselection it doesn't point to a link, move on
234
- if (!selection.fields) {
235
- continue
236
- }
237
-
238
- // if there is a link associated with this field we need to destroy the handler
239
- if (selection.list) {
240
- }
241
-
242
- const { value: previousValue } = this.cache._internal_unstable.storage.get(id, key)
243
-
244
- // if its not a list, wrap it as one so we can dry things up
245
- const links = !Array.isArray(previousValue)
246
- ? [previousValue as string]
247
- : flattenList(previousValue as LinkedList)
248
-
249
- for (const link of links) {
250
- if (link !== null) {
251
- linkedIDs.push([link, selection.fields])
252
- }
253
- }
254
- }
255
-
256
- for (const [linkedRecordID, linkFields] of linkedIDs) {
257
- this.remove(linkedRecordID, linkFields, targets, visited)
258
- }
259
- }
260
-
261
- private removeSubscribers(id: string, fieldName: string, specs: SubscriptionSpec[]) {
262
- // build up a list of the sets we actually need to remove after
263
- // checking reference counts
264
- let targets: SubscriptionSpec['set'][] = []
265
-
266
- for (const spec of specs) {
267
- // if we dont know this field/set combo, there's nothing to do (probably a bug somewhere)
268
- if (!this.referenceCounts[id]?.[fieldName]?.has(spec.set)) {
269
- continue
270
- }
271
- const counts = this.referenceCounts[id][fieldName]
272
- const newVal = (counts.get(spec.set) || 0) - 1
273
-
274
- // decrement the reference of every field
275
- counts.set(spec.set, newVal)
276
-
277
- // if that was the last reference we knew of
278
- if (newVal <= 0) {
279
- targets.push(spec.set)
280
- // remove the reference to the set function
281
- counts.delete(spec.set)
282
- }
283
- }
284
-
285
- // we do need to remove the set from the list
286
- if (this.subscribers[id]) {
287
- this.subscribers[id][fieldName] = this.get(id, fieldName).filter(
288
- ({ set }) => !targets.includes(set)
289
- )
290
- }
291
- }
292
-
293
- removeAllSubscribers(id: string, targets?: SubscriptionSpec[], visited: string[] = []) {
294
- visited.push(id)
295
-
296
- // every field that currently being subscribed to needs to be cleaned up
297
- for (const field of Object.keys(this.subscribers[id] || [])) {
298
- // grab the current set of subscribers
299
- const subscribers = targets || this.subscribers[id][field]
300
-
301
- // delete the subscriber for the field
302
- this.removeSubscribers(id, field, subscribers)
303
-
304
- // look up the value for the field so we can remove any subscribers that existed because of a
305
- // subscriber to this record
306
- const { value, kind } = this.cache._internal_unstable.storage.get(id, field)
307
-
308
- // if the field is a scalar, there's nothing more to do
309
- if (kind === 'scalar') {
310
- continue
311
- }
312
-
313
- // if the value is a single link , wrap it in a list. otherwise, flatten the link list
314
- const nextTargets = Array.isArray(value)
315
- ? flattenList(value as LinkedList)
316
- : [value as string]
317
-
318
- for (const id of nextTargets) {
319
- // if we have already visited this id, move on
320
- if (visited.includes(id)) {
321
- continue
322
- }
323
-
324
- // keep walking down
325
- this.removeAllSubscribers(id, subscribers, visited)
326
- }
327
- }
328
- }
329
- }
@@ -1,408 +0,0 @@
1
- import { test, expect, vi } from 'vitest'
2
-
3
- import { testConfigFile } from '../../../test'
4
- import { Cache } from '../cache'
5
-
6
- const config = testConfigFile()
7
-
8
- test('not partial', function () {
9
- // instantiate the cache
10
- const cache = new Cache(config)
11
-
12
- const selection = {
13
- viewer: {
14
- type: 'User',
15
- keyRaw: 'viewer',
16
- fields: {
17
- id: {
18
- type: 'ID',
19
- keyRaw: 'id',
20
- },
21
- firstName: {
22
- type: 'String',
23
- keyRaw: 'firstName',
24
- },
25
- friends: {
26
- type: 'User',
27
- keyRaw: 'friends',
28
- nullable: true,
29
- fields: {
30
- id: {
31
- type: 'ID',
32
- keyRaw: 'id',
33
- },
34
- firstName: {
35
- type: 'String',
36
- keyRaw: 'firstName',
37
- },
38
- },
39
- },
40
- },
41
- },
42
- }
43
-
44
- // make sure we can't resolve it already
45
- expect(cache.read({ selection })).toMatchObject({
46
- data: null,
47
- partial: false,
48
- })
49
-
50
- // add some data to the cache
51
- cache.write({
52
- selection,
53
- data: {
54
- viewer: {
55
- id: '1',
56
- firstName: 'bob',
57
- friends: [
58
- {
59
- id: '2',
60
- firstName: 'jane',
61
- },
62
- null,
63
- ],
64
- },
65
- },
66
- })
67
-
68
- // make sure we can't resolve it already
69
- expect(cache.read({ selection })).toMatchObject({
70
- partial: false,
71
- })
72
- })
73
-
74
- test('not partial with empty list', function () {
75
- // instantiate the cache
76
- const cache = new Cache(config)
77
-
78
- const selection = {
79
- viewer: {
80
- type: 'User',
81
- keyRaw: 'viewer',
82
- fields: {
83
- id: {
84
- type: 'ID',
85
- keyRaw: 'id',
86
- },
87
- firstName: {
88
- type: 'String',
89
- keyRaw: 'firstName',
90
- },
91
- friends: {
92
- type: 'User',
93
- keyRaw: 'friends',
94
- fields: {
95
- id: {
96
- type: 'ID',
97
- keyRaw: 'id',
98
- },
99
- firstName: {
100
- type: 'String',
101
- keyRaw: 'firstName',
102
- },
103
- },
104
- },
105
- },
106
- },
107
- }
108
-
109
- // make sure we can't resolve it already
110
- expect(cache.read({ selection })).toMatchObject({
111
- data: null,
112
- partial: false,
113
- })
114
-
115
- // add some data to the cache
116
- cache.write({
117
- selection,
118
- data: {
119
- viewer: {
120
- id: '1',
121
- firstName: 'bob',
122
- friends: [],
123
- },
124
- },
125
- })
126
-
127
- // make sure we get the right partial status
128
- expect(cache.read({ selection })).toMatchObject({
129
- partial: false,
130
- })
131
- })
132
-
133
- test('partial with missing linked record', function () {
134
- // instantiate the cache
135
- const cache = new Cache(config)
136
-
137
- const selection = {
138
- viewer: {
139
- type: 'User',
140
- keyRaw: 'viewer',
141
- fields: {
142
- id: {
143
- type: 'ID',
144
- keyRaw: 'id',
145
- },
146
- firstName: {
147
- type: 'String',
148
- keyRaw: 'firstName',
149
- },
150
- parent: {
151
- type: 'User',
152
- keyRaw: 'parent',
153
- fields: {
154
- id: {
155
- type: 'ID',
156
- keyRaw: 'id',
157
- },
158
- firstName: {
159
- type: 'String',
160
- keyRaw: 'firstName',
161
- },
162
- },
163
- },
164
- },
165
- },
166
- }
167
-
168
- // make sure we can't resolve it already
169
- expect(cache.read({ selection })).toMatchObject({
170
- data: null,
171
- partial: false,
172
- })
173
-
174
- // add some data to the cache
175
- cache.write({
176
- selection,
177
- data: {
178
- viewer: {
179
- id: '1',
180
- firstName: 'bob',
181
- },
182
- },
183
- })
184
-
185
- // make sure we get the right partial status
186
- expect(cache.read({ selection })).toMatchObject({
187
- partial: true,
188
- })
189
- })
190
-
191
- test('partial with missing single field', function () {
192
- // instantiate the cache
193
- const cache = new Cache(config)
194
-
195
- const selection = {
196
- viewer: {
197
- type: 'User',
198
- keyRaw: 'viewer',
199
- fields: {
200
- id: {
201
- type: 'ID',
202
- keyRaw: 'id',
203
- },
204
- firstName: {
205
- type: 'String',
206
- keyRaw: 'firstName',
207
- },
208
- friends: {
209
- type: 'User',
210
- keyRaw: 'friends',
211
- fields: {
212
- id: {
213
- type: 'ID',
214
- keyRaw: 'id',
215
- },
216
- firstName: {
217
- type: 'String',
218
- keyRaw: 'firstName',
219
- },
220
- },
221
- },
222
- },
223
- },
224
- }
225
-
226
- // add some data to the cache
227
- cache.write({
228
- selection,
229
- data: {
230
- viewer: {
231
- id: '1',
232
- friends: [],
233
- },
234
- },
235
- })
236
-
237
- expect(cache.read({ selection })).toMatchObject({
238
- partial: true,
239
- })
240
- })
241
-
242
- test('partial missing data inside of linked list', function () {
243
- // instantiate the cache
244
- const cache = new Cache(config)
245
-
246
- const selection = {
247
- viewer: {
248
- type: 'User',
249
- keyRaw: 'viewer',
250
- fields: {
251
- id: {
252
- type: 'ID',
253
- keyRaw: 'id',
254
- },
255
- friends: {
256
- type: 'User',
257
- keyRaw: 'friends',
258
- fields: {
259
- id: {
260
- type: 'ID',
261
- keyRaw: 'id',
262
- },
263
- firstName: {
264
- type: 'String',
265
- keyRaw: 'firstName',
266
- },
267
- },
268
- },
269
- },
270
- },
271
- }
272
-
273
- // add some data to the cache with an incomplete set of values for an element
274
- // inside of a list
275
- cache.write({
276
- selection,
277
- data: {
278
- viewer: {
279
- id: '1',
280
- friends: [{ id: '2', firstName: 'anthony' }, { id: '3' }],
281
- },
282
- },
283
- })
284
-
285
- expect(cache.read({ selection })).toMatchObject({
286
- partial: true,
287
- })
288
- })
289
-
290
- test('missing cursor of item in connection from operation should not trigger null cascade', function () {
291
- // instantiate the cache
292
- const cache = new Cache(config)
293
-
294
- const selection = {
295
- viewer: {
296
- type: 'User',
297
- keyRaw: 'viewer',
298
- fields: {
299
- id: {
300
- type: 'ID',
301
- keyRaw: 'id',
302
- },
303
- friends: {
304
- type: 'User',
305
- keyRaw: 'friends',
306
- list: {
307
- name: 'All_Users',
308
- connection: true,
309
- type: 'User',
310
- },
311
- fields: {
312
- edges: {
313
- type: 'UserEdge',
314
- keyRaw: 'edges',
315
- fields: {
316
- cursor: {
317
- type: 'Node',
318
- keyRaw: 'cursor',
319
- nullable: false,
320
- },
321
- node: {
322
- type: 'Node',
323
- keyRaw: 'node',
324
- abstract: true,
325
- fields: {
326
- __typename: {
327
- type: 'String',
328
- keyRaw: '__typename',
329
- },
330
- id: {
331
- type: 'ID',
332
- keyRaw: 'id',
333
- },
334
- firstName: {
335
- type: 'String',
336
- keyRaw: 'firstName',
337
- },
338
- },
339
- },
340
- },
341
- },
342
- },
343
- },
344
- },
345
- },
346
- }
347
-
348
- // add some elements to the list already
349
- cache.write({
350
- selection,
351
- data: {
352
- viewer: {
353
- id: '1',
354
- friends: {
355
- edges: [
356
- {
357
- node: {
358
- __typename: 'User',
359
- id: '2',
360
- firstName: 'jane',
361
- },
362
- },
363
- ],
364
- },
365
- },
366
- },
367
- })
368
-
369
- cache.subscribe({
370
- set: vi.fn(),
371
- selection,
372
- rootType: 'Query',
373
- })
374
-
375
- // add some data to the cache with an incomplete set of values for an element
376
- // inside of a list
377
- cache.list('All_Users').prepend(
378
- {
379
- __typename: {
380
- type: 'String',
381
- keyRaw: '__typename',
382
- },
383
- id: {
384
- type: 'ID',
385
- keyRaw: 'id',
386
- },
387
- firstName: {
388
- type: 'String',
389
- keyRaw: 'firstName',
390
- },
391
- },
392
- {
393
- __typename: 'User',
394
- id: '2',
395
- firstName: 'Sally',
396
- }
397
- )
398
-
399
- expect(cache.read({ selection })).not.toMatchObject({
400
- data: {
401
- viewer: {
402
- friends: {
403
- edges: expect.arrayContaining([null]),
404
- },
405
- },
406
- },
407
- })
408
- })