@vitest-agent/plugin 5.1.2 → 5.2.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/index.d.ts +20 -0
- package/package.json +13 -10
- package/plugin.js +50 -29
- package/reporter.js +46 -7
- package/utils/discover-strategy.js +13 -3
- package/utils/resolve-no-color.js +13 -0
- package/version.js +1 -1
package/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "@effected/env";
|
|
1
2
|
import { EnvironmentDetector, PlatformOptions, PlatformServices, SettingsInput, StackFrameInput } from "@vitest-agent/engine";
|
|
2
3
|
import { AgentPluginOptions, AgentReporterOptions, ConsoleMode, CoverageBaselines, CoverageInput, CoverageLevel, CoverageLevelName, CoverageLevelName as CoverageLevelName$1, CoverageReport, OutputFormat, ResolvedReporterConfig, ResolvedThresholds, RunEvent, Transport, VitestAgentReporterFactory, resolveCoverageInput, validateCoverageConfig } from "@vitest-agent/sdk";
|
|
3
4
|
import { Context, Effect, Layer, Option } from "effect";
|
|
@@ -693,6 +694,13 @@ export declare class AgentReporter {
|
|
|
693
694
|
* @internal
|
|
694
695
|
*/
|
|
695
696
|
private reporters;
|
|
697
|
+
/**
|
|
698
|
+
* The one close of the run-event channel and the reporters, started at
|
|
699
|
+
* Vitest's close (see `closeReporters`). Undefined until then.
|
|
700
|
+
*
|
|
701
|
+
* @internal
|
|
702
|
+
*/
|
|
703
|
+
private closing;
|
|
696
704
|
/**
|
|
697
705
|
* Whether the user supplied a custom `reporter` factory. A custom
|
|
698
706
|
* reporter may subscribe to the run-event channel in any console mode,
|
|
@@ -777,6 +785,18 @@ export declare class AgentReporter {
|
|
|
777
785
|
* @param vitest - The Vitest instance
|
|
778
786
|
*/
|
|
779
787
|
onInit(vitest: unknown): Promise<void>;
|
|
788
|
+
/**
|
|
789
|
+
* Close the reporters resolved at `onInit`, then end the run-event
|
|
790
|
+
* channel, once, at Vitest's close. Reporters first: a live view folds
|
|
791
|
+
* every event still queued in its subscription and commits its last
|
|
792
|
+
* frame in `close`, and `PubSub.shutdown` would drop whatever a
|
|
793
|
+
* subscriber has not taken yet. The shutdown after is harmless to a
|
|
794
|
+
* closed view and ends any other subscriber. A failing close is logged,
|
|
795
|
+
* never thrown — Vitest is shutting down.
|
|
796
|
+
*
|
|
797
|
+
* @internal
|
|
798
|
+
*/
|
|
799
|
+
private closeReporters;
|
|
780
800
|
/**
|
|
781
801
|
* Resolve the reporter factory at run start.
|
|
782
802
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest-agent/plugin",
|
|
3
|
-
"version": "5.1
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Vitest plugin for the vitest-agent ecosystem: owns persistence, classification, baselines, trends, and dispatches rendering to a configurable reporter.",
|
|
6
6
|
"keywords": [
|
|
@@ -43,15 +43,18 @@
|
|
|
43
43
|
"vitest-agent-mcp": "bin/vitest-agent-mcp.js"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@effect/platform-node": "4.0.0
|
|
47
|
-
"@effected/
|
|
48
|
-
"@effected/
|
|
49
|
-
"@
|
|
50
|
-
"@
|
|
51
|
-
"@
|
|
52
|
-
"@vitest-agent/
|
|
53
|
-
"@vitest-agent/
|
|
54
|
-
"
|
|
46
|
+
"@effect/platform-node": "^4.0.0",
|
|
47
|
+
"@effected/cli": "^0.11.0",
|
|
48
|
+
"@effected/env": "^0.1.0",
|
|
49
|
+
"@effected/glob": "^0.10.0",
|
|
50
|
+
"@effected/walker": "^0.15.0",
|
|
51
|
+
"@effected/workspaces": "^0.31.0",
|
|
52
|
+
"@vitest-agent/cli": "4.0.1",
|
|
53
|
+
"@vitest-agent/engine": "0.5.0",
|
|
54
|
+
"@vitest-agent/mcp": "5.1.7",
|
|
55
|
+
"@vitest-agent/reporter": "4.0.1",
|
|
56
|
+
"@vitest-agent/sdk": "6.0.0",
|
|
57
|
+
"effect": "^4.0.0",
|
|
55
58
|
"magic-string": "^1.4.2"
|
|
56
59
|
},
|
|
57
60
|
"peerDependencies": {
|
package/plugin.js
CHANGED
|
@@ -20,9 +20,11 @@ import { execSync } from "node:child_process";
|
|
|
20
20
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
21
21
|
import { tmpdir } from "node:os";
|
|
22
22
|
import { join } from "node:path";
|
|
23
|
-
import {
|
|
23
|
+
import { CliLog } from "@effected/cli";
|
|
24
|
+
import { Audience, EnvOverride } from "@effected/env";
|
|
25
|
+
import { EnvironmentDetector, EnvironmentDetectorLive, ExecutorResolver, ExecutorResolverLive, LoggerLive, resolveLogLevel } from "@vitest-agent/engine";
|
|
24
26
|
import { AgentConsoleMode, CiConsoleMode, CoverageLevel, HumanConsoleMode, SRC_DIR, TEST_DIR, formatFatalError, isTestFileName } from "@vitest-agent/sdk";
|
|
25
|
-
import { Effect,
|
|
27
|
+
import { Effect, Layer, Option } from "effect";
|
|
26
28
|
|
|
27
29
|
//#region src/plugin.ts
|
|
28
30
|
/**
|
|
@@ -41,29 +43,53 @@ import { Effect, Schema } from "effect";
|
|
|
41
43
|
* the dedicated `ci-annotations` reporter is opt-in until the GHA
|
|
42
44
|
* annotations writer ships).
|
|
43
45
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
46
|
+
* `VITEST_AGENT_CONSOLE` is read through `@effected/env`'s `EnvOverride`
|
|
47
|
+
* (case-insensitive, per-audience accepted literals), with the executor as
|
|
48
|
+
* the `Audience`. A value the executor does not accept is ignored with one
|
|
49
|
+
* `[vitest-agent:plugin]` diagnostic line, worded here from
|
|
50
|
+
* `EnvOverride.readResult`'s structured rejection and sent to `report`
|
|
51
|
+
* (default: `process.stderr`), never stdout. `configureVitest` passes the
|
|
52
|
+
* per-Vitest-instance dedupe sink so the line prints once per run rather than
|
|
53
|
+
* once per project (issue #459).
|
|
48
54
|
*
|
|
49
55
|
* @internal
|
|
50
56
|
*/
|
|
51
57
|
function resolveConsoleMode(options, executor, _env, report = (line) => {
|
|
52
58
|
process.stderr.write(line);
|
|
53
59
|
}) {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
const { accepted, rejected } = Effect.runSync(readConsoleOverride.pipe(Effect.provideService(Audience, {
|
|
61
|
+
kind: executor,
|
|
62
|
+
source: "detected"
|
|
63
|
+
})));
|
|
64
|
+
if (Option.isSome(rejected)) {
|
|
65
|
+
const { value, audience, accepts } = rejected.value;
|
|
66
|
+
report(`[vitest-agent:plugin] ignoring VITEST_AGENT_CONSOLE=${value}: not accepted for the ${audience} audience (accepts ${accepts.join("|")})\n`);
|
|
60
67
|
}
|
|
68
|
+
if (Option.isSome(accepted)) return accepted.value;
|
|
61
69
|
const console = options.console;
|
|
62
70
|
if (executor === "human") return console?.human ?? "passthrough";
|
|
63
71
|
if (executor === "agent") return console?.agent ?? "agent";
|
|
64
72
|
return console?.ci ?? "passthrough";
|
|
65
73
|
}
|
|
66
74
|
/**
|
|
75
|
+
* The `VITEST_AGENT_CONSOLE` override for the current `Audience`, without
|
|
76
|
+
* logging: `accepted` is the literal that audience accepts, `rejected` a set
|
|
77
|
+
* value it does not (with the value, the audience and its literals), both
|
|
78
|
+
* `None` when unset or empty. The accepted type is the union of every slot's
|
|
79
|
+
* literals, not the current audience's; the audience check is a runtime one.
|
|
80
|
+
*
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
const readConsoleOverride = EnvOverride.readResult({
|
|
84
|
+
envVar: "VITEST_AGENT_CONSOLE",
|
|
85
|
+
source: process.env,
|
|
86
|
+
accepts: {
|
|
87
|
+
human: HumanConsoleMode.literals,
|
|
88
|
+
agent: AgentConsoleMode.literals,
|
|
89
|
+
ci: CiConsoleMode.literals
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
/**
|
|
67
93
|
* The plugin owns stdout when the resolved console mode produces visible
|
|
68
94
|
* output that would conflict with Vitest's own reporters. Passthrough lets
|
|
69
95
|
* Vitest emit progress normally; silent strips everything; the other modes
|
|
@@ -143,19 +169,6 @@ const reportedConfigDiagnosticsByVitest = /* @__PURE__ */ new WeakMap();
|
|
|
143
169
|
const TEST_FILE_DIR_RE = new RegExp(`/(?:${SRC_DIR}|${TEST_DIR})/`);
|
|
144
170
|
const isTestFile = (id) => isTestFileName(id) && TEST_FILE_DIR_RE.test(id);
|
|
145
171
|
/**
|
|
146
|
-
* Map a detected {@link Environment} to its {@link Executor}. Inline copy
|
|
147
|
-
* of the `ExecutorResolverLive` mapping so the plugin can compute it
|
|
148
|
-
* synchronously inside `configureVitest` without spinning up an Effect
|
|
149
|
-
* runtime.
|
|
150
|
-
*
|
|
151
|
-
* @internal
|
|
152
|
-
*/
|
|
153
|
-
function envToExecutor(env) {
|
|
154
|
-
if (env === "agent-shell") return "agent";
|
|
155
|
-
if (env === "terminal") return "human";
|
|
156
|
-
return "ci";
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
172
|
* Wraps `resolvedConfig.logger.warn` in place so the benign Vite
|
|
160
173
|
* "Failed to load source map" / ENOENT `.js.map` noise (GitHub issue #110)
|
|
161
174
|
* never reaches stdout, while every other warning still passes through
|
|
@@ -192,7 +205,10 @@ function installViteSourceMapWarningFilter(resolvedConfig) {
|
|
|
192
205
|
function AgentPlugin(options = {}, _layer) {
|
|
193
206
|
const layer = _layer ?? EnvironmentDetectorLive(process.env);
|
|
194
207
|
const logLevel = resolveLogLevel(process.env);
|
|
195
|
-
const
|
|
208
|
+
const diagnostics = logLevel === "Debug" || logLevel === "Trace" || logLevel === "All" ? LoggerLive(logLevel, void 0, process.env) : void 0;
|
|
209
|
+
const log = diagnostics ? (...args) => {
|
|
210
|
+
Effect.runSync(Effect.logDebug(args.map(String).join(" ")).pipe(CliLog.component("vitest-agent:plugin"), Effect.provide(diagnostics)));
|
|
211
|
+
} : (..._args) => {};
|
|
196
212
|
const discoverStrategyResolved = options.discoverStrategy === false ? null : options.discoverStrategy ?? new DefaultDiscoverStrategy();
|
|
197
213
|
const classifyForCache = (id) => {
|
|
198
214
|
if (!discoverStrategyResolved) return void 0;
|
|
@@ -216,8 +232,13 @@ function AgentPlugin(options = {}, _layer) {
|
|
|
216
232
|
ctx.defineCacheKeyGenerator(makeTagCacheKeyGenerator(classifyForCache));
|
|
217
233
|
log("registered fsModuleCache tag cache-key generator");
|
|
218
234
|
}
|
|
219
|
-
const env = await Effect.runPromise(Effect.
|
|
220
|
-
|
|
235
|
+
const { env, executor } = await Effect.runPromise(Effect.gen(function* () {
|
|
236
|
+
const env = yield* (yield* EnvironmentDetector).detect();
|
|
237
|
+
return {
|
|
238
|
+
env,
|
|
239
|
+
executor: yield* (yield* ExecutorResolver).resolve(env)
|
|
240
|
+
};
|
|
241
|
+
}).pipe(Effect.provide(Layer.merge(layer, ExecutorResolverLive))));
|
|
221
242
|
const reportOption = options.report;
|
|
222
243
|
const reportScope = reportOption === false ? void 0 : executor === "human" && reportOption === void 0 ? void 0 : reportOption?.scope ?? "vitest-agent";
|
|
223
244
|
if (reportScope !== void 0) assertFlatScope(reportScope);
|
|
@@ -451,4 +472,4 @@ function makeDiscoverBuilder(options) {
|
|
|
451
472
|
})(AgentPlugin || (AgentPlugin = {}));
|
|
452
473
|
|
|
453
474
|
//#endregion
|
|
454
|
-
export { AgentPlugin, CURRENT_PLUGIN_VERSION, makeDiscoverBuilder, resolveConsoleMode };
|
|
475
|
+
export { AgentPlugin, CURRENT_PLUGIN_VERSION, makeDiscoverBuilder, readConsoleOverride, resolveConsoleMode };
|
package/reporter.js
CHANGED
|
@@ -7,6 +7,7 @@ import { captureSettings, hashSettings } from "./utils/capture-settings.js";
|
|
|
7
7
|
import { isPartialRun } from "./utils/is-partial-run.js";
|
|
8
8
|
import { processFailure } from "./utils/process-failure.js";
|
|
9
9
|
import { assertReportCapable, createReportWriter } from "./utils/report-writer.js";
|
|
10
|
+
import { resolveNoColor } from "./utils/resolve-no-color.js";
|
|
10
11
|
import { routeRenderedOutput } from "./utils/route-rendered-output.js";
|
|
11
12
|
import { stringifyFailureValue } from "./utils/stringify-failure-value.js";
|
|
12
13
|
import { mkdirSync, statSync } from "node:fs";
|
|
@@ -15,7 +16,7 @@ import { DataReader, DataStore, DetailResolver, EnvironmentDetector, ExecutorRes
|
|
|
15
16
|
import { buildAgentReport, coerceErrorField, computeTrend, formatFatalError, isTimeoutError, probeHostMetadataFromEnv } from "@vitest-agent/sdk";
|
|
16
17
|
import { Effect, Option, PubSub } from "effect";
|
|
17
18
|
import { randomUUID } from "node:crypto";
|
|
18
|
-
import
|
|
19
|
+
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
19
20
|
import { DefaultVitestAgentReporter } from "@vitest-agent/reporter";
|
|
20
21
|
|
|
21
22
|
//#region src/reporter.ts
|
|
@@ -339,6 +340,13 @@ var AgentReporter = class {
|
|
|
339
340
|
*/
|
|
340
341
|
reporters;
|
|
341
342
|
/**
|
|
343
|
+
* The one close of the run-event channel and the reporters, started at
|
|
344
|
+
* Vitest's close (see `closeReporters`). Undefined until then.
|
|
345
|
+
*
|
|
346
|
+
* @internal
|
|
347
|
+
*/
|
|
348
|
+
closing;
|
|
349
|
+
/**
|
|
342
350
|
* Whether the user supplied a custom `reporter` factory. A custom
|
|
343
351
|
* reporter may subscribe to the run-event channel in any console mode,
|
|
344
352
|
* so the streaming hooks publish events whenever this is true.
|
|
@@ -492,6 +500,36 @@ var AgentReporter = class {
|
|
|
492
500
|
await this.ensureDbPath();
|
|
493
501
|
} catch {}
|
|
494
502
|
await this.initReporters();
|
|
503
|
+
const onClose = vitest?.onClose;
|
|
504
|
+
if (typeof onClose === "function") onClose.call(vitest, () => this.closeReporters());
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Close the reporters resolved at `onInit`, then end the run-event
|
|
508
|
+
* channel, once, at Vitest's close. Reporters first: a live view folds
|
|
509
|
+
* every event still queued in its subscription and commits its last
|
|
510
|
+
* frame in `close`, and `PubSub.shutdown` would drop whatever a
|
|
511
|
+
* subscriber has not taken yet. The shutdown after is harmless to a
|
|
512
|
+
* closed view and ends any other subscriber. A failing close is logged,
|
|
513
|
+
* never thrown — Vitest is shutting down.
|
|
514
|
+
*
|
|
515
|
+
* @internal
|
|
516
|
+
*/
|
|
517
|
+
closeReporters() {
|
|
518
|
+
this.closing ??= (async () => {
|
|
519
|
+
await Promise.all((this.reporters ?? []).map(async (reporter) => {
|
|
520
|
+
try {
|
|
521
|
+
await reporter.close?.();
|
|
522
|
+
} catch (err) {
|
|
523
|
+
process.stderr.write(`vitest-agent: reporter close failed: ${formatFatalError(err)}\n`);
|
|
524
|
+
}
|
|
525
|
+
}));
|
|
526
|
+
try {
|
|
527
|
+
Effect.runSync(PubSub.shutdown(this.runEvents));
|
|
528
|
+
} catch (err) {
|
|
529
|
+
process.stderr.write(`vitest-agent: run-event channel shutdown threw: ${formatFatalError(err)}\n`);
|
|
530
|
+
}
|
|
531
|
+
})();
|
|
532
|
+
return this.closing;
|
|
495
533
|
}
|
|
496
534
|
/**
|
|
497
535
|
* Resolve the reporter factory at run start.
|
|
@@ -527,16 +565,17 @@ var AgentReporter = class {
|
|
|
527
565
|
hasFailures: false,
|
|
528
566
|
belowTargets: false,
|
|
529
567
|
hasTargets: !!opts.coverageTargets
|
|
530
|
-
}, opts.detail)
|
|
568
|
+
}, opts.detail),
|
|
569
|
+
noColor: yield* resolveNoColor
|
|
531
570
|
};
|
|
532
571
|
});
|
|
533
|
-
const { env, executor, format, detail } = await Effect.runPromise(initProgram.pipe(Effect.provide(OutputPipelineLive(process.env)), Effect.provide(NodeServices.layer)));
|
|
572
|
+
const { env, executor, format, detail, noColor } = await Effect.runPromise(initProgram.pipe(Effect.provide(OutputPipelineLive(process.env)), Effect.provide(NodeServices.layer)));
|
|
534
573
|
const kit = buildReporterKit({
|
|
535
574
|
env,
|
|
536
575
|
executor,
|
|
537
576
|
format,
|
|
538
577
|
detail,
|
|
539
|
-
noColor
|
|
578
|
+
noColor,
|
|
540
579
|
consoleMode: opts.consoleMode ?? "passthrough",
|
|
541
580
|
mcp: opts.mcp ?? false,
|
|
542
581
|
githubActions: opts.githubActions,
|
|
@@ -1139,7 +1178,7 @@ var AgentReporter = class {
|
|
|
1139
1178
|
executor,
|
|
1140
1179
|
format,
|
|
1141
1180
|
detail,
|
|
1142
|
-
noColor:
|
|
1181
|
+
noColor: yield* resolveNoColor,
|
|
1143
1182
|
consoleMode: opts.consoleMode ?? "passthrough",
|
|
1144
1183
|
mcp: opts.mcp ?? false,
|
|
1145
1184
|
githubActions: opts.githubActions,
|
|
@@ -1191,7 +1230,7 @@ var AgentReporter = class {
|
|
|
1191
1230
|
return;
|
|
1192
1231
|
}
|
|
1193
1232
|
if (dbPath !== void 0 && persistDisabled === void 0) try {
|
|
1194
|
-
await ensureMigrated(dbPath, logLevel, logFile);
|
|
1233
|
+
await ensureMigrated(dbPath, logLevel, logFile, process.env);
|
|
1195
1234
|
} catch (err) {
|
|
1196
1235
|
persistDisabled = formatFatalError(err);
|
|
1197
1236
|
}
|
|
@@ -1691,7 +1730,7 @@ var AgentReporter = class {
|
|
|
1691
1730
|
executor,
|
|
1692
1731
|
format,
|
|
1693
1732
|
detail,
|
|
1694
|
-
noColor:
|
|
1733
|
+
noColor: yield* resolveNoColor,
|
|
1695
1734
|
consoleMode: opts.consoleMode ?? "passthrough",
|
|
1696
1735
|
mcp: opts.mcp ?? false,
|
|
1697
1736
|
githubActions: opts.githubActions,
|
|
@@ -2,7 +2,9 @@ import { nodeWalkerFs } from "./walker-fs.js";
|
|
|
2
2
|
import { findTestFiles } from "./find-test-files.js";
|
|
3
3
|
import { Tag } from "./tag.js";
|
|
4
4
|
import { join, sep } from "node:path";
|
|
5
|
+
import { RuntimeEnv } from "@effected/env";
|
|
5
6
|
import { NON_DISCOVERABLE_DIRS, SRC_DIR, TEST_DIR, TEST_FILE_GLOB_SUFFIX, TEST_HELPER_DIRS } from "@vitest-agent/sdk";
|
|
7
|
+
import { Option } from "effect";
|
|
6
8
|
import { configDefaults } from "vitest/config";
|
|
7
9
|
|
|
8
10
|
//#region src/utils/discover-strategy.ts
|
|
@@ -80,12 +82,20 @@ var ConcreteDiscoverStrategy = class ConcreteDiscoverStrategy extends DiscoverSt
|
|
|
80
82
|
return new ConcreteDiscoverStrategy(newTags, newClassifyLayers, newBuildProjectLayers);
|
|
81
83
|
}
|
|
82
84
|
};
|
|
83
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Whether the process runs in CI, by `@effected/env`'s `RuntimeEnv` rule: a
|
|
87
|
+
* truthy `GITHUB_ACTIONS`, or a `CI` / `CONTINUOUS_INTEGRATION` that is set,
|
|
88
|
+
* non-empty, and not `false` / `0` (is-in-ci semantics). Read when a strategy is
|
|
89
|
+
* constructed rather than at module load, so the environment in force when
|
|
90
|
+
* `AgentPlugin.discover()` runs is the one that decides.
|
|
91
|
+
*/
|
|
92
|
+
const runsInCi = () => Option.isSome(RuntimeEnv.fromRecord(process.env).ci);
|
|
93
|
+
const defaultTags = (inCi) => [
|
|
84
94
|
Tag.make("unit"),
|
|
85
95
|
Tag.make("int", { timeout: 6e4 }),
|
|
86
96
|
Tag.make("e2e", {
|
|
87
97
|
timeout: 12e4,
|
|
88
|
-
retry:
|
|
98
|
+
retry: inCi ? 2 : 0
|
|
89
99
|
})
|
|
90
100
|
];
|
|
91
101
|
const E2E_RE = /\.e2e\.(test|spec)\.(ts|tsx|js|jsx)$/;
|
|
@@ -98,7 +108,7 @@ const INT_RE = /\.int\.(test|spec)\.(ts|tsx|js|jsx)$/;
|
|
|
98
108
|
* @public
|
|
99
109
|
*/
|
|
100
110
|
var DefaultDiscoverStrategy = class extends DiscoverStrategy {
|
|
101
|
-
tags =
|
|
111
|
+
tags = defaultTags(runsInCi());
|
|
102
112
|
get tagDefinitions() {
|
|
103
113
|
return this.tags.map((t) => t.definition);
|
|
104
114
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TerminalEnv } from "@effected/env";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/resolve-no-color.ts
|
|
5
|
+
/**
|
|
6
|
+
* Whether the reporter should render without colour, decided by the kit's
|
|
7
|
+
* terminal rule rather than `NO_COLOR` alone: `FORCE_COLOR` beats `NO_COLOR`,
|
|
8
|
+
* and `NODE_DISABLE_COLORS`, `TERM=dumb` and a non-TTY stdout all disable it.
|
|
9
|
+
*/
|
|
10
|
+
const resolveNoColor = TerminalEnv.colorLevel("stdout").pipe(Effect.map((level) => level === "none"));
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { resolveNoColor };
|