netlify-cli 10.0.0 → 10.1.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/npm-shrinkwrap.json +57 -2
- package/package.json +3 -1
- package/src/commands/dev/dev.js +34 -8
- package/src/lib/edge-functions/headers.js +1 -0
- package/src/lib/edge-functions/proxy.js +30 -13
- package/src/lib/edge-functions/registry.js +43 -1
- package/src/lib/geo-location.js +99 -0
- package/src/utils/proxy.js +14 -1
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.1.0",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "netlify-cli",
|
|
9
|
-
"version": "10.
|
|
9
|
+
"version": "10.1.0",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
@@ -138,6 +138,7 @@
|
|
|
138
138
|
"husky": "^7.0.4",
|
|
139
139
|
"ini": "^2.0.0",
|
|
140
140
|
"mock-fs": "^5.1.2",
|
|
141
|
+
"nock": "^13.2.4",
|
|
141
142
|
"p-timeout": "^4.0.0",
|
|
142
143
|
"rewiremock": "^3.14.3",
|
|
143
144
|
"seedrandom": "^3.0.5",
|
|
@@ -14405,6 +14406,12 @@
|
|
|
14405
14406
|
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
|
14406
14407
|
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
|
|
14407
14408
|
},
|
|
14409
|
+
"node_modules/lodash.set": {
|
|
14410
|
+
"version": "4.3.2",
|
|
14411
|
+
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
|
|
14412
|
+
"integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=",
|
|
14413
|
+
"dev": true
|
|
14414
|
+
},
|
|
14408
14415
|
"node_modules/lodash.some": {
|
|
14409
14416
|
"version": "4.6.0",
|
|
14410
14417
|
"resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
|
|
@@ -15831,6 +15838,21 @@
|
|
|
15831
15838
|
"isarray": "0.0.1"
|
|
15832
15839
|
}
|
|
15833
15840
|
},
|
|
15841
|
+
"node_modules/nock": {
|
|
15842
|
+
"version": "13.2.4",
|
|
15843
|
+
"resolved": "https://registry.npmjs.org/nock/-/nock-13.2.4.tgz",
|
|
15844
|
+
"integrity": "sha512-8GPznwxcPNCH/h8B+XZcKjYPXnUV5clOKCjAqyjsiqA++MpNx9E9+t8YPp0MbThO+KauRo7aZJ1WuIZmOrT2Ug==",
|
|
15845
|
+
"dev": true,
|
|
15846
|
+
"dependencies": {
|
|
15847
|
+
"debug": "^4.1.0",
|
|
15848
|
+
"json-stringify-safe": "^5.0.1",
|
|
15849
|
+
"lodash.set": "^4.3.2",
|
|
15850
|
+
"propagate": "^2.0.0"
|
|
15851
|
+
},
|
|
15852
|
+
"engines": {
|
|
15853
|
+
"node": ">= 10.13"
|
|
15854
|
+
}
|
|
15855
|
+
},
|
|
15834
15856
|
"node_modules/node-domexception": {
|
|
15835
15857
|
"version": "1.0.0",
|
|
15836
15858
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
|
@@ -18235,6 +18257,15 @@
|
|
|
18235
18257
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
|
18236
18258
|
"dev": true
|
|
18237
18259
|
},
|
|
18260
|
+
"node_modules/propagate": {
|
|
18261
|
+
"version": "2.0.1",
|
|
18262
|
+
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
|
|
18263
|
+
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
|
|
18264
|
+
"dev": true,
|
|
18265
|
+
"engines": {
|
|
18266
|
+
"node": ">= 8"
|
|
18267
|
+
}
|
|
18268
|
+
},
|
|
18238
18269
|
"node_modules/proxy-addr": {
|
|
18239
18270
|
"version": "2.0.7",
|
|
18240
18271
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
|
@@ -33416,6 +33447,12 @@
|
|
|
33416
33447
|
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
|
33417
33448
|
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
|
|
33418
33449
|
},
|
|
33450
|
+
"lodash.set": {
|
|
33451
|
+
"version": "4.3.2",
|
|
33452
|
+
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
|
|
33453
|
+
"integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=",
|
|
33454
|
+
"dev": true
|
|
33455
|
+
},
|
|
33419
33456
|
"lodash.some": {
|
|
33420
33457
|
"version": "4.6.0",
|
|
33421
33458
|
"resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
|
|
@@ -34486,6 +34523,18 @@
|
|
|
34486
34523
|
}
|
|
34487
34524
|
}
|
|
34488
34525
|
},
|
|
34526
|
+
"nock": {
|
|
34527
|
+
"version": "13.2.4",
|
|
34528
|
+
"resolved": "https://registry.npmjs.org/nock/-/nock-13.2.4.tgz",
|
|
34529
|
+
"integrity": "sha512-8GPznwxcPNCH/h8B+XZcKjYPXnUV5clOKCjAqyjsiqA++MpNx9E9+t8YPp0MbThO+KauRo7aZJ1WuIZmOrT2Ug==",
|
|
34530
|
+
"dev": true,
|
|
34531
|
+
"requires": {
|
|
34532
|
+
"debug": "^4.1.0",
|
|
34533
|
+
"json-stringify-safe": "^5.0.1",
|
|
34534
|
+
"lodash.set": "^4.3.2",
|
|
34535
|
+
"propagate": "^2.0.0"
|
|
34536
|
+
}
|
|
34537
|
+
},
|
|
34489
34538
|
"node-domexception": {
|
|
34490
34539
|
"version": "1.0.0",
|
|
34491
34540
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
|
@@ -36300,6 +36349,12 @@
|
|
|
36300
36349
|
}
|
|
36301
36350
|
}
|
|
36302
36351
|
},
|
|
36352
|
+
"propagate": {
|
|
36353
|
+
"version": "2.0.1",
|
|
36354
|
+
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
|
|
36355
|
+
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
|
|
36356
|
+
"dev": true
|
|
36357
|
+
},
|
|
36303
36358
|
"proxy-addr": {
|
|
36304
36359
|
"version": "2.0.7",
|
|
36305
36360
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
3
|
"description": "Netlify command line tool",
|
|
4
|
-
"version": "10.
|
|
4
|
+
"version": "10.1.0",
|
|
5
5
|
"author": "Netlify Inc.",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Abraham Schilling <AbrahamSchilling@gmail.com> (https://gitlab.com/n4bb12)",
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
"Sam Holmes <samholmes1337@gmail.com> (https://samholmes.net)",
|
|
104
104
|
"Sander de Groot (https://degroot.dev)",
|
|
105
105
|
"Sarah Drasner <sarah.drasner@gmail.com> (https://twitter.com/sarah_edo)",
|
|
106
|
+
"Sarah Etter <sarah@sarahetter.com> (http://www.sarahetter.com)",
|
|
106
107
|
"Scott Spence <spences10apps@gmail.com> (https://twitter.com/spences10)",
|
|
107
108
|
"Sean Grove <sean@bushi.do> (https://twitter.com/sgrove)",
|
|
108
109
|
"Sebastian Smolorz",
|
|
@@ -330,6 +331,7 @@
|
|
|
330
331
|
"husky": "^7.0.4",
|
|
331
332
|
"ini": "^2.0.0",
|
|
332
333
|
"mock-fs": "^5.1.2",
|
|
334
|
+
"nock": "^13.2.4",
|
|
333
335
|
"p-timeout": "^4.0.0",
|
|
334
336
|
"rewiremock": "^3.14.3",
|
|
335
337
|
"seedrandom": "^3.0.5",
|
package/src/commands/dev/dev.js
CHANGED
|
@@ -201,18 +201,33 @@ const FRAMEWORK_PORT_TIMEOUT = 6e5
|
|
|
201
201
|
* @param {*} params.addonsUrls
|
|
202
202
|
* @param {import('../base-command').NetlifyOptions["config"]} params.config
|
|
203
203
|
* @param {() => Promise<object>} params.getUpdatedConfig
|
|
204
|
+
* @param {string} params.geolocationMode
|
|
204
205
|
* @param {*} params.settings
|
|
206
|
+
* @param {boolean} params.offline
|
|
205
207
|
* @param {*} params.site
|
|
208
|
+
* @param {import('../../utils/state-config').StateConfig} params.state
|
|
206
209
|
* @returns
|
|
207
210
|
*/
|
|
208
|
-
const startProxyServer = async ({
|
|
211
|
+
const startProxyServer = async ({
|
|
212
|
+
addonsUrls,
|
|
213
|
+
config,
|
|
214
|
+
geolocationMode,
|
|
215
|
+
getUpdatedConfig,
|
|
216
|
+
offline,
|
|
217
|
+
settings,
|
|
218
|
+
site,
|
|
219
|
+
state,
|
|
220
|
+
}) => {
|
|
209
221
|
const url = await startProxy({
|
|
210
222
|
addonsUrls,
|
|
211
223
|
config,
|
|
212
224
|
configPath: site.configPath,
|
|
225
|
+
geolocationMode,
|
|
213
226
|
getUpdatedConfig,
|
|
227
|
+
offline,
|
|
214
228
|
projectDir: site.root,
|
|
215
229
|
settings,
|
|
230
|
+
state,
|
|
216
231
|
})
|
|
217
232
|
|
|
218
233
|
if (!url) {
|
|
@@ -365,7 +380,16 @@ const dev = async (options, command) => {
|
|
|
365
380
|
return normalizedNewConfig
|
|
366
381
|
}
|
|
367
382
|
|
|
368
|
-
let url = await startProxyServer({
|
|
383
|
+
let url = await startProxyServer({
|
|
384
|
+
addonsUrls,
|
|
385
|
+
config,
|
|
386
|
+
geolocationMode: options.geo,
|
|
387
|
+
getUpdatedConfig,
|
|
388
|
+
offline: options.offline,
|
|
389
|
+
settings,
|
|
390
|
+
site,
|
|
391
|
+
state,
|
|
392
|
+
})
|
|
369
393
|
|
|
370
394
|
const liveTunnelUrl = await handleLiveTunnel({ options, site, api, settings })
|
|
371
395
|
url = liveTunnelUrl || url
|
|
@@ -484,17 +508,19 @@ const createDevCommand = (program) => {
|
|
|
484
508
|
.option('-o ,--offline', 'disables any features that require network access')
|
|
485
509
|
.option('-l, --live', 'start a public live session', false)
|
|
486
510
|
.option('--functionsPort <port>', 'port of functions server', (value) => Number.parseInt(value))
|
|
511
|
+
.addOption(
|
|
512
|
+
new Option(
|
|
513
|
+
'--geo <mode>',
|
|
514
|
+
'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location',
|
|
515
|
+
)
|
|
516
|
+
.choices(['cache', 'mock', 'update'])
|
|
517
|
+
.default('cache'),
|
|
518
|
+
)
|
|
487
519
|
.addOption(
|
|
488
520
|
new Option('--staticServerPort <port>', 'port of the static app server used when no framework is detected')
|
|
489
521
|
.argParser((value) => Number.parseInt(value))
|
|
490
522
|
.hideHelp(),
|
|
491
523
|
)
|
|
492
|
-
.addOption(
|
|
493
|
-
new Option(
|
|
494
|
-
'-g ,--locationDb <path>',
|
|
495
|
-
'specify the path to a local GeoIP location database in MMDB format',
|
|
496
|
-
).hideHelp(),
|
|
497
|
-
)
|
|
498
524
|
.addOption(new Option('--graph', 'enable Netlify Graph support').hideHelp())
|
|
499
525
|
.addExamples([
|
|
500
526
|
'netlify dev',
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
const {
|
|
2
|
+
const { relative } = require('path')
|
|
3
|
+
const { cwd, env } = require('process')
|
|
3
4
|
|
|
4
5
|
const getAvailablePort = require('get-port')
|
|
5
6
|
const { v4: generateUUID } = require('uuid')
|
|
6
7
|
|
|
7
|
-
const { NETLIFYDEVERR, chalk } = require('../../utils/command-helpers')
|
|
8
|
+
const { NETLIFYDEVERR, NETLIFYDEVWARN, chalk, log } = require('../../utils/command-helpers')
|
|
9
|
+
const { getGeoLocation } = require('../geo-location')
|
|
8
10
|
const { getPathInProject } = require('../settings')
|
|
9
11
|
const { startSpinner, stopSpinner } = require('../spinner')
|
|
10
12
|
|
|
@@ -40,7 +42,7 @@ const handleProxyRequest = (req, proxyReq) => {
|
|
|
40
42
|
})
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
const initializeProxy = async ({ config, configPath, getUpdatedConfig, settings }) => {
|
|
45
|
+
const initializeProxy = async ({ config, configPath, geolocationMode, getUpdatedConfig, offline, settings, state }) => {
|
|
44
46
|
const { functions: internalFunctions, importMap, path: internalFunctionsPath } = await getInternalFunctions()
|
|
45
47
|
const { port: mainPort } = settings
|
|
46
48
|
const userFunctionsPath = config.build.edge_functions
|
|
@@ -65,24 +67,39 @@ const initializeProxy = async ({ config, configPath, getUpdatedConfig, settings
|
|
|
65
67
|
return
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
const { registry } = await
|
|
70
|
+
const [geoLocation, { registry }] = await Promise.all([
|
|
71
|
+
getGeoLocation({ mode: geolocationMode, offline, state }),
|
|
72
|
+
server,
|
|
73
|
+
])
|
|
74
|
+
|
|
75
|
+
// Setting header with geolocation.
|
|
76
|
+
req.headers[headers.Geo] = JSON.stringify(geoLocation)
|
|
69
77
|
|
|
70
78
|
await registry.initialize()
|
|
71
79
|
|
|
72
|
-
const manifest = await registry.getManifest()
|
|
73
80
|
const url = new URL(req.url, `http://${LOCAL_HOST}:${mainPort}`)
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
const { functionNames, orphanedDeclarations } = await registry.matchURLPath(url.pathname)
|
|
82
|
+
|
|
83
|
+
// If the request matches a config declaration for an Edge Function without
|
|
84
|
+
// a matching function file, we warn the user.
|
|
85
|
+
orphanedDeclarations.forEach((functionName) => {
|
|
86
|
+
log(
|
|
87
|
+
`${NETLIFYDEVWARN} Request to ${chalk.yellow(
|
|
88
|
+
url.pathname,
|
|
89
|
+
)} matches declaration for edge function ${chalk.yellow(
|
|
90
|
+
functionName,
|
|
91
|
+
)}, but there's no matching function file in ${chalk.yellow(
|
|
92
|
+
relative(cwd(), userFunctionsPath),
|
|
93
|
+
)}. Please visit ${chalk.blue('https://ntl.fyi/edge-create')} for more information.`,
|
|
94
|
+
)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
if (functionNames.length === 0) {
|
|
81
98
|
return
|
|
82
99
|
}
|
|
83
100
|
|
|
84
101
|
req[headersSymbol] = {
|
|
85
|
-
[headers.Functions]:
|
|
102
|
+
[headers.Functions]: functionNames.join(','),
|
|
86
103
|
[headers.PassHost]: `${LOCAL_HOST}:${mainPort}`,
|
|
87
104
|
[headers.Passthrough]: 'passthrough',
|
|
88
105
|
[headers.RequestID]: generateUUID(),
|
|
@@ -158,7 +158,10 @@ class EdgeFunctionsRegistry {
|
|
|
158
158
|
|
|
159
159
|
getDeclarations(config) {
|
|
160
160
|
const { edge_functions: userFunctions = [] } = config
|
|
161
|
-
|
|
161
|
+
|
|
162
|
+
// The order is important, since we want to run user-defined functions
|
|
163
|
+
// before internal functions.
|
|
164
|
+
const declarations = [...userFunctions, ...this.internalFunctions]
|
|
162
165
|
|
|
163
166
|
return declarations
|
|
164
167
|
}
|
|
@@ -224,6 +227,45 @@ class EdgeFunctionsRegistry {
|
|
|
224
227
|
log(`${NETLIFYDEVLOG} ${chalk.magenta('Removed')} edge function ${chalk.yellow(func.name)}`)
|
|
225
228
|
}
|
|
226
229
|
|
|
230
|
+
/**
|
|
231
|
+
* @param {string} urlPath
|
|
232
|
+
*/
|
|
233
|
+
async matchURLPath(urlPath) {
|
|
234
|
+
// `generateManifest` will only include functions for which there is both a
|
|
235
|
+
// function file and a config declaration, but we want to catch cases where
|
|
236
|
+
// a config declaration exists without a matching function file. To do that
|
|
237
|
+
// we compute a list of functions from the declarations (the `path` doesn't
|
|
238
|
+
// really matter) and later on match the resulting routes against the list
|
|
239
|
+
// of functions we have in the registry. Any functions found in the former
|
|
240
|
+
// but not the latter are treated as orphaned declarations.
|
|
241
|
+
const functions = this.declarations.map((declaration) => ({ name: declaration.function, path: '' }))
|
|
242
|
+
const manifest = await this.bundler.generateManifest({
|
|
243
|
+
declarations: this.declarations,
|
|
244
|
+
functions,
|
|
245
|
+
})
|
|
246
|
+
const routes = manifest.routes.map((route) => ({
|
|
247
|
+
...route,
|
|
248
|
+
pattern: new RegExp(route.pattern),
|
|
249
|
+
}))
|
|
250
|
+
const orphanedDeclarations = new Set()
|
|
251
|
+
const functionNames = routes
|
|
252
|
+
.filter(({ pattern }) => pattern.test(urlPath))
|
|
253
|
+
.map((route) => {
|
|
254
|
+
const matchingFunction = this.functions.find(({ name }) => name === route.function)
|
|
255
|
+
|
|
256
|
+
if (matchingFunction === undefined) {
|
|
257
|
+
orphanedDeclarations.add(route.function)
|
|
258
|
+
|
|
259
|
+
return null
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return matchingFunction.name
|
|
263
|
+
})
|
|
264
|
+
.filter(Boolean)
|
|
265
|
+
|
|
266
|
+
return { functionNames, orphanedDeclarations }
|
|
267
|
+
}
|
|
268
|
+
|
|
227
269
|
processGraph(graph) {
|
|
228
270
|
if (!graph) {
|
|
229
271
|
warn('Could not process edge functions dependency graph. Live reload will not be available.')
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const fetch = require('node-fetch')
|
|
3
|
+
|
|
4
|
+
const API_URL = 'https://netlifind.netlify.app'
|
|
5
|
+
const STATE_GEO_PROPERTY = 'geolocation'
|
|
6
|
+
|
|
7
|
+
// 24 hours
|
|
8
|
+
const CACHE_TTL = 8.64e7
|
|
9
|
+
|
|
10
|
+
// 10 seconds
|
|
11
|
+
const REQUEST_TIMEOUT = 1e4
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef GeoLocation
|
|
15
|
+
* @type {object}
|
|
16
|
+
* @property {string} city
|
|
17
|
+
* @property {object} country
|
|
18
|
+
* @property {string} country.code
|
|
19
|
+
* @property {string} country.name
|
|
20
|
+
* @property {object} country
|
|
21
|
+
* @property {string} country.code
|
|
22
|
+
* @property {string} country.name
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// The default location to be used if we're unable to talk to the API.
|
|
26
|
+
const mockLocation = {
|
|
27
|
+
city: 'San Francisco',
|
|
28
|
+
country: { code: 'US', name: 'United States' },
|
|
29
|
+
subdivision: { code: 'CA', name: 'California' },
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns geolocation data from a remote API, the local cache, or a mock
|
|
34
|
+
* location, depending on the mode selected.
|
|
35
|
+
*
|
|
36
|
+
* @param {object} params
|
|
37
|
+
* @param {string} params.geolocationMode
|
|
38
|
+
* @param {"cache"|"update"|"mock"} params.mode
|
|
39
|
+
* @param {boolean} params.offline
|
|
40
|
+
* @param {import('../utils/state-config').StateConfig} params.state
|
|
41
|
+
* @returns {Promise<GeoLocation>}
|
|
42
|
+
*/
|
|
43
|
+
const getGeoLocation = async ({ mode, offline, state }) => {
|
|
44
|
+
const cacheObject = state.get(STATE_GEO_PROPERTY)
|
|
45
|
+
|
|
46
|
+
// If we have cached geolocation data and the `--geo` option is set to
|
|
47
|
+
// `cache`, let's try to use it.
|
|
48
|
+
if (cacheObject !== undefined && mode === 'cache') {
|
|
49
|
+
const age = Date.now() - cacheObject.timestamp
|
|
50
|
+
|
|
51
|
+
// Let's use the cached data if it's not older than the TTL. Also, if the
|
|
52
|
+
// `--offline` option was used, it's best to use the cached location than
|
|
53
|
+
// the mock one.
|
|
54
|
+
if (age < CACHE_TTL || offline) {
|
|
55
|
+
return cacheObject.data
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// If the `--geo` option is set to `mock`, we use the mock location. Also,
|
|
60
|
+
// if the `--offline` option was used, we can't talk to the API, so let's
|
|
61
|
+
// also use the mock location.
|
|
62
|
+
if (mode === 'mock' || offline) {
|
|
63
|
+
return mockLocation
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Trying to retrieve geolocation data from the API and caching it locally.
|
|
67
|
+
try {
|
|
68
|
+
const data = await getGeoLocationFromAPI()
|
|
69
|
+
const newCacheObject = {
|
|
70
|
+
data,
|
|
71
|
+
timestamp: Date.now(),
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
state.set(STATE_GEO_PROPERTY, newCacheObject)
|
|
75
|
+
|
|
76
|
+
return data
|
|
77
|
+
} catch {
|
|
78
|
+
// We couldn't get geolocation data from the API, so let's return the
|
|
79
|
+
// mock location.
|
|
80
|
+
return mockLocation
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Returns geolocation data from a remote API
|
|
86
|
+
*
|
|
87
|
+
* @returns {Promise<GeoLocation>}
|
|
88
|
+
*/
|
|
89
|
+
const getGeoLocationFromAPI = async () => {
|
|
90
|
+
const res = await fetch(API_URL, {
|
|
91
|
+
method: 'GET',
|
|
92
|
+
timeout: REQUEST_TIMEOUT,
|
|
93
|
+
})
|
|
94
|
+
const { geo } = await res.json()
|
|
95
|
+
|
|
96
|
+
return geo
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = { getGeoLocation, mockLocation }
|
package/src/utils/proxy.js
CHANGED
|
@@ -461,13 +461,26 @@ const onRequest = async ({ addonsUrls, edgeFunctionsProxy, functionsServer, prox
|
|
|
461
461
|
proxy.web(req, res, options)
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
-
const startProxy = async function ({
|
|
464
|
+
const startProxy = async function ({
|
|
465
|
+
addonsUrls,
|
|
466
|
+
config,
|
|
467
|
+
configPath,
|
|
468
|
+
geolocationMode,
|
|
469
|
+
getUpdatedConfig,
|
|
470
|
+
offline,
|
|
471
|
+
projectDir,
|
|
472
|
+
settings,
|
|
473
|
+
state,
|
|
474
|
+
}) {
|
|
465
475
|
const functionsServer = settings.functionsPort ? `http://localhost:${settings.functionsPort}` : null
|
|
466
476
|
const edgeFunctionsProxy = await edgeFunctions.initializeProxy({
|
|
467
477
|
config,
|
|
468
478
|
configPath,
|
|
479
|
+
geolocationMode,
|
|
469
480
|
getUpdatedConfig,
|
|
481
|
+
offline,
|
|
470
482
|
settings,
|
|
483
|
+
state,
|
|
471
484
|
})
|
|
472
485
|
const proxy = await initializeProxy({
|
|
473
486
|
port: settings.frameworkPort,
|