@webiny/cli 0.0.0-mt-1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Webiny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # webiny-cli
2
+ [![](https://img.shields.io/npm/dw/webiny-cli.svg)](https://www.npmjs.com/package/webiny-cli)
3
+ [![](https://img.shields.io/npm/v/webiny-cli.svg)](https://www.npmjs.com/package/webiny-cli)
4
+ [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
5
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
6
+
7
+ A pluggable tool to run commands within a Webiny project.
package/bin.js ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const chalk = require("chalk");
5
+ const execa = require("execa");
6
+ const semver = require("semver");
7
+ const currentNodeVersion = process.versions.node;
8
+
9
+ (async () => {
10
+ if (!semver.satisfies(currentNodeVersion, "^12 || ^14")) {
11
+ console.error(
12
+ chalk.red(
13
+ "You are running Node " +
14
+ currentNodeVersion +
15
+ ".\n" +
16
+ "Webiny requires Node ^12 or ^14. \n" +
17
+ "Please update your version of Node."
18
+ )
19
+ );
20
+ process.exit(1);
21
+ }
22
+
23
+ try {
24
+ const { stdout } = await execa("yarn", ["--version"]);
25
+ if (!semver.satisfies(stdout, "^2||^3")) {
26
+ console.error(chalk.red(`"@webiny/cli" requires yarn ^2 or ^3 to be installed!`));
27
+ process.exit(1);
28
+ }
29
+ } catch (err) {
30
+ console.error(chalk.red(`"@webiny/cli" requires yarn ^2 or ^3 to be installed!`));
31
+ console.log(`Please visit https://yarnpkg.com/ to install "yarn".`);
32
+ process.exit(1);
33
+ }
34
+
35
+ require("./cli");
36
+ })();
package/cli.js ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ const path = require("path");
3
+ const yargs = require("yargs");
4
+ const { log, getProject } = require("./utils");
5
+ const { boolean } = require("boolean");
6
+
7
+ // Disable help processing until after plugins are imported.
8
+ yargs.help(false);
9
+
10
+ // Immediately load .env.{PASSED_ENVIRONMENT} and .env files.
11
+ // This way we ensure all of the environment variables are not loaded too late.
12
+ const project = getProject();
13
+ let paths = [path.join(project.root, ".env")];
14
+
15
+ if (yargs.argv.env) {
16
+ paths.push(path.join(project.root, `.env.${yargs.argv.env}`));
17
+ }
18
+
19
+ for (let i = 0; i < paths.length; i++) {
20
+ const path = paths[i];
21
+ const { error } = require("dotenv").config({ path });
22
+ if (boolean(yargs.argv.debug)) {
23
+ if (error) {
24
+ log.debug(`No environment file found on ${log.debug.hl(path)}.`);
25
+ } else {
26
+ log.success(`Successfully loaded environment variables from ${log.success.hl(path)}.`);
27
+ }
28
+ }
29
+ }
30
+
31
+ const { blue, red } = require("chalk");
32
+ const context = require("./context");
33
+ const { createCommands } = require("./commands");
34
+
35
+ yargs
36
+ .usage("Usage: $0 <command> [options]")
37
+ .demandCommand(1)
38
+ .recommendCommands()
39
+ .scriptName("webiny")
40
+ .epilogue(
41
+ `To find more information, docs and tutorials, see ${blue("https://docs.webiny.com")}.`
42
+ )
43
+ .epilogue(`Want to contribute? ${blue("https://github.com/webiny/webiny-js")}.`)
44
+ .fail(function (msg, error, yargs) {
45
+ if (msg) {
46
+ if (msg.includes("Not enough non-option arguments")) {
47
+ console.log();
48
+ context.error(red("Command was not invoked as expected!"));
49
+ context.info(
50
+ `Some non-optional arguments are missing. See the usage examples printed below.`
51
+ );
52
+ console.log();
53
+ yargs.showHelp();
54
+ return;
55
+ }
56
+
57
+ if (msg.includes("Missing required argument")) {
58
+ const args = msg
59
+ .split(":")[1]
60
+ .split(",")
61
+ .map(v => v.trim());
62
+
63
+ console.log();
64
+ context.error(red("Command was not invoked as expected!"));
65
+ context.info(
66
+ `Missing required argument(s): ${args
67
+ .map(arg => red(arg))
68
+ .join(", ")}. See the usage examples printed below.`
69
+ );
70
+ console.log();
71
+ yargs.showHelp();
72
+ return;
73
+ }
74
+ console.log();
75
+ context.error(red("Command execution was aborted!"));
76
+ context.error(msg);
77
+ console.log();
78
+
79
+ process.exit(1);
80
+ }
81
+
82
+ if (error) {
83
+ context.error(error.message);
84
+ // Unfortunately, yargs doesn't provide passed args here, so we had to do it via process.argv.
85
+ if (process.argv.includes("--debug")) {
86
+ context.debug(error);
87
+ }
88
+
89
+ console.log();
90
+ const plugins = context.plugins.byType("cli-command-error");
91
+ for (let i = 0; i < plugins.length; i++) {
92
+ const plugin = plugins[i];
93
+ plugin.handle({
94
+ error,
95
+ context
96
+ });
97
+ }
98
+ }
99
+
100
+ process.exit(1);
101
+ });
102
+
103
+ (async () => {
104
+ await createCommands(yargs, context);
105
+ // Enable help and run the CLI.
106
+ yargs.help().argv;
107
+ })();
@@ -0,0 +1,13 @@
1
+ const run = require("./run");
2
+ const telemetry = require("./telemetry");
3
+ const upgrade = require("./upgrade");
4
+
5
+ module.exports.createCommands = async (yargs, context) => {
6
+ context.plugins.register(run, telemetry, upgrade);
7
+
8
+ await context.loadUserPlugins();
9
+
10
+ context.plugins.byType("cli-command").forEach(plugin => {
11
+ plugin.create({ yargs, context });
12
+ });
13
+ };
@@ -0,0 +1,30 @@
1
+ const camelCase = require("camelcase");
2
+ const findUp = require("find-up");
3
+
4
+ module.exports = {
5
+ type: "cli-command",
6
+ name: "cli-command-run",
7
+ create({ yargs, context }) {
8
+ yargs.command(
9
+ "run <command> [options]",
10
+ `Run command defined in webiny.config.{js,ts}.\nNote: run from folder containing webiny.config.{js,ts} file.`,
11
+ yargs => {
12
+ yargs.positional("command", {
13
+ describe: `Command to run in webiny.config.{js,ts}`,
14
+ type: "string"
15
+ });
16
+ },
17
+ async argv => {
18
+ const configFile = findUp.sync(["webiny.config.ts", "webiny.config.js"]);
19
+ const config = context.import(configFile);
20
+
21
+ const command = camelCase(argv.command);
22
+ if (config.commands && typeof config.commands[command] === "function") {
23
+ return await config.commands[command]({ ...argv }, context);
24
+ }
25
+
26
+ throw Error(`Command "${command}" is not defined in "${configFile}"!`);
27
+ }
28
+ );
29
+ }
30
+ };
@@ -0,0 +1,31 @@
1
+ const telemetry = require("@webiny/telemetry/cli");
2
+
3
+ module.exports = {
4
+ type: "cli-command",
5
+ name: "cli-command-telemetry",
6
+ create({ yargs, context }) {
7
+ yargs.command("enable-telemetry", "Enable anonymous telemetry.", async () => {
8
+ telemetry.enable();
9
+ await telemetry.sendEvent({ event: "enable-telemetry" });
10
+ context.info(
11
+ `Webiny telemetry is now ${context.info.hl(
12
+ "enabled"
13
+ )}! Thank you for helping us in making Webiny better!`
14
+ );
15
+ context.info(
16
+ `For more information, please visit the following link: https://www.webiny.com/telemetry.`
17
+ );
18
+ });
19
+
20
+ yargs.command("disable-telemetry", "Disable anonymous telemetry.", async () => {
21
+ await telemetry.sendEvent({ event: "disable-telemetry" });
22
+ telemetry.disable();
23
+ context.info(`Webiny telemetry is now ${context.info.hl("disabled")}!`);
24
+ context.info(
25
+ `Note that, in order to complete the process, you will also need to re-deploy your project, using the ${context.info.hl(
26
+ "yarn webiny deploy"
27
+ )} command.`
28
+ );
29
+ });
30
+ }
31
+ };
@@ -0,0 +1,107 @@
1
+ const { red } = require("chalk");
2
+ const execa = require("execa");
3
+ const semver = require("semver");
4
+
5
+ module.exports = [
6
+ {
7
+ type: "cli-command",
8
+ name: "cli-command-upgrade",
9
+ create({ yargs, context }) {
10
+ yargs.example("$0 upgrade");
11
+ yargs.command(
12
+ "upgrade",
13
+ `Run an upgrade script for currently installed version of Webiny`,
14
+ yargs => {
15
+ yargs.option("skip-checks", {
16
+ describe: "Do not perform CLI version and Git tree checks.",
17
+ type: "boolean",
18
+ default: false
19
+ });
20
+ yargs.option("debug", {
21
+ default: false,
22
+ describe: `Turn on debug logs`,
23
+ type: "boolean"
24
+ });
25
+ yargs.option("use-version", {
26
+ describe:
27
+ "Use upgrade script for a specific version. Should only be used for development/testing purposes.",
28
+ type: "string"
29
+ });
30
+ },
31
+ async argv => {
32
+ if (!argv.skipChecks) {
33
+ // Before doing any upgrading, there must not be any active changes in the current branch.
34
+ let gitStatus = "";
35
+ try {
36
+ let { stdout } = execa.sync("git", ["status", "--porcelain"]);
37
+ gitStatus = stdout.trim();
38
+ } catch {}
39
+
40
+ if (gitStatus) {
41
+ console.error(
42
+ red(
43
+ "This git repository has untracked files or uncommitted changes:"
44
+ ) +
45
+ "\n\n" +
46
+ gitStatus
47
+ .split("\n")
48
+ .map(line => line.match(/ .*/g)[0].trim())
49
+ .join("\n") +
50
+ "\n\n" +
51
+ red(
52
+ "Remove untracked files, stash or commit any changes, and try again."
53
+ )
54
+ );
55
+ process.exit(1);
56
+ }
57
+ }
58
+
59
+ const defaultUpgradeTargetVersion = semver.coerce(context.version).version;
60
+
61
+ const command = [
62
+ "https://github.com/webiny/webiny-upgrades",
63
+ argv.useVersion || defaultUpgradeTargetVersion
64
+ ];
65
+
66
+ if (yargs.argv.debug) {
67
+ context.debug("npx", ...command);
68
+ }
69
+
70
+ const npx = execa("npx", command, {
71
+ env: {
72
+ FORCE_COLOR: true
73
+ }
74
+ });
75
+
76
+ npx.stdout.on("data", data => {
77
+ const lines = data.toString().replace(/\n$/, "").split("\n");
78
+ for (let i = 0; i < lines.length; i++) {
79
+ const line = lines[i];
80
+ try {
81
+ const json = JSON.parse(line);
82
+ if (json.type === "error") {
83
+ context.error(
84
+ "An error occurred while performing the upgrade."
85
+ );
86
+ console.log(json.message);
87
+ if (yargs.argv.debug) {
88
+ context.debug(json.data.stack);
89
+ }
90
+ }
91
+ } catch {
92
+ // Not JSON, let's just print the line then.
93
+ console.log(line);
94
+ }
95
+ }
96
+ });
97
+
98
+ npx.stderr.on("data", data => {
99
+ console.log(data.toString());
100
+ });
101
+
102
+ await npx;
103
+ }
104
+ );
105
+ }
106
+ }
107
+ ];
package/context.js ADDED
@@ -0,0 +1,137 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const { importModule, getProject, PluginsContainer, log, localStorage } = require("./utils");
4
+
5
+ const project = getProject();
6
+
7
+ if (!project) {
8
+ console.log(
9
+ `🚨 Couldn't locate "webiny.project.js"! Webiny CLI relies on that file to find the root of a Webiny project.`
10
+ );
11
+ process.exit(1);
12
+ }
13
+
14
+ class Context {
15
+ constructor() {
16
+ this.loadedEnvFiles = {};
17
+
18
+ this.version = require("./package.json").version;
19
+ this.project = project;
20
+
21
+ // Check if `projectName` was injected properly.
22
+ if (this.project.name === "[PROJECT_NAME]") {
23
+ console.log(
24
+ [
25
+ "",
26
+ "🚨 IMPORTANT 🚨",
27
+ "Looks like your project was not bootstrapped correctly! We recommend creating a new project from scratch.",
28
+ "If you see errors during project creation, please report them to us:",
29
+ "🔗 Github:\thttps://github.com/webiny/webiny-js",
30
+ "🔗 Slack:\thttps://www.webiny.com/slack",
31
+ ""
32
+ ].join("\n")
33
+ );
34
+ process.exit(1);
35
+ }
36
+
37
+ this.plugins = new PluginsContainer();
38
+
39
+ this.localStorage = localStorage();
40
+
41
+ this.onExitCallbacks = [];
42
+
43
+ let onExitProcessed = false;
44
+ process.on("SIGINT", async () => {
45
+ if (onExitProcessed) {
46
+ return;
47
+ }
48
+
49
+ onExitProcessed = true;
50
+
51
+ for (let i = 0; i < this.onExitCallbacks.length; i++) {
52
+ await this.onExitCallbacks[i]("SIGINT");
53
+ }
54
+
55
+ process.exit(1);
56
+ });
57
+ }
58
+
59
+ onExit(callback) {
60
+ this.onExitCallbacks.push(callback);
61
+ }
62
+
63
+ import(name) {
64
+ return importModule(name);
65
+ }
66
+
67
+ async loadUserPlugins() {
68
+ if (this.project.config.cli) {
69
+ let plugins = this.project.config.cli.plugins || [];
70
+ if (typeof plugins === "function") {
71
+ plugins = await plugins();
72
+ }
73
+
74
+ this.plugins.register(
75
+ ...plugins.map(plugin => {
76
+ if (typeof plugin === "string") {
77
+ let loadedPlugin;
78
+ try {
79
+ loadedPlugin = require(path.join(this.project.root, plugin)); // Try loading the package from the project's root
80
+ } catch {
81
+ // If it fails, perhaps the user still has the package installed somewhere locally...
82
+ loadedPlugin = require(plugin);
83
+ }
84
+ return loadedPlugin;
85
+ }
86
+ return plugin;
87
+ })
88
+ );
89
+ }
90
+ }
91
+
92
+ log = log.log;
93
+ info = log.info;
94
+ success = log.success;
95
+ debug = log.debug;
96
+ warning = log.warning;
97
+ error = log.error;
98
+
99
+ resolve(...dir) {
100
+ return path.resolve(this.project.root, ...dir);
101
+ }
102
+
103
+ replaceProjectRoot(path) {
104
+ return path.replace(this.project.root, "<projectRoot>").replace(/\\/g, "/");
105
+ }
106
+
107
+ /**
108
+ * Uses `dotenv` lib to load env files, by accepting a simple file path.
109
+ * @param filePath
110
+ * @param debug
111
+ * @returns {Promise<void>}
112
+ */
113
+ async loadEnv(filePath, { debug = false } = {}) {
114
+ if (this.loadedEnvFiles[filePath]) {
115
+ return;
116
+ }
117
+
118
+ if (!fs.existsSync(filePath)) {
119
+ debug && this.debug(`No environment file found on ${this.debug.hl(filePath)}.`);
120
+ return;
121
+ }
122
+
123
+ try {
124
+ require("dotenv").config({ path: filePath });
125
+ debug && this.success(`Loaded environment variables from ${filePath}.`);
126
+ this.loadedEnvFiles[filePath] = true;
127
+ } catch (err) {
128
+ if (debug) {
129
+ this.error(`Could not load env variables from ${filePath}:`);
130
+ this.error(err.message);
131
+ console.log();
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ module.exports = new Context();
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@webiny/cli",
3
+ "version": "0.0.0-mt-1",
4
+ "main": "index.js",
5
+ "bin": {
6
+ "webiny": "./bin.js"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/webiny/webiny-js.git",
11
+ "directory": "packages/cli"
12
+ },
13
+ "author": "Pavel Denisjuk <pavel@webiny.com>",
14
+ "description": "A tool to bootstrap a Webiny project.",
15
+ "dependencies": {
16
+ "@webiny/telemetry": "0.0.0-mt-1",
17
+ "boolean": "3.1.4",
18
+ "camelcase": "5.3.1",
19
+ "chalk": "4.1.2",
20
+ "dotenv": "8.2.0",
21
+ "execa": "2.1.0",
22
+ "fast-glob": "3.2.7",
23
+ "find-up": "5.0.0",
24
+ "pirates": "4.0.1",
25
+ "semver": "7.3.4",
26
+ "typescript": "4.1.3",
27
+ "uniqid": "5.4.0",
28
+ "yargs": "14.2.3"
29
+ },
30
+ "license": "MIT",
31
+ "publishConfig": {
32
+ "access": "public",
33
+ "directory": "."
34
+ },
35
+ "adio": {
36
+ "ignoreDirs": [
37
+ "/create/template/",
38
+ "/node_modules/",
39
+ "/dist/"
40
+ ],
41
+ "ignore": {
42
+ "src": [
43
+ "@webiny/project-utils",
44
+ "@webiny/api-file-manager",
45
+ "@webiny/cli-plugin-deploy-pulumi",
46
+ "@webiny/handler",
47
+ "@webiny/handler-http",
48
+ "@webiny/handler-args",
49
+ "@webiny/handler-client",
50
+ "@webiny/api-elasticsearch",
51
+ "@webiny/api-tenancy",
52
+ "@webiny/api-security",
53
+ "@webiny/api-i18n",
54
+ "@webiny/api-i18n-content",
55
+ "@webiny/api-page-builder",
56
+ "@webiny/api-prerendering-service",
57
+ "@webiny/api-form-builder",
58
+ "@webiny/api-headless-cms"
59
+ ]
60
+ }
61
+ },
62
+ "gitHead": "37736d8456a6ecb342a6c3645060bd9a3f2d4bb0"
63
+ }