netlify-cli 9.13.6 → 9.16.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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
- "version": "9.13.6",
3
+ "version": "9.16.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "netlify-cli",
9
- "version": "9.13.6",
9
+ "version": "9.16.0",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
@@ -15,7 +15,7 @@
15
15
  "@netlify/framework-info": "^9.0.2",
16
16
  "@netlify/local-functions-proxy": "^1.1.1",
17
17
  "@netlify/plugin-edge-handlers": "^3.0.7",
18
- "@netlify/plugins-list": "^6.17.0",
18
+ "@netlify/plugins-list": "^6.18.1",
19
19
  "@netlify/routing-local-proxy": "^0.34.1",
20
20
  "@netlify/zip-it-and-ship-it": "^5.9.0",
21
21
  "@octokit/rest": "^18.0.0",
@@ -126,7 +126,7 @@
126
126
  },
127
127
  "devDependencies": {
128
128
  "@babel/preset-react": "^7.12.13",
129
- "@netlify/eslint-config-node": "^5.1.7",
129
+ "@netlify/eslint-config-node": "^5.1.8",
130
130
  "ava": "^4.0.0",
131
131
  "c8": "^7.11.0",
132
132
  "eslint-plugin-sort-destructure-keys": "^1.3.5",
@@ -3452,9 +3452,9 @@
3452
3452
  }
3453
3453
  },
3454
3454
  "node_modules/@netlify/eslint-config-node": {
3455
- "version": "5.1.7",
3456
- "resolved": "https://registry.npmjs.org/@netlify/eslint-config-node/-/eslint-config-node-5.1.7.tgz",
3457
- "integrity": "sha512-5s1FtyIsfOru4kmsio3FGdApl8KvJTYeVfOT13f9KW5qeLkQfON8KldaJSJsSqJPC7T0ZELNwTEXrZSMihhtSQ==",
3455
+ "version": "5.1.8",
3456
+ "resolved": "https://registry.npmjs.org/@netlify/eslint-config-node/-/eslint-config-node-5.1.8.tgz",
3457
+ "integrity": "sha512-A1UsNwPXsjryQxBPXGmEynIVaYq4o2VpCiDfkZiIQ0FTXzJv+aBopxwaKBvdE4NgHueLAgpUlWWCJ7Xkt4zN0Q==",
3458
3458
  "dev": true,
3459
3459
  "dependencies": {
3460
3460
  "@babel/core": "^7.13.8",
@@ -4317,9 +4317,9 @@
4317
4317
  }
4318
4318
  },
4319
4319
  "node_modules/@netlify/plugins-list": {
4320
- "version": "6.17.0",
4321
- "resolved": "https://registry.npmjs.org/@netlify/plugins-list/-/plugins-list-6.17.0.tgz",
4322
- "integrity": "sha512-XQMijnVOxbZwkOeSzUZ8Hwon8WIv9uka5R6+mjJs25lcFiTscA8HqHWjhSHf2xPSrcKopJm4BNJZja5YHV3NQg==",
4320
+ "version": "6.18.1",
4321
+ "resolved": "https://registry.npmjs.org/@netlify/plugins-list/-/plugins-list-6.18.1.tgz",
4322
+ "integrity": "sha512-4aAF+lpoBYOIVMuTxge2YNjNKdMxnsV1equq0VtknBW6EGJ9yFiTPyL0NU0MXDWTWk7dNu8tS5+Uw7LN7+sgcg==",
4323
4323
  "engines": {
4324
4324
  "node": "^12.20.0 || ^14.14.0 || >=16.0.0"
4325
4325
  }
@@ -26726,9 +26726,9 @@
26726
26726
  "integrity": "sha512-tiKmDcHM2riSVN79c0mJY/67EBDafXQAMitHuLiCDAMdtz3kfv+NqdVG5krgf5lWR8Uf8AeZrUW5Q9RP25REvw=="
26727
26727
  },
