@pokujs/c8 0.1.1 → 1.0.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.
package/README.md CHANGED
@@ -1,19 +1,169 @@
1
- ## @pokujs/c8
1
+ <div align="center">
2
+ <img height="180" alt="Poku's Logo" src="https://raw.githubusercontent.com/wellwelwel/poku/main/.github/assets/readme/poku.svg">
2
3
 
3
- ☔️ Facilitator utility for coverage with [**c8**](https://github.com/bcoe/c8) using [**Poku**](https://github.com/wellwelwel/poku).
4
+ # @pokujs/c8
5
+
6
+ Enjoying **Poku**? [Give him a star to show your support](https://github.com/wellwelwel/poku) ⭐
7
+
8
+ </div>
9
+
10
+ ---
11
+
12
+ 📚 [**Documentation**](https://poku.io/docs/documentation/helpers/coverage/c8)
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ ☔️ [**@pokujs/c8**](https://github.com/pokujs/c8) is a **Poku** plugin for **V8** code coverage using [**c8**](https://github.com/bcoe/c8).
19
+
20
+ ---
21
+
22
+ ## Quickstart
23
+
24
+ ### Install
25
+
26
+ ```bash
27
+ npm i -D @pokujs/c8
28
+ ```
29
+
30
+ ### Enable the Plugin
31
+
32
+ ```js
33
+ // poku.config.js
34
+ import { coverage } from '@pokujs/c8';
35
+ import { defineConfig } from 'poku';
36
+
37
+ export default defineConfig({
38
+ plugins: [coverage()],
39
+ });
40
+ ```
41
+
42
+ That's it! Run `poku` and a coverage summary will be printed after your test results.
4
43
 
5
44
  > [!IMPORTANT]
6
45
  >
7
- > WIP 🚧
46
+ > This plugin relies on **Node.js**' built-in `NODE_V8_COVERAGE` environment variable to collect coverage data. **Bun** and **Deno** do not support this mechanism, so coverage data will not be collected when running tests with these runtimes.
47
+
48
+ ---
49
+
50
+ ## Options
51
+
52
+ ```js
53
+ coverage({
54
+ // Reporters
55
+ reporter: ['text', 'lcov'], // default: ['text']
56
+
57
+ // File selection
58
+ include: ['src/**'], // default: [] (all files)
59
+ exclude: ['**/*.test.ts'], // default: c8 defaults
60
+ extension: ['.ts', '.js'], // default: c8 defaults
61
+
62
+ // Thresholds
63
+ checkCoverage: true, // default: false
64
+ lines: 80, // default: 0
65
+ branches: 80, // default: 0
66
+ functions: 80, // default: 0
67
+ statements: 80, // default: 0
68
+ perFile: false, // default: false
69
+
70
+ // Include untested files
71
+ all: true, // default: false
72
+ src: ['src'], // default: [cwd]
73
+
74
+ // Experimental
75
+ experimental: ['monocart'], // default: []
76
+
77
+ // Output
78
+ reportsDirectory: './coverage', // default: './coverage'
79
+ skipFull: false, // default: false
8
80
 
9
- ### Installation
81
+ // Advanced
82
+ excludeAfterRemap: false, // default: false
83
+ mergeAsync: false, // default: false
84
+ clean: true, // default: true
85
+ });
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Examples
91
+
92
+ ### Basic text coverage
10
93
 
11
- ```sh
12
- npm i -D poku @pokujs/c8
94
+ ```js
95
+ coverage({
96
+ include: ['src/**'],
97
+ });
13
98
  ```
14
99
 
15
- ### Usage
100
+ ### Generate HTML and LCOV reports
16
101
 
17
- ```sh
18
- npx poku --coverage=c8
102
+ ```js
103
+ coverage({
104
+ include: ['src/**'],
105
+ reporter: ['text', 'html', 'lcov'],
106
+ });
19
107
  ```
108
+
109
+ ### Enforce coverage thresholds
110
+
111
+ Set a single threshold for all metrics at once by passing a `number`:
112
+
113
+ ```js
114
+ coverage({
115
+ include: ['src/**'],
116
+ checkCoverage: 100,
117
+ });
118
+ ```
119
+
120
+ Or use `true` to set individual thresholds for each metric:
121
+
122
+ ```js
123
+ coverage({
124
+ include: ['src/**'],
125
+ checkCoverage: true,
126
+ lines: 95,
127
+ branches: 90,
128
+ functions: 85,
129
+ statements: 95,
130
+ });
131
+ ```
132
+
133
+ ### TypeScript coverage
134
+
135
+ ```js
136
+ coverage({
137
+ include: ['src/**'],
138
+ extension: ['.ts'],
139
+ all: true,
140
+ });
141
+ ```
142
+
143
+ ### Extending Monocart reporters
144
+
145
+ ```bash
146
+ npm i -D monocart-coverage-reports
147
+ ```
148
+
149
+ ```js
150
+ coverage({
151
+ include: ['src/**'],
152
+ reporter: ['v8', 'console-details', 'codecov'],
153
+ experimental: ['monocart'],
154
+ });
155
+ ```
156
+
157
+ ---
158
+
159
+ ## How It Works
160
+
161
+ - **`setup`** creates a temp directory and sets `NODE_V8_COVERAGE` — every test process spawned by **Poku** automatically writes **V8** coverage data
162
+ - **`teardown`** uses **c8** to generate reports from the collected data, optionally checks thresholds, then cleans up
163
+ - No modification to test commands or runner configuration needed
164
+
165
+ ---
166
+
167
+ ## License
168
+
169
+ **MIT** © [**wellwelwel**](https://github.com/wellwelwel) and [**contributors**](https://github.com/pokujs/c8/graphs/contributors).
package/lib/index.d.ts CHANGED
@@ -1 +1,4 @@
1
- export declare const wip: () => void;
1
+ import type { PokuPlugin } from 'poku/plugins';
2
+ import type { CoverageOptions } from './types.js';
3
+ export type { CoverageOptions } from './types.js';
4
+ export declare const coverage: (options?: CoverageOptions) => PokuPlugin;
package/lib/index.js CHANGED
@@ -1,5 +1,99 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.wip = void 0;
4
- const wip = () => { };
5
- exports.wip = wip;
6
+ exports.coverage = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = require("node:path");
10
+ const node_process_1 = __importDefault(require("node:process"));
11
+ const coverage = (options = Object.create(null)) => {
12
+ let tempDir;
13
+ let originalEnv;
14
+ let userProvidedTempDir;
15
+ return {
16
+ name: '@pokujs/c8',
17
+ setup(context) {
18
+ if (context.runtime !== 'node')
19
+ console.warn(`[@pokujs/c8] V8 coverage is only supported on Node.js (current runtime: ${context.runtime}). Coverage data may not be collected.`);
20
+ originalEnv = node_process_1.default.env.NODE_V8_COVERAGE;
21
+ userProvidedTempDir = typeof options.tempDirectory === 'string';
22
+ tempDir = userProvidedTempDir
23
+ ? options.tempDirectory
24
+ : (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'poku-c8-'));
25
+ node_process_1.default.env.NODE_V8_COVERAGE = tempDir;
26
+ },
27
+ async teardown(context) {
28
+ if (originalEnv !== undefined)
29
+ node_process_1.default.env.NODE_V8_COVERAGE = originalEnv;
30
+ else
31
+ delete node_process_1.default.env.NODE_V8_COVERAGE;
32
+ const reporter = Array.isArray(options.reporter)
33
+ ? options.reporter
34
+ : [options.reporter ?? 'text'];
35
+ const reportsDirectory = (0, node_path_1.resolve)(context.cwd, options.reportsDirectory ?? './coverage');
36
+ const { default: Report } = await import('c8/lib/report.js');
37
+ const useMonocart = options.experimental?.includes('monocart') ?? false;
38
+ const monocartArgv = useMonocart
39
+ ? {
40
+ reporter,
41
+ reportsDir: reportsDirectory,
42
+ tempDirectory: tempDir,
43
+ all: options.all ?? false,
44
+ src: options.src,
45
+ skipFull: options.skipFull ?? false,
46
+ excludeAfterRemap: options.excludeAfterRemap ?? false,
47
+ clean: options.clean !== false,
48
+ }
49
+ : undefined;
50
+ const report = Report({
51
+ tempDirectory: tempDir,
52
+ reportsDirectory,
53
+ reporter,
54
+ include: options.include ?? [],
55
+ exclude: options.exclude,
56
+ extension: options.extension,
57
+ all: options.all ?? false,
58
+ src: options.src,
59
+ resolve: '',
60
+ omitRelative: true,
61
+ excludeNodeModules: true,
62
+ skipFull: options.skipFull ?? false,
63
+ excludeAfterRemap: options.excludeAfterRemap ?? false,
64
+ watermarks: options.watermarks,
65
+ mergeAsync: options.mergeAsync ?? false,
66
+ monocartArgv,
67
+ });
68
+ await report.run();
69
+ if (options.checkCoverage) {
70
+ const { checkCoverages } = await import('c8/lib/commands/check-coverage.js');
71
+ const threshold = typeof options.checkCoverage === 'number'
72
+ ? options.checkCoverage
73
+ : undefined;
74
+ await checkCoverages({
75
+ lines: threshold ?? options.lines ?? 0,
76
+ branches: threshold ?? options.branches ?? 0,
77
+ functions: threshold ?? options.functions ?? 0,
78
+ statements: threshold ?? options.statements ?? 0,
79
+ perFile: options.perFile ?? false,
80
+ }, report);
81
+ if (node_process_1.default.exitCode === 1) {
82
+ const coverageFailure = () => {
83
+ node_process_1.default.exitCode = 1;
84
+ };
85
+ node_process_1.default.once('exit', coverageFailure);
86
+ }
87
+ }
88
+ if (!userProvidedTempDir) {
89
+ try {
90
+ (0, node_fs_1.rmSync)(tempDir, { recursive: true, force: true });
91
+ }
92
+ catch {
93
+ // Best-effort cleanup
94
+ }
95
+ }
96
+ },
97
+ };
98
+ };
99
+ exports.coverage = coverage;
package/lib/types.d.ts ADDED
@@ -0,0 +1,68 @@
1
+ type KnownReporter = 'clover' | 'cobertura' | 'codecov' | 'console-details' | 'html' | 'html-spa' | 'json' | 'json-summary' | 'lcov' | 'lcovonly' | 'none' | 'teamcity' | 'text' | 'text-lcov' | 'text-summary' | 'v8';
2
+ type Reporter = KnownReporter | (string & NonNullable<unknown>);
3
+ type KnownExtension = '.cjs' | '.cts' | '.js' | '.jsx' | '.mjs' | '.mts' | '.ts' | '.tsx';
4
+ type Extension = KnownExtension | (string & NonNullable<unknown>);
5
+ export type CoverageOptions = {
6
+ /** Coverage reporters to use. */
7
+ reporter?: Reporter | Reporter[];
8
+ /** Directory where coverage reports are written. */
9
+ reportsDirectory?: string;
10
+ /**
11
+ * Directory where V8 writes raw coverage JSON files.
12
+ *
13
+ * When provided, the directory is **not** auto-cleaned after report generation.
14
+ */
15
+ tempDirectory?: string;
16
+ /** Glob patterns for source files to include (empty = all). */
17
+ include?: string[];
18
+ /** Glob patterns for source files to exclude. */
19
+ exclude?: string[];
20
+ /** File extensions to consider for coverage. */
21
+ extension?: Extension[];
22
+ /**
23
+ * Include files that were never loaded by any test (reported as 0% coverage).
24
+ *
25
+ * Use `src` to control which directories are scanned.
26
+ */
27
+ all?: boolean;
28
+ /** Directories to scan when `all` is `true`. */
29
+ src?: string[];
30
+ /** Delete previous coverage data before running. */
31
+ clean?: boolean;
32
+ /**
33
+ * Enforce coverage thresholds.
34
+ *
35
+ * - `true` — check using individual `lines`, `branches`, `functions`, and `statements` values.
36
+ * - `number` — set all thresholds to that value (e.g., `100` is equivalent to `--100` in c8 CLI).
37
+ *
38
+ * When a threshold is not met, `process.exitCode` is set to `1`.
39
+ */
40
+ checkCoverage?: boolean | number;
41
+ /** Check thresholds per file instead of globally. */
42
+ perFile?: boolean;
43
+ /** Minimum line coverage percentage. */
44
+ lines?: number;
45
+ /** Minimum branch coverage percentage. */
46
+ branches?: number;
47
+ /** Minimum function coverage percentage. */
48
+ functions?: number;
49
+ /** Minimum statement coverage percentage. */
50
+ statements?: number;
51
+ /** Skip files with 100% coverage in the text report. */
52
+ skipFull?: boolean;
53
+ /** Apply exclude rules after source-map remapping. */
54
+ excludeAfterRemap?: boolean;
55
+ /** Custom watermark thresholds for report coloring. */
56
+ watermarks?: Record<string, [number, number]>;
57
+ /** Use async incremental merge (useful for large test suites). */
58
+ mergeAsync?: boolean;
59
+ /**
60
+ * Enable experimental features.
61
+ *
62
+ * - `'monocart'` — Use monocart-coverage-reports instead of the default
63
+ * Istanbul pipeline. Requires `monocart-coverage-reports` to be installed
64
+ * separately.
65
+ */
66
+ experimental?: 'monocart'[];
67
+ };
68
+ export {};
package/lib/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@pokujs/c8",
3
3
  "private": false,
4
- "version": "0.1.1",
5
- "description": "☔️ Facilitator utility for coverage with c8 using Poku.",
4
+ "version": "1.0.1",
5
+ "description": "☔️ A Poku plugin for V8 code coverage using c8.",
6
6
  "main": "./lib/index.js",
7
7
  "license": "MIT",
8
8
  "repository": {
@@ -16,34 +16,44 @@
16
16
  "author": "https://github.com/wellwelwel",
17
17
  "funding": {
18
18
  "type": "github",
19
- "url": "https://github.com/sponsors/wellwelwel"
19
+ "url": "https://github.com/pokujs/c8?sponsor=1"
20
20
  },
21
21
  "files": [
22
22
  "lib"
23
23
  ],
24
24
  "engines": {
25
- "node": ">=14.x.x"
25
+ "node": ">=18.x.x"
26
26
  },
27
27
  "scripts": {
28
- "test": "poku",
28
+ "test": "poku test/e2e",
29
+ "prebuild": "rm -rf lib",
29
30
  "build": "tsc",
30
- "lint": "biome lint --error-on-warnings && prettier --check .",
31
- "lint:fix": "biome lint --write && prettier --write .github/workflows/*.yml .",
31
+ "lint": "prettier --check .",
32
+ "lint:fix": "prettier --write .github/workflows/*.yml .",
32
33
  "update": "pu minor && npm i && (npm audit fix || true)",
33
34
  "postupdate": "npm run lint:fix"
34
35
  },
35
36
  "dependencies": {
36
37
  "c8": "^10.1.3"
37
38
  },
39
+ "peerDependencies": {
40
+ "monocart-coverage-reports": "^2.12.9",
41
+ "poku": "^4.1.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "monocart-coverage-reports": {
45
+ "optional": true
46
+ }
47
+ },
38
48
  "devDependencies": {
39
- "@biomejs/biome": "1.9.4",
40
- "@ianvs/prettier-plugin-sort-imports": "^4.4.2",
41
- "@types/node": "^22.15.30",
49
+ "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
50
+ "@types/node": "^25.5.0",
51
+ "monocart-coverage-reports": "^2.12.9",
42
52
  "packages-update": "^2.0.0",
43
- "poku": "^3.0.2",
44
- "prettier": "^3.5.3",
45
- "tsx": "4.19.4",
46
- "typescript": "^5.8.3"
53
+ "poku": "^4.1.0",
54
+ "prettier": "^3.8.1",
55
+ "tsx": "^4.21.0",
56
+ "typescript": "^6.0.2"
47
57
  },
48
58
  "publishConfig": {
49
59
  "access": "public"
@@ -52,7 +62,13 @@
52
62
  "🐷",
53
63
  "poku",
54
64
  "pokujs",
65
+ "testing",
66
+ "plugin",
55
67
  "coverage",
56
- "c8"
68
+ "c8",
69
+ "v8",
70
+ "istanbul",
71
+ "monocart",
72
+ "codecov"
57
73
  ]
58
74
  }