A Node.js utility for programmatically executing commands in your scripts, applications, or libraries. Unlike traditional shells, it's optimized for programmatic usage with TypeScript support.
npm install --save @hyperse/exec-program
- π Execute TypeScript files directly
- π» Run shell commands programmatically
- π TypeScript support out of the box
- β‘ Promise-based API
- βοΈ Configurable execution options
- π§ͺ Built-in support for unit testing
Executes a TypeScript file and returns its output.
/**
* Process execute typescript script file using `@hyperse/ts-node`
* @param program - The absolute typescript file path
* @param options - The configuration of `execa` { env: { HPS_TS_NODE_PROJECT: tsconfig } }
* @param args - The runtime argv for program
*/
declare const runTsScript: <T extends ExecOptions>(
program: string,
args?: readonly string[],
options?: T
) => ExecResultPromise<{} & T>;
Executes a shell command with specified arguments and options.
import { execute } from '@hyperse/exec-program';
/**
* Execute a file with arguments and options
* @param file - The program/script to execute, as a string or file URL
* @param args - Arguments to pass to `file` on execution.
* @param options - Options to pass to `execa`
* @returns A `ResultPromise` that is both:
*/
declare function execute<T extends ExecOptions>(
file: string,
args?: readonly string[],
options?: T
): ExecResultPromise<{} & T>;
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { runTsScript } from '@hyperse/exec-program';
const getDirname = (url: string, ...paths: string[]) => {
return join(dirname(fileURLToPath(url)), ...paths);
};
// Execute a TypeScript file
const cliPath = getDirname(import.meta.url, './cli-test.ts');
const { stderr, stdout } = await runTsScript(cliPath);
console.log(stderr, stdout);
import { execute } from '@hyperse/exec-program';
// Install npm packages
const { stdout, stderr } = await execute(
'npm',
['i', '--no-save', '--no-package-lock', ...packages],
{
cwd: targetDirectory,
maxBuffer: TEN_MEGA_BYTE,
env: npmEnv,
}
);
// Create npm package
await execute('npm', ['pack', directory], {
cwd: uniqueDir,
maxBuffer: TEN_MEGA_BYTE,
});
- Configure your
tsconfig.json
:
{
"extends": "@hyperse/eslint-config-hyperse/tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./src",
"rootDir": "./",
"outDir": "dist",
"types": ["vitest/globals"],
"paths": {
"@hyperse/exec-program": ["../src/index.js"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}
- Create a test file (
cli-test.ts
):
import { runTsScript } from '@hyperse/exec-program';
console.log(typeof runTsScript);
console.log('cli...');
- Write your test (
main.spec.ts
):
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { runTsScript } from '@hyperse/exec-program';
const getDirname = (url: string, ...paths: string[]) => {
return join(dirname(fileURLToPath(url)), ...paths);
};
const cliPath = getDirname(import.meta.url, './cli-test.ts');
describe('test suites of exec program', () => {
it('should correctly invoke cli.ts', async () => {
const { stderr, stdout } = await runTsScript(cliPath);
expect(stderr).toBe('');
expect(stdout).toMatch(/cli.../);
});
});
The library supports various configuration options for both runTsScript
and execute
functions. These options allow you to customize the execution environment, working directory, and other parameters.
For detailed configuration options, please refer to the TypeScript types in the source code.