@vlandoss/run-run 0.5.2 → 0.5.3-git-a483516.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.
@@ -1,7 +1,7 @@
1
1
  // @generated by @usage-spec/commander from Commander.js metadata
2
2
  name rr
3
3
  bin rr
4
- version "0.5.2"
4
+ version "0.5.3-git-a483516.0"
5
5
  usage "[options] <command...>"
6
6
  flag --usage help="print KDL spec for this CLI (https://kdl.dev)"
7
7
  cmd completion help="print shell completion script 🐚 (usage)" {
package/dist/run.mjs CHANGED
@@ -1,18 +1,14 @@
1
- import { createRequire } from "node:module";
2
1
  import path from "node:path";
3
- import { colorize, createPkg, createShellService, cwd, dirnameOf, isCI, palette, run, text } from "@vlandoss/clibuddy";
2
+ import { colorize, createPkg, createShellService, cwd, dirnameOf, isCI, palette, resolveBinPath, run, text } from "@vlandoss/clibuddy";
4
3
  import { Argument, Option, createCommand } from "commander";
5
4
  import fs from "node:fs";
6
5
  import os from "node:os";
7
6
  import { lilconfig } from "lilconfig";
8
7
  import { createLoggy } from "@vlandoss/loggy";
9
- import memoize from "memoize";
10
8
  import { glob } from "glob";
11
9
  import { rimraf } from "rimraf";
10
+ import memoize from "memoize";
12
11
  import { generateToStdout } from "@usage-spec/commander";
13
- //#region \0rolldown/runtime.js
14
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
15
- //#endregion
16
12
  //#region src/services/logger.ts
17
13
  const logger = createLoggy({ namespace: "run-run" });
18
14
  //#endregion
@@ -68,10 +64,7 @@ async function createContext(binDir) {
68
64
  if (!appPkg) throw new Error("Could not find app package.json");
69
65
  debug("app pkg info: %O", appPkg.info());
70
66
  debug("bin pkg info: %O", binPkg.info());
71
- const shell = createShellService({
72
- localBaseBinPath: [binDir],
73
- stdio: "inherit"
74
- });
67
+ const shell = createShellService();
75
68
  debug("shell service options: %O", shell.options);
76
69
  return {
77
70
  appPkg,
@@ -130,38 +123,20 @@ var ToolService = class {
130
123
  this.#ui = ui ?? bin;
131
124
  this.#shellService = shellService;
132
125
  }
133
- async exec(args) {
134
- const shell = this.#shell();
135
- return this.#run(shell, args);
126
+ async exec(args = []) {
127
+ return this.#shellService.run(this.getBinDir(), args, { display: this.#bin });
136
128
  }
137
129
  async doctor() {
138
- const shell = this.#shell().mute();
139
- const output = await this.#run(shell, "--help");
130
+ const output = await this.#shellService.runCaptured(this.getBinDir(), ["--help"], { throwOnError: false });
140
131
  return {
141
132
  ok: output.exitCode === 0,
142
- output
133
+ output: {
134
+ stdout: output.stdout,
135
+ stderr: output.stderr,
136
+ exitCode: output.exitCode
137
+ }
143
138
  };
144
139
  }
145
- #shell = memoize((cwd) => {
146
- const preferLocal = this.#getPreferLocal();
147
- return this.#shellService.child({
148
- ...cwd && { cwd },
149
- ...preferLocal && { preferLocal }
150
- });
151
- });
152
- #run(shell, args) {
153
- if (!args) return shell.$`${this.#bin}`;
154
- return shell.$`${this.#bin} ${typeof args === "string" ? args : args.join(" ")}`;
155
- }
156
- #getPreferLocal() {
157
- if (!this.getBinDir) return;
158
- try {
159
- const binPath = this.getBinDir();
160
- return fs.statSync(binPath).isDirectory() ? binPath : path.dirname(binPath);
161
- } catch {
162
- return;
163
- }
164
- }
165
140
  get bin() {
166
141
  return this.#bin;
167
142
  }
@@ -179,6 +154,9 @@ var TsdownService = class extends ToolService {
179
154
  shellService
180
155
  });
181
156
  }
