netlify-cli 8.0.7 → 8.1.0-rc
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/bin/run +81 -3
- package/npm-shrinkwrap.json +305 -2105
- package/package.json +10 -33
- package/src/commands/addons/addons-auth.js +50 -0
- package/src/commands/addons/addons-config.js +180 -0
- package/src/commands/addons/addons-create.js +129 -0
- package/src/commands/addons/addons-delete.js +59 -0
- package/src/commands/addons/addons-list.js +62 -0
- package/src/commands/addons/addons.js +49 -0
- package/src/commands/addons/index.js +3 -24
- package/src/commands/api/api.js +83 -0
- package/src/commands/api/index.js +5 -0
- package/src/commands/base-command.js +322 -0
- package/src/commands/build/build.js +58 -0
- package/src/commands/build/index.js +3 -61
- package/src/commands/completion/completion.js +18 -0
- package/src/commands/completion/index.js +5 -0
- package/src/commands/{deploy.js → deploy/deploy.js} +306 -278
- package/src/commands/deploy/index.js +5 -0
- package/src/commands/dev/dev-exec.js +39 -0
- package/src/commands/dev/dev-trace.js +50 -0
- package/src/commands/dev/dev.js +349 -0
- package/src/commands/dev/index.js +3 -335
- package/src/commands/env/env-get.js +51 -0
- package/src/commands/env/env-import.js +93 -0
- package/src/commands/env/env-list.js +63 -0
- package/src/commands/env/env-set.js +67 -0
- package/src/commands/env/env-unset.js +66 -0
- package/src/commands/env/env.js +47 -0
- package/src/commands/env/index.js +3 -23
- package/src/commands/functions/functions-build.js +59 -0
- package/src/commands/functions/{create.js → functions-create.js} +133 -94
- package/src/commands/functions/functions-invoke.js +276 -0
- package/src/commands/functions/functions-list.js +107 -0
- package/src/commands/functions/functions-serve.js +63 -0
- package/src/commands/functions/functions.js +53 -0
- package/src/commands/functions/index.js +3 -45
- package/src/commands/index.js +5 -0
- package/src/commands/init/index.js +6 -0
- package/src/commands/{init.js → init/init.js} +79 -68
- package/src/commands/link/index.js +6 -0
- package/src/{utils/link/link-by-prompt.js → commands/link/link.js} +153 -14
- package/src/commands/lm/index.js +3 -19
- package/src/commands/lm/lm-info.js +42 -0
- package/src/commands/lm/lm-install.js +36 -0
- package/src/commands/lm/lm-setup.js +106 -0
- package/src/commands/lm/lm-uninstall.js +25 -0
- package/src/commands/lm/lm.js +39 -0
- package/src/commands/login/index.js +6 -0
- package/src/commands/login/login.js +52 -0
- package/src/commands/logout/index.js +5 -0
- package/src/commands/logout/logout.js +43 -0
- package/src/commands/main.js +117 -0
- package/src/commands/open/index.js +3 -39
- package/src/commands/open/open-admin.js +56 -0
- package/src/commands/open/open-site.js +49 -0
- package/src/commands/open/open.js +42 -0
- package/src/commands/sites/index.js +5 -20
- package/src/commands/sites/sites-create.js +184 -0
- package/src/commands/sites/sites-delete.js +108 -0
- package/src/commands/sites/sites-list.js +89 -0
- package/src/commands/sites/sites.js +36 -0
- package/src/commands/status/index.js +3 -118
- package/src/commands/status/status-hooks.js +73 -0
- package/src/commands/status/status.js +125 -0
- package/src/commands/switch/index.js +5 -0
- package/src/commands/switch/switch.js +50 -0
- package/src/commands/unlink/index.js +5 -0
- package/src/commands/unlink/unlink.js +48 -0
- package/src/commands/watch/index.js +5 -0
- package/src/commands/watch/watch.js +121 -0
- package/src/lib/build.js +21 -7
- package/src/lib/exec-fetcher.js +5 -3
- package/src/lib/fs.js +54 -36
- package/src/lib/functions/background.js +1 -1
- package/src/lib/functions/form-submissions-handler.js +2 -1
- package/src/lib/functions/local-proxy.js +2 -1
- package/src/lib/functions/netlify-function.js +4 -1
- package/src/lib/functions/registry.js +4 -6
- package/src/lib/functions/runtimes/go/index.js +2 -1
- package/src/lib/functions/runtimes/js/builders/netlify-lambda.js +6 -4
- package/src/lib/functions/runtimes/js/builders/zisi.js +3 -3
- package/src/lib/functions/runtimes/rust/index.js +4 -3
- package/src/lib/functions/server.js +2 -3
- package/src/lib/functions/synchronous.js +2 -1
- package/src/lib/functions/utils.js +2 -3
- package/src/lib/functions/watcher.js +1 -0
- package/src/lib/http-agent.js +3 -5
- package/src/lib/log.js +2 -1
- package/src/lib/spinner.js +22 -0
- package/src/utils/addons/diffs/index.js +1 -0
- package/src/utils/addons/diffs/options.js +3 -1
- package/src/utils/addons/prepare.js +13 -6
- package/src/utils/addons/prompts.js +2 -1
- package/src/utils/addons/render.js +3 -1
- package/src/utils/command-helpers.js +156 -43
- package/src/utils/create-stream-promise.js +5 -5
- package/src/utils/deferred.js +1 -0
- package/src/utils/deploy/deploy-site.js +1 -1
- package/src/utils/deploy/index.js +4 -0
- package/src/utils/detect-server-settings.js +10 -12
- package/src/utils/dev.js +18 -10
- package/src/utils/dot-env.js +4 -2
- package/src/utils/{edge-handlers.js → functions/edge-handlers.js} +8 -7
- package/src/utils/functions/functions.js +36 -0
- package/src/utils/{get-functions.js → functions/get-functions.js} +2 -1
- package/src/utils/functions/index.js +8 -26
- package/src/utils/get-global-config.js +3 -2
- package/src/utils/get-repo-data.js +1 -0
- package/src/utils/gh-auth.js +1 -0
- package/src/utils/gitignore.js +7 -5
- package/src/utils/header.js +2 -2
- package/src/utils/headers.js +1 -2
- package/src/utils/index.js +42 -0
- package/src/utils/init/config-github.js +12 -5
- package/src/utils/init/config-manual.js +9 -2
- package/src/utils/init/config.js +13 -7
- package/src/utils/init/frameworks.js +1 -0
- package/src/utils/init/node-version.js +4 -2
- package/src/utils/init/plugins.js +1 -0
- package/src/utils/init/utils.js +10 -6
- package/src/utils/live-tunnel.js +3 -4
- package/src/utils/lm/install.js +10 -15
- package/src/utils/lm/requirements.js +3 -1
- package/src/utils/lm/steps.js +1 -1
- package/src/utils/lm/ui.js +7 -3
- package/src/utils/open-browser.js +8 -2
- package/src/utils/parse-raw-flags.js +4 -4
- package/src/utils/proxy.js +6 -5
- package/src/utils/read-repo-url.js +1 -0
- package/src/utils/redirects.js +2 -2
- package/src/utils/rules-proxy.js +2 -1
- package/src/utils/state-config.js +1 -1
- package/src/utils/telemetry/index.js +2 -113
- package/src/utils/telemetry/request.js +3 -1
- package/src/utils/telemetry/telemetry.js +117 -0
- package/src/utils/telemetry/validation.js +13 -12
- package/src/utils/traffic-mesh.js +3 -3
- package/oclif.manifest.json +0 -1
- package/src/commands/addons/auth.js +0 -42
- package/src/commands/addons/config.js +0 -177
- package/src/commands/addons/create.js +0 -127
- package/src/commands/addons/delete.js +0 -69
- package/src/commands/addons/list.js +0 -54
- package/src/commands/api.js +0 -84
- package/src/commands/dev/exec.js +0 -32
- package/src/commands/dev/trace.js +0 -61
- package/src/commands/env/get.js +0 -44
- package/src/commands/env/import.js +0 -90
- package/src/commands/env/list.js +0 -49
- package/src/commands/env/set.js +0 -64
- package/src/commands/env/unset.js +0 -58
- package/src/commands/functions/build.js +0 -60
- package/src/commands/functions/invoke.js +0 -277
- package/src/commands/functions/list.js +0 -102
- package/src/commands/functions/serve.js +0 -70
- package/src/commands/link.js +0 -133
- package/src/commands/lm/info.js +0 -36
- package/src/commands/lm/install.js +0 -30
- package/src/commands/lm/setup.js +0 -107
- package/src/commands/lm/uninstall.js +0 -17
- package/src/commands/login.js +0 -54
- package/src/commands/logout.js +0 -37
- package/src/commands/open/admin.js +0 -51
- package/src/commands/open/site.js +0 -43
- package/src/commands/sites/create.js +0 -191
- package/src/commands/sites/delete.js +0 -116
- package/src/commands/sites/list.js +0 -84
- package/src/commands/status/hooks.js +0 -60
- package/src/commands/switch.js +0 -44
- package/src/commands/unlink.js +0 -38
- package/src/commands/watch.js +0 -115
- package/src/hooks/init.js +0 -46
- package/src/index.js +0 -25
- package/src/lib/help.js +0 -26
- package/src/utils/chalk.js +0 -16
- package/src/utils/check-command-inputs.js +0 -21
- package/src/utils/command.js +0 -262
- package/src/utils/detect-functions-builder.js +0 -25
- package/src/utils/difference.js +0 -4
- package/src/utils/logo.js +0 -11
- package/src/utils/show-help.js +0 -5
- package/src/utils/telemetry/tracked-command.js +0 -51
|
@@ -1,337 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const process = require('process')
|
|
4
|
-
const { promisify } = require('util')
|
|
1
|
+
const { createDevCommand } = require('./dev')
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const chalk = require('chalk')
|
|
9
|
-
const execa = require('execa')
|
|
10
|
-
const StaticServer = require('static-server')
|
|
11
|
-
const stripAnsiCc = require('strip-ansi-control-characters')
|
|
12
|
-
const waitPort = require('wait-port')
|
|
13
|
-
|
|
14
|
-
const { startFunctionsServer } = require('../../lib/functions/server')
|
|
15
|
-
const Command = require('../../utils/command')
|
|
16
|
-
const { exit, log, warn } = require('../../utils/command-helpers')
|
|
17
|
-
const { detectServerSettings } = require('../../utils/detect-server-settings')
|
|
18
|
-
const { getSiteInformation, injectEnvVariables } = require('../../utils/dev')
|
|
19
|
-
const { startLiveTunnel } = require('../../utils/live-tunnel')
|
|
20
|
-
const { NETLIFYDEV, NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN } = require('../../utils/logo')
|
|
21
|
-
const { openBrowser } = require('../../utils/open-browser')
|
|
22
|
-
const { startProxy } = require('../../utils/proxy')
|
|
23
|
-
const { startForwardProxy } = require('../../utils/traffic-mesh')
|
|
24
|
-
|
|
25
|
-
const startStaticServer = async ({ settings }) => {
|
|
26
|
-
const server = new StaticServer({
|
|
27
|
-
rootPath: settings.dist,
|
|
28
|
-
name: 'netlify-dev',
|
|
29
|
-
port: settings.frameworkPort,
|
|
30
|
-
templates: {
|
|
31
|
-
notFound: path.join(settings.dist, '404.html'),
|
|
32
|
-
},
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
await promisify(server.start.bind(server))()
|
|
36
|
-
log(`\n${NETLIFYDEVLOG} Static server listening to`, settings.frameworkPort)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const isNonExistingCommandError = ({ command, error }) => {
|
|
40
|
-
// `ENOENT` is only returned for non Windows systems
|
|
41
|
-
// See https://github.com/sindresorhus/execa/pull/447
|
|
42
|
-
if (error.code === 'ENOENT') {
|
|
43
|
-
return true
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// if the command is a package manager we let it report the error
|
|
47
|
-
if (['yarn', 'npm'].includes(command)) {
|
|
48
|
-
return false
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// this only works on English versions of Windows
|
|
52
|
-
return (
|
|
53
|
-
typeof error.message === 'string' && error.message.includes('is not recognized as an internal or external command')
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Run a command and pipe stdout, stderr and stdin
|
|
59
|
-
* @param {string} command
|
|
60
|
-
* @param {NodeJS.ProcessEnv} env
|
|
61
|
-
* @returns {execa.ExecaChildProcess<string>}
|
|
62
|
-
*/
|
|
63
|
-
const runCommand = (command, env = {}) => {
|
|
64
|
-
const commandProcess = execa.command(command, {
|
|
65
|
-
preferLocal: true,
|
|
66
|
-
// we use reject=false to avoid rejecting synchronously when the command doesn't exist
|
|
67
|
-
reject: false,
|
|
68
|
-
env,
|
|
69
|
-
// windowsHide needs to be false for child process to terminate properly on Windows
|
|
70
|
-
windowsHide: false,
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
commandProcess.stdout.pipe(stripAnsiCc.stream()).pipe(process.stdout)
|
|
74
|
-
commandProcess.stderr.pipe(stripAnsiCc.stream()).pipe(process.stderr)
|
|
75
|
-
process.stdin.pipe(commandProcess.stdin)
|
|
76
|
-
|
|
77
|
-
// we can't try->await->catch since we don't want to block on the framework server which
|
|
78
|
-
// is a long running process
|
|
79
|
-
// eslint-disable-next-line promise/catch-or-return,promise/prefer-await-to-then
|
|
80
|
-
commandProcess.then(async () => {
|
|
81
|
-
const result = await commandProcess
|
|
82
|
-
const [commandWithoutArgs] = command.split(' ')
|
|
83
|
-
// eslint-disable-next-line promise/always-return
|
|
84
|
-
if (result.failed && isNonExistingCommandError({ command: commandWithoutArgs, error: result })) {
|
|
85
|
-
log(
|
|
86
|
-
NETLIFYDEVERR,
|
|
87
|
-
`Failed running command: ${command}. Please verify ${chalk.magenta(`'${commandWithoutArgs}'`)} exists`,
|
|
88
|
-
)
|
|
89
|
-
} else {
|
|
90
|
-
const errorMessage = result.failed
|
|
91
|
-
? `${NETLIFYDEVERR} ${result.shortMessage}`
|
|
92
|
-
: `${NETLIFYDEVWARN} "${command}" exited with code ${result.exitCode}`
|
|
93
|
-
|
|
94
|
-
log(`${errorMessage}. Shutting down Netlify Dev server`)
|
|
95
|
-
}
|
|
96
|
-
process.exit(1)
|
|
97
|
-
})
|
|
98
|
-
;['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP', 'exit'].forEach((signal) => {
|
|
99
|
-
process.on(signal, () => {
|
|
100
|
-
commandProcess.kill('SIGTERM', { forceKillAfterTimeout: 500 })
|
|
101
|
-
process.exit()
|
|
102
|
-
})
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
return commandProcess
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Start a static server if the `useStaticServer` is provided or a framework specific server
|
|
110
|
-
* @param {object} config
|
|
111
|
-
* @param {import('../../utils/types').ServerSettings} config.settings
|
|
112
|
-
* @returns {Promise<void>}
|
|
113
|
-
*/
|
|
114
|
-
const startFrameworkServer = async function ({ settings }) {
|
|
115
|
-
if (settings.useStaticServer) {
|
|
116
|
-
if (settings.command) {
|
|
117
|
-
runCommand(settings.command, settings.env)
|
|
118
|
-
}
|
|
119
|
-
return await startStaticServer({ settings })
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
log(`${NETLIFYDEVLOG} Starting Netlify Dev with ${settings.framework || 'custom config'}`)
|
|
123
|
-
|
|
124
|
-
runCommand(settings.command, settings.env)
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
const open = await waitPort({
|
|
128
|
-
port: settings.frameworkPort,
|
|
129
|
-
output: 'silent',
|
|
130
|
-
timeout: FRAMEWORK_PORT_TIMEOUT,
|
|
131
|
-
...(settings.pollingStrategies.includes('HTTP') && { protocol: 'http' }),
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
if (!open) {
|
|
135
|
-
throw new Error(`Timed out waiting for port '${settings.frameworkPort}' to be open`)
|
|
136
|
-
}
|
|
137
|
-
} catch {
|
|
138
|
-
log(NETLIFYDEVERR, `Netlify Dev could not connect to localhost:${settings.frameworkPort}.`)
|
|
139
|
-
log(NETLIFYDEVERR, `Please make sure your framework server is running on port ${settings.frameworkPort}`)
|
|
140
|
-
exit(1)
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// 10 minutes
|
|
145
|
-
const FRAMEWORK_PORT_TIMEOUT = 6e5
|
|
146
|
-
|
|
147
|
-
const startProxyServer = async ({ addonsUrls, flags, settings, site }) => {
|
|
148
|
-
let url
|
|
149
|
-
if (flags.edgeHandlers || flags.trafficMesh) {
|
|
150
|
-
url = await startForwardProxy({
|
|
151
|
-
port: settings.port,
|
|
152
|
-
frameworkPort: settings.frameworkPort,
|
|
153
|
-
functionsPort: settings.functionsPort,
|
|
154
|
-
publishDir: settings.dist,
|
|
155
|
-
debug: flags.debug,
|
|
156
|
-
locationDb: flags.locationDb,
|
|
157
|
-
jwtRolesPath: settings.jwtRolePath,
|
|
158
|
-
jwtSecret: settings.jwtSecret,
|
|
159
|
-
})
|
|
160
|
-
if (!url) {
|
|
161
|
-
log(NETLIFYDEVERR, `Unable to start forward proxy on port '${settings.port}'`)
|
|
162
|
-
exit(1)
|
|
163
|
-
}
|
|
164
|
-
} else {
|
|
165
|
-
url = await startProxy(settings, addonsUrls, site.configPath, site.root)
|
|
166
|
-
if (!url) {
|
|
167
|
-
log(NETLIFYDEVERR, `Unable to start proxy server on port '${settings.port}'`)
|
|
168
|
-
exit(1)
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return url
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const handleLiveTunnel = async ({ api, flags, settings, site }) => {
|
|
175
|
-
if (flags.live) {
|
|
176
|
-
const sessionUrl = await startLiveTunnel({
|
|
177
|
-
siteId: site.id,
|
|
178
|
-
netlifyApiToken: api.accessToken,
|
|
179
|
-
localPort: settings.port,
|
|
180
|
-
})
|
|
181
|
-
process.env.BASE_URL = sessionUrl
|
|
182
|
-
return sessionUrl
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const printBanner = ({ url }) => {
|
|
187
|
-
const banner = chalk.bold(`${NETLIFYDEVLOG} Server now ready on ${url}`)
|
|
188
|
-
|
|
189
|
-
log(
|
|
190
|
-
boxen(banner, {
|
|
191
|
-
padding: 1,
|
|
192
|
-
margin: 1,
|
|
193
|
-
align: 'center',
|
|
194
|
-
borderColor: '#00c7b7',
|
|
195
|
-
}),
|
|
196
|
-
)
|
|
3
|
+
module.exports = {
|
|
4
|
+
createDevCommand,
|
|
197
5
|
}
|
|
198
|
-
|
|
199
|
-
class DevCommand extends Command {
|
|
200
|
-
async init() {
|
|
201
|
-
this.commandContext = 'dev'
|
|
202
|
-
await super.init()
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
async run() {
|
|
206
|
-
log(`${NETLIFYDEV}`)
|
|
207
|
-
const { flags } = this.parse(DevCommand)
|
|
208
|
-
const { api, config, site, siteInfo } = this.netlify
|
|
209
|
-
config.dev = { ...config.dev }
|
|
210
|
-
config.build = { ...config.build }
|
|
211
|
-
/** @type {import('./types').DevConfig} */
|
|
212
|
-
const devConfig = {
|
|
213
|
-
framework: '#auto',
|
|
214
|
-
...(config.functionsDirectory && { functions: config.functionsDirectory }),
|
|
215
|
-
...(config.build.publish && { publish: config.build.publish }),
|
|
216
|
-
...config.dev,
|
|
217
|
-
...flags,
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (flags.trafficMesh) {
|
|
221
|
-
warn(
|
|
222
|
-
'--trafficMesh and -t are deprecated and will be removed in the near future. Please use --edgeHandlers or -e instead.',
|
|
223
|
-
)
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
await injectEnvVariables({ env: this.netlify.cachedConfig.env, site })
|
|
227
|
-
const { addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({
|
|
228
|
-
flags,
|
|
229
|
-
api,
|
|
230
|
-
site,
|
|
231
|
-
siteInfo,
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
/** @type {Partial<import('../../utils/types').ServerSettings>} */
|
|
235
|
-
let settings = {}
|
|
236
|
-
try {
|
|
237
|
-
settings = await detectServerSettings(devConfig, flags, site.root)
|
|
238
|
-
} catch (error) {
|
|
239
|
-
log(NETLIFYDEVERR, error.message)
|
|
240
|
-
exit(1)
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
this.setAnalyticsPayload({ projectType: settings.framework || 'custom', live: flags.live })
|
|
244
|
-
|
|
245
|
-
await startFunctionsServer({
|
|
246
|
-
config,
|
|
247
|
-
settings,
|
|
248
|
-
site,
|
|
249
|
-
siteUrl,
|
|
250
|
-
capabilities,
|
|
251
|
-
timeouts,
|
|
252
|
-
})
|
|
253
|
-
await startFrameworkServer({ settings })
|
|
254
|
-
|
|
255
|
-
let url = await startProxyServer({ flags, settings, site, addonsUrls })
|
|
256
|
-
|
|
257
|
-
const liveTunnelUrl = await handleLiveTunnel({ flags, site, api, settings })
|
|
258
|
-
url = liveTunnelUrl || url
|
|
259
|
-
|
|
260
|
-
if (devConfig.autoLaunch !== false) {
|
|
261
|
-
await openBrowser({ url, silentBrowserNoneError: true })
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
process.env.URL = url
|
|
265
|
-
process.env.DEPLOY_URL = url
|
|
266
|
-
|
|
267
|
-
printBanner({ url })
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
DevCommand.description = `Local dev server
|
|
272
|
-
The dev command will run a local dev server with Netlify's proxy and redirect rules
|
|
273
|
-
`
|
|
274
|
-
|
|
275
|
-
DevCommand.examples = [
|
|
276
|
-
'$ netlify dev',
|
|
277
|
-
'$ netlify dev -d public',
|
|
278
|
-
'$ netlify dev -c "hugo server -w" --targetPort 1313',
|
|
279
|
-
]
|
|
280
|
-
|
|
281
|
-
DevCommand.strict = false
|
|
282
|
-
|
|
283
|
-
DevCommand.flags = {
|
|
284
|
-
command: flagsLib.string({
|
|
285
|
-
char: 'c',
|
|
286
|
-
description: 'command to run',
|
|
287
|
-
}),
|
|
288
|
-
port: flagsLib.integer({
|
|
289
|
-
char: 'p',
|
|
290
|
-
description: 'port of netlify dev',
|
|
291
|
-
}),
|
|
292
|
-
targetPort: flagsLib.integer({
|
|
293
|
-
description: 'port of target app server',
|
|
294
|
-
}),
|
|
295
|
-
framework: flagsLib.string({
|
|
296
|
-
description: 'framework to use. Defaults to #auto which automatically detects a framework',
|
|
297
|
-
}),
|
|
298
|
-
staticServerPort: flagsLib.integer({
|
|
299
|
-
description: 'port of the static app server used when no framework is detected',
|
|
300
|
-
hidden: true,
|
|
301
|
-
}),
|
|
302
|
-
dir: flagsLib.string({
|
|
303
|
-
char: 'd',
|
|
304
|
-
description: 'dir with static files',
|
|
305
|
-
}),
|
|
306
|
-
functions: flagsLib.string({
|
|
307
|
-
char: 'f',
|
|
308
|
-
description: 'specify a functions folder to serve',
|
|
309
|
-
}),
|
|
310
|
-
offline: flagsLib.boolean({
|
|
311
|
-
char: 'o',
|
|
312
|
-
description: 'disables any features that require network access',
|
|
313
|
-
}),
|
|
314
|
-
live: flagsLib.boolean({
|
|
315
|
-
char: 'l',
|
|
316
|
-
description: 'start a public live session',
|
|
317
|
-
default: false,
|
|
318
|
-
}),
|
|
319
|
-
edgeHandlers: flagsLib.boolean({
|
|
320
|
-
char: 'e',
|
|
321
|
-
hidden: true,
|
|
322
|
-
description: 'activates the Edge Handlers runtime',
|
|
323
|
-
}),
|
|
324
|
-
trafficMesh: flagsLib.boolean({
|
|
325
|
-
char: 't',
|
|
326
|
-
hidden: true,
|
|
327
|
-
description: '(DEPRECATED: use --edgeHandlers or -e instead) uses Traffic Mesh for proxying requests',
|
|
328
|
-
}),
|
|
329
|
-
locationDb: flagsLib.string({
|
|
330
|
-
description: 'specify the path to a local GeoIP location database in MMDB format',
|
|
331
|
-
char: 'g',
|
|
332
|
-
hidden: true,
|
|
333
|
-
}),
|
|
334
|
-
...DevCommand.flags,
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
module.exports = DevCommand
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { log, logJson } = require('../../utils')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The env:get command
|
|
6
|
+
* @param {string} name Environment variable name
|
|
7
|
+
* @param {import('commander').OptionValues} options
|
|
8
|
+
* @param {import('../base-command').BaseCommand} command
|
|
9
|
+
*/
|
|
10
|
+
const envGet = async (name, options, command) => {
|
|
11
|
+
const { api, cachedConfig, site } = command.netlify
|
|
12
|
+
const siteId = site.id
|
|
13
|
+
|
|
14
|
+
if (!siteId) {
|
|
15
|
+
log('No site id found, please run inside a site folder or `netlify link`')
|
|
16
|
+
return false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const siteData = await api.getSite({ siteId })
|
|
20
|
+
|
|
21
|
+
const { value } = cachedConfig.env[name] || {}
|
|
22
|
+
|
|
23
|
+
// Return json response for piping commands
|
|
24
|
+
if (options.json) {
|
|
25
|
+
logJson(value ? { [name]: value } : {})
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!value) {
|
|
30
|
+
log(`Environment variable ${name} not set for site ${siteData.name}`)
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
log(value)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Creates the `netlify env:get` command
|
|
39
|
+
* @param {import('../base-command').BaseCommand} program
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
const createEnvGetCommand = (program) =>
|
|
43
|
+
program
|
|
44
|
+
.command('env:get')
|
|
45
|
+
.argument('<name>', 'Environment variable name')
|
|
46
|
+
.description('Get resolved value of specified environment variable (includes netlify.toml)')
|
|
47
|
+
.action(async (name, options, command) => {
|
|
48
|
+
await envGet(name, options, command)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
module.exports = { createEnvGetCommand }
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { readFile } = require('fs').promises
|
|
3
|
+
|
|
4
|
+
const AsciiTable = require('ascii-table')
|
|
5
|
+
const dotenv = require('dotenv')
|
|
6
|
+
const isEmpty = require('lodash/isEmpty')
|
|
7
|
+
|
|
8
|
+
const { exit, log, logJson } = require('../../utils')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The env:import command
|
|
12
|
+
* @param {string} fileName .env file to import
|
|
13
|
+
* @param {import('commander').OptionValues} options
|
|
14
|
+
* @param {import('../base-command').BaseCommand} command
|
|
15
|
+
* @returns {Promise<boolean>}
|
|
16
|
+
*/
|
|
17
|
+
const envImport = async (fileName, options, command) => {
|
|
18
|
+
const { api, site } = command.netlify
|
|
19
|
+
const siteId = site.id
|
|
20
|
+
|
|
21
|
+
if (!siteId) {
|
|
22
|
+
log('No site id found, please run inside a site folder or `netlify link`')
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const siteData = await api.getSite({ siteId })
|
|
27
|
+
|
|
28
|
+
// Get current environment variables set in the UI
|
|
29
|
+
const {
|
|
30
|
+
build_settings: { env = {} },
|
|
31
|
+
} = siteData
|
|
32
|
+
|
|
33
|
+
let importedEnv = {}
|
|
34
|
+
try {
|
|
35
|
+
const envFileContents = await readFile(fileName, 'utf-8')
|
|
36
|
+
importedEnv = dotenv.parse(envFileContents)
|
|
37
|
+
} catch (error) {
|
|
38
|
+
log(error.message)
|
|
39
|
+
exit(1)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (isEmpty(importedEnv)) {
|
|
43
|
+
log(`No environment variables found in file ${fileName} to import`)
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Apply environment variable updates
|
|
48
|
+
const siteResult = await api.updateSite({
|
|
49
|
+
siteId,
|
|
50
|
+
body: {
|
|
51
|
+
build_settings: {
|
|
52
|
+
// Only set imported variables if --replaceExisting or otherwise merge
|
|
53
|
+
// imported ones with the current environment variables.
|
|
54
|
+
env: options.replaceExisting ? importedEnv : { ...env, ...importedEnv },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// Return new environment variables of site if using json flag
|
|
60
|
+
if (options.json) {
|
|
61
|
+
logJson(siteResult.build_settings.env)
|
|
62
|
+
return false
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// List newly imported environment variables in a table
|
|
66
|
+
log(`site: ${siteData.name}`)
|
|
67
|
+
const table = new AsciiTable(`Imported environment variables`)
|
|
68
|
+
|
|
69
|
+
table.setHeading('Key', 'Value')
|
|
70
|
+
table.addRowMatrix(Object.entries(importedEnv))
|
|
71
|
+
log(table.toString())
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Creates the `netlify env:import` command
|
|
76
|
+
* @param {import('../base-command').BaseCommand} program
|
|
77
|
+
* @returns
|
|
78
|
+
*/
|
|
79
|
+
const createEnvImportCommand = (program) =>
|
|
80
|
+
program
|
|
81
|
+
.command('env:import')
|
|
82
|
+
.argument('<fileName>', '.env file to import')
|
|
83
|
+
.option(
|
|
84
|
+
'-r, --replaceExisting',
|
|
85
|
+
'Replace all existing variables instead of merging them with the current ones',
|
|
86
|
+
false,
|
|
87
|
+
)
|
|
88
|
+
.description('Import and set environment variables from .env file')
|
|
89
|
+
.action(async (fileName, options, command) => {
|
|
90
|
+
await envImport(fileName, options, command)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
module.exports = { createEnvImportCommand }
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const AsciiTable = require('ascii-table')
|
|
3
|
+
const isEmpty = require('lodash/isEmpty')
|
|
4
|
+
|
|
5
|
+
const { log, logJson } = require('../../utils')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The env:list command
|
|
9
|
+
* @param {import('commander').OptionValues} options
|
|
10
|
+
* @param {import('../base-command').BaseCommand} command
|
|
11
|
+
* @returns {Promise<boolean>}
|
|
12
|
+
*/
|
|
13
|
+
const envList = async (options, command) => {
|
|
14
|
+
const { api, cachedConfig, site } = command.netlify
|
|
15
|
+
const siteId = site.id
|
|
16
|
+
|
|
17
|
+
if (!siteId) {
|
|
18
|
+
log('No site id found, please run inside a site folder or `netlify link`')
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const siteData = await api.getSite({ siteId })
|
|
23
|
+
const environment = Object.fromEntries(
|
|
24
|
+
Object.entries(cachedConfig.env)
|
|
25
|
+
// Omitting general variables to reduce noise.
|
|
26
|
+
.filter(([, variable]) => variable.sources[0] !== 'general')
|
|
27
|
+
.map(([key, variable]) => [key, variable.value]),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
// Return json response for piping commands
|
|
31
|
+
if (options.json) {
|
|
32
|
+
logJson(environment)
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (isEmpty(environment)) {
|
|
37
|
+
log(`No environment variables set for site ${siteData.name}`)
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// List environment variables using a table
|
|
42
|
+
log(`site: ${siteData.name}`)
|
|
43
|
+
const table = new AsciiTable(`Environment variables`)
|
|
44
|
+
|
|
45
|
+
table.setHeading('Key', 'Value')
|
|
46
|
+
table.addRowMatrix(Object.entries(environment))
|
|
47
|
+
log(table.toString())
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Creates the `netlify env:list` command
|
|
52
|
+
* @param {import('../base-command').BaseCommand} program
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
55
|
+
const createEnvListCommand = (program) =>
|
|
56
|
+
program
|
|
57
|
+
.command('env:list')
|
|
58
|
+
.description('Lists resolved environment variables for site (includes netlify.toml)')
|
|
59
|
+
.action(async (options, command) => {
|
|
60
|
+
await envList(options, command)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
module.exports = { createEnvListCommand }
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { log, logJson } = require('../../utils')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The env:set command
|
|
6
|
+
* @param {string} name Environment variable name
|
|
7
|
+
* @param {string} value Value to set to
|
|
8
|
+
* @param {import('commander').OptionValues} options
|
|
9
|
+
* @param {import('../base-command').BaseCommand} command
|
|
10
|
+
* @returns {Promise<boolean>}
|
|
11
|
+
*/
|
|
12
|
+
const envSet = async (name, value, options, command) => {
|
|
13
|
+
const { api, site } = command.netlify
|
|
14
|
+
const siteId = site.id
|
|
15
|
+
|
|
16
|
+
if (!siteId) {
|
|
17
|
+
log('No site id found, please run inside a site folder or `netlify link`')
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const siteData = await api.getSite({ siteId })
|
|
22
|
+
|
|
23
|
+
// Get current environment variables set in the UI
|
|
24
|
+
const {
|
|
25
|
+
build_settings: { env = {} },
|
|
26
|
+
} = siteData
|
|
27
|
+
|
|
28
|
+
const newEnv = {
|
|
29
|
+
...env,
|
|
30
|
+
[name]: value,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Apply environment variable updates
|
|
34
|
+
const siteResult = await api.updateSite({
|
|
35
|
+
siteId,
|
|
36
|
+
body: {
|
|
37
|
+
build_settings: {
|
|
38
|
+
env: newEnv,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
// Return new environment variables of site if using json flag
|
|
44
|
+
if (options.json) {
|
|
45
|
+
logJson(siteResult.build_settings.env)
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
log(`Set environment variable ${name}=${value} for site ${siteData.name}`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Creates the `netlify env:set` command
|
|
54
|
+
* @param {import('../base-command').BaseCommand} program
|
|
55
|
+
* @returns
|
|
56
|
+
*/
|
|
57
|
+
const createEnvSetCommand = (program) =>
|
|
58
|
+
program
|
|
59
|
+
.command('env:set')
|
|
60
|
+
.argument('<name>', 'Environment variable name')
|
|
61
|
+
.argument('[value]', 'Value to set to', '')
|
|
62
|
+
.description('Set value of environment variable')
|
|
63
|
+
.action(async (name, value, options, command) => {
|
|
64
|
+
await envSet(name, value, options, command)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
module.exports = { createEnvSetCommand }
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { log, logJson } = require('../../utils')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The env:unset command
|
|
6
|
+
* @param {string} name Environment variable name
|
|
7
|
+
* @param {import('commander').OptionValues} options
|
|
8
|
+
* @param {import('../base-command').BaseCommand} command
|
|
9
|
+
* @returns {Promise<boolean>}
|
|
10
|
+
*/
|
|
11
|
+
const envUnset = async (name, options, command) => {
|
|
12
|
+
const { api, site } = command.netlify
|
|
13
|
+
const siteId = site.id
|
|
14
|
+
|
|
15
|
+
if (!siteId) {
|
|
16
|
+
log('No site id found, please run inside a site folder or `netlify link`')
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const siteData = await api.getSite({ siteId })
|
|
21
|
+
|
|
22
|
+
// Get current environment variables set in the UI
|
|
23
|
+
const {
|
|
24
|
+
build_settings: { env = {} },
|
|
25
|
+
} = siteData
|
|
26
|
+
|
|
27
|
+
const newEnv = env
|
|
28
|
+
|
|
29
|
+
// Delete environment variable from current variables
|
|
30
|
+
delete newEnv[name]
|
|
31
|
+
|
|
32
|
+
// Apply environment variable updates
|
|
33
|
+
const siteResult = await api.updateSite({
|
|
34
|
+
siteId,
|
|
35
|
+
body: {
|
|
36
|
+
build_settings: {
|
|
37
|
+
env: newEnv,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Return new environment variables of site if using json flag
|
|
43
|
+
if (options.json) {
|
|
44
|
+
logJson(siteResult.build_settings.env)
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
log(`Unset environment variable ${name} for site ${siteData.name}`)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates the `netlify env:unset` command
|
|
53
|
+
* @param {import('../base-command').BaseCommand} program
|
|
54
|
+
* @returns
|
|
55
|
+
*/
|
|
56
|
+
const createEnvUnsetCommand = (program) =>
|
|
57
|
+
program
|
|
58
|
+
.command('env:unset')
|
|
59
|
+
.aliases(['env:delete', 'env:remove'])
|
|
60
|
+
.argument('<name>', 'Environment variable name')
|
|
61
|
+
.description('Unset an environment variable which removes it from the UI')
|
|
62
|
+
.action(async (name, options, command) => {
|
|
63
|
+
await envUnset(name, options, command)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
module.exports = { createEnvUnsetCommand }
|