Skip to content
This repository was archived by the owner on Dec 27, 2025. It is now read-only.

Commit f987f4d

Browse files
authored
Merge pull request #1 from jsr-probitas/feat/new-command
Add fmt, lint, and check commands for scenario files
2 parents 8077381 + 57ce13b commit f987f4d

File tree

10 files changed

+312
-0
lines changed

10 files changed

+312
-0
lines changed

assets/usage-check.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
probitas check - Type-check scenario files
2+
3+
Usage: probitas check [options] [paths...]
4+
5+
Arguments:
6+
[paths...] Scenario files or directories
7+
Defaults to current directory
8+
9+
Options:
10+
-h, --help Show help message
11+
--include <pattern> Include pattern for file discovery
12+
--exclude <pattern> Exclude pattern for file discovery
13+
--config <path> Path to probitas config file
14+
-v, --verbose Verbose output
15+
-q, --quiet Suppress output
16+
-d, --debug Debug output
17+
18+
Note:
19+
Runs `deno check --no-config` on discovered scenario files.
20+
Uses includes/excludes from probitas config (same as run/list).
21+
22+
Examples:
23+
probitas check # Check all scenario files
24+
probitas check api/ # Check scenarios in api directory
25+
probitas check --include "e2e/**/*.probitas.ts"
26+
27+
Documentation: https://jsr-probitas.github.io/documents/

assets/usage-fmt.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
probitas fmt - Format scenario files
2+
3+
Usage: probitas fmt [options] [paths...]
4+
5+
Arguments:
6+
[paths...] Scenario files or directories
7+
Defaults to current directory
8+
9+
Options:
10+
-h, --help Show help message
11+
--include <pattern> Include pattern for file discovery
12+
--exclude <pattern> Exclude pattern for file discovery
13+
--config <path> Path to probitas config file
14+
-v, --verbose Verbose output
15+
-q, --quiet Suppress output
16+
-d, --debug Debug output
17+
18+
Note:
19+
Runs `deno fmt --no-config` on discovered scenario files.
20+
Uses includes/excludes from probitas config (same as run/list).
21+
22+
Examples:
23+
probitas fmt # Format all scenario files
24+
probitas fmt api/ # Format scenarios in api directory
25+
probitas fmt --include "e2e/**/*.probitas.ts"
26+
27+
Documentation: https://jsr-probitas.github.io/documents/

assets/usage-lint.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
probitas lint - Lint scenario files
2+
3+
Usage: probitas lint [options] [paths...]
4+
5+
Arguments:
6+
[paths...] Scenario files or directories
7+
Defaults to current directory
8+
9+
Options:
10+
-h, --help Show help message
11+
--include <pattern> Include pattern for file discovery
12+
--exclude <pattern> Exclude pattern for file discovery
13+
--config <path> Path to probitas config file
14+
-v, --verbose Verbose output
15+
-q, --quiet Suppress output
16+
-d, --debug Debug output
17+
18+
Note:
19+
Runs `deno lint --no-config` on discovered scenario files.
20+
Uses includes/excludes from probitas config (same as run/list).
21+
Automatically excludes rules: no-import-prefix, no-unversioned-import
22+
23+
Examples:
24+
probitas lint # Lint all scenario files
25+
probitas lint api/ # Lint scenarios in api directory
26+
probitas lint --include "e2e/**/*.probitas.ts"
27+
28+
Documentation: https://jsr-probitas.github.io/documents/

assets/usage.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ Commands:
66
init Initialize a new probitas project
77
run Run scenarios
88
list List available scenarios
9+
fmt Format scenario files (runs deno fmt)
10+
lint Lint scenario files (runs deno lint)
11+
check Type-check scenario files (runs deno check)
912

1013
Options:
1114
-h, --help Show help message

