fail-on-console 1.2.0 â 1.3.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/CHANGELOG.md +14 -0
- package/README.md +29 -10
- package/index.d.ts +28 -7
- package/index.js +114 -13
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.1](https://github.com/benquarmby/fail-on-console/compare/v1.3.0...v1.3.1) (2026-08-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* use correct rule type for allowStream declaration ([23fe420](https://github.com/benquarmby/fail-on-console/commit/23fe42050a7a46959ea6f2b68204a41e424bcacc))
|
|
9
|
+
|
|
10
|
+
## [1.3.0](https://github.com/benquarmby/fail-on-console/compare/v1.2.0...v1.3.0) (2026-08-01)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* support process.stdout and process.stderr monitoring ([a79f82f](https://github.com/benquarmby/fail-on-console/commit/a79f82fa6ea778d44e8a59654f89bdd66464ab76))
|
|
16
|
+
|
|
3
17
|
## [1.2.0](https://github.com/benquarmby/fail-on-console/compare/v1.1.2...v1.2.0) (2026-07-25)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -5,13 +5,14 @@ Fail Vitest or Jest tests when unexpected console logs, warnings or errors occur
|
|
|
5
5
|
[](https://www.npmjs.com/package/fail-on-console)
|
|
6
6
|
[](https://github.com/benquarmby/fail-on-console/blob/main/LICENSE)
|
|
7
7
|
|
|
8
|
-
The `fail-on-console` utility fails test suites whenever unexpected `console`
|
|
8
|
+
The `fail-on-console` utility fails test suites whenever unexpected `console` output or `process` writes are triggered, keeping test results clear and easy to read.
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
12
|
- **⥠Vitest and Jest Native**: Seamless integration with Vitest (including Browser Mode) and Jest using standard lifecycle hooks.
|
|
13
|
+
- **đĄ Raw Stream Monitoring:** Fails on unexpected writes to `process.stdout` or `process.stderr` on top of standard console calls. Output from libraries that write directly to the stream doesn't slip through.
|
|
13
14
|
- **đĒļ Zero Dependencies**: Pure, lightweight JavaScript with a tiny footprint.
|
|
14
|
-
- **đ¯ Configurable Targets**: Choose exactly which console methods
|
|
15
|
+
- **đ¯ Configurable Targets**: Choose exactly which console methods and / or process streams to monitor.
|
|
15
16
|
- **đ Flexible Allowlist**: Easily suppress expected console noise globally, per suite, or per test using strings, regular expressions, or custom predicates.
|
|
16
17
|
|
|
17
18
|
## Installation
|
|
@@ -53,39 +54,42 @@ import {setupConsole} from "fail-on-console";
|
|
|
53
54
|
setupConsole({beforeEach, afterEach});
|
|
54
55
|
```
|
|
55
56
|
|
|
56
|
-
### Customizing Monitored Methods
|
|
57
|
+
### Customizing Monitored Methods and Streams
|
|
57
58
|
|
|
58
|
-
By default, `debug` is not monitored but `error`, `warn`, `info`, and `log` are. This can be customized by passing a `methods` array:
|
|
59
|
+
By default, `console.debug` is not monitored but `error`, `warn`, `info`, and `log` are. This can be customized by passing a `methods` array. Similarly, `process.stdout` and `process.stderr` are not monitored by default, but can be configured with a `streams` array:
|
|
59
60
|
|
|
60
61
|
```ts
|
|
61
62
|
setupConsole({
|
|
62
63
|
beforeEach,
|
|
63
64
|
afterEach,
|
|
64
65
|
// Fail on console.error, console.warn, and console.debug.
|
|
65
|
-
methods: ["error", "warn", "debug"]
|
|
66
|
+
methods: ["error", "warn", "debug"],
|
|
67
|
+
// Fail when libraries like Bunyan write straight to process.stdout,
|
|
68
|
+
// bypassing console entirely.
|
|
69
|
+
streams: ["stdout", "stderr"]
|
|
66
70
|
});
|
|
67
71
|
```
|
|
68
72
|
|
|
69
73
|
## Suppressing Expected Logs
|
|
70
74
|
|
|
71
|
-
If a specific test or third-party dependency intentionally logs to the console, `allowConsole` can be used to allow the test to pass.
|
|
75
|
+
If a specific test or third-party dependency intentionally logs to the console, `allowConsole` and `allowStream` can be used to allow the test to pass.
|
|
72
76
|
|
|
73
|
-
|
|
77
|
+
These functions can be invoked globally, inside a `describe` block, or inside a specific `test`/`it` block.
|
|
74
78
|
|
|
75
79
|
```javascript
|
|
76
|
-
import {allowConsole} from "fail-on-console";
|
|
80
|
+
import {allowConsole, allowStream} from "fail-on-console";
|
|
77
81
|
|
|
78
82
|
// Allow a substring.
|
|
79
83
|
allowConsole("warn", "third-party library warning");
|
|
80
84
|
|
|
81
85
|
// Allow a Regular Expression.
|
|
82
|
-
|
|
86
|
+
allowStream("stderr", /^Warning: Each child in a list/);
|
|
83
87
|
|
|
84
88
|
// Allow with a custom predicate function
|
|
85
89
|
allowConsole("log", (message) => message.startsWith("[analytics]"));
|
|
86
90
|
|
|
87
91
|
// An array of mixed matchers
|
|
88
|
-
|
|
92
|
+
allowStream("stdout", ["known warning", /deprecated/, (msg) => msg.includes("third-party")]);
|
|
89
93
|
```
|
|
90
94
|
|
|
91
95
|
## API Reference
|
|
@@ -97,6 +101,7 @@ Initializes console spies that monitor active tests.
|
|
|
97
101
|
- `options.beforeEach`: The framework's `beforeEach` hook.
|
|
98
102
|
- `options.afterEach`: The framework's `afterEach` hook.
|
|
99
103
|
- `options.methods`: _(Optional)_ Array of `console` methods to track. Defaults to `["error", "warn", "info", "log"]`.
|
|
104
|
+
- `options.streams`: _(Optional)_ Array of `process` streams to track. Defaults to `[]` (no streams monitored).
|
|
100
105
|
|
|
101
106
|
### `allowConsole(method, rules)`
|
|
102
107
|
|
|
@@ -108,6 +113,16 @@ Registers a temporary or global allowlist rule for a monitored console method.
|
|
|
108
113
|
- `RegExp`: Allowed if the regex tests true against the message.
|
|
109
114
|
- `Function`: A predicate `(message: string) => boolean` returning `true` to allow the message.
|
|
110
115
|
|
|
116
|
+
### `allowStream(stream, rules)`
|
|
117
|
+
|
|
118
|
+
Registers a temporary or global allowlist rule for a monitored process stream.
|
|
119
|
+
|
|
120
|
+
- `stream`: `"stdout" | "stderr"`
|
|
121
|
+
- `rules`: A single rule or an array of rules. A rule can be:
|
|
122
|
+
- `string`: Allowed if the written message contains this substring.
|
|
123
|
+
- `RegExp`: Allowed if the regex tests true against the message.
|
|
124
|
+
- `Function`: A predicate `(message: string) => boolean` returning `true` to allow the message.
|
|
125
|
+
|
|
111
126
|
## Limitations
|
|
112
127
|
|
|
113
128
|
### Concurrency
|
|
@@ -122,6 +137,10 @@ Monitoring `console.assert` is currently unsupported. It has a distinct signatur
|
|
|
122
137
|
|
|
123
138
|
Mocha is unsupported due to API incompatibilities related to test context. There are no clean or reliable workarounds for integration.
|
|
124
139
|
|
|
140
|
+
### Browser Mode
|
|
141
|
+
|
|
142
|
+
`process.stdout` and `process.stderr` don't exist in a real browser environment, so the `streams` option has no effect under Vitest Browser Mode. `setupConsole` detects this and silently skips stream monitoring rather than throwing. `methods` monitoring is unaffected and works normally.
|
|
143
|
+
|
|
125
144
|
## Credits & Prior Art
|
|
126
145
|
|
|
127
146
|
This package is inspired by and builds on the excellent foundation laid by:
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type ConsoleMethod = "error" | "warn" | "info" | "log" | "debug";
|
|
2
|
+
export type ProcessStream = "stderr" | "stdout";
|
|
2
3
|
|
|
3
4
|
export interface ExpectStateLike {
|
|
4
5
|
currentTestName?: string;
|
|
@@ -23,6 +24,7 @@ export interface TestApi {
|
|
|
23
24
|
|
|
24
25
|
export interface SetupOptions extends TestApi {
|
|
25
26
|
methods?: ConsoleMethod[];
|
|
27
|
+
streams?: ProcessStream[];
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
export interface AllowPredicate {
|
|
@@ -46,6 +48,7 @@ export function setup(options: SetupOptions): void;
|
|
|
46
48
|
* @param {Function} options.beforeEach The beforeEach hook from the test framework.
|
|
47
49
|
* @param {Function} options.afterEach The afterEach hook from the test framework.
|
|
48
50
|
* @param {string[]} [options.methods=["error","warn","info","log"]] Console methods to monitor.
|
|
51
|
+
* @param {string[]} [options.streams=[]] Process streams to monitor. None by default.
|
|
49
52
|
* @example
|
|
50
53
|
* // Vitest
|
|
51
54
|
* import {beforeEach, afterEach} from "vitest";
|
|
@@ -65,14 +68,13 @@ export function setupConsole(options: SetupOptions): void;
|
|
|
65
68
|
* Allows specific console calls to pass. Console exceptions can be configured
|
|
66
69
|
* globally, within a describe block or inside a single test.
|
|
67
70
|
* @param {string} method The console method to allow: "error", "warn", "info",
|
|
68
|
-
* "log"
|
|
71
|
+
* "log" or "debug".
|
|
69
72
|
* @param {string|RegExp|Function|Array<string|RegExp|Function>} rules One or
|
|
70
|
-
* more
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* allow it.
|
|
73
|
+
* more rules. A message is allowed if any rule finds a match. A string matches
|
|
74
|
+
* when the message contains it. A RegExp matches when it tests true against
|
|
75
|
+
* the message. A function receives the message and returns true to allow it.
|
|
74
76
|
* @example
|
|
75
|
-
* //
|
|
77
|
+
* // String - allow any warn containing this substring
|
|
76
78
|
* allowConsole("warn", "third-party library warning");
|
|
77
79
|
* @example
|
|
78
80
|
* // RegExp - allow errors matching a pattern
|
|
@@ -81,7 +83,26 @@ export function setupConsole(options: SetupOptions): void;
|
|
|
81
83
|
* // Predicate - allow logs from a specific source
|
|
82
84
|
* allowConsole("log", (message) => message.startsWith("[analytics]"));
|
|
83
85
|
* @example
|
|
84
|
-
* // Mixed array - allow multiple
|
|
86
|
+
* // Mixed array - allow multiple rules at once
|
|
85
87
|
* allowConsole("error", ["known warning", /deprecated/, (m) => m.includes("third-party")]);
|
|
86
88
|
*/
|
|
87
89
|
export function allowConsole(method: ConsoleMethod, rules: AllowRule | AllowRule[]): void;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Allows specific writes to `process.stdout` or `process.stderr` to pass.
|
|
93
|
+
* Stream exceptions can be configured globally, within a describe block or
|
|
94
|
+
* inside a single test. No-op in environments where `globalThis.process` does
|
|
95
|
+
* not exist.
|
|
96
|
+
* @param {string} stream The target process stream to allow: "stdout" or "stderr".
|
|
97
|
+
* @param {string|RegExp|Function|Array<string|RegExp|Function>} rules One or
|
|
98
|
+
* more rules. A message is allowed if any rule finds a match. A string matches
|
|
99
|
+
* when the message contains it. A RegExp matches when it tests true against
|
|
100
|
+
* the message. A function receives the message and returns true to allow it.
|
|
101
|
+
* @example
|
|
102
|
+
* // String - allow standard output containing this substring
|
|
103
|
+
* allowStream("stdout", "unavoidable log message");]);
|
|
104
|
+
* @example
|
|
105
|
+
* // Mixed array - allow standard errors using multiple rules at once
|
|
106
|
+
* allowStream("stderr", ["known warning", /deprecated/, (m) => m.includes("third-party")]);
|
|
107
|
+
*/
|
|
108
|
+
export function allowStream(stream: ProcessStream, rules: AllowRule | AllowRule[]): void;
|
package/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const supportedMethods = ["error", "warn", "info", "log", "debug"];
|
|
2
|
+
const supportedStreams = ["stderr", "stdout"];
|
|
2
3
|
// Everything but console.debug is monitored by default. Debug logging in tests
|
|
3
4
|
// is usually intentional.
|
|
4
5
|
const defaultMethods = supportedMethods.slice(0, -1);
|
|
6
|
+
// No streams are monitored by default.
|
|
7
|
+
const defaultStreams = [];
|
|
5
8
|
// %s string, %d/%i integer, %o object, %f float
|
|
6
9
|
const printfPattern = /%[sdiof]/g;
|
|
7
10
|
|
|
@@ -9,32 +12,40 @@ const printfPattern = /%[sdiof]/g;
|
|
|
9
12
|
// Test frameworks run tests serially by default.
|
|
10
13
|
let testApi;
|
|
11
14
|
let isInsideTest = false;
|
|
12
|
-
const
|
|
15
|
+
const allowedMethods = new Map();
|
|
16
|
+
const allowedStreams = new Map();
|
|
13
17
|
|
|
14
18
|
function quoteString(value) {
|
|
15
19
|
return `"${value}"`;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
function
|
|
19
|
-
if (!Array.isArray(
|
|
20
|
-
throw new Error(
|
|
22
|
+
function assertSupportedValues(pluralName, supportedValues, values) {
|
|
23
|
+
if (!Array.isArray(values)) {
|
|
24
|
+
throw new Error(`fail-on-console: Expected an array of ${pluralName}.`);
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
const unsupported =
|
|
27
|
+
const unsupported = values.filter((value) => !supportedValues.includes(value));
|
|
24
28
|
|
|
25
29
|
if (!unsupported.length) {
|
|
26
30
|
return;
|
|
27
31
|
}
|
|
28
32
|
|
|
29
|
-
const method = unsupported.length === 1 ? "method" : "methods";
|
|
30
33
|
const invalidList = unsupported.map(quoteString).join(", ");
|
|
31
|
-
const validList =
|
|
34
|
+
const validList = supportedValues.map(quoteString).join(", ");
|
|
32
35
|
|
|
33
36
|
throw new Error(
|
|
34
|
-
`fail-on-console:
|
|
37
|
+
`fail-on-console: One or more unsupported ${pluralName} provided: ${invalidList}. Supported ${pluralName} are: ${validList}.`
|
|
35
38
|
);
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
function assertSupportedMethods(methods) {
|
|
42
|
+
return assertSupportedValues("console methods", supportedMethods, methods);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function assertSupportedStreams(streams) {
|
|
46
|
+
return assertSupportedValues("process streams", supportedStreams, streams);
|
|
47
|
+
}
|
|
48
|
+
|
|
38
49
|
/**
|
|
39
50
|
* Basic implementation of node:util/format for console message formatting.
|
|
40
51
|
* Covers only the most common uses. Does not handle all specifiers (such as
|
|
@@ -77,18 +88,36 @@ function isAllowed(message, rule) {
|
|
|
77
88
|
return rule.test(message);
|
|
78
89
|
}
|
|
79
90
|
|
|
80
|
-
function
|
|
91
|
+
function chunkToString(chunk, encoding = "utf8") {
|
|
92
|
+
if (typeof chunk === "string") {
|
|
93
|
+
return chunk;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (ArrayBuffer.isView(chunk)) {
|
|
97
|
+
if (Buffer.isBuffer(chunk)) {
|
|
98
|
+
return chunk.toString(encoding);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return new TextDecoder(encoding).decode(chunk);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return Buffer.from(chunk).toString(encoding);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function setupConsole({beforeEach, afterEach, methods = defaultMethods, streams = defaultStreams}) {
|
|
81
108
|
if (testApi) {
|
|
82
109
|
throw new Error("fail-on-console: Call setupConsole() only once.");
|
|
83
110
|
}
|
|
84
111
|
|
|
85
112
|
assertSupportedMethods(methods);
|
|
113
|
+
assertSupportedStreams(streams);
|
|
86
114
|
|
|
87
115
|
testApi = {beforeEach, afterEach};
|
|
88
116
|
|
|
89
117
|
beforeEach(function () {
|
|
90
118
|
isInsideTest = true;
|
|
91
|
-
|
|
119
|
+
allowedMethods.clear();
|
|
120
|
+
allowedStreams.clear();
|
|
92
121
|
});
|
|
93
122
|
|
|
94
123
|
afterEach(function () {
|
|
@@ -104,7 +133,7 @@ function setupConsole({beforeEach, afterEach, methods = defaultMethods}) {
|
|
|
104
133
|
|
|
105
134
|
console[method] = function consoleOverride(...args) {
|
|
106
135
|
const message = format(...args);
|
|
107
|
-
const rules =
|
|
136
|
+
const rules = allowedMethods.get(method);
|
|
108
137
|
|
|
109
138
|
if (rules?.some((rule) => isAllowed(message, rule))) {
|
|
110
139
|
return;
|
|
@@ -131,6 +160,56 @@ function setupConsole({beforeEach, afterEach, methods = defaultMethods}) {
|
|
|
131
160
|
);
|
|
132
161
|
});
|
|
133
162
|
});
|
|
163
|
+
|
|
164
|
+
streams.forEach(function (streamName) {
|
|
165
|
+
const stream = globalThis.process?.[streamName];
|
|
166
|
+
|
|
167
|
+
if (!stream) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const originalWrite = stream.write;
|
|
172
|
+
const calls = [];
|
|
173
|
+
|
|
174
|
+
beforeEach(function () {
|
|
175
|
+
calls.length = 0;
|
|
176
|
+
|
|
177
|
+
stream.write = function streamOverride(chunk, encoding, cb) {
|
|
178
|
+
if (typeof encoding === "function") {
|
|
179
|
+
cb = encoding;
|
|
180
|
+
encoding = undefined;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const message = chunkToString(chunk, encoding);
|
|
184
|
+
const rules = allowedStreams.get(streamName);
|
|
185
|
+
|
|
186
|
+
if (!rules?.some((rule) => isAllowed(message, rule))) {
|
|
187
|
+
const call = {message, stack: ""};
|
|
188
|
+
Error.captureStackTrace?.(call, streamOverride);
|
|
189
|
+
|
|
190
|
+
calls.push(call);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
cb?.();
|
|
194
|
+
|
|
195
|
+
return true;
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
afterEach(function () {
|
|
200
|
+
stream.write = originalWrite;
|
|
201
|
+
|
|
202
|
+
if (!calls.length) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const detail = calls.map(({message, stack}) => `${message}\n${stack}`).join("\n\n");
|
|
207
|
+
|
|
208
|
+
throw new Error(
|
|
209
|
+
`Expected test not to write to process.${streamName}.\n\n${detail}\n\nIf expected, use allowStream("${streamName}", ...) to add an exception.`
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
134
213
|
}
|
|
135
214
|
|
|
136
215
|
function allowConsole(method, rules) {
|
|
@@ -143,8 +222,29 @@ function allowConsole(method, rules) {
|
|
|
143
222
|
const normalized = Array.isArray(rules) ? rules : [rules];
|
|
144
223
|
|
|
145
224
|
function addRules() {
|
|
146
|
-
const existing =
|
|
147
|
-
|
|
225
|
+
const existing = allowedMethods.get(method) ?? [];
|
|
226
|
+
allowedMethods.set(method, [...existing, ...normalized]);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (isInsideTest) {
|
|
230
|
+
addRules();
|
|
231
|
+
} else {
|
|
232
|
+
testApi.beforeEach(addRules);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function allowStream(stream, rules) {
|
|
237
|
+
if (!testApi) {
|
|
238
|
+
throw new Error("fail-on-console: Call setupConsole() before using allowStream().");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
assertSupportedStreams([stream]);
|
|
242
|
+
|
|
243
|
+
const normalized = Array.isArray(rules) ? rules : [rules];
|
|
244
|
+
|
|
245
|
+
function addRules() {
|
|
246
|
+
const existing = allowedStreams.get(stream) ?? [];
|
|
247
|
+
allowedStreams.set(stream, [...existing, ...normalized]);
|
|
148
248
|
}
|
|
149
249
|
|
|
150
250
|
if (isInsideTest) {
|
|
@@ -157,3 +257,4 @@ function allowConsole(method, rules) {
|
|
|
157
257
|
exports.setup = setupConsole;
|
|
158
258
|
exports.setupConsole = setupConsole;
|
|
159
259
|
exports.allowConsole = allowConsole;
|
|
260
|
+
exports.allowStream = allowStream;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fail-on-console",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Fail Vitest or Jest tests when unexpected console logs, warnings or errors occur.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jest",
|
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
"@vitest/coverage-v8": "4.1.10",
|
|
24
24
|
"commitlint": "^21.2.1",
|
|
25
25
|
"jest": "^30.4.2",
|
|
26
|
-
"npm-run-all2": "^9.0.
|
|
26
|
+
"npm-run-all2": "^9.0.3",
|
|
27
27
|
"prettier": "^3.9.6",
|
|
28
28
|
"prettier-plugin-packagejson": "^3.0.2",
|
|
29
|
+
"typescript": "^7.0.2",
|
|
29
30
|
"vitest": "^4.1.10"
|
|
30
31
|
},
|
|
31
32
|
"scripts": {
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
"format:check": "prettier --check .",
|
|
35
36
|
"test:jest": "jest",
|
|
36
37
|
"test:vitest": "vitest run --coverage",
|
|
37
|
-
"
|
|
38
|
+
"type:check": "tsc",
|
|
39
|
+
"verify": "run-s commit:check format:check type:check test:vitest test:jest"
|
|
38
40
|
}
|
|
39
41
|
}
|