157
+ getBinDir() {
158
+ return resolveBinPath("tsdown", { from: import.meta.url });
159
+ }
182
160
  async buildLib() {
183
161
  await this.exec();
184
162
  }
@@ -263,6 +241,7 @@ function createConfigCommand(ctx) {
263
241
  }
264
242
  //#endregion
265
243
  //#region src/services/biome.ts
244
+ const COMMON_FLAGS = ["--colors=force", "--no-errors-on-unmatched"];
266
245
  var BiomeService = class extends ToolService {
267
246
  constructor(shellService) {
268
247
  super({
@@ -272,23 +251,38 @@ var BiomeService = class extends ToolService {
272
251
  });
273
252
  }
274
253
  getBinDir() {
275
- return createRequire(import.meta.url).resolve("@biomejs/biome/bin/biome");
254
+ return resolveBinPath("@biomejs/biome", {
255
+ from: import.meta.url,
256
+ binName: "biome"
257
+ });
276
258
  }
277
259
  async format(options) {
278
- const commonOptions = "format --colors=force --no-errors-on-unmatched";
279
- if (options.fix) await this.exec(`${commonOptions} --fix`);
280
- else await this.exec(`${commonOptions}`);
260
+ const args = ["format", ...COMMON_FLAGS];
261
+ if (options.fix) args.push("--fix");
262
+ await this.exec(args);
281
263
  }
282
264
  async lint(options) {
283
- const commonOptions = "check --colors=force --no-errors-on-unmatched --formatter-enabled=false";
284
- if (options.fix) await this.exec(`${commonOptions} --fix --unsafe`);
285
- else await this.exec(`${commonOptions}`);
265
+ const args = [
266
+ "check",
267
+ ...COMMON_FLAGS,
268
+ "--formatter-enabled=false"
269
+ ];
270
+ if (options.fix) args.push("--fix", "--unsafe");
271
+ await this.exec(args);
286
272
  }
287
273
  async check(options) {
288
- const commonOptions = (cmd = "check") => `${cmd} --colors=force --no-errors-on-unmatched`;
289
- if (options.fix) await this.exec(`${commonOptions()} --fix`);
290
- else if (options.fixStaged) await this.exec(`${commonOptions()} --fix --staged`);
291
- else await this.exec(`${commonOptions(isCI ? "ci" : "check")}`);
274
+ if (options.fix) await this.exec([
275
+ "check",
276
+ ...COMMON_FLAGS,
277
+ "--fix"
278
+ ]);
279
+ else if (options.fixStaged) await this.exec([
280
+ "check",
281
+ ...COMMON_FLAGS,
282
+ "--fix",
283
+ "--staged"
284
+ ]);
285
+ else await this.exec([isCI ? "ci" : "check", ...COMMON_FLAGS]);
292
286
  }
293
287
  };
294
288
  //#endregion
@@ -302,12 +296,10 @@ var OxfmtService = class extends ToolService {
302
296
  });
303
297
  }
304
298
  getBinDir() {
305
- return __require.resolve("oxfmt/bin/oxfmt");
299
+ return resolveBinPath("oxfmt", { from: import.meta.url });
306
300
  }
307
301
  async format(options) {
308
- const commonOptions = "--no-error-on-unmatched-pattern";
309
- if (options.fix) await this.exec(`${commonOptions} --fix`);
310
- else await this.exec(`${commonOptions} --check`);
302
+ await this.exec(["--no-error-on-unmatched-pattern", options.fix ? "--fix" : "--check"]);
311
303
  }
312
304
  };
313
305
  //#endregion
@@ -342,12 +334,10 @@ var OxlintService = class extends ToolService {
342
334
  });
343
335
  }
344
336
  getBinDir() {
345
- return __require.resolve("oxlint/bin/oxlint");
337
+ return resolveBinPath("oxlint", { from: import.meta.url });
346
338
  }
347
339
  async lint(options) {
348
- const commonOptions = "--report-unused-disable-directives";
349
- if (options.fix) await this.exec(`${commonOptions} --fix`);
350
- else await this.exec(`${commonOptions} --check`);
340
+ await this.exec(["--report-unused-disable-directives", options.fix ? "--fix" : "--check"]);
351
341
  }
352
342
  };
353
343
  //#endregion