26728
26728
  "@netlify/eslint-config-node": {
26729
- "version": "5.1.7",
26730
- "resolved": "https://registry.npmjs.org/@netlify/eslint-config-node/-/eslint-config-node-5.1.7.tgz",
26731
- "integrity": "sha512-5s1FtyIsfOru4kmsio3FGdApl8KvJTYeVfOT13f9KW5qeLkQfON8KldaJSJsSqJPC7T0ZELNwTEXrZSMihhtSQ==",
26729
+ "version": "5.1.8",
26730
+ "resolved": "https://registry.npmjs.org/@netlify/eslint-config-node/-/eslint-config-node-5.1.8.tgz",
26731
+ "integrity": "sha512-A1UsNwPXsjryQxBPXGmEynIVaYq4o2VpCiDfkZiIQ0FTXzJv+aBopxwaKBvdE4NgHueLAgpUlWWCJ7Xkt4zN0Q==",
26732
26732
  "dev": true,
26733
26733
  "requires": {
26734
26734
  "@babel/core": "^7.13.8",
@@ -27260,9 +27260,9 @@
27260
27260
  }
27261
27261
  },
27262
27262
  "@netlify/plugins-list": {
27263
- "version": "6.17.0",
27264
- "resolved": "https://registry.npmjs.org/@netlify/plugins-list/-/plugins-list-6.17.0.tgz",
27265
- "integrity": "sha512-XQMijnVOxbZwkOeSzUZ8Hwon8WIv9uka5R6+mjJs25lcFiTscA8HqHWjhSHf2xPSrcKopJm4BNJZja5YHV3NQg=="
27263
+ "version": "6.18.1",
27264
+ "resolved": "https://registry.npmjs.org/@netlify/plugins-list/-/plugins-list-6.18.1.tgz",
27265
+ "integrity": "sha512-4aAF+lpoBYOIVMuTxge2YNjNKdMxnsV1equq0VtknBW6EGJ9yFiTPyL0NU0MXDWTWk7dNu8tS5+Uw7LN7+sgcg=="
27266
27266
  },
