Skip to content

Commit e6cd7e4

Browse files
authored
chore(scripts): support multi-commands in cli dispatcher (#7295)
1 parent f27ff64 commit e6cd7e4

File tree

5 files changed

+102
-65
lines changed

5 files changed

+102
-65
lines changed

scripts/cli-dispatcher/index.js

Lines changed: 33 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#!/usr/bin/env node
22

3-
const fs = require("fs");
43
const path = require("path");
54
const readline = require("readline");
65

@@ -37,31 +36,21 @@ async function main() {
3736
const [node, dispatcher, ...rest] = argv;
3837
const flags = rest.filter((f) => f.startsWith("--"));
3938
const options = {
40-
dry: flags.includes("--dry"),
4139
help: flags.includes("--help") || rest.length === 0,
42-
confirm: flags.includes("--c"),
4340
};
4441

4542
if (options.help) {
4643
console.info(`
4744
Usage:
4845
b [package query words] - [command query words]
49-
b c s3 c - b t
46+
b c s3 c - b t, b cjs
5047
5148
matches to:
52-
(cd clients/client-s3-control && yarn build:types)
49+
(cd clients/client-s3-control && yarn build:types && yarn build:cjs)
5350
5451
Query words are substrings that match against the package name and npm scripts.
5552
The substrings must appear in order for a match.
5653
Match priority goes to whole-word matching and initial matching.
57-
58-
Options:
59-
--dry
60-
dry run with no command execution.
61-
--help
62-
show this message.
63-
--c
64-
ask for confirmation before executing command.
6554
`);
6655
return 0;
6756
}
@@ -70,6 +59,10 @@ async function main() {
7059
const separatorIndex = rest.indexOf("-") !== -1 ? rest.indexOf("-") : rest.length;
7160
const query = nonFlags.slice(0, separatorIndex);
7261
const commands = nonFlags.slice(separatorIndex + 1);
62+
const multiCommands = commands
63+
.join(" ")
64+
.split(/,\s?/)
65+
.map((c) => c.split(" "));
7366

7467
const matchedPackages = findFolders(allPackages, ...query);
7568

@@ -85,59 +78,42 @@ async function main() {
8578
);
8679

8780
const [target] = matchedPackages;
88-
8981
const targetPkgJson = require(path.join(target.location, "package.json"));
90-
const matchedScripts = findScripts(Object.keys(targetPkgJson.scripts || {}), ...commands);
91-
const [script] = matchedScripts;
92-
93-
if (commands.length === 0) {
94-
console.info("No commands entered");
95-
return 0;
96-
}
9782

98-
if (matchedScripts.length === 0) {
99-
console.error("No matching scripts for command query:", commands);
100-
return 0;
101-
}
83+
for (const commands of multiCommands) {
84+
const matchedScripts = findScripts(Object.keys(targetPkgJson.scripts || {}), ...commands);
10285

103-
console.log("commands:", ...commands);
104-
console.log("matched commands:", matchedScripts);
86+
if (commands.length === 0) {
87+
console.info("No commands entered");
88+
return 0;
89+
}
10590

106-
const command = `yarn ${script} in ${target.location}`;
91+
if (matchedScripts.length === 0) {
92+
console.error("No matching scripts for command query:", commands);
93+
return 0;
94+
}
10795

108-
if (options.dry) {
109-
console.log("DRYRUN:", command);
110-
return 0;
96+
console.log("commands:", ...commands);
97+
console.log("matched commands:", matchedScripts);
11198
}
11299

113-
const execute = async () => {
114-
const { spawnProcess } = require("../utils/spawn-process");
115-
console.info("Running:", "yarn", script);
116-
console.info("Location:", target.location);
117-
await spawnProcess("yarn", [script], {
118-
cwd: target.location,
119-
stdio: "inherit",
120-
});
121-
return;
122-
};
123-
124-
if (options.confirm) {
125-
const rl = readline.createInterface({
126-
input: process.stdin,
127-
output: process.stdout,
128-
});
129-
130-
rl.question(`run script "${script}" in ${target.location} (y)/n?:`, async (confirm) => {
131-
if (confirm.toLowerCase().trim() === "y" || confirm === "") {
132-
await execute();
133-
}
134-
rl.close();
135-
});
136-
return 0;
100+
for (const commands of multiCommands) {
101+
const matchedScripts = findScripts(Object.keys(targetPkgJson.scripts || {}), ...commands);
102+
const [script] = matchedScripts;
103+
104+
const execute = async () => {
105+
const { spawnProcess } = require("../utils/spawn-process");
106+
console.info("Running:", "yarn", script);
107+
console.info("Location:", target.location);
108+
await spawnProcess("yarn", [script], {
109+
cwd: target.location,
110+
stdio: "inherit",
111+
});
112+
};
113+
114+
await execute();
137115
}
138116

139-
await execute();
140-
141117
return 0;
142118
}
143119

tests/bundlers/Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ test:
66

77
# create bundles
88
build:
9-
make vite webpack
9+
make vite webpack esbuild
1010

1111
vite:
1212
npx vite build
1313

1414
webpack:
15-
npx webpack
15+
npx webpack
16+
17+
esbuild:
18+
npx esbuild ./source.ts --bundle --outfile=./dist/esbuild-dist.js --format=esm --tree-shaking=true

tests/bundlers/test.spec.mjs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,25 @@ const viteDist = {
1414
name: "vite",
1515
content: fs.readFileSync(path.join(__dirname, "dist", "vite-dist.js"), "utf-8"),
1616
};
17+
const esbuildDist = {
18+
name: "esbuild",
19+
content: fs.readFileSync(path.join(__dirname, "dist", "esbuild-dist.js"), "utf-8"),
20+
};
1721

18-
for (const { content: fileContents, name } of [webpackDist, viteDist]) {
19-
console.log(name);
22+
for (const { content: fileContents, name } of [webpackDist, viteDist, esbuildDist]) {
23+
console.log("================", name, "================");
2024

2125
const contentSize = fileContents.replaceAll(/\s+/g, "").length;
22-
const callsToClassBuilder = fileContents.match(/\.classBuilder\(\)/g);
23-
const runtimeConfig = fileContents.match(/runtime: "browser"/);
26+
const callsToClassBuilder = fileContents.match(/\.classBuilder\(\)/g) || [];
27+
const runtimeConfig = fileContents.match(/runtime: "browser"/) || [];
28+
29+
const serializers = fileContents.match(/(var|const) se_/g) || [];
30+
const operationSchemas = fileContents.match(/ op\(/g) || [];
31+
const structSchemas = fileContents.match(/ struct\(/g) || [];
2432

2533
try {
2634
assert(contentSize < 1_000_000);
27-
console.info(`✅ content size is under 1M char.`);
35+
console.info(`✅ content size is under 1M char. ${contentSize.toLocaleString()}`);
2836
} catch (e) {
2937
throw new Error("Content size should be less than 1M characters.");
3038
}
@@ -33,7 +41,9 @@ for (const { content: fileContents, name } of [webpackDist, viteDist]) {
3341
assert(callsToClassBuilder.length <= 2); // only GetObject and CreateSession should be present.
3442
console.info(`✅ two commands bundled (tree shaken).`);
3543
} catch (e) {
36-
throw new Error("there should only be 2 calls to the Command classBuilder. Tree-shaking failure?");
44+
throw new Error(
45+
`there should only be 2 calls to the Command classBuilder, got ${callsToClassBuilder.length}. Tree-shaking failure?`
46+
);
3747
}
3848

3949
try {
@@ -42,4 +52,42 @@ for (const { content: fileContents, name } of [webpackDist, viteDist]) {
4252
} catch (e) {
4353
throw new Error("the browser runtimeConfig should be present in the bundle.");
4454
}
55+
56+
console.log("serializers", serializers.length);
57+
console.log("operationSchemas", operationSchemas.length);
58+
console.log("structSchemas", structSchemas.length);
4559
}
60+
61+
// Model-ignorant codegen expected output:
62+
// problems: webpack fails to tree shake serde functions.
63+
/*
64+
================ webpack ================
65+
✅ content size is under 1M char. 628,148
66+
✅ two commands bundled (tree shaken).
67+
✅ runtimeConfig is browser.
68+
serializers 250
69+
operationSchemas 11
70+
================ vite ================
71+
✅ content size is under 1M char. 341,346
72+
✅ two commands bundled (tree shaken).
73+
✅ runtimeConfig is browser.
74+
serializers 2
75+
operationSchemas 10
76+
*/
77+
78+
// Schema serde expected output:
79+
// problems: both bundlers fail to tree-shake schemas (fix WIP).
80+
/*
81+
================ webpack ================
82+
✅ content size is under 1M char. 557,102
83+
✅ two commands bundled (tree shaken).
84+
✅ runtimeConfig is browser.
85+
serializers 0
86+
operationSchemas 116
87+
================ vite ================
88+
✅ content size is under 1M char. 459,392
89+
✅ two commands bundled (tree shaken).
90+
✅ runtimeConfig is browser.
91+
serializers 0
92+
operationSchemas 115
93+
*/

tests/bundlers/vite.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export default defineConfig({
1717
// Provide global variables to use in the UMD build
1818
// for externalized deps
1919
globals: {},
20+
// to get an easier aggregate accounting of bundle contents
21+
inlineDynamicImports: true,
2022
},
2123
},
2224
minify: false,

tests/bundlers/webpack.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,20 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
66
export default {
77
mode: "production",
88
entry: "./source.ts",
9+
target: "web",
910
output: {
1011
path: path.resolve(__dirname, "dist"),
1112
filename: "webpack-dist.js",
1213
library: "dist",
1314
},
1415
optimization: {
1516
minimize: false,
17+
splitChunks: false,
18+
runtimeChunk: false,
19+
sideEffects: true,
20+
usedExports: true,
21+
},
22+
stats: {
23+
optimizationBailout: false,
1624
},
1725
};

0 commit comments

Comments
 (0)