type-a-bin 0.1.0 → 0.1.1

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.
Files changed (3) hide show
  1. package/README.md +67 -36
  2. package/dist/mock-bin.js +1 -2
  3. package/package.json +37 -29
package/README.md CHANGED
@@ -57,6 +57,7 @@ fully typed, dependency-free library with richer features.
57
57
  - [Packages](#packages)
58
58
  - [Prerequisites](#prerequisites)
59
59
  - [Scripts](#scripts)
60
+ - [Releasing](#releasing)
60
61
  - [How it works under the hood](#how-it-works-under-the-hood)
61
62
  - [Windows support](#windows-support)
62
63
  - [Comparison with other tools](#comparison-with-other-tools)
@@ -74,12 +75,12 @@ slow, fragile, and impossible to reproduce deterministically.
74
75
 
75
76
  There are a few common workarounds, each with drawbacks:
76
77
 
77
- | Approach | Problem |
78
- |-----------------------|----------------------------------------------------------|
79
- | Stub `child_process` | Couples tests to the module boundary; misses edge cases. |
80
- | `nock` / HTTP mocking | Only works for HTTP, not arbitrary binaries. |
81
- | Real binaries in CI | Slow, requires secrets, produces flaky tests. |
82
- | **Type-A-Bin** | Mocks *any* binary at the `PATH` level — transparently. |
78
+ | Approach | Problem |
79
+ |----|----|
80
+ | Stub `child_process` | Couples tests to the module boundary; misses edge cases. |
81
+ | `nock` / HTTP mocking | Only works for HTTP, not arbitrary binaries. |
82
+ | Real binaries in CI | Slow, requires secrets, produces flaky tests. |
83
+ | **Type-A-Bin** | Mocks *any* binary at the `PATH` level — transparently. |
83
84
 
84
85
  Type-A-Bin works by creating a temporary executable with the same name
85
86
  as the target binary and prepending its directory to `PATH`. When your
@@ -462,10 +463,10 @@ The function is overloaded with three signatures:
462
463
  mockBin(binNameOrConfig, output): Promise<MockBinCleanup>
463
464
  ```
464
465
 
465
- | Parameter | Type | Description |
466
- |-------------------|---------------------------|-----------------------------------------------------|
466
+ | Parameter | Type | Description |
467
+ |----|----|----|
467
468
  | `binNameOrConfig` | `string \| MockBinConfig` | Binary name, or a config with `binName` + `pattern` |
468
- | `output` | `string` | The text the mock echoes (via `bash`) |
469
+ | `output` | `string` | The text the mock echoes (via `bash`) |
469
470
 
470
471
  Mocks the binary so that every invocation prints `output`. The fastest
471
472
  way to stub a command that just needs to return a string.
@@ -476,11 +477,11 @@ way to stub a command that just needs to return a string.
476
477
  mockBin(binNameOrConfig, shebang, code): Promise<MockBinCleanup>
477
478
  ```
478
479
 
479
- | Parameter | Type | Description |
480
- |-------------------|---------------------------|-----------------------------------------------------|
480
+ | Parameter | Type | Description |
481
+ |----|----|----|
481
482
  | `binNameOrConfig` | `string \| MockBinConfig` | Binary name, or a config with `binName` + `pattern` |
482
- | `shebang` | `string` | Interpreter (e.g. `"bash"`, `"node"`) |
483
- | `code` | `string` | The script body that runs when the mock is invoked |
483
+ | `shebang` | `string` | Interpreter (e.g. `"bash"`, `"node"`) |
484
+ | `code` | `string` | The script body that runs when the mock is invoked |
484
485
 
485
486
  Gives full control. The `shebang` accepts a bare interpreter name
486
487
  (wrapped in `#!/usr/bin/env …` automatically) or a full shebang line.
@@ -491,11 +492,11 @@ Gives full control. The `shebang` accepts a bare interpreter name
491
492
  mockBin(binNameOrConfig, shebang, script): Promise<MockBinCleanup>
492
493
  ```
493
494
 
494
- | Parameter | Type | Description |
495
- |-------------------|---------------------------|-----------------------------------------------------|
495
+ | Parameter | Type | Description |
496
+ |----|----|----|
496
497
  | `binNameOrConfig` | `string \| MockBinConfig` | Binary name, or a config with `binName` + `pattern` |
497
- | `shebang` | `string` | Interpreter used to run the file |
498
- | `script` | `MockBinScriptFile` | `{ file: string }` pointing at a script on disk |
498
+ | `shebang` | `string` | Interpreter used to run the file |
499
+ | `script` | `MockBinScriptFile` | `{ file: string }` pointing at a script on disk |
499
500
 
500
501
  Runs a script file through the given interpreter, keeping the file’s
501
502
  original extension so extension-aware loaders (e.g. `node --import tsx`)
@@ -539,7 +540,7 @@ library lives at the root; additional packages live under `packages/`:
539
540
 
540
541
  - [Node.js](https://nodejs.org) 26 and [pnpm](https://pnpm.io) (enforced
541
542
  via `engines` in `package.json`)
542
- - [pandoc](https://pandoc.org) ≥ 3.1 — only needed for Markdown
543
+ - [pandoc](https://pandoc.org) ≥ 3.10 — only needed for Markdown
543
544
  formatting/linting (`pnpm lint:md` / `pnpm format:md`), not for using
544
545
  the library
545
546
  - On Windows: [Git for Windows](https://gitforwindows.org/) — its bash
@@ -550,13 +551,43 @@ library lives at the root; additional packages live under `packages/`:
550
551
 
551
552
  Run from the repository root:
552
553
 
553
- | Script | Description |
554
- |-------------------|-------------------------------------------------------|
555
- | `pnpm build` | Build the library (and workspace packages) to `dist/` |
556
- | `pnpm test` | Build, run unit tests, then run workspace tests |
557
- | `pnpm lint` | Run all linters (Biome, oxlint, ast-grep, pandoc) |
558
- | `pnpm format` | Run all formatters with auto-fix |
559
- | `pnpm test:watch` | Run unit tests in watch mode |
554
+ | Script | Description |
555
+ |----|----|
556
+ | `pnpm build` | Build the library (and workspace packages) to `dist/` |
557
+ | `pnpm test` | Build, run unit tests, then run workspace tests |
558
+ | `pnpm lint` | Run all linters (Biome, oxlint, ast-grep, pandoc, audit, jscpd) |
559
+ | `pnpm format` | Run all formatters with auto-fix |
560
+ | `pnpm test:watch` | Run unit tests in watch mode |
561
+
562
+ ## Releasing
563
+
564
+ Releases are published to npm by the manually triggered [Release
565
+ workflow](https://github.com/SynthLuvr/type-a-bin/actions/workflows/release.yml)
566
+ using OIDC trusted publishing — no npm token is stored in the
567
+ repository.
568
+
569
+ One-time setup on npm (required before the workflow can publish): on
570
+ npmjs.com, open the package **type-a-bin → Settings → Trusted
571
+ publishing** and add a GitHub Actions publisher with repository owner
572
+ `SynthLuvr`, repository `type-a-bin`, workflow filename `release.yml`,
573
+ an *empty* environment, and the `npm publish` action allowed.
574
+
575
+ To cut a release, run the workflow from `main` with a semver `bump` or
576
+ an exact `version`. It builds, tests, publishes to npm with provenance,
577
+ then commits the version bump, pushes the `vX.Y.Z` tag, and opens the
578
+ GitHub release. (Version `0.1.0` was published manually to claim the
579
+ package name; every later version goes through the workflow.)
580
+
581
+ If publishing fails, the workflow annotates the run with the fix. Both
582
+ known registry rejections are auth or provenance problems, not problems
583
+ with the package itself:
584
+
585
+ - `E404 Not Found - PUT https://registry.npmjs.org/type-a-bin` — npm
586
+ masks a rejected OIDC exchange as a 404: the trusted-publisher entry
587
+ is missing or does not match the exact values above.
588
+ - `E422` — provenance requires `package.json` to carry `repository.url`
589
+ matching the GitHub repository
590
+ (`https://github.com/SynthLuvr/type-a-bin`).
560
591
 
561
592
  ## How it works under the hood
562
593
 
@@ -648,17 +679,17 @@ any process that is not a mock shim.
648
679
 
649
680
  ## Comparison with other tools
650
681
 
651
- | Feature | Type-A-Bin | [mock-bin](https://github.com/stevemao/mock-bin) | [mock-a-bin](https://github.com/levibostian/mock-a-bin) |
652
- |------------------------------------|:----------:|:------------------------------------------------:|:-------------------------------------------------------:|
653
- | Mocks any binary via `PATH` | | | |
654
- | Runtime dependencies | 0 | several | several (Deno) |
655
- | TypeScript types & overloads | | | partial |
656
- | Output shorthand | | | |
657
- | Script-file mode (keeps extension) | | | |
658
- | Pattern-based conditional mocking | | | |
659
- | `run-original` pass-through | | | |
660
- | Cleanup function | | | |
661
- | Runtime | Node.js | Node.js | Deno |
682
+ | Feature | Type-A-Bin | [mock-bin](https://github.com/stevemao/mock-bin) | [mock-a-bin](https://github.com/levibostian/mock-a-bin) |
683
+ |----|:--:|:--:|:--:|
684
+ | Mocks any binary via `PATH` | | | |
685
+ | Runtime dependencies | 0 | several | several (Deno) |
686
+ | TypeScript types & overloads | | | partial |
687
+ | Output shorthand | | | |
688
+ | Script-file mode (keeps extension) | | | |
689
+ | Pattern-based conditional mocking | | | |
690
+ | `run-original` pass-through | | | |
691
+ | Cleanup function | | | |
692
+ | Runtime | Node.js | Node.js | Deno |
662
693
 
663
694
  ## Contributing
664
695
 
package/dist/mock-bin.js CHANGED
@@ -36,9 +36,8 @@ const toShebangLine = (interpreter) => interpreter.startsWith("#!") ? interprete
36
36
  const resolveScriptFile = async (shebang, { file }) => {
37
37
  const resolvedFile = path.resolve(file);
38
38
  const stats = await stat(resolvedFile).catch(() => null);
39
- if (!stats?.isFile()) {
39
+ if (!stats?.isFile())
40
40
  throw new Error(`mockBin: script file not found: ${file}`);
41
- }
42
41
  // Accept either a bare interpreter ("node --import tsx") or a full
43
42
  // shebang line ("#!/usr/bin/env node"); strip "#!" for the exec line.
44
43
  const interpreter = shebang.startsWith("#!")
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "type-a-bin",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Mock any executable binary for testing in Node.js",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/SynthLuvr/type-a-bin"
9
+ },
6
10
  "type": "module",
7
11
  "main": "./dist/index.js",
8
12
  "types": "./dist/index.d.ts",
@@ -15,43 +19,47 @@
15
19
  "files": [
16
20
  "dist"
17
21
  ],
22
+ "packageManager": "pnpm@11.24.0",
18
23
  "engines": {
19
24
  "node": "==26"
20
25
  },
21
- "devDependencies": {
22
- "@ast-grep/cli": "^0.44.1",
23
- "@ast-grep/cli-linux-x64-gnu": "^0.44.1",
24
- "@biomejs/biome": "^2.5.4",
25
- "@types/node": "^26.1.1",
26
- "convert-to-arrow": "^1.1.4",
27
- "del-cli": "^7.0.0",
28
- "npm-run-all2": "^9.0.2",
29
- "oxlint": "^1.74.0",
30
- "oxlint-tsgolint": "^0.25.0",
31
- "tsx": "^4.23.1",
32
- "typescript": "^7.0.2",
33
- "vitest": "^4.1.10"
34
- },
35
26
  "scripts": {
36
- "build:lib": "pnpm del-cli dist && pnpm tsc && pnpm del-cli dist/tests",
27
+ "build:lib": "del-cli dist && tsc && del-cli dist/tests",
37
28
  "build": "pnpm build:lib && pnpm -r build",
38
- "format:arrows": "pnpm convert-to-arrow \"{src,packages/*/src}/**/*.{ts,tsx}\"",
39
- "format:biome": "pnpm biome format --write .",
40
- "format:braces": "pnpm strip-braces .",
41
- "format:check": "pnpm biome check --write .",
29
+ "format:arrows": "convert-to-arrow \"{src,packages/*/src}/**/*.{ts,tsx}\"",
30
+ "format:biome": "biome format --write .",
31
+ "format:braces": "ast-grep scan --rule .ast-grep/rules/strip-braces.yml -U .",
32
+ "format:check": "biome check --write .",
42
33
  "format": "npm-run-all format:arrows format:braces format:biome format:check format:md",
43
- "lint:biome": "pnpm biome check .",
44
- "lint:oxlint": "pnpm oxlint .",
45
- "lint": "npm-run-all lint:biome lint:oxlint lint:exports lint:functions lint:file-comment lint:md lint:peer-deps",
46
- "strip-braces": "pnpm exec ast-grep scan --rule .ast-grep/rules/strip-braces.yml -U",
47
- "lint:exports": "pnpm exec ast-grep scan --rule .ast-grep/rules/no-inline-export.yml --error=no-inline-export --globs '!**/*.d.ts' .",
48
- "lint:functions": "pnpm exec ast-grep scan --rule .ast-grep/rules/no-function-declaration.yml --error=no-function-declaration --globs '!**/*.d.ts' .",
49
- "lint:file-comment": "pnpm exec ast-grep scan --rule .ast-grep/rules/no-file-comment.yml --error=no-file-comment --globs '!**/*.d.ts' .",
34
+ "lint:biome": "biome check .",
35
+ "lint:oxlint": "tsx scripts/oxlint.mts --deny-warnings .",
36
+ "lint": "npm-run-all lint:biome lint:oxlint lint:exports lint:functions lint:file-comment lint:md lint:peer-deps lint:audit lint:duplicates",
37
+ "lint:exports": "ast-grep scan --rule .ast-grep/rules/no-inline-export.yml --error=no-inline-export --globs '!**/*.d.ts' .",
38
+ "lint:functions": "ast-grep scan --rule .ast-grep/rules/no-function-declaration.yml --error=no-function-declaration --globs '!**/*.d.ts' .",
39
+ "lint:file-comment": "ast-grep scan --rule .ast-grep/rules/no-file-comment.yml --error=no-file-comment --globs '!**/*.d.ts' .",
50
40
  "lint:md": "tsx scripts/pandoc-md.mts --check",
41
+ "lint:audit": "pnpm audit --prod",
42
+ "lint:duplicates": "jscpd src --format typescript --min-lines 3 --threshold 5",
51
43
  "lint:peer-deps": "tsx scripts/peer-deps.mts",
52
44
  "format:md": "tsx scripts/pandoc-md.mts --write",
53
- "test:lib": "vitest run",
45
+ "test:lib": "vitest run --coverage",
54
46
  "test": "pnpm build:lib && pnpm test:lib && pnpm -r test",
55
47
  "test:watch": "vitest"
48
+ },
49
+ "devDependencies": {
50
+ "@ast-grep/cli": "^0.45.2",
51
+ "@ast-grep/cli-linux-x64-gnu": "^0.45.2",
52
+ "@biomejs/biome": "^2.5.10",
53
+ "@types/node": "^26.3.0",
54
+ "@vitest/coverage-v8": "^4.1.11",
55
+ "convert-to-arrow": "^1.1.4",
56
+ "del-cli": "^7.0.0",
57
+ "jscpd": "^5.0.16",
58
+ "npm-run-all2": "^9.0.3",
59
+ "oxlint": "^1.80.0",
60
+ "oxlint-tsgolint": "^7.0.2001",
61
+ "tsx": "^4.23.12",
62
+ "typescript": "^7.0.2",
63
+ "vitest": "^4.1.11"
56
64
  }
57
- }
65
+ }