netlify-cli 8.15.1 → 8.15.5

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,23 +1,23 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
- "version": "8.15.1",
3
+ "version": "8.15.5",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "netlify-cli",
9
- "version": "8.15.1",
9
+ "version": "8.15.5",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
13
- "@netlify/build": "^26.2.0",
13
+ "@netlify/build": "^26.2.3",
14
14
  "@netlify/config": "^17.0.6",
15
15
  "@netlify/framework-info": "^9.0.0",
16
16
  "@netlify/local-functions-proxy": "^1.1.1",
17
17
  "@netlify/plugin-edge-handlers": "^3.0.4",
18
- "@netlify/plugins-list": "^6.3.1",
18
+ "@netlify/plugins-list": "^6.7.0",
19
19
  "@netlify/routing-local-proxy": "^0.34.1",
20
- "@netlify/zip-it-and-ship-it": "^5.5.0",
20
+ "@netlify/zip-it-and-ship-it": "^5.5.2",
21
21
  "@octokit/rest": "^18.0.0",
22
22
  "@sindresorhus/slugify": "^1.1.0",
23
23
  "ansi-escapes": "^5.0.0",
@@ -70,7 +70,7 @@
70
70
  "is-wsl": "^2.2.0",
71
71
  "isexe": "^2.0.0",
72
72
  "jwt-decode": "^3.0.0",
73
- "lambda-local": "2.0.0",
73
+ "lambda-local": "2.0.1",
74
74
  "listr": "^0.14.3",
75
75
  "locate-path": "^6.0.0",
76
76
  "lodash": "^4.17.20",
@@ -81,7 +81,7 @@
81
81
  "multiparty": "^4.2.1",
82
82
  "netlify": "^10.1.2",
83
83
  "netlify-headers-parser": "^6.0.1",
84
- "netlify-onegraph-internal": "0.0.16",
84
+ "netlify-onegraph-internal": "0.0.18",
85
85
  "netlify-redirect-parser": "^13.0.1",
86
86
  "netlify-redirector": "^0.2.1",
87
87
  "node-fetch": "^2.6.0",
@@ -140,7 +140,7 @@
140
140
  "proxyquire": "^2.1.3",
141
141
  "seedrandom": "^3.0.5",
142
142
  "serialize-javascript": "^6.0.0",
143
- "sinon": "^12.0.0",
143
+ "sinon": "^13.0.0",
144
144
  "sort-on": "^4.1.0",
145
145
  "strip-ansi": "^6.0.0",
146
146
  "supertest": "^6.1.6",
@@ -148,7 +148,7 @@
148
148
  "tomlify-j0.4": "^3.0.0",
149
149
  "tree-kill": "^1.2.2",
150
150
  "typescript": "^4.4.4",
151
- "verdaccio": "^5.5.2"
151
+ "verdaccio": "^5.4.0"
152
152
  },
153
153
  "engines": {
154
154
  "node": "^12.20.0 || ^14.14.0 || >=16.0.0"
@@ -2313,9 +2313,9 @@
2313
2313
  }
2314
2314
  },
2315
2315
  "node_modules/@netlify/build": {
2316
- "version": "26.2.0",
2317
- "resolved": "https://registry.npmjs.org/@netlify/build/-/build-26.2.0.tgz",
2318
- "integrity": "sha512-2yNzdO0nCRIZ5TLB7WUlis2NTSonVjairWnd1s/Tt9SBF3L3Z+IU/xSiXgAwYZ/xe+tkziUltwrx9l8rxm2VGw==",
2316
+ "version": "26.2.3",
2317
+ "resolved": "https://registry.npmjs.org/@netlify/build/-/build-26.2.3.tgz",
2318
+ "integrity": "sha512-cD6RKntGoEjDjixA78hvnk5k1QfEmiR8gARV9BwRAbyKyK7zNAr6w8/5gLhj9eWP8O/p2YjF67Xii93sgOwhrw==",
2319
2319
  "dependencies": {
2320
2320
  "@bugsnag/js": "^7.0.0",
2321
2321
  "@netlify/cache-utils": "^4.0.0",
@@ -2323,9 +2323,9 @@
2323
2323
  "@netlify/functions-utils": "^4.0.0",
2324
2324
  "@netlify/git-utils": "^4.0.0",
2325
2325
  "@netlify/plugin-edge-handlers": "^3.0.4",
2326
- "@netlify/plugins-list": "^6.3.0",
2326
+ "@netlify/plugins-list": "^6.6.0",
2327
2327
  "@netlify/run-utils": "^4.0.0",
2328
- "@netlify/zip-it-and-ship-it": "^5.5.0",
2328
+ "@netlify/zip-it-and-ship-it": "5.5.2",
2329
2329
  "@sindresorhus/slugify": "^1.1.0",
2330
2330
  "@types/node": "^16.0.0",
2331
2331
  "ansi-escapes": "^4.3.2",
@@ -2911,9 +2911,9 @@
2911
2911
  }
2912
2912
  },
2913
2913
  "node_modules/@netlify/plugins-list": {
2914
- "version": "6.3.1",
2915
- "resolved": "https://registry.npmjs.org/@netlify/plugins-list/-/plugins-list-6.3.1.tgz",
2916
- "integrity": "sha512-6yAYBSELlg3oROgrFt1OCa5QwhINfkoBM2rv2Bpo7T5guwsCsEw7vI/O6nMLNDs6wGUyN43cjv2HTxaJBM/i4A==",
2914
+ "version": "6.7.0",
2915
+ "resolved": "https://registry.npmjs.org/@netlify/plugins-list/-/plugins-list-6.7.0.tgz",
2916
+ "integrity": "sha512-5+KKvsfg+lWiwQddLCNPv7pL1CiwKIT0M1GE8RuIokAq8DE+c8Ug2PC7seslRM5C5gGQiv60MfCpiFuwY6diQg==",
2917
2917
  "engines": {
2918
2918
  "node": "^12.20.0 || ^14.14.0 || >=16.0.0"
2919
2919
  }
@@ -2989,11 +2989,11 @@
2989
2989
  }
