const { ttySetMode, isatty, getWindowSize: _getWindowSize } = $lazy("tty"); function ReadStream(fd) { if (!(this instanceof ReadStream)) return new ReadStream(fd); if (fd >> 0 !== fd || fd < 0) throw new RangeError("fd must be a positive integer"); const stream = require("node:fs").ReadStream.call(this, "", { fd, }); stream.isRaw = false; stream.isTTY = isatty(stream.fd); return stream; } Object.defineProperty(ReadStream, "prototype", { get() { const Real = require("node:fs").ReadStream.prototype; Object.defineProperty(ReadStream, "prototype", { value: Real }); ReadStream.prototype.setRawMode = function (flag) { const mode = flag ? 1 : 0; const err = ttySetMode(this.fd, mode); if (err) { this.emit("error", new Error("setRawMode failed with errno:", err)); return this; } this.isRaw = flag; return this; }; return Real; }, enumerable: true, configurable: true, }); let OSRelease; const COLORS_2 = 1; const COLORS_16 = 4; const COLORS_256 = 8; const COLORS_16m = 24; // Some entries were taken from `dircolors` // (https://linux.die.net/man/1/dircolors). The corresponding terminals might // support more than 16 colors, but this was not tested for. // // Copyright (C) 1996-2016 Free Software Foundation, Inc. Copying and // distribution of this file, with or without modification, are permitted // provided the copyright notice and this notice are preserved. const TERM_ENVS = { "eterm": COLORS_16, "cons25": COLORS_16, "console": COLORS_16, "cygwin": COLORS_16, "dtterm": COLORS_16, "gnome": COLORS_16, "hurd": COLORS_16, "jfbterm": COLORS_16, "konsole": COLORS_16, "kterm": COLORS_16, "mlterm": COLORS_16, "mosh": COLORS_16m, "putty": COLORS_16, "st": COLORS_16, // https://github.com/da-x/rxvt-unicode/tree/v9.22-with-24bit-color "rxvt-unicode-24bit": COLORS_16m, // https://gist.github.com/XVilka/8346728#gistcomment-2823421 "terminator": COLORS_16m, }; const TERM_ENVS_REG_EXP = [/ansi/, /color/, /linux/, /^con[0-9]*x[0-9]/, /^rxvt/, /^screen/, /^xterm/, /^vt100/]; let warned = false; function warnOnDeactivatedColors(env) { if (warned) return; let name = ""; if (env.NODE_DISABLE_COLORS !== undefined) name = "NODE_DISABLE_COLORS"; if (env.NO_COLOR !== undefined) { if (name !== "") { name += "' and '"; } name += "NO_COLOR"; } if (name !== "") { process.emitWarning(`The '${name}' env is ignored due to the 'FORCE_COLOR' env being set.`, "Warning"); warned = true; } } function WriteStream(fd) { if (!(this instanceof WriteStream)) return new WriteStream(fd); if (fd >> 0 !== fd || fd < 0) throw new RangeError("fd must be a positive integer"); const stream = require("node:fs").WriteStream.call(this, "", { fd, }); stream.columns = undefined; stream.rows = undefined; stream.isTTY = isatty(stream.fd); if (stream.isTTY) { const windowSizeArray = [0, 0]; if (_getWindowSize(fd, windowSizeArray) === true) { stream.columns = windowSizeArray[0]; stream.rows = windowSizeArray[1]; } } return stream; } Object.defineProperty(WriteStream, "prototype", { get() { const Real = require("node:fs").WriteStream.prototype; Object.defineProperty(WriteStream, "prototype", { value: Real }); WriteStream.prototype._refreshSize = function () { const oldCols = this.columns; const oldRows = this.rows; const windowSizeArray = [0, 0]; if (_getWindowSize(this.fd, windowSizeArray) === true) { if (oldCols !== windowSizeArray[0] || oldRows !== windowSizeArray[1]) { this.columns = windowSizeArray[0]; this.rows = windowSizeArray[1]; this.emit("resize"); } } }; var readline = undefined; WriteStream.prototype.clearLine = function (dir, cb) { return (readline ??= require("node:readline")).clearLine(this, dir, cb); }; WriteStream.prototype.clearScreenDown = function (cb) { return (readline ??= require("node:readline")).clearScreenDown(this, cb); }; WriteStream.prototype.cursorTo = function (x, y, cb) { return (readline ??= require("node:readline")).cursorTo(this, x, y, cb); }; // The `getColorDepth` API got inspired by multiple sources such as // https://github.com/chalk/supports-color, // https://github.com/isaacs/color-support. WriteStream.prototype.getColorDepth = function (env = process.env) { // Use level 0-3 to support the same levels as `chalk` does. This is done for // consistency throughout the ecosystem. if (env.FORCE_COLOR !== undefined) { switch (env.FORCE_COLOR) { case "": case "1": case "true": warnOnDeactivatedColors(env); return COLORS_16; case "2": warnOnDeactivatedColors(env); return COLORS_256; case "3": warnOnDeactivatedColors(env); return COLORS_16m; default: return COLORS_2; } } if ( env.NODE_DISABLE_COLORS !== undefined || // See https://no-color.org/ env.NO_COLOR !== undefined || // The "dumb" special terminal, as defined by terminfo, doesn't support // ANSI color control codes. // See https://invisible-island.net/ncurses/terminfo.ti.html#toc-_Specials env.TERM === "dumb" ) { return COLORS_2; } if (process.platform === "win32") { // Lazy load for startup performance. if (OSRelease === undefined) { const { release } = require("node:os"); OSRelease = StringPrototypeSplit(release(), "."); } // Windows 10 build 10586 is the first Windows release that supports 256 // colors. Windows 10 build 14931 is the first release that supports // 16m/TrueColor. if (+OSRelease[0] >= 10) { const build = +OSRelease[2]; if (build >= 14931) return COLORS_16m; if (build >= 10586) return COLORS_256; } return COLORS_16; } if (env.TMUX) { return COLORS_256; } if (env.CI) { if ( ["APPVEYOR", "BUILDKITE", "CIRCLECI", "DRONE", "GITHUB_ACTIONS", "GITLAB_CI", "TRAVIS"].some( sign => sign in env, ) || env.CI_NAME === "codeship" ) { return COLORS_256; } return COLORS_2; } if ("TEAMCITY_VERSION" in env) { return RegExpPrototypeExec(/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/, env.TEAMCITY_VERSION) !== null ? COLORS_16 : COLORS_2; } switch (env.TERM_PROGRAM) { case "iTerm.app": if (!env.TERM_PROGRAM_VERSION || RegExpPrototypeExec(/^[0-2]\./, env.TERM_PROGRAM_VERSION) !== null) { return COLORS_256; } return COLORS_16m; case "HyperTerm": case "MacTerm": return COLORS_16m; case "Apple_Terminal": return COLORS_256; } if (env.COLORTERM === "truecolor" || env.COLORTERM === "24bit") { return COLORS_16m; } if (env.TERM) { if (RegExpPrototypeExec(/^xterm-256/, env.TERM) !== null) { return COLORS_256; } const termEnv = StringPrototypeToLowerCase(env.TERM); if (TERM_ENVS[termEnv]) { return TERM_ENVS[termEnv]; } if (ArrayPrototypeSome(TERM_ENVS_REG_EXP, term => RegExpPrototypeExec(term, termEnv) !== null)) { return COLORS_16; } } // Move 16 color COLORTERM below 16m and 256 if (env.COLORTERM) { return COLORS_16; } return COLORS_2; }; WriteStream.prototype.getWindowSize = function () { return [this.columns, this.rows]; }; WriteStream.prototype.hasColors = function (count, env) { if (env === undefined && (count === undefined || (typeof count === "object" && count !== null))) { env = count; count = 16; } else { validateInteger(count, "count", 2); } return count <= 2 ** this.getColorDepth(env); }; WriteStream.prototype.moveCursor = function (dx, dy, cb) { return (readline ??= require("node:readline")).moveCursor(this, dx, dy, cb); }; return Real; }, enumerable: true, configurable: true, }); var validateInteger = (value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) => { if (typeof value !== "number") throw new ERR_INVALID_ARG_TYPE(name, "number", value); if (!Number.isInteger(value)) throw new ERR_OUT_OF_RANGE(name, "an integer", value); if (value < min || value > max) throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value); }; export default { ReadStream, WriteStream, isatty };