@effected/cli-kit 0.0.0-stage → 0.27.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/Cancelled.js +43 -0
- package/CliAudience.js +177 -0
- package/CliColor.js +66 -0
- package/CliEnv.js +101 -0
- package/CliExit.js +117 -0
- package/CliFailure.js +287 -0
- package/CliFormat.js +124 -0
- package/CliInteractive.js +94 -0
- package/CliLinks.js +153 -0
- package/CliLog.js +367 -0
- package/CliLogger.js +91 -0
- package/CliMessage.js +79 -0
- package/CliPrompt.js +110 -0
- package/CliRuntime.js +254 -0
- package/CliTest.js +240 -0
- package/CliTheme.js +142 -0
- package/ConfigIssueRenderer.js +62 -0
- package/Doc.js +548 -0
- package/Fmt.js +295 -0
- package/GithubAnnotation.js +39 -0
- package/Glyphs.js +82 -0
- package/LICENSE +21 -0
- package/NotInteractive.js +41 -0
- package/README.md +213 -2
- package/Render.js +280 -0
- package/SchemaIssueRenderer.js +47 -0
- package/Status.js +165 -0
- package/TestTerminal.js +107 -0
- package/Token.js +70 -0
- package/index.d.ts +4035 -0
- package/index.js +27 -0
- package/internal/ExitRequested.js +21 -0
- package/internal/HelpRouting.js +63 -0
- package/internal/ansi.js +229 -0
- package/internal/autoFormat.js +33 -0
- package/internal/canPrompt.js +14 -0
- package/internal/counts.js +83 -0
- package/internal/diagnostics.js +31 -0
- package/internal/displayPath.js +46 -0
- package/internal/displayWidth.js +42 -0
- package/internal/failureTarget.js +195 -0
- package/internal/fallbackAnswer.js +17 -0
- package/internal/fileSink.js +61 -0
- package/internal/format.js +173 -0
- package/internal/inspect.js +40 -0
- package/internal/isExitCode.js +11 -0
- package/internal/layout.js +249 -0
- package/internal/linkScheme.js +29 -0
- package/internal/linkTarget.js +49 -0
- package/internal/logSafety.js +45 -0
- package/internal/renderAnsi.js +51 -0
- package/internal/renderDoc.js +322 -0
- package/internal/renderGithubLog.js +59 -0
- package/internal/renderMarkdown.js +367 -0
- package/internal/renderPlain.js +49 -0
- package/internal/scanAudience.js +105 -0
- package/internal/splitFrame.js +55 -0
- package/internal/terminalCapabilities.js +23 -0
- package/internal/wizardGate.js +17 -0
- package/package.json +87 -5
- package/testing.d.ts +283 -0
- package/testing.js +4 -0
- package/tsdoc-metadata.json +11 -0
- package/ui/CliUi.js +509 -0
- package/ui/CliUiDetached.js +36 -0
- package/ui/CliUiLive.js +436 -0
- package/ui/CliUiRouteStream.js +72 -0
- package/ui/Confirm.js +244 -0
- package/ui/DocView.js +76 -0
- package/ui/KeyHelp.js +61 -0
- package/ui/KeyTable.js +198 -0
- package/ui/MultiSelect.js +259 -0
- package/ui/Select.js +229 -0
- package/ui/Tabs.js +201 -0
- package/ui/TextInput.js +289 -0
- package/ui/Toggle.js +31 -0
- package/ui/UiKey.js +48 -0
- package/ui/UiProvider.js +62 -0
- package/ui/UiStreams.js +17 -0
- package/ui/UiTheme.js +166 -0
- package/ui/Viewport.js +203 -0
- package/ui/internal/ErrorBoundary.js +29 -0
- package/ui/internal/Holder.js +73 -0
- package/ui/internal/ScreenContext.js +51 -0
- package/ui/internal/UiProviders.js +38 -0
- package/ui/internal/ink.js +121 -0
- package/ui/internal/inkChalk.js +47 -0
- package/ui/internal/inkConsole.js +150 -0
- package/ui/internal/lazyView.js +73 -0
- package/ui/internal/lineRouter.js +70 -0
- package/ui/internal/lineText.js +18 -0
- package/ui/internal/mountPermit.js +15 -0
- package/ui/internal/processStreams.js +18 -0
- package/ui/internal/renderOptions.js +12 -0
- package/ui/testing/CliUiTest.js +792 -0
- package/ui/testing/fakeStreams.js +104 -0
- package/ui/testing/terminalModel.js +67 -0
- package/ui-testing-serializer.d.ts +12 -0
- package/ui-testing-serializer.js +32 -0
- package/ui-testing.d.ts +558 -0
- package/ui-testing.js +3 -0
- package/ui.d.ts +2013 -0
- package/ui.js +17 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { UiStreams } from "../UiStreams.js";
|
|
2
|
+
import { inkModules } from "./ink.js";
|
|
3
|
+
import { Effect, Inspectable } from "effect";
|
|
4
|
+
|
|
5
|
+
// src/ui/internal/inkConsole.ts
|
|
6
|
+
/** One argument as a console shows it: a string as is, an `Error` with its stack, anything else as data (JSON). */
|
|
7
|
+
const shown = (arg) => arg instanceof Error ? arg.stack ?? String(arg) : Inspectable.toStringUnknown(arg, 0);
|
|
8
|
+
/** A console call's arguments as one line of text, joined by spaces. */
|
|
9
|
+
const textOf = (args) => args.map(shown).join(" ");
|
|
10
|
+
/** `console.table`'s rows, as a plain pipe table: an `(index)` column, then each key, then `Values` for scalars. */
|
|
11
|
+
const tableOf = (data, properties) => {
|
|
12
|
+
if (data === null || typeof data !== "object") return textOf([data]);
|
|
13
|
+
const rows = Object.entries(data);
|
|
14
|
+
const isRecord = (value) => value !== null && typeof value === "object";
|
|
15
|
+
const keys = properties ?? [...new Set(rows.flatMap(([, value]) => isRecord(value) ? Object.keys(value) : []))];
|
|
16
|
+
const scalars = rows.some(([, value]) => !isRecord(value));
|
|
17
|
+
const header = [
|
|
18
|
+
"(index)",
|
|
19
|
+
...keys,
|
|
20
|
+
...scalars ? ["Values"] : []
|
|
21
|
+
];
|
|
22
|
+
const cell = (value) => value === void 0 ? "" : typeof value === "string" ? value : shown(value);
|
|
23
|
+
const body = rows.map(([index, value]) => [
|
|
24
|
+
index,
|
|
25
|
+
...keys.map((key) => isRecord(value) ? cell(value[key]) : ""),
|
|
26
|
+
...scalars ? [isRecord(value) ? "" : cell(value)] : []
|
|
27
|
+
]);
|
|
28
|
+
const widths = header.map((title, column) => Math.max(title.length, ...body.map((row) => (row[column] ?? "").length)));
|
|
29
|
+
const line = (cells) => `| ${cells.map((text, column) => text.padEnd(widths[column] ?? 0)).join(" | ")} |`;
|
|
30
|
+
return [line(header), ...body.map(line)].join("\n");
|
|
31
|
+
};
|
|
32
|
+
/** Milliseconds now, for `time`; the platform clock when there is one. */
|
|
33
|
+
const now = () => globalThis.performance?.now() ?? Date.now();
|
|
34
|
+
/**
|
|
35
|
+
* Build an `InkConsole` over `UiStreams`.
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* Ink's writers (`useStdout().write`, `useStderr().write`) clear the frame, write the line and repaint the frame, so a
|
|
39
|
+
* line written through them lands above the frame without tearing it; a raw write to the stream lands inside the frame
|
|
40
|
+
* instead. They are reachable only from inside the tree, which is what the `Bridge` is for. Ink drops whatever they
|
|
41
|
+
* are handed once it has unmounted, so the owner detaches before it unmounts, and a line written after goes straight
|
|
42
|
+
* to the stream.
|
|
43
|
+
*
|
|
44
|
+
* Every `Console` method is the bridge's own, none the ambient console's: one that fell through would write to the
|
|
45
|
+
* process's terminal past Ink, tearing the frame and escaping `UiStreams`.
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
const makeInkConsole = Effect.gen(function* () {
|
|
50
|
+
const streams = yield* UiStreams;
|
|
51
|
+
let attached;
|
|
52
|
+
let indent = "";
|
|
53
|
+
const counts = /* @__PURE__ */ new Map();
|
|
54
|
+
const timers = /* @__PURE__ */ new Map();
|
|
55
|
+
const emit = (stream, text) => {
|
|
56
|
+
const data = `${text.split("\n").map((line) => indent + line).join("\n")}\n`;
|
|
57
|
+
if (attached !== void 0) (stream === "out" ? attached.out : attached.err)(data);
|
|
58
|
+
else if (stream === "out") streams.stdout.write(data);
|
|
59
|
+
else streams.stderr.write(data);
|
|
60
|
+
};
|
|
61
|
+
const toOut = (...args) => emit("out", textOf(args));
|
|
62
|
+
const toErr = (...args) => emit("err", textOf(args));
|
|
63
|
+
const elapsed = (label, method, extra) => {
|
|
64
|
+
const started = timers.get(label);
|
|
65
|
+
if (started === void 0) {
|
|
66
|
+
emit("err", `Warning: No such label '${label}' for console.${method}()`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const tail = extra.length === 0 ? "" : ` ${textOf(extra)}`;
|
|
70
|
+
emit("out", `${label}: ${(now() - started).toFixed(3)}ms${tail}`);
|
|
71
|
+
};
|
|
72
|
+
const group = (...label) => {
|
|
73
|
+
if (label.length > 0) toOut(...label);
|
|
74
|
+
indent += " ";
|
|
75
|
+
};
|
|
76
|
+
const writer = {
|
|
77
|
+
log: toOut,
|
|
78
|
+
info: toOut,
|
|
79
|
+
debug: toOut,
|
|
80
|
+
dirxml: toOut,
|
|
81
|
+
error: toErr,
|
|
82
|
+
warn: toErr,
|
|
83
|
+
trace: (...args) => {
|
|
84
|
+
const stack = ((/* @__PURE__ */ new Error()).stack ?? "").split("\n").slice(2).join("\n");
|
|
85
|
+
emit("err", `Trace${args.length === 0 ? "" : `: ${textOf(args)}`}${stack === "" ? "" : `\n${stack}`}`);
|
|
86
|
+
},
|
|
87
|
+
dir: (item) => toOut(item),
|
|
88
|
+
table: (data, properties) => emit("out", tableOf(data, properties)),
|
|
89
|
+
assert: (condition, ...args) => {
|
|
90
|
+
if (!condition) emit("err", `Assertion failed${args.length === 0 ? "" : `: ${textOf(args)}`}`);
|
|
91
|
+
},
|
|
92
|
+
count: (label = "default") => {
|
|
93
|
+
const next = (counts.get(label) ?? 0) + 1;
|
|
94
|
+
counts.set(label, next);
|
|
95
|
+
emit("out", `${label}: ${next}`);
|
|
96
|
+
},
|
|
97
|
+
countReset: (label = "default") => {
|
|
98
|
+
counts.delete(label);
|
|
99
|
+
},
|
|
100
|
+
group,
|
|
101
|
+
groupCollapsed: group,
|
|
102
|
+
groupEnd: () => {
|
|
103
|
+
indent = indent.slice(2);
|
|
104
|
+
},
|
|
105
|
+
time: (label = "default") => {
|
|
106
|
+
timers.set(label, now());
|
|
107
|
+
},
|
|
108
|
+
timeLog: (label = "default", ...extra) => elapsed(label, "timeLog", extra),
|
|
109
|
+
timeEnd: (label = "default") => {
|
|
110
|
+
elapsed(label, "timeEnd", []);
|
|
111
|
+
timers.delete(label);
|
|
112
|
+
},
|
|
113
|
+
clear: () => void 0
|
|
114
|
+
};
|
|
115
|
+
const Bridge = (props) => {
|
|
116
|
+
const { ink, react } = inkModules();
|
|
117
|
+
const out = ink.useStdout().write;
|
|
118
|
+
const err = ink.useStderr().write;
|
|
119
|
+
react.useLayoutEffect(() => {
|
|
120
|
+
const writers = {
|
|
121
|
+
out,
|
|
122
|
+
err
|
|
123
|
+
};
|
|
124
|
+
attached = writers;
|
|
125
|
+
return () => {
|
|
126
|
+
if (attached === writers) attached = void 0;
|
|
127
|
+
};
|
|
128
|
+
}, [out, err]);
|
|
129
|
+
return props.children ?? null;
|
|
130
|
+
};
|
|
131
|
+
return {
|
|
132
|
+
writer,
|
|
133
|
+
print: (text) => {
|
|
134
|
+
const data = `${text}\n`;
|
|
135
|
+
if (attached !== void 0) attached.out(data);
|
|
136
|
+
else streams.stdout.write(data);
|
|
137
|
+
},
|
|
138
|
+
printAbove: (stream, text) => {
|
|
139
|
+
if (attached === void 0) return false;
|
|
140
|
+
(stream === "stdout" ? attached.out : attached.err)(`${text}\n`);
|
|
141
|
+
return true;
|
|
142
|
+
},
|
|
143
|
+
Bridge,
|
|
144
|
+
detach: () => {
|
|
145
|
+
attached = void 0;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export { makeInkConsole };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
|
|
3
|
+
// src/ui/internal/lazyView.ts
|
|
4
|
+
/** Where a lazy view keeps its loader: a `Symbol.for` key, so two copies of the package agree on it. */
|
|
5
|
+
const LOAD = Symbol.for("@effected/cli-kit/ui/lazyView");
|
|
6
|
+
const NOT_LOADED = "@effected/cli-kit/ui: a CliUi.lazyView render was called before its module loaded; only CliUi.live loads it first";
|
|
7
|
+
const kindOf = (value) => value === null ? "null" : Array.isArray(value) ? "an array" : typeof value === "object" ? "an object" : typeof value;
|
|
8
|
+
const EXPECTED = "a view, (state, frame) => ReactElement, or a module whose default export is one: { default: view }";
|
|
9
|
+
/** What a `load` resolved to that is no view: said with what was received and what is expected. */
|
|
10
|
+
const NO_VIEW = (resolved) => {
|
|
11
|
+
if (typeof resolved !== "object" || resolved === null) return `@effected/cli-kit/ui: CliUi.lazyView's load resolved to ${kindOf(resolved)}. Expected ${EXPECTED}`;
|
|
12
|
+
const named = Object.keys(resolved).filter((key) => key !== "default");
|
|
13
|
+
const exports = named.length === 0 ? "" : ` (it exports ${named.join(", ")})`;
|
|
14
|
+
return `@effected/cli-kit/ui: CliUi.lazyView's load resolved to ${Object.hasOwn(resolved, "default") ? `a module whose default export is ${kindOf(resolved.default)}, not a function${exports}; a CommonJS module imported as ESM nests it one level deeper, as default.default` : `a module with no default export${exports}; resolve to the export itself, as .then((module) => module.name)`}. Expected ${EXPECTED}`;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* A load that resolved to no view: deterministic, so a lazy view keeps it (one error object for the handle's life) and
|
|
18
|
+
* the live view warns about it once, where a failed import is tried again by the next run.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
var LazyViewShapeError = class extends Error {};
|
|
23
|
+
/** The view `load` resolved to: the value itself when it is a function (a `default` property on it is ignored), else
|
|
24
|
+
* its `default` when that is a function; anything else throws, saying what it got. */
|
|
25
|
+
const pick = (resolved) => {
|
|
26
|
+
if (typeof resolved === "function") return resolved;
|
|
27
|
+
if (typeof resolved === "object" && resolved !== null) {
|
|
28
|
+
const fallback = resolved.default;
|
|
29
|
+
if (typeof fallback === "function") return fallback;
|
|
30
|
+
}
|
|
31
|
+
throw new LazyViewShapeError(NO_VIEW(resolved));
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* `CliUi.lazyView`: a `render` that draws with what `load` resolves to, loaded on first use: the render itself, or a
|
|
35
|
+
* module whose default export it is. One load is shared: an import that rejected is cleared, so the next run loads
|
|
36
|
+
* again; a load that resolved to no view is kept, a `LazyViewShapeError` every later run gets as is. Calling the render
|
|
37
|
+
* before it has loaded is a defect, since only `CliUi.live` knows to load it first.
|
|
38
|
+
*
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
const lazyView = (load) => {
|
|
42
|
+
let loaded;
|
|
43
|
+
let pending;
|
|
44
|
+
const ensure = () => {
|
|
45
|
+
pending ??= load().then((resolved) => {
|
|
46
|
+
loaded = pick(resolved);
|
|
47
|
+
}, (error) => {
|
|
48
|
+
pending = void 0;
|
|
49
|
+
throw error;
|
|
50
|
+
});
|
|
51
|
+
return pending;
|
|
52
|
+
};
|
|
53
|
+
const render = (state, frame) => {
|
|
54
|
+
if (loaded === void 0) throw new Error(NOT_LOADED);
|
|
55
|
+
return loaded(state, frame);
|
|
56
|
+
};
|
|
57
|
+
return Object.assign(render, { [LOAD]: ensure });
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Load a lazy view's module before its render is first called; nothing for a render that is not lazy. Fails with what
|
|
61
|
+
* the import failed with.
|
|
62
|
+
*
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
const loadView = (render) => {
|
|
66
|
+
const ensure = render[LOAD];
|
|
67
|
+
return ensure === void 0 ? Effect.void : Effect.asVoid(Effect.tryPromise({
|
|
68
|
+
try: ensure,
|
|
69
|
+
catch: (error) => error
|
|
70
|
+
}));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export { LazyViewShapeError, lazyView, loadView };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { isEscapeOnly } from "../../internal/displayWidth.js";
|
|
2
|
+
|
|
3
|
+
// src/ui/internal/lineRouter.ts
|
|
4
|
+
/** The text a printer is handed for one line: a CRLF's `\r` dropped, and under `last` only what the line ends on. */
|
|
5
|
+
const printable = (line, carriageReturn) => {
|
|
6
|
+
const text = line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
7
|
+
if (carriageReturn === "keep") return text;
|
|
8
|
+
const cut = text.lastIndexOf("\r");
|
|
9
|
+
return cut === -1 ? text : text.slice(cut + 1);
|
|
10
|
+
};
|
|
11
|
+
/** @internal */
|
|
12
|
+
const makeLineRouter = (options) => {
|
|
13
|
+
const decoder = new TextDecoder("utf-8");
|
|
14
|
+
let held = "";
|
|
15
|
+
let routing = true;
|
|
16
|
+
const offer = (line) => {
|
|
17
|
+
if (!options.printer(options.stream, printable(line, options.carriageReturn))) options.write(`${line}\n`);
|
|
18
|
+
};
|
|
19
|
+
const route = (text) => {
|
|
20
|
+
if (text === "") return;
|
|
21
|
+
if (!routing) {
|
|
22
|
+
options.write(text);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (held === "" && isEscapeOnly(text)) {
|
|
26
|
+
options.write(text);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!text.includes("\n")) {
|
|
30
|
+
held += text;
|
|
31
|
+
if (held.length > options.maxHeld) {
|
|
32
|
+
const line = held;
|
|
33
|
+
held = "";
|
|
34
|
+
offer(line);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const lines = (held + text).split("\n");
|
|
39
|
+
const rest = lines.pop() ?? "";
|
|
40
|
+
if (rest.length > options.maxHeld) {
|
|
41
|
+
lines.push(rest);
|
|
42
|
+
held = "";
|
|
43
|
+
} else held = rest;
|
|
44
|
+
for (const line of lines) offer(line);
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
take: (chunk) => {
|
|
48
|
+
const text = typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
|
|
49
|
+
if (text !== "") options.onText?.(text);
|
|
50
|
+
route(text);
|
|
51
|
+
},
|
|
52
|
+
route: (on) => {
|
|
53
|
+
if (!on && held !== "") {
|
|
54
|
+
options.write(held);
|
|
55
|
+
held = "";
|
|
56
|
+
}
|
|
57
|
+
routing = on;
|
|
58
|
+
},
|
|
59
|
+
flush: () => {
|
|
60
|
+
const pending = decoder.decode();
|
|
61
|
+
if (pending !== "") options.onText?.(pending);
|
|
62
|
+
const text = held + pending;
|
|
63
|
+
held = "";
|
|
64
|
+
if (text === "") return;
|
|
65
|
+
if (!routing || !options.printer(options.stream, printable(text, options.carriageReturn))) options.write(text);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { makeLineRouter };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { sanitize } from "../../Fmt.js";
|
|
2
|
+
|
|
3
|
+
// src/ui/internal/lineText.ts
|
|
4
|
+
/**
|
|
5
|
+
* Consumer text made safe for one row of a widget: sanitised as `Fmt.sanitize` does (no escape sequence, no other
|
|
6
|
+
* control character), with each line break (CR, LF or CR LF) folded to a space.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* Every string a kit widget draws from data goes through it before it is measured or cut. Ink keeps SGR and OSC
|
|
10
|
+
* sequences it is handed, so unsanitised text would paint colour at colour `none` and could plant a hyperlink whose
|
|
11
|
+
* target differs from its label; and a widget's row budget counts one row per line, so a second line would push the
|
|
12
|
+
* frame past the terminal, where Ink wipes the screen and its scrollback.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
const lineText = (text) => sanitize(text).replace(/\r\n|\r|\n/g, " ");
|
|
17
|
+
|
|
18
|
+
export { lineText };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Semaphore } from "effect";
|
|
2
|
+
|
|
3
|
+
// src/ui/internal/mountPermit.ts
|
|
4
|
+
/**
|
|
5
|
+
* One Ink mount at a time, process-wide: a `CliUi.run` screen, or one run of a live view.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Ink keys its instances by stdout and owns raw mode on the one terminal, so concurrent mounts are meaningless, and
|
|
9
|
+
* serializing them keeps each mount's save-and-restore of Ink's colour level well nested.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
const mountPermit = Semaphore.makeUnsafe(1);
|
|
14
|
+
|
|
15
|
+
export { mountPermit };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/ui/internal/processStreams.ts
|
|
2
|
+
/**
|
|
3
|
+
* The process's own standard streams, the default `UiStreams`.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* One of the three files licensed to touch Node: it reads
|
|
7
|
+
* `process.stdin`, `process.stdout` and `process.stderr` and nothing else, and only when called, never at import.
|
|
8
|
+
* The boundary test holds that licence exact.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
const processStreams = () => ({
|
|
13
|
+
stdin: process.stdin,
|
|
14
|
+
stdout: process.stdout,
|
|
15
|
+
stderr: process.stderr
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export { processStreams };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
|
|
3
|
+
// src/ui/internal/renderOptions.ts
|
|
4
|
+
/**
|
|
5
|
+
* The render-option overrides in force: none by default. Internal, so `CliUi.run`'s public signature stays as
|
|
6
|
+
* specified; `CliUiTest` sets it.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
var UiRenderOptions = class extends Context.Reference("@effected/cli-kit/ui/UiRenderOptions", { defaultValue: () => ({}) }) {};
|
|
11
|
+
|
|
12
|
+
export { UiRenderOptions };
|