@meadown/logger 1.8.9 → 1.8.10
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/dist/cjs/core/createLog.js +2 -2
- package/dist/cjs/core/writeLog/formatLocation.d.ts +6 -0
- package/dist/cjs/core/writeLog/formatLocation.js +19 -0
- package/dist/cjs/core/{writeLog.d.ts → writeLog/index.d.ts} +3 -6
- package/dist/cjs/core/writeLog/index.js +48 -0
- package/dist/cjs/core/writeLog/renderMessage.d.ts +7 -0
- package/dist/cjs/core/writeLog/renderMessage.js +40 -0
- package/dist/cjs/core/writeLog/visibleLines.d.ts +6 -0
- package/dist/cjs/core/writeLog/visibleLines.js +22 -0
- package/dist/cjs/decorations/link.d.ts +2 -6
- package/dist/cjs/decorations/link.js +3 -8
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/tap/createTap.js +2 -2
- package/dist/cjs/tap/tapAsync.js +6 -6
- package/dist/core/createLog.js +1 -1
- package/dist/core/writeLog/formatLocation.d.ts +6 -0
- package/dist/core/writeLog/formatLocation.js +16 -0
- package/dist/core/{writeLog.d.ts → writeLog/index.d.ts} +3 -6
- package/dist/core/writeLog/index.js +39 -0
- package/dist/core/writeLog/renderMessage.d.ts +7 -0
- package/dist/core/writeLog/renderMessage.js +37 -0
- package/dist/core/writeLog/visibleLines.d.ts +6 -0
- package/dist/core/writeLog/visibleLines.js +17 -0
- package/dist/decorations/link.d.ts +2 -6
- package/dist/decorations/link.js +3 -8
- package/dist/index.js +1 -1
- package/dist/tap/createTap.js +1 -1
- package/dist/tap/tapAsync.js +1 -1
- package/package.json +1 -1
- package/dist/cjs/core/writeLog.js +0 -92
- package/dist/core/writeLog.js +0 -84
|
@@ -11,7 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.default = createLog;
|
|
13
13
|
const getCaller_js_1 = __importDefault(require("../caller/getCaller.js"));
|
|
14
|
-
const
|
|
14
|
+
const index_js_1 = require("./writeLog/index.js");
|
|
15
15
|
const config_js_1 = require("../config.js");
|
|
16
16
|
/**
|
|
17
17
|
* Builds a log function bound to a console channel and tag. The returned closure
|
|
@@ -24,6 +24,6 @@ function createLog(channel, tag) {
|
|
|
24
24
|
if (!(0, config_js_1.isLogAllowed)())
|
|
25
25
|
return;
|
|
26
26
|
const caller = (0, getCaller_js_1.default)();
|
|
27
|
-
(0,
|
|
27
|
+
(0, index_js_1.writeLog)({ channel, tag, args, caller });
|
|
28
28
|
};
|
|
29
29
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Caller } from "../../caller/getCaller.js";
|
|
2
|
+
/**
|
|
3
|
+
* Renders a caller as a `(file:line)` location — a clickable OSC-8 link on a
|
|
4
|
+
* supporting terminal, plain text otherwise. Pure (no stack access).
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatLocation(caller: Caller, interactive: boolean): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* formatLocation.ts
|
|
4
|
+
* Created by Dewan Mobashirul
|
|
5
|
+
* Copyright (c) 2026 dewan-meadown
|
|
6
|
+
* All rights reserved
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.formatLocation = formatLocation;
|
|
10
|
+
const link_js_1 = require("../../decorations/link.js");
|
|
11
|
+
/**
|
|
12
|
+
* Renders a caller as a `(file:line)` location — a clickable OSC-8 link on a
|
|
13
|
+
* supporting terminal, plain text otherwise. Pure (no stack access).
|
|
14
|
+
*/
|
|
15
|
+
function formatLocation(caller, interactive) {
|
|
16
|
+
if (caller.file !== null && caller.line !== null && interactive)
|
|
17
|
+
return (0, link_js_1.hyperlink)(caller.label, (0, link_js_1.fileUrl)(caller.file));
|
|
18
|
+
return caller.label;
|
|
19
|
+
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { type LogChannel } from "
|
|
2
|
-
import { type Caller } from "
|
|
3
|
-
|
|
4
|
-
export declare function getVisibleLines(): number;
|
|
5
|
-
/** Set how many lines a long message shows before collapsing (0 = all). */
|
|
6
|
-
export declare function setVisibleLines(value: number): void;
|
|
1
|
+
import { type LogChannel } from "../../constants.js";
|
|
2
|
+
import { type Caller } from "../../caller/getCaller.js";
|
|
3
|
+
export { getVisibleLines, setVisibleLines } from "./visibleLines.js";
|
|
7
4
|
/**
|
|
8
5
|
* Renders and writes one log entry. The `caller` is resolved by the *caller* of
|
|
9
6
|
* this function (the log closure or `tap`) and passed in, so this helper never
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* index.ts
|
|
4
|
+
* Created by Dewan Mobashirul
|
|
5
|
+
* Copyright (c) 2026 dewan-meadown
|
|
6
|
+
* All rights reserved
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.setVisibleLines = exports.getVisibleLines = void 0;
|
|
13
|
+
exports.writeLog = writeLog;
|
|
14
|
+
const constants_js_1 = require("../../constants.js");
|
|
15
|
+
const getTimeStamp_js_1 = __importDefault(require("../../time/getTimeStamp.js"));
|
|
16
|
+
const color_js_1 = require("../../colors/color.js");
|
|
17
|
+
const isTTY_js_1 = require("../../terminal/isTTY.js");
|
|
18
|
+
const renderMessage_js_1 = require("./renderMessage.js");
|
|
19
|
+
const formatLocation_js_1 = require("./formatLocation.js");
|
|
20
|
+
var visibleLines_js_1 = require("./visibleLines.js");
|
|
21
|
+
Object.defineProperty(exports, "getVisibleLines", { enumerable: true, get: function () { return visibleLines_js_1.getVisibleLines; } });
|
|
22
|
+
Object.defineProperty(exports, "setVisibleLines", { enumerable: true, get: function () { return visibleLines_js_1.setVisibleLines; } });
|
|
23
|
+
/**
|
|
24
|
+
* Renders and writes one log entry. The `caller` is resolved by the *caller* of
|
|
25
|
+
* this function (the log closure or `tap`) and passed in, so this helper never
|
|
26
|
+
* touches the stack — keeping {@link getCaller}'s frame depth correct no matter
|
|
27
|
+
* which user-facing function delegates here.
|
|
28
|
+
*/
|
|
29
|
+
function writeLog(opts) {
|
|
30
|
+
const { channel, tag, args, caller } = opts;
|
|
31
|
+
const streamName = channel === "log" ? "stdout" : "stderr";
|
|
32
|
+
// One terminal check drives both color and clickable links — `isTTY` is the
|
|
33
|
+
// single source of truth (DRY). Off when output is piped/redirected.
|
|
34
|
+
const useColor = (0, isTTY_js_1.isTTY)(streamName);
|
|
35
|
+
const paint = (s, c) => useColor ? (0, color_js_1.colorize)(s, c) : s;
|
|
36
|
+
const location = (0, formatLocation_js_1.formatLocation)(caller, useColor);
|
|
37
|
+
const tagOut = paint(tag, constants_js_1.TAG_COLOR[channel]);
|
|
38
|
+
const timeStamp = paint((0, getTimeStamp_js_1.default)(), "teal");
|
|
39
|
+
const locOut = paint(`(${location})`, "dimTeal");
|
|
40
|
+
const connector = paint(constants_js_1.BRANCH, "gray");
|
|
41
|
+
const connectorBottom = paint(constants_js_1.BRANCH_END, "gray");
|
|
42
|
+
const separator = paint(constants_js_1.SEPARATOR, "gray");
|
|
43
|
+
// Layout: the tag, the message hanging off a `├──` branch, then the timestamp
|
|
44
|
+
// and location on a `└──` branch below. Leading `\n` spaces entries apart.
|
|
45
|
+
const message = (0, renderMessage_js_1.renderMessage)(args, useColor);
|
|
46
|
+
const meta = `\n${connectorBottom} ${timeStamp} ${separator} ${locOut}`;
|
|
47
|
+
console[channel](`\n${tagOut}`, `\n${connector}`, message, meta);
|
|
48
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders the args into a single message string exactly as console would —
|
|
3
|
+
* objects/errors via util.inspect, `%s`/`%d` format specifiers, and colors when
|
|
4
|
+
* on a terminal — then hang-indents every continuation line so multi-line
|
|
5
|
+
* output stays left-aligned under the branch, and collapses very long output.
|
|
6
|
+
*/
|
|
7
|
+
export declare function renderMessage(args: unknown[], useColor: boolean): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* renderMessage.ts
|
|
4
|
+
* Created by Dewan Mobashirul
|
|
5
|
+
* Copyright (c) 2026 dewan-meadown
|
|
6
|
+
* All rights reserved
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.renderMessage = renderMessage;
|
|
10
|
+
const node_util_1 = require("node:util");
|
|
11
|
+
const constants_js_1 = require("../../constants.js");
|
|
12
|
+
const color_js_1 = require("../../colors/color.js");
|
|
13
|
+
const visibleLines_js_1 = require("./visibleLines.js");
|
|
14
|
+
/**
|
|
15
|
+
* Collapses a long multi-line message to {@link visibleLines} lines, replacing
|
|
16
|
+
* the rest with a dimmed `… N more lines` summary. When `visibleLines` is 0
|
|
17
|
+
* (the default) nothing is collapsed — the full message is shown.
|
|
18
|
+
*/
|
|
19
|
+
function collapse(text, useColor) {
|
|
20
|
+
if (visibleLines_js_1.visibleLines < 1)
|
|
21
|
+
return text;
|
|
22
|
+
const lines = text.split("\n");
|
|
23
|
+
if (lines.length <= visibleLines_js_1.visibleLines)
|
|
24
|
+
return text;
|
|
25
|
+
const hidden = lines.length - visibleLines_js_1.visibleLines;
|
|
26
|
+
const summary = `${constants_js_1.MESSAGE_INDENT}... ${hidden} more line${hidden === 1 ? "" : "s"}`;
|
|
27
|
+
const visible = lines.slice(0, visibleLines_js_1.visibleLines);
|
|
28
|
+
visible.push(useColor ? (0, color_js_1.colorize)(summary, "gray") : summary);
|
|
29
|
+
return visible.join("\n");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Renders the args into a single message string exactly as console would —
|
|
33
|
+
* objects/errors via util.inspect, `%s`/`%d` format specifiers, and colors when
|
|
34
|
+
* on a terminal — then hang-indents every continuation line so multi-line
|
|
35
|
+
* output stays left-aligned under the branch, and collapses very long output.
|
|
36
|
+
*/
|
|
37
|
+
function renderMessage(args, useColor) {
|
|
38
|
+
const text = (0, node_util_1.formatWithOptions)({ colors: useColor }, ...args);
|
|
39
|
+
return collapse(text.replace(/\n/g, `\n${(0, color_js_1.colorize)(constants_js_1.MESSAGE_INDENT, "gray")}`), useColor);
|
|
40
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Max message lines to show before collapsing the rest; 0 (default) shows all. */
|
|
2
|
+
export declare let visibleLines: number;
|
|
3
|
+
/** How many lines a long message shows before collapsing (0 = all). */
|
|
4
|
+
export declare function getVisibleLines(): number;
|
|
5
|
+
/** Set how many lines a long message shows before collapsing (0 = all). */
|
|
6
|
+
export declare function setVisibleLines(value: number): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* visibleLines.ts
|
|
4
|
+
* Created by Dewan Mobashirul
|
|
5
|
+
* Copyright (c) 2026 dewan-meadown
|
|
6
|
+
* All rights reserved
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.visibleLines = void 0;
|
|
10
|
+
exports.getVisibleLines = getVisibleLines;
|
|
11
|
+
exports.setVisibleLines = setVisibleLines;
|
|
12
|
+
const constants_js_1 = require("../../constants.js");
|
|
13
|
+
/** Max message lines to show before collapsing the rest; 0 (default) shows all. */
|
|
14
|
+
exports.visibleLines = constants_js_1.DEFAULT_MAX_LINES;
|
|
15
|
+
/** How many lines a long message shows before collapsing (0 = all). */
|
|
16
|
+
function getVisibleLines() {
|
|
17
|
+
return exports.visibleLines;
|
|
18
|
+
}
|
|
19
|
+
/** Set how many lines a long message shows before collapsing (0 = all). */
|
|
20
|
+
function setVisibleLines(value) {
|
|
21
|
+
exports.visibleLines = Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
22
|
+
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
* When `line` is provided, appends `:line` so supporting terminals (VS Code,
|
|
4
|
-
* iTerm2, WezTerm) jump straight to that line.
|
|
5
|
-
*/
|
|
6
|
-
export declare function fileUrl(file: string, line?: number): string;
|
|
1
|
+
/** Builds a `file://` URL for a path so terminals can open it on click. */
|
|
2
|
+
export declare function fileUrl(file: string): string;
|
|
7
3
|
/**
|
|
8
4
|
* Wraps `text` in an OSC-8 terminal hyperlink pointing at `url`. Terminals that
|
|
9
5
|
* support OSC-8 render `text` as a clickable link; others ignore the escape and
|
|
@@ -9,14 +9,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.fileUrl = fileUrl;
|
|
10
10
|
exports.hyperlink = hyperlink;
|
|
11
11
|
const node_url_1 = require("node:url");
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* iTerm2, WezTerm) jump straight to that line.
|
|
16
|
-
*/
|
|
17
|
-
function fileUrl(file, line) {
|
|
18
|
-
const base = file.startsWith("file://") ? file : (0, node_url_1.pathToFileURL)(file).href;
|
|
19
|
-
return line != null ? `${base}:${line}` : base;
|
|
12
|
+
/** Builds a `file://` URL for a path so terminals can open it on click. */
|
|
13
|
+
function fileUrl(file) {
|
|
14
|
+
return file.startsWith("file://") ? file : (0, node_url_1.pathToFileURL)(file).href;
|
|
20
15
|
}
|
|
21
16
|
/**
|
|
22
17
|
* Wraps `text` in an OSC-8 terminal hyperlink pointing at `url`. Terminals that
|
package/dist/cjs/index.js
CHANGED
|
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.logger = void 0;
|
|
13
13
|
const createLog_js_1 = __importDefault(require("./core/createLog.js"));
|
|
14
14
|
const createTap_js_1 = __importDefault(require("./tap/createTap.js"));
|
|
15
|
-
const
|
|
15
|
+
const index_js_1 = require("./core/writeLog/index.js");
|
|
16
16
|
/**
|
|
17
17
|
* Logs to the console, but only outside production. Each line is prefixed with
|
|
18
18
|
* a level tag, a short local timestamp, and a clickable link to the file it was
|
|
@@ -32,8 +32,8 @@ exports.logger = logger;
|
|
|
32
32
|
// `maxLines` is a live getter/setter backed by the shared collapse setting, so
|
|
33
33
|
// setting it once affects info, error, and warn alike.
|
|
34
34
|
Object.defineProperty(logger, "maxLines", {
|
|
35
|
-
get:
|
|
36
|
-
set:
|
|
35
|
+
get: index_js_1.getVisibleLines,
|
|
36
|
+
set: index_js_1.setVisibleLines,
|
|
37
37
|
enumerable: true,
|
|
38
38
|
configurable: true,
|
|
39
39
|
});
|
|
@@ -11,7 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.default = createTap;
|
|
13
13
|
const getCaller_js_1 = __importDefault(require("../caller/getCaller.js"));
|
|
14
|
-
const
|
|
14
|
+
const index_js_1 = require("../core/writeLog/index.js");
|
|
15
15
|
const config_js_1 = require("../config.js");
|
|
16
16
|
const tapAsync_js_1 = require("./tapAsync.js");
|
|
17
17
|
/**
|
|
@@ -38,7 +38,7 @@ function createTap() {
|
|
|
38
38
|
(0, tapAsync_js_1.tapAsync)(value, label, caller);
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
|
-
(0,
|
|
41
|
+
(0, index_js_1.writeLog)({
|
|
42
42
|
channel: "log",
|
|
43
43
|
tag: "[TAP]",
|
|
44
44
|
args: label === undefined ? [value] : [label, value],
|
package/dist/cjs/tap/tapAsync.js
CHANGED
|
@@ -14,7 +14,7 @@ exports.isThenable = isThenable;
|
|
|
14
14
|
exports.tapAsync = tapAsync;
|
|
15
15
|
const node_perf_hooks_1 = require("node:perf_hooks");
|
|
16
16
|
const node_util_1 = require("node:util");
|
|
17
|
-
const
|
|
17
|
+
const index_js_1 = require("../core/writeLog/index.js");
|
|
18
18
|
const color_js_1 = require("../colors/color.js");
|
|
19
19
|
const isTTY_js_1 = require("../terminal/isTTY.js");
|
|
20
20
|
/** Whether `value` is thenable (a promise we can await + time). */
|
|
@@ -151,7 +151,7 @@ function tapAsync(promise, label, caller) {
|
|
|
151
151
|
clone = null;
|
|
152
152
|
}
|
|
153
153
|
if (clone === null) {
|
|
154
|
-
(0,
|
|
154
|
+
(0, index_js_1.writeLog)({
|
|
155
155
|
channel: "log", tag: "[TAP]",
|
|
156
156
|
args: buildBlock(label, ms, resolved, { data: undefined, size: "unknown" }, useColor),
|
|
157
157
|
caller,
|
|
@@ -161,7 +161,7 @@ function tapAsync(promise, label, caller) {
|
|
|
161
161
|
const cl = resolved.headers?.get?.("content-length");
|
|
162
162
|
const tooLarge = cl != null && cl !== "" && Number(cl) > 512 * 1024;
|
|
163
163
|
if (tooLarge) {
|
|
164
|
-
(0,
|
|
164
|
+
(0, index_js_1.writeLog)({
|
|
165
165
|
channel: "log", tag: "[TAP]",
|
|
166
166
|
args: buildBlock(label, ms, resolved, { data: "(body too large to display)", size: formatBytes(Number(cl)) }, useColor),
|
|
167
167
|
caller,
|
|
@@ -169,13 +169,13 @@ function tapAsync(promise, label, caller) {
|
|
|
169
169
|
return;
|
|
170
170
|
}
|
|
171
171
|
void readBody(clone).then((body) => {
|
|
172
|
-
(0,
|
|
172
|
+
(0, index_js_1.writeLog)({ channel: "log", tag: "[TAP]", args: buildBlock(label, ms, resolved, body, useColor), caller });
|
|
173
173
|
});
|
|
174
174
|
return;
|
|
175
175
|
}
|
|
176
176
|
// Non-Response promise — plain value with elapsed time.
|
|
177
177
|
const elapsed = formatDuration(ms, useColor);
|
|
178
|
-
(0,
|
|
178
|
+
(0, index_js_1.writeLog)({
|
|
179
179
|
channel: "log", tag: "[TAP]",
|
|
180
180
|
args: label === undefined ? [elapsed, resolved] : [`${label} ${elapsed}`, resolved],
|
|
181
181
|
caller,
|
|
@@ -183,7 +183,7 @@ function tapAsync(promise, label, caller) {
|
|
|
183
183
|
}, (err) => {
|
|
184
184
|
const ms = Math.round(node_perf_hooks_1.performance.now() - start);
|
|
185
185
|
const elapsed = formatDuration(ms, useColor);
|
|
186
|
-
(0,
|
|
186
|
+
(0, index_js_1.writeLog)({
|
|
187
187
|
channel: "error", tag: "[TAP]",
|
|
188
188
|
args: [label === undefined ? `rejected after ${elapsed}` : `${label} rejected after ${elapsed}`, err],
|
|
189
189
|
caller,
|
package/dist/core/createLog.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* All rights reserved
|
|
6
6
|
*/
|
|
7
7
|
import getCaller from "../caller/getCaller.js";
|
|
8
|
-
import { writeLog } from "./writeLog.js";
|
|
8
|
+
import { writeLog } from "./writeLog/index.js";
|
|
9
9
|
import { isLogAllowed } from "../config.js";
|
|
10
10
|
/**
|
|
11
11
|
* Builds a log function bound to a console channel and tag. The returned closure
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Caller } from "../../caller/getCaller.js";
|
|
2
|
+
/**
|
|
3
|
+
* Renders a caller as a `(file:line)` location — a clickable OSC-8 link on a
|
|
4
|
+
* supporting terminal, plain text otherwise. Pure (no stack access).
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatLocation(caller: Caller, interactive: boolean): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* formatLocation.ts
|
|
3
|
+
* Created by Dewan Mobashirul
|
|
4
|
+
* Copyright (c) 2026 dewan-meadown
|
|
5
|
+
* All rights reserved
|
|
6
|
+
*/
|
|
7
|
+
import { fileUrl, hyperlink } from "../../decorations/link.js";
|
|
8
|
+
/**
|
|
9
|
+
* Renders a caller as a `(file:line)` location — a clickable OSC-8 link on a
|
|
10
|
+
* supporting terminal, plain text otherwise. Pure (no stack access).
|
|
11
|
+
*/
|
|
12
|
+
export function formatLocation(caller, interactive) {
|
|
13
|
+
if (caller.file !== null && caller.line !== null && interactive)
|
|
14
|
+
return hyperlink(caller.label, fileUrl(caller.file));
|
|
15
|
+
return caller.label;
|
|
16
|
+
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { type LogChannel } from "
|
|
2
|
-
import { type Caller } from "
|
|
3
|
-
|
|
4
|
-
export declare function getVisibleLines(): number;
|
|
5
|
-
/** Set how many lines a long message shows before collapsing (0 = all). */
|
|
6
|
-
export declare function setVisibleLines(value: number): void;
|
|
1
|
+
import { type LogChannel } from "../../constants.js";
|
|
2
|
+
import { type Caller } from "../../caller/getCaller.js";
|
|
3
|
+
export { getVisibleLines, setVisibleLines } from "./visibleLines.js";
|
|
7
4
|
/**
|
|
8
5
|
* Renders and writes one log entry. The `caller` is resolved by the *caller* of
|
|
9
6
|
* this function (the log closure or `tap`) and passed in, so this helper never
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* index.ts
|
|
3
|
+
* Created by Dewan Mobashirul
|
|
4
|
+
* Copyright (c) 2026 dewan-meadown
|
|
5
|
+
* All rights reserved
|
|
6
|
+
*/
|
|
7
|
+
import { TAG_COLOR, BRANCH, BRANCH_END, SEPARATOR, } from "../../constants.js";
|
|
8
|
+
import getTimeStamp from "../../time/getTimeStamp.js";
|
|
9
|
+
import { colorize } from "../../colors/color.js";
|
|
10
|
+
import { isTTY } from "../../terminal/isTTY.js";
|
|
11
|
+
import { renderMessage } from "./renderMessage.js";
|
|
12
|
+
import { formatLocation } from "./formatLocation.js";
|
|
13
|
+
export { getVisibleLines, setVisibleLines } from "./visibleLines.js";
|
|
14
|
+
/**
|
|
15
|
+
* Renders and writes one log entry. The `caller` is resolved by the *caller* of
|
|
16
|
+
* this function (the log closure or `tap`) and passed in, so this helper never
|
|
17
|
+
* touches the stack — keeping {@link getCaller}'s frame depth correct no matter
|
|
18
|
+
* which user-facing function delegates here.
|
|
19
|
+
*/
|
|
20
|
+
export function writeLog(opts) {
|
|
21
|
+
const { channel, tag, args, caller } = opts;
|
|
22
|
+
const streamName = channel === "log" ? "stdout" : "stderr";
|
|
23
|
+
// One terminal check drives both color and clickable links — `isTTY` is the
|
|
24
|
+
// single source of truth (DRY). Off when output is piped/redirected.
|
|
25
|
+
const useColor = isTTY(streamName);
|
|
26
|
+
const paint = (s, c) => useColor ? colorize(s, c) : s;
|
|
27
|
+
const location = formatLocation(caller, useColor);
|
|
28
|
+
const tagOut = paint(tag, TAG_COLOR[channel]);
|
|
29
|
+
const timeStamp = paint(getTimeStamp(), "teal");
|
|
30
|
+
const locOut = paint(`(${location})`, "dimTeal");
|
|
31
|
+
const connector = paint(BRANCH, "gray");
|
|
32
|
+
const connectorBottom = paint(BRANCH_END, "gray");
|
|
33
|
+
const separator = paint(SEPARATOR, "gray");
|
|
34
|
+
// Layout: the tag, the message hanging off a `├──` branch, then the timestamp
|
|
35
|
+
// and location on a `└──` branch below. Leading `\n` spaces entries apart.
|
|
36
|
+
const message = renderMessage(args, useColor);
|
|
37
|
+
const meta = `\n${connectorBottom} ${timeStamp} ${separator} ${locOut}`;
|
|
38
|
+
console[channel](`\n${tagOut}`, `\n${connector}`, message, meta);
|
|
39
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders the args into a single message string exactly as console would —
|
|
3
|
+
* objects/errors via util.inspect, `%s`/`%d` format specifiers, and colors when
|
|
4
|
+
* on a terminal — then hang-indents every continuation line so multi-line
|
|
5
|
+
* output stays left-aligned under the branch, and collapses very long output.
|
|
6
|
+
*/
|
|
7
|
+
export declare function renderMessage(args: unknown[], useColor: boolean): string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* renderMessage.ts
|
|
3
|
+
* Created by Dewan Mobashirul
|
|
4
|
+
* Copyright (c) 2026 dewan-meadown
|
|
5
|
+
* All rights reserved
|
|
6
|
+
*/
|
|
7
|
+
import { formatWithOptions } from "node:util";
|
|
8
|
+
import { MESSAGE_INDENT } from "../../constants.js";
|
|
9
|
+
import { colorize } from "../../colors/color.js";
|
|
10
|
+
import { visibleLines } from "./visibleLines.js";
|
|
11
|
+
/**
|
|
12
|
+
* Collapses a long multi-line message to {@link visibleLines} lines, replacing
|
|
13
|
+
* the rest with a dimmed `… N more lines` summary. When `visibleLines` is 0
|
|
14
|
+
* (the default) nothing is collapsed — the full message is shown.
|
|
15
|
+
*/
|
|
16
|
+
function collapse(text, useColor) {
|
|
17
|
+
if (visibleLines < 1)
|
|
18
|
+
return text;
|
|
19
|
+
const lines = text.split("\n");
|
|
20
|
+
if (lines.length <= visibleLines)
|
|
21
|
+
return text;
|
|
22
|
+
const hidden = lines.length - visibleLines;
|
|
23
|
+
const summary = `${MESSAGE_INDENT}... ${hidden} more line${hidden === 1 ? "" : "s"}`;
|
|
24
|
+
const visible = lines.slice(0, visibleLines);
|
|
25
|
+
visible.push(useColor ? colorize(summary, "gray") : summary);
|
|
26
|
+
return visible.join("\n");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Renders the args into a single message string exactly as console would —
|
|
30
|
+
* objects/errors via util.inspect, `%s`/`%d` format specifiers, and colors when
|
|
31
|
+
* on a terminal — then hang-indents every continuation line so multi-line
|
|
32
|
+
* output stays left-aligned under the branch, and collapses very long output.
|
|
33
|
+
*/
|
|
34
|
+
export function renderMessage(args, useColor) {
|
|
35
|
+
const text = formatWithOptions({ colors: useColor }, ...args);
|
|
36
|
+
return collapse(text.replace(/\n/g, `\n${colorize(MESSAGE_INDENT, "gray")}`), useColor);
|
|
37
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Max message lines to show before collapsing the rest; 0 (default) shows all. */
|
|
2
|
+
export declare let visibleLines: number;
|
|
3
|
+
/** How many lines a long message shows before collapsing (0 = all). */
|
|
4
|
+
export declare function getVisibleLines(): number;
|
|
5
|
+
/** Set how many lines a long message shows before collapsing (0 = all). */
|
|
6
|
+
export declare function setVisibleLines(value: number): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* visibleLines.ts
|
|
3
|
+
* Created by Dewan Mobashirul
|
|
4
|
+
* Copyright (c) 2026 dewan-meadown
|
|
5
|
+
* All rights reserved
|
|
6
|
+
*/
|
|
7
|
+
import { DEFAULT_MAX_LINES } from "../../constants.js";
|
|
8
|
+
/** Max message lines to show before collapsing the rest; 0 (default) shows all. */
|
|
9
|
+
export let visibleLines = DEFAULT_MAX_LINES;
|
|
10
|
+
/** How many lines a long message shows before collapsing (0 = all). */
|
|
11
|
+
export function getVisibleLines() {
|
|
12
|
+
return visibleLines;
|
|
13
|
+
}
|
|
14
|
+
/** Set how many lines a long message shows before collapsing (0 = all). */
|
|
15
|
+
export function setVisibleLines(value) {
|
|
16
|
+
visibleLines = Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
17
|
+
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
* When `line` is provided, appends `:line` so supporting terminals (VS Code,
|
|
4
|
-
* iTerm2, WezTerm) jump straight to that line.
|
|
5
|
-
*/
|
|
6
|
-
export declare function fileUrl(file: string, line?: number): string;
|
|
1
|
+
/** Builds a `file://` URL for a path so terminals can open it on click. */
|
|
2
|
+
export declare function fileUrl(file: string): string;
|
|
7
3
|
/**
|
|
8
4
|
* Wraps `text` in an OSC-8 terminal hyperlink pointing at `url`. Terminals that
|
|
9
5
|
* support OSC-8 render `text` as a clickable link; others ignore the escape and
|
package/dist/decorations/link.js
CHANGED
|
@@ -5,14 +5,9 @@
|
|
|
5
5
|
* All rights reserved
|
|
6
6
|
*/
|
|
7
7
|
import { pathToFileURL } from "node:url";
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* iTerm2, WezTerm) jump straight to that line.
|
|
12
|
-
*/
|
|
13
|
-
export function fileUrl(file, line) {
|
|
14
|
-
const base = file.startsWith("file://") ? file : pathToFileURL(file).href;
|
|
15
|
-
return line != null ? `${base}:${line}` : base;
|
|
8
|
+
/** Builds a `file://` URL for a path so terminals can open it on click. */
|
|
9
|
+
export function fileUrl(file) {
|
|
10
|
+
return file.startsWith("file://") ? file : pathToFileURL(file).href;
|
|
16
11
|
}
|
|
17
12
|
/**
|
|
18
13
|
* Wraps `text` in an OSC-8 terminal hyperlink pointing at `url`. Terminals that
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import createLog from "./core/createLog.js";
|
|
8
8
|
import createTap from "./tap/createTap.js";
|
|
9
|
-
import { getVisibleLines, setVisibleLines } from "./core/writeLog.js";
|
|
9
|
+
import { getVisibleLines, setVisibleLines } from "./core/writeLog/index.js";
|
|
10
10
|
/**
|
|
11
11
|
* Logs to the console, but only outside production. Each line is prefixed with
|
|
12
12
|
* a level tag, a short local timestamp, and a clickable link to the file it was
|
package/dist/tap/createTap.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* All rights reserved
|
|
6
6
|
*/
|
|
7
7
|
import getCaller from "../caller/getCaller.js";
|
|
8
|
-
import { writeLog } from "../core/writeLog.js";
|
|
8
|
+
import { writeLog } from "../core/writeLog/index.js";
|
|
9
9
|
import { isLogAllowed } from "../config.js";
|
|
10
10
|
import { isThenable, tapAsync } from "./tapAsync.js";
|
|
11
11
|
/**
|
package/dist/tap/tapAsync.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { performance } from "node:perf_hooks";
|
|
12
12
|
import { formatWithOptions } from "node:util";
|
|
13
|
-
import { writeLog } from "../core/writeLog.js";
|
|
13
|
+
import { writeLog } from "../core/writeLog/index.js";
|
|
14
14
|
import { colorize } from "../colors/color.js";
|
|
15
15
|
import { isTTY } from "../terminal/isTTY.js";
|
|
16
16
|
/** Whether `value` is thenable (a promise we can await + time). */
|
package/package.json
CHANGED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* writeLog.ts
|
|
4
|
-
* Created by Dewan Mobashirul
|
|
5
|
-
* Copyright (c) 2026 dewan-meadown
|
|
6
|
-
* All rights reserved
|
|
7
|
-
*/
|
|
8
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.getVisibleLines = getVisibleLines;
|
|
13
|
-
exports.setVisibleLines = setVisibleLines;
|
|
14
|
-
exports.writeLog = writeLog;
|
|
15
|
-
const node_util_1 = require("node:util");
|
|
16
|
-
const constants_js_1 = require("../constants.js");
|
|
17
|
-
const getTimeStamp_js_1 = __importDefault(require("../time/getTimeStamp.js"));
|
|
18
|
-
const link_js_1 = require("../decorations/link.js");
|
|
19
|
-
const color_js_1 = require("../colors/color.js");
|
|
20
|
-
const isTTY_js_1 = require("../terminal/isTTY.js");
|
|
21
|
-
/** Max message lines to show before collapsing the rest; 0 (default) shows all. */
|
|
22
|
-
let visibleLines = constants_js_1.DEFAULT_MAX_LINES;
|
|
23
|
-
/** How many lines a long message shows before collapsing (0 = all). */
|
|
24
|
-
function getVisibleLines() {
|
|
25
|
-
return visibleLines;
|
|
26
|
-
}
|
|
27
|
-
/** Set how many lines a long message shows before collapsing (0 = all). */
|
|
28
|
-
function setVisibleLines(value) {
|
|
29
|
-
visibleLines = Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Collapses a long multi-line message to {@link visibleLines} lines, replacing
|
|
33
|
-
* the rest with a dimmed `… N more lines` summary. When `visibleLines` is 0
|
|
34
|
-
* (the default) nothing is collapsed — the full message is shown.
|
|
35
|
-
*/
|
|
36
|
-
function collapse(text, useColor) {
|
|
37
|
-
if (visibleLines < 1)
|
|
38
|
-
return text;
|
|
39
|
-
const lines = text.split("\n");
|
|
40
|
-
if (lines.length <= visibleLines)
|
|
41
|
-
return text;
|
|
42
|
-
const hidden = lines.length - visibleLines;
|
|
43
|
-
const summary = `${constants_js_1.MESSAGE_INDENT}... ${hidden} more line${hidden === 1 ? "" : "s"}`;
|
|
44
|
-
const visible = lines.slice(0, visibleLines);
|
|
45
|
-
visible.push(useColor ? (0, color_js_1.colorize)(summary, "gray") : summary);
|
|
46
|
-
return visible.join("\n");
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Renders the args into a single message string exactly as console would —
|
|
50
|
-
* objects/errors via util.inspect, `%s`/`%d` format specifiers, and colors when
|
|
51
|
-
* on a terminal — then hang-indents every continuation line so multi-line
|
|
52
|
-
* output stays left-aligned under the branch, and collapses very long output.
|
|
53
|
-
*/
|
|
54
|
-
function renderMessage(args, useColor) {
|
|
55
|
-
const text = (0, node_util_1.formatWithOptions)({ colors: useColor }, ...args);
|
|
56
|
-
return collapse(text.replace(/\n/g, `\n${(0, color_js_1.colorize)(constants_js_1.MESSAGE_INDENT, "gray")}`), useColor);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Renders a caller as a `(file:line)` location — a clickable OSC-8 link on a
|
|
60
|
-
* supporting terminal, plain text otherwise. Pure (no stack access).
|
|
61
|
-
*/
|
|
62
|
-
function formatLocation(caller, interactive) {
|
|
63
|
-
if (caller.file !== null && caller.line !== null && interactive)
|
|
64
|
-
return (0, link_js_1.hyperlink)(caller.label, (0, link_js_1.fileUrl)(caller.file, caller.line));
|
|
65
|
-
return caller.label;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Renders and writes one log entry. The `caller` is resolved by the *caller* of
|
|
69
|
-
* this function (the log closure or `tap`) and passed in, so this helper never
|
|
70
|
-
* touches the stack — keeping {@link getCaller}'s frame depth correct no matter
|
|
71
|
-
* which user-facing function delegates here.
|
|
72
|
-
*/
|
|
73
|
-
function writeLog(opts) {
|
|
74
|
-
const { channel, tag, args, caller } = opts;
|
|
75
|
-
const streamName = channel === "log" ? "stdout" : "stderr";
|
|
76
|
-
// One terminal check drives both color and clickable links — `isTTY` is the
|
|
77
|
-
// single source of truth (DRY). Off when output is piped/redirected.
|
|
78
|
-
const useColor = (0, isTTY_js_1.isTTY)(streamName);
|
|
79
|
-
const paint = (s, c) => useColor ? (0, color_js_1.colorize)(s, c) : s;
|
|
80
|
-
const location = formatLocation(caller, useColor);
|
|
81
|
-
const tagOut = paint(tag, constants_js_1.TAG_COLOR[channel]);
|
|
82
|
-
const timeStamp = paint((0, getTimeStamp_js_1.default)(), "teal");
|
|
83
|
-
const locOut = paint(`(${location})`, "dimTeal");
|
|
84
|
-
const connector = paint(constants_js_1.BRANCH, "gray");
|
|
85
|
-
const connectorBottom = paint(constants_js_1.BRANCH_END, "gray");
|
|
86
|
-
const separator = paint(constants_js_1.SEPARATOR, "gray");
|
|
87
|
-
// Layout: the tag, the message hanging off a `├──` branch, then the timestamp
|
|
88
|
-
// and location on a `└──` branch below. Leading `\n` spaces entries apart.
|
|
89
|
-
const message = renderMessage(args, useColor);
|
|
90
|
-
const meta = `\n${connectorBottom} ${timeStamp} ${separator} ${locOut}`;
|
|
91
|
-
console[channel](`\n${tagOut}`, `\n${connector}`, message, meta);
|
|
92
|
-
}
|
package/dist/core/writeLog.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* writeLog.ts
|
|
3
|
-
* Created by Dewan Mobashirul
|
|
4
|
-
* Copyright (c) 2026 dewan-meadown
|
|
5
|
-
* All rights reserved
|
|
6
|
-
*/
|
|
7
|
-
import { formatWithOptions } from "node:util";
|
|
8
|
-
import { TAG_COLOR, BRANCH, BRANCH_END, SEPARATOR, MESSAGE_INDENT, DEFAULT_MAX_LINES, } from "../constants.js";
|
|
9
|
-
import getTimeStamp from "../time/getTimeStamp.js";
|
|
10
|
-
import { fileUrl, hyperlink } from "../decorations/link.js";
|
|
11
|
-
import { colorize } from "../colors/color.js";
|
|
12
|
-
import { isTTY } from "../terminal/isTTY.js";
|
|
13
|
-
/** Max message lines to show before collapsing the rest; 0 (default) shows all. */
|
|
14
|
-
let visibleLines = DEFAULT_MAX_LINES;
|
|
15
|
-
/** How many lines a long message shows before collapsing (0 = all). */
|
|
16
|
-
export function getVisibleLines() {
|
|
17
|
-
return visibleLines;
|
|
18
|
-
}
|
|
19
|
-
/** Set how many lines a long message shows before collapsing (0 = all). */
|
|
20
|
-
export function setVisibleLines(value) {
|
|
21
|
-
visibleLines = Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Collapses a long multi-line message to {@link visibleLines} lines, replacing
|
|
25
|
-
* the rest with a dimmed `… N more lines` summary. When `visibleLines` is 0
|
|
26
|
-
* (the default) nothing is collapsed — the full message is shown.
|
|
27
|
-
*/
|
|
28
|
-
function collapse(text, useColor) {
|
|
29
|
-
if (visibleLines < 1)
|
|
30
|
-
return text;
|
|
31
|
-
const lines = text.split("\n");
|
|
32
|
-
if (lines.length <= visibleLines)
|
|
33
|
-
return text;
|
|
34
|
-
const hidden = lines.length - visibleLines;
|
|
35
|
-
const summary = `${MESSAGE_INDENT}... ${hidden} more line${hidden === 1 ? "" : "s"}`;
|
|
36
|
-
const visible = lines.slice(0, visibleLines);
|
|
37
|
-
visible.push(useColor ? colorize(summary, "gray") : summary);
|
|
38
|
-
return visible.join("\n");
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Renders the args into a single message string exactly as console would —
|
|
42
|
-
* objects/errors via util.inspect, `%s`/`%d` format specifiers, and colors when
|
|
43
|
-
* on a terminal — then hang-indents every continuation line so multi-line
|
|
44
|
-
* output stays left-aligned under the branch, and collapses very long output.
|
|
45
|
-
*/
|
|
46
|
-
function renderMessage(args, useColor) {
|
|
47
|
-
const text = formatWithOptions({ colors: useColor }, ...args);
|
|
48
|
-
return collapse(text.replace(/\n/g, `\n${colorize(MESSAGE_INDENT, "gray")}`), useColor);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Renders a caller as a `(file:line)` location — a clickable OSC-8 link on a
|
|
52
|
-
* supporting terminal, plain text otherwise. Pure (no stack access).
|
|
53
|
-
*/
|
|
54
|
-
function formatLocation(caller, interactive) {
|
|
55
|
-
if (caller.file !== null && caller.line !== null && interactive)
|
|
56
|
-
return hyperlink(caller.label, fileUrl(caller.file, caller.line));
|
|
57
|
-
return caller.label;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Renders and writes one log entry. The `caller` is resolved by the *caller* of
|
|
61
|
-
* this function (the log closure or `tap`) and passed in, so this helper never
|
|
62
|
-
* touches the stack — keeping {@link getCaller}'s frame depth correct no matter
|
|
63
|
-
* which user-facing function delegates here.
|
|
64
|
-
*/
|
|
65
|
-
export function writeLog(opts) {
|
|
66
|
-
const { channel, tag, args, caller } = opts;
|
|
67
|
-
const streamName = channel === "log" ? "stdout" : "stderr";
|
|
68
|
-
// One terminal check drives both color and clickable links — `isTTY` is the
|
|
69
|
-
// single source of truth (DRY). Off when output is piped/redirected.
|
|
70
|
-
const useColor = isTTY(streamName);
|
|
71
|
-
const paint = (s, c) => useColor ? colorize(s, c) : s;
|
|
72
|
-
const location = formatLocation(caller, useColor);
|
|
73
|
-
const tagOut = paint(tag, TAG_COLOR[channel]);
|
|
74
|
-
const timeStamp = paint(getTimeStamp(), "teal");
|
|
75
|
-
const locOut = paint(`(${location})`, "dimTeal");
|
|
76
|
-
const connector = paint(BRANCH, "gray");
|
|
77
|
-
const connectorBottom = paint(BRANCH_END, "gray");
|
|
78
|
-
const separator = paint(SEPARATOR, "gray");
|
|
79
|
-
// Layout: the tag, the message hanging off a `├──` branch, then the timestamp
|
|
80
|
-
// and location on a `└──` branch below. Leading `\n` spaces entries apart.
|
|
81
|
-
const message = renderMessage(args, useColor);
|
|
82
|
-
const meta = `\n${connectorBottom} ${timeStamp} ${separator} ${locOut}`;
|
|
83
|
-
console[channel](`\n${tagOut}`, `\n${connector}`, message, meta);
|
|
84
|
-
}
|