src/commands/_deno.ts

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/**
2+
* Shared helper for Deno subcommand execution
3+
*
4+
* Used by fmt, lint, and check commands to run corresponding deno commands
5+
* on discovered scenario files.
6+
*
7+
* @module
8+
*/
9+
10+
import { parseArgs } from "@std/cli";
11+
import { resolve } from "@std/path";
12+
import { configureLogging, getLogger, type LogLevel } from "@probitas/logger";
13+
import { discoverScenarioFiles } from "@probitas/discover";
14+
import { EXIT_CODE } from "../constants.ts";
15+
import { findProbitasConfigFile, loadConfig } from "../config.ts";
16+
import { createDiscoveryProgress } from "../progress.ts";
17+
import { readAsset } from "../utils.ts";
18+
19+
const logger = getLogger("probitas", "cli", "deno");
20+
21+
/**
22+
* Options for running a Deno subcommand
23+
*/
24+
export interface DenoSubcommandOptions {
25+
/** Asset file name for help text */
26+
usageAsset: string;
27+
/** Extra arguments to pass to the deno command */
28+
extraArgs?: readonly string[];
29+
}
30+
31+
/**
32+
* Run a Deno subcommand on discovered scenario files
33+
*
34+
* @param subcommand - Deno subcommand to run (fmt, lint, check)
35+
* @param args - Command-line arguments
36+
* @param cwd - Current working directory
37+
* @param options - Subcommand options
38+
* @returns Exit code from the deno command
39+
*/
40+
export async function runDenoSubcommand(
41+
subcommand: string,
42+
args: string[],
43+
cwd: string,
44+
options: DenoSubcommandOptions,
45+
): Promise<number> {
46+
try {
47+
const parsed = parseArgs(args, {
48+
string: ["config", "include", "exclude"],
49+
boolean: ["help", "quiet", "verbose", "debug"],
50+
collect: ["include", "exclude"],
51+
alias: {
52+
h: "help",
53+
v: "verbose",
54+
q: "quiet",
55+
d: "debug",
56+
},
57+
default: {
58+
include: undefined,
59+
exclude: undefined,
60+
},
61+
});
62+
63+
if (parsed.help) {
64+
const helpText = await readAsset(options.usageAsset);
65+
console.log(helpText);
66+
return EXIT_CODE.SUCCESS;
67+
}
68+
69+
// Determine log level
70+
const logLevel: LogLevel = parsed.debug
71+
? "debug"
72+
: parsed.verbose
73+
? "info"
74+
: parsed.quiet
75+
? "fatal"
76+
: "warning";
77+
78+
try {
79+
await configureLogging(logLevel);
80+
} catch {
81+
// Ignore - logging may already be configured
82+
}
83+
84+
// Load probitas config (NOT deno.json)
85+
const configPath = parsed.config ??
86+
await findProbitasConfigFile(cwd, { parentLookup: true });
87+
const config = configPath ? await loadConfig(configPath) : {};
88+
89+
// CLI > config
90+
const includes = parsed.include ?? config?.includes;
91+
const excludes = parsed.exclude ?? config?.excludes;
92+
93+
// Discover scenario files
94+
const paths = parsed._.map(String).map((p) => resolve(cwd, p));
95+
const discoveryProgress = parsed.quiet ? null : createDiscoveryProgress();
96+
const scenarioFiles = await discoverScenarioFiles(
97+
paths.length ? paths : [cwd],
98+
{ includes, excludes, onProgress: discoveryProgress?.onProgress },
99+
);
100+
discoveryProgress?.complete(scenarioFiles.length);
101+
102+
if (scenarioFiles.length === 0) {
103+
console.warn("No scenario files found");
104+
return EXIT_CODE.NOT_FOUND;
105+
}
106+
107+
logger.debug(`Running deno ${subcommand}`, {
108+
fileCount: scenarioFiles.length,
109+
});
110+
111+
// Run deno command with --no-config
112+
const denoArgs = [
113+
subcommand,
114+
"--no-config",
115+
...(options.extraArgs ?? []),
116+
...scenarioFiles,
117+
];
118+
119+
const command = new Deno.Command("deno", {
120+
args: denoArgs,
121+
cwd,
122+
stdin: "inherit",
123+
stdout: "inherit",
124+
stderr: "inherit",
125+
});
126+
127+
const { code } = await command.output();
128+
return code;
129+
} catch (err: unknown) {
130+
logger.error(`deno ${subcommand} failed`, { error: err });
131+
const m = err instanceof Error ? err.message : String(err);
132+
console.error(`Error: ${m}`);
133+
return EXIT_CODE.FAILURE;
134+
}
135+
}

