netlify-cli 8.18.0 → 8.19.2

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.
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  const fs = require('fs')
2
3
  const path = require('path')
3
4
  const process = require('process')
@@ -17,6 +18,8 @@ const internalConsole = {
17
18
 
18
19
  InternalConsole.registerConsole(internalConsole)
19
20
 
21
+ const { extractFunctionsFromOperationDoc } = NetlifyGraph
22
+
20
23
  /**
21
24
  * Remove any relative path components from the given path
22
25
  * @param {string[]} items Filesystem path items to filter
@@ -27,10 +30,11 @@ const filterRelativePathItems = (items) => items.filter((part) => part !== '')
27
30
  /**
28
31
  * Return the default Netlify Graph configuration for a generic site
29
32
  * @param {object} context
33
+ * @param {object} context.baseConfig
30
34
  * @param {string[]} context.detectedFunctionsPath
31
35
  * @param {string[]} context.siteRoot
32
36
  */
33
- const makeDefaultNetlifGraphConfig = ({ baseConfig, detectedFunctionsPath }) => {
37
+ const makeDefaultNetlifyGraphConfig = ({ baseConfig, detectedFunctionsPath }) => {
34
38
  const functionsPath = filterRelativePathItems([...detectedFunctionsPath])
35
39
  const webhookBasePath = '/.netlify/functions'
36
40
  const netlifyGraphPath = [...functionsPath, 'netlifyGraph']
@@ -57,10 +61,11 @@ const makeDefaultNetlifGraphConfig = ({ baseConfig, detectedFunctionsPath }) =>
57
61
  /**
58
62
  * Return the default Netlify Graph configuration for a Nextjs site
59
63
  * @param {object} context
64
+ * @param {object} context.baseConfig
60
65
  * @param {string[]} context.detectedFunctionsPath
61
66
  * @param {string[]} context.siteRoot
62
67
  */
63
- const makeDefaultNextJsNetlifGraphConfig = ({ baseConfig, siteRoot }) => {
68
+ const makeDefaultNextJsNetlifyGraphConfig = ({ baseConfig, siteRoot }) => {
64
69
  const functionsPath = filterRelativePathItems([...siteRoot, 'pages', 'api'])
65
70
  const webhookBasePath = '/api'
66
71
  const netlifyGraphPath = filterRelativePathItems([...siteRoot, 'lib', 'netlifyGraph'])
@@ -87,10 +92,11 @@ const makeDefaultNextJsNetlifGraphConfig = ({ baseConfig, siteRoot }) => {
87
92
  /**
88
93
  * Return the default Netlify Graph configuration for a Remix site
89
94
  * @param {object} context
95
+ * @param {object} context.baseConfig
90
96
  * @param {string[]} context.detectedFunctionsPath
91
97
  * @param {string[]} context.siteRoot
92
98
  */
93
- const makeDefaultRemixNetlifGraphConfig = ({ baseConfig, detectedFunctionsPath, siteRoot }) => {
99
+ const makeDefaultRemixNetlifyGraphConfig = ({ baseConfig, detectedFunctionsPath, siteRoot }) => {
94
100
  const functionsPath = filterRelativePathItems([...detectedFunctionsPath])
95
101
  const webhookBasePath = '/webhooks'
96
102
  const netlifyGraphPath = filterRelativePathItems([
@@ -118,22 +124,25 @@ const makeDefaultRemixNetlifGraphConfig = ({ baseConfig, detectedFunctionsPath,
118
124
  }
119
125
 
120
126
  const defaultFrameworkLookup = {
121
- 'Next.js': makeDefaultNextJsNetlifGraphConfig,
122
- Remix: makeDefaultRemixNetlifGraphConfig,
123
- default: makeDefaultNetlifGraphConfig,
127
+ 'Next.js': makeDefaultNextJsNetlifyGraphConfig,
128
+ Remix: makeDefaultRemixNetlifyGraphConfig,
129
+ default: makeDefaultNetlifyGraphConfig,
124
130
  }
125
131
 
126
132
  /**
127
133
  * Return a full NetlifyGraph config with any defaults overridden by netlify.toml
128
- * @param {import('../base-command').BaseCommand} command
129
- * @return {NetlifyGraphConfig} NetlifyGraphConfig
134
+ * @param {object} input
135
+ * @param {import('../../commands/base-command').BaseCommand} input.command
136
+ * @param {import('commander').OptionValues} input.options
137
+ * @param {Partial<import('../../utils/types').ServerSettings>=} input.settings
138
+ * @return {Promise<NetlifyGraph.NetlifyGraphConfig>} NetlifyGraphConfig
130
139
  */
131
140
  const getNetlifyGraphConfig = async ({ command, options, settings }) => {
132
141
  const { config, site } = command.netlify
133
142
  config.dev = { ...config.dev }
134
143
  config.build = { ...config.build }
135
144
  const userSpecifiedConfig = (config && config.graph) || {}
136
- /** @type {import('./types').DevConfig} */
145
+ /** @type {import('../../commands/dev/types').DevConfig} */
137
146
  const devConfig = {
138
147
  framework: '#auto',
139
148
  ...(config.functionsDirectory && { functions: config.functionsDirectory }),
@@ -148,7 +157,13 @@ const getNetlifyGraphConfig = async ({ command, options, settings }) => {
148
157
  settings = await detectServerSettings(devConfig, options, site.root)
149
158
  } catch (detectServerSettingsError) {
150
159
  settings = {}
151
- warn('Error while auto-detecting project settings, Netlify Graph encounter problems', detectServerSettingsError)
160
+ warn(
161
+ `Error while auto-detecting project settings, Netlify Graph encounter problems: ${JSON.stringify(
162
+ detectServerSettingsError,
163
+ null,
164
+ 2,
165
+ )}`,
166
+ )
152
167
  }
153
168
  }
154
169
 
@@ -167,9 +182,11 @@ const getNetlifyGraphConfig = async ({ command, options, settings }) => {
167
182
  const baseConfig = { ...NetlifyGraph.defaultNetlifyGraphConfig, ...userSpecifiedConfig }
168
183
  const defaultFrameworkConfig = makeDefaultFrameworkConfig({ baseConfig, detectedFunctionsPath, siteRoot })
169
184
 
185
+ const userSpecifiedFunctionPath =
186
+ userSpecifiedConfig.functionsPath && userSpecifiedConfig.functionsPath.split(path.sep)
187
+
170
188
  const functionsPath =
171
- (userSpecifiedConfig.functionsPath && userSpecifiedConfig.functionsPath.split(path.sep)) ||
172
- defaultFrameworkConfig.functionsPath
189
+ (userSpecifiedFunctionPath && [...siteRoot, ...userSpecifiedFunctionPath]) || defaultFrameworkConfig.functionsPath
173
190
  const netlifyGraphPath =
174
191
  (userSpecifiedConfig.netlifyGraphPath && userSpecifiedConfig.netlifyGraphPath.split(path.sep)) ||
175
192
  defaultFrameworkConfig.netlifyGraphPath
@@ -225,7 +242,7 @@ const getNetlifyGraphConfig = async ({ command, options, settings }) => {
225
242
 
226
243
  /**
227
244
  * Given a NetlifyGraphConfig, ensure that the netlifyGraphPath exists
228
- * @param {NetlifyGraphConfig} netlifyGraphConfig
245
+ * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
229
246
  */
230
247
  const ensureNetlifyGraphPath = (netlifyGraphConfig) => {
231
248
  const fullPath = path.resolve(...netlifyGraphConfig.netlifyGraphPath)
@@ -234,7 +251,7 @@ const ensureNetlifyGraphPath = (netlifyGraphConfig) => {
234
251
 
235
252
  /**
236
253
  * Given a NetlifyGraphConfig, ensure that the functionsPath exists
237
- * @param {NetlifyGraphConfig} netlifyGraphConfig
254
+ * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
238
255
  */
239
256
  const ensureFunctionsPath = (netlifyGraphConfig) => {
240
257
  const fullPath = path.resolve(...netlifyGraphConfig.functionsPath)
@@ -248,9 +265,8 @@ const runPrettier = async (filePath) => {
248
265
  return
249
266
  }
250
267
 
251
- const command = `prettier --write ${filePath}`
252
268
  try {
253
- const commandProcess = execa.command(command, {
269
+ const commandProcess = execa('prettier', ['--write', filePath], {
254
270
  preferLocal: true,
255
271
  // windowsHide needs to be false for child process to terminate properly on Windows
256
272
  windowsHide: false,
@@ -269,11 +285,11 @@ const runPrettier = async (filePath) => {
269
285
  /**
270
286
  * Generate a library file with type definitions for a given NetlifyGraphConfig, operationsDoc, and schema, writing them to the filesystem
271
287
  * @param {object} context
272
- * @param {NetlifyGraphConfig} context.netlifyGraphConfig
273
- * @param {GraphQLSchema} context.schema The schema to use when generating the functions and their types
288
+ * @param {NetlifyGraph.NetlifyGraphConfig} context.netlifyGraphConfig
289
+ * @param {GraphQL.GraphQLSchema} context.schema The schema to use when generating the functions and their types
274
290
  * @param {string} context.operationsDoc The GraphQL operations doc to use when generating the functions
275
- * @param {NetlifyGraph.ParsedFunction} context.functions The parsed queries with metadata to use when generating library functions
276
- * @param {NetlifyGraph.ParsedFragment} context.fragments The parsed queries with metadata to use when generating library functions
291
+ * @param {Record<string, NetlifyGraph.ExtractedFunction>} context.functions The parsed queries with metadata to use when generating library functions
292
+ * @param {Record<string, NetlifyGraph.ExtractedFragment>} context.fragments The parsed queries with metadata to use when generating library functions
277
293
  * @returns {void} Void, effectfully writes the generated library to the filesystem
278
294
  */
279
295
  const generateFunctionsFile = ({ fragments, functions, netlifyGraphConfig, operationsDoc, schema }) => {
@@ -298,7 +314,7 @@ const generateFunctionsFile = ({ fragments, functions, netlifyGraphConfig, opera
298
314
 
299
315
  /**
300
316
  * Using the given NetlifyGraphConfig, read the GraphQL operations file and return the _unparsed_ GraphQL operations doc
301
- * @param {NetlifyGraphConfig} netlifyGraphConfig
317
+ * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
302
318
  * @returns {string} GraphQL operations doc
303
319
  */
304
320
  const readGraphQLOperationsSourceFile = (netlifyGraphConfig) => {
@@ -317,11 +333,11 @@ const readGraphQLOperationsSourceFile = (netlifyGraphConfig) => {
317
333
 
318
334
  /**
319
335
  * Write an operations doc to the filesystem using the given NetlifyGraphConfig
320
- * @param {NetlifyGraphConfig} netlifyGraphConfig
321
- * @param {string} operationsDoc The GraphQL operations doc to write
336
+ * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
337
+ * @param {string} operationsDocString The GraphQL operations doc to write
322
338
  */
323
- const writeGraphQLOperationsSourceFile = (netlifyGraphConfig, operationDocString) => {
324
- const graphqlSource = operationDocString
339
+ const writeGraphQLOperationsSourceFile = (netlifyGraphConfig, operationsDocString) => {
340
+ const graphqlSource = operationsDocString
325
341
 
326
342
  ensureNetlifyGraphPath(netlifyGraphConfig)
327
343
  fs.writeFileSync(path.resolve(...netlifyGraphConfig.graphQLOperationsSourceFilename), graphqlSource, 'utf8')
@@ -329,8 +345,8 @@ const writeGraphQLOperationsSourceFile = (netlifyGraphConfig, operationDocString
329
345
 
330
346
  /**
331
347
  * Write a GraphQL Schema printed in SDL format to the filesystem using the given NetlifyGraphConfig
332
- * @param {NetlifyGraphConfig} netlifyGraphConfig
333
- * @param {GraphQLSchema} schema The GraphQL schema to print and write to the filesystem
348
+ * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
349
+ * @param {GraphQL.GraphQLSchema} schema The GraphQL schema to print and write to the filesystem
334
350
  */
335
351
  const writeGraphQLSchemaFile = (netlifyGraphConfig, schema) => {
336
352
  const graphqlSource = printSchema(schema)
@@ -341,7 +357,7 @@ const writeGraphQLSchemaFile = (netlifyGraphConfig, schema) => {
341
357
 
342
358
  /**
343
359
  * Using the given NetlifyGraphConfig, read the GraphQL schema file and return it _unparsed_
344
- * @param {NetlifyGraphConfig} netlifyGraphConfig
360
+ * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
345
361
  * @returns {string} GraphQL schema
346
362
  */
347
363
  const readGraphQLSchemaFile = (netlifyGraphConfig) => {
@@ -351,13 +367,13 @@ const readGraphQLSchemaFile = (netlifyGraphConfig) => {
351
367
 
352
368
  /**
353
369
  * Given a NetlifyGraphConfig, read the appropriate files and write a handler for the given operationId to the filesystem
354
- * @param {NetlifyGraphConfig} netlifyGraphConfig
355
- * @param {GraphQLSchema} schema The GraphQL schema to use when generating the handler
370
+ * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
371
+ * @param {GraphQL.GraphQLSchema} schema The GraphQL schema to use when generating the handler
356
372
  * @param {string} operationId The operationId to use when generating the handler
357
373
  * @param {object} handlerOptions The options to use when generating the handler
358
374
  * @returns
359
375
  */
360
- const generateHandler = (netlifyGraphConfig, schema, operationId, handlerOptions) => {
376
+ const generateHandlerByOperationId = (netlifyGraphConfig, schema, operationId, handlerOptions) => {
361
377
  let currentOperationsDoc = readGraphQLOperationsSourceFile(netlifyGraphConfig)
362
378
  if (currentOperationsDoc.trim().length === 0) {
363
379
  currentOperationsDoc = NetlifyGraph.defaultExampleOperationsDoc
@@ -415,6 +431,35 @@ const generateHandler = (netlifyGraphConfig, schema, operationId, handlerOptions
415
431
  })
416
432
  }
417
433
 
434
+ /**
435
+ * Given a NetlifyGraphConfig, read the appropriate files and write a handler for the given operationId to the filesystem
436
+ * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
437
+ * @param {GraphQL.GraphQLSchema} schema The GraphQL schema to use when generating the handler
438
+ * @param {string} operationName The name of the operation to use when generating the handler
439
+ * @param {object} handlerOptions The options to use when generating the handler
440
+ * @returns
441
+ */
442
+ const generateHandlerByOperationName = (netlifyGraphConfig, schema, operationName, handlerOptions) => {
443
+ let currentOperationsDoc = readGraphQLOperationsSourceFile(netlifyGraphConfig)
444
+ if (currentOperationsDoc.trim().length === 0) {
445
+ currentOperationsDoc = NetlifyGraph.defaultExampleOperationsDoc
446
+ }
447
+
448
+ const parsedDoc = parse(currentOperationsDoc)
449
+ const { functions } = extractFunctionsFromOperationDoc(parsedDoc)
450
+
451
+ const operation = Object.values(functions).find(
452
+ (potentialOperation) => potentialOperation.operationName === operationName,
453
+ )
454
+
455
+ if (!operation) {
456
+ warn(`No operation named ${operationName} was found in the operations doc`)
457
+ return
458
+ }
459
+
460
+ generateHandlerByOperationId(netlifyGraphConfig, schema, operation.id, handlerOptions)
461
+ }
462
+
418
463
  // Export the minimal set of functions that are required for Netlify Graph
419
464
  const { buildSchema, parse } = GraphQL
420
465
 
@@ -455,13 +500,15 @@ module.exports = {
455
500
  generateFunctionsSource: NetlifyGraph.generateFunctionsSource,
456
501
  generateFunctionsFile,
457
502
  generateHandlerSource: NetlifyGraph.generateHandlerSource,
458
- generateHandler,
503
+ generateHandlerByOperationId,
504
+ generateHandlerByOperationName,
459
505
  getGraphEditUrlBySiteId,
460
506
  getGraphEditUrlBySiteName,
461
507
  getNetlifyGraphConfig,
462
508
  parse,
463
509
  readGraphQLOperationsSourceFile,
464
510
  readGraphQLSchemaFile,
511
+ runPrettier,
465
512
  writeGraphQLOperationsSourceFile,
466
513
  writeGraphQLSchemaFile,
467
514
  }
@@ -47,8 +47,6 @@ const USER_AGENT = `${name}/${version} ${platform}-${arch} node-${process.versio
47
47
  /** A list of base command flags that needs to be sorted down on documentation and on help pages */
48
48
  const BASE_FLAGS = new Set(['--debug', '--httpProxy', '--httpProxyCertificateFilename'])
49
49
 
50
- const { NETLIFY_AUTH_TOKEN } = process.env
51
-
52
50
  // eslint-disable-next-line no-magic-numbers
53
51
  const NETLIFY_CYAN = chalk.rgb(40, 180, 170)
54
52
 
@@ -121,6 +119,7 @@ const getToken = async (tokenFromOptions) => {
121
119
  return [tokenFromOptions, 'flag']
122
120
  }
123
121
  // 2. then Check ENV var
122
+ const { NETLIFY_AUTH_TOKEN } = process.env
124
123
  if (NETLIFY_AUTH_TOKEN && NETLIFY_AUTH_TOKEN !== 'null') {
125
124
  return [NETLIFY_AUTH_TOKEN, 'env']
126
125
  }