netlify-cli 17.3.1 → 17.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/README.md +3 -139
- package/npm-shrinkwrap.json +82 -82
- package/package.json +16 -15
- package/src/commands/addons/addons-auth.mjs +27 -30
- package/src/commands/addons/addons-config.mjs +145 -154
- package/src/commands/addons/addons-create.mjs +94 -108
- package/src/commands/addons/addons-delete.mjs +36 -41
- package/src/commands/addons/addons-list.mjs +38 -42
- package/src/commands/addons/addons.mjs +26 -28
- package/src/commands/addons/index.mjs +1 -1
- package/src/commands/api/api.mjs +45 -53
- package/src/commands/api/index.mjs +1 -1
- package/src/commands/base-command.mjs +597 -684
- package/src/commands/blobs/blobs-delete.mjs +35 -0
- package/src/commands/blobs/blobs-get.mjs +44 -0
- package/src/commands/blobs/blobs-list.mjs +48 -0
- package/src/commands/blobs/blobs-set.mjs +54 -0
- package/src/commands/blobs/blobs.mjs +32 -0
- package/src/commands/blobs/index.mjs +1 -0
- package/src/commands/build/build.mjs +55 -67
- package/src/commands/build/index.mjs +1 -1
- package/src/commands/completion/completion.mjs +41 -46
- package/src/commands/completion/index.mjs +1 -1
- package/src/commands/deploy/deploy.mjs +675 -710
- package/src/commands/deploy/index.mjs +1 -1
- package/src/commands/dev/dev-exec.mjs +20 -32
- package/src/commands/dev/dev.mjs +217 -302
- package/src/commands/dev/index.mjs +1 -1
- package/src/commands/dev/types.d.ts +30 -0
- package/src/commands/env/env-clone.mjs +157 -184
- package/src/commands/env/env-get.mjs +49 -68
- package/src/commands/env/env-import.mjs +100 -119
- package/src/commands/env/env-list.mjs +104 -129
- package/src/commands/env/env-set.mjs +160 -185
- package/src/commands/env/env-unset.mjs +104 -122
- package/src/commands/env/env.mjs +28 -30
- package/src/commands/env/index.mjs +1 -1
- package/src/commands/functions/functions-build.mjs +29 -41
- package/src/commands/functions/functions-create.mjs +533 -601
- package/src/commands/functions/functions-invoke.mjs +193 -216
- package/src/commands/functions/functions-list.mjs +45 -55
- package/src/commands/functions/functions-serve.mjs +51 -61
- package/src/commands/functions/functions.mjs +26 -32
- package/src/commands/functions/index.mjs +1 -1
- package/src/commands/index.mjs +2 -2
- package/src/commands/init/index.mjs +1 -1
- package/src/commands/init/init.mjs +138 -167
- package/src/commands/integration/deploy.mjs +337 -399
- package/src/commands/integration/index.mjs +12 -13
- package/src/commands/link/index.mjs +1 -1
- package/src/commands/link/link.mjs +298 -317
- package/src/commands/lm/index.mjs +1 -1
- package/src/commands/lm/lm-info.mjs +23 -31
- package/src/commands/lm/lm-install.mjs +13 -17
- package/src/commands/lm/lm-setup.mjs +80 -84
- package/src/commands/lm/lm-uninstall.mjs +7 -12
- package/src/commands/lm/lm.mjs +18 -22
- package/src/commands/login/index.mjs +1 -1
- package/src/commands/login/login.mjs +35 -41
- package/src/commands/logout/index.mjs +1 -1
- package/src/commands/logout/logout.mjs +25 -31
- package/src/commands/main.mjs +166 -201
- package/src/commands/open/index.mjs +1 -1
- package/src/commands/open/open-admin.mjs +15 -18
- package/src/commands/open/open-site.mjs +16 -19
- package/src/commands/open/open.mjs +24 -27
- package/src/commands/recipes/common.mjs +23 -34
- package/src/commands/recipes/index.mjs +1 -1
- package/src/commands/recipes/recipes-list.mjs +13 -20
- package/src/commands/recipes/recipes.mjs +59 -72
- package/src/commands/serve/index.mjs +1 -1
- package/src/commands/serve/serve.mjs +142 -189
- package/src/commands/sites/index.mjs +2 -2
- package/src/commands/sites/sites-create-template.mjs +214 -236
- package/src/commands/sites/sites-create.mjs +145 -157
- package/src/commands/sites/sites-delete.mjs +75 -81
- package/src/commands/sites/sites-list.mjs +63 -66
- package/src/commands/sites/sites.mjs +18 -20
- package/src/commands/status/index.mjs +1 -1
- package/src/commands/status/status-hooks.mjs +32 -34
- package/src/commands/status/status.mjs +99 -106
- package/src/commands/switch/index.mjs +1 -1
- package/src/commands/switch/switch.mjs +32 -37
- package/src/commands/types.d.ts +31 -0
- package/src/commands/unlink/index.mjs +1 -1
- package/src/commands/unlink/unlink.mjs +23 -29
- package/src/commands/watch/index.mjs +1 -1
- package/src/commands/watch/watch.mjs +91 -105
- package/src/functions-templates/javascript/hello/{{name}}.js +2 -3
- package/src/lib/account.mjs +4 -5
- package/src/lib/api.mjs +22 -20
- package/src/lib/blobs/blobs.mjs +36 -45
- package/src/lib/build.mjs +82 -85
- package/src/lib/completion/constants.mjs +2 -4
- package/src/lib/completion/generate-autocompletion.mjs +33 -36
- package/src/lib/completion/get-autocompletion.mjs +31 -35
- package/src/lib/completion/index.mjs +1 -1
- package/src/lib/completion/script.mjs +12 -19
- package/src/lib/edge-functions/bootstrap.mjs +3 -5
- package/src/lib/edge-functions/consts.mjs +9 -10
- package/src/lib/edge-functions/deploy.mjs +28 -34
- package/src/lib/edge-functions/editor-helper.mjs +29 -42
- package/src/lib/edge-functions/headers.mjs +24 -26
- package/src/lib/edge-functions/internal.mjs +38 -44
- package/src/lib/edge-functions/proxy.mjs +229 -228
- package/src/lib/edge-functions/registry.mjs +473 -574
- package/src/lib/exec-fetcher.mjs +115 -122
- package/src/lib/fs.mjs +28 -27
- package/src/lib/functions/background.mjs +16 -20
- package/src/lib/functions/config.mjs +12 -9
- package/src/lib/functions/form-submissions-handler.mjs +143 -149
- package/src/lib/functions/local-proxy.mjs +40 -44
- package/src/lib/functions/memoized-build.mjs +19 -21
- package/src/lib/functions/netlify-function.mjs +269 -249
- package/src/lib/functions/registry.mjs +509 -568
- package/src/lib/functions/runtimes/go/index.mjs +62 -71
- package/src/lib/functions/runtimes/index.mjs +8 -15
- package/src/lib/functions/runtimes/js/builders/netlify-lambda.mjs +55 -64
- package/src/lib/functions/runtimes/js/builders/zisi.mjs +135 -154
- package/src/lib/functions/runtimes/js/constants.mjs +1 -1
- package/src/lib/functions/runtimes/js/index.mjs +92 -109
- package/src/lib/functions/runtimes/js/worker.mjs +43 -45
- package/src/lib/functions/runtimes/rust/index.mjs +64 -73
- package/src/lib/functions/scheduled.mjs +70 -88
- package/src/lib/functions/server.mjs +269 -327
- package/src/lib/functions/synchronous.mjs +118 -147
- package/src/lib/functions/utils.mjs +38 -46
- package/src/lib/geo-location.mjs +69 -81
- package/src/lib/http-agent.mjs +87 -90
- package/src/lib/images/proxy.mjs +97 -89
- package/src/lib/log.mjs +6 -9
- package/src/lib/path.mjs +2 -1
- package/src/lib/render-error-template.mjs +19 -20
- package/src/lib/settings.mjs +17 -19
- package/src/lib/spinner.mjs +21 -23
- package/src/lib/string.mjs +4 -2
- package/src/recipes/vscode/index.mjs +69 -85
- package/src/recipes/vscode/settings.mjs +53 -58
- package/src/utils/addons/compare.mjs +31 -32
- package/src/utils/addons/diffs/index.mjs +16 -17
- package/src/utils/addons/diffs/options.mjs +99 -101
- package/src/utils/addons/prepare.mjs +100 -97
- package/src/utils/addons/prompts.mjs +73 -76
- package/src/utils/addons/render.mjs +33 -36
- package/src/utils/addons/validation.mjs +19 -15
- package/src/utils/banner.mjs +11 -16
- package/src/utils/build-info.mjs +65 -66
- package/src/utils/command-helpers.mjs +185 -199
- package/src/utils/create-deferred.mjs +9 -12
- package/src/utils/create-stream-promise.mjs +54 -47
- package/src/utils/deploy/constants.mjs +9 -11
- package/src/utils/deploy/deploy-site.mjs +162 -182
- package/src/utils/deploy/hash-config.mjs +21 -21
- package/src/utils/deploy/hash-files.mjs +34 -38
- package/src/utils/deploy/hash-fns.mjs +149 -154
- package/src/utils/deploy/hasher-segments.mjs +58 -52
- package/src/utils/deploy/upload-files.mjs +99 -113
- package/src/utils/deploy/util.mjs +85 -91
- package/src/utils/detect-server-settings.mjs +236 -268
- package/src/utils/dev.mjs +163 -178
- package/src/utils/dot-env.mjs +37 -42
- package/src/utils/env/index.mjs +148 -148
- package/src/utils/execa.mjs +9 -13
- package/src/utils/feature-flags.mjs +6 -5
- package/src/utils/framework-server.mjs +43 -52
- package/src/utils/functions/constants.mjs +1 -1
- package/src/utils/functions/functions.mjs +30 -40
- package/src/utils/functions/get-functions.mjs +28 -29
- package/src/utils/functions/index.mjs +3 -3
- package/src/utils/get-global-config.mjs +33 -36
- package/src/utils/get-package-json.mjs +14 -15
- package/src/utils/get-repo-data.mjs +54 -64
- package/src/utils/get-site.mjs +14 -14
- package/src/utils/gh-auth.mjs +79 -100
- package/src/utils/gitignore.mjs +37 -40
- package/src/utils/headers.mjs +33 -35
- package/src/utils/hooks/requires-site-info.mjs +26 -22
- package/src/utils/init/config-github.mjs +207 -219
- package/src/utils/init/config-manual.mjs +83 -100
- package/src/utils/init/config.mjs +25 -26
- package/src/utils/init/node-version.mjs +23 -30
- package/src/utils/init/plugins.mjs +12 -8
- package/src/utils/init/utils.mjs +152 -172
- package/src/utils/live-tunnel.mjs +118 -141
- package/src/utils/lm/install.mjs +220 -259
- package/src/utils/lm/requirements.mjs +54 -63
- package/src/utils/lm/steps.mjs +31 -31
- package/src/utils/lm/ui.mjs +13 -20
- package/src/utils/open-browser.mjs +31 -32
- package/src/utils/parse-raw-flags.mjs +39 -35
- package/src/utils/proxy-server.mjs +84 -71
- package/src/utils/proxy.mjs +696 -750
- package/src/utils/read-repo-url.mjs +48 -47
- package/src/utils/redirects.mjs +49 -49
- package/src/utils/request-id.mjs +2 -4
- package/src/utils/rules-proxy.mjs +96 -100
- package/src/utils/run-build.mjs +109 -132
- package/src/utils/shell.mjs +99 -106
- package/src/utils/sign-redirect.mjs +14 -14
- package/src/utils/sites/utils.mjs +48 -55
- package/src/utils/state-config.mjs +101 -101
- package/src/utils/static-server.mjs +28 -34
- package/src/utils/telemetry/index.mjs +2 -2
- package/src/utils/telemetry/report-error.mjs +45 -49
- package/src/utils/telemetry/request.mjs +36 -43
- package/src/utils/telemetry/telemetry.mjs +90 -105
- package/src/utils/telemetry/utils.mjs +5 -6
- package/src/utils/telemetry/validation.mjs +55 -53
- package/src/utils/types.d.ts +46 -0
- package/src/utils/validation.mjs +10 -13
|
@@ -1,88 +1,81 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import { BACKGROUND, CLOCKWORK_USERAGENT, getFunctions } from '../../utils/functions/index.mjs'
|
|
11
|
-
|
|
12
|
-
const require = createRequire(import.meta.url)
|
|
13
|
-
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'node... Remove this comment to see the full error message
|
|
6
|
+
import fetch from 'node-fetch';
|
|
7
|
+
import { NETLIFYDEVWARN, chalk, error, exit } from '../../utils/command-helpers.mjs';
|
|
8
|
+
import { BACKGROUND, CLOCKWORK_USERAGENT, getFunctions } from '../../utils/functions/index.mjs';
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
14
10
|
// https://docs.netlify.com/functions/trigger-on-events/
|
|
15
11
|
const events = [
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
const DEFAULT_PORT = 8888
|
|
33
|
-
|
|
12
|
+
'deploy-building',
|
|
13
|
+
'deploy-succeeded',
|
|
14
|
+
'deploy-failed',
|
|
15
|
+
'deploy-locked',
|
|
16
|
+
'deploy-unlocked',
|
|
17
|
+
'split-test-activated',
|
|
18
|
+
'split-test-deactivated',
|
|
19
|
+
'split-test-modified',
|
|
20
|
+
'submission-created',
|
|
21
|
+
'identity-validate',
|
|
22
|
+
'identity-signup',
|
|
23
|
+
'identity-login',
|
|
24
|
+
];
|
|
25
|
+
const eventTriggeredFunctions = new Set([...events, ...events.map((name) => `${name}${BACKGROUND}`)]);
|
|
26
|
+
const DEFAULT_PORT = 8888;
|
|
34
27
|
// https://stackoverflow.com/questions/3710204/how-to-check-if-a-string-is-a-valid-json-string-in-javascript-without-using-try
|
|
28
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'jsonString' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
35
29
|
const tryParseJSON = function (jsonString) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
30
|
+
try {
|
|
31
|
+
const parsedValue = JSON.parse(jsonString);
|
|
32
|
+
// Handle non-exception-throwing cases:
|
|
33
|
+
// Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
|
|
34
|
+
// but... JSON.parse(null) returns null, and typeof null === "object",
|
|
35
|
+
// so we must check for that, too. Thankfully, null is falsey, so this suffices:
|
|
36
|
+
if (parsedValue && typeof parsedValue === 'object') {
|
|
37
|
+
return parsedValue;
|
|
38
|
+
}
|
|
45
39
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
catch { }
|
|
41
|
+
return false;
|
|
42
|
+
};
|
|
43
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'querystring' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
51
44
|
const formatQstring = function (querystring) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
45
|
+
if (querystring) {
|
|
46
|
+
return `?${querystring}`;
|
|
47
|
+
}
|
|
48
|
+
return '';
|
|
49
|
+
};
|
|
58
50
|
/**
|
|
59
51
|
* process payloads from flag
|
|
60
52
|
* @param {string} payloadString
|
|
61
53
|
* @param {string} workingDir
|
|
62
54
|
*/
|
|
55
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'payloadString' implicitly has an 'any' ... Remove this comment to see the full error message
|
|
63
56
|
const processPayloadFromFlag = function (payloadString, workingDir) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
57
|
+
if (payloadString) {
|
|
58
|
+
// case 1: jsonstring
|
|
59
|
+
let payload = tryParseJSON(payloadString);
|
|
60
|
+
if (payload)
|
|
61
|
+
return payload;
|
|
62
|
+
// case 2: jsonpath
|
|
63
|
+
const payloadpath = path.join(workingDir, payloadString);
|
|
64
|
+
const pathexists = fs.existsSync(payloadpath);
|
|
65
|
+
if (pathexists) {
|
|
66
|
+
try {
|
|
67
|
+
// there is code execution potential here
|
|
68
|
+
payload = require(payloadpath);
|
|
69
|
+
return payload;
|
|
70
|
+
}
|
|
71
|
+
catch (error_) {
|
|
72
|
+
console.error(error_);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// case 3: invalid string, invalid path
|
|
76
|
+
return false;
|
|
80
77
|
}
|
|
81
|
-
|
|
82
|
-
return false
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
78
|
+
};
|
|
86
79
|
/**
|
|
87
80
|
* prompt for a name if name not supplied
|
|
88
81
|
* also used in functions:create
|
|
@@ -91,182 +84,166 @@ const processPayloadFromFlag = function (payloadString, workingDir) {
|
|
|
91
84
|
* @param {string} [argumentName] The name that might be provided as argument (optional argument)
|
|
92
85
|
* @returns {Promise<string>}
|
|
93
86
|
*/
|
|
87
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'functions' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
94
88
|
const getNameFromArgs = async function (functions, options, argumentName) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
89
|
+
const functionToTrigger = getFunctionToTrigger(options, argumentName);
|
|
90
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'name' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
91
|
+
const functionNames = functions.map(({ name }) => name);
|
|
92
|
+
if (functionToTrigger) {
|
|
93
|
+
if (functionNames.includes(functionToTrigger)) {
|
|
94
|
+
return functionToTrigger;
|
|
95
|
+
}
|
|
96
|
+
console.warn(`Function name ${chalk.yellow(functionToTrigger)} supplied but no matching function found in your functions folder, forcing you to pick a valid one...`);
|
|
101
97
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
type: 'list',
|
|
113
|
-
message: 'Pick a function to trigger',
|
|
114
|
-
name: 'trigger',
|
|
115
|
-
choices: functionNames,
|
|
116
|
-
},
|
|
117
|
-
])
|
|
118
|
-
return trigger
|
|
119
|
-
}
|
|
120
|
-
|
|
98
|
+
const { trigger } = await inquirer.prompt([
|
|
99
|
+
{
|
|
100
|
+
type: 'list',
|
|
101
|
+
message: 'Pick a function to trigger',
|
|
102
|
+
name: 'trigger',
|
|
103
|
+
choices: functionNames,
|
|
104
|
+
},
|
|
105
|
+
]);
|
|
106
|
+
return trigger;
|
|
107
|
+
};
|
|
121
108
|
/**
|
|
122
109
|
* get the function name out of the argument or options
|
|
123
110
|
* @param {import('commander').OptionValues} options
|
|
124
111
|
* @param {string} [argumentName] The name that might be provided as argument (optional argument)
|
|
125
112
|
* @returns {string}
|
|
126
113
|
*/
|
|
114
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
|
|
127
115
|
const getFunctionToTrigger = function (options, argumentName) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
116
|
+
if (options.name) {
|
|
117
|
+
if (argumentName) {
|
|
118
|
+
console.error('function name specified in both flag and arg format, pick one');
|
|
119
|
+
exit(1);
|
|
120
|
+
}
|
|
121
|
+
return options.name;
|
|
132
122
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return argumentName
|
|
138
|
-
}
|
|
139
|
-
|
|
123
|
+
return argumentName;
|
|
124
|
+
};
|
|
140
125
|
/**
|
|
141
126
|
* The functions:invoke command
|
|
142
127
|
* @param {string} nameArgument
|
|
143
128
|
* @param {import('commander').OptionValues} options
|
|
144
129
|
* @param {import('../base-command.mjs').default} command
|
|
145
130
|
*/
|
|
131
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'nameArgument' implicitly has an 'any' t... Remove this comment to see the full error message
|
|
146
132
|
const functionsInvoke = async (nameArgument, options, command) => {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
error(`Functions directory is undefined, did you forget to set it in ${relConfigFilePath}?`)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (!options.port)
|
|
155
|
-
console.warn(`${NETLIFYDEVWARN} "port" flag was not specified. Attempting to connect to localhost:8888 by default`)
|
|
156
|
-
const port = options.port || DEFAULT_PORT
|
|
157
|
-
|
|
158
|
-
const functions = await getFunctions(functionsDir, config)
|
|
159
|
-
const functionToTrigger = await getNameFromArgs(functions, options, nameArgument)
|
|
160
|
-
const functionObj = functions.find((func) => func.name === functionToTrigger)
|
|
161
|
-
|
|
162
|
-
let headers = {}
|
|
163
|
-
let body = {}
|
|
164
|
-
|
|
165
|
-
if (functionObj.schedule) {
|
|
166
|
-
headers = {
|
|
167
|
-
'user-agent': CLOCKWORK_USERAGENT,
|
|
133
|
+
const { config, relConfigFilePath } = command.netlify;
|
|
134
|
+
const functionsDir = options.functions || (config.dev && config.dev.functions) || config.functionsDirectory;
|
|
135
|
+
if (typeof functionsDir === 'undefined') {
|
|
136
|
+
error(`Functions directory is undefined, did you forget to set it in ${relConfigFilePath}?`);
|
|
168
137
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
138
|
+
if (!options.port)
|
|
139
|
+
console.warn(`${NETLIFYDEVWARN} "port" flag was not specified. Attempting to connect to localhost:8888 by default`);
|
|
140
|
+
const port = options.port || DEFAULT_PORT;
|
|
141
|
+
const functions = await getFunctions(functionsDir, config);
|
|
142
|
+
const functionToTrigger = await getNameFromArgs(functions, options, nameArgument);
|
|
143
|
+
const functionObj = functions.find((func) => func.name === functionToTrigger);
|
|
144
|
+
let headers = {};
|
|
145
|
+
let body = {};
|
|
146
|
+
// @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'.
|
|
147
|
+
if (functionObj.schedule) {
|
|
148
|
+
headers = {
|
|
149
|
+
'user-agent': CLOCKWORK_USERAGENT,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
else if (eventTriggeredFunctions.has(functionToTrigger)) {
|
|
153
|
+
/** handle event triggered fns */
|
|
154
|
+
// https://docs.netlify.com/functions/trigger-on-events/
|
|
155
|
+
const [name, event] = functionToTrigger.split('-');
|
|
156
|
+
if (name === 'identity') {
|
|
157
|
+
// https://docs.netlify.com/functions/functions-and-identity/#trigger-functions-on-identity-events
|
|
158
|
+
// @ts-expect-error TS(2339) FIXME: Property 'event' does not exist on type '{}'.
|
|
159
|
+
body.event = event;
|
|
160
|
+
// @ts-expect-error TS(2339) FIXME: Property 'user' does not exist on type '{}'.
|
|
161
|
+
body.user = {
|
|
162
|
+
id: '1111a1a1-a11a-1111-aa11-aaa11111a11a',
|
|
163
|
+
aud: '',
|
|
164
|
+
role: '',
|
|
165
|
+
email: 'foo@trust-this-company.com',
|
|
166
|
+
app_metadata: {
|
|
167
|
+
provider: 'email',
|
|
168
|
+
},
|
|
169
|
+
user_metadata: {
|
|
170
|
+
full_name: 'Test Person',
|
|
171
|
+
},
|
|
172
|
+
created_at: new Date(Date.now()).toISOString(),
|
|
173
|
+
update_at: new Date(Date.now()).toISOString(),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
// non identity functions seem to have a different shape
|
|
178
|
+
// https://docs.netlify.com/functions/trigger-on-events/#payload
|
|
179
|
+
// @ts-expect-error TS(2339) FIXME: Property 'payload' does not exist on type '{}'.
|
|
180
|
+
body.payload = {
|
|
181
|
+
TODO: 'mock up payload data better',
|
|
182
|
+
};
|
|
183
|
+
// @ts-expect-error TS(2339) FIXME: Property 'site' does not exist on type '{}'.
|
|
184
|
+
body.site = {
|
|
185
|
+
TODO: 'mock up site data better',
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// NOT an event triggered function, but may still want to simulate authentication locally
|
|
191
|
+
const isAuthenticated = Boolean(options.identity);
|
|
192
|
+
if (isAuthenticated) {
|
|
193
|
+
headers = {
|
|
194
|
+
authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGZ1bmN0aW9uczp0cmlnZ2VyIiwidGVzdERhdGEiOiJORVRMSUZZX0RFVl9MT0NBTExZX0VNVUxBVEVEX0pXVCJ9.Xb6vOFrfLUZmyUkXBbCvU4bM7q8tPilF0F03Wupap_c',
|
|
195
|
+
};
|
|
196
|
+
// you can decode this https://jwt.io/
|
|
197
|
+
// {
|
|
198
|
+
// "source": "netlify functions:trigger",
|
|
199
|
+
// "testData": "NETLIFY_DEV_LOCALLY_EMULATED_JWT"
|
|
200
|
+
// }
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const payload = processPayloadFromFlag(options.payload, command.workingDir);
|
|
204
|
+
body = { ...body, ...payload };
|
|
205
|
+
try {
|
|
206
|
+
const response = await fetch(`http://localhost:${port}/.netlify/functions/${functionToTrigger}${formatQstring(options.querystring)}`, {
|
|
207
|
+
method: 'post',
|
|
208
|
+
headers,
|
|
209
|
+
body: JSON.stringify(body),
|
|
210
|
+
});
|
|
211
|
+
const data = await response.text();
|
|
212
|
+
console.log(data);
|
|
199
213
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (isAuthenticated) {
|
|
205
|
-
headers = {
|
|
206
|
-
authorization:
|
|
207
|
-
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGZ1bmN0aW9uczp0cmlnZ2VyIiwidGVzdERhdGEiOiJORVRMSUZZX0RFVl9MT0NBTExZX0VNVUxBVEVEX0pXVCJ9.Xb6vOFrfLUZmyUkXBbCvU4bM7q8tPilF0F03Wupap_c',
|
|
208
|
-
}
|
|
209
|
-
// you can decode this https://jwt.io/
|
|
210
|
-
// {
|
|
211
|
-
// "source": "netlify functions:trigger",
|
|
212
|
-
// "testData": "NETLIFY_DEV_LOCALLY_EMULATED_JWT"
|
|
213
|
-
// }
|
|
214
|
+
catch (error_) {
|
|
215
|
+
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
|
|
216
|
+
error(`Ran into an error invoking your function: ${error_.message}`);
|
|
214
217
|
}
|
|
215
|
-
|
|
216
|
-
const payload = processPayloadFromFlag(options.payload, command.workingDir)
|
|
217
|
-
body = { ...body, ...payload }
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
const response = await fetch(
|
|
221
|
-
`http://localhost:${port}/.netlify/functions/${functionToTrigger}${formatQstring(options.querystring)}`,
|
|
222
|
-
{
|
|
223
|
-
method: 'post',
|
|
224
|
-
headers,
|
|
225
|
-
body: JSON.stringify(body),
|
|
226
|
-
},
|
|
227
|
-
)
|
|
228
|
-
const data = await response.text()
|
|
229
|
-
console.log(data)
|
|
230
|
-
} catch (error_) {
|
|
231
|
-
error(`Ran into an error invoking your function: ${error_.message}`)
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
218
|
+
};
|
|
235
219
|
/**
|
|
236
220
|
* Creates the `netlify functions:invoke` command
|
|
237
221
|
* @param {import('../base-command.mjs').default} program
|
|
238
222
|
* @returns
|
|
239
223
|
*/
|
|
240
|
-
|
|
241
|
-
|
|
224
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type.
|
|
225
|
+
export const createFunctionsInvokeCommand = (program) => program
|
|
242
226
|
.command('functions:invoke')
|
|
243
227
|
.alias('function:trigger')
|
|
244
228
|
.argument('[name]', 'function name to invoke')
|
|
245
|
-
.description(
|
|
246
|
-
`Trigger a function while in netlify dev with simulated data, good for testing function calls including Netlify's Event Triggered Functions`,
|
|
247
|
-
)
|
|
229
|
+
.description(`Trigger a function while in netlify dev with simulated data, good for testing function calls including Netlify's Event Triggered Functions`)
|
|
248
230
|
.option('-n, --name <name>', 'function name to invoke')
|
|
249
231
|
.option('-f, --functions <dir>', 'Specify a functions folder to parse, overriding netlify.toml')
|
|
250
232
|
.option('-q, --querystring <query>', 'Querystring to add to your function invocation')
|
|
251
233
|
.option('-p, --payload <data>', 'Supply POST payload in stringified json, or a path to a json file')
|
|
252
234
|
// TODO: refactor to not need the `undefined` state by removing the --identity flag (value `identity` will be then always defined to true or false)
|
|
253
|
-
.option(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
)
|
|
257
|
-
.option(
|
|
258
|
-
'--no-identity',
|
|
259
|
-
'simulate Netlify Identity authentication JWT. pass --no-identity to affirm unauthenticated request',
|
|
260
|
-
)
|
|
235
|
+
.option('--identity', 'simulate Netlify Identity authentication JWT. pass --identity to affirm unauthenticated request')
|
|
236
|
+
.option('--no-identity', 'simulate Netlify Identity authentication JWT. pass --no-identity to affirm unauthenticated request')
|
|
237
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type.
|
|
261
238
|
.option('--port <port>', 'Port where netlify dev is accessible. e.g. 8888', (value) => Number.parseInt(value))
|
|
262
239
|
.addExamples([
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
.action(functionsInvoke)
|
|
240
|
+
'netlify functions:invoke',
|
|
241
|
+
'netlify functions:invoke myfunction',
|
|
242
|
+
'netlify functions:invoke --name myfunction',
|
|
243
|
+
'netlify functions:invoke --name myfunction --identity',
|
|
244
|
+
'netlify functions:invoke --name myfunction --no-identity',
|
|
245
|
+
`netlify functions:invoke myfunction --payload '{"foo": 1}'`,
|
|
246
|
+
'netlify functions:invoke myfunction --querystring "foo=1',
|
|
247
|
+
'netlify functions:invoke myfunction --payload "./pathTo.json"',
|
|
248
|
+
])
|
|
249
|
+
.action(functionsInvoke);
|
|
@@ -1,74 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs'
|
|
7
|
-
|
|
1
|
+
import AsciiTable from 'ascii-table';
|
|
2
|
+
import { exit, log, logJson } from '../../utils/command-helpers.mjs';
|
|
3
|
+
import { getFunctions, getFunctionsDir } from '../../utils/functions/index.mjs';
|
|
4
|
+
import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs';
|
|
5
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'deployedFunctions' implicitly has an 'a... Remove this comment to see the full error message
|
|
8
6
|
const normalizeFunction = function (deployedFunctions, { name, urlPath: url }) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
7
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'deployedFunction' implicitly has an 'an... Remove this comment to see the full error message
|
|
8
|
+
const isDeployed = deployedFunctions.some((deployedFunction) => deployedFunction.n === name);
|
|
9
|
+
return { name, url, isDeployed };
|
|
10
|
+
};
|
|
13
11
|
/**
|
|
14
12
|
* The functions:list command
|
|
15
13
|
* @param {import('commander').OptionValues} options
|
|
16
14
|
* @param {import('../base-command.mjs').default} command
|
|
17
15
|
*/
|
|
16
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
|
|
18
17
|
const functionsList = async (options, command) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
table.setHeading('Name', 'URL', 'deployed')
|
|
50
|
-
normalizedFunctions.forEach(({ isDeployed, name, url }) => {
|
|
51
|
-
table.addRow(name, url, isDeployed ? 'yes' : 'no')
|
|
52
|
-
})
|
|
53
|
-
log(table.toString())
|
|
54
|
-
}
|
|
55
|
-
|
|
18
|
+
const { config, relConfigFilePath, siteInfo } = command.netlify;
|
|
19
|
+
const deploy = siteInfo.published_deploy || {};
|
|
20
|
+
const deployedFunctions = deploy.available_functions || [];
|
|
21
|
+
// @ts-expect-error TS(2554) FIXME: Expected 2 arguments, but got 1.
|
|
22
|
+
const functionsDir = getFunctionsDir({ options, config });
|
|
23
|
+
if (typeof functionsDir === 'undefined') {
|
|
24
|
+
log('Functions directory is undefined');
|
|
25
|
+
log(`Please verify that 'functions.directory' is set in your Netlify configuration file ${relConfigFilePath}`);
|
|
26
|
+
log('Refer to https://ntl.fyi/file-based-build-config for more information');
|
|
27
|
+
exit(1);
|
|
28
|
+
}
|
|
29
|
+
const functions = await getFunctions(functionsDir);
|
|
30
|
+
const normalizedFunctions = functions.map(normalizeFunction.bind(null, deployedFunctions));
|
|
31
|
+
if (normalizedFunctions.length === 0) {
|
|
32
|
+
log(`No functions found in ${functionsDir}`);
|
|
33
|
+
exit();
|
|
34
|
+
}
|
|
35
|
+
if (options.json) {
|
|
36
|
+
logJson(normalizedFunctions);
|
|
37
|
+
exit();
|
|
38
|
+
}
|
|
39
|
+
// Make table
|
|
40
|
+
log(`Based on local functions folder ${functionsDir}, these are the functions detected`);
|
|
41
|
+
const table = new AsciiTable(`Netlify Functions (in local functions folder)`);
|
|
42
|
+
table.setHeading('Name', 'URL', 'deployed');
|
|
43
|
+
normalizedFunctions.forEach(({ isDeployed, name, url }) => {
|
|
44
|
+
table.addRow(name, url, isDeployed ? 'yes' : 'no');
|
|
45
|
+
});
|
|
46
|
+
log(table.toString());
|
|
47
|
+
};
|
|
56
48
|
/**
|
|
57
49
|
* Creates the `netlify functions:list` command
|
|
58
50
|
* @param {import('../base-command.mjs').default} program
|
|
59
51
|
* @returns
|
|
60
52
|
*/
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type.
|
|
54
|
+
export const createFunctionsListCommand = (program) => program
|
|
63
55
|
.command('functions:list')
|
|
64
56
|
.alias('function:list')
|
|
65
|
-
.description(
|
|
66
|
-
`List functions that exist locally
|
|
57
|
+
.description(`List functions that exist locally
|
|
67
58
|
Helpful for making sure that you have formatted your functions correctly
|
|
68
59
|
|
|
69
|
-
NOT the same as listing the functions that have been deployed. For that info you need to go to your Netlify deploy log
|
|
70
|
-
)
|
|
60
|
+
NOT the same as listing the functions that have been deployed. For that info you need to go to your Netlify deploy log.`)
|
|
71
61
|
.option('-f, --functions <dir>', 'Specify a functions directory to list')
|
|
72
62
|
.option('--json', 'Output function data as JSON')
|
|
73
63
|
.hook('preAction', requiresSiteInfo)
|
|
74
|
-
.action(functionsList)
|
|
64
|
+
.action(functionsList);
|