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,484 +0,0 @@
1
- import { logGreen, logYellow } from '@kitql/helper'
2
- import * as graphql from 'graphql'
3
-
4
- import {
5
- Config,
6
- parentTypeFromAncestors,
7
- HoudiniError,
8
- CollectedGraphQLDocument,
9
- siteURL,
10
- } from '../../lib'
11
- import { ArtifactKind } from '../../runtime/lib/types'
12
- import { TypeWrapper, unwrapType } from '../utils'
13
- import { pageInfoSelection } from './paginate'
14
-
15
- // addListFragments adds fragments for the fields tagged with @list
16
- export default async function addListFragments(
17
- config: Config,
18
- documents: CollectedGraphQLDocument[]
19
- ): Promise<void> {
20
- // collect all of the fields that have the list applied
21
- const lists: {
22
- [name: string]: {
23
- selection: graphql.SelectionSetNode | undefined
24
- type: graphql.GraphQLNamedType
25
- filename: string
26
- }
27
- } = {}
28
-
29
- const errors: Error[] = []
30
- // look at every document
31
- for (const doc of documents) {
32
- doc.document = graphql.visit(doc.document, {
33
- Directive(node, key, parent, path, ancestors) {
34
- // if we found a @list applied (or a @paginate which implies a @list )
35
- if ([config.listDirective, config.paginateDirective].includes(node.name.value)) {
36
- // look up the name passed to the directive
37
- const nameArg = node.arguments?.find((arg) => arg.name.value === 'name')
38
-
39
- // if we need to use an error relative to this node
40
- let error = {
41
- ...new graphql.GraphQLError(
42
- '',
43
- node,
44
- new graphql.Source(''),
45
- node.loc ? [node.loc.start, node.loc.end] : null,
46
- path
47
- ),
48
- filepath: doc.filename,
49
- }
50
-
51
- // if there is no name argument
52
- if (!nameArg) {
53
- // if we are looking at a @list we need a name argument
54
- if (node.name.value === config.listDirective) {
55
- error.message = `@${node.name.value} must have a name argument`
56
- errors.push(error)
57
- }
58
-
59
- // regardless, we don't need to process this node any more
60
- return
61
- }
62
-
63
- // make sure it was a string
64
- if (nameArg.value.kind !== 'StringValue') {
65
- error.message = `@${node.name.value} name must be a string`
66
- errors.push(error)
67
- return
68
- }
69
-
70
- // if we've already seen this list
71
- if (lists[nameArg.value.value]) {
72
- error.message = `@${node.name.value} name must be unique`
73
- errors.push(error)
74
- }
75
-
76
- // look up the parent's type
77
- const parentType = parentTypeFromAncestors(
78
- config.schema,
79
- doc.filename,
80
- ancestors.slice(0, -1)
81
- )
82
-
83
- // a non-connection list can just use the selection set of the tagged field
84
- // but if this is a connection tagged with list we need to use the selection
85
- // of the edges.node field
86
- const targetField = ancestors[ancestors.length - 1] as graphql.FieldNode
87
- const targetFieldDefinition = parentType.getFields()[
88
- targetField.name.value
89
- ] as graphql.GraphQLField<any, any>
90
-
91
- const { selection, type, connection } = connectionSelection(
92
- config,
93
- targetFieldDefinition,
94
- parentTypeFromAncestors(
95
- config.schema,
96
- doc.filename,
97
- ancestors
98
- ) as graphql.GraphQLObjectType,
99
- (ancestors[ancestors.length - 1] as graphql.FieldNode).selectionSet
100
- )
101
-
102
- // add the target of the directive to the list
103
- lists[nameArg.value.value] = {
104
- selection,
105
- type,
106
- filename: doc.filename,
107
- }
108
-
109
- // if the list is marking a connection we need to add the flag in a place we can track when
110
- // generating the artifact
111
- if (connection) {
112
- return {
113
- ...node,
114
- arguments: [
115
- ...node.arguments!,
116
- {
117
- kind: 'Argument',
118
- name: {
119
- kind: graphql.Kind.NAME,
120
- value: 'connection',
121
- },
122
- value: {
123
- kind: 'BooleanValue',
124
- value: true,
125
- },
126
- } as graphql.ArgumentNode,
127
- ],
128
- }
129
- }
130
- }
131
- },
132
- Field(node, key, parent, path, ancestors) {
133
- // if the is marked with @list and is a connection, we need to make sure that we ask for
134
- // the cursor fields
135
- if (
136
- !node.directives?.find(
137
- (directive) => directive.name.value === config.listDirective
138
- )
139
- ) {
140
- return
141
- }
142
-
143
- // the field is a list, is it a connection?
144
-
145
- // look up the parent's type
146
- const parentType = parentTypeFromAncestors(config.schema, doc.filename, ancestors)
147
- // a non-connection list can just use the selection set of the tagged field
148
- // but if this is a connection tagged with list we need to use the selection
149
- // of the edges.node field
150
- const targetField = node
151
- const targetFieldDefinition = parentType.getFields()[
152
- targetField.name.value
153
- ] as graphql.GraphQLField<any, any>
154
-
155
- const { connection } = connectionSelection(
156
- config,
157
- targetFieldDefinition,
158
- parentTypeFromAncestors(
159
- config.schema,
160
- doc.filename,
161
- ancestors
162
- ) as graphql.GraphQLObjectType,
163
- node.selectionSet
164
- )
165
-
166
- // if the field is a connection, add the cursor
167
- if (connection) {
168
- return {
169
- ...node,
170
- selectionSet: {
171
- ...node.selectionSet,
172
- selections: [...node.selectionSet!.selections, ...pageInfoSelection],
173
- },
174
- }
175
- }
176
- },
177
- })
178
- }
179
-
180
- // if we ran into any errors
181
- if (errors.length > 0) {
182
- throw errors
183
- }
184
-
185
- // we need to add a delete directive for every type that is the target of a list
186
- const listTargets = [
187
- ...new Set(
188
- Object.values(lists).map(({ type }) => {
189
- // only consider object types
190
- if (!(type instanceof graphql.GraphQLObjectType)) {
191
- return ''
192
- }
193
-
194
- return type.name
195
- })
196
- ).values(),
197
- ].filter(Boolean)
198
-
199
- // if there are no documents, we don't have anything to do
200
- if (Object.keys(lists).length === 0) {
201
- return
202
- }
203
-
204
- // we need to add the fragment definitions __somewhere__ where they will be picked up
205
- // so we're going to add them to the list of documents, one each
206
- const generatedDoc: graphql.DocumentNode = {
207
- kind: graphql.Kind.DOCUMENT,
208
- definitions: (
209
- Object.entries(lists).flatMap<graphql.FragmentDefinitionNode>(
210
- ([name, { selection, type }]) => {
211
- // look up the type
212
- const schemaType = config.schema.getType(type.name) as graphql.GraphQLObjectType
213
-
214
- // if there is no selection set
215
- if (!selection) {
216
- throw new HoudiniError({ message: 'Lists must have a selection' })
217
- }
218
-
219
- // we need a copy of the field's selection set that we can mutate
220
- const fragmentSelection: graphql.SelectionSetNode = {
221
- kind: graphql.Kind.SELECTION_SET,
222
- selections: [...selection.selections],
223
- }
224
-
225
- // is there no id selection
226
- if (
227
- schemaType &&
228
- fragmentSelection &&
229
- !fragmentSelection?.selections.find(
230
- (field) => field.kind === 'Field' && field.name.value === 'id'
231
- )
232
- ) {
233
- // add the id field to the selection
234
- fragmentSelection.selections = [
235
- ...fragmentSelection.selections,
236
- {
237
- kind: graphql.Kind.FIELD,
238
- name: {
239
- kind: graphql.Kind.NAME,
240
- value: 'id',
241
- },
242
- },
243
- ]
244
- }
245
-
246
- // we at least want to create fragment to indicate inserts in lists
247
- return [
248
- // a fragment to insert items into this list
249
- {
250
- name: {
251
- value: config.listInsertFragment(name),
252
- kind: graphql.Kind.NAME,
253
- },
254
- kind: graphql.Kind.FRAGMENT_DEFINITION,
255
- // in order to insert an item into this list, it must
256
- // have the same selection as the field
257
- selectionSet: fragmentSelection,
258
- typeCondition: {
259
- kind: graphql.Kind.NAMED_TYPE,
260
- name: {
261
- kind: graphql.Kind.NAME,
262
- value: type.name,
263
- },
264
- },
265
- },
266
- // a fragment to insert or remove an item into the list
267
- {
268
- name: {
269
- value: config.listToggleFragment(name),
270
- kind: graphql.Kind.NAME,
271
- },
272
- kind: graphql.Kind.FRAGMENT_DEFINITION,
273
- // in order to insert an item into this list, it must
274
- // have the same selection as the field
275
- selectionSet: {
276
- ...fragmentSelection,
277
- selections: [
278
- ...fragmentSelection.selections,
279
- {
280
- kind: graphql.Kind.FIELD,
281
- name: {
282
- kind: graphql.Kind.NAME,
283
- value: 'id',
284
- },
285
- },
286
- ],
287
- },
288
- typeCondition: {
289
- kind: graphql.Kind.NAMED_TYPE,
290
- name: {
291
- kind: graphql.Kind.NAME,
292
- value: type.name,
293
- },
294
- },
295
- },
296
- // add a fragment to remove from the specific list
297
- {
298
- kind: graphql.Kind.FRAGMENT_DEFINITION,
299
- name: {
300
- value: config.listRemoveFragment(name),
301
- kind: graphql.Kind.NAME,
302
- },
303
- // deleting an entity just takes its id and the parent
304
- selectionSet: {
305
- kind: graphql.Kind.SELECTION_SET,
306
- selections: [
307
- {
308
- kind: graphql.Kind.FIELD,
309
- name: {
310
- kind: graphql.Kind.NAME,
311
- value: 'id',
312
- },
313
- },
314
- ],
315
- },
316
- typeCondition: {
317
- kind: graphql.Kind.NAMED_TYPE,
318
- name: {
319
- kind: graphql.Kind.NAME,
320
- value: type.name,
321
- },
322
- },
323
- },
324
- ]
325
- }
326
- ) as graphql.DefinitionNode[]
327
- ).concat(
328
- ...listTargets.map<graphql.DirectiveDefinitionNode>((typeName) => ({
329
- kind: graphql.Kind.DIRECTIVE_DEFINITION,
330
- name: {
331
- kind: graphql.Kind.NAME,
332
- value: config.listDeleteDirective(typeName),
333
- },
334
- locations: [
335
- // the delete directive must be applied to a field in the response
336
- // corresponding to the id
337
- {
338
- kind: graphql.Kind.NAME,
339
- value: 'FIELD',
340
- },
341
- ],
342
- repeatable: true,
343
- }))
344
- ),
345
- }
346
-
347
- config.newSchema +=
348
- '\n' +
349
- generatedDoc.definitions
350
- .filter((c) => c.kind !== 'FragmentDefinition')
351
- .map(graphql.print)
352
- .join('\n\n')
353
- config.newDocuments +=
354
- '\n' +
355
- generatedDoc.definitions
356
- .filter((c) => c.kind === 'FragmentDefinition')
357
- .map(graphql.print)
358
- .join('\n\n')
359
-
360
- documents.push({
361
- name: 'generated::lists',
362
- kind: ArtifactKind.Fragment,
363
- generateArtifact: false,
364
- generateStore: false,
365
- document: generatedDoc,
366
- originalDocument: generatedDoc,
367
- filename: 'generated::lists',
368
- originalString: '',
369
- })
370
- }
371
-
372
- // a field is considered a connection if it has one of the required connection arguments
373
- // as well as an edges > node selection
374
- export function connectionSelection(
375
- config: Config,
376
- field: graphql.GraphQLField<any, any>,
377
- type: graphql.GraphQLObjectType,
378
- selection: graphql.SelectionSetNode | undefined
379
- ): {
380
- selection: graphql.SelectionSetNode | undefined
381
- type: graphql.GraphQLObjectType
382
- connection: boolean
383
- error: string | null
384
- } {
385
- // make sure the field has the fields for either forward or backwards pagination
386
- const fieldArgs = field.args.reduce<Record<string, string>>(
387
- (args, arg) => ({
388
- ...args,
389
- [arg.name]: unwrapType(config, arg.type).type.name,
390
- }),
391
- {}
392
- )
393
-
394
- // if the field has an argument for limit, we're good to go
395
- if (fieldArgs['limit']) {
396
- return { selection, type, connection: false, error: null }
397
- }
398
-
399
- const forwardPagination =
400
- fieldArgs['first'] === 'Int' && ['Cursor', 'String'].includes(fieldArgs['after'])
401
- const backwardsPagination =
402
- fieldArgs['last'] === 'Int' && ['Cursor', 'String'].includes(fieldArgs['before'])
403
- if (!forwardPagination && !backwardsPagination) {
404
- return { selection, type, connection: false, error: missingPaginationArgMessage(config) }
405
- }
406
-
407
- // we need to make sure that there is an edges field
408
- const edgesField = selection?.selections.find(
409
- (selection) => selection.kind === 'Field' && selection.name.value === 'edges'
410
- ) as graphql.FieldNode
411
- if (!edgesField) {
412
- return { selection, type, connection: false, error: missingEdgeSelectionMessage(config) }
413
- }
414
-
415
- const nodeSelection = edgesField.selectionSet?.selections.find(
416
- (selection) => selection.kind === 'Field' && selection.name.value === 'node'
417
- ) as graphql.FieldNode
418
- if (!nodeSelection.selectionSet) {
419
- return { selection, type, connection: false, error: missingNodeSelectionMessage(config) }
420
- }
421
-
422
- // now that we have the correct selection, we have to lookup node type
423
- // we need to make sure that there is an edges field
424
- const edgeField = (
425
- unwrapType(config, field.type).type as graphql.GraphQLObjectType
426
- ).getFields()['edges']
427
- const { wrappers, type: edgeFieldType } = unwrapType(config, edgeField.type)
428
- // wrappers are in reverse order (last one is the top level, and there's a nullable entry)
429
- // so a nullable list of non-null elements looks like [NonNull, List, Nullable].
430
- // this means we just have to look at the second to last element and check if its a list
431
- const list = wrappers[wrappers.length - 2] === TypeWrapper.List
432
- if (!list) {
433
- return { selection, type, connection: false, error: edgeInvalidTypeMessage(config) }
434
- }
435
-
436
- const nodeField = (edgeFieldType as graphql.GraphQLObjectType).getFields()['node']
437
- if (!nodeField) {
438
- return { selection, type, connection: false, error: nodeNotDefinedMessage(config) }
439
- }
440
-
441
- return {
442
- selection: nodeSelection.selectionSet,
443
- type: unwrapType(config, nodeField.type).type as graphql.GraphQLObjectType,
444
- connection: true,
445
- error: null,
446
- }
447
- }
448
-
449
- const missingPaginationArgMessage = (
450
- config: Config
451
- ) => `Looks like you are trying to use the ${logGreen(
452
- `@${config.paginateDirective}`
453
- )} directive on a field but have not provided a ${logYellow('first')}, ${logYellow(
454
- 'last'
455
- )}, or ${logYellow('limit')} argument. Please add one and try again.
456
- For more information, visit this link: ${siteURL}/guides/pagination`
457
-
458
- const missingEdgeSelectionMessage = (
459
- config: Config
460
- ) => `Looks like you are trying to use the ${logGreen(
461
- `@${config.paginateDirective}`
462
- )} directive on a field but your selection does not contain an ${logYellow(
463
- 'edges'
464
- )} field. Please add one and try again.
465
- For more information, visit this link: ${siteURL}/guides/pagination`
466
-
467
- const missingNodeSelectionMessage = (
468
- config: Config
469
- ) => `Looks like you are trying to use the ${logGreen(
470
- `@${config.paginateDirective}`
471
- )} directive on a field but your selection does not contain a ${logYellow(
472
- 'node'
473
- )} field. Please add one and try again.
474
- For more information, visit this link: ${siteURL}/guides/pagination`
475
-
476
- const edgeInvalidTypeMessage = (config: Config) => `Looks like you are trying to use the ${logGreen(
477
- `@${config.paginateDirective}`
478
- )} directive on a field but your field does not conform to the connection spec: your edges field seems strange.
479
- For more information, visit this link: ${siteURL}/guides/pagination`
480
-
481
- const nodeNotDefinedMessage = (config: Config) => `Looks like you are trying to use the ${logGreen(
482
- `@${config.paginateDirective}`
483
- )} directive on a field but your field does not conform to the connection spec: your edge type does not have node as a field.
484
- For more information, visit this link: ${siteURL}/guides/pagination`