src/commands/check.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Type-check command for Probitas CLI
3+
*
4+
* Runs `deno check --no-config` on discovered scenario files.
5+
*
6+
* @module
7+
*/
8+
9+
import { runDenoSubcommand } from "./_deno.ts";
10+
11+
/**
12+
* Run the check command
13+
*
14+
* @param args - Command-line arguments
15+
* @param cwd - Current working directory
16+
* @returns Exit code
17+
*/
18+
export async function checkCommand(
19+
args: string[],
20+
cwd: string,
21+
): Promise<number> {
22+
return await runDenoSubcommand("check", args, cwd, {
23+
usageAsset: "usage-check.txt",
24+
});
25+
}

src/commands/fmt.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Format command for Probitas CLI
3+
*
4+
* Runs `deno fmt --no-config` on discovered scenario files.
5+
*
6+
* @module
7+
*/
8+
9+
import { runDenoSubcommand } from "./_deno.ts";
10+
11+
/**
12+
* Run the fmt command
13+
*
14+
* @param args - Command-line arguments
15+
* @param cwd - Current working directory
16+
* @returns Exit code
17+
*/
18+
export async function fmtCommand(
19+
args: string[],
20+
cwd: string,
21+
): Promise<number> {
22+
return await runDenoSubcommand("fmt", args, cwd, {
23+
usageAsset: "usage-fmt.txt",
24+
});
25+
}

src/commands/lint.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Lint command for Probitas CLI
3+
*
4+
* Runs `deno lint --no-config` on discovered scenario files.
5+
* Automatically excludes rules that conflict with scenario imports.
6+
*
7+
* @module
8+
*/
9+
10+
import { runDenoSubcommand } from "./_deno.ts";
11+
12+
/**
13+
* Run the lint command
14+
*
15+
* @param args - Command-line arguments
16+
* @param cwd - Current working directory
17+
* @returns Exit code
18+
*/
19+
export async function lintCommand(
20+
args: string[],
21+
cwd: string,
22+
): Promise<number> {
23+
return await runDenoSubcommand("lint", args, cwd, {
24+
usageAsset: "usage-lint.txt",
25+
extraArgs: ["--rules-exclude=no-import-prefix,no-unversioned-import"],
26+
});
27+
}

src/commands/mod.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
* @module
55
*/
66

7+
export { checkCommand } from "./check.ts";
8+
export { fmtCommand } from "./fmt.ts";
79
export { initCommand } from "./init.ts";
10+
export { lintCommand } from "./lint.ts";
811
export { listCommand } from "./list.ts";
912
export { runCommand } from "./run.ts";

src/main.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
import { parseArgs } from "@std/cli";
88
import { getLogger } from "@probitas/logger";
99
import { EXIT_CODE } from "./constants.ts";
10+
import { checkCommand } from "./commands/check.ts";
11+
import { fmtCommand } from "./commands/fmt.ts";
1012
import { initCommand } from "./commands/init.ts";
13+
import { lintCommand } from "./commands/lint.ts";
1114
import { listCommand } from "./commands/list.ts";
1215
import { runCommand } from "./commands/run.ts";
1316
import { getVersionInfo, readAsset } from "./utils.ts";
@@ -78,6 +81,15 @@ export async function main(args: string[]): Promise<number> {
7881
case "list":
7982
return await listCommand(commandArgs, cwd);
8083

84+
case "fmt":
85+
return await fmtCommand(commandArgs, cwd);
86+
87+
case "lint":
88+
return await lintCommand(commandArgs, cwd);
89+
90+
case "check":
91+
return await checkCommand(commandArgs, cwd);
92+
8193
default:
8294
console.warn(`Unknown command: ${command}`);
8395
console.warn("Run 'probitas --help' for usage information");

0 commit comments

Comments
 (0)