netlify-cli 9.3.0 → 9.4.0

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
3
  "description": "Netlify command line tool",
4
- "version": "9.3.0",
4
+ "version": "9.4.0",
5
5
  "author": "Netlify Inc.",
6
6
  "contributors": [
7
7
  "Abraham Schilling <AbrahamSchilling@gmail.com> (https://gitlab.com/n4bb12)",
@@ -198,8 +198,8 @@
198
198
  "prettier": "--ignore-path .gitignore --loglevel=warn \"{src,tools,scripts,site,tests,.github}/**/*.{mjs,cjs,js,md,yml,json,html}\" \"*.{mjs,cjs,js,yml,json,html}\" \".*.{mjs,cjs,js,yml,json,html}\" \"!CHANGELOG.md\" \"!npm-shrinkwrap.json\" \"!site/package-lock.json\" \"!.github/**/*.md\""
199
199
  },
200
200
  "dependencies": {
201
- "@netlify/build": "^26.2.6",
202
- "@netlify/config": "^17.0.7",
201
+ "@netlify/build": "^26.3.0",
202
+ "@netlify/config": "^17.0.8",
203
203
  "@netlify/framework-info": "^9.0.0",
204
204
  "@netlify/local-functions-proxy": "^1.1.1",
205
205
  "@netlify/plugin-edge-handlers": "^3.0.6",
@@ -1,9 +1,10 @@
1
1
  // @ts-check
2
2
  const fs = require('fs')
3
3
  const path = require('path')
4
+ const process = require('process')
4
5
 
5
6
  const { getNetlifyGraphConfig } = require('../../lib/one-graph/cli-netlify-graph')
6
- const { NETLIFYDEVERR, chalk, error } = require('../../utils')
7
+ const { NETLIFYDEVERR, chalk, error, log } = require('../../utils')
7
8
 
8
9
  /**
9
10
  * Creates the `netlify graph:config:write` command
@@ -33,8 +34,10 @@ const graphConfigWrite = async (options, command) => {
33
34
  }
34
35
 
35
36
  const filePath = path.resolve(...netlifyGraphConfig.graphQLConfigJsonFilename)
36
-
37
37
  fs.writeFileSync(filePath, JSON.stringify(graphQLConfig, null, 2))
38
+
39
+ const relativePath = path.relative(process.cwd(), filePath)
40
+ log(`Wrote ${chalk.cyan(relativePath)}`)
38
41
  }
39
42
 
40
43
  /**
@@ -14,7 +14,7 @@ const {
14
14
  getNetlifyGraphConfig,
15
15
  readGraphQLOperationsSourceFile,
16
16
  } = require('../../lib/one-graph/cli-netlify-graph')
17
- const { NETLIFYDEVERR, chalk, error } = require('../../utils')
17
+ const { NETLIFYDEVERR, chalk, error, log } = require('../../utils')
18
18
  const { openBrowser } = require('../../utils/open-browser')
19
19
 
20
20
  const { createPersistedQuery, ensureAppForSite } = OneGraphCliClient
@@ -77,6 +77,7 @@ const graphEdit = async (options, command) => {
77
77
 
78
78
  const graphEditUrl = getGraphEditUrlBySiteId({ siteId, oneGraphSessionId })
79
79
 
80
+ log(`Opening graph:edit session at ${chalk.cyan(graphEditUrl)}`)
80
81
  await openBrowser({ url: graphEditUrl })
81
82
  }
82
83
 
@@ -5,7 +5,7 @@ const {
5
5
  getNetlifyGraphConfig,
6
6
  readGraphQLSchemaFile,
7
7
  } = require('../../lib/one-graph/cli-netlify-graph')
8
- const { error } = require('../../utils')
8
+ const { error, log } = require('../../utils')
9
9
 
10
10
  /**
11
11
  * Creates the `netlify graph:handler` command
@@ -31,7 +31,7 @@ const graphHandler = async (operationName, options, command) => {
31
31
  error(`Failed to parse Netlify GraphQL schema`)
32
32
  }
33
33
 
34
- generateHandlerByOperationName(netlifyGraphConfig, schema, operationName, {})
34
+ generateHandlerByOperationName({ logger: log, netlifyGraphConfig, schema, operationName, handlerOptions: {} })
35
35
  }
36
36
 
37
37
  /**
@@ -9,7 +9,7 @@ const {
9
9
  readGraphQLOperationsSourceFile,
10
10
  readGraphQLSchemaFile,
11
11
  } = require('../../lib/one-graph/cli-netlify-graph')
12
- const { error } = require('../../utils')
12
+ const { error, log } = require('../../utils')
13
13
 
14
14
  /**
15
15
  * Creates the `netlify graph:library` command
@@ -42,7 +42,14 @@ const graphLibrary = async (options, command) => {
42
42
  const parsedDoc = parse(currentOperationsDoc)
43
43
  const { fragments, functions } = extractFunctionsFromOperationDoc(parsedDoc)
44
44
 
45
- generateFunctionsFile({ netlifyGraphConfig, schema, operationsDoc: currentOperationsDoc, functions, fragments })
45
+ generateFunctionsFile({
46
+ logger: log,
47
+ netlifyGraphConfig,
48
+ schema,
49
+ operationsDoc: currentOperationsDoc,
50
+ functions,
51
+ fragments,
52
+ })
46
53
  }
47
54
 
48
55
  /**
@@ -8,7 +8,7 @@ const {
8
8
  refetchAndGenerateFromOneGraph,
9
9
  } = require('../../lib/one-graph/cli-client')
10
10
  const { buildSchema, getNetlifyGraphConfig, readGraphQLSchemaFile } = require('../../lib/one-graph/cli-netlify-graph')
11
- const { chalk, error, warn } = require('../../utils')
11
+ const { chalk, error, log, warn } = require('../../utils')
12
12
 
13
13
  /**
14
14
  * Creates the `netlify graph:pull` command
@@ -31,12 +31,14 @@ const graphPull = async (options, command) => {
31
31
  const netlifyToken = await command.authenticate()
32
32
  const siteId = site.id
33
33
 
34
- await refetchAndGenerateFromOneGraph({ netlifyGraphConfig, netlifyToken, state, siteId })
34
+ await refetchAndGenerateFromOneGraph({ logger: log, netlifyGraphConfig, netlifyToken, state, siteId })
35
35
 
36
36
  const oneGraphSessionId = loadCLISession(state)
37
37
 
38
38
  if (!oneGraphSessionId) {
39
- warn('No local Netlify Graph session found, skipping command queue drain')
39
+ warn(
40
+ 'No local Netlify Graph session found, skipping command queue drain. Create a new session by running `netlify graph:edit`.',
41
+ )
40
42
  return
41
43
  }
42
44
 
@@ -10,7 +10,7 @@ const { GraphQL, InternalConsole, OneGraphClient } = require('netlify-onegraph-i
10
10
  const { NetlifyGraph } = require('netlify-onegraph-internal')
11
11
 
12
12
  // eslint-disable-next-line no-unused-vars
13
- const { StateConfig, chalk, error, log, warn } = require('../../utils')
13
+ const { StateConfig, USER_AGENT, chalk, error, log, warn } = require('../../utils')
14
14
  const { watchDebounced } = require('../functions/watcher')
15
15
 
16
16
  const {
@@ -147,10 +147,11 @@ const monitorOperationFile = async ({ netlifyGraphConfig, onAdd, onChange, onUnl
147
147
  * @param {string} input.netlifyToken The (typically netlify) access token that is used for authentication, if any
148
148
  * @param {NetlifyGraph.NetlifyGraphConfig} input.netlifyGraphConfig A standalone config object that contains all the information necessary for Netlify Graph to process events
149
149
  * @param {StateConfig} input.state A function to call to set/get the current state of the local Netlify project
150
+ * @param {(message: string) => void=} input.logger A function that if provided will be used to log messages
150
151
  * @returns {Promise<void>}
151
152
  */
152
153
  const refetchAndGenerateFromOneGraph = async (input) => {
153
- const { netlifyGraphConfig, netlifyToken, siteId, state } = input
154
+ const { logger, netlifyGraphConfig, netlifyToken, siteId, state } = input
154
155
  await OneGraphClient.ensureAppForSite(netlifyToken, siteId)
155
156
 
156
157
  const enabledServicesInfo = await OneGraphClient.fetchEnabledServices(netlifyToken, siteId)
@@ -162,6 +163,7 @@ const refetchAndGenerateFromOneGraph = async (input) => {
162
163
  const enabledServices = enabledServicesInfo
163
164
  .map((service) => service.service)
164
165
  .sort((aString, bString) => aString.localeCompare(bString))
166
+
165
167
  const schema = await OneGraphClient.fetchOneGraphSchema(siteId, enabledServices)
166
168
 
167
169
  let currentOperationsDoc = readGraphQLOperationsSourceFile(netlifyGraphConfig)
@@ -172,8 +174,15 @@ const refetchAndGenerateFromOneGraph = async (input) => {
172
174
  const parsedDoc = parse(currentOperationsDoc)
173
175
  const { fragments, functions } = extractFunctionsFromOperationDoc(parsedDoc)
174
176
 
175
- generateFunctionsFile({ netlifyGraphConfig, schema, operationsDoc: currentOperationsDoc, functions, fragments })
176
- writeGraphQLSchemaFile(netlifyGraphConfig, schema)
177
+ generateFunctionsFile({
178
+ logger,
179
+ netlifyGraphConfig,
180
+ schema,
181
+ operationsDoc: currentOperationsDoc,
182
+ functions,
183
+ fragments,
184
+ })
185
+ writeGraphQLSchemaFile({ logger, netlifyGraphConfig, schema })
177
186
  state.set('oneGraphEnabledServices', enabledServices)
178
187
  }
179
188
 
@@ -220,12 +229,13 @@ const quickHash = (input) => {
220
229
  * @param {string} input.siteId The site id to query against
221
230
  * @param {string} input.netlifyToken The (typically netlify) access token that is used for authentication, if any
222
231
  * @param {string} input.docId The GraphQL operations document id to fetch
232
+ * @param {(message: string) => void=} input.logger A function that if provided will be used to log messages
223
233
  * @param {GraphQL.GraphQLSchema} input.schema The GraphQL schema to use when generating code
224
234
  * @param {NetlifyGraph.NetlifyGraphConfig} input.netlifyGraphConfig A standalone config object that contains all the information necessary for Netlify Graph to process events
225
235
  * @returns
226
236
  */
227
237
  const updateGraphQLOperationsFileFromPersistedDoc = async (input) => {
228
- const { docId, netlifyGraphConfig, netlifyToken, schema, siteId } = input
238
+ const { docId, logger, netlifyGraphConfig, netlifyToken, schema, siteId } = input
229
239
  const persistedDoc = await OneGraphClient.fetchPersistedQuery(netlifyToken, siteId, docId)
230
240
  if (!persistedDoc) {
231
241
  warn(`No persisted doc found for: ${docId}`)
@@ -233,12 +243,12 @@ const updateGraphQLOperationsFileFromPersistedDoc = async (input) => {
233
243
  }
234
244
 
235
245
  // Sorts the operations stably, prepends the @netlify directive, etc.
236
- const doc = normalizeOperationsDoc(persistedDoc.query)
246
+ const operationsDocString = normalizeOperationsDoc(persistedDoc.query)
237
247
 
238
- writeGraphQLOperationsSourceFile(netlifyGraphConfig, doc)
248
+ writeGraphQLOperationsSourceFile({ logger, netlifyGraphConfig, operationsDocString })
239
249
  regenerateFunctionsFileFromOperationsFile({ netlifyGraphConfig, schema })
240
250
 
241
- const hash = quickHash(doc)
251
+ const hash = quickHash(operationsDocString)
242
252
 
243
253
  const relevantHasLength = 10
244
254
 
@@ -260,7 +270,12 @@ const handleCliSessionEvent = async ({ event, netlifyGraphConfig, netlifyToken,
260
270
  warn(`No operation id found in payload, ${JSON.stringify(payload, null, 2)}`)
261
271
  return
262
272
  }
263
- generateHandlerByOperationId(netlifyGraphConfig, schema, payload.operationId.id, payload)
273
+ generateHandlerByOperationId({
274
+ netlifyGraphConfig,
275
+ schema,
276
+ operationId: payload.operationId.id,
277
+ handlerOptions: payload,
278
+ })
264
279
  break
265
280
  case 'OneGraphNetlifyCliSessionPersistedLibraryUpdatedEvent':
266
281
  await updateGraphQLOperationsFileFromPersistedDoc({
@@ -324,12 +339,14 @@ const detectLocalCLISessionMetadata = ({ siteRoot }) => {
324
339
  const hostname = os.hostname()
325
340
  const userInfo = os.userInfo({ encoding: 'utf-8' })
326
341
  const { username } = userInfo
342
+ const cliVersion = USER_AGENT
327
343
 
328
344
  const detectedMetadata = {
329
345
  gitBranch: branch,
330
346
  hostname,
331
347
  username,
332
348
  siteRoot,
349
+ cliVersion,
333
350
  }
334
351
 
335
352
  return detectedMetadata
@@ -5,7 +5,7 @@ const process = require('process')
5
5
 
6
6
  const { GraphQL, GraphQLHelpers, InternalConsole, NetlifyGraph } = require('netlify-onegraph-internal')
7
7
 
8
- const { detectServerSettings, error, execa, getFunctionsDir, log, warn } = require('../../utils')
8
+ const { chalk, detectServerSettings, error, execa, getFunctionsDir, log, warn } = require('../../utils')
9
9
 
10
10
  const { printSchema } = GraphQL
11
11
 
@@ -280,10 +280,11 @@ const runPrettier = async (filePath) => {
280
280
  })
281
281
 
282
282
  await commandProcess
283
+ // eslint-disable-next-line unicorn/prefer-optional-catch-binding
283
284
  } catch (prettierError) {
285
+ // It would be nice to log this error to help debugging, but it's potentially a bit scary for the dev to see it
284
286
  if (!disablePrettierDueToPreviousError) {
285
287
  disablePrettierDueToPreviousError = true
286
- warn(prettierError)
287
288
  warn("Error while running prettier, make sure you have installed it globally with 'npm i -g prettier'")
288
289
  }
289
290
  }
@@ -297,9 +298,10 @@ const runPrettier = async (filePath) => {
297
298
  * @param {string} context.operationsDoc The GraphQL operations doc to use when generating the functions
298
299
  * @param {Record<string, NetlifyGraph.ExtractedFunction>} context.functions The parsed queries with metadata to use when generating library functions
299
300
  * @param {Record<string, NetlifyGraph.ExtractedFragment>} context.fragments The parsed queries with metadata to use when generating library functions
301
+ * @param {(message: string) => void=} context.logger A function that if provided will be used to log messages
300
302
  * @returns {void} Void, effectfully writes the generated library to the filesystem
301
303
  */
302
- const generateFunctionsFile = ({ fragments, functions, netlifyGraphConfig, operationsDoc, schema }) => {
304
+ const generateFunctionsFile = ({ fragments, functions, logger, netlifyGraphConfig, operationsDoc, schema }) => {
303
305
  const { clientSource, typeDefinitionsSource } = NetlifyGraph.generateFunctionsSource(
304
306
  netlifyGraphConfig,
305
307
  schema,
@@ -309,12 +311,15 @@ const generateFunctionsFile = ({ fragments, functions, netlifyGraphConfig, opera
309
311
  )
310
312
 
311
313
  ensureNetlifyGraphPath(netlifyGraphConfig)
312
- fs.writeFileSync(path.resolve(...netlifyGraphConfig.netlifyGraphImplementationFilename), clientSource, 'utf8')
313
- fs.writeFileSync(
314
- path.resolve(...netlifyGraphConfig.netlifyGraphTypeDefinitionsFilename),
315
- typeDefinitionsSource,
316
- 'utf8',
317
- )
314
+ const implementationResolvedPath = path.resolve(...netlifyGraphConfig.netlifyGraphImplementationFilename)
315
+ fs.writeFileSync(implementationResolvedPath, clientSource, 'utf8')
316
+ const implementationRelativePath = path.relative(process.cwd(), implementationResolvedPath)
317
+ logger && logger(`Wrote ${chalk.cyan(implementationRelativePath)}`)
318
+
319
+ const typeDefinitionsResolvedPath = path.resolve(...netlifyGraphConfig.netlifyGraphTypeDefinitionsFilename)
320
+ fs.writeFileSync(typeDefinitionsResolvedPath, typeDefinitionsSource, 'utf8')
321
+ const typeDefinitionsRelativePath = path.relative(process.cwd(), typeDefinitionsResolvedPath)
322
+ logger && logger(`Wrote ${chalk.cyan(typeDefinitionsRelativePath)}`)
318
323
  runPrettier(path.resolve(...netlifyGraphConfig.netlifyGraphImplementationFilename))
319
324
  runPrettier(path.resolve(...netlifyGraphConfig.netlifyGraphTypeDefinitionsFilename))
320
325
  }
@@ -340,26 +345,36 @@ const readGraphQLOperationsSourceFile = (netlifyGraphConfig) => {
340
345
 
341
346
  /**
342
347
  * Write an operations doc to the filesystem using the given NetlifyGraphConfig
343
- * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
344
- * @param {string} operationsDocString The GraphQL operations doc to write
348
+ * @param {object} input
349
+ * @param {(message: string) => void=} input.logger A function that if provided will be used to log messages
350
+ * @param {NetlifyGraph.NetlifyGraphConfig} input.netlifyGraphConfig
351
+ * @param {string} input.operationsDocString The GraphQL operations doc to write
345
352
  */
346
- const writeGraphQLOperationsSourceFile = (netlifyGraphConfig, operationsDocString) => {
353
+ const writeGraphQLOperationsSourceFile = ({ logger, netlifyGraphConfig, operationsDocString }) => {
347
354
  const graphqlSource = operationsDocString
348
355
 
349
356
  ensureNetlifyGraphPath(netlifyGraphConfig)
350
- fs.writeFileSync(path.resolve(...netlifyGraphConfig.graphQLOperationsSourceFilename), graphqlSource, 'utf8')
357
+ const resolvedPath = path.resolve(...netlifyGraphConfig.graphQLOperationsSourceFilename)
358
+ fs.writeFileSync(resolvedPath, graphqlSource, 'utf8')
359
+ const relativePath = path.relative(process.cwd(), resolvedPath)
360
+ logger && logger(`Wrote ${chalk.cyan(relativePath)}`)
351
361
  }
352
362
 
353
363
  /**
354
364
  * Write a GraphQL Schema printed in SDL format to the filesystem using the given NetlifyGraphConfig
355
- * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
356
- * @param {GraphQL.GraphQLSchema} schema The GraphQL schema to print and write to the filesystem
365
+ * @param {object} input
366
+ * @param {(message: string) => void=} input.logger A function that if provided will be used to log messages
367
+ * @param {NetlifyGraph.NetlifyGraphConfig} input.netlifyGraphConfig
368
+ * @param {GraphQL.GraphQLSchema} input.schema The GraphQL schema to print and write to the filesystem
357
369
  */
358
- const writeGraphQLSchemaFile = (netlifyGraphConfig, schema) => {
370
+ const writeGraphQLSchemaFile = ({ logger, netlifyGraphConfig, schema }) => {
359
371
  const graphqlSource = printSchema(schema)
360
372
 
361
373
  ensureNetlifyGraphPath(netlifyGraphConfig)
362
- fs.writeFileSync(path.resolve(...netlifyGraphConfig.graphQLSchemaFilename), graphqlSource, 'utf8')
374
+ const resolvedPath = path.resolve(...netlifyGraphConfig.graphQLSchemaFilename)
375
+ fs.writeFileSync(resolvedPath, graphqlSource, 'utf8')
376
+ const relativePath = path.relative(process.cwd(), resolvedPath)
377
+ logger && logger(`Wrote ${chalk.cyan(relativePath)}`)
363
378
  }
364
379
 
365
380
  /**
@@ -374,19 +389,21 @@ const readGraphQLSchemaFile = (netlifyGraphConfig) => {
374
389
 
375
390
  /**
376
391
  * Given a NetlifyGraphConfig, read the appropriate files and write a handler for the given operationId to the filesystem
377
- * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
378
- * @param {GraphQL.GraphQLSchema} schema The GraphQL schema to use when generating the handler
379
- * @param {string} operationId The operationId to use when generating the handler
380
- * @param {object} handlerOptions The options to use when generating the handler
392
+ * @param {object} input
393
+ * @param {NetlifyGraph.NetlifyGraphConfig} input.netlifyGraphConfig
394
+ * @param {GraphQL.GraphQLSchema} input.schema The GraphQL schema to use when generating the handler
395
+ * @param {string} input.operationId The operationId to use when generating the handler
396
+ * @param {object} input.handlerOptions The options to use when generating the handler
397
+ * @param {(message: string) => void=} input.logger A function that if provided will be used to log messages
381
398
  * @returns
382
399
  */
383
- const generateHandlerByOperationId = (netlifyGraphConfig, schema, operationId, handlerOptions) => {
400
+ const generateHandlerByOperationId = ({ handlerOptions, logger, netlifyGraphConfig, operationId, schema }) => {
384
401
  let currentOperationsDoc = readGraphQLOperationsSourceFile(netlifyGraphConfig)
385
402
  if (currentOperationsDoc.trim().length === 0) {
386
403
  currentOperationsDoc = NetlifyGraph.defaultExampleOperationsDoc
387
404
  }
388
405
 
389
- const payload = {
406
+ const generateHandlerPayload = {
390
407
  handlerOptions,
391
408
  schema,
392
409
  netlifyGraphConfig,
@@ -394,7 +411,7 @@ const generateHandlerByOperationId = (netlifyGraphConfig, schema, operationId, h
394
411
  operationsDoc: currentOperationsDoc,
395
412
  }
396
413
 
397
- const result = NetlifyGraph.generateHandlerSource(payload)
414
+ const result = NetlifyGraph.generateHandlerSource(generateHandlerPayload)
398
415
 
399
416
  if (!result) {
400
417
  warn(`No handler was generated for operationId ${operationId}`)
@@ -434,19 +451,23 @@ const generateHandlerByOperationId = (netlifyGraphConfig, schema, operationId, h
434
451
  const absoluteFilename = path.resolve(...filenameArr)
435
452
 
436
453
  fs.writeFileSync(absoluteFilename, content)
454
+ const relativePath = path.relative(process.cwd(), absoluteFilename)
455
+ logger && logger(`Wrote ${chalk.cyan(relativePath)}`)
437
456
  runPrettier(absoluteFilename)
438
457
  })
439
458
  }
440
459
 
441
460
  /**
442
461
  * Given a NetlifyGraphConfig, read the appropriate files and write a handler for the given operationId to the filesystem
443
- * @param {NetlifyGraph.NetlifyGraphConfig} netlifyGraphConfig
444
- * @param {GraphQL.GraphQLSchema} schema The GraphQL schema to use when generating the handler
445
- * @param {string} operationName The name of the operation to use when generating the handler
446
- * @param {object} handlerOptions The options to use when generating the handler
462
+ * @param {object} input
463
+ * @param {NetlifyGraph.NetlifyGraphConfig} input.netlifyGraphConfig
464
+ * @param {GraphQL.GraphQLSchema} input.schema The GraphQL schema to use when generating the handler
465
+ * @param {string} input.operationName The name of the operation to use when generating the handler
466
+ * @param {object} input.handlerOptions The options to use when generating the handler
467
+ * @param {(message: string) => void=} input.logger A function that if provided will be used to log messages
447
468
  * @returns
448
469
  */
449
- const generateHandlerByOperationName = (netlifyGraphConfig, schema, operationName, handlerOptions) => {
470
+ const generateHandlerByOperationName = ({ handlerOptions, logger, netlifyGraphConfig, operationName, schema }) => {
450
471
  let currentOperationsDoc = readGraphQLOperationsSourceFile(netlifyGraphConfig)
451
472
  if (currentOperationsDoc.trim().length === 0) {
452
473
  currentOperationsDoc = NetlifyGraph.defaultExampleOperationsDoc
@@ -464,7 +485,7 @@ const generateHandlerByOperationName = (netlifyGraphConfig, schema, operationNam
464
485
  return
465
486
  }
466
487
 
467
- generateHandlerByOperationId(netlifyGraphConfig, schema, operation.id, handlerOptions)
488
+ generateHandlerByOperationId({ logger, netlifyGraphConfig, schema, operationId: operation.id, handlerOptions })
468
489
  }
469
490
 
470
491
  // Export the minimal set of functions that are required for Netlify Graph