27267
27267
  "@netlify/routing-local-proxy": {
27268
27268
  "version": "0.34.1",
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.13.6",
4
+ "version": "9.16.0",
5
5
  "author": "Netlify Inc.",
6
6
  "contributors": [
7
7
  "Abraham Schilling <AbrahamSchilling@gmail.com> (https://gitlab.com/n4bb12)",
@@ -30,6 +30,7 @@
30
30
  "Cole Bosmann",
31
31
  "Dan Croak (https://twitter.com/croaky)",
32
32
  "Dan Loewenherz <dan@lionheartsw.com> (https://twitter.com/dwlz)",
33
+ "Daniel Woelfel <dwwoelfel@gmail.com> (https://twitter.com/danielwoelfel)",
33
34
  "Dave Ackerman <dmackerman@gmail.com>",
34
35
  "David Calavera <david@netlify.com> (https://twitter.com/calavera)",
35
36
  "David Lemler <dlemler@pm.me> (https://twitter.com/davidlemlerm)",
@@ -47,7 +48,7 @@
47
48
  "Gergely Nemeth (https://twitter.com/nthgergo)",
48
49
  "HonkingGoose",
49
50
  "Ian Martorell <ianmartorell@gmail.com>",
50
- "Ibrahima",
51
+ "Ibrahima G. Coulibaly",
51
52
  "Jackie Macharia (wangoimacharia.dev)",
52
53
  "Jacob Schatz",
53
54
  "Jake Jarvis <jake@jarv.is> (https://twitter.com/jakejarvis)",
@@ -209,7 +210,7 @@
209
210
  "@netlify/framework-info": "^9.0.2",
210
211
  "@netlify/local-functions-proxy": "^1.1.1",
211
212
  "@netlify/plugin-edge-handlers": "^3.0.7",
212
- "@netlify/plugins-list": "^6.17.0",
213
+ "@netlify/plugins-list": "^6.18.1",
213
214
  "@netlify/routing-local-proxy": "^0.34.1",
214
215
  "@netlify/zip-it-and-ship-it": "^5.9.0",
215
216
  "@octokit/rest": "^18.0.0",
@@ -316,7 +317,7 @@
316
317
  },
317
318
  "devDependencies": {
318
319
  "@babel/preset-react": "^7.12.13",
319
- "@netlify/eslint-config-node": "^5.1.7",
320
+ "@netlify/eslint-config-node": "^5.1.8",
320
321
  "ava": "^4.0.0",
321
322
  "c8": "^7.11.0",
322
323
  "eslint-plugin-sort-destructure-keys": "^1.3.5",
@@ -294,7 +294,9 @@ const startPollingForAPIAuthentication = async function (options) {
294
294
  process.env.ONEGRAPH_AUTHLIFY_TOKEN = netlifyGraphJWT
295
295
  process.env.NETLIFY_GRAPH_TOKEN = netlifyGraphJWT
296
296
  }
297
- } else {
297
+ } else if (!authlifyTokenId) {
298
+ // If there's no `authlifyTokenId`, it's because the user disabled API
299
+ // Auth. Delete the config in this case.
298
300
  delete config.netlifyGraphConfig
299
301
  }
300
302
 
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ name: 'scheduled-function',
3
+ priority: 1,
4
+ description: 'Basic implementation of a scheduled function in Go.',
5
+ }
@@ -0,0 +1,5 @@
1
+ module github.com/your-github-handle/{{name}}
2
+
3
+ go 1.17
4
+
5
+ require github.com/aws/aws-lambda-go v1.28.0
@@ -0,0 +1,21 @@
1
+ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
2
+ github.com/aws/aws-lambda-go v1.28.0 h1:fZiik1PZqW2IyAN4rj+Y0UBaO1IDFlsNo9Zz/XnArK4=
3
+ github.com/aws/aws-lambda-go v1.28.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU=
4
+ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
5
+ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
6
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
8
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
11
+ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
12
+ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
13
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
14
+ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
15
+ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16
+ github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
17
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
18
+ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
19
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
20
+ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
21
+ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -0,0 +1,11 @@
1
+ [build]
2
+ functions = "functions"
3
+
4
+ [build.environment]
5
+ GO_VERSION = "1.17"
6
+
7
+ [functions]
8
+ directory = "src/"
9
+
10
+ [functions.hourly-schedule]
11
+ schedule = "@hourly"
@@ -0,0 +1,36 @@
1
+ package main
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "log"
7
+ "net/http"
8
+ "time"
9
+
10
+ "github.com/aws/aws-lambda-go/events"
11
+ "github.com/aws/aws-lambda-go/lambda"
12
+ )
13
+
14
+ type requestBody struct {
15
+ NextRun time.Time `json:"next_run"`
16
+ }
17
+
18
+ // The schedule for this function is defined inside the netlify.toml file. To learn about scheduled functions
19
+ // and supported cron extensions, visit https://ntl.fyi/sched-func.
20
+ func handler(ctx context.Context, request events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) {
21
+ requestBody := requestBody{}
22
+
23
+ if err := json.Unmarshal([]byte(request.Body), &requestBody); err != nil {
24
+ log.Fatalf("cannot parse request body: %s", err.Error())
25
+ }
26
+
27
+ log.Printf("Next run at %s\n", requestBody.NextRun.Local())
28
+
29
+ return &events.APIGatewayProxyResponse{
30
+ StatusCode: http.StatusNoContent,
31
+ }, nil
32
+ }
33
+
34
+ func main() {
35
+ lambda.Start(handler)
36
+ }
@@ -41,7 +41,9 @@ class NetlifyFunction {
41
41
  // Determines whether this is a background function based on the function
42
42
  // name.
43
43
  this.isBackground = name.endsWith(BACKGROUND_SUFFIX)
44
- this.schedule = null
44
+
45
+ const functionConfig = config.functions && config.functions[name]
46
+ this.schedule = functionConfig && functionConfig.schedule
45
47
 
46
48
  // List of the function's source files. This starts out as an empty set
47
49
  // and will get populated on every build.
@@ -91,7 +93,7 @@ class NetlifyFunction {
91
93
 
92
94
  this.buildData = buildData
93
95
  this.srcFiles = srcFilesSet
94
- this.schedule = schedule
96
+ this.schedule = schedule || this.schedule
95
97
 
96
98
  return { srcFilesDiff }
97
99
  } catch (error) {
@@ -177,6 +177,7 @@ class FunctionsRegistry {
177
177
  buildGoSource: true,
178
178
  buildRustSource: env.NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE === 'true',
179
179
  },
180
+ config: this.config,
180
181
  })
