houdini 0.17.9 → 0.17.11
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/README.md +33 -0
- package/build/cmd-cjs/index.js +2 -2
- package/build/cmd-esm/index.js +2 -2
- package/package.json +16 -1
- package/.turbo/turbo-compile.log +0 -5
- package/.turbo/turbo-typedefs.log +0 -5
- package/CHANGELOG.md +0 -377
- package/src/cmd/generate.ts +0 -54
- package/src/cmd/index.ts +0 -60
- package/src/cmd/init.ts +0 -637
- package/src/cmd/pullSchema.ts +0 -40
- package/src/codegen/generators/artifacts/artifacts.test.ts +0 -3246
- package/src/codegen/generators/artifacts/fieldKey.ts +0 -60
- package/src/codegen/generators/artifacts/index.ts +0 -330
- package/src/codegen/generators/artifacts/indexFile.ts +0 -24
- package/src/codegen/generators/artifacts/inputs.ts +0 -81
- package/src/codegen/generators/artifacts/operations.ts +0 -281
- package/src/codegen/generators/artifacts/pagination.test.ts +0 -664
- package/src/codegen/generators/artifacts/policy.test.ts +0 -298
- package/src/codegen/generators/artifacts/selection.ts +0 -208
- package/src/codegen/generators/artifacts/utils.test.ts +0 -118
- package/src/codegen/generators/artifacts/utils.ts +0 -108
- package/src/codegen/generators/definitions/enums.test.ts +0 -61
- package/src/codegen/generators/definitions/enums.ts +0 -68
- package/src/codegen/generators/definitions/index.ts +0 -11
- package/src/codegen/generators/definitions/schema.test.ts +0 -236
- package/src/codegen/generators/index.ts +0 -6
- package/src/codegen/generators/indexFile/index.ts +0 -63
- package/src/codegen/generators/indexFile/indexFile.test.ts +0 -72
- package/src/codegen/generators/persistedQueries/index.ts +0 -55
- package/src/codegen/generators/persistedQueries/persistedQuery.test.ts +0 -26
- package/src/codegen/generators/runtime/index.test.ts +0 -74
- package/src/codegen/generators/runtime/index.ts +0 -64
- package/src/codegen/generators/runtime/runtime.test.ts +0 -25
- package/src/codegen/generators/typescript/addReferencedInputTypes.ts +0 -77
- package/src/codegen/generators/typescript/index.ts +0 -412
- package/src/codegen/generators/typescript/inlineType.ts +0 -409
- package/src/codegen/generators/typescript/typeReference.ts +0 -44
- package/src/codegen/generators/typescript/types.ts +0 -81
- package/src/codegen/generators/typescript/typescript.test.ts +0 -1434
- package/src/codegen/index.ts +0 -406
- package/src/codegen/transforms/addID.test.ts +0 -93
- package/src/codegen/transforms/addID.ts +0 -86
- package/src/codegen/transforms/composeQueries.test.ts +0 -50
- package/src/codegen/transforms/composeQueries.ts +0 -154
- package/src/codegen/transforms/fragmentVariables.test.ts +0 -636
- package/src/codegen/transforms/fragmentVariables.ts +0 -417
- package/src/codegen/transforms/index.ts +0 -7
- package/src/codegen/transforms/list.ts +0 -484
- package/src/codegen/transforms/lists.test.ts +0 -530
- package/src/codegen/transforms/paginate.test.ts +0 -1528
- package/src/codegen/transforms/paginate.ts +0 -770
- package/src/codegen/transforms/schema.test.ts +0 -136
- package/src/codegen/transforms/schema.ts +0 -109
- package/src/codegen/transforms/typename.test.ts +0 -125
- package/src/codegen/transforms/typename.ts +0 -55
- package/src/codegen/utils/commonjs.ts +0 -26
- package/src/codegen/utils/flattenSelections.ts +0 -179
- package/src/codegen/utils/graphql.test.ts +0 -35
- package/src/codegen/utils/graphql.ts +0 -79
- package/src/codegen/utils/index.ts +0 -5
- package/src/codegen/utils/moduleExport.ts +0 -27
- package/src/codegen/utils/murmur.ts +0 -79
- package/src/codegen/validators/index.ts +0 -4
- package/src/codegen/validators/noIDAlias.test.ts +0 -71
- package/src/codegen/validators/noIDAlias.ts +0 -39
- package/src/codegen/validators/plugins.ts +0 -25
- package/src/codegen/validators/typeCheck.test.ts +0 -960
- package/src/codegen/validators/typeCheck.ts +0 -1086
- package/src/codegen/validators/uniqueNames.test.ts +0 -59
- package/src/codegen/validators/uniqueNames.ts +0 -39
- package/src/lib/cleanupFiles.ts +0 -20
- package/src/lib/config.test.ts +0 -13
- package/src/lib/config.ts +0 -954
- package/src/lib/constants.ts +0 -11
- package/src/lib/error.ts +0 -24
- package/src/lib/fs.ts +0 -285
- package/src/lib/graphql.test.ts +0 -211
- package/src/lib/graphql.ts +0 -200
- package/src/lib/imports.ts +0 -82
- package/src/lib/index.ts +0 -17
- package/src/lib/introspection.ts +0 -39
- package/src/lib/parse.test.ts +0 -75
- package/src/lib/parse.ts +0 -23
- package/src/lib/path.ts +0 -49
- package/src/lib/pipeline.ts +0 -17
- package/src/lib/types.ts +0 -34
- package/src/lib/walk.ts +0 -104
- package/src/runtime/cache/cache.ts +0 -1026
- package/src/runtime/cache/gc.ts +0 -56
- package/src/runtime/cache/index.ts +0 -3
- package/src/runtime/cache/lists.ts +0 -516
- package/src/runtime/cache/storage.ts +0 -574
- package/src/runtime/cache/stuff.ts +0 -77
- package/src/runtime/cache/subscription.ts +0 -329
- package/src/runtime/cache/tests/availability.test.ts +0 -408
- package/src/runtime/cache/tests/gc.test.ts +0 -319
- package/src/runtime/cache/tests/keys.test.ts +0 -36
- package/src/runtime/cache/tests/list.test.ts +0 -3854
- package/src/runtime/cache/tests/readwrite.test.ts +0 -1201
- package/src/runtime/cache/tests/scalars.test.ts +0 -218
- package/src/runtime/cache/tests/storage.test.ts +0 -426
- package/src/runtime/cache/tests/subscriptions.test.ts +0 -1757
- package/src/runtime/index.ts +0 -29
- package/src/runtime/lib/config.ts +0 -211
- package/src/runtime/lib/constants.ts +0 -17
- package/src/runtime/lib/deepEquals.ts +0 -32
- package/src/runtime/lib/errors.ts +0 -8
- package/src/runtime/lib/index.ts +0 -8
- package/src/runtime/lib/log.ts +0 -69
- package/src/runtime/lib/network.ts +0 -303
- package/src/runtime/lib/networkUtils.ts +0 -151
- package/src/runtime/lib/scalars.test.ts +0 -877
- package/src/runtime/lib/scalars.ts +0 -195
- package/src/runtime/lib/types.ts +0 -195
- package/src/test/index.ts +0 -294
- package/src/vite/ast.ts +0 -107
- package/src/vite/houdini.ts +0 -113
- package/src/vite/imports.ts +0 -129
- package/src/vite/index.ts +0 -55
- package/src/vite/schema.ts +0 -80
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import * as graphql from 'graphql'
|
|
2
|
-
|
|
3
|
-
import { Config } from '../../../lib'
|
|
4
|
-
|
|
5
|
-
// we need to generate a static key that we can use to index this field in the cache.
|
|
6
|
-
// this needs to be a unique hash driven by the field's attribute and arguments
|
|
7
|
-
// returns the key for a specific field
|
|
8
|
-
export default function fieldKey(config: Config, field: graphql.FieldNode): string {
|
|
9
|
-
// we're going to hash a field by creating a json object and adding it
|
|
10
|
-
// to the attribute name
|
|
11
|
-
const attributeName = field.alias?.value || field.name.value
|
|
12
|
-
|
|
13
|
-
// field might not have a location so print and re-parse before we look at serialized values
|
|
14
|
-
const printed = graphql.print(field)
|
|
15
|
-
const secondParse = (
|
|
16
|
-
graphql.parse(`{${printed}}`).definitions[0] as graphql.OperationDefinitionNode
|
|
17
|
-
).selectionSet.selections[0] as graphql.FieldNode
|
|
18
|
-
|
|
19
|
-
// if the field is paginated, we need to strip away any args
|
|
20
|
-
const paginated = !!field.directives?.find(
|
|
21
|
-
(directive) => directive.name.value === config.paginateDirective
|
|
22
|
-
)
|
|
23
|
-
const paginationArgs = ['first', 'after', 'last', 'before', 'limit', 'offset']
|
|
24
|
-
|
|
25
|
-
const argObj = (secondParse.arguments || []).reduce<{ [key: string]: string }>((acc, arg) => {
|
|
26
|
-
// the query already contains a serialized version of the argument so just pull it out of the
|
|
27
|
-
// document string
|
|
28
|
-
const start = arg.value.loc?.start
|
|
29
|
-
const end = arg.value.loc?.end
|
|
30
|
-
|
|
31
|
-
// if the field is paginated, ignore the pagination args in the key
|
|
32
|
-
if (paginated && paginationArgs.includes(arg.name.value)) {
|
|
33
|
-
return acc
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// if the argument is not in the query, life doesn't make sense
|
|
37
|
-
if (!start || !end) {
|
|
38
|
-
return acc
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
...acc,
|
|
43
|
-
[arg.name.value]: printed.substring(start - 1, end - 1),
|
|
44
|
-
}
|
|
45
|
-
}, {})
|
|
46
|
-
|
|
47
|
-
let key =
|
|
48
|
-
Object.values(argObj).length > 0
|
|
49
|
-
? `${attributeName}(${Object.entries(argObj)
|
|
50
|
-
.map((entries) => entries.join(': '))
|
|
51
|
-
.join(', ')})`
|
|
52
|
-
: attributeName
|
|
53
|
-
|
|
54
|
-
// if the field is paginated, key it differently so other documents can ask for the non paginated value without conflict
|
|
55
|
-
if (paginated) {
|
|
56
|
-
key = key + '::paginated'
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return key
|
|
60
|
-
}
|
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
import * as graphql from 'graphql'
|
|
2
|
-
import * as recast from 'recast'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
Config,
|
|
6
|
-
getRootType,
|
|
7
|
-
hashDocument,
|
|
8
|
-
HoudiniError,
|
|
9
|
-
parentTypeFromAncestors,
|
|
10
|
-
fs,
|
|
11
|
-
CollectedGraphQLDocument,
|
|
12
|
-
cleanupFiles,
|
|
13
|
-
} from '../../../lib'
|
|
14
|
-
import { ArtifactKind } from '../../../lib'
|
|
15
|
-
import { moduleExport } from '../../utils'
|
|
16
|
-
import writeIndexFile from './indexFile'
|
|
17
|
-
import { inputObject } from './inputs'
|
|
18
|
-
import { operationsByPath, FilterMap } from './operations'
|
|
19
|
-
import selection from './selection'
|
|
20
|
-
import { serializeValue } from './utils'
|
|
21
|
-
|
|
22
|
-
const AST = recast.types.builders
|
|
23
|
-
|
|
24
|
-
// the artifact generator creates files in the runtime directory for each
|
|
25
|
-
// document containing meta data that the preprocessor might use
|
|
26
|
-
export default function artifactGenerator(stats: {
|
|
27
|
-
total: string[]
|
|
28
|
-
new: string[]
|
|
29
|
-
changed: string[]
|
|
30
|
-
deleted: string[]
|
|
31
|
-
}) {
|
|
32
|
-
return async function (config: Config, docs: CollectedGraphQLDocument[]) {
|
|
33
|
-
// put together the type information for the filter for every list
|
|
34
|
-
const filterTypes: FilterMap = {}
|
|
35
|
-
|
|
36
|
-
for (const doc of docs) {
|
|
37
|
-
graphql.visit(doc.document, {
|
|
38
|
-
// look for any field marked with a list
|
|
39
|
-
Directive(node, _, __, ___, ancestors) {
|
|
40
|
-
// we only care about lists
|
|
41
|
-
if (node.name.value !== config.listDirective) {
|
|
42
|
-
return
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// get the name of the list
|
|
46
|
-
const nameArg = node.arguments?.find(
|
|
47
|
-
(arg) => arg.name.value === config.listNameArg
|
|
48
|
-
)
|
|
49
|
-
if (!nameArg || nameArg.value.kind !== 'StringValue') {
|
|
50
|
-
throw new HoudiniError({
|
|
51
|
-
filepath: doc.filename,
|
|
52
|
-
message: 'could not find name arg in list directive',
|
|
53
|
-
})
|
|
54
|
-
}
|
|
55
|
-
const listName = nameArg.value.value
|
|
56
|
-
|
|
57
|
-
// look up the actual field in the ancestor list so we can get type info
|
|
58
|
-
let field = ancestors[ancestors.length - 1] as graphql.FieldNode
|
|
59
|
-
let i = 1
|
|
60
|
-
while (Array.isArray(field)) {
|
|
61
|
-
i++
|
|
62
|
-
field = ancestors[ancestors.length - i] as graphql.FieldNode
|
|
63
|
-
}
|
|
64
|
-
if (field.kind !== 'Field') {
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// look up the parent's type so we can ask about the field marked as a list
|
|
69
|
-
const parentType = parentTypeFromAncestors(config.schema, doc.filename, [
|
|
70
|
-
...ancestors.slice(0, -1),
|
|
71
|
-
]) as graphql.GraphQLObjectType
|
|
72
|
-
const parentField = parentType.getFields()[field.name.value]
|
|
73
|
-
if (!parentField) {
|
|
74
|
-
throw new HoudiniError({
|
|
75
|
-
filepath: doc.filename,
|
|
76
|
-
message: 'Could not find field information when computing filters',
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
const fieldType = getRootType(parentField.type).toString()
|
|
80
|
-
|
|
81
|
-
// look at every arg on the list to figure out the valid filters
|
|
82
|
-
filterTypes[listName] = parentField.args.reduce((prev, arg) => {
|
|
83
|
-
return {
|
|
84
|
-
...prev,
|
|
85
|
-
[arg.name]: getRootType(arg.type).toString(),
|
|
86
|
-
}
|
|
87
|
-
}, {})
|
|
88
|
-
|
|
89
|
-
// the delete directive is an interesting one since there isn't a specific
|
|
90
|
-
// list. we need to use something that points to deleting an instance of
|
|
91
|
-
// the type as a key
|
|
92
|
-
filterTypes[`${fieldType}_delete`] = {
|
|
93
|
-
...filterTypes[`${fieldType}_delete`],
|
|
94
|
-
// every field with the list type adds to the delete filters
|
|
95
|
-
...filterTypes[listName],
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const listOfArtifacts: string[] = []
|
|
102
|
-
|
|
103
|
-
// we have everything we need to generate the artifacts
|
|
104
|
-
await Promise.all(
|
|
105
|
-
[
|
|
106
|
-
// generate the index file
|
|
107
|
-
writeIndexFile(config, docs),
|
|
108
|
-
].concat(
|
|
109
|
-
// and an artifact for every document
|
|
110
|
-
docs.map(async (doc) => {
|
|
111
|
-
// pull out the info we need from the collected doc
|
|
112
|
-
const { document, name, generateArtifact } = doc
|
|
113
|
-
|
|
114
|
-
// if the document is generated, don't write it to disk - it's use is to provide definitions
|
|
115
|
-
// for the other transforms
|
|
116
|
-
if (!generateArtifact) {
|
|
117
|
-
return
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// before we can print the document, we need to strip:
|
|
121
|
-
// 1. all references to internal directives
|
|
122
|
-
// 2. all variables only used by internal directives
|
|
123
|
-
const usedVariableNames = new Set<string>()
|
|
124
|
-
let documentWithoutInternalDirectives = graphql.visit(document, {
|
|
125
|
-
Directive(node) {
|
|
126
|
-
// if the directive is one of the internal ones, remove it
|
|
127
|
-
if (config.isInternalDirective(node)) {
|
|
128
|
-
return null
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
Variable(node, _key, parent) {
|
|
133
|
-
const variableIsBeingDefined =
|
|
134
|
-
parent &&
|
|
135
|
-
!(parent instanceof Array) &&
|
|
136
|
-
parent.kind === 'VariableDefinition'
|
|
137
|
-
|
|
138
|
-
if (!variableIsBeingDefined) {
|
|
139
|
-
usedVariableNames.add(node.name.value)
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
})
|
|
143
|
-
let documentWithoutExtraVariables = graphql.visit(
|
|
144
|
-
documentWithoutInternalDirectives,
|
|
145
|
-
{
|
|
146
|
-
VariableDefinition(variableDefinitionNode) {
|
|
147
|
-
const name = variableDefinitionNode.variable.name.value
|
|
148
|
-
|
|
149
|
-
if (!usedVariableNames.has(name)) {
|
|
150
|
-
return null
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
}
|
|
154
|
-
)
|
|
155
|
-
let rawString = graphql.print(documentWithoutExtraVariables)
|
|
156
|
-
|
|
157
|
-
// figure out the document kind
|
|
158
|
-
let docKind = doc.kind
|
|
159
|
-
|
|
160
|
-
// look for the operation
|
|
161
|
-
const operations = document.definitions.filter(
|
|
162
|
-
({ kind }) => kind === graphql.Kind.OPERATION_DEFINITION
|
|
163
|
-
) as graphql.OperationDefinitionNode[]
|
|
164
|
-
// there are no operations, so its a fragment
|
|
165
|
-
const fragments = document.definitions.filter(
|
|
166
|
-
({ kind }) => kind === graphql.Kind.FRAGMENT_DEFINITION
|
|
167
|
-
) as graphql.FragmentDefinitionNode[]
|
|
168
|
-
|
|
169
|
-
let rootType: string | undefined = ''
|
|
170
|
-
let selectionSet: graphql.SelectionSetNode
|
|
171
|
-
|
|
172
|
-
// if we are generating the artifact for an operation
|
|
173
|
-
if (docKind !== ArtifactKind.Fragment) {
|
|
174
|
-
// find the operation
|
|
175
|
-
const operation = operations[0]
|
|
176
|
-
|
|
177
|
-
if (operation.operation === 'query') {
|
|
178
|
-
rootType = config.schema.getQueryType()?.name
|
|
179
|
-
} else if (operation.operation === 'mutation') {
|
|
180
|
-
rootType = config.schema.getMutationType()?.name
|
|
181
|
-
} else if (operation.operation === 'subscription') {
|
|
182
|
-
rootType = config.schema.getSubscriptionType()?.name
|
|
183
|
-
}
|
|
184
|
-
if (!rootType) {
|
|
185
|
-
throw new HoudiniError({
|
|
186
|
-
filepath: doc.filename,
|
|
187
|
-
message:
|
|
188
|
-
'could not find root type for operation: ' +
|
|
189
|
-
operation.operation +
|
|
190
|
-
'. Maybe you need to re-run the introspection query?',
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// use this selection set
|
|
195
|
-
selectionSet = operation.selectionSet
|
|
196
|
-
}
|
|
197
|
-
// we are looking at a fragment so use its selection set and type for the subscribe index
|
|
198
|
-
else {
|
|
199
|
-
// there are a lot of fragments added to a document. The fragment we care about
|
|
200
|
-
// is the one with the matching name
|
|
201
|
-
const matchingFragment = fragments.find(
|
|
202
|
-
(fragment) => fragment.name.value === name
|
|
203
|
-
)
|
|
204
|
-
if (!matchingFragment) {
|
|
205
|
-
throw new HoudiniError({
|
|
206
|
-
filepath: doc.filename,
|
|
207
|
-
message: `Fragment "${name}" doesn't exist in its own document?!`,
|
|
208
|
-
})
|
|
209
|
-
}
|
|
210
|
-
rootType = matchingFragment.typeCondition.name.value
|
|
211
|
-
selectionSet = matchingFragment.selectionSet
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// if there are inputs to the operation
|
|
215
|
-
const inputs = operations[0]?.variableDefinitions
|
|
216
|
-
|
|
217
|
-
// generate a hash of the document that we can use to detect changes
|
|
218
|
-
// start building up the artifact
|
|
219
|
-
const artifact: Record<string, any> = {
|
|
220
|
-
name,
|
|
221
|
-
kind: docKind,
|
|
222
|
-
hash: hashDocument(rawString),
|
|
223
|
-
refetch: doc.refetch,
|
|
224
|
-
raw: rawString,
|
|
225
|
-
rootType,
|
|
226
|
-
selection: selection({
|
|
227
|
-
config,
|
|
228
|
-
filepath: doc.filename,
|
|
229
|
-
rootType,
|
|
230
|
-
selections: selectionSet.selections,
|
|
231
|
-
operations: operationsByPath(
|
|
232
|
-
config,
|
|
233
|
-
doc.filename,
|
|
234
|
-
operations[0],
|
|
235
|
-
filterTypes
|
|
236
|
-
),
|
|
237
|
-
// do not include used fragments if we are rendering the selection
|
|
238
|
-
// for a fragment document
|
|
239
|
-
includeFragments: docKind !== 'HoudiniFragment',
|
|
240
|
-
document: doc,
|
|
241
|
-
}),
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// if the document has inputs describe their types in the artifact so we can
|
|
245
|
-
// marshal and unmarshal scalars
|
|
246
|
-
if (inputs && inputs.length > 0) {
|
|
247
|
-
artifact.input = inputObject(config, inputs)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// add the cache policy to query documents
|
|
251
|
-
if (docKind === 'HoudiniQuery') {
|
|
252
|
-
const cacheDirective = operations[0].directives?.find(
|
|
253
|
-
(directive) => directive.name.value === config.cacheDirective
|
|
254
|
-
)
|
|
255
|
-
if (cacheDirective) {
|
|
256
|
-
// look for arguments
|
|
257
|
-
const args: { [key: string]: graphql.ArgumentNode } =
|
|
258
|
-
cacheDirective.arguments?.reduce(
|
|
259
|
-
(acc, arg) => ({
|
|
260
|
-
...acc,
|
|
261
|
-
[arg.name.value]: arg,
|
|
262
|
-
}),
|
|
263
|
-
{}
|
|
264
|
-
) || {}
|
|
265
|
-
|
|
266
|
-
const policy = args[config.cachePolicyArg]
|
|
267
|
-
if (policy && policy.value.kind === 'EnumValue') {
|
|
268
|
-
artifact.policy = policy.value.value
|
|
269
|
-
} else {
|
|
270
|
-
artifact.policy = config.defaultCachePolicy
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// if the user opted-in for partial data
|
|
274
|
-
const partial = args[config.cachePartialArg]
|
|
275
|
-
if (partial && partial.value.kind === 'BooleanValue') {
|
|
276
|
-
artifact.partial = partial.value.value
|
|
277
|
-
} else {
|
|
278
|
-
artifact.partial = config.defaultPartial
|
|
279
|
-
}
|
|
280
|
-
} else {
|
|
281
|
-
artifact.policy = config.defaultCachePolicy
|
|
282
|
-
artifact.partial = config.defaultPartial
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// the artifact should be the default export of the file
|
|
287
|
-
const file = AST.program([
|
|
288
|
-
moduleExport(config, 'default', serializeValue(artifact)),
|
|
289
|
-
AST.expressionStatement(
|
|
290
|
-
AST.stringLiteral(`HoudiniHash=${hashDocument(doc.originalString)}`)
|
|
291
|
-
),
|
|
292
|
-
])
|
|
293
|
-
|
|
294
|
-
const artifactPath = config.artifactPath(document)
|
|
295
|
-
|
|
296
|
-
// don't count the document unless it's user-facing (ie, generates a store)
|
|
297
|
-
const countDocument = doc.generateStore
|
|
298
|
-
|
|
299
|
-
// check if the file exists (indicating a new document)
|
|
300
|
-
let existingArtifact = await fs.readFile(artifactPath)
|
|
301
|
-
if (existingArtifact === null) {
|
|
302
|
-
if (countDocument) {
|
|
303
|
-
stats.new.push(artifact.name)
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// write the result to the artifact path we're configured to write to
|
|
308
|
-
await fs.writeFile(artifactPath, recast.print(file).code)
|
|
309
|
-
listOfArtifacts.push(config.documentName(document))
|
|
310
|
-
|
|
311
|
-
if (!countDocument) {
|
|
312
|
-
return
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// check if the artifact exists
|
|
316
|
-
const match = existingArtifact && existingArtifact.match(/"HoudiniHash=(\w+)"/)
|
|
317
|
-
if (match && match[1] !== hashDocument(doc.originalString)) {
|
|
318
|
-
stats.changed.push(artifact.name)
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// regardless of whether it was changed or not, we need to track the total list of artifacts
|
|
322
|
-
stats.total.push(artifact.name)
|
|
323
|
-
})
|
|
324
|
-
)
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
// cleanup files that are no more necessary!
|
|
328
|
-
stats.deleted = await cleanupFiles(config.artifactDirectory, listOfArtifacts)
|
|
329
|
-
}
|
|
330
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Config, fs, CollectedGraphQLDocument, path } from '../../../lib'
|
|
2
|
-
import { cjsIndexFilePreamble, exportDefaultFrom } from '../../utils'
|
|
3
|
-
|
|
4
|
-
export default async function writeIndexFile(config: Config, docs: CollectedGraphQLDocument[]) {
|
|
5
|
-
const docsToGenerate = docs
|
|
6
|
-
.filter((doc) => doc.generateArtifact)
|
|
7
|
-
.sort((a, b) => a.name.localeCompare(b.name))
|
|
8
|
-
|
|
9
|
-
// we want to export every artifact from the index file.
|
|
10
|
-
let body =
|
|
11
|
-
config.module === 'esm'
|
|
12
|
-
? docsToGenerate.reduce(
|
|
13
|
-
(content, doc) =>
|
|
14
|
-
content + `\n export { default as ${doc.name}} from './${doc.name}'`,
|
|
15
|
-
''
|
|
16
|
-
)
|
|
17
|
-
: docsToGenerate.reduce(
|
|
18
|
-
(content, doc) => content + `\n${exportDefaultFrom(`./${doc.name}`, doc.name)}`,
|
|
19
|
-
cjsIndexFilePreamble
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
// write the result to the artifact path we're configured to write to
|
|
23
|
-
await fs.writeFile(path.join(config.artifactDirectory, 'index.js'), body)
|
|
24
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import * as graphql from 'graphql'
|
|
2
|
-
import * as recast from 'recast'
|
|
3
|
-
|
|
4
|
-
import { Config } from '../../../lib/config'
|
|
5
|
-
import { InputObject } from '../../../runtime/lib/types'
|
|
6
|
-
import { unwrapType } from '../../utils'
|
|
7
|
-
|
|
8
|
-
const AST = recast.types.builders
|
|
9
|
-
|
|
10
|
-
export function inputObject(
|
|
11
|
-
config: Config,
|
|
12
|
-
inputs: readonly graphql.VariableDefinitionNode[]
|
|
13
|
-
): InputObject {
|
|
14
|
-
// make sure we don't define the same input type
|
|
15
|
-
const visitedTypes = new Set<string>()
|
|
16
|
-
|
|
17
|
-
// inputs can be recursive so we can't flatten the input type into a single object
|
|
18
|
-
const inputObj: InputObject = {
|
|
19
|
-
fields: inputs.reduce((fields, input) => {
|
|
20
|
-
// find the inner type
|
|
21
|
-
const { type } = unwrapType(config, input.type)
|
|
22
|
-
|
|
23
|
-
// embed the type in the input
|
|
24
|
-
return {
|
|
25
|
-
...fields,
|
|
26
|
-
[input.variable.name.value]: type.name,
|
|
27
|
-
}
|
|
28
|
-
}, {}),
|
|
29
|
-
types: {},
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// walk through every type referenced and add it to the list
|
|
33
|
-
for (const input of inputs) {
|
|
34
|
-
walkInputs(config, visitedTypes, inputObj, input.type)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return inputObj
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function walkInputs(
|
|
41
|
-
config: Config,
|
|
42
|
-
visitedTypes: Set<string>,
|
|
43
|
-
inputObj: InputObject,
|
|
44
|
-
rootType: graphql.TypeNode | graphql.GraphQLNamedType
|
|
45
|
-
) {
|
|
46
|
-
// find the core type
|
|
47
|
-
const { type } = unwrapType(config, rootType)
|
|
48
|
-
|
|
49
|
-
// if we've seen this type already
|
|
50
|
-
if (visitedTypes.has(type.name)) {
|
|
51
|
-
// don't do anything else
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// if this is a scalar or enum then we don't need to add anything to the type object
|
|
56
|
-
if (graphql.isEnumType(type) || graphql.isScalarType(type)) {
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
if (graphql.isUnionType(type)) {
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// we haven't seen this type before and are about to generate the type
|
|
64
|
-
visitedTypes.add(type.name)
|
|
65
|
-
|
|
66
|
-
// generate the entry for the type
|
|
67
|
-
inputObj!.types[type.name] = Object.values(type.getFields()).reduce(
|
|
68
|
-
(typeFields, field: graphql.GraphQLInputField) => {
|
|
69
|
-
const { type: fieldType } = unwrapType(config, field.type)
|
|
70
|
-
|
|
71
|
-
// keep walking down
|
|
72
|
-
walkInputs(config, visitedTypes, inputObj, fieldType)
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
...typeFields,
|
|
76
|
-
[field.name]: fieldType.toString(),
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
|
-
{}
|
|
80
|
-
)
|
|
81
|
-
}
|