2990
2990
  },
2991
2991
  "node_modules/@netlify/zip-it-and-ship-it": {
2992
- "version": "5.5.0",
2993
- "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-5.5.0.tgz",
2994
- "integrity": "sha512-V7hVGr8xwdiPF7kmH+TSvekorjFI/OTYe34dlEvEmPhEuDG3LejRjy2XzQ0hW5TpFXvd4V+JRPH4jMh85Xt6qg==",
2992
+ "version": "5.5.2",
2993
+ "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-5.5.2.tgz",
2994
+ "integrity": "sha512-5uBfXHYarfNeOxrW7JK4rJaq1Xk2be0Ogt/MvLDr0kuKPtPmfHyNrWmr9JlZ1qtR/SuV1t2x22Tj/mxecL8eIQ==",
2995
2995
  "dependencies": {
2996
- "@babel/parser": "^7.15.7",
2996
+ "@babel/parser": "7.16.8",
2997
2997
  "@netlify/esbuild": "^0.13.6",
2998
2998
  "@vercel/nft": "^0.17.0",
2999
2999
  "archiver": "^5.3.0",
@@ -3033,6 +3033,17 @@
3033
3033
  "node": "^12.20.0 || ^14.14.0 || >=16.0.0"
3034
3034
  }
3035
3035
  },
3036
+ "node_modules/@netlify/zip-it-and-ship-it/node_modules/@babel/parser": {
3037
+ "version": "7.16.8",
3038
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz",
3039
+ "integrity": "sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw==",
3040
+ "bin": {
3041
+ "parser": "bin/babel-parser.js"
3042
+ },
3043
+ "engines": {
3044
+ "node": ">=6.0.0"
3045
+ }
3046
+ },
3036
3047
  "node_modules/@netlify/zip-it-and-ship-it/node_modules/get-caller-file": {
3037
3048
  "version": "2.0.5",
3038
3049
  "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -3427,18 +3438,18 @@
3427
3438
  }
3428
3439
  },
3429
3440
  "node_modules/@sinonjs/fake-timers": {
3430
- "version": "8.1.0",
3431
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz",
3432
- "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==",
3441
+ "version": "9.0.0",
3442
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.0.0.tgz",
3443
+ "integrity": "sha512-+shXA2X7KNP7H7qNbQTJ3SA+NQc0pZDSBrdvFSRwF8sAo/ohw+ZQFD8Moc+gnz51+1eRXtEQBpKWPiQ4jsRC/w==",
3433
3444
  "dev": true,
3434
3445
  "dependencies": {
3435
3446
  "@sinonjs/commons": "^1.7.0"
3436
3447
  }
3437
3448
  },
3438
3449
  "node_modules/@sinonjs/samsam": {
3439
- "version": "6.0.2",
3440
- "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.0.2.tgz",
3441
- "integrity": "sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ==",
3450
+ "version": "6.1.1",
3451
+ "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz",
3452
+ "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==",
3442
3453
  "dev": true,
3443
3454
  "dependencies": {
3444
3455
  "@sinonjs/commons": "^1.6.0",
@@ -11144,9 +11155,9 @@
11144
11155
  "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
11145
11156
  },
11146
11157
  "node_modules/graphql": {
11147
- "version": "16.2.0",
11148
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.2.0.tgz",
11149
- "integrity": "sha512-MuQd7XXrdOcmfwuLwC2jNvx0n3rxIuNYOxUtiee5XOmfrWo613ar2U8pE7aHAKh8VwfpifubpD9IP+EdEAEOsA==",
11158
+ "version": "16.3.0",
11159
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.3.0.tgz",
11160
+ "integrity": "sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==",
11150
11161
  "engines": {
11151
11162
  "node": "^12.22.0 || ^14.16.0 || >=16.0.0"
11152
11163
  }
@@ -13230,11 +13241,11 @@
13230
13241
  "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
13231
13242
  },
13232
13243
  "node_modules/lambda-local": {
13233
- "version": "2.0.0",
13234
- "resolved": "https://registry.npmjs.org/lambda-local/-/lambda-local-2.0.0.tgz",
13235
- "integrity": "sha512-5Z7ZEhqVYJSm3djoq7QLDkEk7Ao+jNYbARo3nk3wtjKpgCnEbzOuraxDPDWg7OlZ4JKcsRDP+wNLeORMdbF2ow==",
13244
+ "version": "2.0.1",
13245
+ "resolved": "https://registry.npmjs.org/lambda-local/-/lambda-local-2.0.1.tgz",
13246
+ "integrity": "sha512-21AoIJYuGRPNMCEtxAOa/BP2j0fNY10IVYMQ1pRqDyhSJi5xt4r4IZUqWF40+aYU6TJ1SdB7t5s1BmSq391ILQ==",
13236
13247
  "dependencies": {
13237
- "commander": "^7.2.0",
13248
+ "commander": "^8.3.0",
13238
13249
  "dotenv": "^10.0.0",
13239
13250
  "winston": "^3.3.3"
13240
13251
  },
@@ -13245,14 +13256,6 @@
13245
13256
  "node": ">=6"
13246
13257
  }
13247
13258
  },
13248
- "node_modules/lambda-local/node_modules/commander": {
13249
- "version": "7.2.0",
13250
- "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
13251
- "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
13252
- "engines": {
13253
- "node": ">= 10"
13254
- }
13255
- },
13256
13259
  "node_modules/latest-version": {
13257
13260
  "version": "5.1.0",
13258
13261
  "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
@@ -15017,9 +15020,9 @@
15017
15020
  }
15018
15021
  },
