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,574 +0,0 @@
1
- import type { GraphQLValue } from '../lib/types'
2
- import { flattenList } from './stuff'
3
-
4
- // NOTE: the current implementation of delete is slow. it should try to compare the
5
- // type of the id being deleted with the type contained in the linked list so that
6
- // the removal logic is only performed when its possible the ID is found inside.
7
- // ie: deleting a user should not slow down looking up a list of cats
8
-
9
- export class InMemoryStorage {
10
- private data: Layer[]
11
- private idCount = 0
12
- private rank = 0
13
-
14
- constructor() {
15
- this.data = []
16
- }
17
-
18
- get layerCount(): number {
19
- return this.data.length
20
- }
21
-
22
- get nextRank(): number {
23
- return this.rank++
24
- }
25
-
26
- // create a layer and return its id
27
- createLayer(optimistic: boolean = false): Layer {
28
- // generate the next layer
29
- const layer = new Layer(this.idCount++)
30
- layer.optimistic = optimistic
31
-
32
- // add the layer to the list
33
- this.data.push(layer)
34
-
35
- // pass the layer on so it can be updated
36
- return layer
37
- }
38
-
39
- insert(id: string, field: string, location: OperationLocation, target: string) {
40
- return this.topLayer.insert(id, field, location, target)
41
- }
42
-
43
- remove(id: string, field: string, target: string) {
44
- return this.topLayer.remove(id, field, target)
45
- }
46
-
47
- delete(id: string) {
48
- return this.topLayer.delete(id)
49
- }
50
-
51
- deleteField(id: string, field: string) {
52
- return this.topLayer.deleteField(id, field)
53
- }
54
-
55
- getLayer(id: number): Layer {
56
- for (const layer of this.data) {
57
- if (layer.id === id) {
58
- return layer
59
- }
60
- }
61
-
62
- // we didn't find the layer
63
- throw new Error('Could not find layer with id: ' + id)
64
- }
65
-
66
- replaceID(replacement: { from: string; to: string }) {
67
- for (const layer of this.data) {
68
- layer.replaceID(replacement)
69
- }
70
- }
71
-
72
- get(
73
- id: string,
74
- field: string
75
- ): {
76
- value: GraphQLField
77
- kind: 'link' | 'scalar' | 'unknown'
78
- displayLayers: number[]
79
- } {
80
- // the list of operations for the field
81
- const operations = {
82
- [OperationKind.insert]: {
83
- [OperationLocation.start]: [] as string[],
84
- [OperationLocation.end]: [] as string[],
85
- },
86
- [OperationKind.remove]: new Set<string>(),
87
- }
88
-
89
- // the list of layers we used to build up the value
90
- const layerIDs: number[] = []
91
-
92
- // go through the list of layers in reverse
93
- for (let i = this.data.length - 1; i >= 0; i--) {
94
- const layer = this.data[i]
95
- const [layerValue, kind] = layer.get(id, field)
96
- const layerOperations = layer.getOperations(id, field) || []
97
- layer.deletedIDs.forEach((v) => {
98
- // if the layer wants to undo a delete for the id
99
- if (layer.operations[v]?.undoDeletesInList?.includes(field)) {
100
- return
101
- }
102
- operations.remove.add(v)
103
- })
104
-
105
- // if the layer does not contain a value for the field, move on
106
- if (typeof layerValue === 'undefined' && layerOperations.length === 0) {
107
- if (layer.deletedIDs.size > 0) {
108
- layerIDs.push(layer.id)
109
- }
110
- continue
111
- }
112
-
113
- // if the result isn't an array we can just use the value since we can't
114
- // apply operations to the field
115
- if (typeof layerValue !== 'undefined' && !Array.isArray(layerValue)) {
116
- return {
117
- value: layerValue,
118
- kind,
119
- displayLayers: [layer.id],
120
- }
121
- }
122
-
123
- // if the layer contains operations or values add it to the list of relevant layers
124
- // add the layer to the list
125
- layerIDs.push(layer.id)
126
-
127
- // if we have an operation
128
- if (layerOperations.length > 0) {
129
- // process every operation
130
- for (const op of layerOperations) {
131
- // remove operation
132
- if (isRemoveOperation(op)) {
133
- operations.remove.add(op.id)
134
- }
135
- // inserts are sorted by location
136
- if (isInsertOperation(op)) {
137
- operations.insert[op.location].unshift(op.id)
138
- }
139
- // if we found a delete operation, we're done
140
- if (isDeleteOperation(op)) {
141
- return {
142
- value: undefined,
143
- kind: 'unknown',
144
- displayLayers: [],
145
- }
146
- }
147
- }
148
- }
149
-
150
- // if we don't have a value to return, we're done
151
- if (typeof layerValue === 'undefined') {
152
- continue
153
- }
154
-
155
- // if there are no operations, move along
156
- if (
157
- !operations.remove.size &&
158
- !operations.insert.start.length &&
159
- !operations.insert.end.length
160
- ) {
161
- return { value: layerValue, displayLayers: layerIDs, kind: 'link' }
162
- }
163
-
164
- // we have operations to apply to the list
165
- return {
166
- value: [...operations.insert.start, ...layerValue, ...operations.insert.end].filter(
167
- (value) => !operations.remove.has(value as string)
168
- ),
169
- displayLayers: layerIDs,
170
- kind,
171
- }
172
- }
173
-
174
- return {
175
- value: undefined,
176
- kind: 'unknown',
177
- displayLayers: [],
178
- }
179
- }
180
-
181
- writeLink(id: string, field: string, value: string | LinkedList) {
182
- // write to the top most layer
183
- return this.topLayer.writeLink(id, field, value)
184
- }
185
-
186
- writeField(id: string, field: string, value: GraphQLValue) {
187
- return this.topLayer.writeField(id, field, value)
188
- }
189
-
190
- resolveLayer(id: number): void {
191
- let startingIndex: number | null = null
192
-
193
- // find the layer with the matching id
194
- for (const [index, layer] of this.data.entries()) {
195
- if (layer.id !== id) {
196
- continue
197
- }
198
-
199
- // we found the target layer
200
- startingIndex = index - 1
201
-
202
- // its not optimistic any more
203
- this.data[index].optimistic = false
204
-
205
- // we're done
206
- break
207
- }
208
-
209
- // if we didn't find the layer, yell loudly
210
- if (startingIndex === null) {
211
- throw new Error('could not find layer with id: ' + id)
212
- }
213
-
214
- // if we are resolving the base layer make sure we start at zero
215
- if (startingIndex === -1) {
216
- startingIndex = 0
217
- }
218
-
219
- // if the starting layer is optimistic then we can't write to it
220
- if (this.data[startingIndex].optimistic) {
221
- startingIndex++
222
- }
223
-
224
- // start walking down the list of layers, applying any non-optimistic ones to the target
225
- const baseLayer = this.data[startingIndex]
226
- let layerIndex = startingIndex
227
- while (layerIndex < this.data.length) {
228
- // the layer in question and move the counter up one after we index
229
- const layer = this.data[layerIndex++]
230
-
231
- // if the layer is optimistic, we can't go further
232
- if (layer.optimistic) {
233
- layerIndex--
234
- break
235
- }
236
-
237
- // apply the layer onto our base
238
- baseLayer.writeLayer(layer)
239
- }
240
-
241
- // delete the layers we merged
242
- this.data.splice(startingIndex + 1, layerIndex - startingIndex - 1)
243
- }
244
-
245
- get topLayer(): Layer {
246
- // if there is no base layer
247
- if (this.data.length === 0) {
248
- this.createLayer()
249
- }
250
-
251
- // if the last layer is optimistic, create another layer on top of it
252
- // since optimistic layers have to be written to directly
253
- if (this.data[this.data.length - 1]?.optimistic) {
254
- this.createLayer()
255
- }
256
-
257
- // the top layer is safe to write to (its non-null and guaranteed not optimistic)
258
- return this.data[this.data.length - 1]
259
- }
260
- }
261
-
262
- export class Layer {
263
- readonly id: LayerID
264
-
265
- optimistic: boolean = false
266
-
267
- fields: EntityFieldMap = {}
268
- links: LinkMap = {}
269
- operations: OperationMap = {}
270
- deletedIDs = new Set<string>()
271
-
272
- constructor(id: number) {
273
- this.id = id
274
- }
275
-
276
- get(id: string, field: string): [GraphQLField, 'link' | 'scalar'] {
277
- // if its a link return the value
278
- if (typeof this.links[id]?.[field] !== 'undefined') {
279
- return [this.links[id][field], 'link']
280
- }
281
-
282
- // only other option is a value
283
- return [this.fields[id]?.[field], 'scalar']
284
- }
285
-
286
- getOperations(id: string, field: string): Operation[] | undefined {
287
- // if the id has been deleted
288
- if (this.operations[id]?.deleted) {
289
- return [
290
- {
291
- kind: OperationKind.delete,
292
- target: id,
293
- },
294
- ]
295
- }
296
-
297
- // there could be a mutation for the specific field
298
- if (this.operations[id]?.fields?.[field]) {
299
- return this.operations[id].fields[field]
300
- }
301
- }
302
-
303
- writeField(id: string, field: string, value: GraphQLField): LayerID {
304
- this.fields[id] = {
305
- ...this.fields[id],
306
- [field]: value,
307
- }
308
-
309
- return this.id
310
- }
311
-
312
- writeLink(id: string, field: string, value: null | string | LinkedList): LayerID {
313
- // if any of the values in this link are flagged to be deleted, undelete it
314
- const valueList = Array.isArray(value) ? value : [value]
315
- for (const value of flattenList(valueList)) {
316
- if (!value) {
317
- continue
318
- }
319
-
320
- const fieldOperations = this.operations[id]?.fields[field]
321
-
322
- // if the operation was globally deleted
323
- if (this.operations[value]?.deleted || this.deletedIDs.has(value)) {
324
- // undo the delete
325
- this.operations[value] = {
326
- ...this.operations[value],
327
- undoDeletesInList: [...(this.operations[id]?.undoDeletesInList || []), field],
328
- }
329
-
330
- // the value could have been removed specifically from the list
331
- } else if (value && fieldOperations?.length > 0) {
332
- // if we have a field operation to remove the list, undo the operation
333
- this.operations[id].fields[field] = fieldOperations.filter(
334
- (op) => op.kind !== 'remove' || op.id !== value
335
- )
336
- }
337
- }
338
-
339
- this.links[id] = {
340
- ...this.links[id],
341
- [field]: value,
342
- }
343
-
344
- return this.id
345
- }
346
-
347
- isDisplayLayer(displayLayers: number[]) {
348
- return (
349
- displayLayers.length === 0 ||
350
- displayLayers.includes(this.id) ||
351
- Math.max(...displayLayers) < this.id
352
- )
353
- }
354
-
355
- clear() {
356
- // before we clear the data of the layer, look for any subscribers that need to be updated
357
-
358
- // now that everything has been notified we can reset the data
359
- this.links = {}
360
- this.fields = {}
361
- this.operations = {}
362
- this.deletedIDs = new Set<string>()
363
- }
364
-
365
- replaceID({ from, to }: { from: string; to: string }) {
366
- // any fields that existing in from, assign to to
367
- this.fields[to] = this.fields[from]
368
- this.links[to] = this.links[from]
369
- this.operations[to] = this.operations[from] || { fields: {} }
370
- if (this.deletedIDs.has(from)) {
371
- this.deletedIDs.add(to)
372
- }
373
- }
374
-
375
- removeUndefinedFields() {
376
- // any field that's marked as undefined needs to be deleted
377
- for (const [id, fields] of Object.entries(this.fields)) {
378
- for (const [field, value] of Object.entries(fields)) {
379
- if (typeof value === 'undefined') {
380
- try {
381
- delete this.fields[id][field]
382
- } catch {}
383
- try {
384
- delete this.links[id][field]
385
- } catch {}
386
- }
387
- }
388
-
389
- // if there are no fields left for the object, clean it up
390
- if (Object.keys(fields || {}).length === 0) {
391
- delete this.fields[id]
392
- }
393
-
394
- // if there are no more links, clean it up
395
- if (Object.keys(this.links[id] || {}).length === 0) {
396
- delete this.links[id]
397
- }
398
- }
399
- }
400
-
401
- delete(id: string) {
402
- // add an insert operation to the map
403
- this.operations = {
404
- ...this.operations,
405
- [id]: {
406
- ...this.operations[id],
407
- deleted: true,
408
- // reapply any delete undos
409
- undoDeletesInList: [],
410
- },
411
- }
412
-
413
- // add the id to the list of ids that have been deleted in this layer (so we can filter them out later)
414
- this.deletedIDs.add(id)
415
- }
416
-
417
- deleteField(id: string, field: string) {
418
- this.fields[id] = {
419
- ...this.fields[id],
420
- [field]: undefined,
421
- }
422
- }
423
-
424
- insert(id: string, field: string, where: OperationLocation, target: string) {
425
- // add an insert operation for the field
426
- this.addFieldOperation(id, field, {
427
- kind: OperationKind.insert,
428
- id: target,
429
- location: where,
430
- })
431
- }
432
-
433
- remove(id: string, field: string, target: string) {
434
- // add a remove operation for the field
435
- this.addFieldOperation(id, field, {
436
- kind: OperationKind.remove,
437
- id: target,
438
- })
439
- }
440
-
441
- writeLayer(layer: Layer): void {
442
- // if we are merging into ourselves, we're done
443
- if (layer.id === this.id) {
444
- return
445
- }
446
-
447
- // we have to apply operations before we move fields so we can clean up existing
448
- // data if we have a delete before we copy over the values
449
- for (const [id, ops] of Object.entries(layer.operations)) {
450
- const fields: OperationMap['fieldName']['fields'] = {}
451
-
452
- // merge the two operation maps
453
- for (const opMap of [this.operations[id], layer.operations[id]].filter(Boolean)) {
454
- for (const [fieldName, operations] of Object.entries(opMap.fields || {})) {
455
- fields[fieldName] = [...(fields[fieldName] || []), ...operations]
456
- }
457
- }
458
-
459
- // only copy a field key if there is something
460
- if (Object.keys(fields).length > 0) {
461
- this.operations[id] = {
462
- ...this.operations[id],
463
- fields,
464
- }
465
- }
466
-
467
- // if we are applying
468
- if (ops?.deleted) {
469
- delete this.fields[id]
470
- delete this.links[id]
471
- }
472
- }
473
-
474
- // copy the field values
475
- for (const [id, values] of Object.entries(layer.fields)) {
476
- if (!values) {
477
- continue
478
- }
479
- // we do have a record matching this id, copy the individual fields
480
- for (const [field, value] of Object.entries(values)) {
481
- this.writeField(id, field, value)
482
- }
483
- }
484
-
485
- // copy the link values
486
- for (const [id, values] of Object.entries(layer.links)) {
487
- if (!values) {
488
- continue
489
- }
490
- // we do have a record matching this id, copy the individual links
491
- for (const [field, value] of Object.entries(values)) {
492
- this.writeLink(id, field, value)
493
- }
494
- }
495
-
496
- // add the list of deleted ids to this layer
497
- layer.deletedIDs.forEach((v) => this.deletedIDs.add(v))
498
- }
499
-
500
- private addFieldOperation(id: string, field: string, operation: ListOperation) {
501
- this.operations = {
502
- ...this.operations,
503
- [id]: {
504
- ...this.operations[id],
505
- fields: {
506
- [field]: [...(this.operations[id]?.fields[field] || []), operation],
507
- },
508
- },
509
- }
510
- }
511
- }
512
-
513
- type GraphQLField = GraphQLValue | LinkedList
514
-
515
- type EntityMap<_Value> = { [id: string]: { [field: string]: _Value } }
516
-
517
- type EntityFieldMap = EntityMap<GraphQLField>
518
-
519
- type LinkMap = EntityMap<string | null | LinkedList>
520
-
521
- type OperationMap = {
522
- [id: string]: {
523
- deleted?: boolean
524
- undoDeletesInList?: string[]
525
- fields: { [field: string]: ListOperation[] }
526
- }
527
- }
528
-
529
- type LinkedList<_Result = string> = (_Result | null | LinkedList<_Result>)[]
530
-
531
- type InsertOperation = {
532
- kind: OperationKind.insert
533
- location: OperationLocation
534
- id: string
535
- }
536
-
537
- type RemoveOperation = {
538
- kind: OperationKind.remove
539
- id: string
540
- }
541
-
542
- type DeleteOperation = {
543
- kind: OperationKind.delete
544
- target: string
545
- }
546
-
547
- type ListOperation = InsertOperation | RemoveOperation
548
-
549
- function isDeleteOperation(value: GraphQLField | Operation): value is DeleteOperation {
550
- return !!value && (value as Operation).kind === OperationKind.delete
551
- }
552
-
553
- function isInsertOperation(value: GraphQLField | Operation): value is InsertOperation {
554
- return !!value && (value as Operation).kind === OperationKind.insert
555
- }
556
-
557
- function isRemoveOperation(value: GraphQLField | Operation): value is RemoveOperation {
558
- return !!value && (value as Operation).kind === OperationKind.remove
559
- }
560
-
561
- type Operation = ListOperation | DeleteOperation
562
-
563
- export enum OperationLocation {
564
- start = 'start',
565
- end = 'end',
566
- }
567
-
568
- export enum OperationKind {
569
- delete = 'delete',
570
- insert = 'insert',
571
- remove = 'remove',
572
- }
573
-
574
- export type LayerID = number
@@ -1,77 +0,0 @@
1
- import { GraphQLValue } from '../lib/types'
2
- import { LinkedList } from './cache'
3
-
4
- export function flattenList<T>(source: LinkedList<T>): T[] {
5
- const flat: T[] = []
6
-
7
- // we need to flatten the list links
8
- const unvisited = [source || []]
9
- while (unvisited.length > 0) {
10
- const target = unvisited.shift() as T[]
11
-
12
- for (const id of target) {
13
- if (Array.isArray(id)) {
14
- unvisited.push(id)
15
- continue
16
- }
17
-
18
- flat.push(id)
19
- }
20
- }
21
-
22
- return flat
23
- }
24
-
25
- // given a raw key and a set of variables, generate the fully qualified key
26
- export function evaluateKey(key: string, variables: { [key: string]: GraphQLValue } = {}): string {
27
- // accumulate the evaluated key
28
- let evaluated = ''
29
- // accumulate a variable name that we're evaluating
30
- let varName = ''
31
- // some state to track if we are "in" a string
32
- let inString = false
33
-
34
- for (const char of key) {
35
- // if we are building up a variable
36
- if (varName) {
37
- // if we are looking at a valid variable character
38
- if (varChars.includes(char)) {
39
- // add it to the variable name
40
- varName += char
41
- continue
42
- }
43
- // we are at the end of a variable name so we
44
- // need to clean up and add before continuing with the string
45
-
46
- // look up the variable and add the result (varName starts with a $)
47
- const value = variables[varName.slice(1)]
48
-
49
- evaluated += typeof value !== 'undefined' ? JSON.stringify(value) : 'undefined'
50
-
51
- // clear the variable name accumulator
52
- varName = ''
53
- }
54
-
55
- // if we are looking at the start of a variable
56
- if (char === '$' && !inString) {
57
- // start the accumulator
58
- varName = '$'
59
-
60
- // move along
61
- continue
62
- }
63
-
64
- // if we found a quote, invert the string state
65
- if (char === '"') {
66
- inString = !inString
67
- }
68
-
69
- // this isn't a special case, just add the letter to the value
70
- evaluated += char
71
- }
72
-
73
- return evaluated
74
- }
75
-
76
- // the list of characters that make up a valid graphql variable name
77
- const varChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789'