Skip to content

Commit 818fd7e

Browse files
authored
Merge pull request #1 from hyperweb-io/dev/test-watch
add test command with nodemon support
2 parents 157a029 + 0b16f94 commit 818fd7e

File tree

5 files changed

+2757
-4984
lines changed

5 files changed

+2757
-4984
lines changed

packages/makage/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ Or with recursive patterns:
9292
"copy:all-sql": "makage copy src/**/*.sql dist/sql --flat"
9393
```
9494

95+
### Watching Tests
96+
97+
**Before:**
98+
```json
99+
"test:watch": "nodemon --watch deploy --watch revert --ext sql --exec 'jest'"
100+
```
101+
102+
**After:**
103+
```json
104+
"test:watch": "makage test --watch deploy,revert --ext sql"
105+
```
106+
95107
> **Note:** For convenience, `makage assets` combines copy + footer functionality and is kept for backwards compatibility.
96108
97109
## Assumptions
@@ -242,6 +254,41 @@ Run from the monorepo root:
242254
makage update-workspace
243255
```
244256

257+
makage update-workspace
258+
```
259+
260+
### `makage test [--runner <cmd>] [--watch <dirs>] [--ext <exts>] [-- <args...>]`
261+
262+
Runs tests using a specified runner (defaults to `jest`). Automatically switches to `nodemon` if watch directories or extensions are specified.
263+
264+
- Use `--runner` to specify a custom test runner (e.g., `vitest`, `node --test`)
265+
- Use `--watch` to enable watch mode. If followed by directories (comma-separated), it uses `nodemon` to watch those directories.
266+
- Use `--ext` to specify file extensions to watch (comma-separated). Implies `nodemon`.
267+
- Use `--` to pass additional arguments to the runner.
268+
269+
```bash
270+
# Default (runs jest)
271+
makage test
272+
273+
# Watch mode (runs jest --watch)
274+
makage test --watch
275+
276+
# Custom runner
277+
makage test --runner vitest
278+
279+
# Watch specific directories (uses nodemon)
280+
makage test --watch dir1,dir2
281+
282+
# Watch specific extensions (uses nodemon)
283+
makage test --ext js,sql,ts
284+
285+
# Complex example: Watch dirs and extensions, run custom command
286+
# Runs: nodemon --watch dir1 --watch dir2 --ext sql,js --exec "vitest --runInBand"
287+
makage test --watch dir1,dir2 --ext sql,js --runner vitest -- --runInBand
288+
```
289+
290+
### `makage update-workspace`
291+
245292
This will:
246293
1. Scan all packages in the `packages/` directory
247294
2. Identify internal package names

packages/makage/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,8 @@
3939
"lint": "eslint . --fix",
4040
"test": "jest",
4141
"test:watch": "jest --watch"
42+
},
43+
"dependencies": {
44+
"nodemon": "^3.1.11"
4245
}
4346
}

packages/makage/src/cli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { runAssets } from './commands/assets';
66
import { runBuild } from './commands/build';
77
import { runBuildTs } from './commands/buildTs';
88
import { runUpdateWorkspace } from './commands/updateWorkspace';
9+
import { runTest } from './commands/testCommand';
910

1011
const [, , cmd, ...rest] = process.argv;
1112

@@ -33,6 +34,9 @@ async function main() {
3334
case 'update-workspace':
3435
await runUpdateWorkspace(rest);
3536
break;
37+
case 'test':
38+
await runTest(rest);
39+
break;
3640
case '-h':
3741
case '--help':
3842
default:
@@ -57,6 +61,7 @@ Usage:
5761
makage assets
5862
makage build-ts [--dev]
5963
makage update-workspace
64+
makage test [--runner <cmd>] [--watch] [-- <args...>]
6065
`);
6166
}
6267

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { spawn } from 'node:child_process';
2+
3+
interface TestOptions {
4+
runner: string;
5+
watchMode: boolean;
6+
watchDirs: string[];
7+
extensions: string[];
8+
passThrough: string[];
9+
}
10+
11+
export async function runTest(args: string[]) {
12+
const opts: TestOptions = {
13+
runner: 'jest',
14+
watchMode: false,
15+
watchDirs: [],
16+
extensions: [],
17+
passThrough: []
18+
};
19+
20+
// Parse args
21+
for (let i = 0; i < args.length; i++) {
22+
const arg = args[i];
23+
24+
if (arg === '--runner') {
25+
if (i + 1 < args.length) {
26+
opts.runner = args[i + 1];
27+
i++;
28+
}
29+
} else if (arg === '--watch') {
30+
// Check if next arg is a value (not starting with -)
31+
const nextArg = args[i + 1];
32+
if (nextArg && !nextArg.startsWith('-')) {
33+
opts.watchDirs.push(...nextArg.split(','));
34+
i++;
35+
} else {
36+
opts.watchMode = true;
37+
}
38+
} else if (arg === '--ext') {
39+
const nextArg = args[i + 1];
40+
if (nextArg && !nextArg.startsWith('-')) {
41+
opts.extensions.push(...nextArg.split(','));
42+
i++;
43+
}
44+
} else if (arg === '--') {
45+
opts.passThrough = args.slice(i + 1);
46+
break;
47+
} else if (arg.startsWith('-')) {
48+
// Unknown flag, ignore or assume it's part of pass-through if we wanted to support mixed args,
49+
// but for now we stick to strict parsing and assume user puts runner args after --
50+
}
51+
}
52+
53+
// Determine mode
54+
const useNodemon = opts.watchDirs.length > 0 || opts.extensions.length > 0;
55+
56+
let command: string;
57+
let commandArgs: string[];
58+
59+
if (useNodemon) {
60+
// Nodemon mode
61+
command = 'nodemon';
62+
commandArgs = [];
63+
64+
// Add watch dirs
65+
for (const dir of opts.watchDirs) {
66+
commandArgs.push('--watch', dir);
67+
}
68+
69+
// Add extensions
70+
for (const ext of opts.extensions) {
71+
commandArgs.push('--ext', ext);
72+
}
73+
74+
// Add exec command
75+
// We need to combine runner and passThrough into a single string for --exec
76+
const runnerCmd = [opts.runner, ...opts.passThrough].join(' ');
77+
commandArgs.push('--exec', runnerCmd);
78+
79+
} else {
80+
// Standard mode
81+
const runnerParts = opts.runner.split(' ');
82+
command = runnerParts[0];
83+
commandArgs = runnerParts.slice(1);
84+
85+
if (opts.watchMode) {
86+
commandArgs.push('--watch');
87+
}
88+
89+
commandArgs.push(...opts.passThrough);
90+
}
91+
92+
console.log(`[makage] running tests with: ${command} ${commandArgs.join(' ')}`);
93+
94+
const child = spawn(command, commandArgs, {
95+
stdio: 'inherit',
96+
shell: true
97+
});
98+
99+
return new Promise<void>((resolve, reject) => {
100+
child.on('close', (code) => {
101+
if (code === 0) {
102+
resolve();
103+
} else {
104+
process.exit(code ?? 1);
105+
}
106+
});
107+
child.on('error', (err) => {
108+
console.error(`[makage] failed to start runner: ${err.message}`);
109+
process.exit(1);
110+
});
111+
});
112+
}

0 commit comments

Comments
 (0)