15019
15022
  "node_modules/netlify-onegraph-internal": {
15020
- "version": "0.0.16",
15021
- "resolved": "https://registry.npmjs.org/netlify-onegraph-internal/-/netlify-onegraph-internal-0.0.16.tgz",
15022
- "integrity": "sha512-reQ/C7ztbYCDMXqFLSw0rBwOi866sqdBjagUs6Ug6LXDkCIGHBTjMX0iwNhEn7+/WzV4f1lJj66NhdjF5Q4/aQ==",
15023
+ "version": "0.0.18",
15024
+ "resolved": "https://registry.npmjs.org/netlify-onegraph-internal/-/netlify-onegraph-internal-0.0.18.tgz",
15025
+ "integrity": "sha512-dUODB7zQDj03gwXQZQPlxFAfB1NBAtAt0A/CvWkfieG0g3MuRFAT/TOQGWtFesN1HkRZbW7dnC3JR9S9jB66WQ==",
15023
15026
  "dependencies": {
15024
15027
  "graphql": "16.0.0",
15025
15028
  "node-fetch": "^2.6.0",
@@ -18744,14 +18747,14 @@
18744
18747
  "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
18745
18748
  },
18746
18749
  "node_modules/sinon": {
18747
- "version": "12.0.1",
18748
- "resolved": "https://registry.npmjs.org/sinon/-/sinon-12.0.1.tgz",
18749
- "integrity": "sha512-iGu29Xhym33ydkAT+aNQFBINakjq69kKO6ByPvTsm3yyIACfyQttRTP03aBP/I8GfhFmLzrnKwNNkr0ORb1udg==",
18750
+ "version": "13.0.0",
18751
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.0.tgz",
18752
+ "integrity": "sha512-3tjMDB/tY04b06Bnb4aMKQfNrau2C9HET+R4HVWfv2KegDVLGg4wnBqjVepvxR7S7R1GTwDZzEv52tpFipt6yA==",
18750
18753
  "dev": true,
18751
18754
  "dependencies": {
18752
18755
  "@sinonjs/commons": "^1.8.3",
18753
- "@sinonjs/fake-timers": "^8.1.0",
18754
- "@sinonjs/samsam": "^6.0.2",
18756
+ "@sinonjs/fake-timers": "^9.0.0",
18757
+ "@sinonjs/samsam": "^6.1.1",
18755
18758
  "diff": "^5.0.0",
18756
18759
  "nise": "^5.1.0",
18757
18760
  "supports-color": "^7.2.0"
@@ -23228,9 +23231,9 @@
23228
23231
  }
23229
23232
  },
23230
23233
  "@netlify/build": {
23231
- "version": "26.2.0",
23232
- "resolved": "https://registry.npmjs.org/@netlify/build/-/build-26.2.0.tgz",
23233
- "integrity": "sha512-2yNzdO0nCRIZ5TLB7WUlis2NTSonVjairWnd1s/Tt9SBF3L3Z+IU/xSiXgAwYZ/xe+tkziUltwrx9l8rxm2VGw==",
23234
+ "version": "26.2.3",
23235
+ "resolved": "https://registry.npmjs.org/@netlify/build/-/build-26.2.3.tgz",
23236
+ "integrity": "sha512-cD6RKntGoEjDjixA78hvnk5k1QfEmiR8gARV9BwRAbyKyK7zNAr6w8/5gLhj9eWP8O/p2YjF67Xii93sgOwhrw==",
23234
23237
  "requires": {
23235
23238
  "@bugsnag/js": "^7.0.0",
23236
23239
  "@netlify/cache-utils": "^4.0.0",
@@ -23238,9 +23241,9 @@
23238
23241
  "@netlify/functions-utils": "^4.0.0",
23239
23242
  "@netlify/git-utils": "^4.0.0",
23240
23243
  "@netlify/plugin-edge-handlers": "^3.0.4",
23241
- "@netlify/plugins-list": "^6.3.0",
23244
+ "@netlify/plugins-list": "^6.6.0",
23242
23245
  "@netlify/run-utils": "^4.0.0",
23243
- "@netlify/zip-it-and-ship-it": "^5.5.0",
23246
+ "@netlify/zip-it-and-ship-it": "5.5.2",
23244
23247
  "@sindresorhus/slugify": "^1.1.0",
23245
23248
  "@types/node": "^16.0.0",
23246
23249
  "ansi-escapes": "^4.3.2",
@@ -23630,9 +23633,9 @@
23630
23633
  }
23631
23634
  },
23632
23635
  "@netlify/plugins-list": {
23633
- "version": "6.3.1",
23634
- "resolved": "https://registry.npmjs.org/@netlify/plugins-list/-/plugins-list-6.3.1.tgz",
23635
- "integrity": "sha512-6yAYBSELlg3oROgrFt1OCa5QwhINfkoBM2rv2Bpo7T5guwsCsEw7vI/O6nMLNDs6wGUyN43cjv2HTxaJBM/i4A=="
23636
+ "version": "6.7.0",
23637
+ "resolved": "https://registry.npmjs.org/@netlify/plugins-list/-/plugins-list-6.7.0.tgz",
23638
+ "integrity": "sha512-5+KKvsfg+lWiwQddLCNPv7pL1CiwKIT0M1GE8RuIokAq8DE+c8Ug2PC7seslRM5C5gGQiv60MfCpiFuwY6diQg=="
23636
23639
  },
23637
23640
  "@netlify/routing-local-proxy": {
23638
23641
  "version": "0.34.1",
@@ -23678,11 +23681,11 @@
23678
23681
  }
23679
23682
  },
