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
package/src/lib/graphql.ts
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import crypto from 'crypto'
|
|
2
|
-
import * as graphql from 'graphql'
|
|
3
|
-
|
|
4
|
-
import { HoudiniError } from './error'
|
|
5
|
-
import * as path from './path'
|
|
6
|
-
|
|
7
|
-
export function getRootType(type: graphql.GraphQLType): graphql.GraphQLType {
|
|
8
|
-
// if the type is non-null, unwrap and go again
|
|
9
|
-
if (graphql.isNonNullType(type)) {
|
|
10
|
-
return getRootType((type as graphql.GraphQLNonNull<any>).ofType)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// if the type is non-null, unwrap and go again
|
|
14
|
-
if (graphql.isListType(type)) {
|
|
15
|
-
return getRootType((type as graphql.GraphQLList<any>).ofType)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// we've unwrapped everything
|
|
19
|
-
return type
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function hashDocument(document: string | graphql.DocumentNode): string {
|
|
23
|
-
// if we were given an AST document, print it first
|
|
24
|
-
const docString = typeof document === 'string' ? document : graphql.print(document)
|
|
25
|
-
|
|
26
|
-
// hash the string
|
|
27
|
-
return crypto.createHash('sha256').update(docString).digest('hex')
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
type GraphQLParentType =
|
|
31
|
-
| graphql.GraphQLObjectType
|
|
32
|
-
| graphql.GraphQLInputObjectType
|
|
33
|
-
| graphql.GraphQLInterfaceType
|
|
34
|
-
|
|
35
|
-
export function parentTypeFromAncestors(
|
|
36
|
-
schema: graphql.GraphQLSchema,
|
|
37
|
-
filepath: string,
|
|
38
|
-
ancestors: readonly any[]
|
|
39
|
-
) {
|
|
40
|
-
const parents = [...ancestors] as (
|
|
41
|
-
| graphql.OperationDefinitionNode
|
|
42
|
-
| graphql.FragmentDefinitionNode
|
|
43
|
-
| graphql.SelectionNode
|
|
44
|
-
)[]
|
|
45
|
-
parents.reverse()
|
|
46
|
-
|
|
47
|
-
return walkAncestors(schema, filepath, parents)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function walkAncestors(
|
|
51
|
-
schema: graphql.GraphQLSchema,
|
|
52
|
-
filepath: string,
|
|
53
|
-
ancestors: (
|
|
54
|
-
| graphql.OperationDefinitionNode
|
|
55
|
-
| graphql.FragmentDefinitionNode
|
|
56
|
-
| graphql.SelectionNode
|
|
57
|
-
| graphql.SelectionSetNode
|
|
58
|
-
)[]
|
|
59
|
-
): GraphQLParentType {
|
|
60
|
-
// get the front node
|
|
61
|
-
let head = ancestors.shift()
|
|
62
|
-
// if it was a list, skip it
|
|
63
|
-
if (Array.isArray(head)) {
|
|
64
|
-
return walkAncestors(schema, filepath, ancestors)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (!head) {
|
|
68
|
-
throw new HoudiniError({ filepath, message: 'Could not figure out type of field' })
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// if we are at the top of the definition stack
|
|
72
|
-
if (head.kind === 'OperationDefinition') {
|
|
73
|
-
// grab the appropriate
|
|
74
|
-
const operationType = {
|
|
75
|
-
query: schema.getQueryType(),
|
|
76
|
-
mutation: schema.getMutationType(),
|
|
77
|
-
subscription: schema.getSubscriptionType(),
|
|
78
|
-
}[head.operation]
|
|
79
|
-
|
|
80
|
-
if (!operationType) {
|
|
81
|
-
throw new HoudiniError({ filepath, message: 'Could not find operation type' })
|
|
82
|
-
}
|
|
83
|
-
return operationType
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (head.kind === 'FragmentDefinition') {
|
|
87
|
-
// look up the type condition in the schema
|
|
88
|
-
const result = schema.getType(head.typeCondition.name.value) as GraphQLParentType
|
|
89
|
-
if (!result) {
|
|
90
|
-
throw new HoudiniError({
|
|
91
|
-
filepath,
|
|
92
|
-
message: `Could not find definition for ${head.typeCondition.name.value} in the schema`,
|
|
93
|
-
})
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// we're done here
|
|
97
|
-
return result
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// if we are looking at a fragment spread there is a serious problem
|
|
101
|
-
if (head.kind === 'FragmentSpread') {
|
|
102
|
-
throw new Error('How the hell did this happen?')
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// grab our parent type
|
|
106
|
-
const parent = walkAncestors(schema, filepath, ancestors)
|
|
107
|
-
|
|
108
|
-
// if we are looking at an inline fragment
|
|
109
|
-
if (head.kind === 'InlineFragment') {
|
|
110
|
-
// if there is no type condition, then our parents type is the answer
|
|
111
|
-
if (!head.typeCondition) {
|
|
112
|
-
return parent
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// look at the type condition to find the type
|
|
116
|
-
const wrapper = schema.getType(head.typeCondition.name.value) as GraphQLParentType
|
|
117
|
-
if (!wrapper) {
|
|
118
|
-
throw new HoudiniError({
|
|
119
|
-
filepath,
|
|
120
|
-
message: 'Could not find type with name: ' + head.typeCondition.name.value,
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return wrapper
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// we are looking at a selection select our type is our parent's type
|
|
128
|
-
if (head.kind === 'SelectionSet') {
|
|
129
|
-
return parent
|
|
130
|
-
}
|
|
131
|
-
// we are looking at a field so we can just access the field map of the parent type
|
|
132
|
-
const field = parent.getFields()[head.name.value]
|
|
133
|
-
if (!field) {
|
|
134
|
-
throw new HoudiniError({
|
|
135
|
-
filepath,
|
|
136
|
-
message: `Could not find definition of ${head.name.value} in ${parent.toString()}`,
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return getRootType(field.type) as GraphQLParentType
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export function definitionFromAncestors(ancestors: readonly any[]) {
|
|
144
|
-
// in order to look up field type information we have to start at the parent
|
|
145
|
-
// and work our way down
|
|
146
|
-
// note: the top-most parent is always gonna be a document so we ignore it
|
|
147
|
-
let parents = [...ancestors] as (
|
|
148
|
-
| graphql.FieldNode
|
|
149
|
-
| graphql.InlineFragmentNode
|
|
150
|
-
| graphql.FragmentDefinitionNode
|
|
151
|
-
| graphql.OperationDefinitionNode
|
|
152
|
-
| graphql.SelectionSetNode
|
|
153
|
-
)[]
|
|
154
|
-
parents.shift()
|
|
155
|
-
|
|
156
|
-
// the first meaningful parent is a definition of some kind
|
|
157
|
-
let definition = parents.shift() as
|
|
158
|
-
| graphql.FragmentDefinitionNode
|
|
159
|
-
| graphql.OperationDefinitionNode
|
|
160
|
-
while (Array.isArray(definition) && definition) {
|
|
161
|
-
// @ts-ignore
|
|
162
|
-
definition = parents.shift()
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return definition
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export function formatErrors(e: unknown, afterError?: (e: Error) => void) {
|
|
169
|
-
// we need an array of errors to loop through
|
|
170
|
-
const errors = (Array.isArray(e) ? e : [e]) as (Error & {
|
|
171
|
-
filepath?: string
|
|
172
|
-
description?: string
|
|
173
|
-
})[]
|
|
174
|
-
|
|
175
|
-
for (const error of errors) {
|
|
176
|
-
// if we have filepath, show that to the user
|
|
177
|
-
if ('filepath' in error && error.filepath) {
|
|
178
|
-
const relative = path.relative(process.cwd(), error.filepath)
|
|
179
|
-
console.error(`❌ Encountered error in ${relative}`)
|
|
180
|
-
if (error.message) {
|
|
181
|
-
console.error(error.message)
|
|
182
|
-
}
|
|
183
|
-
} else {
|
|
184
|
-
console.error(`❌ ${error.message}`)
|
|
185
|
-
if ('description' in error && error.description) {
|
|
186
|
-
console.error(`${error.description}`)
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
afterError?.(e as Error)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export function operation_requires_variables(operation: graphql.OperationDefinitionNode) {
|
|
194
|
-
return Boolean(
|
|
195
|
-
operation.variableDefinitions &&
|
|
196
|
-
operation.variableDefinitions?.find(
|
|
197
|
-
(defn) => defn.type.kind === 'NonNullType' && !defn.defaultValue
|
|
198
|
-
)
|
|
199
|
-
)
|
|
200
|
-
}
|
package/src/lib/imports.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import * as recast from 'recast'
|
|
2
|
-
|
|
3
|
-
import { Config } from './config'
|
|
4
|
-
|
|
5
|
-
const AST = recast.types.builders
|
|
6
|
-
|
|
7
|
-
type Statement = recast.types.namedTypes.Statement
|
|
8
|
-
type ImportDeclaration = recast.types.namedTypes.ImportDeclaration
|
|
9
|
-
|
|
10
|
-
export function ensureArtifactImport({
|
|
11
|
-
config,
|
|
12
|
-
artifact,
|
|
13
|
-
body,
|
|
14
|
-
local,
|
|
15
|
-
withExtension,
|
|
16
|
-
}: {
|
|
17
|
-
config: Config
|
|
18
|
-
artifact: { name: string }
|
|
19
|
-
body: Statement[]
|
|
20
|
-
local?: string
|
|
21
|
-
withExtension?: boolean
|
|
22
|
-
}) {
|
|
23
|
-
return ensureImports({
|
|
24
|
-
config,
|
|
25
|
-
body,
|
|
26
|
-
sourceModule: config.artifactImportPath(artifact.name) + (withExtension ? '.js' : ''),
|
|
27
|
-
import: local || `_${artifact.name}Artifact`,
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function ensureImports<_Count extends string[] | string>({
|
|
32
|
-
config,
|
|
33
|
-
body,
|
|
34
|
-
import: importID,
|
|
35
|
-
sourceModule,
|
|
36
|
-
importKind,
|
|
37
|
-
}: {
|
|
38
|
-
config: Config
|
|
39
|
-
body: Statement[]
|
|
40
|
-
import: _Count
|
|
41
|
-
sourceModule: string
|
|
42
|
-
importKind?: 'value' | 'type'
|
|
43
|
-
}): _Count {
|
|
44
|
-
const idList = Array.isArray(importID) ? importID : [importID]
|
|
45
|
-
|
|
46
|
-
// figure out the list of things to import
|
|
47
|
-
const toImport = idList.filter(
|
|
48
|
-
(identifier) =>
|
|
49
|
-
!body.find(
|
|
50
|
-
(statement) =>
|
|
51
|
-
statement.type === 'ImportDeclaration' &&
|
|
52
|
-
(statement as ImportDeclaration).specifiers!.find(
|
|
53
|
-
(importSpecifier) =>
|
|
54
|
-
(importSpecifier.type === 'ImportSpecifier' &&
|
|
55
|
-
importSpecifier.imported.type === 'Identifier' &&
|
|
56
|
-
importSpecifier.imported.name === identifier &&
|
|
57
|
-
importSpecifier.local!.name === identifier) ||
|
|
58
|
-
(importSpecifier.type === 'ImportDefaultSpecifier' &&
|
|
59
|
-
importSpecifier.local!.type === 'Identifier' &&
|
|
60
|
-
importSpecifier.local!.name === identifier)
|
|
61
|
-
)
|
|
62
|
-
)
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
// add the import if it doesn't exist, add it
|
|
66
|
-
if (toImport.length > 0) {
|
|
67
|
-
body.unshift({
|
|
68
|
-
type: 'ImportDeclaration',
|
|
69
|
-
// @ts-ignore
|
|
70
|
-
source: AST.stringLiteral(sourceModule),
|
|
71
|
-
// @ts-ignore
|
|
72
|
-
specifiers: toImport.map((identifier) =>
|
|
73
|
-
!Array.isArray(importID)
|
|
74
|
-
? AST.importDefaultSpecifier(AST.identifier(identifier))
|
|
75
|
-
: AST.importSpecifier(AST.identifier(identifier), AST.identifier(identifier))
|
|
76
|
-
),
|
|
77
|
-
importKind,
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return Array.isArray(importID) ? toImport : toImport[0]
|
|
82
|
-
}
|
package/src/lib/index.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export * from './pipeline'
|
|
2
|
-
export * from './config'
|
|
3
|
-
export * from './graphql'
|
|
4
|
-
export * from './types'
|
|
5
|
-
export * from './parse'
|
|
6
|
-
export * from './imports'
|
|
7
|
-
export * from './error'
|
|
8
|
-
export * from './types'
|
|
9
|
-
export * from './constants'
|
|
10
|
-
export * from './introspection'
|
|
11
|
-
export * from './cleanupFiles'
|
|
12
|
-
|
|
13
|
-
export * from './walk'
|
|
14
|
-
export type { EmbeddedGraphqlDocument } from './walk'
|
|
15
|
-
|
|
16
|
-
export * as fs from './fs'
|
|
17
|
-
export * as path from './path'
|
package/src/lib/introspection.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import * as graphql from 'graphql'
|
|
2
|
-
import fetch from 'node-fetch'
|
|
3
|
-
|
|
4
|
-
import * as fs from './fs'
|
|
5
|
-
|
|
6
|
-
export async function pullSchema(
|
|
7
|
-
url: string,
|
|
8
|
-
schemaPath: string,
|
|
9
|
-
headers?: Record<string, string>
|
|
10
|
-
): Promise<boolean> {
|
|
11
|
-
try {
|
|
12
|
-
// send the request
|
|
13
|
-
const resp = await fetch(url, {
|
|
14
|
-
method: 'POST',
|
|
15
|
-
body: JSON.stringify({
|
|
16
|
-
query: graphql.getIntrospectionQuery(),
|
|
17
|
-
}),
|
|
18
|
-
headers: { 'Content-Type': 'application/json', ...headers },
|
|
19
|
-
})
|
|
20
|
-
const content = await resp.text()
|
|
21
|
-
|
|
22
|
-
const jsonSchema = JSON.parse(content).data
|
|
23
|
-
const schema = graphql.buildClientSchema(jsonSchema)
|
|
24
|
-
|
|
25
|
-
// Check if the schemapath ends with .gql or .graphql - if so write the schema as string
|
|
26
|
-
// Otherwise write the json/introspection
|
|
27
|
-
if (schemaPath!.endsWith('gql') || schemaPath!.endsWith('graphql')) {
|
|
28
|
-
const schemaAsString = graphql.printSchema(graphql.lexicographicSortSchema(schema))
|
|
29
|
-
await fs.writeFile(schemaPath, schemaAsString)
|
|
30
|
-
} else {
|
|
31
|
-
await fs.writeFile(schemaPath, JSON.stringify(jsonSchema))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return true
|
|
35
|
-
} catch (e) {
|
|
36
|
-
console.warn(`⚠️ Couldn't pull your latest schema: ` + (e as Error).message)
|
|
37
|
-
}
|
|
38
|
-
return false
|
|
39
|
-
}
|
package/src/lib/parse.test.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { test, expect, describe } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { parseJSON } from './parse'
|
|
4
|
-
|
|
5
|
-
describe('parse', function () {
|
|
6
|
-
test('parseJSON without comments', async function () {
|
|
7
|
-
const original_file = `{
|
|
8
|
-
"extends": "./.svelte-kit/tsconfig.json",
|
|
9
|
-
"compilerOptions": {
|
|
10
|
-
"allowJs": true,
|
|
11
|
-
"checkJs": true,
|
|
12
|
-
"esModuleInterop": true,
|
|
13
|
-
"forceConsistentCasingInFileNames": true,
|
|
14
|
-
"resolveJsonModule": true,
|
|
15
|
-
"skipLibCheck": true,
|
|
16
|
-
"sourceMap": true,
|
|
17
|
-
"strict": true,
|
|
18
|
-
"noImplicitAny": true
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
`
|
|
22
|
-
|
|
23
|
-
const parsed = parseJSON(original_file)
|
|
24
|
-
expect(parsed).toMatchObject({
|
|
25
|
-
extends: './.svelte-kit/tsconfig.json',
|
|
26
|
-
compilerOptions: {
|
|
27
|
-
allowJs: true,
|
|
28
|
-
checkJs: true,
|
|
29
|
-
esModuleInterop: true,
|
|
30
|
-
forceConsistentCasingInFileNames: true,
|
|
31
|
-
resolveJsonModule: true,
|
|
32
|
-
skipLibCheck: true,
|
|
33
|
-
sourceMap: true,
|
|
34
|
-
strict: true,
|
|
35
|
-
noImplicitAny: true,
|
|
36
|
-
},
|
|
37
|
-
})
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
test('parseJSON with comments', async function () {
|
|
41
|
-
const original_file = `{
|
|
42
|
-
"extends": "./.svelte-kit/tsconfig.json",
|
|
43
|
-
"compilerOptions": {
|
|
44
|
-
"allowJs": true,
|
|
45
|
-
// this is a comment
|
|
46
|
-
"checkJs": true,
|
|
47
|
-
"esModuleInterop": true,
|
|
48
|
-
"forceConsistentCasingInFileNames": true,
|
|
49
|
-
"resolveJsonModule": true,
|
|
50
|
-
"skipLibCheck": true,
|
|
51
|
-
"sourceMap": true,
|
|
52
|
-
"strict": true,
|
|
53
|
-
"noImplicitAny": true
|
|
54
|
-
}
|
|
55
|
-
// this is another comment
|
|
56
|
-
}
|
|
57
|
-
`
|
|
58
|
-
|
|
59
|
-
const parsed = parseJSON(original_file)
|
|
60
|
-
expect(parsed).toMatchObject({
|
|
61
|
-
extends: './.svelte-kit/tsconfig.json',
|
|
62
|
-
compilerOptions: {
|
|
63
|
-
allowJs: true,
|
|
64
|
-
checkJs: true,
|
|
65
|
-
esModuleInterop: true,
|
|
66
|
-
forceConsistentCasingInFileNames: true,
|
|
67
|
-
resolveJsonModule: true,
|
|
68
|
-
skipLibCheck: true,
|
|
69
|
-
sourceMap: true,
|
|
70
|
-
strict: true,
|
|
71
|
-
noImplicitAny: true,
|
|
72
|
-
},
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
})
|
package/src/lib/parse.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { parse as parseJavascript } from '@babel/parser'
|
|
2
|
-
|
|
3
|
-
import type { Maybe, Script } from './types'
|
|
4
|
-
|
|
5
|
-
export type ParsedFile = Maybe<{ script: Script; start: number; end: number }>
|
|
6
|
-
|
|
7
|
-
export async function parseJS(str: string): Promise<ParsedFile> {
|
|
8
|
-
return {
|
|
9
|
-
start: 0,
|
|
10
|
-
// @ts-ignore
|
|
11
|
-
script: parseJavascript(str || '', {
|
|
12
|
-
plugins: ['typescript'],
|
|
13
|
-
sourceType: 'module',
|
|
14
|
-
}).program,
|
|
15
|
-
end: str.length,
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function parseJSON(str: string): any {
|
|
20
|
-
// remove all comments to be able to parse the file, and add stuff to it.
|
|
21
|
-
str = str.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => (g ? '' : m))
|
|
22
|
-
return JSON.parse(str)
|
|
23
|
-
}
|
package/src/lib/path.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import os from 'os'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
|
|
4
|
-
// this package is meant to enforce posix conventions whenever
|
|
5
|
-
// performing path-related tasks since in general we don't actually
|
|
6
|
-
// want to consider the windows conventions. Those situations that _do_
|
|
7
|
-
// care will have the necessary logic to turn the posix path into one
|
|
8
|
-
// thats appropriate for windows
|
|
9
|
-
|
|
10
|
-
// sep is always the posix one given ^
|
|
11
|
-
export const sep = '/'
|
|
12
|
-
|
|
13
|
-
export function resolve(...parts: string[]): string {
|
|
14
|
-
return posixify(path.resolve(...parts))
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function join(...parts: string[]): string {
|
|
18
|
-
return posixify(path.join(...parts))
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function extname(target: string): string {
|
|
22
|
-
return path.extname(target)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function relative(from: string, to: string): string {
|
|
26
|
-
return posixify(path.relative(from, to))
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function basename(target: string): string {
|
|
30
|
-
return path.basename(target)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function dirname(target: string): string {
|
|
34
|
-
return path.dirname(target)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function isAbsolute(target: string): boolean {
|
|
38
|
-
return path.isAbsolute(target)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function parse(target: string) {
|
|
42
|
-
return path.parse(target)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const posixify = (str: string) => str.replace(/\\/g, '/')
|
|
46
|
-
|
|
47
|
-
export function importPath(target: string): string {
|
|
48
|
-
return ['win32', 'win64'].includes(os.platform()) ? 'file:///' + target : target
|
|
49
|
-
}
|
package/src/lib/pipeline.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Config } from './config'
|
|
2
|
-
|
|
3
|
-
// transforms are functions that takes the collected documents. some will mutate
|
|
4
|
-
// the document definition, some check the definition for errors (undefined fields, etc)
|
|
5
|
-
export type Transform<_TransformType> =
|
|
6
|
-
| null
|
|
7
|
-
| ((config: Config, documents: _TransformType) => Promise<void>)
|
|
8
|
-
|
|
9
|
-
export async function runPipeline<_TransformType>(
|
|
10
|
-
config: Config,
|
|
11
|
-
pipeline: Transform<_TransformType>[],
|
|
12
|
-
target: _TransformType
|
|
13
|
-
) {
|
|
14
|
-
for (const transform of pipeline) {
|
|
15
|
-
await transform?.(config, target)
|
|
16
|
-
}
|
|
17
|
-
}
|
package/src/lib/types.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import graphql from 'graphql'
|
|
2
|
-
import * as recast from 'recast'
|
|
3
|
-
|
|
4
|
-
import { ArtifactKind, BaseCompiledDocument } from '../runtime/lib/types'
|
|
5
|
-
import type { Config } from './config'
|
|
6
|
-
|
|
7
|
-
type Program = recast.types.namedTypes.Program
|
|
8
|
-
|
|
9
|
-
export type Maybe<T> = T | null | undefined
|
|
10
|
-
|
|
11
|
-
export type Script = Program
|
|
12
|
-
|
|
13
|
-
export type TransformDocument = {
|
|
14
|
-
instance: Maybe<Script>
|
|
15
|
-
config: Config
|
|
16
|
-
dependencies: string[]
|
|
17
|
-
filename: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// the result of collecting documents from source code
|
|
21
|
-
export type CollectedGraphQLDocument = {
|
|
22
|
-
kind: ArtifactKind
|
|
23
|
-
filename: string
|
|
24
|
-
name: string
|
|
25
|
-
document: graphql.DocumentNode
|
|
26
|
-
originalDocument: graphql.DocumentNode
|
|
27
|
-
generateArtifact: boolean
|
|
28
|
-
generateStore: boolean
|
|
29
|
-
originalString: string
|
|
30
|
-
refetch?: BaseCompiledDocument['refetch']
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export * from '../runtime/lib/types'
|
|
34
|
-
export * from '../runtime/lib/config'
|
package/src/lib/walk.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import type { TaggedTemplateExpressionKind, IdentifierKind } from 'ast-types/gen/kinds'
|
|
2
|
-
import { asyncWalk, BaseNode } from 'estree-walker'
|
|
3
|
-
import * as graphql from 'graphql'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
CompiledDocumentKind,
|
|
7
|
-
CompiledFragmentKind,
|
|
8
|
-
CompiledMutationKind,
|
|
9
|
-
CompiledQueryKind,
|
|
10
|
-
CompiledSubscriptionKind,
|
|
11
|
-
} from '../runtime/lib/types'
|
|
12
|
-
import { Config } from './config'
|
|
13
|
-
import { Script } from './types'
|
|
14
|
-
|
|
15
|
-
export type EmbeddedGraphqlDocument = {
|
|
16
|
-
parsedDocument: graphql.DocumentNode
|
|
17
|
-
artifact: {
|
|
18
|
-
name: string
|
|
19
|
-
kind: CompiledDocumentKind
|
|
20
|
-
}
|
|
21
|
-
node: BaseNode & {
|
|
22
|
-
remove: () => void
|
|
23
|
-
replaceWith: (node: BaseNode) => void
|
|
24
|
-
}
|
|
25
|
-
tagContent: string
|
|
26
|
-
parent: BaseNode
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
type GraphqlTagWalker = {
|
|
30
|
-
where?: (tag: graphql.DocumentNode) => boolean
|
|
31
|
-
dependency?: (fp: string) => void
|
|
32
|
-
tag: (tag: EmbeddedGraphqlDocument) => void | Promise<void>
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// yield the tagged graphql documents contained within the provided AST
|
|
36
|
-
export async function find_graphql(
|
|
37
|
-
config: Config,
|
|
38
|
-
parsedScript: Script,
|
|
39
|
-
walker: GraphqlTagWalker
|
|
40
|
-
): Promise<void> {
|
|
41
|
-
await asyncWalk(parsedScript!, {
|
|
42
|
-
async enter(node, parent) {
|
|
43
|
-
// if we are looking at the graphql template tag
|
|
44
|
-
if (
|
|
45
|
-
node.type === 'TaggedTemplateExpression' &&
|
|
46
|
-
((node as TaggedTemplateExpressionKind).tag as IdentifierKind).name === 'graphql'
|
|
47
|
-
) {
|
|
48
|
-
const expr = node as TaggedTemplateExpressionKind
|
|
49
|
-
// we're going to replace the tag with something the runtime can use
|
|
50
|
-
|
|
51
|
-
// first, lets parse the tag contents to get the info we need
|
|
52
|
-
const tagContent = expr.quasi.quasis[0].value.raw
|
|
53
|
-
const parsedTag = graphql.parse(tagContent)
|
|
54
|
-
|
|
55
|
-
// if there is a predicate and the graphql tag does not satisfy it
|
|
56
|
-
if (walker.where && !walker.where(parsedTag)) {
|
|
57
|
-
// ignore the tag
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// pull out the name of the thing
|
|
62
|
-
const definition = config.extractDefinition(parsedTag) as
|
|
63
|
-
| graphql.OperationDefinitionNode
|
|
64
|
-
| graphql.FragmentDefinitionNode
|
|
65
|
-
const name = definition.name?.value
|
|
66
|
-
if (!name) {
|
|
67
|
-
throw new Error('Could not find definition name')
|
|
68
|
-
}
|
|
69
|
-
let kind: CompiledDocumentKind
|
|
70
|
-
if (definition.kind === 'FragmentDefinition') {
|
|
71
|
-
kind = CompiledFragmentKind
|
|
72
|
-
} else {
|
|
73
|
-
if (definition.operation === 'query') {
|
|
74
|
-
kind = CompiledQueryKind
|
|
75
|
-
} else if (definition.operation === 'mutation') {
|
|
76
|
-
kind = CompiledMutationKind
|
|
77
|
-
} else {
|
|
78
|
-
kind = CompiledSubscriptionKind
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// tell the walk there was a dependency
|
|
83
|
-
walker.dependency?.(config.artifactPath(parsedTag))
|
|
84
|
-
|
|
85
|
-
// invoker the walker's callback with the right context
|
|
86
|
-
await walker.tag({
|
|
87
|
-
parsedDocument: parsedTag,
|
|
88
|
-
node: {
|
|
89
|
-
...node,
|
|
90
|
-
...this,
|
|
91
|
-
remove: this.remove,
|
|
92
|
-
replaceWith: this.replace,
|
|
93
|
-
},
|
|
94
|
-
artifact: {
|
|
95
|
-
name,
|
|
96
|
-
kind,
|
|
97
|
-
},
|
|
98
|
-
parent,
|
|
99
|
-
tagContent,
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
})
|
|
104
|
-
}
|