bintastic 3.0.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.
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # bintastic
2
+
3
+ ![CI Build](https://github.com/scalvert/bintastic/workflows/CI%20Build/badge.svg)
4
+ [![npm version](https://badge.fury.io/js/bintastic.svg)](https://badge.fury.io/js/bintastic)
5
+ [![License](https://img.shields.io/npm/l/bintastic.svg)](https://github.com/scalvert/bintastic/blob/master/package.json)
6
+ ![Dependabot](https://badgen.net/badge/icon/dependabot?icon=dependabot&label)
7
+ [![Code Style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](#badge)
8
+
9
+ > **Note:** This package was formerly published as `@scalvert/bin-tester`.
10
+
11
+ A test harness for Node.js CLI tools.
12
+
13
+ Testing a CLI isn't like testing a library—you can't just import functions and call them. You need to spawn your CLI as a subprocess, give it real files to work with, and capture its output. bintastic simplifies this:
14
+
15
+ ```ts snippet=basic-example.ts
16
+ import { createBintastic } from 'bintastic';
17
+
18
+ describe('my-cli', () => {
19
+ const { setupProject, teardownProject, runBin } = createBintastic({
20
+ binPath: './bin/my-cli.js',
21
+ });
22
+
23
+ let project;
24
+
25
+ beforeEach(async () => {
26
+ project = await setupProject();
27
+ });
28
+
29
+ afterEach(() => {
30
+ teardownProject();
31
+ });
32
+
33
+ test('processes files', async () => {
34
+ project.files = { 'input.txt': 'hello' };
35
+ await project.write();
36
+
37
+ const result = await runBin('input.txt');
38
+
39
+ expect(result.exitCode).toBe(0);
40
+ expect(result.stdout).toContain('processed');
41
+ });
42
+ });
43
+ ```
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ npm add bintastic --save-dev
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ `createBintastic` returns helpers for setting up projects, running your CLI, and cleaning up:
54
+
55
+ ```ts snippet=create-bintastic.ts
56
+ const { setupProject, teardownProject, runBin } = createBintastic({
57
+ binPath: './bin/my-cli.js',
58
+ staticArgs: ['--verbose'], // args passed to every invocation
59
+ });
60
+ ```
61
+
62
+ **Setup and teardown:**
63
+
64
+ ```ts snippet=setup-teardown.ts
65
+ const project = await setupProject(); // creates temp directory
66
+ // ... run tests ...
67
+ teardownProject(); // removes temp directory
68
+ ```
69
+
70
+ **Writing fixture files:**
71
+
72
+ ```ts snippet=writing-fixtures.ts
73
+ project.files = {
74
+ 'src/index.js': 'export default 42;',
75
+ 'package.json': JSON.stringify({ name: 'test' }),
76
+ };
77
+ await project.write();
78
+ ```
79
+
80
+ **Running your CLI:**
81
+
82
+ ```ts snippet=running-cli.ts
83
+ const result = await runBin('--flag', 'arg');
84
+
85
+ result.exitCode; // number
86
+ result.stdout; // string
87
+ result.stderr; // string
88
+ ```
89
+
90
+ ## Debugging
91
+
92
+ Set `BINTASTIC_DEBUG` to enable the Node inspector and preserve fixtures for inspection:
93
+
94
+ ```bash
95
+ BINTASTIC_DEBUG=attach npm test # attach debugger
96
+ BINTASTIC_DEBUG=break npm test # break on first line
97
+ ```
98
+
99
+ Or use `runBinDebug()` programmatically:
100
+
101
+ ```ts snippet=run-bin-debug.ts
102
+ await runBinDebug('--flag'); // runs with --inspect
103
+ ```
104
+
105
+ For VS Code, add to `.vscode/launch.json`:
106
+
107
+ ```jsonc
108
+ {
109
+ "name": "Debug Tests",
110
+ "type": "node",
111
+ "request": "launch",
112
+ "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/vitest",
113
+ "runtimeArgs": ["run"],
114
+ "autoAttachChildProcesses": true,
115
+ "console": "integratedTerminal",
116
+ }
117
+ ```
118
+
119
+ ## API
120
+
121
+ See the [full API documentation](https://scalvert.github.io/bintastic/).
package/dist/index.cjs ADDED
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BintasticProject: () => BintasticProject,
24
+ createBintastic: () => createBintastic
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/create-bintastic.ts
29
+ var import_execa2 = require("execa");
30
+
31
+ // src/project.ts
32
+ var import_execa = require("execa");
33
+ var import_fixturify_project = require("fixturify-project");
34
+ var ROOT = process.cwd();
35
+ var BintasticProject = class extends import_fixturify_project.Project {
36
+ /**
37
+ * Constructs an instance of a BintasticProject.
38
+ * @param {string} name - The name of the project. Used within the package.json as the name property.
39
+ * @param {string} version - The version of the project. Used within the package.json as the version property.
40
+ * @param {Function} cb - An optional callback for additional setup steps after the project is constructed.
41
+ */
42
+ constructor(name = "fake-project", version, cb) {
43
+ super(name, version, cb);
44
+ this._dirChanged = false;
45
+ this.pkg = Object.assign({}, this.pkg, {
46
+ license: "MIT",
47
+ description: "Fake project",
48
+ repository: "http://fakerepo.com"
49
+ });
50
+ }
51
+ /**
52
+ * Runs `git init` inside a project.
53
+ * @returns {*} {ResultPromise}
54
+ */
55
+ gitInit() {
56
+ return (0, import_execa.execa)("git", ["init", "-q", this.baseDir]);
57
+ }
58
+ /**
59
+ * Writes the project files to disk.
60
+ */
61
+ async write() {
62
+ return super.write();
63
+ }
64
+ /**
65
+ * Changes a directory from inside the project.
66
+ */
67
+ async chdir() {
68
+ this._dirChanged = true;
69
+ await this.write();
70
+ process.chdir(this.baseDir);
71
+ }
72
+ /**
73
+ * Correctly disposes of the project, observing when the directory has been changed.
74
+ * @returns {void}
75
+ */
76
+ dispose() {
77
+ if (this._dirChanged) {
78
+ process.chdir(ROOT);
79
+ }
80
+ return super.dispose();
81
+ }
82
+ };
83
+
84
+ // src/create-bintastic.ts
85
+ var DEFAULT_BINTASTIC_OPTIONS = {
86
+ staticArgs: []
87
+ };
88
+ function parseArgs(args) {
89
+ if (args.length > 0 && typeof args[args.length - 1] === "object") {
90
+ const argsCopy = [...args];
91
+ const execaOptions = argsCopy.pop();
92
+ return {
93
+ args: argsCopy,
94
+ execaOptions
95
+ };
96
+ } else {
97
+ return {
98
+ args: [...args],
99
+ execaOptions: {}
100
+ };
101
+ }
102
+ }
103
+ function createBintastic(options) {
104
+ let project;
105
+ const mergedOptions = {
106
+ ...DEFAULT_BINTASTIC_OPTIONS,
107
+ ...options
108
+ };
109
+ function runBin(...args) {
110
+ const mergedRunOptions = parseArgs(args);
111
+ const binPath = typeof mergedOptions.binPath === "function" ? mergedOptions.binPath(project) : mergedOptions.binPath;
112
+ const optionsEnv = mergedRunOptions.execaOptions.env;
113
+ const debugEnv = optionsEnv?.BINTASTIC_DEBUG ?? process.env.BINTASTIC_DEBUG;
114
+ const nodeOptions = [];
115
+ if (debugEnv && debugEnv !== "0" && debugEnv.toLowerCase() !== "false") {
116
+ if (debugEnv.toLowerCase() === "break") {
117
+ nodeOptions.push("--inspect-brk=0");
118
+ } else {
119
+ nodeOptions.push("--inspect=0");
120
+ }
121
+ console.log(`[bintastic] Debugging enabled. Fixture: ${project.baseDir}`);
122
+ }
123
+ const resolvedCwd = mergedRunOptions.execaOptions.cwd ?? project.baseDir;
124
+ return (0, import_execa2.execaNode)(binPath, [...mergedOptions.staticArgs, ...mergedRunOptions.args], {
125
+ reject: false,
126
+ cwd: resolvedCwd,
127
+ nodeOptions,
128
+ ...mergedRunOptions.execaOptions
129
+ });
130
+ }
131
+ function runBinDebug(...args) {
132
+ const parsedArgs = parseArgs(args);
133
+ const debugEnv = process.env.BINTASTIC_DEBUG || "attach";
134
+ parsedArgs.execaOptions = {
135
+ ...parsedArgs.execaOptions,
136
+ env: {
137
+ ...parsedArgs.execaOptions.env,
138
+ BINTASTIC_DEBUG: debugEnv
139
+ }
140
+ };
141
+ const reconstructedArgs = [...parsedArgs.args, parsedArgs.execaOptions];
142
+ return runBin(...reconstructedArgs);
143
+ }
144
+ async function setupProject() {
145
+ project = "createProject" in mergedOptions ? await mergedOptions.createProject() : new BintasticProject();
146
+ await project.write();
147
+ return project;
148
+ }
149
+ async function setupTmpDir() {
150
+ if (typeof project === "undefined") {
151
+ await setupProject();
152
+ }
153
+ return project.baseDir;
154
+ }
155
+ function teardownProject() {
156
+ const debugEnv = process.env.BINTASTIC_DEBUG;
157
+ if (debugEnv && debugEnv !== "0" && debugEnv.toLowerCase() !== "false") {
158
+ console.log(`[bintastic] Fixture preserved: ${project.baseDir}`);
159
+ return;
160
+ }
161
+ project.dispose();
162
+ }
163
+ return {
164
+ runBin,
165
+ runBinDebug,
166
+ setupProject,
167
+ teardownProject,
168
+ setupTmpDir
169
+ };
170
+ }
171
+ // Annotate the CommonJS export names for ESM import in node:
172
+ 0 && (module.exports = {
173
+ BintasticProject,
174
+ createBintastic
175
+ });
@@ -0,0 +1,112 @@
1
+ import { ResultPromise, Options } from 'execa';
2
+ import { Project } from 'fixturify-project';
3
+
4
+ declare class BintasticProject extends Project {
5
+ private _dirChanged;
6
+ /**
7
+ * Constructs an instance of a BintasticProject.
8
+ * @param {string} name - The name of the project. Used within the package.json as the name property.
9
+ * @param {string} version - The version of the project. Used within the package.json as the version property.
10
+ * @param {Function} cb - An optional callback for additional setup steps after the project is constructed.
11
+ */
12
+ constructor(name?: string, version?: string, cb?: (project: Project) => void);
13
+ /**
14
+ * Runs `git init` inside a project.
15
+ * @returns {*} {ResultPromise}
16
+ */
17
+ gitInit(): ResultPromise;
18
+ /**
19
+ * Writes the project files to disk.
20
+ */
21
+ write(): Promise<void>;
22
+ /**
23
+ * Changes a directory from inside the project.
24
+ */
25
+ chdir(): Promise<void>;
26
+ /**
27
+ * Correctly disposes of the project, observing when the directory has been changed.
28
+ * @returns {void}
29
+ */
30
+ dispose(): void;
31
+ }
32
+
33
+ /**
34
+ * Options for configuring bintastic.
35
+ */
36
+ interface BintasticOptions<TProject> {
37
+ /**
38
+ * The absolute path to the bin to invoke
39
+ */
40
+ binPath: string | (<TProject extends BintasticProject>(project: TProject) => string);
41
+ /**
42
+ * An array of static arguments that will be used every time when running the bin
43
+ */
44
+ staticArgs?: string[];
45
+ /**
46
+ * An optional function to use to create the project. Use this if you want to provide a custom implementation of a BintasticProject.
47
+ */
48
+ createProject?: () => Promise<TProject>;
49
+ }
50
+ /**
51
+ * Function signature for running the configured CLI binary.
52
+ */
53
+ interface RunBin {
54
+ /**
55
+ * A runBin implementation that takes no parameters.
56
+ * @returns {*} {ResultPromise}
57
+ */
58
+ (): ResultPromise;
59
+ /**
60
+ * A runBin implementation that takes string varargs.
61
+ * @param {...RunBinArgs} args
62
+ * @returns {*} {ResultPromise}
63
+ */
64
+ (...args: [...binArgs: string[]]): ResultPromise;
65
+ /**
66
+ * A runBin implementation that takes an Options object.
67
+ * @param {...RunBinArgs} args
68
+ * @returns {*} {ResultPromise}
69
+ */
70
+ (...args: [execaOptions: Options]): ResultPromise;
71
+ /**
72
+ * A runBin implementation that takes string or an Options object varargs.
73
+ * @param {...RunBinArgs} args
74
+ * @returns {*} {ResultPromise}
75
+ */
76
+ (...args: [...binArgs: string[], execaOptions: Options]): ResultPromise;
77
+ }
78
+ /**
79
+ * The result returned by createBintastic.
80
+ */
81
+ interface CreateBintasticResult<TProject extends BintasticProject> {
82
+ /**
83
+ * Runs the configured bin function via execa.
84
+ */
85
+ runBin: RunBin;
86
+ /**
87
+ * Sets up the specified project for use within tests.
88
+ */
89
+ setupProject: () => Promise<TProject>;
90
+ /**
91
+ * Sets up a tmp directory for use within tests.
92
+ */
93
+ setupTmpDir: () => Promise<string>;
94
+ /**
95
+ * Tears the project down, ensuring the tmp directory is removed.
96
+ * When BINTASTIC_DEBUG is set, fixtures are preserved for inspection.
97
+ */
98
+ teardownProject: () => void;
99
+ /**
100
+ * Runs the configured bin with Node inspector enabled in attach mode (--inspect).
101
+ * Set BINTASTIC_DEBUG=break to break on first line instead.
102
+ */
103
+ runBinDebug: RunBin;
104
+ }
105
+ /**
106
+ * Creates the bintastic API functions to use within tests.
107
+ * @param {BintasticOptions<TProject>} options - An object of bintastic options
108
+ * @returns {CreateBintasticResult<TProject>} - A project instance.
109
+ */
110
+ declare function createBintastic<TProject extends BintasticProject>(options: BintasticOptions<TProject>): CreateBintasticResult<TProject>;
111
+
112
+ export { type BintasticOptions, BintasticProject, type CreateBintasticResult, type RunBin, createBintastic };
@@ -0,0 +1,112 @@
1
+ import { ResultPromise, Options } from 'execa';
2
+ import { Project } from 'fixturify-project';
3
+
4
+ declare class BintasticProject extends Project {
5
+ private _dirChanged;
6
+ /**
7
+ * Constructs an instance of a BintasticProject.
8
+ * @param {string} name - The name of the project. Used within the package.json as the name property.
9
+ * @param {string} version - The version of the project. Used within the package.json as the version property.
10
+ * @param {Function} cb - An optional callback for additional setup steps after the project is constructed.
11
+ */
12
+ constructor(name?: string, version?: string, cb?: (project: Project) => void);
13
+ /**
14
+ * Runs `git init` inside a project.
15
+ * @returns {*} {ResultPromise}
16
+ */
17
+ gitInit(): ResultPromise;
18
+ /**
19
+ * Writes the project files to disk.
20
+ */
21
+ write(): Promise<void>;
22
+ /**
23
+ * Changes a directory from inside the project.
24
+ */
25
+ chdir(): Promise<void>;
26
+ /**
27
+ * Correctly disposes of the project, observing when the directory has been changed.
28
+ * @returns {void}
29
+ */
30
+ dispose(): void;
31
+ }
32
+
33
+ /**
34
+ * Options for configuring bintastic.
35
+ */
36
+ interface BintasticOptions<TProject> {
37
+ /**
38
+ * The absolute path to the bin to invoke
39
+ */
40
+ binPath: string | (<TProject extends BintasticProject>(project: TProject) => string);
41
+ /**
42
+ * An array of static arguments that will be used every time when running the bin
43
+ */
44
+ staticArgs?: string[];
45
+ /**
46
+ * An optional function to use to create the project. Use this if you want to provide a custom implementation of a BintasticProject.
47
+ */
48
+ createProject?: () => Promise<TProject>;
49
+ }
50
+ /**
51
+ * Function signature for running the configured CLI binary.
52
+ */
53
+ interface RunBin {
54
+ /**
55
+ * A runBin implementation that takes no parameters.
56
+ * @returns {*} {ResultPromise}
57
+ */
58
+ (): ResultPromise;
59
+ /**
60
+ * A runBin implementation that takes string varargs.
61
+ * @param {...RunBinArgs} args
62
+ * @returns {*} {ResultPromise}
63
+ */
64
+ (...args: [...binArgs: string[]]): ResultPromise;
65
+ /**
66
+ * A runBin implementation that takes an Options object.
67
+ * @param {...RunBinArgs} args
68
+ * @returns {*} {ResultPromise}
69
+ */
70
+ (...args: [execaOptions: Options]): ResultPromise;
71
+ /**
72
+ * A runBin implementation that takes string or an Options object varargs.
73
+ * @param {...RunBinArgs} args
74
+ * @returns {*} {ResultPromise}
75
+ */
76
+ (...args: [...binArgs: string[], execaOptions: Options]): ResultPromise;
77
+ }
78
+ /**
79
+ * The result returned by createBintastic.
80
+ */
81
+ interface CreateBintasticResult<TProject extends BintasticProject> {
82
+ /**
83
+ * Runs the configured bin function via execa.
84
+ */
85
+ runBin: RunBin;
86
+ /**
87
+ * Sets up the specified project for use within tests.
88
+ */
89
+ setupProject: () => Promise<TProject>;
90
+ /**
91
+ * Sets up a tmp directory for use within tests.
92
+ */
93
+ setupTmpDir: () => Promise<string>;
94
+ /**
95
+ * Tears the project down, ensuring the tmp directory is removed.
96
+ * When BINTASTIC_DEBUG is set, fixtures are preserved for inspection.
97
+ */
98
+ teardownProject: () => void;
99
+ /**
100
+ * Runs the configured bin with Node inspector enabled in attach mode (--inspect).
101
+ * Set BINTASTIC_DEBUG=break to break on first line instead.
102
+ */
103
+ runBinDebug: RunBin;
104
+ }
105
+ /**
106
+ * Creates the bintastic API functions to use within tests.
107
+ * @param {BintasticOptions<TProject>} options - An object of bintastic options
108
+ * @returns {CreateBintasticResult<TProject>} - A project instance.
109
+ */
110
+ declare function createBintastic<TProject extends BintasticProject>(options: BintasticOptions<TProject>): CreateBintasticResult<TProject>;
111
+
112
+ export { type BintasticOptions, BintasticProject, type CreateBintasticResult, type RunBin, createBintastic };
package/dist/index.js ADDED
@@ -0,0 +1,147 @@
1
+ // src/create-bintastic.ts
2
+ import { execaNode } from "execa";
3
+
4
+ // src/project.ts
5
+ import { execa } from "execa";
6
+ import { Project } from "fixturify-project";
7
+ var ROOT = process.cwd();
8
+ var BintasticProject = class extends Project {
9
+ /**
10
+ * Constructs an instance of a BintasticProject.
11
+ * @param {string} name - The name of the project. Used within the package.json as the name property.
12
+ * @param {string} version - The version of the project. Used within the package.json as the version property.
13
+ * @param {Function} cb - An optional callback for additional setup steps after the project is constructed.
14
+ */
15
+ constructor(name = "fake-project", version, cb) {
16
+ super(name, version, cb);
17
+ this._dirChanged = false;
18
+ this.pkg = Object.assign({}, this.pkg, {
19
+ license: "MIT",
20
+ description: "Fake project",
21
+ repository: "http://fakerepo.com"
22
+ });
23
+ }
24
+ /**
25
+ * Runs `git init` inside a project.
26
+ * @returns {*} {ResultPromise}
27
+ */
28
+ gitInit() {
29
+ return execa("git", ["init", "-q", this.baseDir]);
30
+ }
31
+ /**
32
+ * Writes the project files to disk.
33
+ */
34
+ async write() {
35
+ return super.write();
36
+ }
37
+ /**
38
+ * Changes a directory from inside the project.
39
+ */
40
+ async chdir() {
41
+ this._dirChanged = true;
42
+ await this.write();
43
+ process.chdir(this.baseDir);
44
+ }
45
+ /**
46
+ * Correctly disposes of the project, observing when the directory has been changed.
47
+ * @returns {void}
48
+ */
49
+ dispose() {
50
+ if (this._dirChanged) {
51
+ process.chdir(ROOT);
52
+ }
53
+ return super.dispose();
54
+ }
55
+ };
56
+
57
+ // src/create-bintastic.ts
58
+ var DEFAULT_BINTASTIC_OPTIONS = {
59
+ staticArgs: []
60
+ };
61
+ function parseArgs(args) {
62
+ if (args.length > 0 && typeof args[args.length - 1] === "object") {
63
+ const argsCopy = [...args];
64
+ const execaOptions = argsCopy.pop();
65
+ return {
66
+ args: argsCopy,
67
+ execaOptions
68
+ };
69
+ } else {
70
+ return {
71
+ args: [...args],
72
+ execaOptions: {}
73
+ };
74
+ }
75
+ }
76
+ function createBintastic(options) {
77
+ let project;
78
+ const mergedOptions = {
79
+ ...DEFAULT_BINTASTIC_OPTIONS,
80
+ ...options
81
+ };
82
+ function runBin(...args) {
83
+ const mergedRunOptions = parseArgs(args);
84
+ const binPath = typeof mergedOptions.binPath === "function" ? mergedOptions.binPath(project) : mergedOptions.binPath;
85
+ const optionsEnv = mergedRunOptions.execaOptions.env;
86
+ const debugEnv = optionsEnv?.BINTASTIC_DEBUG ?? process.env.BINTASTIC_DEBUG;
87
+ const nodeOptions = [];
88
+ if (debugEnv && debugEnv !== "0" && debugEnv.toLowerCase() !== "false") {
89
+ if (debugEnv.toLowerCase() === "break") {
90
+ nodeOptions.push("--inspect-brk=0");
91
+ } else {
92
+ nodeOptions.push("--inspect=0");
93
+ }
94
+ console.log(`[bintastic] Debugging enabled. Fixture: ${project.baseDir}`);
95
+ }
96
+ const resolvedCwd = mergedRunOptions.execaOptions.cwd ?? project.baseDir;
97
+ return execaNode(binPath, [...mergedOptions.staticArgs, ...mergedRunOptions.args], {
98
+ reject: false,
99
+ cwd: resolvedCwd,
100
+ nodeOptions,
101
+ ...mergedRunOptions.execaOptions
102
+ });
103
+ }
104
+ function runBinDebug(...args) {
105
+ const parsedArgs = parseArgs(args);
106
+ const debugEnv = process.env.BINTASTIC_DEBUG || "attach";
107
+ parsedArgs.execaOptions = {
108
+ ...parsedArgs.execaOptions,
109
+ env: {
110
+ ...parsedArgs.execaOptions.env,
111
+ BINTASTIC_DEBUG: debugEnv
112
+ }
113
+ };
114
+ const reconstructedArgs = [...parsedArgs.args, parsedArgs.execaOptions];
115
+ return runBin(...reconstructedArgs);
116
+ }
117
+ async function setupProject() {
118
+ project = "createProject" in mergedOptions ? await mergedOptions.createProject() : new BintasticProject();
119
+ await project.write();
120
+ return project;
121
+ }
122
+ async function setupTmpDir() {
123
+ if (typeof project === "undefined") {
124
+ await setupProject();
125
+ }
126
+ return project.baseDir;
127
+ }
128
+ function teardownProject() {
129
+ const debugEnv = process.env.BINTASTIC_DEBUG;
130
+ if (debugEnv && debugEnv !== "0" && debugEnv.toLowerCase() !== "false") {
131
+ console.log(`[bintastic] Fixture preserved: ${project.baseDir}`);
132
+ return;
133
+ }
134
+ project.dispose();
135
+ }
136
+ return {
137
+ runBin,
138
+ runBinDebug,
139
+ setupProject,
140
+ teardownProject,
141
+ setupTmpDir
142
+ };
143
+ }
144
+ export {
145
+ BintasticProject,
146
+ createBintastic
147
+ };
package/package.json ADDED
@@ -0,0 +1,102 @@
1
+ {
2
+ "name": "bintastic",
3
+ "version": "3.0.0",
4
+ "description": "A test harness for Node.js CLI tools",
5
+ "keywords": [
6
+ "cli",
7
+ "test",
8
+ "harness",
9
+ "binary",
10
+ "subprocess"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/scalvert/bintastic.git"
15
+ },
16
+ "homepage": "https://github.com/scalvert/bintastic#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/scalvert/bintastic/issues"
19
+ },
20
+ "license": "MIT",
21
+ "author": "Steve Calvert <steve.calvert@gmail.com>",
22
+ "type": "module",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js",
27
+ "require": "./dist/index.cjs"
28
+ }
29
+ },
30
+ "main": "./dist/index.cjs",
31
+ "module": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "scripts": {
34
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
35
+ "docs": "typedoc",
36
+ "docs:check": "markdown-code check",
37
+ "docs:sync": "markdown-code sync",
38
+ "format": "prettier --write .",
39
+ "format:check": "prettier --check .",
40
+ "lint": "eslint . && npm run format:check && npm run docs:check",
41
+ "prepublishOnly": "npm run build",
42
+ "test": "npm run lint && npm run test:vitest",
43
+ "test:vitest": "vitest run",
44
+ "test:watch": "vitest",
45
+ "watch": "npm run build -- --watch src"
46
+ },
47
+ "files": [
48
+ "dist"
49
+ ],
50
+ "dependencies": {
51
+ "execa": "^9.6.1",
52
+ "fixturify-project": "^7.1.3"
53
+ },
54
+ "devDependencies": {
55
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
56
+ "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
57
+ "@babel/plugin-transform-typescript": "^7.27.0",
58
+ "@babel/preset-env": "^7.26.9",
59
+ "@babel/preset-typescript": "^7.27.0",
60
+ "@release-it-plugins/lerna-changelog": "^8.0.1",
61
+ "@typescript-eslint/eslint-plugin": "^8.29.1",
62
+ "@typescript-eslint/parser": "^8.29.1",
63
+ "eslint": "^9.24.0",
64
+ "eslint-config-prettier": "^10.1.2",
65
+ "eslint-plugin-jsdoc": "^61.5.0",
66
+ "eslint-plugin-node": "^11.1.0",
67
+ "eslint-plugin-prettier": "^5.2.6",
68
+ "eslint-plugin-unicorn": "^62.0.0",
69
+ "fixturify": "^3.0.0",
70
+ "markdown-code": "^0.6.1",
71
+ "prettier": "^3.5.3",
72
+ "release-it": "^19.2.2",
73
+ "tsup": "^8.4.0",
74
+ "type-fest": "^5.3.1",
75
+ "typedoc": "^0.28.15",
76
+ "typescript": "^5.8.3",
77
+ "vite": "^7.3.0",
78
+ "vitest": "^4.0.16"
79
+ },
80
+ "engines": {
81
+ "node": ">=22"
82
+ },
83
+ "publishConfig": {
84
+ "registry": "https://registry.npmjs.org",
85
+ "access": "public"
86
+ },
87
+ "release-it": {
88
+ "plugins": {
89
+ "@release-it-plugins/lerna-changelog": {
90
+ "infile": "CHANGELOG.md",
91
+ "launchEditor": true
92
+ }
93
+ },
94
+ "git": {
95
+ "tagName": "v${version}"
96
+ },
97
+ "github": {
98
+ "release": true,
99
+ "tokenRef": "GITHUB_AUTH"
100
+ }
101
+ }
102
+ }