@@ -402,7 +392,11 @@ function createPkgsCommand(ctx) {
402
392
  //#region src/program/commands/test-static.ts
403
393
  function createTestStaticCommand(ctx) {
404
394
  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() {
405
- await ctx.shell.$`rr x jscheck tscheck`;
395
+ await ctx.shell.run("rr", [
396
+ "x",
397
+ "jscheck",
398
+ "tscheck"
399
+ ]);
406
400
  });
407
401
  }
408
402
  //#endregion
@@ -435,6 +429,12 @@ var TscService = class extends ToolService {
435
429
  shellService
436
430
  });
437
431
  }
432
+ getBinDir() {
433
+ return resolveBinPath("typescript", {
434
+ from: import.meta.url,
435
+ binName: "tsc"
436
+ });
437
+ }
438
438
  };
439
439
  //#endregion
440
440
  //#region src/program/commands/tscheck.ts
@@ -451,7 +451,7 @@ async function typecheckAt({ dir, scripts, log, shell, run }) {
451
451
  const preScript = getPreScript(scripts);
452
452
  if (preScript) {
453
453
  log.start(`Running pre-script: ${preScript}`);
454
- await shellAt.$`${preScript}`;
454
+ await shellAt.run(preScript, [], { shell: true });
455
455
  log.success("Pre-script completed");
456
456
  }
457
457
  log.start("Type checking started");
@@ -469,8 +469,12 @@ function createTsCheckCommand(ctx) {
469
469
  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.").addCommand(createDoctorSubcommand(doctorService)).addHelpText("afterAll", `\nUnder the hood, this command uses the ${toolUi} CLI to check the code.`).action(async function typecheckAction() {
470
470
  const isTsProject = (dir) => appPkg.hasFile("tsconfig.json", dir);
471
471
  const runTypecheck = async (shell) => {
472
- if (config.future?.oxc) await new OxlintService(shell).exec(`--type-aware --type-check --report-unused-disable-directives`);
473
- else await new TscService(shell).exec(`--noEmit`);
472
+ if (config.future?.oxc) await new OxlintService(shell).exec([
473
+ "--type-aware",
474
+ "--type-check",
475
+ "--report-unused-disable-directives"
476
+ ]);
477
+ else await new TscService(shell).exec(["--noEmit"]);
474
478
  };
475
479
  if (!appPkg.isMonorepo()) {
476
480
  if (!isTsProject(appPkg.dirPath)) {
@@ -515,8 +519,7 @@ function addUsage(program) {
515
519
  //#region src/program/commands/x.ts
516
520
  function createXCommand(ctx) {
517
521
  return createCommand("x").summary("run multiple rr subcommands concurrently").description("Run multiple rr subcommands concurrently (e.g. `rr x jsc tsc`).").argument("<cmds...>", "rr subcommands to execute concurrently").action(async function runXAction(cmds) {
518
- const { $ } = ctx.shell;
519
- if ((await Promise.allSettled(cmds.map((cmd) => $`rr ${cmd}`))).some((r) => r.status === "rejected")) process.exitCode = 1;
522
+ if ((await Promise.allSettled(cmds.map((cmd) => ctx.shell.run("rr", [cmd])))).some((r) => r.status === "rejected")) process.exitCode = 1;
520
523
  });
521
524
  }
522
525
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vlandoss/run-run",
3
- "version": "0.5.2",
3
+ "version": "0.5.3-git-a483516.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": {
@@ -63,8 +63,8 @@
63
63
  "rimraf": "6.1.3",
64
64
  "tsdown": "0.21.10",
65
65
  "typescript": "6.0.3",
66
- "@vlandoss/loggy": "0.2.0",
67
- "@vlandoss/clibuddy": "0.5.0"
66
+ "@vlandoss/clibuddy": "0.5.1-git-a483516.0",
67
+ "@vlandoss/loggy": "0.2.0"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@vlandoss/tsdown-config": "^0.0.1"
@@ -9,6 +9,6 @@ export function createTestStaticCommand(ctx: Context) {
9
9
  "Runs static tests, including linting, formatting checks, and TypeScript type checking, to ensure code quality and correctness without executing the code.",
10
10
  )
11
11
  .action(async function testStaticAction() {
12
- await ctx.shell.$`rr x jscheck tscheck`;
12
+ await ctx.shell.run("rr", ["x", "jscheck", "tscheck"]);
13
13
  });
14
14
  }
@@ -34,7 +34,9 @@ async function typecheckAt({ dir, scripts, log, shell, run }: TypecheckAtOptions
34
34
  const preScript = getPreScript(scripts);
35
35
  if (preScript) {
36
36
  log.start(`Running pre-script: ${preScript}`);
37
- await shellAt.$`${preScript}`;
37
+ // Pre-scripts come from package.json and may contain shell features
38
+ // (`&&`, pipes, env-var substitution) — run them through `/bin/sh -c`.
39
+ await shellAt.run(preScript, [], { shell: true });
38
40
  log.success("Pre-script completed");
39
41
  }
40
42
 
@@ -71,11 +73,10 @@ export function createTsCheckCommand(ctx: Context) {
71
73
  const runTypecheck = async (shell: ShellService) => {
72
74
  if (config.future?.oxc) {
73
75
  const oxlint = new OxlintService(shell);
74
- await oxlint.exec(`--type-aware --type-check --report-unused-disable-directives`);
76
+ await oxlint.exec(["--type-aware", "--type-check", "--report-unused-disable-directives"]);
75
77
  } else {
76
78
  const tsc = new TscService(shell);
77
- await tsc.exec(`--noEmit`);
78
- // await shell.$`tsc --noEmit`;
79
+ await tsc.exec(["--noEmit"]);
79
80
  }
80
81
  };
81
82
 
@@ -7,8 +7,7 @@ export function createXCommand(ctx: Context) {
7
7
  .description("Run multiple rr subcommands concurrently (e.g. `rr x jsc tsc`).")
8
8
  .argument("<cmds...>", "rr subcommands to execute concurrently")
9
9
  .action(async function runXAction(cmds: string[]) {
10
- const { $ } = ctx.shell;
11
- const results = await Promise.allSettled(cmds.map((cmd) => $`rr ${cmd}`));
10
+ const results = await Promise.allSettled(cmds.map((cmd) => ctx.shell.run("rr", [cmd])));
12
11
  if (results.some((r) => r.status === "rejected")) {
13
12
  process.exitCode = 1;
14
13
  }
@@ -1,48 +1,38 @@
1
- import { createRequire } from "node:module";
2
- import { isCI, type ShellService } from "@vlandoss/clibuddy";
1
+ import { isCI, resolveBinPath, type ShellService } from "@vlandoss/clibuddy";
3
2
  import { TOOL_LABELS } from "#src/program/ui.ts";
4
3
  import type { FormatOptions, Formatter, Linter, LintOptions, StaticChecker, StaticCheckerOptions } from "#src/types/tool.ts";
5
4
  import { ToolService } from "./tool.ts";
6
5
 
6
+ const COMMON_FLAGS = ["--colors=force", "--no-errors-on-unmatched"];
7
+
7
8
  export class BiomeService extends ToolService implements Formatter, Linter, StaticChecker {
8
9
  constructor(shellService: ShellService) {
9
10
  super({ bin: "biome", ui: TOOL_LABELS.BIOME, shellService });
10
11
  }
11
12
 
12
13
  override getBinDir() {
13
- const require = createRequire(import.meta.url);
14
- return require.resolve("@biomejs/biome/bin/biome");
14
+ return resolveBinPath("@biomejs/biome", { from: import.meta.url, binName: "biome" });
15
15
  }
16
16
 
17
17
  async format(options: FormatOptions) {
18
- const commonOptions = "format --colors=force --no-errors-on-unmatched";
19
-
20
- if (options.fix) {
21
- await this.exec(`${commonOptions} --fix`);
22
- } else {
23
- await this.exec(`${commonOptions}`);
24
- }
18
+ const args = ["format", ...COMMON_FLAGS];
19
+ if (options.fix) args.push("--fix");
20
+ await this.exec(args);
25
21
  }
26
22
 
27
23
  async lint(options: LintOptions) {
28
- const commonOptions = "check --colors=force --no-errors-on-unmatched --formatter-enabled=false";
29
-
30
- if (options.fix) {
31
- await this.exec(`${commonOptions} --fix --unsafe`);
32
- } else {
33
- await this.exec(`${commonOptions}`);
34
- }
24
+ const args = ["check", ...COMMON_FLAGS, "--formatter-enabled=false"];
25
+ if (options.fix) args.push("--fix", "--unsafe");
26
+ await this.exec(args);
35
27
  }
36
28
 
37
29
  async check(options: StaticCheckerOptions): Promise<void> {
38
- const commonOptions = (cmd = "check") => `${cmd} --colors=force --no-errors-on-unmatched`;
39
-
40
30
  if (options.fix) {
41
- await this.exec(`${commonOptions()} --fix`);
31
+ await this.exec(["check", ...COMMON_FLAGS, "--fix"]);
42
32
  } else if (options.fixStaged) {
43
- await this.exec(`${commonOptions()} --fix --staged`);
33
+ await this.exec(["check", ...COMMON_FLAGS, "--fix", "--staged"]);
44
34
  } else {
45
- await this.exec(`${commonOptions(isCI ? "ci" : "check")}`);
35
+ await this.exec([isCI ? "ci" : "check", ...COMMON_FLAGS]);
46
36
  }
47
37
  }
48
38
  }
@@ -32,10 +32,7 @@ export async function createContext(binDir: string): Promise<Context> {
32
32
  debug("app pkg info: %O", appPkg.info());
33
33
  debug("bin pkg info: %O", binPkg.info());
34
34
 
35
- const shell = createShellService({
36
- localBaseBinPath: [binDir],
37
- stdio: "inherit",
38
- });
35
+ const shell = createShellService();
39
36
 
40
37
  debug("shell service options: %O", shell.options);
41
38
 
@@ -1,4 +1,4 @@
1
- import type { ShellService } from "@vlandoss/clibuddy";
1
+ import { resolveBinPath, type ShellService } from "@vlandoss/clibuddy";
2
2
  import { TOOL_LABELS } from "#src/program/ui.ts";
3
3
  import type { FormatOptions, Formatter } from "#src/types/tool.ts";
4
4
  import { ToolService } from "./tool.ts";
@@ -9,16 +9,10 @@ export class OxfmtService extends ToolService implements Formatter {
9
9
  }
10
10
 
11
11
  override getBinDir() {
12
- return require.resolve("oxfmt/bin/oxfmt");
12
+ return resolveBinPath("oxfmt", { from: import.meta.url });
13
13
  }
14
14
 
15
15
  async format(options: FormatOptions) {
16
- const commonOptions = "--no-error-on-unmatched-pattern";
17
-
18
- if (options.fix) {
19
- await this.exec(`${commonOptions} --fix`);
20
- } else {
21
- await this.exec(`${commonOptions} --check`);
22
- }
16
+ await this.exec(["--no-error-on-unmatched-pattern", options.fix ? "--fix" : "--check"]);
23
17
  }
24
18
  }
@@ -1,4 +1,4 @@
1
- import type { ShellService } from "@vlandoss/clibuddy";
1
+ import { resolveBinPath, type ShellService } from "@vlandoss/clibuddy";
2
2
  import { TOOL_LABELS } from "#src/program/ui.ts";
3
3
  import type { Linter, LintOptions } from "#src/types/tool.ts";
4
4
  import { ToolService } from "./tool.ts";
@@ -9,16 +9,10 @@ export class OxlintService extends ToolService implements Linter {
9
9
  }
10
10
 
11
11
  override getBinDir() {
12
- return require.resolve("oxlint/bin/oxlint");
12
+ return resolveBinPath("oxlint", { from: import.meta.url });
13
13
  }
14
14
 
15
15
  async lint(options: LintOptions) {
16
- const commonOptions = "--report-unused-disable-directives";
17
-
18
- if (options.fix) {
19
- await this.exec(`${commonOptions} --fix`);
20
- } else {
21
- await this.exec(`${commonOptions} --check`);
22
- }
16
+ await this.exec(["--report-unused-disable-directives", options.fix ? "--fix" : "--check"]);
23
17
  }
24
18
  }
@@ -1,7 +1,4 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
1
  import type { ShellService } from "@vlandoss/clibuddy";
4
- import memoize from "memoize";
5
2
  import type { DoctorResult } from "#src/types/tool.ts";
6
3
 
7
4
  type CreateOptions = {
@@ -21,51 +18,22 @@ export abstract class ToolService {
21
18
  this.#shellService = shellService;
22
19
  }
23
20
 
24
- getBinDir?(): string;
21
+ // Must return an absolute path so we bypass the `node_modules/.bin/<bin>`
22
+ // shims that run-run itself publishes (`tools/biome`, etc) — otherwise
23
+ // calling the friendly name loops back through `rr tools <bin>`.
24
+ abstract getBinDir(): string;
25
25
 
26
- async exec(args?: string | string[]) {
27
- const shell = this.#shell();
28
- return this.#run(shell, args);
26
+ async exec(args: string[] = []) {
27
+ return this.#shellService.run(this.getBinDir(), args, { display: this.#bin });
29
28
  }
30
29
 
31
30
  async doctor(): Promise<DoctorResult> {
32
- const shell = this.#shell().mute();
33
-
34
- const output = await this.#run(shell, "--help");
31
+ const output = await this.#shellService.runCaptured(this.getBinDir(), ["--help"], { throwOnError: false });
35
32
  const ok = output.exitCode === 0;
36
-
37
- return { ok, output };
38
- }
39
-
40
- #shell = memoize((cwd?: string) => {
41
- const preferLocal = this.#getPreferLocal();
42
-
43
- return this.#shellService.child({
44
- ...(cwd && { cwd }),
45
- ...(preferLocal && { preferLocal }),
46
- });
47
- });
48
-
49
- #run(shell: ShellService, args?: string | string[]) {
50
- if (!args) {
51
- return shell.$`${this.#bin}`;
52
- }
53
-
54
- return shell.$`${this.#bin} ${typeof args === "string" ? args : args.join(" ")}`;
55
- }
56
-
57
- #getPreferLocal() {
58
- if (!this.getBinDir) {
59
- return undefined;
60
- }
61
-
62
- try {
63
- const binPath = this.getBinDir();
64
- const isDir = fs.statSync(binPath).isDirectory();
65
- return isDir ? binPath : path.dirname(binPath);
66
- } catch {
67
- return undefined;
68
- }
33
+ return {
34
+ ok,
35
+ output: { stdout: output.stdout, stderr: output.stderr, exitCode: output.exitCode },
36
+ };
69
37
  }
70
38
 
71
39
  get bin() {
@@ -1,4 +1,4 @@
1
- import type { ShellService } from "@vlandoss/clibuddy";
1
+ import { resolveBinPath, type ShellService } from "@vlandoss/clibuddy";
2
2
  import { TOOL_LABELS } from "#src/program/ui.ts";
3
3
  import { ToolService } from "./tool.ts";
4
4
 
@@ -6,4 +6,8 @@ export class TscService extends ToolService {
6
6
  constructor(shellService: ShellService) {
7
7
  super({ bin: "tsc", ui: TOOL_LABELS.TSC, shellService });
8
8
  }
9
+
10
+ override getBinDir() {
11
+ return resolveBinPath("typescript", { from: import.meta.url, binName: "tsc" });
12
+ }
9
13
  }
@@ -1,4 +1,4 @@
1
- import type { ShellService } from "@vlandoss/clibuddy";
1
+ import { resolveBinPath, type ShellService } from "@vlandoss/clibuddy";
2
2
  import { TOOL_LABELS } from "#src/program/ui.ts";
3
3
  import { ToolService } from "./tool.ts";
4
4
 
@@ -7,6 +7,10 @@ export class TsdownService extends ToolService {
7
7
  super({ bin: "tsdown", ui: TOOL_LABELS.TSDOWN, shellService });
8
8
  }
9
9
 
10
+ override getBinDir() {
11
+ return resolveBinPath("tsdown", { from: import.meta.url });
12
+ }
13
+
10
14
  async buildLib() {
11
15
  await this.exec();
12
16
  }
package/src/types/tool.ts CHANGED
@@ -14,7 +14,7 @@ export type StaticCheckerOptions = {
14
14
  export type DoctorOutput = {
15
15
  stdout: string;
16
16
  stderr: string;
17
- exitCode: number | null;
17
+ exitCode: number | undefined;
18
18
  };
19
19
 
20
20
  export type DoctorResult = {