netlify-cli 9.1.0 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/npm-shrinkwrap.json +1172 -1155
- package/package.json +5 -6
- package/src/commands/dev/dev.js +6 -41
- package/src/commands/functions/functions-serve.js +2 -0
- package/src/commands/graph/graph-config-write.js +5 -2
- package/src/commands/graph/graph-edit.js +22 -7
- package/src/commands/graph/graph-handler.js +2 -2
- package/src/commands/graph/graph-library.js +9 -2
- package/src/commands/graph/graph-pull.js +5 -3
- package/src/lib/functions/server.js +58 -23
- package/src/lib/one-graph/cli-client.js +133 -14
- package/src/lib/one-graph/cli-netlify-graph.js +56 -33
- package/src/utils/dev.js +3 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
3
|
"description": "Netlify command line tool",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.4.0",
|
|
5
5
|
"author": "Netlify Inc.",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Abraham Schilling <AbrahamSchilling@gmail.com> (https://gitlab.com/n4bb12)",
|
|
@@ -164,7 +164,6 @@
|
|
|
164
164
|
"url": "https://github.com/netlify/cli/issues"
|
|
165
165
|
},
|
|
166
166
|
"scripts": {
|
|
167
|
-
"snap": "ava --verbose -u tests/integration/**/*graph*.test.js",
|
|
168
167
|
"prepare": "husky install node_modules/@netlify/eslint-config-node/.husky/",
|
|
169
168
|
"start": "node ./bin/run",
|
|
170
169
|
"test": "run-s format test:dev",
|
|
@@ -199,12 +198,12 @@
|
|
|
199
198
|
"prettier": "--ignore-path .gitignore --loglevel=warn \"{src,tools,scripts,site,tests,.github}/**/*.{mjs,cjs,js,md,yml,json,html}\" \"*.{mjs,cjs,js,yml,json,html}\" \".*.{mjs,cjs,js,yml,json,html}\" \"!CHANGELOG.md\" \"!npm-shrinkwrap.json\" \"!site/package-lock.json\" \"!.github/**/*.md\""
|
|
200
199
|
},
|
|
201
200
|
"dependencies": {
|
|
202
|
-
"@netlify/build": "^26.
|
|
203
|
-
"@netlify/config": "^17.0.
|
|
201
|
+
"@netlify/build": "^26.3.0",
|
|
202
|
+
"@netlify/config": "^17.0.8",
|
|
204
203
|
"@netlify/framework-info": "^9.0.0",
|
|
205
204
|
"@netlify/local-functions-proxy": "^1.1.1",
|
|
206
205
|
"@netlify/plugin-edge-handlers": "^3.0.6",
|
|
207
|
-
"@netlify/plugins-list": "^6.
|
|
206
|
+
"@netlify/plugins-list": "^6.10.1",
|
|
208
207
|
"@netlify/routing-local-proxy": "^0.34.1",
|
|
209
208
|
"@netlify/zip-it-and-ship-it": "^5.7.4",
|
|
210
209
|
"@octokit/rest": "^18.0.0",
|
|
@@ -271,7 +270,7 @@
|
|
|
271
270
|
"multiparty": "^4.2.1",
|
|
272
271
|
"netlify": "^11.0.0",
|
|
273
272
|
"netlify-headers-parser": "^6.0.1",
|
|
274
|
-
"netlify-onegraph-internal": "0.0.
|
|
273
|
+
"netlify-onegraph-internal": "0.0.42",
|
|
275
274
|
"netlify-redirect-parser": "^13.0.2",
|
|
276
275
|
"netlify-redirector": "^0.2.1",
|
|
277
276
|
"node-fetch": "^2.6.0",
|
package/src/commands/dev/dev.js
CHANGED
|
@@ -32,7 +32,6 @@ const {
|
|
|
32
32
|
detectServerSettings,
|
|
33
33
|
error,
|
|
34
34
|
exit,
|
|
35
|
-
generateAuthlifyJWT,
|
|
36
35
|
getSiteInformation,
|
|
37
36
|
injectEnvVariables,
|
|
38
37
|
log,
|
|
@@ -265,27 +264,7 @@ const dev = async (options, command) => {
|
|
|
265
264
|
}
|
|
266
265
|
|
|
267
266
|
const startNetlifyGraphWatcher = Boolean(options.graph)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (startNetlifyGraphWatcher) {
|
|
271
|
-
const netlifyToken = await command.authenticate()
|
|
272
|
-
authlifyJWT = generateAuthlifyJWT(netlifyToken, siteInfo.authlify_token_id, site.id)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
await injectEnvVariables({
|
|
276
|
-
env: Object.assign(
|
|
277
|
-
command.netlify.cachedConfig.env,
|
|
278
|
-
authlifyJWT == null
|
|
279
|
-
? {}
|
|
280
|
-
: {
|
|
281
|
-
ONEGRAPH_AUTHLIFY_TOKEN: {
|
|
282
|
-
sources: ['general'],
|
|
283
|
-
value: authlifyJWT,
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
),
|
|
287
|
-
site,
|
|
288
|
-
})
|
|
267
|
+
await injectEnvVariables({ env: command.netlify.cachedConfig.env, site })
|
|
289
268
|
|
|
290
269
|
const { addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({
|
|
291
270
|
// inherited from base command --offline
|
|
@@ -306,28 +285,14 @@ const dev = async (options, command) => {
|
|
|
306
285
|
|
|
307
286
|
command.setAnalyticsPayload({ projectType: settings.framework || 'custom', live: options.live })
|
|
308
287
|
|
|
309
|
-
let configWithAuthlify
|
|
310
|
-
|
|
311
|
-
if (siteInfo.authlify_token_id) {
|
|
312
|
-
const netlifyToken = command.authenticate()
|
|
313
|
-
// Only inject the authlify config if a token ID exists. This prevents
|
|
314
|
-
// calling command.authenticate() (which opens a browser window) if the
|
|
315
|
-
// user hasn't enabled API Authentication
|
|
316
|
-
configWithAuthlify = Object.assign(config, {
|
|
317
|
-
authlify: {
|
|
318
|
-
netlifyToken,
|
|
319
|
-
authlifyTokenId: siteInfo.authlify_token_id,
|
|
320
|
-
siteId: site.id,
|
|
321
|
-
},
|
|
322
|
-
})
|
|
323
|
-
} else {
|
|
324
|
-
configWithAuthlify = config
|
|
325
|
-
}
|
|
326
|
-
|
|
327
288
|
await startFunctionsServer({
|
|
328
|
-
|
|
289
|
+
api,
|
|
290
|
+
command,
|
|
291
|
+
config,
|
|
292
|
+
isGraphEnabled: startNetlifyGraphWatcher,
|
|
329
293
|
settings,
|
|
330
294
|
site,
|
|
295
|
+
siteInfo,
|
|
331
296
|
siteUrl,
|
|
332
297
|
capabilities,
|
|
333
298
|
timeouts,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
const fs = require('fs')
|
|
3
3
|
const path = require('path')
|
|
4
|
+
const process = require('process')
|
|
4
5
|
|
|
5
6
|
const { getNetlifyGraphConfig } = require('../../lib/one-graph/cli-netlify-graph')
|
|
6
|
-
const { NETLIFYDEVERR, chalk, error } = require('../../utils')
|
|
7
|
+
const { NETLIFYDEVERR, chalk, error, log } = require('../../utils')
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Creates the `netlify graph:config:write` command
|
|
@@ -33,8 +34,10 @@ const graphConfigWrite = async (options, command) => {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
const filePath = path.resolve(...netlifyGraphConfig.graphQLConfigJsonFilename)
|
|
36
|
-
|
|
37
37
|
fs.writeFileSync(filePath, JSON.stringify(graphQLConfig, null, 2))
|
|
38
|
+
|
|
39
|
+
const relativePath = path.relative(process.cwd(), filePath)
|
|
40
|
+
log(`Wrote ${chalk.cyan(relativePath)}`)
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
/**
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
const gitRepoInfo = require('git-repo-info')
|
|
3
3
|
|
|
4
|
-
const {
|
|
4
|
+
const {
|
|
5
|
+
OneGraphCliClient,
|
|
6
|
+
createCLISession,
|
|
7
|
+
generateSessionName,
|
|
8
|
+
loadCLISession,
|
|
9
|
+
upsertMergeCLISessionMetadata,
|
|
10
|
+
} = require('../../lib/one-graph/cli-client')
|
|
5
11
|
const {
|
|
6
12
|
defaultExampleOperationsDoc,
|
|
7
13
|
getGraphEditUrlBySiteId,
|
|
8
14
|
getNetlifyGraphConfig,
|
|
9
15
|
readGraphQLOperationsSourceFile,
|
|
10
16
|
} = require('../../lib/one-graph/cli-netlify-graph')
|
|
11
|
-
const { NETLIFYDEVERR, chalk, error } = require('../../utils')
|
|
17
|
+
const { NETLIFYDEVERR, chalk, error, log } = require('../../utils')
|
|
12
18
|
const { openBrowser } = require('../../utils/open-browser')
|
|
13
19
|
|
|
14
|
-
const {
|
|
20
|
+
const { createPersistedQuery, ensureAppForSite } = OneGraphCliClient
|
|
15
21
|
|
|
16
22
|
/**
|
|
17
23
|
* Creates the `netlify graph:edit` command
|
|
@@ -32,8 +38,6 @@ const graphEdit = async (options, command) => {
|
|
|
32
38
|
}
|
|
33
39
|
const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options })
|
|
34
40
|
|
|
35
|
-
const { branch } = gitRepoInfo()
|
|
36
|
-
|
|
37
41
|
let graphqlDocument = readGraphQLOperationsSourceFile(netlifyGraphConfig)
|
|
38
42
|
|
|
39
43
|
if (graphqlDocument.trim().length === 0) {
|
|
@@ -47,11 +51,12 @@ const graphEdit = async (options, command) => {
|
|
|
47
51
|
let oneGraphSessionId = loadCLISession(state)
|
|
48
52
|
if (!oneGraphSessionId) {
|
|
49
53
|
const sessionName = generateSessionName()
|
|
50
|
-
const oneGraphSession = await createCLISession(netlifyToken, site.id, sessionName,
|
|
54
|
+
const oneGraphSession = await createCLISession({ netlifyToken, siteId: site.id, sessionName, metadata: {} })
|
|
51
55
|
state.set('oneGraphSessionId', oneGraphSession.id)
|
|
52
56
|
oneGraphSessionId = state.get('oneGraphSessionId')
|
|
53
57
|
}
|
|
54
58
|
|
|
59
|
+
const { branch } = gitRepoInfo()
|
|
55
60
|
const persistedDoc = await createPersistedQuery(netlifyToken, {
|
|
56
61
|
appId: siteId,
|
|
57
62
|
description: 'Temporary snapshot of local queries',
|
|
@@ -59,10 +64,20 @@ const graphEdit = async (options, command) => {
|
|
|
59
64
|
tags: ['netlify-cli', `session:${oneGraphSessionId}`, `git-branch:${branch}`],
|
|
60
65
|
})
|
|
61
66
|
|
|
62
|
-
|
|
67
|
+
const newMetadata = { docId: persistedDoc.id }
|
|
68
|
+
|
|
69
|
+
await upsertMergeCLISessionMetadata({
|
|
70
|
+
netlifyGraphConfig,
|
|
71
|
+
netlifyToken,
|
|
72
|
+
siteId,
|
|
73
|
+
siteRoot: site.root,
|
|
74
|
+
oneGraphSessionId,
|
|
75
|
+
newMetadata,
|
|
76
|
+
})
|
|
63
77
|
|
|
64
78
|
const graphEditUrl = getGraphEditUrlBySiteId({ siteId, oneGraphSessionId })
|
|
65
79
|
|
|
80
|
+
log(`Opening graph:edit session at ${chalk.cyan(graphEditUrl)}`)
|
|
66
81
|
await openBrowser({ url: graphEditUrl })
|
|
67
82
|
}
|
|
68
83
|
|
|
@@ -5,7 +5,7 @@ const {
|
|
|
5
5
|
getNetlifyGraphConfig,
|
|
6
6
|
readGraphQLSchemaFile,
|
|
7
7
|
} = require('../../lib/one-graph/cli-netlify-graph')
|
|
8
|
-
const { error } = require('../../utils')
|
|
8
|
+
const { error, log } = require('../../utils')
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Creates the `netlify graph:handler` command
|
|
@@ -31,7 +31,7 @@ const graphHandler = async (operationName, options, command) => {
|
|
|
31
31
|
error(`Failed to parse Netlify GraphQL schema`)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
generateHandlerByOperationName(netlifyGraphConfig, schema, operationName, {})
|
|
34
|
+
generateHandlerByOperationName({ logger: log, netlifyGraphConfig, schema, operationName, handlerOptions: {} })
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/**
|
|
@@ -9,7 +9,7 @@ const {
|
|
|
9
9
|
readGraphQLOperationsSourceFile,
|
|
10
10
|
readGraphQLSchemaFile,
|
|
11
11
|
} = require('../../lib/one-graph/cli-netlify-graph')
|
|
12
|
-
const { error } = require('../../utils')
|
|
12
|
+
const { error, log } = require('../../utils')
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Creates the `netlify graph:library` command
|
|
@@ -42,7 +42,14 @@ const graphLibrary = async (options, command) => {
|
|
|
42
42
|
const parsedDoc = parse(currentOperationsDoc)
|
|
43
43
|
const { fragments, functions } = extractFunctionsFromOperationDoc(parsedDoc)
|
|
44
44
|
|
|
45
|
-
generateFunctionsFile({
|
|
45
|
+
generateFunctionsFile({
|
|
46
|
+
logger: log,
|
|
47
|
+
netlifyGraphConfig,
|
|
48
|
+
schema,
|
|
49
|
+
operationsDoc: currentOperationsDoc,
|
|
50
|
+
functions,
|
|
51
|
+
fragments,
|
|
52
|
+
})
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
/**
|
|
@@ -8,7 +8,7 @@ const {
|
|
|
8
8
|
refetchAndGenerateFromOneGraph,
|
|
9
9
|
} = require('../../lib/one-graph/cli-client')
|
|
10
10
|
const { buildSchema, getNetlifyGraphConfig, readGraphQLSchemaFile } = require('../../lib/one-graph/cli-netlify-graph')
|
|
11
|
-
const { chalk, error, warn } = require('../../utils')
|
|
11
|
+
const { chalk, error, log, warn } = require('../../utils')
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Creates the `netlify graph:pull` command
|
|
@@ -31,12 +31,14 @@ const graphPull = async (options, command) => {
|
|
|
31
31
|
const netlifyToken = await command.authenticate()
|
|
32
32
|
const siteId = site.id
|
|
33
33
|
|
|
34
|
-
await refetchAndGenerateFromOneGraph({ netlifyGraphConfig, netlifyToken, state, siteId })
|
|
34
|
+
await refetchAndGenerateFromOneGraph({ logger: log, netlifyGraphConfig, netlifyToken, state, siteId })
|
|
35
35
|
|
|
36
36
|
const oneGraphSessionId = loadCLISession(state)
|
|
37
37
|
|
|
38
38
|
if (!oneGraphSessionId) {
|
|
39
|
-
warn(
|
|
39
|
+
warn(
|
|
40
|
+
'No local Netlify Graph session found, skipping command queue drain. Create a new session by running `netlify graph:edit`.',
|
|
41
|
+
)
|
|
40
42
|
return
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
+
const process = require('process')
|
|
3
|
+
|
|
2
4
|
const jwtDecode = require('jwt-decode')
|
|
3
5
|
|
|
4
6
|
const {
|
|
@@ -6,7 +8,7 @@ const {
|
|
|
6
8
|
NETLIFYDEVERR,
|
|
7
9
|
NETLIFYDEVLOG,
|
|
8
10
|
error: errorExit,
|
|
9
|
-
|
|
11
|
+
generateNetlifyGraphJWT,
|
|
10
12
|
getInternalFunctionsDir,
|
|
11
13
|
log,
|
|
12
14
|
} = require('../../utils')
|
|
@@ -45,7 +47,51 @@ const buildClientContext = function (headers) {
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
const
|
|
50
|
+
const startPollingForAPIAuthentication = async function (options) {
|
|
51
|
+
const { api, command, config, site, siteInfo } = options
|
|
52
|
+
const frequency = 5000
|
|
53
|
+
|
|
54
|
+
const helper = async (maybeSiteData) => {
|
|
55
|
+
const siteData = await (maybeSiteData || api.getSite({ siteId: site.id }))
|
|
56
|
+
const authlifyTokenId = siteData && siteData.authlify_token_id
|
|
57
|
+
|
|
58
|
+
const existingAuthlifyTokenId = config && config.netlifyGraphConfig && config.netlifyGraphConfig.authlifyTokenId
|
|
59
|
+
if (authlifyTokenId && authlifyTokenId !== existingAuthlifyTokenId) {
|
|
60
|
+
const netlifyToken = await command.authenticate()
|
|
61
|
+
// Only inject the authlify config if a token ID exists. This prevents
|
|
62
|
+
// calling command.authenticate() (which opens a browser window) if the
|
|
63
|
+
// user hasn't enabled API Authentication
|
|
64
|
+
const netlifyGraphConfig = {
|
|
65
|
+
netlifyToken,
|
|
66
|
+
authlifyTokenId: siteData.authlify_token_id,
|
|
67
|
+
siteId: site.id,
|
|
68
|
+
}
|
|
69
|
+
config.netlifyGraphConfig = netlifyGraphConfig
|
|
70
|
+
|
|
71
|
+
const netlifyGraphJWT = generateNetlifyGraphJWT(netlifyGraphConfig)
|
|
72
|
+
|
|
73
|
+
if (netlifyGraphJWT != null) {
|
|
74
|
+
// XXX(anmonteiro): this name is deprecated. Delete after 3/31/2022
|
|
75
|
+
process.env.ONEGRAPH_AUTHLIFY_TOKEN = netlifyGraphJWT
|
|
76
|
+
process.env.NETLIFY_GRAPH_TOKEN = netlifyGraphJWT
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
delete config.authlify
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
setTimeout(helper, frequency)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
await helper(siteInfo)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const createHandler = function (options) {
|
|
89
|
+
const { config, functionsRegistry } = options
|
|
90
|
+
|
|
91
|
+
if (options.isGraphEnabled) {
|
|
92
|
+
startPollingForAPIAuthentication(options)
|
|
93
|
+
}
|
|
94
|
+
|
|
49
95
|
return async function handler(request, response) {
|
|
50
96
|
// handle proxies without path re-writes (http-servr)
|
|
51
97
|
const cleanPath = request.path.replace(/^\/.netlify\/(functions|builders)/, '')
|
|
@@ -107,8 +153,10 @@ const createHandler = function ({ config, functionsRegistry }) {
|
|
|
107
153
|
}
|
|
108
154
|
|
|
109
155
|
if (config && config.authlify && config.authlify.authlifyTokenId != null) {
|
|
110
|
-
|
|
111
|
-
|
|
156
|
+
// XXX(anmonteiro): this name is deprecated. Delete after 3/31/2022
|
|
157
|
+
const jwt = generateNetlifyGraphJWT(config.netlifyGraphConfig)
|
|
158
|
+
event.authlifyToken = jwt
|
|
159
|
+
event.netlifyGraphToken = jwt
|
|
112
160
|
}
|
|
113
161
|
|
|
114
162
|
const clientContext = buildClientContext(request.headers) || {}
|
|
@@ -160,14 +208,15 @@ const createHandler = function ({ config, functionsRegistry }) {
|
|
|
160
208
|
}
|
|
161
209
|
}
|
|
162
210
|
|
|
163
|
-
const getFunctionsServer = function (
|
|
211
|
+
const getFunctionsServer = function (options) {
|
|
212
|
+
const { buildersPrefix = '', functionsPrefix = '', functionsRegistry, siteUrl } = options
|
|
164
213
|
// performance optimization, load express on demand
|
|
165
214
|
// eslint-disable-next-line node/global-require
|
|
166
215
|
const express = require('express')
|
|
167
216
|
// eslint-disable-next-line node/global-require
|
|
168
217
|
const expressLogging = require('express-logging')
|
|
169
218
|
const app = express()
|
|
170
|
-
const functionHandler = createHandler(
|
|
219
|
+
const functionHandler = createHandler(options)
|
|
171
220
|
|
|
172
221
|
app.set('query parser', 'simple')
|
|
173
222
|
|
|
@@ -195,16 +244,8 @@ const getFunctionsServer = function ({ buildersPrefix, config, functionsPrefix,
|
|
|
195
244
|
return app
|
|
196
245
|
}
|
|
197
246
|
|
|
198
|
-
const startFunctionsServer = async ({
|
|
199
|
-
|
|
200
|
-
capabilities,
|
|
201
|
-
config,
|
|
202
|
-
functionsPrefix = '',
|
|
203
|
-
settings,
|
|
204
|
-
site,
|
|
205
|
-
siteUrl,
|
|
206
|
-
timeouts,
|
|
207
|
-
}) => {
|
|
247
|
+
const startFunctionsServer = async (options) => {
|
|
248
|
+
const { capabilities, config, settings, site, siteUrl, timeouts } = options
|
|
208
249
|
const internalFunctionsDir = await getInternalFunctionsDir({ base: site.root })
|
|
209
250
|
|
|
210
251
|
// The order of the function directories matters. Leftmost directories take
|
|
@@ -223,13 +264,7 @@ const startFunctionsServer = async ({
|
|
|
223
264
|
|
|
224
265
|
await functionsRegistry.scan(functionsDirectories)
|
|
225
266
|
|
|
226
|
-
const server = getFunctionsServer({
|
|
227
|
-
config,
|
|
228
|
-
functionsRegistry,
|
|
229
|
-
siteUrl,
|
|
230
|
-
functionsPrefix,
|
|
231
|
-
buildersPrefix,
|
|
232
|
-
})
|
|
267
|
+
const server = getFunctionsServer(Object.assign(options, { functionsRegistry }))
|
|
233
268
|
|
|
234
269
|
await startWebServer({ server, settings })
|
|
235
270
|
}
|