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
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import boxen from 'boxen'
|
|
3
|
+
|
|
4
|
+
import { chalk, log, NETLIFYDEVLOG } from './command-helpers.mjs'
|
|
5
|
+
|
|
6
|
+
export const printBanner = ({ url }) => {
|
|
7
|
+
const banner = chalk.bold(`${NETLIFYDEVLOG} Server now ready on ${url}`)
|
|
8
|
+
|
|
9
|
+
log(
|
|
10
|
+
boxen(banner, {
|
|
11
|
+
padding: 1,
|
|
12
|
+
margin: 1,
|
|
13
|
+
align: 'center',
|
|
14
|
+
borderColor: '#00c7b7',
|
|
15
|
+
}),
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -12,7 +12,7 @@ import WSL from 'is-wsl'
|
|
|
12
12
|
import debounce from 'lodash/debounce.js'
|
|
13
13
|
import terminalLink from 'terminal-link'
|
|
14
14
|
|
|
15
|
-
import { clearSpinner, startSpinner } from '../lib/spinner.
|
|
15
|
+
import { clearSpinner, startSpinner } from '../lib/spinner.mjs'
|
|
16
16
|
|
|
17
17
|
import getGlobalConfig from './get-global-config.mjs'
|
|
18
18
|
import getPackageJson from './get-package-json.mjs'
|
|
@@ -11,7 +11,7 @@ import isPlainObject from 'is-plain-obj'
|
|
|
11
11
|
|
|
12
12
|
import { NETLIFYDEVWARN, chalk, log } from './command-helpers.mjs'
|
|
13
13
|
import { acquirePort } from './dev.mjs'
|
|
14
|
-
import { getInternalFunctionsDir } from './functions/
|
|
14
|
+
import { getInternalFunctionsDir } from './functions/functions.mjs'
|
|
15
15
|
|
|
16
16
|
const formatProperty = (str) => chalk.magenta(`'${str}'`)
|
|
17
17
|
const formatValue = (str) => chalk.green(`'${str}'`)
|
|
@@ -364,4 +364,38 @@ const formatSettingsArrForInquirer = function (frameworks) {
|
|
|
364
364
|
return formattedArr.flat()
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Returns a copy of the provided config with any plugins provided by the
|
|
369
|
+
* server settings
|
|
370
|
+
* @param {*} config
|
|
371
|
+
* @param {Partial<import('./types').ServerSettings>} settings
|
|
372
|
+
* @returns {*} Modified config
|
|
373
|
+
*/
|
|
374
|
+
export const getConfigWithPlugins = (config, settings) => {
|
|
375
|
+
if (!settings.plugins) {
|
|
376
|
+
return config
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// If there are plugins that we should be running for this site, add them
|
|
380
|
+
// to the config as if they were declared in netlify.toml. We must check
|
|
381
|
+
// whether the plugin has already been added by another source (like the
|
|
382
|
+
// TOML file or the UI), as we don't want to run the same plugin twice.
|
|
383
|
+
const { plugins: existingPlugins = [] } = config
|
|
384
|
+
const existingPluginNames = new Set(existingPlugins.map((plugin) => plugin.package))
|
|
385
|
+
const newPlugins = settings.plugins
|
|
386
|
+
.map((pluginName) => {
|
|
387
|
+
if (existingPluginNames.has(pluginName)) {
|
|
388
|
+
return
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return { package: pluginName, origin: 'config', inputs: {} }
|
|
392
|
+
})
|
|
393
|
+
.filter(Boolean)
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
...config,
|
|
397
|
+
plugins: [...newPlugins, ...config.plugins],
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
367
401
|
export default detectServerSettings
|
package/src/utils/dev.mjs
CHANGED
|
@@ -148,6 +148,10 @@ export const injectEnvVariables = async ({ devConfig, env, site }) => {
|
|
|
148
148
|
const newSourceName = `${file} file`
|
|
149
149
|
const sources = environment.has(key) ? [newSourceName, ...environment.get(key).sources] : [newSourceName]
|
|
150
150
|
|
|
151
|
+
if (sources.includes('internal')) {
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
151
155
|
environment.set(key, {
|
|
152
156
|
sources,
|
|
153
157
|
value: fileEnv[key],
|
|
@@ -160,6 +164,7 @@ export const injectEnvVariables = async ({ devConfig, env, site }) => {
|
|
|
160
164
|
const existsInProcess = process.env[key] !== undefined
|
|
161
165
|
const [usedSource, ...overriddenSources] = existsInProcess ? ['process', ...variable.sources] : variable.sources
|
|
162
166
|
const usedSourceName = getEnvSourceName(usedSource)
|
|
167
|
+
const isInternal = variable.sources.includes('internal')
|
|
163
168
|
|
|
164
169
|
overriddenSources.forEach((source) => {
|
|
165
170
|
const sourceName = getEnvSourceName(source)
|
|
@@ -173,17 +178,15 @@ export const injectEnvVariables = async ({ devConfig, env, site }) => {
|
|
|
173
178
|
)
|
|
174
179
|
})
|
|
175
180
|
|
|
176
|
-
if (!existsInProcess) {
|
|
177
|
-
// Omitting `general` env vars to reduce noise in the logs.
|
|
178
|
-
if (usedSource !== 'general') {
|
|
181
|
+
if (!existsInProcess || isInternal) {
|
|
182
|
+
// Omitting `general` and `internal` env vars to reduce noise in the logs.
|
|
183
|
+
if (usedSource !== 'general' && !isInternal) {
|
|
179
184
|
log(`${NETLIFYDEVLOG} Injected ${usedSourceName} env var: ${chalk.yellow(key)}`)
|
|
180
185
|
}
|
|
181
186
|
|
|
182
187
|
process.env[key] = variable.value
|
|
183
188
|
}
|
|
184
189
|
}
|
|
185
|
-
|
|
186
|
-
process.env.NETLIFY_DEV = 'true'
|
|
187
190
|
}
|
|
188
191
|
|
|
189
192
|
export const acquirePort = async ({ configuredPort, defaultPort, errorMessage }) => {
|
package/src/utils/dot-env.mjs
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import waitPort from 'wait-port'
|
|
3
|
+
|
|
4
|
+
import { startSpinner, stopSpinner } from '../lib/spinner.mjs'
|
|
5
|
+
|
|
6
|
+
import { error, exit, log, NETLIFYDEVERR, NETLIFYDEVLOG } from './command-helpers.mjs'
|
|
7
|
+
import { runCommand } from './shell.mjs'
|
|
8
|
+
import { startStaticServer } from './static-server.mjs'
|
|
9
|
+
|
|
10
|
+
// 10 minutes
|
|
11
|
+
const FRAMEWORK_PORT_TIMEOUT = 6e5
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef StartReturnObject
|
|
15
|
+
* @property {4 | 6 | undefined=} ipVersion The version the open port was found on
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Start a static server if the `useStaticServer` is provided or a framework specific server
|
|
20
|
+
* @param {object} config
|
|
21
|
+
* @param {Partial<import('./types').ServerSettings>} config.settings
|
|
22
|
+
* @returns {Promise<StartReturnObject>}
|
|
23
|
+
*/
|
|
24
|
+
export const startFrameworkServer = async function ({ settings }) {
|
|
25
|
+
if (settings.useStaticServer) {
|
|
26
|
+
if (settings.command) {
|
|
27
|
+
runCommand(settings.command, settings.env)
|
|
28
|
+
}
|
|
29
|
+
await startStaticServer({ settings })
|
|
30
|
+
|
|
31
|
+
return {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
log(`${NETLIFYDEVLOG} Starting Netlify Dev with ${settings.framework || 'custom config'}`)
|
|
35
|
+
|
|
36
|
+
const spinner = startSpinner({
|
|
37
|
+
text: `Waiting for framework port ${settings.frameworkPort}. This can be configured using the 'targetPort' property in the netlify.toml`,
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
runCommand(settings.command, settings.env, spinner)
|
|
41
|
+
|
|
42
|
+
let port
|
|
43
|
+
try {
|
|
44
|
+
port = await waitPort({
|
|
45
|
+
port: settings.frameworkPort,
|
|
46
|
+
host: 'localhost',
|
|
47
|
+
output: 'silent',
|
|
48
|
+
timeout: FRAMEWORK_PORT_TIMEOUT,
|
|
49
|
+
...(settings.pollingStrategies.includes('HTTP') && { protocol: 'http' }),
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
if (!port.open) {
|
|
53
|
+
throw new Error(`Timed out waiting for port '${settings.frameworkPort}' to be open`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
stopSpinner({ error: false, spinner })
|
|
57
|
+
} catch (error_) {
|
|
58
|
+
stopSpinner({ error: true, spinner })
|
|
59
|
+
log(NETLIFYDEVERR, `Netlify Dev could not start or connect to localhost:${settings.frameworkPort}.`)
|
|
60
|
+
log(NETLIFYDEVERR, `Please make sure your framework server is running on port ${settings.frameworkPort}`)
|
|
61
|
+
error(error_)
|
|
62
|
+
exit(1)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return { ipVersion: port?.ipVersion }
|
|
66
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
+
import { promises as fs } from 'fs'
|
|
2
3
|
import { resolve } from 'path'
|
|
3
4
|
|
|
4
|
-
import { isDirectoryAsync, isFileAsync } from '../../lib/fs.
|
|
5
|
-
import { getPathInProject } from '../../lib/settings.
|
|
5
|
+
import { isDirectoryAsync, isFileAsync } from '../../lib/fs.mjs'
|
|
6
|
+
import { getPathInProject } from '../../lib/settings.mjs'
|
|
7
|
+
|
|
8
|
+
export const INTERNAL_FUNCTIONS_FOLDER = 'functions-internal'
|
|
9
|
+
export const SERVE_FUNCTIONS_FOLDER = 'functions-serve'
|
|
6
10
|
|
|
7
11
|
/**
|
|
8
12
|
* retrieves the function directory out of the flags or config
|
|
@@ -26,8 +30,20 @@ export const getFunctionsManifestPath = async ({ base }) => {
|
|
|
26
30
|
return isFile ? path : null
|
|
27
31
|
}
|
|
28
32
|
|
|
29
|
-
export const
|
|
30
|
-
const path = resolve(base, getPathInProject(['functions
|
|
33
|
+
export const getFunctionsDistPath = async ({ base }) => {
|
|
34
|
+
const path = resolve(base, getPathInProject(['functions']))
|
|
35
|
+
const isDirectory = await isDirectoryAsync(path)
|
|
36
|
+
|
|
37
|
+
return isDirectory ? path : null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const getInternalFunctionsDir = async ({ base, ensureExists }) => {
|
|
41
|
+
const path = resolve(base, getPathInProject([INTERNAL_FUNCTIONS_FOLDER]))
|
|
42
|
+
|
|
43
|
+
if (ensureExists) {
|
|
44
|
+
await fs.mkdir(path, { recursive: true })
|
|
45
|
+
}
|
|
46
|
+
|
|
31
47
|
const isDirectory = await isDirectoryAsync(path)
|
|
32
48
|
|
|
33
49
|
return isDirectory ? path : null
|
|
@@ -3,7 +3,7 @@ import { readFile } from 'fs/promises'
|
|
|
3
3
|
import Configstore from 'configstore'
|
|
4
4
|
import { v4 as uuidv4 } from 'uuid'
|
|
5
5
|
|
|
6
|
-
import { getLegacyPathInHome, getPathInHome } from '../lib/settings.
|
|
6
|
+
import { getLegacyPathInHome, getPathInHome } from '../lib/settings.mjs'
|
|
7
7
|
|
|
8
8
|
const globalConfigDefaults = {
|
|
9
9
|
/* disable stats from being sent to Netlify */
|
package/src/utils/gitignore.mjs
CHANGED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import events from 'events'
|
|
3
|
+
import process from 'process'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
OneGraphCliClient,
|
|
7
|
+
loadCLISession,
|
|
8
|
+
markCliSessionInactive,
|
|
9
|
+
persistNewOperationsDocForSession,
|
|
10
|
+
startOneGraphCLISession,
|
|
11
|
+
} from '../lib/one-graph/cli-client.mjs'
|
|
12
|
+
import {
|
|
13
|
+
defaultExampleOperationsDoc,
|
|
14
|
+
getGraphEditUrlBySiteId,
|
|
15
|
+
getNetlifyGraphConfig,
|
|
16
|
+
readGraphQLOperationsSourceFile,
|
|
17
|
+
} from '../lib/one-graph/cli-netlify-graph.mjs'
|
|
18
|
+
|
|
19
|
+
import { chalk, error, getToken, log, normalizeConfig, warn, watchDebounced } from './command-helpers.mjs'
|
|
20
|
+
import { generateNetlifyGraphJWT, processOnExit } from './dev.mjs'
|
|
21
|
+
import { addCleanupJob } from './shell.mjs'
|
|
22
|
+
|
|
23
|
+
export const startPollingForAPIAuthentication = async function (options) {
|
|
24
|
+
const { api, command, config, site, siteInfo } = options
|
|
25
|
+
const frequency = 5000
|
|
26
|
+
|
|
27
|
+
const helper = async (maybeSiteData) => {
|
|
28
|
+
const siteData = await (maybeSiteData || api.getSite({ siteId: site.id }))
|
|
29
|
+
const authlifyTokenId = siteData && siteData.authlify_token_id
|
|
30
|
+
|
|
31
|
+
const existingAuthlifyTokenId = config && config.netlifyGraphConfig && config.netlifyGraphConfig.authlifyTokenId
|
|
32
|
+
if (authlifyTokenId && authlifyTokenId !== existingAuthlifyTokenId) {
|
|
33
|
+
const netlifyToken = await command.authenticate()
|
|
34
|
+
// Only inject the authlify config if a token ID exists. This prevents
|
|
35
|
+
// calling command.authenticate() (which opens a browser window) if the
|
|
36
|
+
// user hasn't enabled API Authentication
|
|
37
|
+
const netlifyGraphConfig = {
|
|
38
|
+
netlifyToken,
|
|
39
|
+
authlifyTokenId: siteData.authlify_token_id,
|
|
40
|
+
siteId: site.id,
|
|
41
|
+
}
|
|
42
|
+
config.netlifyGraphConfig = netlifyGraphConfig
|
|
43
|
+
|
|
44
|
+
const netlifyGraphJWT = generateNetlifyGraphJWT(netlifyGraphConfig)
|
|
45
|
+
|
|
46
|
+
if (netlifyGraphJWT != null) {
|
|
47
|
+
// XXX(anmonteiro): this name is deprecated. Delete after 3/31/2022
|
|
48
|
+
process.env.ONEGRAPH_AUTHLIFY_TOKEN = netlifyGraphJWT
|
|
49
|
+
process.env.NETLIFY_GRAPH_TOKEN = netlifyGraphJWT
|
|
50
|
+
}
|
|
51
|
+
} else if (!authlifyTokenId) {
|
|
52
|
+
// If there's no `authlifyTokenId`, it's because the user disabled API
|
|
53
|
+
// Auth. Delete the config in this case.
|
|
54
|
+
delete config.netlifyGraphConfig
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
setTimeout(helper, frequency)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
await helper(siteInfo)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const startNetlifyGraph = async ({
|
|
64
|
+
command,
|
|
65
|
+
config,
|
|
66
|
+
options,
|
|
67
|
+
settings,
|
|
68
|
+
site,
|
|
69
|
+
startNetlifyGraphWatcher,
|
|
70
|
+
state,
|
|
71
|
+
}) => {
|
|
72
|
+
if (startNetlifyGraphWatcher && options.offline) {
|
|
73
|
+
warn(`Unable to start Netlify Graph in offline mode`)
|
|
74
|
+
} else if (startNetlifyGraphWatcher && !site.id) {
|
|
75
|
+
error(
|
|
76
|
+
`No siteId defined, unable to start Netlify Graph. To enable, run ${chalk.yellow(
|
|
77
|
+
'netlify init',
|
|
78
|
+
)} or ${chalk.yellow('netlify link')}.`,
|
|
79
|
+
)
|
|
80
|
+
} else if (startNetlifyGraphWatcher) {
|
|
81
|
+
const netlifyToken = await command.authenticate()
|
|
82
|
+
await OneGraphCliClient.ensureAppForSite(netlifyToken, site.id)
|
|
83
|
+
|
|
84
|
+
let stopWatchingCLISessions
|
|
85
|
+
|
|
86
|
+
let liveConfig = { ...config }
|
|
87
|
+
let isRestartingSession = false
|
|
88
|
+
|
|
89
|
+
const createOrResumeSession = async function () {
|
|
90
|
+
const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options, settings })
|
|
91
|
+
|
|
92
|
+
let graphqlDocument = readGraphQLOperationsSourceFile(netlifyGraphConfig)
|
|
93
|
+
|
|
94
|
+
if (!graphqlDocument || graphqlDocument.trim().length === 0) {
|
|
95
|
+
graphqlDocument = defaultExampleOperationsDoc
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
stopWatchingCLISessions = await startOneGraphCLISession({
|
|
99
|
+
config: liveConfig,
|
|
100
|
+
netlifyGraphConfig,
|
|
101
|
+
netlifyToken,
|
|
102
|
+
site,
|
|
103
|
+
state,
|
|
104
|
+
oneGraphSessionId: options.sessionId,
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// Should be created by startOneGraphCLISession
|
|
108
|
+
const oneGraphSessionId = loadCLISession(state)
|
|
109
|
+
|
|
110
|
+
await persistNewOperationsDocForSession({
|
|
111
|
+
config: liveConfig,
|
|
112
|
+
netlifyGraphConfig,
|
|
113
|
+
netlifyToken,
|
|
114
|
+
oneGraphSessionId,
|
|
115
|
+
operationsDoc: graphqlDocument,
|
|
116
|
+
siteId: site.id,
|
|
117
|
+
siteRoot: site.root,
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
return oneGraphSessionId
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const configWatcher = new events.EventEmitter()
|
|
124
|
+
|
|
125
|
+
// Only set up a watcher if we know the config path.
|
|
126
|
+
const { configPath } = command.netlify.site
|
|
127
|
+
if (configPath) {
|
|
128
|
+
// chokidar handle
|
|
129
|
+
command.configWatcherHandle = await watchDebounced(configPath, {
|
|
130
|
+
depth: 1,
|
|
131
|
+
onChange: async () => {
|
|
132
|
+
const cwd = options.cwd || process.cwd()
|
|
133
|
+
const [token] = await getToken(options.auth)
|
|
134
|
+
const { config: newConfig } = await command.getConfig({ cwd, state, token, ...command.netlify.apiUrlOpts })
|
|
135
|
+
|
|
136
|
+
const normalizedNewConfig = normalizeConfig(newConfig)
|
|
137
|
+
configWatcher.emit('change', normalizedNewConfig)
|
|
138
|
+
},
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
processOnExit(async () => {
|
|
142
|
+
await command.configWatcherHandle.close()
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Set up a handler for config changes.
|
|
147
|
+
configWatcher.on('change', async (newConfig) => {
|
|
148
|
+
command.netlify.config = newConfig
|
|
149
|
+
liveConfig = newConfig
|
|
150
|
+
if (isRestartingSession) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
stopWatchingCLISessions && stopWatchingCLISessions()
|
|
154
|
+
isRestartingSession = true
|
|
155
|
+
await createOrResumeSession()
|
|
156
|
+
isRestartingSession = false
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
const oneGraphSessionId = await createOrResumeSession()
|
|
160
|
+
const cleanupSession = () => markCliSessionInactive({ netlifyToken, sessionId: oneGraphSessionId, siteId: site.id })
|
|
161
|
+
|
|
162
|
+
addCleanupJob(cleanupSession)
|
|
163
|
+
|
|
164
|
+
const graphEditUrl = getGraphEditUrlBySiteId({ siteId: site.id, oneGraphSessionId })
|
|
165
|
+
|
|
166
|
+
log(
|
|
167
|
+
`Starting Netlify Graph session, to edit your library visit ${graphEditUrl} or run \`netlify graph:edit\` in another tab`,
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
}
|
package/src/utils/init/utils.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import process from 'process'
|
|
|
6
6
|
import cleanDeep from 'clean-deep'
|
|
7
7
|
import inquirer from 'inquirer'
|
|
8
8
|
|
|
9
|
-
import { fileExistsAsync } from '../../lib/fs.
|
|
9
|
+
import { fileExistsAsync } from '../../lib/fs.mjs'
|
|
10
10
|
import { normalizeBackslash } from '../../lib/path.mjs'
|
|
11
11
|
import { chalk, error as failAndExit, log, warn } from '../command-helpers.mjs'
|
|
12
12
|
|
|
@@ -5,7 +5,7 @@ import fetch from 'node-fetch'
|
|
|
5
5
|
import pWaitFor from 'p-wait-for'
|
|
6
6
|
|
|
7
7
|
import { fetchLatestVersion, shouldFetchLatestVersion } from '../lib/exec-fetcher.mjs'
|
|
8
|
-
import { getPathInHome } from '../lib/settings.
|
|
8
|
+
import { getPathInHome } from '../lib/settings.mjs'
|
|
9
9
|
|
|
10
10
|
import { NETLIFYDEVERR, NETLIFYDEVLOG, chalk, log } from './command-helpers.mjs'
|
|
11
11
|
import execa from './execa.mjs'
|
package/src/utils/lm/install.mjs
CHANGED
|
@@ -11,9 +11,9 @@ import Listr from 'listr'
|
|
|
11
11
|
import pathKey from 'path-key'
|
|
12
12
|
|
|
13
13
|
import { fetchLatestVersion, shouldFetchLatestVersion } from '../../lib/exec-fetcher.mjs'
|
|
14
|
-
import { fileExistsAsync } from '../../lib/fs.
|
|
14
|
+
import { fileExistsAsync } from '../../lib/fs.mjs'
|
|
15
15
|
import { normalizeBackslash } from '../../lib/path.mjs'
|
|
16
|
-
import { getLegacyPathInHome, getPathInHome } from '../../lib/settings.
|
|
16
|
+
import { getLegacyPathInHome, getPathInHome } from '../../lib/settings.mjs'
|
|
17
17
|
import { chalk } from '../command-helpers.mjs'
|
|
18
18
|
|
|
19
19
|
import { checkGitLFSVersionStep, checkGitVersionStep, checkLFSFiltersStep } from './steps.mjs'
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { exit, log, NETLIFYDEVERR } from './command-helpers.mjs'
|
|
3
|
+
import { startProxy } from './proxy.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} InspectSettings
|
|
7
|
+
* @property {boolean} enabled - Inspect enabled
|
|
8
|
+
* @property {boolean} pause - Pause on breakpoints
|
|
9
|
+
* @property {string|undefined} address - Host/port override (optional)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {boolean|string} edgeInspect
|
|
14
|
+
* @param {boolean|string} edgeInspectBrk
|
|
15
|
+
* @returns {InspectSettings}
|
|
16
|
+
*/
|
|
17
|
+
export const generateInspectSettings = (edgeInspect, edgeInspectBrk) => {
|
|
18
|
+
const enabled = Boolean(edgeInspect) || Boolean(edgeInspectBrk)
|
|
19
|
+
const pause = Boolean(edgeInspectBrk)
|
|
20
|
+
const getAddress = () => {
|
|
21
|
+
if (edgeInspect) {
|
|
22
|
+
return typeof edgeInspect === 'string' ? edgeInspect : undefined
|
|
23
|
+
}
|
|
24
|
+
if (edgeInspectBrk) {
|
|
25
|
+
return typeof edgeInspectBrk === 'string' ? edgeInspectBrk : undefined
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
enabled,
|
|
31
|
+
pause,
|
|
32
|
+
address: getAddress(),
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param {object} params
|
|
39
|
+
* @param {*} params.addonsUrls
|
|
40
|
+
* @param {import('../commands/base-command.mjs').NetlifyOptions["config"]} params.config
|
|
41
|
+
* @param {string} [params.configPath] An override for the Netlify config path
|
|
42
|
+
* @param {import('../commands/base-command.mjs').NetlifyOptions["cachedConfig"]['env']} params.env
|
|
43
|
+
* @param {InspectSettings} params.inspectSettings
|
|
44
|
+
* @param {() => Promise<object>} params.getUpdatedConfig
|
|
45
|
+
* @param {string} params.geolocationMode
|
|
46
|
+
* @param {string} params.geoCountry
|
|
47
|
+
* @param {*} params.settings
|
|
48
|
+
* @param {boolean} params.offline
|
|
49
|
+
* @param {*} params.site
|
|
50
|
+
* @param {*} params.siteInfo
|
|
51
|
+
* @param {import('./state-config.mjs').default} params.state
|
|
52
|
+
* @returns
|
|
53
|
+
*/
|
|
54
|
+
export const startProxyServer = async ({
|
|
55
|
+
addonsUrls,
|
|
56
|
+
config,
|
|
57
|
+
configPath,
|
|
58
|
+
env,
|
|
59
|
+
geoCountry,
|
|
60
|
+
geolocationMode,
|
|
61
|
+
getUpdatedConfig,
|
|
62
|
+
inspectSettings,
|
|
63
|
+
offline,
|
|
64
|
+
settings,
|
|
65
|
+
site,
|
|
66
|
+
siteInfo,
|
|
67
|
+
state,
|
|
68
|
+
}) => {
|
|
69
|
+
const url = await startProxy({
|
|
70
|
+
addonsUrls,
|
|
71
|
+
config,
|
|
72
|
+
configPath: configPath || site.configPath,
|
|
73
|
+
env,
|
|
74
|
+
geolocationMode,
|
|
75
|
+
geoCountry,
|
|
76
|
+
getUpdatedConfig,
|
|
77
|
+
inspectSettings,
|
|
78
|
+
offline,
|
|
79
|
+
projectDir: site.root,
|
|
80
|
+
settings,
|
|
81
|
+
state,
|
|
82
|
+
siteInfo,
|
|
83
|
+
})
|
|
84
|
+
if (!url) {
|
|
85
|
+
log(NETLIFYDEVERR, `Unable to start proxy server on port '${settings.port}'`)
|
|
86
|
+
exit(1)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return url
|
|
90
|
+
}
|
package/src/utils/proxy.mjs
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
initializeProxy as initializeEdgeFunctionsProxy,
|
|
26
26
|
isEdgeFunctionsRequest,
|
|
27
27
|
} from '../lib/edge-functions/proxy.mjs'
|
|
28
|
-
import { fileExistsAsync, isFileAsync } from '../lib/fs.
|
|
28
|
+
import { fileExistsAsync, isFileAsync } from '../lib/fs.mjs'
|
|
29
29
|
import renderErrorTemplate from '../lib/render-error-template.mjs'
|
|
30
30
|
|
|
31
31
|
import { NETLIFYDEVLOG, NETLIFYDEVWARN } from './command-helpers.mjs'
|
|
@@ -6,7 +6,7 @@ import cookie from 'cookie'
|
|
|
6
6
|
import redirector from 'netlify-redirector'
|
|
7
7
|
import pFilter from 'p-filter'
|
|
8
8
|
|
|
9
|
-
import { fileExistsAsync } from '../lib/fs.
|
|
9
|
+
import { fileExistsAsync } from '../lib/fs.mjs'
|
|
10
10
|
|
|
11
11
|
import { NETLIFYDEVLOG } from './command-helpers.mjs'
|
|
12
12
|
import { parseRedirects } from './redirects.mjs'
|