mfer 1.4.2 → 1.5.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 +14 -3
- package/dist/commands/run.js +96 -35
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,11 +123,22 @@ Run micro frontend applications concurrently.
|
|
|
123
123
|
|
|
124
124
|
- `group_name`: Name of the group to run (defaults to "all")
|
|
125
125
|
|
|
126
|
-
**
|
|
126
|
+
**Options:**
|
|
127
|
+
|
|
128
|
+
- `-c, --command <command>`: Custom command to run (default: npm start)
|
|
129
|
+
- `-a, --async`: Run custom command concurrently instead of sequentially
|
|
130
|
+
- `-s, --select`: Prompt to select which micro frontends to run
|
|
131
|
+
|
|
132
|
+
**Examples:**
|
|
127
133
|
|
|
128
134
|
```bash
|
|
129
|
-
mfer run
|
|
130
|
-
mfer run frontend
|
|
135
|
+
mfer run # Run all micro frontends with default command (npm start)
|
|
136
|
+
mfer run frontend # Run only frontend group with default command
|
|
137
|
+
mfer run --command "npm ci" home # Run custom command sequentially on home group
|
|
138
|
+
mfer run -c "yarn install" shared # Run yarn install sequentially on shared group
|
|
139
|
+
mfer run --command "npm ci" --async home # Run custom command concurrently on home group
|
|
140
|
+
mfer run -c "yarn install" -a shared # Run yarn install concurrently on shared group
|
|
141
|
+
mfer run --command "npm run build" --select # Select MFEs and run build command sequentially
|
|
131
142
|
```
|
|
132
143
|
|
|
133
144
|
### `mfer pull [group_name]`
|
package/dist/commands/run.js
CHANGED
|
@@ -13,17 +13,32 @@ import concurrently from "concurrently";
|
|
|
13
13
|
import chalk from "chalk";
|
|
14
14
|
import path from "path";
|
|
15
15
|
import { checkbox } from "@inquirer/prompts";
|
|
16
|
-
|
|
16
|
+
import { spawn } from "child_process";
|
|
17
|
+
const DEFAULT_RUN_COMMAND = "npm start";
|
|
17
18
|
const runCommand = new Command("run")
|
|
18
19
|
.description("run micro-frontend applications")
|
|
19
20
|
.argument("[group_name]", "name of the group as specified in the configuration", "all")
|
|
20
21
|
.option("-s, --select", "prompt to select which micro frontends to run")
|
|
22
|
+
.option("-c, --command <command>", "custom command to run (default: npm start)")
|
|
23
|
+
.option("-a, --async", "run custom command concurrently instead of sequentially")
|
|
21
24
|
.action((groupName, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
25
|
var _a, _b;
|
|
23
26
|
if (!configExists) {
|
|
24
27
|
warnOfMissingConfig();
|
|
25
28
|
return;
|
|
26
29
|
}
|
|
30
|
+
if (options.command &&
|
|
31
|
+
typeof options.command === "string" &&
|
|
32
|
+
options.command.trim() === "") {
|
|
33
|
+
const messagePrefix = chalk.red("Error");
|
|
34
|
+
console.log(`${messagePrefix}: custom command cannot be empty`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (options.async && !options.command) {
|
|
38
|
+
const messagePrefix = chalk.red("Error");
|
|
39
|
+
console.log(`${messagePrefix}: --async can only be used with --command option`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
27
42
|
const group = currentConfig.groups[groupName];
|
|
28
43
|
if (!group) {
|
|
29
44
|
const messagePrefix = chalk.red("Error");
|
|
@@ -57,45 +72,91 @@ const runCommand = new Command("run")
|
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
const mfeDir = currentConfig.mfe_directory;
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
name: mfe,
|
|
63
|
-
cwd: path.join(mfeDir, mfe),
|
|
64
|
-
prefixColor: "blue",
|
|
65
|
-
}));
|
|
75
|
+
const commandToRun = options.command || DEFAULT_RUN_COMMAND;
|
|
76
|
+
const isAsync = options.async && options.command;
|
|
66
77
|
const groupText = options.select
|
|
67
78
|
? `selected MFEs from group '${groupName}'`
|
|
68
79
|
: `group '${groupName}'`;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
const commandText = options.command
|
|
81
|
+
? `custom command '${commandToRun}'`
|
|
82
|
+
: "default command";
|
|
83
|
+
const executionMode = isAsync ? "concurrently" : "sequentially";
|
|
84
|
+
console.log(chalk.green(`Running ${commandText} on micro frontends in ${groupText} ${executionMode}...`));
|
|
85
|
+
if (isAsync || !options.command) {
|
|
86
|
+
yield runConcurrently(selectedMFEs, commandToRun, mfeDir);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
yield runSequentially(selectedMFEs, commandToRun, mfeDir);
|
|
90
|
+
}
|
|
91
|
+
}));
|
|
92
|
+
function runSequentially(mfes, command, mfeDir) {
|
|
93
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
+
for (const mfe of mfes) {
|
|
95
|
+
const cwd = path.join(mfeDir, mfe);
|
|
96
|
+
console.log(chalk.blue(`\n[${mfe}] Running: ${command}`));
|
|
97
|
+
try {
|
|
98
|
+
const result = yield new Promise((resolve) => {
|
|
99
|
+
const child = spawn(command, [], {
|
|
100
|
+
stdio: "inherit",
|
|
101
|
+
cwd,
|
|
102
|
+
shell: true,
|
|
103
|
+
});
|
|
104
|
+
child.on("close", (exitCode) => {
|
|
105
|
+
resolve({ exitCode });
|
|
106
|
+
});
|
|
107
|
+
child.on("error", (error) => {
|
|
108
|
+
console.error(chalk.red(`[${mfe}] Error: ${error.message}`));
|
|
109
|
+
resolve({ exitCode: 1 });
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
if (result.exitCode !== 0) {
|
|
113
|
+
console.error(chalk.red(`[${mfe}] Command failed with exit code ${result.exitCode}`));
|
|
114
|
+
}
|
|
80
115
|
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error(chalk.red(`[${mfe}] Unexpected error: ${error}`));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function runConcurrently(mfes, command, mfeDir) {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
const commands = mfes.map((mfe) => ({
|
|
125
|
+
command,
|
|
126
|
+
name: mfe,
|
|
127
|
+
cwd: path.join(mfeDir, mfe),
|
|
128
|
+
prefixColor: "blue",
|
|
129
|
+
}));
|
|
130
|
+
const concurrentlyResult = concurrently(commands, {
|
|
131
|
+
prefix: "{name} |",
|
|
132
|
+
killOthersOn: ["failure", "success"],
|
|
133
|
+
restartTries: 0,
|
|
81
134
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
err.forEach((fail) => {
|
|
89
|
-
var _a, _b;
|
|
90
|
-
const name = ((_a = fail.command) === null || _a === void 0 ? void 0 : _a.name) || "unknown";
|
|
91
|
-
const exitCode = fail.exitCode;
|
|
92
|
-
const cwd = ((_b = fail.command) === null || _b === void 0 ? void 0 : _b.cwd) || "unknown";
|
|
93
|
-
console.error(chalk.yellow(` MFE ${name} failed to start (cwd: ${cwd}) with exit code ${exitCode}`));
|
|
135
|
+
const handleSigint = () => {
|
|
136
|
+
console.log(chalk.yellow("\nReceived SIGINT. Stopping all micro frontends..."));
|
|
137
|
+
concurrentlyResult.commands.forEach((cmd) => {
|
|
138
|
+
if (cmd && typeof cmd.kill === "function") {
|
|
139
|
+
cmd.kill();
|
|
140
|
+
}
|
|
94
141
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
142
|
+
process.exit(0);
|
|
143
|
+
};
|
|
144
|
+
process.once("SIGINT", handleSigint);
|
|
145
|
+
concurrentlyResult.result.then(() => { }, (err) => {
|
|
146
|
+
console.error(chalk.red("One or more micro frontends failed to start."));
|
|
147
|
+
if (Array.isArray(err)) {
|
|
148
|
+
err.forEach((fail) => {
|
|
149
|
+
var _a, _b;
|
|
150
|
+
const name = ((_a = fail.command) === null || _a === void 0 ? void 0 : _a.name) || "unknown";
|
|
151
|
+
const exitCode = fail.exitCode;
|
|
152
|
+
const cwd = ((_b = fail.command) === null || _b === void 0 ? void 0 : _b.cwd) || "unknown";
|
|
153
|
+
console.error(chalk.yellow(` MFE ${name} failed to start (cwd: ${cwd}) with exit code ${exitCode}`));
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
else if (err && typeof err === "object" && "message" in err) {
|
|
157
|
+
console.error(err.message);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
99
160
|
});
|
|
100
|
-
}
|
|
161
|
+
}
|
|
101
162
|
export default runCommand;
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { loadConfig } from "./utils/config-utils.js";
|
|
|
10
10
|
program
|
|
11
11
|
.name("mfer")
|
|
12
12
|
.description("Micro Frontend Runner (mfer) - A CLI for running your project's micro frontends.")
|
|
13
|
-
.version("1.
|
|
13
|
+
.version("1.5.0", "-v, --version", "mfer CLI version")
|
|
14
14
|
.hook("preAction", () => {
|
|
15
15
|
console.log();
|
|
16
16
|
})
|