23680
23683
  "@netlify/zip-it-and-ship-it": {
23681
- "version": "5.5.0",
23682
- "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-5.5.0.tgz",
23683
- "integrity": "sha512-V7hVGr8xwdiPF7kmH+TSvekorjFI/OTYe34dlEvEmPhEuDG3LejRjy2XzQ0hW5TpFXvd4V+JRPH4jMh85Xt6qg==",
23684
+ "version": "5.5.2",
23685
+ "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-5.5.2.tgz",
23686
+ "integrity": "sha512-5uBfXHYarfNeOxrW7JK4rJaq1Xk2be0Ogt/MvLDr0kuKPtPmfHyNrWmr9JlZ1qtR/SuV1t2x22Tj/mxecL8eIQ==",
23684
23687
  "requires": {
23685
- "@babel/parser": "^7.15.7",
23688
+ "@babel/parser": "7.16.8",
23686
23689
  "@netlify/esbuild": "^0.13.6",
23687
23690
  "@vercel/nft": "^0.17.0",
23688
23691
  "archiver": "^5.3.0",
@@ -23716,6 +23719,11 @@
23716
23719
  "yargs": "^16.0.0"
23717
23720
  },
23718
23721
  "dependencies": {
23722
+ "@babel/parser": {
23723
+ "version": "7.16.8",
23724
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz",
23725
+ "integrity": "sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw=="
23726
+ },
23719
23727
  "get-caller-file": {
23720
23728
  "version": "2.0.5",
23721
23729
  "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -24016,18 +24024,18 @@
24016
24024
  }
24017
24025
  },
24018
24026
  "@sinonjs/fake-timers": {
24019
- "version": "8.1.0",
24020
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz",
24021
- "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==",
24027
+ "version": "9.0.0",
24028
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.0.0.tgz",
24029
+ "integrity": "sha512-+shXA2X7KNP7H7qNbQTJ3SA+NQc0pZDSBrdvFSRwF8sAo/ohw+ZQFD8Moc+gnz51+1eRXtEQBpKWPiQ4jsRC/w==",
24022
24030
  "dev": true,
24023
24031
  "requires": {
24024
24032
  "@sinonjs/commons": "^1.7.0"
24025
24033
  }
24026
24034
  },
24027
24035
  "@sinonjs/samsam": {
24028
- "version": "6.0.2",
24029
- "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.0.2.tgz",
24030
- "integrity": "sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ==",
24036
+ "version": "6.1.1",
24037
+ "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.1.1.tgz",
24038
+ "integrity": "sha512-cZ7rKJTLiE7u7Wi/v9Hc2fs3Ucc3jrWeMgPHbbTCeVAB2S0wOBbYlkJVeNSL04i7fdhT8wIbDq1zhC/PXTD2SA==",
24031
24039
  "dev": true,
24032
24040
  "requires": {
24033
24041
  "@sinonjs/commons": "^1.6.0",
@@ -29899,9 +29907,9 @@
29899
29907
  "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
29900
29908
  },
29901
29909
  "graphql": {
29902
- "version": "16.2.0",
29903
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.2.0.tgz",
29904
- "integrity": "sha512-MuQd7XXrdOcmfwuLwC2jNvx0n3rxIuNYOxUtiee5XOmfrWo613ar2U8pE7aHAKh8VwfpifubpD9IP+EdEAEOsA=="
29910
+ "version": "16.3.0",
29911
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.3.0.tgz",
29912
+ "integrity": "sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A=="
29905
29913
  },
29906
29914
  "graphviz": {
29907
29915
  "version": "0.0.9",
@@ -31417,20 +31425,13 @@
31417
31425
  "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
31418
31426
  },
31419
31427
  "lambda-local": {
31420
- "version": "2.0.0",
31421
- "resolved": "https://registry.npmjs.org/lambda-local/-/lambda-local-2.0.0.tgz",
31422
- "integrity": "sha512-5Z7ZEhqVYJSm3djoq7QLDkEk7Ao+jNYbARo3nk3wtjKpgCnEbzOuraxDPDWg7OlZ4JKcsRDP+wNLeORMdbF2ow==",
31428
+ "version": "2.0.1",
31429
+ "resolved": "https://registry.npmjs.org/lambda-local/-/lambda-local-2.0.1.tgz",
31430
+ "integrity": "sha512-21AoIJYuGRPNMCEtxAOa/BP2j0fNY10IVYMQ1pRqDyhSJi5xt4r4IZUqWF40+aYU6TJ1SdB7t5s1BmSq391ILQ==",
31423
31431
  "requires": {
31424
- "commander": "^7.2.0",
31432
+ "commander": "^8.3.0",
31425
31433
  "dotenv": "^10.0.0",
31426
31434
  "winston": "^3.3.3"
31427
- },
31428
- "dependencies": {
31429
- "commander": {
31430
- "version": "7.2.0",
31431
- "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
31432
- "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
31433
- }
31434
31435
  }
31435
31436
  },
31436
31437
  "latest-version": {
@@ -32784,9 +32785,9 @@
32784
32785
  }
32785
32786
  },
32786
32787
  "netlify-onegraph-internal": {
32787
- "version": "0.0.16",
32788
- "resolved": "https://registry.npmjs.org/netlify-onegraph-internal/-/netlify-onegraph-internal-0.0.16.tgz",
32789
- "integrity": "sha512-reQ/C7ztbYCDMXqFLSw0rBwOi866sqdBjagUs6Ug6LXDkCIGHBTjMX0iwNhEn7+/WzV4f1lJj66NhdjF5Q4/aQ==",
32788
+ "version": "0.0.18",
32789
+ "resolved": "https://registry.npmjs.org/netlify-onegraph-internal/-/netlify-onegraph-internal-0.0.18.tgz",
32790
+ "integrity": "sha512-dUODB7zQDj03gwXQZQPlxFAfB1NBAtAt0A/CvWkfieG0g3MuRFAT/TOQGWtFesN1HkRZbW7dnC3JR9S9jB66WQ==",
32790
32791
  "requires": {
32791
32792
  "graphql": "16.0.0",
32792
32793
  "node-fetch": "^2.6.0",
@@ -35632,14 +35633,14 @@
35632
35633
  }
35633
35634
  },
35634
35635
  "sinon": {
35635
- "version": "12.0.1",
35636
- "resolved": "https://registry.npmjs.org/sinon/-/sinon-12.0.1.tgz",
35637
- "integrity": "sha512-iGu29Xhym33ydkAT+aNQFBINakjq69kKO6ByPvTsm3yyIACfyQttRTP03aBP/I8GfhFmLzrnKwNNkr0ORb1udg==",
35636
+ "version": "13.0.0",
35637
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.0.tgz",
35638
+ "integrity": "sha512-3tjMDB/tY04b06Bnb4aMKQfNrau2C9HET+R4HVWfv2KegDVLGg4wnBqjVepvxR7S7R1GTwDZzEv52tpFipt6yA==",
35638
35639
  "dev": true,
35639
35640
  "requires": {
35640
35641
  "@sinonjs/commons": "^1.8.3",
35641
- "@sinonjs/fake-timers": "^8.1.0",
35642
- "@sinonjs/samsam": "^6.0.2",
35642
+ "@sinonjs/fake-timers": "^9.0.0",
35643
+ "@sinonjs/samsam": "^6.1.1",
35643
35644
  "diff": "^5.0.0",
35644
35645
  "nise": "^5.1.0",
35645
35646
  "supports-color": "^7.2.0"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
3
  "description": "Netlify command line tool",
4
- "version": "8.15.1",
4
+ "version": "8.15.5",
5
5
  "author": "Netlify Inc.",
6
6
  "contributors": [
7
7
  "Mathias Biilmann <matt@netlify.com> (https://twitter.com/biilmann)",
@@ -55,17 +55,17 @@
55
55
  "format:check:prettier": "cross-env-shell prettier --check $npm_package_config_prettier",
56
56
  "format:fix:prettier": "cross-env-shell prettier --write $npm_package_config_prettier",
57
57
  "test:dev": "run-s test:init:* test:dev:*",
58
- "test:ci": "run-s test:ci:*",
59
58
  "test:init": "run-s test:init:*",
60
59
  "test:init:cli-version": "npm run start -- --version",
61
60
  "test:init:cli-help": "npm run start -- --help",
62
- "test:init:eleventy-deps": "npm ci --prefix tests/eleventy-site --no-audit",
63
- "test:init:hugo-deps": "npm ci --prefix tests/hugo-site --no-audit",
61
+ "test:init:eleventy-deps": "npm ci --prefix tests/integration/eleventy-site --no-audit",
62
+ "test:init:hugo-deps": "npm ci --prefix tests/integration/hugo-site --no-audit",
64
63
  "test:dev:ava": "ava --verbose",
65
- "test:ci:ava": "c8 -r json ava",
64
+ "test:ci:ava:unit": "c8 -r json ava --no-worker-threads tests/unit/**/*.test.js tools/**/*.test.js",
65
+ "test:ci:ava:integration": "c8 -r json ava --concurrency 1 --no-worker-threads tests/integration/**/*.test.js",
66
66
  "test:affected": "node ./tools/affected-test.js",
67
67
  "e2e": "node ./tools/e2e/run.mjs",
68
- "docs": "node ./site/scripts/docs.js",
68
+ "docs": "node ./site/scripts/docs.mjs",
69
69
  "watch": "c8 --reporter=lcov ava --watch",
70
70
  "site:build": "run-s site:build:*",
71
71
  "site:build:install": "cd site && npm ci --no-audit",
@@ -77,14 +77,14 @@
77
77
  "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\" \"!.github/**/*.md\""
78
78
  },
79
79
  "dependencies": {
80
- "@netlify/build": "^26.2.0",
80
+ "@netlify/build": "^26.2.3",
81
81
  "@netlify/config": "^17.0.6",
82
82
  "@netlify/framework-info": "^9.0.0",
83
83
  "@netlify/local-functions-proxy": "^1.1.1",
84
84
  "@netlify/plugin-edge-handlers": "^3.0.4",
85
- "@netlify/plugins-list": "^6.3.1",
85
+ "@netlify/plugins-list": "^6.7.0",
86
86
  "@netlify/routing-local-proxy": "^0.34.1",
87
- "@netlify/zip-it-and-ship-it": "^5.5.0",
87
+ "@netlify/zip-it-and-ship-it": "^5.5.2",
88
88
  "@octokit/rest": "^18.0.0",
89
89
  "@sindresorhus/slugify": "^1.1.0",
90
90
  "ansi-escapes": "^5.0.0",
@@ -136,8 +136,9 @@
136
136
  "is-plain-obj": "^3.0.0",
137
137
  "is-wsl": "^2.2.0",
138
138
  "isexe": "^2.0.0",
139
+ "jsonwebtoken": "^8.5.1",
139
140
  "jwt-decode": "^3.0.0",
140
- "lambda-local": "2.0.0",
141
+ "lambda-local": "2.0.1",
141
142
  "listr": "^0.14.3",
142
143
  "locate-path": "^6.0.0",
143
144
  "lodash": "^4.17.20",
@@ -148,7 +149,7 @@
148
149
  "multiparty": "^4.2.1",
149
150
  "netlify": "^10.1.2",
150
151
  "netlify-headers-parser": "^6.0.1",
151
- "netlify-onegraph-internal": "0.0.16",
152
+ "netlify-onegraph-internal": "0.0.18",
152
153
  "netlify-redirect-parser": "^13.0.1",
153
154
  "netlify-redirector": "^0.2.1",
154
155
  "node-fetch": "^2.6.0",
@@ -197,13 +198,12 @@
197
198
  "graphviz": "^0.0.9",
198
199
  "husky": "^7.0.4",
199
200
  "ini": "^2.0.0",
200
- "jsonwebtoken": "^8.5.1",
201
201
  "mock-fs": "^5.1.2",
202
202
  "p-timeout": "^4.0.0",
203
203
  "proxyquire": "^2.1.3",
204
204
  "seedrandom": "^3.0.5",
205
205
  "serialize-javascript": "^6.0.0",
206
- "sinon": "^12.0.0",
206
+ "sinon": "^13.0.0",
207
207
  "sort-on": "^4.1.0",
208
208
  "strip-ansi": "^6.0.0",
209
209
  "supertest": "^6.1.6",
@@ -215,10 +215,8 @@
215
215
  },
216
216
  "ava": {
217
217
  "files": [
218
- "site/**/*.test.js",
219
- "src/**/*.test.js",
220
218
  "tools/**/*.test.js",
221
- "tests/*.test.js"
219
+ "tests/**/*.test.js"
222
220
  ],
223
221
  "cache": true,
224
222
  "concurrency": 5,
@@ -22,6 +22,7 @@ const {
22
22
  detectServerSettings,
23
23
  error,
24
24
  exit,
25
+ generateAuthlifyJWT,
25
26
  getSiteInformation,
26
27
  injectEnvVariables,
27
28
  log,
@@ -253,7 +254,29 @@ const dev = async (options, command) => {
253
254
  )
254
255
  }
255
256
 
256
- await injectEnvVariables({ env: command.netlify.cachedConfig.env, site })
257
+ const startNetlifyGraphWatcher = Boolean(options.graph)
258
+ let authlifyJWT
259
+
260
+ if (startNetlifyGraphWatcher) {
261
+ const netlifyToken = await command.authenticate()
262
+ authlifyJWT = generateAuthlifyJWT(netlifyToken, siteInfo.authlify_token_id, site.id)
263
+ }
264
+
265
+ await injectEnvVariables({
266
+ env: Object.assign(
267
+ command.netlify.cachedConfig.env,
268
+ authlifyJWT == null
269
+ ? {}
270
+ : {
271
+ ONEGRAPH_AUTHLIFY_TOKEN: {
272
+ sources: ['general'],
273
+ value: authlifyJWT,
274
+ },
275
+ },
276
+ ),
277
+ site,
278
+ })
279
+
257
280
  const { addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({
258
281
  // inherited from base command --offline
259
282
  offline: options.offline,
@@ -273,8 +296,26 @@ const dev = async (options, command) => {
273
296
 
274
297
  command.setAnalyticsPayload({ projectType: settings.framework || 'custom', live: options.live })
275
298
 
299
+ let configWithAuthlify
300
+
301
+ if (siteInfo.authlify_token_id) {
302
+ const netlifyToken = command.authenticate()
303
+ // Only inject the authlify config if a token ID exists. This prevents
304
+ // calling command.authenticate() (which opens a browser window) if the
305
+ // user hasn't enabled API Authentication
306
+ configWithAuthlify = Object.assign(config, {
307
+ authlify: {
308
+ netlifyToken,
309
+ authlifyTokenId: siteInfo.authlify_token_id,
310
+ siteId: site.id,
311
+ },
312
+ })
313
+ } else {
314
+ configWithAuthlify = config
315
+ }
316
+
276
317
  await startFunctionsServer({
277
- config,
318
+ config: configWithAuthlify,
278
319
  settings,
279
320
  site,
280
321
  siteUrl,
@@ -295,8 +336,6 @@ const dev = async (options, command) => {
295
336
  process.env.URL = url
296
337
  process.env.DEPLOY_URL = url
297
338
 
298
- const startNetlifyGraphWatcher = Boolean(options.graph)
299
-
300
339
  if (startNetlifyGraphWatcher && options.offline) {
301
340
  warn(`Unable to start Netlify Graph in offline mode`)
302
341
  } else if (startNetlifyGraphWatcher && !site.id) {
@@ -3,7 +3,6 @@ const fs = require('fs')
3
3
  const path = require('path')
4
4
  const process = require('process')
5
5
 
6
- const CronParser = require('cron-parser')
7
6
  const inquirer = require('inquirer')
8
7
  const fetch = require('node-fetch')
9
8
 
@@ -131,13 +130,6 @@ const getFunctionToTrigger = function (options, argumentName) {
131
130
  return argumentName
132
131
  }
133
132
 
134
- const getNextRun = function (schedule) {
135
- const cron = CronParser.parseExpression(schedule, {
136
- tz: 'Etc/UTC',
137
- })
138
- return cron.next().toDate()
139
- }
140
-
141
133
  /**
142
134
  * The functions:invoke command
143
135
  * @param {string} nameArgument
@@ -156,7 +148,7 @@ const functionsInvoke = async (nameArgument, options, command) => {
156
148
  console.warn(`${NETLIFYDEVWARN} "port" flag was not specified. Attempting to connect to localhost:8888 by default`)
157
149
  const port = options.port || DEFAULT_PORT
158
150
 
159
- const functions = await getFunctions(functionsDir)
151
+ const functions = await getFunctions(functionsDir, config)
160
152
  const functionToTrigger = await getNameFromArgs(functions, options, nameArgument)
161
153
  const functionObj = functions.find((func) => func.name === functionToTrigger)
162
154
 
@@ -164,10 +156,8 @@ const functionsInvoke = async (nameArgument, options, command) => {
164
156
  let body = {}
165
157
 
166
158
  if (functionObj.schedule) {
167
- body.next_run = getNextRun(functionObj.schedule)
168
159
  headers = {
169
160
  'user-agent': CLOCKWORK_USERAGENT,
170
- 'X-NF-Event': 'schedule',
171
161
  }
172
162
  } else if (eventTriggeredFunctions.has(functionToTrigger)) {
173
163
  /** handle event triggered fns */
@@ -11,4 +11,4 @@ http = "0.2.6"
11
11
  lambda_runtime = "0.4.1"
12
12
  log = "0.4.14"
13
13
  simple_logger = "1.16.0"
14
- tokio = "1.15.0"
14
+ tokio = "1.16.1"
@@ -1,4 +1,6 @@
1
1
  // @ts-check
2
+ const CronParser = require('cron-parser')
3
+
2
4
  const { error: errorExit } = require('../../utils/command-helpers')
3
5
 
4
6
  const BACKGROUND_SUFFIX = '-background'
@@ -6,6 +8,13 @@ const BACKGROUND_SUFFIX = '-background'
6
8
  // Returns a new set with all elements of `setA` that don't exist in `setB`.
7
9
  const difference = (setA, setB) => new Set([...setA].filter((item) => !setB.has(item)))
8
10
 
11
+ const getNextRun = function (schedule) {
12
+ const cron = CronParser.parseExpression(schedule, {
13
+ tz: 'Etc/UTC',
14
+ })
15
+ return cron.next().toDate()
16
+ }
17
+
9
18
  class NetlifyFunction {
10
19
  constructor({
11
20
  config,
@@ -51,6 +60,14 @@ class NetlifyFunction {
51
60
  return Boolean(this.schedule)
52
61
  }
53
62
 
63
+ async getNextRun() {
64
+ if (!(await this.isScheduled())) {
65
+ return null
66
+ }
67
+
68
+ return getNextRun(this.schedule)
69
+ }
70
+
54
71
  // The `build` method transforms source files into invocable functions. Its
55
72
  // return value is an object with:
56
73
  //
@@ -1,7 +1,15 @@
1
1
  // @ts-check
2
2
  const jwtDecode = require('jwt-decode')
3
3
 
4
- const { NETLIFYDEVERR, NETLIFYDEVLOG, error: errorExit, getInternalFunctionsDir, log } = require('../../utils')
4
+ const {
5
+ CLOCKWORK_USERAGENT,
6
+ NETLIFYDEVERR,
7
+ NETLIFYDEVLOG,
8
+ error: errorExit,
9
+ generateAuthlifyJWT,
10
+ getInternalFunctionsDir,
11
+ log,
12
+ } = require('../../utils')
5
13
 
6
14
  const { handleBackgroundFunction, handleBackgroundFunctionResult } = require('./background')
7
15
  const { createFormSubmissionHandler } = require('./form-submissions-handler')
@@ -37,7 +45,7 @@ const buildClientContext = function (headers) {
37
45
  }
38
46
  }
39
47
 
40
- const createHandler = function ({ functionsRegistry }) {
48
+ const createHandler = function ({ config, functionsRegistry }) {
41
49
  return async function handler(request, response) {
42
50
  // handle proxies without path re-writes (http-servr)
43
51
  const cleanPath = request.path.replace(/^\/.netlify\/(functions|builders)/, '')
@@ -98,6 +106,11 @@ const createHandler = function ({ functionsRegistry }) {
98
106
  rawQuery,
99
107
  }
100
108
 
109
+ if (config && config.authlify && config.authlify.authlifyTokenId != null) {
110
+ const { authlifyTokenId, netlifyToken, siteId } = config.authlify
111
+ event.authlifyToken = generateAuthlifyJWT(netlifyToken, authlifyTokenId, siteId)
112
+ }
113
+
101
114
  const clientContext = buildClientContext(request.headers) || {}
102
115
 
103
116
  if (func.isBackground) {
@@ -107,7 +120,21 @@ const createHandler = function ({ functionsRegistry }) {
107
120
 
108
121
  handleBackgroundFunctionResult(functionName, error)
109
122
  } else if (await func.isScheduled()) {
110
- const { error, result } = await func.invoke(event, clientContext)
123
+ const { error, result } = await func.invoke(
124
+ {
125
+ ...event,
126
+ body: JSON.stringify({
127
+ next_run: await func.getNextRun(),
128
+ }),
129
+ isBase64Encoded: false,
130
+ headers: {
131
+ ...event.headers,
132
+ 'user-agent': CLOCKWORK_USERAGENT,
133
+ 'X-NF-Event': 'schedule',
134
+ },
135
+ },
136
+ clientContext,
137
+ )
111
138
 
112
139
  handleScheduledFunction({
113
140
  error,
@@ -133,14 +160,14 @@ const createHandler = function ({ functionsRegistry }) {
133
160
  }
134
161
  }
135
162
 
136
- const getFunctionsServer = function ({ buildersPrefix, functionsPrefix, functionsRegistry, siteUrl }) {
163
+ const getFunctionsServer = function ({ buildersPrefix, config, functionsPrefix, functionsRegistry, siteUrl }) {
137
164
  // performance optimization, load express on demand
138
165
  // eslint-disable-next-line node/global-require
139
166
  const express = require('express')
140
167
  // eslint-disable-next-line node/global-require
141
168
  const expressLogging = require('express-logging')
142
169
  const app = express()
143
- const functionHandler = createHandler({ functionsRegistry })
170
+ const functionHandler = createHandler({ config, functionsRegistry })
144
171
 
145
172
  app.set('query parser', 'simple')
146
173
 
@@ -197,6 +224,7 @@ const startFunctionsServer = async ({
197
224
  await functionsRegistry.scan(functionsDirectories)
198
225
 
199
226
  const server = getFunctionsServer({
227
+ config,
200
228
  functionsRegistry,
201
229
  siteUrl,
202
230
  functionsPrefix,
@@ -138,9 +138,9 @@ const refetchAndGenerateFromOneGraph = async (input) => {
138
138
  }
139
139
 
140
140
  const parsedDoc = parse(currentOperationsDoc)
141
- const operations = extractFunctionsFromOperationDoc(parsedDoc)
141
+ const { fragments, functions } = extractFunctionsFromOperationDoc(parsedDoc)
142
142
 
143
- generateFunctionsFile(netlifyGraphConfig, schema, currentOperationsDoc, operations)
143
+ generateFunctionsFile({ netlifyGraphConfig, schema, operationsDoc: currentOperationsDoc, functions, fragments })
144
144
  writeGraphQLSchemaFile(netlifyGraphConfig, schema)
145
145
  state.set('oneGraphEnabledServices', enabledServices)
146
146
  }
@@ -170,8 +170,8 @@ const updateGraphQLOperationsFile = async (input) => {
170
170
  const parsedDoc = parse(appOperationsDoc, {
171
171
  noLocation: true,
172
172
  })
173
- const operations = extractFunctionsFromOperationDoc(parsedDoc)
174
- generateFunctionsFile(netlifyGraphConfig, schema, appOperationsDoc, operations)
173
+ const { fragments, functions } = extractFunctionsFromOperationDoc(parsedDoc)
174
+ generateFunctionsFile({ netlifyGraphConfig, schema, operationsDoc: appOperationsDoc, functions, fragments })
175
175
  }
176
176
 
177
177
  const handleCliSessionEvent = async ({ event, netlifyGraphConfig, netlifyToken, schema, siteId }) => {
@@ -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,7 +228,8 @@ 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
  /**
@@ -105,22 +237,27 @@ const ensureNetlifyGraphPath = (netlifyGraphConfig) => {
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
 
package/src/utils/dev.js CHANGED
@@ -3,6 +3,7 @@ const process = require('process')
3
3
 
4
4
  const { get } = require('dot-prop')
5
5
  const getPort = require('get-port')
6
+ const jwt = require('jsonwebtoken')
6
7
  const isEmpty = require('lodash/isEmpty')
7
8
 
8
9
  const { supportsBackgroundFunctions } = require('../lib/account')
@@ -193,8 +194,30 @@ const acquirePort = async ({ configuredPort, defaultPort, errorMessage }) => {
193
194
  return acquiredPort
194
195
  }
195
196
 
197
+ // Generates an Authlify JWT with the following claims:
198
+ // - site_id
199
+ // - netlify_token -- the bearer token for the Netlify API
200
+ // - authlify_token_id -- the authlify token ID stored for the site after
201
+ // enabling API Authentication.
202
+ const generateAuthlifyJWT = (netlifyToken, authlifyTokenId, siteId) => {
203
+ const claims = {
204
+ netlify_token: netlifyToken,
205
+ authlify_token_id: authlifyTokenId,
206
+ site_id: siteId,
207
+ }
208
+
209
+ return jwt.sign(
210
+ { 'https://netlify.com/jwt/claims': claims },
211
+ // doesn't matter. OneGraph doesn't check the signature. The presence of
212
+ // the Netlify API bearer token is enough because we've authenticated the
213
+ // user through `command.authenticate()`
214
+ 'NOT_SIGNED',
215
+ )
216
+ }
217
+
196
218
  module.exports = {
197
219
  getSiteInformation,
198
220
  injectEnvVariables,
199
221
  acquirePort,
222
+ generateAuthlifyJWT,
200
223
  }
@@ -13,7 +13,14 @@ const addFunctionProps = ({ mainFile, name, runtime, schedule }) => {
13
13
 
14
14
  const JS = 'js'
15
15
 
16
- const getFunctions = async (functionsSrcDir) => {
16
+ /**
17
+ * @param {Record<string, { schedule?: string }>} functionConfigRecord
18
+ * @returns {Record<string, { schedule?: string }>}
19
+ */
20
+ const extractSchedule = (functionConfigRecord) =>
21
+ Object.fromEntries(Object.entries(functionConfigRecord).map(([name, { schedule }]) => [name, { schedule }]))
22
+
23
+ const getFunctions = async (functionsSrcDir, config = {}) => {
17
24
  if (!(await fileExistsAsync(functionsSrcDir))) {
18
25
  return []
19
26
  }
@@ -22,6 +29,7 @@ const getFunctions = async (functionsSrcDir) => {
22
29
  // eslint-disable-next-line node/global-require
23
30
  const { listFunctions } = require('@netlify/zip-it-and-ship-it')
24
31
  const functions = await listFunctions(functionsSrcDir, {
32
+ config: config.functions ? extractSchedule(config.functions) : undefined,
25
33
  parseISC: true,
26
34
  })
27
35
  const functionsWithProps = functions.filter(({ runtime }) => runtime === JS).map((func) => addFunctionProps(func))
@@ -123,8 +123,8 @@ const getPromptInputs = async ({
123
123
  .map(({ name }) => `${name} plugin`)
124
124
  .map(formatTitle)
125
125
  .join(', ')}${EOL}➡️ OK to install??`,
126
- choices: infos.map(({ name, package }) => ({ name: `${name} plugin`, value: package })),
127
- default: infos.map(({ package }) => package),
126
+ choices: infos.map((info) => ({ name: `${info.name} plugin`, value: info.package })),
127
+ default: infos.map((info) => info.package),
128
128
  },
129
129
  ]
130
130
  }
@@ -11,14 +11,21 @@ const { fileExistsAsync } = require('../lib/fs')
11
11
  const { NETLIFYDEVLOG } = require('./command-helpers')
12
12
  const { parseRedirects } = require('./redirects')
13
13
 
14
+ const watchers = []
15
+
14
16
  const onChanges = function (files, listener) {
15
17
  files.forEach((file) => {
16
18
  const watcher = chokidar.watch(file)
17
19
  watcher.on('change', listener)
18
20
  watcher.on('unlink', listener)
21
+ watchers.push(watcher)
19
22
  })
20
23
  }
21
24
 
25
+ const getWatchers = function () {
26
+ return watchers
27
+ }
28
+
22
29
  const getLanguage = function (headers) {
23
30
  if (headers['accept-language']) {
24
31
  return headers['accept-language'].split(',')[0].slice(0, 2)
@@ -97,4 +104,5 @@ module.exports = {
97
104
  onChanges,
98
105
  getLanguage,
99
106
  createRewriter,
107
+ getWatchers,
100
108
  }