@@ -24,6 +24,105 @@ InternalConsole.registerConsole(internalConsole)
24
24
*/
25
25
const filterRelativePathItems = ( items ) => items . filter ( ( part ) => part !== '' )
26
26
27
+ /**
28
+ * Return the default Netlify Graph configuration for a generic site
29
+ * @param {object } context
30
+ * @param {string[] } context.detectedFunctionsPath
31
+ * @param {string[] } context.siteRoot
32
+ */
33
+ const makeDefaultNetlifGraphConfig = ( { baseConfig, detectedFunctionsPath } ) => {
34
+ const functionsPath = filterRelativePathItems ( [ ...detectedFunctionsPath ] )
35
+ const webhookBasePath = '/.netlify/functions'
36
+ const netlifyGraphPath = [ ...functionsPath , 'netlifyGraph' ]
37
+ const netlifyGraphImplementationFilename = [ ...netlifyGraphPath , `index.${ baseConfig . extension } ` ]
38
+ const netlifyGraphTypeDefinitionsFilename = [ ...netlifyGraphPath , `index.d.ts` ]
39
+ const graphQLOperationsSourceFilename = [ ...netlifyGraphPath , NetlifyGraph . defaultSourceOperationsFilename ]
40
+ const graphQLSchemaFilename = [ ...netlifyGraphPath , NetlifyGraph . defaultGraphQLSchemaFilename ]
41
+ const netlifyGraphRequirePath = [ `./netlifyGraph` ]
42
+ const moduleType = baseConfig . moduleType || 'esm'
43
+
44
+ return {
45
+ functionsPath,
46
+ webhookBasePath,
47
+ netlifyGraphPath,
48
+ netlifyGraphImplementationFilename,
49
+ netlifyGraphTypeDefinitionsFilename,
50
+ graphQLOperationsSourceFilename,
51
+ graphQLSchemaFilename,
52
+ netlifyGraphRequirePath,
53
+ moduleType,
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Return the default Netlify Graph configuration for a Nextjs site
59
+ * @param {object } context
60
+ * @param {string[] } context.detectedFunctionsPath
61
+ * @param {string[] } context.siteRoot
62
+ */
63
+ const makeDefaultNextJsNetlifGraphConfig = ( { baseConfig, siteRoot } ) => {
64
+ const functionsPath = filterRelativePathItems ( [ ...siteRoot , 'pages' , 'api' ] )
65
+ const webhookBasePath = '/api'
66
+ const netlifyGraphPath = filterRelativePathItems ( [ ...siteRoot , 'lib' , 'netlifyGraph' ] )
67
+ const netlifyGraphImplementationFilename = [ ...netlifyGraphPath , `index.${ baseConfig . extension } ` ]
68
+ const netlifyGraphTypeDefinitionsFilename = [ ...netlifyGraphPath , `index.d.ts` ]
69
+ const graphQLOperationsSourceFilename = [ ...netlifyGraphPath , NetlifyGraph . defaultSourceOperationsFilename ]
70
+ const graphQLSchemaFilename = [ ...netlifyGraphPath , NetlifyGraph . defaultGraphQLSchemaFilename ]
71
+ const netlifyGraphRequirePath = [ '..' , '..' , 'lib' , 'netlifyGraph' ]
72
+ const moduleType = baseConfig . moduleType || 'esm'
73
+
74
+ return {
75
+ functionsPath,
76
+ webhookBasePath,
77
+ netlifyGraphPath,
78
+ netlifyGraphImplementationFilename,
79
+ netlifyGraphTypeDefinitionsFilename,
80
+ graphQLOperationsSourceFilename,
81
+ graphQLSchemaFilename,
82
+ netlifyGraphRequirePath,
83
+ moduleType,
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Return the default Netlify Graph configuration for a Remix site
89
+ * @param {object } context
90
+ * @param {string[] } context.detectedFunctionsPath
91
+ * @param {string[] } context.siteRoot
92
+ */
93
+ const makeDefaultRemixNetlifGraphConfig = ( { baseConfig, detectedFunctionsPath, siteRoot } ) => {
94
+ const functionsPath = filterRelativePathItems ( [ ...detectedFunctionsPath ] )
95
+ const webhookBasePath = '/webhooks'
96
+ const netlifyGraphPath = filterRelativePathItems ( [
97
+ ...siteRoot ,
98
+ ...NetlifyGraph . defaultNetlifyGraphConfig . netlifyGraphPath ,
99
+ ] )
100
+ const netlifyGraphImplementationFilename = [ ...netlifyGraphPath , `index.${ baseConfig . extension } ` ]
101
+ const netlifyGraphTypeDefinitionsFilename = [ ...netlifyGraphPath , `index.d.ts` ]
102
+ const graphQLOperationsSourceFilename = [ ...netlifyGraphPath , NetlifyGraph . defaultSourceOperationsFilename ]
103
+ const graphQLSchemaFilename = [ ...netlifyGraphPath , NetlifyGraph . defaultGraphQLSchemaFilename ]
104
+ const netlifyGraphRequirePath = [ `../../netlify/functions/netlifyGraph` ]
105
+ const moduleType = 'esm'
106
+
107
+ return {
108
+ functionsPath,
109
+ webhookBasePath,
110
+ netlifyGraphPath,
111
+ netlifyGraphImplementationFilename,
112
+ netlifyGraphTypeDefinitionsFilename,
113
+ graphQLOperationsSourceFilename,
114
+ graphQLSchemaFilename,
115
+ netlifyGraphRequirePath,
116
+ moduleType,
117
+ }
118
+ }
119
+
120
+ const defaultFrameworkLookup = {
121
+ 'Next.js' : makeDefaultNextJsNetlifGraphConfig ,
122
+ Remix : makeDefaultRemixNetlifGraphConfig ,
123
+ default : makeDefaultNetlifGraphConfig ,
124
+ }
125
+
27
126
/**
28
127
* Return a full NetlifyGraph config with any defaults overridden by netlify.toml
29
128
* @param {import('../base-command').BaseCommand } command
@@ -48,7 +147,8 @@ const getNetlifyGraphConfig = async ({ command, options, settings }) => {
48
147
try {
49
148
settings = await detectServerSettings ( devConfig , options , site . root )
50
149
} catch ( detectServerSettingsError ) {
51
- error ( detectServerSettingsError )
150
+ settings = { }
151
+ warn ( 'Error while auto-detecting project settings, Netlify Graph encounter problems' , detectServerSettingsError )
52
152
}
53
153
}
54
154
@@ -58,26 +158,55 @@ const getNetlifyGraphConfig = async ({ command, options, settings }) => {
58
158
const autodetectedLanguage = fs . existsSync ( tsConfig ) ? 'typescript' : 'javascript'
59
159
60
160
const framework = settings . framework || userSpecifiedConfig . framework
61
- const isNextjs = framework === 'Next.js'
161
+ const makeDefaultFrameworkConfig = defaultFrameworkLookup [ framework ] || defaultFrameworkLookup . default
162
+
62
163
const detectedFunctionsPathString = getFunctionsDir ( { config, options } )
63
- const detectedFunctionsPath = detectedFunctionsPathString ? detectedFunctionsPathString . split ( path . sep ) : null
64
- const functionsPath = filterRelativePathItems ( isNextjs ? [ ...siteRoot , 'pages' , 'api' ] : [ ...detectedFunctionsPath ] )
65
- const netlifyGraphPath = filterRelativePathItems (
66
- isNextjs
67
- ? [ ...siteRoot , 'lib' , 'netlifyGraph' ]
68
- : [ ...siteRoot , ...NetlifyGraph . defaultNetlifyGraphConfig . netlifyGraphPath ] ,
69
- )
164
+ const detectedFunctionsPath = detectedFunctionsPathString
165
+ ? [ path . sep , ...detectedFunctionsPathString . split ( path . sep ) ]
166
+ : null
70
167
const baseConfig = { ...NetlifyGraph . defaultNetlifyGraphConfig , ...userSpecifiedConfig }
71
- const netlifyGraphImplementationFilename = [ ...netlifyGraphPath , `index.${ baseConfig . extension } ` ]
72
- const netlifyGraphTypeDefinitionsFilename = [ ...netlifyGraphPath , `index.d.ts` ]
73
- const graphQLOperationsSourceFilename = [ ...netlifyGraphPath , NetlifyGraph . defaultSourceOperationsFilename ]
74
- const graphQLSchemaFilename = [ ...netlifyGraphPath , NetlifyGraph . defaultGraphQLSchemaFilename ]
75
- const netlifyGraphRequirePath = isNextjs ? [ '..' , '..' , 'lib' , 'netlifyGraph' ] : [ `./netlifyGraph` ]
76
- const language = userSpecifiedConfig . language || autodetectedLanguage
77
- const moduleType = baseConfig . moduleType || isNextjs ? 'esm' : 'commonjs'
168
+ const defaultFrameworkConfig = makeDefaultFrameworkConfig ( { baseConfig, detectedFunctionsPath, siteRoot } )
169
+
170
+ const functionsPath =
171
+ ( userSpecifiedConfig . functionsPath && userSpecifiedConfig . functionsPath . split ( path . sep ) ) ||
172
+ defaultFrameworkConfig . functionsPath
173
+ const netlifyGraphPath =
174
+ ( userSpecifiedConfig . netlifyGraphPath && userSpecifiedConfig . netlifyGraphPath . split ( path . sep ) ) ||
175
+ defaultFrameworkConfig . netlifyGraphPath
176
+ const netlifyGraphImplementationFilename =
177
+ ( userSpecifiedConfig . netlifyGraphImplementationFilename &&
178
+ userSpecifiedConfig . netlifyGraphImplementationFilename . split ( path . sep ) ) ||
179
+ defaultFrameworkConfig . netlifyGraphImplementationFilename
180
+ const netlifyGraphTypeDefinitionsFilename =
181
+ ( userSpecifiedConfig . netlifyGraphTypeDefinitionsFilename &&
182
+ userSpecifiedConfig . netlifyGraphTypeDefinitionsFilename . split ( path . sep ) ) ||
183
+ defaultFrameworkConfig . netlifyGraphTypeDefinitionsFilename
184
+ const graphQLOperationsSourceFilename =
185
+ ( userSpecifiedConfig . graphQLOperationsSourceFilename &&
186
+ userSpecifiedConfig . graphQLOperationsSourceFilename . split ( path . sep ) ) ||
187
+ defaultFrameworkConfig . graphQLOperationsSourceFilename
188
+ const graphQLSchemaFilename =
189
+ ( userSpecifiedConfig . graphQLSchemaFilename && userSpecifiedConfig . graphQLSchemaFilename . split ( path . sep ) ) ||
190
+ defaultFrameworkConfig . graphQLSchemaFilename
191
+ const netlifyGraphRequirePath =
192
+ ( userSpecifiedConfig . netlifyGraphRequirePath && userSpecifiedConfig . netlifyGraphRequirePath . split ( path . sep ) ) ||
193
+ defaultFrameworkConfig . netlifyGraphRequirePath
194
+ const moduleType =
195
+ ( userSpecifiedConfig . moduleType && userSpecifiedConfig . moduleType . split ( path . sep ) ) ||
196
+ defaultFrameworkConfig . moduleType
197
+ const language =
198
+ ( userSpecifiedConfig . language && userSpecifiedConfig . language . split ( path . sep ) ) || autodetectedLanguage
199
+ const webhookBasePath =
200
+ ( userSpecifiedConfig . webhookBasePath && userSpecifiedConfig . webhookBasePath . split ( path . sep ) ) ||
201
+ defaultFrameworkConfig . webhookBasePath
202
+ const customGeneratorFile =
203
+ userSpecifiedConfig . customGeneratorFile && userSpecifiedConfig . customGeneratorFile . split ( path . sep )
204
+ const runtimeTargetEnv = userSpecifiedConfig . runtimeTargetEnv || defaultFrameworkConfig . runtimeTargetEnv || 'node'
205
+
78
206
const fullConfig = {
79
207
...baseConfig ,
80
208
functionsPath,
209
+ webhookBasePath,
81
210
netlifyGraphPath,
82
211
netlifyGraphImplementationFilename,
83
212
netlifyGraphTypeDefinitionsFilename,
@@ -87,6 +216,8 @@ const getNetlifyGraphConfig = async ({ command, options, settings }) => {
87
216
framework,
88
217
language,
89
218
moduleType,
219
+ customGeneratorFile,
220
+ runtimeTargetEnv,
90
221
}
91
222
92
223
return fullConfig
@@ -97,30 +228,36 @@ const getNetlifyGraphConfig = async ({ command, options, settings }) => {
97
228
* @param {NetlifyGraphConfig } netlifyGraphConfig
98
229
*/
99
230
const ensureNetlifyGraphPath = ( netlifyGraphConfig ) => {
100
- fs . mkdirSync ( path . resolve ( ...netlifyGraphConfig . netlifyGraphPath ) , { recursive : true } )
231
+ const fullPath = path . resolve ( ...netlifyGraphConfig . netlifyGraphPath )
232
+ fs . mkdirSync ( fullPath , { recursive : true } )
101
233
}
102
234
103
235
/**
104
236
* Given a NetlifyGraphConfig, ensure that the functionsPath exists
105
237
* @param {NetlifyGraphConfig } netlifyGraphConfig
106
238
*/
107
239
const ensureFunctionsPath = ( netlifyGraphConfig ) => {
108
- fs . mkdirSync ( path . resolve ( ...netlifyGraphConfig . functionsPath ) , { recursive : true } )
240
+ const fullPath = path . resolve ( ...netlifyGraphConfig . functionsPath )
241
+ fs . mkdirSync ( fullPath , { recursive : true } )
109
242
}
110
243
111
244
/**
112
245
* Generate a library file with type definitions for a given NetlifyGraphConfig, operationsDoc, and schema, writing them to the filesystem
113
- * @param {NetlifyGraphConfig } netlifyGraphConfig
114
- * @param {GraphQLSchema } schema The schema to use when generating the functions and their types
115
- * @param {string } operationsDoc The GraphQL operations doc to use when generating the functions
116
- * @param {NetlifyGraph.ParsedFunction } queries The parsed queries with metadata to use when generating library functions
246
+ * @param {object } context
247
+ * @param {NetlifyGraphConfig } context.netlifyGraphConfig
248
+ * @param {GraphQLSchema } context.schema The schema to use when generating the functions and their types
249
+ * @param {string } context.operationsDoc The GraphQL operations doc to use when generating the functions
250
+ * @param {NetlifyGraph.ParsedFunction } context.functions The parsed queries with metadata to use when generating library functions
251
+ * @param {NetlifyGraph.ParsedFragment } context.fragments The parsed queries with metadata to use when generating library functions
252
+ * @returns {void } Void, effectfully writes the generated library to the filesystem
117
253
*/
118
- const generateFunctionsFile = ( netlifyGraphConfig , schema , operationsDoc , queries ) => {
254
+ const generateFunctionsFile = ( { fragments , functions , netlifyGraphConfig , operationsDoc, schema } ) => {
119
255
const { clientSource, typeDefinitionsSource } = NetlifyGraph . generateFunctionsSource (
120
256
netlifyGraphConfig ,
121
257
schema ,
122
258
operationsDoc ,
123
- queries ,
259
+ functions ,
260
+ fragments ,
124
261
)
125
262
126
263
ensureNetlifyGraphPath ( netlifyGraphConfig )
@@ -199,13 +336,15 @@ const generateHandler = (netlifyGraphConfig, schema, operationId, handlerOptions
199
336
currentOperationsDoc = NetlifyGraph . defaultExampleOperationsDoc
200
337
}
201
338
202
- const result = NetlifyGraph . generateHandlerSource ( {
339
+ const payload = {
203
340
handlerOptions,
204
341
schema,
205
342
netlifyGraphConfig,
206
343
operationId,
207
344
operationsDoc : currentOperationsDoc ,
208
- } )
345
+ }
346
+
347
+ const result = NetlifyGraph . generateHandlerSource ( payload )
209
348
210
349
if ( ! result ) {
211
350
warn ( `No handler was generated for operationId ${ operationId } ` )
@@ -237,6 +376,11 @@ const generateHandler = (netlifyGraphConfig, schema, operationId, handlerOptions
237
376
filenameArr = [ path . sep , ...netlifyGraphConfig . functionsPath , baseFilename ]
238
377
}
239
378
379
+ const parentDir = path . resolve ( ...filterRelativePathItems ( filenameArr . slice ( 0 , - 1 ) ) )
380
+
381
+ // Make sure the parent directory exists
382
+ fs . mkdirSync ( parentDir , { recursive : true } )
383
+
240
384
const absoluteFilename = path . resolve ( ...filenameArr )
241
385
242
386
fs . writeFileSync ( absoluteFilename , content )
@@ -254,7 +398,7 @@ const { buildSchema, parse } = GraphQL
254
398
* @returns {string } The url to the Netlify Graph UI for the current session
255
399
*/
256
400
const getGraphEditUrlBySiteName = ( { oneGraphSessionId, siteName } ) => {
257
- const host = 'app.netlify.com' || process . env . NETLIFY_APP_HOST
401
+ const host = process . env . NETLIFY_APP_HOST || 'app.netlify.com'
258
402
// http because app.netlify.com will redirect to https, and localhost will still work for development
259
403
const url = `http://${ host } /sites/${ siteName } /graph/explorer?cliSessionId=${ oneGraphSessionId } `
260
404
0 commit comments