Skip to content

Commit

Permalink
chore: migrate CLI execution to execa
Browse files Browse the repository at this point in the history
  • Loading branch information
FRSgit committed Jan 5, 2025
1 parent 9243c63 commit 3657d49
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 61 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,17 +227,17 @@ const result = sync({
### input as glob pattern [40 files]

| Rank | Library | Average latency [ms] | Difference percentage (comparing to best average latency) |
| --- | --- | --- | --- |
| 1 | @frsource/frs-replace (async) | 0.63 ± 2.61% | +0.00% |
| 2 | @frsource/frs-replace (sync) | 0.69 ± 0.84% | +9.48% |
| 3 | replace-in-file (async) | 0.80 ± 1.14% | +28.41% |
| 4 | replace-in-file (async) | 0.88 ± 1.49% | +40.16% |
| Rank | Library | Average latency [ms] | Difference percentage (comparing to best average latency) |
| ---- | ----------------------------- | -------------------- | ----------------------------------------------------------------------------- |
| 1 | @frsource/frs-replace (async) | 0.63 ± 1.11% | +0.00% |
| 2 | @frsource/frs-replace (sync) | 0.72 ± 0.76% | +14.38% |
| 3 | replace-in-file (async) | 0.85 ± 0.74% | +33.88% |
| 4 | replace-in-file (async) | 0.92 ± 1.36% | +44.73% |

### input & replacement as strings

| Rank | Library | Average latency [ms] | Difference percentage (comparing to best average latency) |
| --- | --- | --- | --- |
| 1 | @frsource/frs-replace (sync) | 0.00 ± 0.31% | +0.00% |
| 2 | @frsource/frs-replace (async) | 0.01 ± 0.38% | +13.63% |
| 3 | replaceString | 0.03 ± 0.73% | +560.57% |
| Rank | Library | Average latency [ms] | Difference percentage (comparing to best average latency) |
| ---- | ----------------------------- | -------------------- | ----------------------------------------------------------------------------- |
| 1 | @frsource/frs-replace (sync) | 0.01 ± 0.33% | +0.00% |
| 2 | @frsource/frs-replace (async) | 0.01 ± 0.32% | +12.15% |
| 3 | replaceString | 0.03 ± 0.72% | +517.31% |
103 changes: 54 additions & 49 deletions bin/cli.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import childProcess from 'child_process';
import fs from 'fs';
import tmp from 'tmp-promise';
import glob from 'fast-glob';
import path from 'path';
import { SyncOptions, execaSync } from 'execa';
import {
afterAll,
afterEach,
Expand All @@ -19,7 +19,7 @@ const tmpPrefixes = {
};
const defaultOptions = {
timeout: 2000,
encoding: 'utf-8',
reject: false,
} as const;
const content = `aąbcćdeęfg%hi
jklmn
Expand Down Expand Up @@ -62,7 +62,7 @@ afterEach(() => {

test('no arguments', () => {
const result = runCli();
expect(result.status, 'process should send error status (1)').toEqual(1);
expect(result.exitCode, 'process should send error status (1)').toEqual(1);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(
result.parsedError,
Expand All @@ -71,8 +71,8 @@ test('no arguments', () => {
});

test('one argument', () => {
const result = runCli('sth');
expect(result.status, 'process should send error status (1)').toEqual(1);
const result = runCli(['sth']);
expect(result.exitCode, 'process should send error status (1)').toEqual(1);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(
result.parsedError,
Expand All @@ -82,7 +82,7 @@ test('one argument', () => {

test('two arguments', () => {
const result = runCli(['sth', 'sth']);
expect(result.status, 'process should send error status (1)').toEqual(1);
expect(result.exitCode, 'process should send error status (1)').toEqual(1);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(result.parsedError).toEqual('Missing required argument: i');
});
Expand All @@ -93,7 +93,7 @@ describe('content argument', () => {
['-c', '--content'],
content,
(result) => {
expect(result.status, 'process should send success status (0)').toEqual(
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(
Expand All @@ -107,7 +107,7 @@ describe('content argument', () => {

test('no stdout argument', () => {
const result = runCli([needle, replacement, '--content', content]);
expect(result.status, 'process should send success status (0)').toEqual(0);
expect(result.exitCode, 'process should send success status (0)').toEqual(0);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(result.parsedError, 'stderr should be empty').toEqual('');
});
Expand All @@ -120,7 +120,7 @@ test('stdout argument', () => {
content,
'--stdout',
]);
expect(result.status, 'process should send success status (0)').toEqual(0);
expect(result.exitCode, 'process should send success status (0)').toEqual(0);
expect(result.parsedOutput, 'stdout should contain replaced string').toEqual(
expectedOutput,
);
Expand Down Expand Up @@ -174,9 +174,10 @@ describe('input argument', async () => {
['-i', '--input'],
() => input!.path,
(result) => {
expect(result.status, 'process should send success status (0)').toEqual(
0,
);
expect(
result.exitCode,
'process should send success status (0)',
).toEqual(0);
expect(
result.parsedOutput,
'stdout should contain replaced string',
Expand All @@ -203,9 +204,10 @@ describe('input argument', async () => {
['-i', '--input'],
() => [input!.path, input2!.path],
(result) => {
expect(result.status, 'process should send success status (0)').toEqual(
0,
);
expect(
result.exitCode,
'process should send success status (0)',
).toEqual(0);
expect(
result.parsedOutput,
'stdout should contain replaced string',
Expand Down Expand Up @@ -253,9 +255,10 @@ describe('input argument', async () => {
['-i', '--input'],
() => [input!.path, input2!.path],
(result) => {
expect(result.status, 'process should send success status (0)').toEqual(
0,
);
expect(
result.exitCode,
'process should send success status (0)',
).toEqual(0);
expect(
result.parsedOutput,
'stdout should contain replaced string',
Expand Down Expand Up @@ -294,9 +297,10 @@ describe('input argument', async () => {
['-i', '--input'],
`${dir}/${tmpPrefixes.input}*`,
(result) => {
expect(result.status, 'process should send success status (0)').toEqual(
0,
);
expect(
result.exitCode,
'process should send success status (0)',
).toEqual(0);
expect(
result.parsedOutput,
'stdout should contain replaced string',
Expand Down Expand Up @@ -341,7 +345,7 @@ describe('i-read-opts argument', async () => {
{ input: content },
);

expect(result.status, 'process should send error status (1)').toEqual(1);
expect(result.exitCode, 'process should send error status (1)').toEqual(1);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(
result.parsedError,
Expand All @@ -360,7 +364,7 @@ describe('i-read-opts argument', async () => {
'--stdout',
]);

expect(result.status, 'process should send error status (1)').toEqual(1);
expect(result.exitCode, 'process should send error status (1)').toEqual(1);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');

if (process.version.includes('v16')) {
Expand Down Expand Up @@ -398,7 +402,9 @@ describe('i-read-opts argument', async () => {
'--stdout',
]);

expect(result.status, 'process should send success status (0)').toEqual(0);
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(
result.parsedOutput,
'stdout should contain replaced string',
Expand Down Expand Up @@ -458,7 +464,7 @@ describe('i-glob-opts argument', async () => {
{ input: content },
);

expect(result.status, 'process should send error status (1)').toEqual(1);
expect(result.exitCode, 'process should send error status (1)').toEqual(1);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(
result.parsedError,
Expand All @@ -477,7 +483,9 @@ describe('i-glob-opts argument', async () => {
'--stdout',
]);

expect(result.status, 'process should send success status (0)').toEqual(0);
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(result.parsedError, 'stderr should be empty').toEqual('');
});
Expand Down Expand Up @@ -535,7 +543,9 @@ describe('o-join-str argument', () => {
'--stdout',
]);

expect(result.status, 'process should send success status (0)').toEqual(0);
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(
result.parsedOutput,
'stdout should contain replaced string',
Expand All @@ -551,7 +561,7 @@ describe('output argument', async () => {
['-o', '--output'],
outputPath,
(result) => {
expect(result.status, 'process should send success status (0)').toEqual(
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
Expand Down Expand Up @@ -580,15 +590,15 @@ describe('input options argument', async () => {
{ input: content },
);

expect(result.status, 'process should send error status (1)').toEqual(1);
expect(result.exitCode, 'process should send error status (1)').toEqual(1);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(
result.parsedError,
'stderr contain error about missing i-read-opts dependency: i argument',
).toEqual('Missing required argument: i');
});

test('correct with input argument', () => {
test('correct with output argument', () => {
const result = runCli(
[
needle,
Expand All @@ -602,9 +612,9 @@ describe('input options argument', async () => {
{ input: content },
);

console.log('zxczxc', result);

expect(result.status, 'process should send success status (0)').toEqual(0);
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(result.parsedOutput, 'stdout should be empty').toEqual('');
expect(result.parsedError, 'stderr should be empty').toEqual('');

Expand All @@ -623,7 +633,7 @@ describe('stdin && output argument', () => {
['-o', '--output'],
outputPath,
(result) => {
expect(result.status, 'process should send success status (0)').toEqual(
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(
Expand Down Expand Up @@ -653,7 +663,7 @@ describe('flags argument', async () => {
['-f', '--flags'],
flags,
(result) => {
expect(result.status, 'process should send success status (0)').toEqual(
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(
Expand Down Expand Up @@ -702,7 +712,9 @@ describe('replace-fn argument', async () => {
});

checkEachArgCombination(args, ['-r', '--replace-fn'], undefined, (result) => {
expect(result.status, 'process should send success status (0)').toEqual(0);
expect(result.exitCode, 'process should send success status (0)').toEqual(
0,
);
expect(
result.parsedOutput,
'stdout should contain replaced string',
Expand All @@ -719,7 +731,7 @@ describe('replace-fn argument', async () => {
test('stdin stream as input argument (like piped stream)', async () => {
const result = runCli([needle, replacement, '--stdout'], { input: content });

expect(result.status, 'process should send success status (0)').toEqual(0);
expect(result.exitCode, 'process should send success status (0)').toEqual(0);
expect(result.parsedOutput, 'stdout should contain replaced string').toEqual(
expectedOutput,
);
Expand All @@ -745,21 +757,14 @@ function checkEachArgCombination(
}
}

function runCli(
_args?: string | string[],
_options?: Omit<childProcess.SpawnSyncOptionsWithStringEncoding, 'encoding'>,
) {
_options = Object.assign({}, defaultOptions, _options);
const result = childProcess.spawnSync(
'node',
['./bin/cli.mjs'].concat(_args || []),
_options,
);
function runCli(args: string[] = [], options?: SyncOptions) {
const _options = Object.assign({}, defaultOptions, options);
const result = execaSync(_options)`node ${['./bin/cli.mjs', ...args]}`;

return {
...result,
parsedOutput: result.stdout.toString().trim(),
parsedOutput: result.stdout?.toString().trim() || '',
parsedError:
result.stderr.toString().trim().split('\n').pop()?.trim() ?? '',
result.stderr?.toString().trim().split('\n').pop()?.trim() ?? '',
};
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"release:ci": "pnpm release --yes",
"test": "vitest",
"coverage": "vitest --coverage",
"test:ci": "vitest run --coverage && vitest bench --run && TEST_TYPE=bench vitest run",
"test:ci": "vitest bench --run && vitest run --coverage && TEST_TYPE=bench vitest run",
"eslint": "eslint .",
"prettier": "prettier . --check",
"lint": "pnpm eslint && pnpm prettier",
Expand All @@ -74,6 +74,7 @@
"@vitest/coverage-v8": "1.6.0",
"@vitest/ui": "1.6.0",
"eslint": "^9.2.0",
"execa": "^9.5.2",
"globals": "^15.14.0",
"globals-vitest": "^1.6.0",
"microbundle": "^0.15.1",
Expand Down
Loading

0 comments on commit 3657d49

Please sign in to comment.