181
182
 
182
183
  // Before registering any functions, we look for any functions that were on
@@ -113,6 +113,7 @@ const createHandler = function (options) {
113
113
  const jwt = generateNetlifyGraphJWT(config.netlifyGraphConfig)
114
114
  event.authlifyToken = jwt
115
115
  event.netlifyGraphToken = jwt
116
+ event.headers['X-Nf-Graph-Token'] = jwt
116
117
  }
117
118
 
118
119
  const clientContext = buildClientContext(request.headers) || {}
@@ -160,7 +161,7 @@ const createHandler = function (options) {
160
161
  return
161
162
  }
162
163
 
163
- handleSynchronousFunction(error, result, response)
164
+ handleSynchronousFunction(error, result, request, response)
164
165
  }
165
166
  }
166
167
  }
@@ -1,5 +1,7 @@
1
1
  // @ts-check
2
2
  const { Buffer } = require('buffer')
3
+ const { readFile } = require('fs').promises
4
+ const { join } = require('path')
3
5
 
4
6
  const { NETLIFYDEVERR } = require('../../utils')
5
7
 
@@ -15,15 +17,15 @@ const addHeaders = (headers, response) => {
15
17
  })
16
18
  }
17
19
 
18
- const handleSynchronousFunction = function (err, result, response) {
20
+ const handleSynchronousFunction = function (err, result, request, response) {
19
21
  if (err) {
20
- return handleErr(err, response)
22
+ return handleErr(err, request, response)
21
23
  }
22
24
 
23
25
  const { error } = validateLambdaResponse(result)
24
26
  if (error) {
25
27
  console.log(`${NETLIFYDEVERR} ${error}`)
26
- return handleErr(error, response)
28
+ return handleErr(error, request, response)
27
29
  }
28
30
 
29
31
  response.statusCode = result.statusCode
@@ -36,14 +38,36 @@ const handleSynchronousFunction = function (err, result, response) {
36
38
  response.end()
37
39
  }
38
40
 
39
- const formatLambdaLocalError = (err) => `${err.errorType}: ${err.errorMessage}\n ${err.stackTrace.join('\n ')}`
41
+ const formatLambdaLocalError = (err, acceptsHtml) =>
42
+ acceptsHtml
43
+ ? JSON.stringify({
44
+ errorType: err.errorType,
45
+ errorMessage: err.errorMessage,
46
+ trace: err.stackTrace,
47
+ })
48
+ : `${err.errorType}: ${err.errorMessage}\n ${err.stackTrace.join('\n ')}`
40
49
 
41
- const handleErr = function (err, response) {
50
+ let errorTemplateFile
51
+
52
+ const renderErrorTemplate = async (errString) => {
53
+ const regexPattern = /<!--@ERROR-DETAILS-->/g
54
+ errorTemplateFile = errorTemplateFile || (await readFile(join(__dirname, './templates/function-error.html'), 'utf-8'))
55
+
56
+ return errorTemplateFile.replace(regexPattern, errString)
57
+ }
58
+
59
+ const processRenderedResponse = async (err, request) => {
60
+ const acceptsHtml = request.headers && request.headers.accept && request.headers.accept.includes('text/html')
61
+ const errorString = typeof err === 'string' ? err : formatLambdaLocalError(err, acceptsHtml)
62
+
63
+ return acceptsHtml ? await renderErrorTemplate(errorString) : errorString
64
+ }
65
+
66
+ const handleErr = async (err, request, response) => {
42
67
  detectAwsSdkError({ err })
43
68
 
44
69
  response.statusCode = 500
45
- const errorString = typeof err === 'string' ? err : formatLambdaLocalError(err)
46
- response.end(errorString)
70
+ response.end(await processRenderedResponse(err, request))
47
71
  }
48
72
 
49
73
  const validateLambdaResponse = (lambdaResponse) => {