netlify-cli 12.5.0 → 12.7.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/README.md +5 -0
- package/npm-shrinkwrap.json +1075 -634
- package/package.json +7 -160
- package/src/commands/base-command.mjs +16 -5
- package/src/commands/deploy/deploy.mjs +1 -1
- package/src/commands/dev/dev.mjs +27 -511
- package/src/commands/env/env-list.mjs +1 -0
- package/src/commands/functions/functions-create.mjs +35 -25
- package/src/commands/functions/functions-serve.mjs +5 -1
- package/src/commands/main.mjs +2 -0
- package/src/commands/serve/serve.mjs +189 -0
- package/src/commands/sites/sites-list.mjs +1 -1
- package/src/commands/watch/watch.mjs +1 -1
- package/src/functions-templates/go/hello-world/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/apollo-graphql/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/apollo-graphql-rest/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/auth-fetch/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/create-user/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/fauna-crud/{.netlify-function-template.cjs → .netlify-function-template.mjs} +3 -2
- package/src/functions-templates/javascript/fauna-graphql/{.netlify-function-template.cjs → .netlify-function-template.mjs} +3 -2
- package/src/functions-templates/javascript/google-analytics/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/graphql-gateway/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/hasura-event-triggered/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/hello/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/{typescript/hello-world/.netlify-function-template.cjs → javascript/hello-world/.netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/identity-signup/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/image-external/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/localized-content/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/node-fetch/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/oauth-passport/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/oauth-passport/package.json +1 -1
- package/src/functions-templates/javascript/protected-function/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/sanity-create/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/sanity-groq/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/scheduled-function/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/scheduled-function/package.json +1 -1
- package/src/functions-templates/javascript/send-email/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/serverless-ssr/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/set-cookie/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/set-cookies/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/{typescript/set-req-header/.netlify-function-template.cjs → javascript/set-req-header/.netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/set-res-header/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/slack-rate-limit/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/stripe-charge/{.netlify-function-template.cjs → .netlify-function-template.mjs} +2 -2
- package/src/functions-templates/javascript/stripe-subscription/{.netlify-function-template.cjs → .netlify-function-template.mjs} +2 -2
- package/src/functions-templates/javascript/submission-created/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/token-hider/{.netlify-function-template.cjs → .netlify-function-template.mjs} +2 -2
- package/src/functions-templates/{typescript/transform-response/.netlify-function-template.cjs → javascript/transform-response/.netlify-function-template.mjs} +1 -1
- package/src/functions-templates/javascript/url-shortener/{.netlify-function-template.cjs → .netlify-function-template.mjs} +2 -2
- package/src/functions-templates/javascript/using-middleware/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/rust/hello-world/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/typescript/abtest/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/typescript/geolocation/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/typescript/geolocation/{{name}}.ts +1 -1
- package/src/functions-templates/{javascript/hello-world/.netlify-function-template.cjs → typescript/hello-world/.netlify-function-template.mjs} +1 -1
- package/src/functions-templates/typescript/hello-world/package-lock.json +7 -7
- package/src/functions-templates/typescript/hello-world/package.json +1 -1
- package/src/functions-templates/typescript/json/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/typescript/json/{{name}}.ts +1 -1
- package/src/functions-templates/typescript/log/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/typescript/log/{{name}}.ts +2 -2
- package/src/functions-templates/typescript/scheduled-function/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/typescript/scheduled-function/package.json +1 -1
- package/src/functions-templates/typescript/set-cookies/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/{javascript/set-req-header/.netlify-function-template.cjs → typescript/set-req-header/.netlify-function-template.mjs} +1 -1
- package/src/functions-templates/typescript/set-res-header/{.netlify-function-template.cjs → .netlify-function-template.mjs} +1 -1
- package/src/functions-templates/{javascript/transform-response/.netlify-function-template.cjs → typescript/transform-response/.netlify-function-template.mjs} +1 -1
- package/src/lib/completion/constants.mjs +1 -1
- package/src/lib/edge-functions/deploy.mjs +1 -1
- package/src/lib/edge-functions/internal.mjs +1 -1
- package/src/lib/edge-functions/proxy.mjs +2 -2
- package/src/lib/edge-functions/registry.mjs +2 -5
- package/src/lib/{fs.cjs → fs.mjs} +5 -13
- package/src/lib/functions/registry.mjs +55 -33
- package/src/lib/functions/runtimes/js/builders/netlify-lambda.mjs +1 -1
- package/src/lib/functions/runtimes/js/builders/zisi.mjs +3 -2
- package/src/lib/functions/runtimes/rust/index.mjs +3 -2
- package/src/lib/functions/server.mjs +35 -18
- package/src/lib/{settings.cjs → settings.mjs} +6 -8
- package/src/lib/{spinner.cjs → spinner.mjs} +5 -7
- package/src/utils/banner.mjs +17 -0
- package/src/utils/command-helpers.mjs +1 -1
- package/src/utils/detect-server-settings.mjs +35 -1
- package/src/utils/dev.mjs +8 -5
- package/src/utils/dot-env.mjs +1 -1
- package/src/utils/framework-server.mjs +66 -0
- package/src/utils/functions/functions.mjs +20 -4
- package/src/utils/functions/get-functions.mjs +1 -1
- package/src/utils/get-global-config.mjs +1 -1
- package/src/utils/gitignore.mjs +1 -1
- package/src/utils/graph.mjs +170 -0
- package/src/utils/init/utils.mjs +1 -1
- package/src/utils/live-tunnel.mjs +1 -1
- package/src/utils/lm/install.mjs +2 -2
- package/src/utils/proxy-server.mjs +90 -0
- package/src/utils/proxy.mjs +1 -1
- package/src/utils/rules-proxy.mjs +1 -1
- package/src/utils/run-build.mjs +129 -0
- package/src/utils/shell.mjs +120 -0
- package/src/utils/state-config.mjs +1 -1
- package/src/utils/static-server.mjs +34 -0
- package/src/utils/validation.mjs +15 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import cp from 'child_process'
|
|
3
3
|
import fs from 'fs'
|
|
4
|
-
import { mkdir } from 'fs/promises'
|
|
4
|
+
import { mkdir, readdir, unlink } from 'fs/promises'
|
|
5
5
|
import { createRequire } from 'module'
|
|
6
6
|
import path, { dirname } from 'path'
|
|
7
7
|
import process from 'process'
|
|
8
|
-
import { fileURLToPath } from 'url'
|
|
8
|
+
import { fileURLToPath, pathToFileURL } from 'url'
|
|
9
9
|
import { promisify } from 'util'
|
|
10
10
|
|
|
11
11
|
import copyTemplateDirOriginal from 'copy-template-dir'
|
|
@@ -16,6 +16,7 @@ import inquirerAutocompletePrompt from 'inquirer-autocomplete-prompt'
|
|
|
16
16
|
import fetch from 'node-fetch'
|
|
17
17
|
import ora from 'ora'
|
|
18
18
|
|
|
19
|
+
import { fileExistsAsync } from '../../lib/fs.mjs'
|
|
19
20
|
import { getAddons, getCurrentAddon, getSiteData } from '../../utils/addons/prepare.mjs'
|
|
20
21
|
import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, error, log } from '../../utils/command-helpers.mjs'
|
|
21
22
|
import { injectEnvVariables } from '../../utils/dev.mjs'
|
|
@@ -90,19 +91,26 @@ const filterRegistry = function (registry, input) {
|
|
|
90
91
|
})
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
const formatRegistryArrayForInquirer = function (lang, funcType) {
|
|
94
|
-
const folderNames =
|
|
95
|
-
const registry = folderNames
|
|
96
|
-
// filter out markdown files
|
|
97
|
-
.filter((folderName) => !folderName.endsWith('.md'))
|
|
94
|
+
const formatRegistryArrayForInquirer = async function (lang, funcType) {
|
|
95
|
+
const folderNames = await readdir(path.join(templatesDir, lang))
|
|
98
96
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
97
|
+
const imports = await Promise.all(
|
|
98
|
+
folderNames
|
|
99
|
+
// filter out markdown files
|
|
100
|
+
.filter((folderName) => !folderName.endsWith('.md'))
|
|
101
|
+
.map(async (folderName) => {
|
|
102
|
+
const templatePath = path.join(templatesDir, lang, folderName, '.netlify-function-template.mjs')
|
|
103
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
104
|
+
const template = await import(pathToFileURL(templatePath))
|
|
105
|
+
|
|
106
|
+
return template.default
|
|
107
|
+
}),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
const registry = imports
|
|
111
|
+
.filter((template) => template.functionType === funcType)
|
|
112
|
+
.sort((templateA, templateB) => {
|
|
113
|
+
const priorityDiff = (templateA.priority || DEFAULT_PRIORITY) - (templateB.priority || DEFAULT_PRIORITY)
|
|
106
114
|
|
|
107
115
|
if (priorityDiff !== 0) {
|
|
108
116
|
return priorityDiff
|
|
@@ -112,7 +120,7 @@ const formatRegistryArrayForInquirer = function (lang, funcType) {
|
|
|
112
120
|
// until Node 11, so the original sorting order from `fs.readdirSync`
|
|
113
121
|
// was not respected. We can simplify this once we drop support for
|
|
114
122
|
// Node 10.
|
|
115
|
-
return
|
|
123
|
+
return templateA - templateB
|
|
116
124
|
})
|
|
117
125
|
.map((t) => {
|
|
118
126
|
t.lang = lang
|
|
@@ -170,7 +178,7 @@ const pickTemplate = async function ({ language: languageFromFlag }, funcType) {
|
|
|
170
178
|
let templatesForLanguage
|
|
171
179
|
|
|
172
180
|
try {
|
|
173
|
-
templatesForLanguage = formatRegistryArrayForInquirer(language, funcType)
|
|
181
|
+
templatesForLanguage = await formatRegistryArrayForInquirer(language, funcType)
|
|
174
182
|
} catch {
|
|
175
183
|
throw error(`Invalid language: ${language}`)
|
|
176
184
|
}
|
|
@@ -292,14 +300,14 @@ const ensureFunctionDirExists = async function (command) {
|
|
|
292
300
|
}
|
|
293
301
|
}
|
|
294
302
|
|
|
295
|
-
if (!
|
|
303
|
+
if (!(await fileExistsAsync(functionsDirHolder))) {
|
|
296
304
|
log(
|
|
297
305
|
`${NETLIFYDEVLOG} functions directory ${chalk.magenta.inverse(
|
|
298
306
|
functionsDirHolder,
|
|
299
307
|
)} does not exist yet, creating it...`,
|
|
300
308
|
)
|
|
301
309
|
|
|
302
|
-
|
|
310
|
+
await mkdir(functionsDirHolder, { recursive: true })
|
|
303
311
|
|
|
304
312
|
log(`${NETLIFYDEVLOG} functions directory ${chalk.magenta.inverse(functionsDirHolder)} created`)
|
|
305
313
|
}
|
|
@@ -350,15 +358,17 @@ const downloadFromURL = async function (command, options, argumentName, function
|
|
|
350
358
|
})
|
|
351
359
|
|
|
352
360
|
// read, execute, and delete function template file if exists
|
|
353
|
-
const fnTemplateFile = path.join(fnFolder, '.netlify-function-template.
|
|
354
|
-
if (
|
|
355
|
-
|
|
356
|
-
|
|
361
|
+
const fnTemplateFile = path.join(fnFolder, '.netlify-function-template.mjs')
|
|
362
|
+
if (await fileExistsAsync(fnTemplateFile)) {
|
|
363
|
+
const {
|
|
364
|
+
default: { onComplete, addons = [] },
|
|
365
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
366
|
+
} = await import(pathToFileURL(fnTemplateFile).href)
|
|
357
367
|
|
|
358
368
|
await installAddons(command, addons, path.resolve(fnFolder))
|
|
359
369
|
await handleOnComplete({ command, onComplete })
|
|
360
370
|
// delete
|
|
361
|
-
|
|
371
|
+
await unlink(fnTemplateFile)
|
|
362
372
|
}
|
|
363
373
|
}
|
|
364
374
|
|
|
@@ -471,7 +481,7 @@ const scaffoldFromTemplate = async function (command, options, argumentName, fun
|
|
|
471
481
|
|
|
472
482
|
// These files will not be part of the log message because they'll likely
|
|
473
483
|
// be removed before the command finishes.
|
|
474
|
-
const omittedFromOutput = new Set(['.netlify-function-template.
|
|
484
|
+
const omittedFromOutput = new Set(['.netlify-function-template.mjs', 'package.json', 'package-lock.json'])
|
|
475
485
|
const createdFiles = await copyTemplateDir(pathToTemplate, functionPath, vars)
|
|
476
486
|
createdFiles.forEach((filePath) => {
|
|
477
487
|
const filename = path.basename(filePath)
|
|
@@ -487,7 +497,7 @@ const scaffoldFromTemplate = async function (command, options, argumentName, fun
|
|
|
487
497
|
})
|
|
488
498
|
|
|
489
499
|
// delete function template file that was copied over by copydir
|
|
490
|
-
|
|
500
|
+
await unlink(path.join(functionPath, '.netlify-function-template.mjs'))
|
|
491
501
|
|
|
492
502
|
// npm install
|
|
493
503
|
if (functionPackageJson !== undefined) {
|
|
@@ -16,8 +16,11 @@ const functionsServe = async (options, command) => {
|
|
|
16
16
|
const { api, config, site, siteInfo } = command.netlify
|
|
17
17
|
|
|
18
18
|
const functionsDir = getFunctionsDir({ options, config }, join('netlify', 'functions'))
|
|
19
|
+
const { env } = command.netlify.cachedConfig
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
env.NETLIFY_DEV = { sources: ['internal'], value: 'true' }
|
|
22
|
+
|
|
23
|
+
await injectEnvVariables({ devConfig: { ...config.dev }, env, site })
|
|
21
24
|
|
|
22
25
|
const { capabilities, siteUrl, timeouts } = await getSiteInformation({
|
|
23
26
|
offline: options.offline,
|
|
@@ -34,6 +37,7 @@ const functionsServe = async (options, command) => {
|
|
|
34
37
|
|
|
35
38
|
await startFunctionsServer({
|
|
36
39
|
config,
|
|
40
|
+
debug: options.debug,
|
|
37
41
|
api,
|
|
38
42
|
settings: { functions: functionsDir, functionsPort },
|
|
39
43
|
site,
|
package/src/commands/main.mjs
CHANGED
|
@@ -28,6 +28,7 @@ import { createLoginCommand } from './login/index.mjs'
|
|
|
28
28
|
import { createLogoutCommand } from './logout/index.mjs'
|
|
29
29
|
import { createOpenCommand } from './open/index.mjs'
|
|
30
30
|
import { createRecipesCommand } from './recipes/index.mjs'
|
|
31
|
+
import { createServeCommand } from './serve/serve.mjs'
|
|
31
32
|
import { createSitesCommand } from './sites/index.mjs'
|
|
32
33
|
import { createStatusCommand } from './status/index.mjs'
|
|
33
34
|
import { createSwitchCommand } from './switch/index.mjs'
|
|
@@ -173,6 +174,7 @@ export const createMainCommand = () => {
|
|
|
173
174
|
createLoginCommand(program)
|
|
174
175
|
createLogoutCommand(program)
|
|
175
176
|
createOpenCommand(program)
|
|
177
|
+
createServeCommand(program)
|
|
176
178
|
createSitesCommand(program)
|
|
177
179
|
createStatusCommand(program)
|
|
178
180
|
createSwitchCommand(program)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import process from 'process'
|
|
3
|
+
|
|
4
|
+
import { Option } from 'commander'
|
|
5
|
+
|
|
6
|
+
import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.mjs'
|
|
7
|
+
import { startFunctionsServer } from '../../lib/functions/server.mjs'
|
|
8
|
+
import { printBanner } from '../../utils/banner.mjs'
|
|
9
|
+
import {
|
|
10
|
+
chalk,
|
|
11
|
+
exit,
|
|
12
|
+
log,
|
|
13
|
+
NETLIFYDEVERR,
|
|
14
|
+
NETLIFYDEVLOG,
|
|
15
|
+
NETLIFYDEVWARN,
|
|
16
|
+
normalizeConfig,
|
|
17
|
+
} from '../../utils/command-helpers.mjs'
|
|
18
|
+
import detectServerSettings, { getConfigWithPlugins } from '../../utils/detect-server-settings.mjs'
|
|
19
|
+
import { getSiteInformation, injectEnvVariables } from '../../utils/dev.mjs'
|
|
20
|
+
import { getEnvelopeEnv, normalizeContext } from '../../utils/env/index.mjs'
|
|
21
|
+
import { getInternalFunctionsDir } from '../../utils/functions/functions.mjs'
|
|
22
|
+
import { ensureNetlifyIgnore } from '../../utils/gitignore.mjs'
|
|
23
|
+
import openBrowser from '../../utils/open-browser.mjs'
|
|
24
|
+
import { generateInspectSettings, startProxyServer } from '../../utils/proxy-server.mjs'
|
|
25
|
+
import { runBuildTimeline } from '../../utils/run-build.mjs'
|
|
26
|
+
import { getGeoCountryArgParser } from '../../utils/validation.mjs'
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The serve command
|
|
30
|
+
* @param {import('commander').OptionValues} options
|
|
31
|
+
* @param {import('../base-command.mjs').default} command
|
|
32
|
+
*/
|
|
33
|
+
const serve = async (options, command) => {
|
|
34
|
+
const { api, cachedConfig, config, repositoryRoot, site, siteInfo, state } = command.netlify
|
|
35
|
+
config.dev = { ...config.dev }
|
|
36
|
+
config.build = { ...config.build }
|
|
37
|
+
/** @type {import('../dev/types').DevConfig} */
|
|
38
|
+
const devConfig = {
|
|
39
|
+
...(config.functionsDirectory && { functions: config.functionsDirectory }),
|
|
40
|
+
...(config.build.publish && { publish: config.build.publish }),
|
|
41
|
+
...config.dev,
|
|
42
|
+
...options,
|
|
43
|
+
// Override the `framework` value so that we start a static server and not
|
|
44
|
+
// the framework's development server.
|
|
45
|
+
framework: '#static',
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let { env } = cachedConfig
|
|
49
|
+
|
|
50
|
+
if (!options.offline && siteInfo.use_envelope) {
|
|
51
|
+
env = await getEnvelopeEnv({ api, context: options.context, env, siteInfo })
|
|
52
|
+
log(`${NETLIFYDEVLOG} Injecting environment variable values for ${chalk.yellow('all scopes')}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
await injectEnvVariables({ devConfig, env, site })
|
|
56
|
+
await promptEditorHelper({ chalk, config, log, NETLIFYDEVLOG, repositoryRoot, state })
|
|
57
|
+
|
|
58
|
+
const { addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({
|
|
59
|
+
// inherited from base command --offline
|
|
60
|
+
offline: options.offline,
|
|
61
|
+
api,
|
|
62
|
+
site,
|
|
63
|
+
siteInfo,
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// Ensure the internal functions directory exists so that the functions
|
|
67
|
+
// server and registry are initialized, and any functions created by
|
|
68
|
+
// Netlify Build are loaded.
|
|
69
|
+
await getInternalFunctionsDir({ base: site.root, ensureExists: true })
|
|
70
|
+
|
|
71
|
+
/** @type {Partial<import('../../utils/types').ServerSettings>} */
|
|
72
|
+
let settings = {}
|
|
73
|
+
try {
|
|
74
|
+
settings = await detectServerSettings(devConfig, options, site.root)
|
|
75
|
+
|
|
76
|
+
cachedConfig.config = getConfigWithPlugins(cachedConfig.config, settings)
|
|
77
|
+
} catch (error_) {
|
|
78
|
+
log(NETLIFYDEVERR, error_.message)
|
|
79
|
+
exit(1)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
command.setAnalyticsPayload({ projectType: settings.framework || 'custom', live: options.live, graph: options.graph })
|
|
83
|
+
|
|
84
|
+
log(`${NETLIFYDEVLOG} Building site for production`)
|
|
85
|
+
log(
|
|
86
|
+
`${NETLIFYDEVWARN} Changes will not be hot-reloaded, so if you need to rebuild your site you must exit and run 'netlify serve' again`,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
const { configPath: configPathOverride } = await runBuildTimeline({ cachedConfig, options, settings, site })
|
|
90
|
+
|
|
91
|
+
await startFunctionsServer({
|
|
92
|
+
api,
|
|
93
|
+
command,
|
|
94
|
+
config,
|
|
95
|
+
debug: options.debug,
|
|
96
|
+
loadDistFunctions: true,
|
|
97
|
+
settings,
|
|
98
|
+
site,
|
|
99
|
+
siteInfo,
|
|
100
|
+
siteUrl,
|
|
101
|
+
capabilities,
|
|
102
|
+
timeouts,
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// Try to add `.netlify` to `.gitignore`.
|
|
106
|
+
try {
|
|
107
|
+
await ensureNetlifyIgnore(repositoryRoot)
|
|
108
|
+
} catch {
|
|
109
|
+
// no-op
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// TODO: We should consolidate this with the existing config watcher.
|
|
113
|
+
const getUpdatedConfig = async () => {
|
|
114
|
+
const cwd = options.cwd || process.cwd()
|
|
115
|
+
const { config: newConfig } = await command.getConfig({ cwd, offline: true, state })
|
|
116
|
+
const normalizedNewConfig = normalizeConfig(newConfig)
|
|
117
|
+
|
|
118
|
+
return normalizedNewConfig
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const inspectSettings = generateInspectSettings(options.edgeInspect, options.edgeInspectBrk)
|
|
122
|
+
const url = await startProxyServer({
|
|
123
|
+
addonsUrls,
|
|
124
|
+
config,
|
|
125
|
+
configPath: configPathOverride,
|
|
126
|
+
env,
|
|
127
|
+
geolocationMode: options.geo,
|
|
128
|
+
geoCountry: options.country,
|
|
129
|
+
getUpdatedConfig,
|
|
130
|
+
inspectSettings,
|
|
131
|
+
offline: options.offline,
|
|
132
|
+
settings,
|
|
133
|
+
site,
|
|
134
|
+
siteInfo,
|
|
135
|
+
state,
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
if (devConfig.autoLaunch !== false) {
|
|
139
|
+
await openBrowser({ url, silentBrowserNoneError: true })
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
process.env.URL = url
|
|
143
|
+
process.env.DEPLOY_URL = url
|
|
144
|
+
|
|
145
|
+
printBanner({ url })
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Creates the `netlify serve` command
|
|
150
|
+
* @param {import('../base-command.mjs').default} program
|
|
151
|
+
* @returns
|
|
152
|
+
*/
|
|
153
|
+
export const createServeCommand = (program) =>
|
|
154
|
+
program
|
|
155
|
+
.command('serve')
|
|
156
|
+
.description(
|
|
157
|
+
'(Beta) Build the site for production and serve locally. This does not watch the code for changes, so if you need to rebuild your site then you must exit and run `serve` again.',
|
|
158
|
+
)
|
|
159
|
+
.option(
|
|
160
|
+
'--context <context>',
|
|
161
|
+
'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")',
|
|
162
|
+
normalizeContext,
|
|
163
|
+
)
|
|
164
|
+
.option('-p ,--port <port>', 'port of netlify dev', (value) => Number.parseInt(value))
|
|
165
|
+
.option('-d ,--dir <path>', 'dir with static files')
|
|
166
|
+
.option('-f ,--functions <folder>', 'specify a functions folder to serve')
|
|
167
|
+
.option('-o ,--offline', 'disables any features that require network access')
|
|
168
|
+
.option('--functionsPort <port>', 'port of functions server', (value) => Number.parseInt(value))
|
|
169
|
+
.addOption(
|
|
170
|
+
new Option(
|
|
171
|
+
'--geo <mode>',
|
|
172
|
+
'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location',
|
|
173
|
+
)
|
|
174
|
+
.choices(['cache', 'mock', 'update'])
|
|
175
|
+
.default('cache'),
|
|
176
|
+
)
|
|
177
|
+
.addOption(
|
|
178
|
+
new Option(
|
|
179
|
+
'--country <geoCountry>',
|
|
180
|
+
'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)',
|
|
181
|
+
).argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR')),
|
|
182
|
+
)
|
|
183
|
+
.addOption(
|
|
184
|
+
new Option('--staticServerPort <port>', 'port of the static app server used when no framework is detected')
|
|
185
|
+
.argParser((value) => Number.parseInt(value))
|
|
186
|
+
.hideHelp(),
|
|
187
|
+
)
|
|
188
|
+
.addExamples(['netlify serve', 'BROWSER=none netlify serve # disable browser auto opening'])
|
|
189
|
+
.action(serve)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { listSites } from '../../lib/api.mjs'
|
|
3
|
-
import { startSpinner, stopSpinner } from '../../lib/spinner.
|
|
3
|
+
import { startSpinner, stopSpinner } from '../../lib/spinner.mjs'
|
|
4
4
|
import { chalk, log, logJson } from '../../utils/command-helpers.mjs'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import pWaitFor from 'p-wait-for'
|
|
3
3
|
import prettyjson from 'prettyjson'
|
|
4
4
|
|
|
5
|
-
import { startSpinner, stopSpinner } from '../../lib/spinner.
|
|
5
|
+
import { startSpinner, stopSpinner } from '../../lib/spinner.mjs'
|
|
6
6
|
import { chalk, error, log } from '../../utils/command-helpers.mjs'
|
|
7
7
|
import { init } from '../init/index.mjs'
|
|
8
8
|
|