@vlandoss/run-run 0.0.21 → 0.0.22-git-9445806.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/bin.ts +0 -0
- package/dist/bin.mjs +599 -0
- package/dist/config.mjs +1 -2
- package/dist/tools/tsdown.mjs +2 -3
- package/package.json +14 -9
- package/tools/biome +1 -1
- package/tools/oxfmt +1 -1
- package/tools/oxlint +1 -1
- package/tools/tsdown +1 -1
- package/src/program/__tests__/__snapshots__/snapshots.test.ts.snap +0 -189
- package/src/program/__tests__/snapshots.test.ts +0 -38
package/bin.ts
CHANGED
|
File without changes
|
package/dist/bin.mjs
ADDED
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { colorIsSupported, colorize, createPkgService, createShellService, cwd, getVersion, palette, run } from "@vlandoss/clibuddy";
|
|
4
|
+
import { Option, createCommand } from "commander";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import { lilconfig } from "lilconfig";
|
|
8
|
+
import { createLoggy } from "@vlandoss/loggy";
|
|
9
|
+
import { glob } from "glob";
|
|
10
|
+
import { rimraf } from "rimraf";
|
|
11
|
+
import isCI from "is-ci";
|
|
12
|
+
import memoize from "memoize";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
//#region \0rolldown/runtime.js
|
|
15
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/services/logger.ts
|
|
18
|
+
const logger = createLoggy({ namespace: "run-run" });
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/services/config.ts
|
|
21
|
+
const DEFAULT_CONFIG = { future: { oxc: false } };
|
|
22
|
+
var ConfigService = class {
|
|
23
|
+
#searcher;
|
|
24
|
+
constructor() {
|
|
25
|
+
this.#searcher = lilconfig("run-run", {
|
|
26
|
+
searchPlaces: ["run-run.config.ts"],
|
|
27
|
+
cache: true,
|
|
28
|
+
stopDir: os.homedir(),
|
|
29
|
+
loaders: { ".ts": (filepath) => import(filepath).then((mod) => mod.default) }
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async load() {
|
|
33
|
+
const debug = logger.subdebug("load-config");
|
|
34
|
+
const searchResult = await this.#searcher.search();
|
|
35
|
+
if (!searchResult || searchResult?.isEmpty) {
|
|
36
|
+
debug("loaded default config: %O", DEFAULT_CONFIG);
|
|
37
|
+
return {
|
|
38
|
+
config: DEFAULT_CONFIG,
|
|
39
|
+
meta: {
|
|
40
|
+
isDefault: true,
|
|
41
|
+
filepath: void 0
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const config = searchResult.config;
|
|
46
|
+
debug("loaded config: %O", config);
|
|
47
|
+
debug("config file: %s", searchResult.filepath);
|
|
48
|
+
return {
|
|
49
|
+
config,
|
|
50
|
+
meta: {
|
|
51
|
+
isDefault: false,
|
|
52
|
+
filepath: searchResult.filepath
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/services/ctx.ts
|
|
59
|
+
async function createContext(binDir) {
|
|
60
|
+
const debug = logger.subdebug("create-context");
|
|
61
|
+
const binPath = fs.realpathSync(binDir);
|
|
62
|
+
debug("bin path:", binPath);
|
|
63
|
+
debug("process cwd:", process.cwd());
|
|
64
|
+
const [appPkg, binPkg] = await Promise.all([createPkgService(cwd), createPkgService(binPath)]);
|
|
65
|
+
if (!binPkg) throw new Error("Could not find bin package.json");
|
|
66
|
+
if (!appPkg) throw new Error("Could not find app package.json");
|
|
67
|
+
debug("app pkg info: %O", appPkg.info());
|
|
68
|
+
debug("bin pkg info: %O", binPkg.info());
|
|
69
|
+
const shell = createShellService({
|
|
70
|
+
localBaseBinPath: [binDir],
|
|
71
|
+
stdio: "inherit"
|
|
72
|
+
});
|
|
73
|
+
debug("shell service options: %O", shell.options);
|
|
74
|
+
return {
|
|
75
|
+
appPkg,
|
|
76
|
+
binPkg,
|
|
77
|
+
shell,
|
|
78
|
+
config: await new ConfigService().load()
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/program/ui.ts
|
|
83
|
+
const CREDITS_TEXT = `\nAcknowledgment:
|
|
84
|
+
- kcd-scripts: for main inspiration
|
|
85
|
+
${palette.link("https://github.com/kentcdodds/kcd-scripts")}
|
|
86
|
+
|
|
87
|
+
- peruvian news: in honor to Run Run
|
|
88
|
+
${palette.link("https://es.wikipedia.org/wiki/Run_Run")}`;
|
|
89
|
+
const tsdownColor = colorize("#FF7E18");
|
|
90
|
+
const biomeColor = colorize("#61A5FA");
|
|
91
|
+
const oxlintColor = colorize("#32F3E9");
|
|
92
|
+
const oxfmtColor = colorize("#32F3E9");
|
|
93
|
+
const tscColor = colorize("#3178C6");
|
|
94
|
+
const rimrafColor = colorize("#7C7270");
|
|
95
|
+
const runRunColor = colorize("FC7A1E");
|
|
96
|
+
const TOOL_LABELS = {
|
|
97
|
+
TSDOWN: tsdownColor("tsdown"),
|
|
98
|
+
BIOME: biomeColor("biome"),
|
|
99
|
+
OXLINT: oxlintColor("oxlint"),
|
|
100
|
+
OXFMT: oxfmtColor("oxfmt"),
|
|
101
|
+
TSC: tscColor("tsc"),
|
|
102
|
+
RIMRAF: rimrafColor("rimraf"),
|
|
103
|
+
RUN_RUN: runRunColor("run-run")
|
|
104
|
+
};
|
|
105
|
+
function getBannerText(version) {
|
|
106
|
+
const uiLogo = `🦊 ${palette.bold("R")} ${palette.bold("U")} ${palette.bold("N")} - ${palette.bold("R")} ${palette.bold("U")} ${palette.bold("N")}`;
|
|
107
|
+
const vlandLogo = `${palette.link(palette.vland("https://variable.land"))} 👊`;
|
|
108
|
+
const title = `${uiLogo} ${palette.muted(`v${version}`)}`;
|
|
109
|
+
const subtitle = `${palette.italic(palette.muted("The CLI toolbox for"))} ${vlandLogo}`;
|
|
110
|
+
if (!colorIsSupported()) return `${title}\n${subtitle}\n`;
|
|
111
|
+
const FOX_COLORS = {
|
|
112
|
+
BLACK: colorize("#39393A"),
|
|
113
|
+
ORANGE: runRunColor,
|
|
114
|
+
WHITE: colorize("#FFFFFF")
|
|
115
|
+
};
|
|
116
|
+
const _ = " ";
|
|
117
|
+
const B = FOX_COLORS.BLACK("██");
|
|
118
|
+
const O = FOX_COLORS.ORANGE("██");
|
|
119
|
+
const W = FOX_COLORS.WHITE("██");
|
|
120
|
+
const lines = [
|
|
121
|
+
[
|
|
122
|
+
_,
|
|
123
|
+
B,
|
|
124
|
+
_,
|
|
125
|
+
_,
|
|
126
|
+
_,
|
|
127
|
+
_,
|
|
128
|
+
_,
|
|
129
|
+
B,
|
|
130
|
+
_
|
|
131
|
+
],
|
|
132
|
+
[
|
|
133
|
+
_,
|
|
134
|
+
O,
|
|
135
|
+
W,
|
|
136
|
+
_,
|
|
137
|
+
_,
|
|
138
|
+
_,
|
|
139
|
+
W,
|
|
140
|
+
O,
|
|
141
|
+
_
|
|
142
|
+
],
|
|
143
|
+
[
|
|
144
|
+
_,
|
|
145
|
+
O,
|
|
146
|
+
W,
|
|
147
|
+
O,
|
|
148
|
+
_,
|
|
149
|
+
O,
|
|
150
|
+
W,
|
|
151
|
+
O,
|
|
152
|
+
_
|
|
153
|
+
],
|
|
154
|
+
[
|
|
155
|
+
B,
|
|
156
|
+
O,
|
|
157
|
+
O,
|
|
158
|
+
O,
|
|
159
|
+
O,
|
|
160
|
+
O,
|
|
161
|
+
O,
|
|
162
|
+
O,
|
|
163
|
+
B
|
|
164
|
+
],
|
|
165
|
+
[
|
|
166
|
+
O,
|
|
167
|
+
O,
|
|
168
|
+
O,
|
|
169
|
+
O,
|
|
170
|
+
O,
|
|
171
|
+
O,
|
|
172
|
+
O,
|
|
173
|
+
O,
|
|
174
|
+
O
|
|
175
|
+
],
|
|
176
|
+
[
|
|
177
|
+
W,
|
|
178
|
+
O,
|
|
179
|
+
B,
|
|
180
|
+
O,
|
|
181
|
+
O,
|
|
182
|
+
O,
|
|
183
|
+
B,
|
|
184
|
+
O,
|
|
185
|
+
W
|
|
186
|
+
],
|
|
187
|
+
[
|
|
188
|
+
_,
|
|
189
|
+
W,
|
|
190
|
+
W,
|
|
191
|
+
O,
|
|
192
|
+
O,
|
|
193
|
+
O,
|
|
194
|
+
W,
|
|
195
|
+
W,
|
|
196
|
+
_
|
|
197
|
+
],
|
|
198
|
+
[
|
|
199
|
+
_,
|
|
200
|
+
_,
|
|
201
|
+
W,
|
|
202
|
+
W,
|
|
203
|
+
B,
|
|
204
|
+
W,
|
|
205
|
+
W,
|
|
206
|
+
_,
|
|
207
|
+
_
|
|
208
|
+
],
|
|
209
|
+
[
|
|
210
|
+
_,
|
|
211
|
+
_,
|
|
212
|
+
_,
|
|
213
|
+
W,
|
|
214
|
+
W,
|
|
215
|
+
W,
|
|
216
|
+
_,
|
|
217
|
+
_,
|
|
218
|
+
_
|
|
219
|
+
]
|
|
220
|
+
].map((row) => row.join(""));
|
|
221
|
+
lines[3] += ` ${title}`;
|
|
222
|
+
lines[4] += ` ${subtitle}`;
|
|
223
|
+
return `${lines.join("\n")}\n`;
|
|
224
|
+
}
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region src/program/commands/build-lib.ts
|
|
227
|
+
function createBuildLibCommand(ctx) {
|
|
228
|
+
return createCommand("build:lib").summary(`build a ts library 🏗️ (${TOOL_LABELS.TSDOWN})`).description("Compiles TypeScript code into JavaScript and generates type declaration files, making it ready for distribution.").action(async function buildAction() {
|
|
229
|
+
await ctx.shell.$`tsdown`;
|
|
230
|
+
}).addHelpText("afterAll", `\nUnder the hood, this command uses the ${TOOL_LABELS.TSDOWN} CLI to build the project.`);
|
|
231
|
+
}
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region src/program/commands/clean.ts
|
|
234
|
+
function createCleanCommand() {
|
|
235
|
+
return createCommand("clean").summary(`delete dirty files 🗑️ (${TOOL_LABELS.RIMRAF})`).description("Deletes generated files and folders such as 'dist', 'node_modules', and lock files to ensure a clean state.").option("--only-dist", "delete 'dist' folders only").option("--dry-run", "outputs the paths that would be deleted").action(async function cleanCommandAction(options) {
|
|
236
|
+
async function run(paths, globOptions) {
|
|
237
|
+
if (options.dryRun) {
|
|
238
|
+
const toDelete = await glob(paths, globOptions);
|
|
239
|
+
logger.info("Paths that would be deleted: %O", toDelete);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
logger.start("Clean started");
|
|
243
|
+
await rimraf(paths, { glob: globOptions });
|
|
244
|
+
logger.success("Clean completed");
|
|
245
|
+
}
|
|
246
|
+
const BUILD_PATHS = ["**/dist"];
|
|
247
|
+
const ALL_DIRTY_PATHS = [
|
|
248
|
+
"**/.turbo",
|
|
249
|
+
"**/node_modules",
|
|
250
|
+
"pnpm-lock.yaml",
|
|
251
|
+
"bun.lock",
|
|
252
|
+
...BUILD_PATHS
|
|
253
|
+
];
|
|
254
|
+
if (options.onlyDist) await run(BUILD_PATHS, {
|
|
255
|
+
cwd,
|
|
256
|
+
ignore: ["**/node_modules/**"]
|
|
257
|
+
});
|
|
258
|
+
else await run(ALL_DIRTY_PATHS, { cwd });
|
|
259
|
+
}).addHelpText("afterAll", `\nUnder the hood, this command uses ${TOOL_LABELS.RIMRAF} to delete dirty folders or files.`);
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/program/commands/config.ts
|
|
263
|
+
function createConfigCommand(ctx) {
|
|
264
|
+
return createCommand("config").summary("display the current config 🛠️").description("Displays the current configuration settings, including their source file path if available.").action(async function configAction() {
|
|
265
|
+
const { config, meta } = ctx.config;
|
|
266
|
+
console.log(palette.muted("Config:"));
|
|
267
|
+
console.log(config);
|
|
268
|
+
console.log(palette.muted(`Loaded from ${meta.filepath ? palette.link(meta.filepath) : "n/a"}`));
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region src/utils/gracefullBinDir.ts
|
|
273
|
+
function gracefullBinDir(binPathResolver) {
|
|
274
|
+
try {
|
|
275
|
+
const binPath = binPathResolver();
|
|
276
|
+
return fs.statSync(binPath).isDirectory() ? binPath : path.dirname(binPath);
|
|
277
|
+
} catch (error) {
|
|
278
|
+
logger.error("Error getting bin directory:", error);
|
|
279
|
+
process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region src/services/tool.ts
|
|
284
|
+
var ToolService = class {
|
|
285
|
+
#shellService;
|
|
286
|
+
#bin;
|
|
287
|
+
#ui;
|
|
288
|
+
constructor({ bin, ui, shellService }) {
|
|
289
|
+
this.#bin = bin;
|
|
290
|
+
this.#ui = ui ?? bin;
|
|
291
|
+
this.#shellService = shellService;
|
|
292
|
+
}
|
|
293
|
+
exec(args) {
|
|
294
|
+
const $ = this.#shell();
|
|
295
|
+
return this.#run($, args);
|
|
296
|
+
}
|
|
297
|
+
#shell = memoize((cwd) => {
|
|
298
|
+
const { getBinDir } = this;
|
|
299
|
+
return this.#shellService.child({
|
|
300
|
+
cwd,
|
|
301
|
+
...getBinDir && { preferLocal: gracefullBinDir(() => getBinDir()) }
|
|
302
|
+
}).$;
|
|
303
|
+
});
|
|
304
|
+
#run(shell, args) {
|
|
305
|
+
return shell`${this.#bin} ${typeof args === "string" ? args : args.join(" ")}`;
|
|
306
|
+
}
|
|
307
|
+
get bin() {
|
|
308
|
+
return this.#bin;
|
|
309
|
+
}
|
|
310
|
+
get ui() {
|
|
311
|
+
return this.#ui;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
//#endregion
|
|
315
|
+
//#region src/services/biome.ts
|
|
316
|
+
var BiomeService = class extends ToolService {
|
|
317
|
+
constructor(shellService) {
|
|
318
|
+
super({
|
|
319
|
+
bin: "biome",
|
|
320
|
+
ui: TOOL_LABELS.BIOME,
|
|
321
|
+
shellService
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
getBinDir() {
|
|
325
|
+
return __require.resolve("@biomejs/biome/bin/biome");
|
|
326
|
+
}
|
|
327
|
+
async format(options) {
|
|
328
|
+
const commonOptions = "format --colors=force --no-errors-on-unmatched";
|
|
329
|
+
if (options.fix) await this.exec(`${commonOptions} --fix`);
|
|
330
|
+
else await this.exec(`${commonOptions}`);
|
|
331
|
+
}
|
|
332
|
+
async lint(options) {
|
|
333
|
+
const commonOptions = "check --colors=force --no-errors-on-unmatched --formatter-enabled=false";
|
|
334
|
+
if (options.fix) await this.exec(`${commonOptions} --fix --unsafe`);
|
|
335
|
+
else await this.exec(`${commonOptions}`);
|
|
336
|
+
}
|
|
337
|
+
async check(options) {
|
|
338
|
+
const commonOptions = (cmd = "check") => `${cmd} --colors=force --no-errors-on-unmatched`;
|
|
339
|
+
if (options.fix) await this.exec(`${commonOptions()} --fix`);
|
|
340
|
+
else if (options.fixStaged) await this.exec(`${commonOptions()} --fix --staged`);
|
|
341
|
+
else await this.exec(`${commonOptions(isCI ? "ci" : "check")}`);
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
//#endregion
|
|
345
|
+
//#region src/services/oxfmt.ts
|
|
346
|
+
var OxfmtService = class extends ToolService {
|
|
347
|
+
constructor(shellService) {
|
|
348
|
+
super({
|
|
349
|
+
bin: "oxfmt",
|
|
350
|
+
ui: TOOL_LABELS.OXFMT,
|
|
351
|
+
shellService
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
getBinDir() {
|
|
355
|
+
return __require.resolve("oxfmt/bin/oxfmt");
|
|
356
|
+
}
|
|
357
|
+
async format(options) {
|
|
358
|
+
const commonOptions = "--no-error-on-unmatched-pattern";
|
|
359
|
+
if (options.fix) await this.exec(`${commonOptions} --fix`);
|
|
360
|
+
else await this.exec(`${commonOptions} --check`);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
//#endregion
|
|
364
|
+
//#region src/program/commands/format.ts
|
|
365
|
+
function getToolService$2(ctx) {
|
|
366
|
+
const { config } = ctx.config;
|
|
367
|
+
if (config.future?.oxc) return new OxfmtService(ctx.shell);
|
|
368
|
+
return new BiomeService(ctx.shell);
|
|
369
|
+
}
|
|
370
|
+
function createFormatCommand(ctx) {
|
|
371
|
+
const toolService = getToolService$2(ctx);
|
|
372
|
+
return createCommand("format").summary(`check & fix format errors 🎨 (${toolService.ui})`).description("Checks the code for formatting issues and optionally fixes them, ensuring it adheres to the defined style standards.").option("--fix", "format all the code").action(async function formatAction(options) {
|
|
373
|
+
await toolService.format(options);
|
|
374
|
+
}).addHelpText("afterAll", `\nUnder the hood, this command uses the ${toolService.ui} CLI to format the code.`);
|
|
375
|
+
}
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region src/program/commands/jscheck.ts
|
|
378
|
+
function createJsCheckCommand(ctx) {
|
|
379
|
+
const checkerService = new BiomeService(ctx.shell);
|
|
380
|
+
return createCommand("jsc").alias("jscheck").alias("check").summary(`check format and lint 🔍 (${checkerService.ui})`).description("Checks the code for formatting and linting issues, ensuring it adheres to the defined style and quality standards.").option("--fix", "try to fix issues automatically").option("--fix-staged", "try to fix staged files only").action(async function checkAction(options) {
|
|
381
|
+
await checkerService.check(options);
|
|
382
|
+
}).addHelpText("afterAll", `\nUnder the hood, this command uses the ${checkerService.ui} CLI to check the code.`);
|
|
383
|
+
}
|
|
384
|
+
//#endregion
|
|
385
|
+
//#region src/services/oxlint.ts
|
|
386
|
+
var OxlintService = class extends ToolService {
|
|
387
|
+
constructor(shellService) {
|
|
388
|
+
super({
|
|
389
|
+
bin: "oxlint",
|
|
390
|
+
ui: TOOL_LABELS.OXLINT,
|
|
391
|
+
shellService
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
getBinDir() {
|
|
395
|
+
return __require.resolve("oxlint/bin/oxlint");
|
|
396
|
+
}
|
|
397
|
+
async lint(options) {
|
|
398
|
+
const commonOptions = "--report-unused-disable-directives";
|
|
399
|
+
if (options.fix) await this.exec(`${commonOptions} --fix`);
|
|
400
|
+
else await this.exec(`${commonOptions} --check`);
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
//#endregion
|
|
404
|
+
//#region src/program/commands/lint.ts
|
|
405
|
+
function getToolService$1(ctx) {
|
|
406
|
+
const { config } = ctx.config;
|
|
407
|
+
if (config.future?.oxc) return new OxlintService(ctx.shell);
|
|
408
|
+
return new BiomeService(ctx.shell);
|
|
409
|
+
}
|
|
410
|
+
function createLintCommand(ctx) {
|
|
411
|
+
const toolService = getToolService$1(ctx);
|
|
412
|
+
return createCommand("lint").summary(`check & fix lint errors 🔍 (${toolService.ui})`).description("Checks the code for linting issues and optionally fixes them, ensuring it adheres to the defined quality standards.").option("-c, --check", "check if the code is valid", true).option("--fix", "try to fix all the code").action(async function lintAction(options) {
|
|
413
|
+
await toolService.lint(options);
|
|
414
|
+
}).addHelpText("afterAll", `\nUnder the hood, this command uses the ${toolService.ui} CLI to lint the code.`);
|
|
415
|
+
}
|
|
416
|
+
//#endregion
|
|
417
|
+
//#region src/program/commands/pkgs.ts
|
|
418
|
+
const decorators = ["turbo"];
|
|
419
|
+
function createPkgsCommand(ctx) {
|
|
420
|
+
return createCommand("pkgs").summary("list affected packages 📦").description("Given a list of files, returns the list of affected packages. Useful to run commands only on affected packages.").addOption(new Option("--files <files...>", "list of files to check")).addOption(new Option("--decorator [type]", "type of decorator to use").choices(decorators)).action(async function pkgsAction({ files, decorator }, cmd) {
|
|
421
|
+
const { appPkg } = ctx;
|
|
422
|
+
if (!appPkg.isMonorepo()) {
|
|
423
|
+
const cmdName = cmd.parent?.args[0] ?? cmd.args[0] ?? cmd.name();
|
|
424
|
+
logger.error(`The \`${cmdName}\` command can only be run in a monorepo.`);
|
|
425
|
+
return process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
const projects = await appPkg.getWorkspaceProjects();
|
|
428
|
+
const getRelativeRootDir = memoize((rootDir) => {
|
|
429
|
+
const appDir = appPkg.dirPath;
|
|
430
|
+
if (!path.isAbsolute(rootDir)) return rootDir;
|
|
431
|
+
return path.relative(appDir, rootDir);
|
|
432
|
+
});
|
|
433
|
+
function getPackageForFile(filePath) {
|
|
434
|
+
for (const project of projects) {
|
|
435
|
+
const relativeRootDir = getRelativeRootDir(project.rootDir);
|
|
436
|
+
if (filePath.startsWith(relativeRootDir)) return project;
|
|
437
|
+
}
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
const uniquePkgsNames = /* @__PURE__ */ new Set();
|
|
441
|
+
files.forEach((file) => {
|
|
442
|
+
const pkg = getPackageForFile(file);
|
|
443
|
+
if (pkg?.manifest.name) uniquePkgsNames.add(pkg.manifest.name);
|
|
444
|
+
});
|
|
445
|
+
if (!uniquePkgsNames.size) return;
|
|
446
|
+
const pkgsNames = Array.from(uniquePkgsNames);
|
|
447
|
+
if (decorator === "turbo") console.log(...pkgsNames.map((name) => `--filter=...${name}`));
|
|
448
|
+
else console.log(...pkgsNames);
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
//#endregion
|
|
452
|
+
//#region src/program/commands/run.ts
|
|
453
|
+
function createRunCommand(ctx) {
|
|
454
|
+
return createCommand("run").argument("<cmds...>", "commands to execute concurrently (e.g. 'check tsc')").action(async function runRunAction(cmds) {
|
|
455
|
+
const { $ } = ctx.shell;
|
|
456
|
+
const commands = cmds.map((cmd) => $`rr ${cmd}`);
|
|
457
|
+
await Promise.all(commands);
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region src/program/commands/test-static.ts
|
|
462
|
+
function createTestStaticCommand(ctx) {
|
|
463
|
+
return createCommand("test:static").summary(`run static tests 🔬 (${TOOL_LABELS.RUN_RUN})`).description("Runs static tests, including linting, formatting checks, and TypeScript type checking, to ensure code quality and correctness without executing the code.").action(async function testStaticAction() {
|
|
464
|
+
await ctx.shell.$`rr jscheck tscheck`;
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
//#endregion
|
|
468
|
+
//#region src/services/tsdown.ts
|
|
469
|
+
var TsdownService = class extends ToolService {
|
|
470
|
+
constructor(shellService) {
|
|
471
|
+
super({
|
|
472
|
+
bin: "tsdown",
|
|
473
|
+
ui: TOOL_LABELS.TSDOWN,
|
|
474
|
+
shellService
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
//#endregion
|
|
479
|
+
//#region src/program/commands/tools.ts
|
|
480
|
+
function getToolService(bin, shell) {
|
|
481
|
+
switch (bin) {
|
|
482
|
+
case "biome": return new BiomeService(shell);
|
|
483
|
+
case "oxfmt": return new OxfmtService(shell);
|
|
484
|
+
case "oxlint": return new OxlintService(shell);
|
|
485
|
+
case "tsdown": return new TsdownService(shell);
|
|
486
|
+
default: throw new Error(`Unknown tool: ${bin}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function createToolCommand(bin, shell) {
|
|
490
|
+
const tool = getToolService(bin, shell);
|
|
491
|
+
return createCommand(tool.bin).helpCommand(false).helpOption(false).allowExcessArguments(true).allowUnknownOption(true).action(async (_, { args }) => {
|
|
492
|
+
await tool.exec(args);
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
function createToolsCommand(ctx) {
|
|
496
|
+
return createCommand("tools").description("expose the internal tools 🛠️").addCommand(createToolCommand("biome", ctx.shell)).addCommand(createToolCommand("oxfmt", ctx.shell)).addCommand(createToolCommand("oxlint", ctx.shell)).addCommand(createToolCommand("tsdown", ctx.shell));
|
|
497
|
+
}
|
|
498
|
+
//#endregion
|
|
499
|
+
//#region src/program/commands/tscheck.ts
|
|
500
|
+
const getPreScript = (scripts) => scripts?.pretsc ?? scripts?.pretypecheck;
|
|
501
|
+
async function typecheckAt({ dir, scripts, log, shell, run }) {
|
|
502
|
+
let shellAt;
|
|
503
|
+
log.debug(`checking types at ${dir}`);
|
|
504
|
+
if (cwd === dir) shellAt = shell;
|
|
505
|
+
else {
|
|
506
|
+
log.debug(`Changing directory to ${dir} for typecheck`);
|
|
507
|
+
shellAt = shell.at(dir);
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
const preScript = getPreScript(scripts);
|
|
511
|
+
if (preScript) {
|
|
512
|
+
log.start(`Running pre-script: ${preScript}`);
|
|
513
|
+
await shellAt.$`${preScript}`;
|
|
514
|
+
log.success("Pre-script completed");
|
|
515
|
+
}
|
|
516
|
+
log.start("Type checking started");
|
|
517
|
+
await run(shellAt);
|
|
518
|
+
log.success("Typecheck completed");
|
|
519
|
+
} catch (error) {
|
|
520
|
+
log.error("Typecheck failed");
|
|
521
|
+
throw error;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function createTsCheckCommand(ctx) {
|
|
525
|
+
const { appPkg, shell, config: { config } } = ctx;
|
|
526
|
+
const toolUi = config.future?.oxc ? TOOL_LABELS.OXLINT : TOOL_LABELS.TSC;
|
|
527
|
+
return createCommand("tsc").alias("tscheck").summary(`check typescript errors 🧩 (${toolUi})`).description("Checks the TypeScript code for type errors, ensuring that the code adheres to the defined type constraints and helps catch potential issues before runtime.").addHelpText("afterAll", `\nUnder the hood, this command uses the ${toolUi} CLI to check the code.`).action(async function typecheckAction() {
|
|
528
|
+
const isTsProject = (dir) => appPkg.hasFile("tsconfig.json", dir);
|
|
529
|
+
const runTypecheck = async (shell) => {
|
|
530
|
+
if (config.future?.oxc) await new OxlintService(shell).exec(`--type-aware --type-check --report-unused-disable-directives`);
|
|
531
|
+
else await shell.$`tsc --noEmit`;
|
|
532
|
+
};
|
|
533
|
+
if (!appPkg.isMonorepo()) {
|
|
534
|
+
if (!isTsProject(appPkg.dirPath)) {
|
|
535
|
+
logger.info("No tsconfig.json found, skipping typecheck");
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
await typecheckAt({
|
|
539
|
+
shell,
|
|
540
|
+
run: runTypecheck,
|
|
541
|
+
dir: appPkg.dirPath,
|
|
542
|
+
scripts: appPkg.packageJson.scripts,
|
|
543
|
+
log: logger
|
|
544
|
+
});
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
const tsProjects = (await appPkg.getWorkspaceProjects()).filter((project) => isTsProject(project.rootDir));
|
|
548
|
+
if (!tsProjects.length) {
|
|
549
|
+
logger.warn("No ts projects found in the monorepo, skipping typecheck");
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
await Promise.all(tsProjects.map((p) => typecheckAt({
|
|
553
|
+
shell,
|
|
554
|
+
run: runTypecheck,
|
|
555
|
+
dir: p.rootDir,
|
|
556
|
+
scripts: p.manifest.scripts,
|
|
557
|
+
log: logger.child({
|
|
558
|
+
tag: p.manifest.name,
|
|
559
|
+
namespace: "typecheck"
|
|
560
|
+
})
|
|
561
|
+
})));
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
//#endregion
|
|
565
|
+
//#region src/program/index.ts
|
|
566
|
+
async function createProgram(options) {
|
|
567
|
+
const ctx = await createContext(options.binDir);
|
|
568
|
+
const version = getVersion(ctx.binPkg);
|
|
569
|
+
return {
|
|
570
|
+
program: createCommand("rr").alias("run-run").usage("[options] <command...>").helpCommand(false).version(version, "-v, --version").addHelpText("before", getBannerText(version)).addHelpText("after", CREDITS_TEXT).addCommand(createBuildLibCommand(ctx)).addCommand(createJsCheckCommand(ctx)).addCommand(createTsCheckCommand(ctx)).addCommand(createLintCommand(ctx)).addCommand(createFormatCommand(ctx)).addCommand(createTestStaticCommand(ctx)).addCommand(createCleanCommand()).addCommand(createPkgsCommand(ctx)).addCommand(createConfigCommand(ctx)).addCommand(createRunCommand(ctx), { hidden: true }).addCommand(createToolsCommand(ctx), { hidden: true }),
|
|
571
|
+
ctx
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
//#endregion
|
|
575
|
+
//#region src/program/parse-args.ts
|
|
576
|
+
const debug = logger.subdebug("parseArgs");
|
|
577
|
+
function parseArgs(argv = process.argv) {
|
|
578
|
+
const args = argv.slice(2);
|
|
579
|
+
const allArgsAreValidCommands = args.every((arg) => !arg.startsWith("-")) && args.length > 1 && args[0] !== "tools";
|
|
580
|
+
debug("args %O", args);
|
|
581
|
+
if (allArgsAreValidCommands) {
|
|
582
|
+
debug("multiple commands detected, adding 'run' command");
|
|
583
|
+
return ["run", ...args];
|
|
584
|
+
}
|
|
585
|
+
return args;
|
|
586
|
+
}
|
|
587
|
+
//#endregion
|
|
588
|
+
//#region src/main.ts
|
|
589
|
+
async function main(options) {
|
|
590
|
+
await run(async () => {
|
|
591
|
+
const { program } = await createProgram(options);
|
|
592
|
+
await program.parseAsync(parseArgs(), { from: "user" });
|
|
593
|
+
}, logger);
|
|
594
|
+
}
|
|
595
|
+
//#endregion
|
|
596
|
+
//#region bin.ts
|
|
597
|
+
main({ binDir: __dirname });
|
|
598
|
+
//#endregion
|
|
599
|
+
export {};
|
package/dist/config.mjs
CHANGED
package/dist/tools/tsdown.mjs
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export * from "tsdown"
|
|
2
|
-
|
|
3
|
-
export { };
|
|
1
|
+
export * from "tsdown";
|
|
2
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vlandoss/run-run",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.22-git-9445806.0",
|
|
4
4
|
"description": "The CLI toolbox to fullstack common scripts in Variable Land",
|
|
5
5
|
"homepage": "https://github.com/variableland/dx/tree/main/packages/run-run#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/variableland/dx.git"
|
|
11
|
+
"url": "git+https://github.com/variableland/dx.git",
|
|
12
|
+
"directory": "packages/run-run"
|
|
12
13
|
},
|
|
13
14
|
"license": "MIT",
|
|
14
15
|
"author": "rcrd <rcrd@variable.land>",
|
|
@@ -19,19 +20,17 @@
|
|
|
19
20
|
},
|
|
20
21
|
"exports": {
|
|
21
22
|
"./config": {
|
|
22
|
-
"bun": "./src/lib/config.ts",
|
|
23
23
|
"types": "./dist/config.d.mts",
|
|
24
24
|
"default": "./dist/config.mjs"
|
|
25
25
|
},
|
|
26
26
|
"./tools/*": {
|
|
27
|
-
"bun": "./src/lib/tools/*.ts",
|
|
28
27
|
"types": "./dist/tools/*.d.mts",
|
|
29
28
|
"default": "./dist/tools/*.mjs"
|
|
30
29
|
}
|
|
31
30
|
},
|
|
32
31
|
"bin": {
|
|
33
|
-
"rr": "./bin.
|
|
34
|
-
"run-run": "./bin.
|
|
32
|
+
"rr": "./dist/bin.mjs",
|
|
33
|
+
"run-run": "./dist/bin.mjs",
|
|
35
34
|
"biome": "./tools/biome",
|
|
36
35
|
"oxfmt": "./tools/oxfmt",
|
|
37
36
|
"oxlint": "./tools/oxlint"
|
|
@@ -40,6 +39,8 @@
|
|
|
40
39
|
"bin.ts",
|
|
41
40
|
"dist",
|
|
42
41
|
"src",
|
|
42
|
+
"!src/**/__tests__",
|
|
43
|
+
"!src/**/*.test.*",
|
|
43
44
|
"tools",
|
|
44
45
|
"tsconfig.json"
|
|
45
46
|
],
|
|
@@ -54,17 +55,21 @@
|
|
|
54
55
|
"oxlint": "1.50.0",
|
|
55
56
|
"oxlint-tsgolint": "0.15.0",
|
|
56
57
|
"rimraf": "6.1.3",
|
|
57
|
-
"tsdown": "0.21.
|
|
58
|
+
"tsdown": "0.21.10",
|
|
58
59
|
"typescript": "5.9.3",
|
|
59
|
-
"@vlandoss/clibuddy": "0.0.
|
|
60
|
-
"@vlandoss/loggy": "0.0.
|
|
60
|
+
"@vlandoss/clibuddy": "0.0.11-git-9445806.0",
|
|
61
|
+
"@vlandoss/loggy": "0.0.8-git-9445806.0"
|
|
61
62
|
},
|
|
62
63
|
"publishConfig": {
|
|
63
64
|
"access": "public"
|
|
64
65
|
},
|
|
65
66
|
"engines": {
|
|
67
|
+
"node": ">=20.0.0",
|
|
66
68
|
"bun": ">=1.0.0"
|
|
67
69
|
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@vlandoss/tsdown-config": "^0.0.2-git-9445806.0"
|
|
72
|
+
},
|
|
68
73
|
"scripts": {
|
|
69
74
|
"build": "tsdown",
|
|
70
75
|
"test": "bun test",
|
package/tools/biome
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
|
|
2
|
+
rr tools biome "$@"
|
package/tools/oxfmt
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
|
|
2
|
+
rr tools oxfmt "$@"
|
package/tools/oxlint
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
|
|
2
|
+
rr tools oxlint "$@"
|
package/tools/tsdown
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
|
|
2
|
+
rr tools tsdown "$@"
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
|
|
2
|
-
|
|
3
|
-
exports[`should match all root commands: root-command---help 1`] = `
|
|
4
|
-
"🦊 R U N - R U N v0.0.0-test
|
|
5
|
-
The CLI toolbox for https://variable.land 👊
|
|
6
|
-
|
|
7
|
-
Usage: rr|run-run [options] <command...>
|
|
8
|
-
|
|
9
|
-
Options:
|
|
10
|
-
-v, --version output the version number
|
|
11
|
-
-h, --help display help for command
|
|
12
|
-
|
|
13
|
-
Commands:
|
|
14
|
-
build:lib build a ts library 🏗️ (tsdown)
|
|
15
|
-
jsc|jscheck [options] check format and lint 🔍 (biome)
|
|
16
|
-
tsc|tscheck check typescript errors 🧩 (tsc)
|
|
17
|
-
lint [options] check & fix lint errors 🔍 (biome)
|
|
18
|
-
format [options] check & fix format errors 🎨 (biome)
|
|
19
|
-
test:static run static tests 🔬 (run-run)
|
|
20
|
-
clean [options] delete dirty files 🗑️ (rimraf)
|
|
21
|
-
pkgs [options] list affected packages 📦
|
|
22
|
-
config display the current config 🛠️
|
|
23
|
-
|
|
24
|
-
Acknowledgment:
|
|
25
|
-
- kcd-scripts: for main inspiration
|
|
26
|
-
https://github.com/kentcdodds/kcd-scripts
|
|
27
|
-
|
|
28
|
-
- peruvian news: in honor to Run Run
|
|
29
|
-
https://es.wikipedia.org/wiki/Run_Run
|
|
30
|
-
"
|
|
31
|
-
`;
|
|
32
|
-
|
|
33
|
-
exports[`should match all root commands: root-command---version 1`] = `
|
|
34
|
-
"0.0.0-test
|
|
35
|
-
"
|
|
36
|
-
`;
|
|
37
|
-
|
|
38
|
-
exports[`should match all root commands: root-command--v 1`] = `
|
|
39
|
-
"0.0.0-test
|
|
40
|
-
"
|
|
41
|
-
`;
|
|
42
|
-
|
|
43
|
-
exports[`should match help messages for all commands: help-command-build:lib 1`] = `
|
|
44
|
-
"Usage: rr build:lib [options]
|
|
45
|
-
|
|
46
|
-
Compiles TypeScript code into JavaScript and generates type declaration files,
|
|
47
|
-
making it ready for distribution.
|
|
48
|
-
|
|
49
|
-
Options:
|
|
50
|
-
-h, --help display help for command
|
|
51
|
-
|
|
52
|
-
Under the hood, this command uses the tsdown CLI to build the project.
|
|
53
|
-
"
|
|
54
|
-
`;
|
|
55
|
-
|
|
56
|
-
exports[`should match help messages for all commands: help-command-jsc 1`] = `
|
|
57
|
-
"Usage: rr jsc|jscheck [options]
|
|
58
|
-
|
|
59
|
-
Checks the code for formatting and linting issues, ensuring it adheres to the
|
|
60
|
-
defined style and quality standards.
|
|
61
|
-
|
|
62
|
-
Options:
|
|
63
|
-
--fix try to fix issues automatically
|
|
64
|
-
--fix-staged try to fix staged files only
|
|
65
|
-
-h, --help display help for command
|
|
66
|
-
|
|
67
|
-
Under the hood, this command uses the biome CLI to check the code.
|
|
68
|
-
"
|
|
69
|
-
`;
|
|
70
|
-
|
|
71
|
-
exports[`should match help messages for all commands: help-command-tsc 1`] = `
|
|
72
|
-
"Usage: rr tsc|tscheck [options]
|
|
73
|
-
|
|
74
|
-
Checks the TypeScript code for type errors, ensuring that the code adheres to
|
|
75
|
-
the defined type constraints and helps catch potential issues before runtime.
|
|
76
|
-
|
|
77
|
-
Options:
|
|
78
|
-
-h, --help display help for command
|
|
79
|
-
|
|
80
|
-
Under the hood, this command uses the tsc CLI to check the code.
|
|
81
|
-
"
|
|
82
|
-
`;
|
|
83
|
-
|
|
84
|
-
exports[`should match help messages for all commands: help-command-lint 1`] = `
|
|
85
|
-
"Usage: rr lint [options]
|
|
86
|
-
|
|
87
|
-
Checks the code for linting issues and optionally fixes them, ensuring it
|
|
88
|
-
adheres to the defined quality standards.
|
|
89
|
-
|
|
90
|
-
Options:
|
|
91
|
-
-c, --check check if the code is valid (default: true)
|
|
92
|
-
--fix try to fix all the code
|
|
93
|
-
-h, --help display help for command
|
|
94
|
-
|
|
95
|
-
Under the hood, this command uses the biome CLI to lint the code.
|
|
96
|
-
"
|
|
97
|
-
`;
|
|
98
|
-
|
|
99
|
-
exports[`should match help messages for all commands: help-command-format 1`] = `
|
|
100
|
-
"Usage: rr format [options]
|
|
101
|
-
|
|
102
|
-
Checks the code for formatting issues and optionally fixes them, ensuring it
|
|
103
|
-
adheres to the defined style standards.
|
|
104
|
-
|
|
105
|
-
Options:
|
|
106
|
-
--fix format all the code
|
|
107
|
-
-h, --help display help for command
|
|
108
|
-
|
|
109
|
-
Under the hood, this command uses the biome CLI to format the code.
|
|
110
|
-
"
|
|
111
|
-
`;
|
|
112
|
-
|
|
113
|
-
exports[`should match help messages for all commands: help-command-test:static 1`] = `
|
|
114
|
-
"Usage: rr test:static [options]
|
|
115
|
-
|
|
116
|
-
Runs static tests, including linting, formatting checks, and TypeScript type
|
|
117
|
-
checking, to ensure code quality and correctness without executing the code.
|
|
118
|
-
|
|
119
|
-
Options:
|
|
120
|
-
-h, --help display help for command
|
|
121
|
-
"
|
|
122
|
-
`;
|
|
123
|
-
|
|
124
|
-
exports[`should match help messages for all commands: help-command-clean 1`] = `
|
|
125
|
-
"Usage: rr clean [options]
|
|
126
|
-
|
|
127
|
-
Deletes generated files and folders such as 'dist', 'node_modules', and lock
|
|
128
|
-
files to ensure a clean state.
|
|
129
|
-
|
|
130
|
-
Options:
|
|
131
|
-
--only-dist delete 'dist' folders only
|
|
132
|
-
--dry-run outputs the paths that would be deleted
|
|
133
|
-
-h, --help display help for command
|
|
134
|
-
|
|
135
|
-
Under the hood, this command uses rimraf to delete dirty folders or files.
|
|
136
|
-
"
|
|
137
|
-
`;
|
|
138
|
-
|
|
139
|
-
exports[`should match help messages for all commands: help-command-pkgs 1`] = `
|
|
140
|
-
"Usage: rr pkgs [options]
|
|
141
|
-
|
|
142
|
-
Given a list of files, returns the list of affected packages. Useful to run
|
|
143
|
-
commands only on affected packages.
|
|
144
|
-
|
|
145
|
-
Options:
|
|
146
|
-
--files <files...> list of files to check
|
|
147
|
-
--decorator [type] type of decorator to use (choices: "turbo")
|
|
148
|
-
-h, --help display help for command
|
|
149
|
-
"
|
|
150
|
-
`;
|
|
151
|
-
|
|
152
|
-
exports[`should match help messages for all commands: help-command-config 1`] = `
|
|
153
|
-
"Usage: rr config [options]
|
|
154
|
-
|
|
155
|
-
Displays the current configuration settings, including their source file path if
|
|
156
|
-
available.
|
|
157
|
-
|
|
158
|
-
Options:
|
|
159
|
-
-h, --help display help for command
|
|
160
|
-
"
|
|
161
|
-
`;
|
|
162
|
-
|
|
163
|
-
exports[`should match help messages for all commands: help-command-run 1`] = `
|
|
164
|
-
"Usage: rr run [options] <cmds...>
|
|
165
|
-
|
|
166
|
-
Arguments:
|
|
167
|
-
cmds commands to execute concurrently (e.g. 'check tsc')
|
|
168
|
-
|
|
169
|
-
Options:
|
|
170
|
-
-h, --help display help for command
|
|
171
|
-
"
|
|
172
|
-
`;
|
|
173
|
-
|
|
174
|
-
exports[`should match help messages for all commands: help-command-tools 1`] = `
|
|
175
|
-
"Usage: rr tools [options] [command]
|
|
176
|
-
|
|
177
|
-
expose the internal tools 🛠️
|
|
178
|
-
|
|
179
|
-
Options:
|
|
180
|
-
-h, --help display help for command
|
|
181
|
-
|
|
182
|
-
Commands:
|
|
183
|
-
biome
|
|
184
|
-
oxfmt
|
|
185
|
-
oxlint
|
|
186
|
-
tsdown
|
|
187
|
-
help [command] display help for command
|
|
188
|
-
"
|
|
189
|
-
`;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { afterEach, expect, test } from "bun:test";
|
|
2
|
-
import { createTestProgram, execCli, mocked } from "#test/helpers.ts";
|
|
3
|
-
|
|
4
|
-
const { program, ctx } = await createTestProgram();
|
|
5
|
-
const $ = ctx.shell.$;
|
|
6
|
-
|
|
7
|
-
const rootCommands = ["--help", "--version", "-v"];
|
|
8
|
-
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
mocked($).mockClear();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test("should match all root commands", async () => {
|
|
14
|
-
const results = await Promise.all(
|
|
15
|
-
rootCommands.map(async (cmd) => {
|
|
16
|
-
const { stdout } = await execCli(cmd);
|
|
17
|
-
return { cmd, output: stdout };
|
|
18
|
-
}),
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
for (const { cmd, output } of results) {
|
|
22
|
-
expect(output).toMatchSnapshot(`root-command-${cmd}`);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("should match help messages for all commands", async () => {
|
|
27
|
-
const results = await Promise.all(
|
|
28
|
-
program.commands.map(async (command) => {
|
|
29
|
-
const cmd = command.name();
|
|
30
|
-
const { stdout } = await execCli(`${cmd} --help`);
|
|
31
|
-
return { cmd, output: stdout };
|
|
32
|
-
}),
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
for (const { cmd, output } of results) {
|
|
36
|
-
expect(output).toMatchSnapshot(`help-command-${cmd}`);
|
|
37
|
-
}
|
|
38
|
-
});
|