@meadown/logger 1.8.9 → 1.8.11
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/helpers/formatLocation.d.ts +6 -0
- package/dist/cjs/core/writeLog/helpers/formatLocation.js +20 -0
- package/dist/cjs/core/writeLog/helpers/index.d.ts +3 -0
- package/dist/cjs/core/writeLog/helpers/index.js +17 -0
- package/dist/cjs/core/writeLog/helpers/renderMessage.d.ts +7 -0
- package/dist/cjs/core/writeLog/helpers/renderMessage.js +40 -0
- package/dist/cjs/core/writeLog/helpers/visibleLines.d.ts +6 -0
- package/dist/cjs/core/writeLog/helpers/visibleLines.js +22 -0
- package/dist/cjs/core/writeLog/index.d.ts +2 -0
- package/dist/cjs/core/writeLog/index.js +14 -0
- package/dist/cjs/core/{writeLog.d.ts → writeLog/writeLog.d.ts} +2 -6
- package/dist/cjs/core/writeLog/writeLog.js +43 -0
- package/dist/cjs/decorations/link.d.ts +2 -6
- package/dist/cjs/decorations/link.js +3 -8
- package/dist/cjs/index.d.ts +46 -17
- package/dist/cjs/index.js +20 -10
- package/dist/cjs/tap/createTap.js +6 -6
- package/dist/cjs/tap/tapAsync/helpers/buildBlock.d.ts +19 -0
- package/dist/cjs/tap/tapAsync/helpers/buildBlock.js +56 -0
- package/dist/cjs/tap/tapAsync/helpers/format.d.ts +4 -0
- package/dist/cjs/tap/tapAsync/helpers/format.js +30 -0
- package/dist/cjs/tap/tapAsync/helpers/index.d.ts +4 -0
- package/dist/cjs/tap/tapAsync/helpers/index.js +20 -0
- package/dist/cjs/tap/tapAsync/helpers/isThenable.d.ts +2 -0
- package/dist/cjs/tap/tapAsync/helpers/isThenable.js +15 -0
- package/dist/cjs/tap/tapAsync/helpers/response.d.ts +21 -0
- package/dist/cjs/tap/tapAsync/helpers/response.js +62 -0
- package/dist/cjs/tap/tapAsync/index.d.ts +2 -0
- package/dist/cjs/tap/tapAsync/index.js +13 -0
- package/dist/cjs/tap/{tapAsync.d.ts → tapAsync/tapAsync.d.ts} +1 -3
- package/dist/cjs/tap/tapAsync/tapAsync.js +92 -0
- package/dist/core/createLog.js +1 -1
- package/dist/core/writeLog/helpers/formatLocation.d.ts +6 -0
- package/dist/core/writeLog/helpers/formatLocation.js +17 -0
- package/dist/core/writeLog/helpers/index.d.ts +3 -0
- package/dist/core/writeLog/helpers/index.js +9 -0
- package/dist/core/writeLog/helpers/renderMessage.d.ts +7 -0
- package/dist/core/writeLog/helpers/renderMessage.js +37 -0
- package/dist/core/writeLog/helpers/visibleLines.d.ts +6 -0
- package/dist/core/writeLog/helpers/visibleLines.js +17 -0
- package/dist/core/writeLog/index.d.ts +2 -0
- package/dist/core/writeLog/index.js +8 -0
- package/dist/core/{writeLog.d.ts → writeLog/writeLog.d.ts} +2 -6
- package/dist/core/writeLog/writeLog.js +37 -0
- package/dist/decorations/link.d.ts +2 -6
- package/dist/decorations/link.js +3 -8
- package/dist/index.d.ts +46 -17
- package/dist/index.js +18 -8
- package/dist/tap/createTap.js +3 -3
- package/dist/tap/tapAsync/helpers/buildBlock.d.ts +19 -0
- package/dist/tap/tapAsync/helpers/buildBlock.js +53 -0
- package/dist/tap/tapAsync/helpers/format.d.ts +4 -0
- package/dist/tap/tapAsync/helpers/format.js +26 -0
- package/dist/tap/tapAsync/helpers/index.d.ts +4 -0
- package/dist/tap/tapAsync/helpers/index.js +10 -0
- package/dist/tap/tapAsync/helpers/isThenable.d.ts +2 -0
- package/dist/tap/tapAsync/helpers/isThenable.js +12 -0
- package/dist/tap/tapAsync/helpers/response.d.ts +21 -0
- package/dist/tap/tapAsync/helpers/response.js +57 -0
- package/dist/tap/tapAsync/index.d.ts +2 -0
- package/dist/tap/tapAsync/index.js +8 -0
- package/dist/tap/{tapAsync.d.ts → tapAsync/tapAsync.d.ts} +1 -3
- package/dist/tap/tapAsync/tapAsync.js +89 -0
- package/package.json +7 -4
- package/dist/cjs/core/writeLog.js +0 -92
- package/dist/cjs/tap/tapAsync.js +0 -192
- package/dist/core/writeLog.js +0 -84
- package/dist/tap/tapAsync.js +0 -188
|
@@ -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,20 @@
|
|
|
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
|
+
}
|
|
19
|
+
return caller.label;
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* index.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 = exports.renderMessage = exports.setVisibleLines = exports.getVisibleLines = exports.visibleLines = void 0;
|
|
10
|
+
var visibleLines_js_1 = require("./visibleLines.js");
|
|
11
|
+
Object.defineProperty(exports, "visibleLines", { enumerable: true, get: function () { return visibleLines_js_1.visibleLines; } });
|
|
12
|
+
Object.defineProperty(exports, "getVisibleLines", { enumerable: true, get: function () { return visibleLines_js_1.getVisibleLines; } });
|
|
13
|
+
Object.defineProperty(exports, "setVisibleLines", { enumerable: true, get: function () { return visibleLines_js_1.setVisibleLines; } });
|
|
14
|
+
var renderMessage_js_1 = require("./renderMessage.js");
|
|
15
|
+
Object.defineProperty(exports, "renderMessage", { enumerable: true, get: function () { return renderMessage_js_1.renderMessage; } });
|
|
16
|
+
var formatLocation_js_1 = require("./formatLocation.js");
|
|
17
|
+
Object.defineProperty(exports, "formatLocation", { enumerable: true, get: function () { return formatLocation_js_1.formatLocation; } });
|
|
@@ -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 visibleLines_js_1 = require("./visibleLines.js");
|
|
12
|
+
const color_js_1 = require("../../../colors/color.js");
|
|
13
|
+
const constants_js_1 = require("../../../constants.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
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* index.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.setVisibleLines = exports.getVisibleLines = exports.writeLog = void 0;
|
|
10
|
+
var writeLog_js_1 = require("./writeLog.js");
|
|
11
|
+
Object.defineProperty(exports, "writeLog", { enumerable: true, get: function () { return writeLog_js_1.writeLog; } });
|
|
12
|
+
var index_js_1 = require("./helpers/index.js");
|
|
13
|
+
Object.defineProperty(exports, "getVisibleLines", { enumerable: true, get: function () { return index_js_1.getVisibleLines; } });
|
|
14
|
+
Object.defineProperty(exports, "setVisibleLines", { enumerable: true, get: function () { return index_js_1.setVisibleLines; } });
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import { type LogChannel } from "
|
|
2
|
-
import { type Caller } from "
|
|
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;
|
|
1
|
+
import { type LogChannel } from "../../constants.js";
|
|
2
|
+
import { type Caller } from "../../caller/getCaller.js";
|
|
7
3
|
/**
|
|
8
4
|
* Renders and writes one log entry. The `caller` is resolved by the *caller* of
|
|
9
5
|
* this function (the log closure or `tap`) and passed in, so this helper never
|
|
@@ -0,0 +1,43 @@
|
|
|
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.writeLog = writeLog;
|
|
13
|
+
const constants_js_1 = require("../../constants.js");
|
|
14
|
+
const isTTY_js_1 = require("../../terminal/isTTY.js");
|
|
15
|
+
const getTimeStamp_js_1 = __importDefault(require("../../time/getTimeStamp.js"));
|
|
16
|
+
const color_js_1 = require("../../colors/color.js");
|
|
17
|
+
const index_js_1 = require("./helpers/index.js");
|
|
18
|
+
/**
|
|
19
|
+
* Renders and writes one log entry. The `caller` is resolved by the *caller* of
|
|
20
|
+
* this function (the log closure or `tap`) and passed in, so this helper never
|
|
21
|
+
* touches the stack — keeping {@link getCaller}'s frame depth correct no matter
|
|
22
|
+
* which user-facing function delegates here.
|
|
23
|
+
*/
|
|
24
|
+
function writeLog(opts) {
|
|
25
|
+
const { channel, tag, args, caller } = opts;
|
|
26
|
+
const streamName = channel === "log" ? "stdout" : "stderr";
|
|
27
|
+
// One terminal check drives both color and clickable links — `isTTY` is the
|
|
28
|
+
// single source of truth (DRY). Off when output is piped/redirected.
|
|
29
|
+
const useColor = (0, isTTY_js_1.isTTY)(streamName);
|
|
30
|
+
const paint = (s, c) => (useColor ? (0, color_js_1.colorize)(s, c) : s);
|
|
31
|
+
const location = (0, index_js_1.formatLocation)(caller, useColor);
|
|
32
|
+
const tagOut = paint(tag, constants_js_1.TAG_COLOR[channel]);
|
|
33
|
+
const timeStamp = paint((0, getTimeStamp_js_1.default)(), "teal");
|
|
34
|
+
const locOut = paint(`(${location})`, "dimTeal");
|
|
35
|
+
const connector = paint(constants_js_1.BRANCH, "gray");
|
|
36
|
+
const connectorBottom = paint(constants_js_1.BRANCH_END, "gray");
|
|
37
|
+
const separator = paint(constants_js_1.SEPARATOR, "gray");
|
|
38
|
+
// Layout: the tag, the message hanging off a `├──` branch, then the timestamp
|
|
39
|
+
// and location on a `└──` branch below. Leading `\n` spaces entries apart.
|
|
40
|
+
const message = (0, index_js_1.renderMessage)(args, useColor);
|
|
41
|
+
const meta = `\n${connectorBottom} ${timeStamp} ${separator} ${locOut}`;
|
|
42
|
+
console[channel](`\n${tagOut}`, `\n${connector}`, message, meta);
|
|
43
|
+
}
|
|
@@ -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.d.ts
CHANGED
|
@@ -1,32 +1,61 @@
|
|
|
1
|
-
/**
|
|
2
|
-
export interface
|
|
1
|
+
/** Type of the logger — use this to annotate variables or parameters that accept it. */
|
|
2
|
+
export interface Logger {
|
|
3
|
+
/** Log at info level — `stdout`, cyan `[INFO]` tag. */
|
|
3
4
|
(...args: unknown[]): void;
|
|
5
|
+
/** Log at error level — `stderr`, red `[ERROR]` tag. */
|
|
4
6
|
error(...args: unknown[]): void;
|
|
7
|
+
/** Log at warn level — `stderr`, yellow `[WARN]` tag. */
|
|
5
8
|
warn(...args: unknown[]): void;
|
|
6
9
|
/**
|
|
7
|
-
* Logs `value`
|
|
8
|
-
* so it
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Logs `value` with an optional `label` and gives it straight back unchanged
|
|
11
|
+
* — so you can drop it into any expression without adding an extra line.
|
|
12
|
+
*
|
|
13
|
+
* **Sync value** — logged immediately, returned as-is:
|
|
14
|
+
* ```ts
|
|
15
|
+
* const port = logger.tap(3000, "port") // logs it, port is still 3000
|
|
16
|
+
* const user = logger.tap(getUser(), "user") // logs the user object, returns it
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* **Promise** — the same promise comes back; timing and HTTP status are logged
|
|
20
|
+
* in the background once it settles, without blocking your code:
|
|
21
|
+
* ```ts
|
|
22
|
+
* const res = await logger.tap(fetch(url), "GET /users") // logs status + ms
|
|
23
|
+
* const data = await logger.tap(loadConfig(), "config") // logs value + ms
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @param value Any value or promise — always returned as-is.
|
|
27
|
+
* @param label Optional label shown next to the value in the log line.
|
|
12
28
|
*/
|
|
13
29
|
tap<T>(value: T, label?: string): T;
|
|
14
30
|
/**
|
|
15
|
-
* How many lines
|
|
16
|
-
*
|
|
31
|
+
* How many lines to show before the rest collapses into a
|
|
32
|
+
* `… N more lines` summary. `0` (default) shows everything.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* logger.maxLines = 5
|
|
17
36
|
*/
|
|
18
37
|
maxLines: number;
|
|
19
38
|
}
|
|
20
39
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
40
|
+
* A logger built for development — colored tags, a local timestamp, and a
|
|
41
|
+
* clickable `(file:line)` link on every line so you always know where a
|
|
42
|
+
* message came from. Works like `console.log`: pass anything and it prints.
|
|
43
|
+
*
|
|
44
|
+
* Logs only when `NODE_ENV !== "production"`.
|
|
45
|
+
*
|
|
24
46
|
* @example
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* logger.
|
|
47
|
+
* ```ts
|
|
48
|
+
* logger("server started", { port: 3000 })
|
|
49
|
+
* logger.error("db failed", new Error("ECONNREFUSED"))
|
|
50
|
+
* logger.warn("disk above 80%")
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example Tap — keep the value flowing, log it on the side
|
|
54
|
+
* ```ts
|
|
55
|
+
* const user = logger.tap(await getUser(id), "user")
|
|
56
|
+
* const res = await logger.tap(fetch(url), "GET /users")
|
|
57
|
+
* ```
|
|
29
58
|
*/
|
|
30
|
-
declare const logger:
|
|
59
|
+
declare const logger: Logger;
|
|
31
60
|
export { logger };
|
|
32
61
|
export default logger;
|
package/dist/cjs/index.js
CHANGED
|
@@ -12,16 +12,26 @@ 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
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* A logger built for development — colored tags, a local timestamp, and a
|
|
18
|
+
* clickable `(file:line)` link on every line so you always know where a
|
|
19
|
+
* message came from. Works like `console.log`: pass anything and it prints.
|
|
20
|
+
*
|
|
21
|
+
* Logs only when `NODE_ENV !== "production"`.
|
|
22
|
+
*
|
|
20
23
|
* @example
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* logger.
|
|
24
|
+
* ```ts
|
|
25
|
+
* logger("server started", { port: 3000 })
|
|
26
|
+
* logger.error("db failed", new Error("ECONNREFUSED"))
|
|
27
|
+
* logger.warn("disk above 80%")
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example Tap — keep the value flowing, log it on the side
|
|
31
|
+
* ```ts
|
|
32
|
+
* const user = logger.tap(await getUser(id), "user")
|
|
33
|
+
* const res = await logger.tap(fetch(url), "GET /users")
|
|
34
|
+
* ```
|
|
25
35
|
*/
|
|
26
36
|
const logger = Object.assign((0, createLog_js_1.default)("log", "[INFO]"), {
|
|
27
37
|
error: (0, createLog_js_1.default)("error", "[ERROR]"),
|
|
@@ -32,8 +42,8 @@ exports.logger = logger;
|
|
|
32
42
|
// `maxLines` is a live getter/setter backed by the shared collapse setting, so
|
|
33
43
|
// setting it once affects info, error, and warn alike.
|
|
34
44
|
Object.defineProperty(logger, "maxLines", {
|
|
35
|
-
get:
|
|
36
|
-
set:
|
|
45
|
+
get: index_js_1.getVisibleLines,
|
|
46
|
+
set: index_js_1.setVisibleLines,
|
|
37
47
|
enumerable: true,
|
|
38
48
|
configurable: true,
|
|
39
49
|
});
|
|
@@ -10,10 +10,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.default = createTap;
|
|
13
|
-
const getCaller_js_1 = __importDefault(require("../caller/getCaller.js"));
|
|
14
|
-
const writeLog_js_1 = require("../core/writeLog.js");
|
|
15
13
|
const config_js_1 = require("../config.js");
|
|
16
|
-
const
|
|
14
|
+
const getCaller_js_1 = __importDefault(require("../caller/getCaller.js"));
|
|
15
|
+
const index_js_1 = require("../core/writeLog/index.js");
|
|
16
|
+
const index_js_2 = require("./tapAsync/index.js");
|
|
17
17
|
/**
|
|
18
18
|
* Builds `tap` — logs a value and returns it **unchanged**, so it drops into any
|
|
19
19
|
* expression (`const u = logger.tap(getUser(), "user")`). The consumer always
|
|
@@ -32,13 +32,13 @@ function createTap() {
|
|
|
32
32
|
if (!(0, config_js_1.isLogAllowed)())
|
|
33
33
|
return value;
|
|
34
34
|
const caller = (0, getCaller_js_1.default)();
|
|
35
|
-
if ((0,
|
|
35
|
+
if ((0, index_js_2.isThenable)(value)) {
|
|
36
36
|
// value is a promise → hand off to the async tap (caller passed in so the
|
|
37
37
|
// location stays on the user's file, not on this helper).
|
|
38
|
-
(0,
|
|
38
|
+
(0, index_js_2.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],
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ResponseLike } from "./response.js";
|
|
2
|
+
/**
|
|
3
|
+
* Renders the nested tree block:
|
|
4
|
+
*
|
|
5
|
+
* GET /users/1
|
|
6
|
+
* │
|
|
7
|
+
* │ response:
|
|
8
|
+
* │ ├── time: 65ms
|
|
9
|
+
* │ ├── status: 200 OK
|
|
10
|
+
* │ └── size: 848 B
|
|
11
|
+
* │
|
|
12
|
+
* │ body:
|
|
13
|
+
* │ ├── id: 1
|
|
14
|
+
* │ └── name: Leanne Graham
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildBlock(label: string | undefined, ms: number, res: ResponseLike, body: {
|
|
17
|
+
data: unknown;
|
|
18
|
+
size: string;
|
|
19
|
+
}, useColor: boolean): unknown[];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* buildBlock.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.buildBlock = buildBlock;
|
|
10
|
+
const node_util_1 = require("node:util");
|
|
11
|
+
const format_js_1 = require("./format.js");
|
|
12
|
+
const color_js_1 = require("../../../colors/color.js");
|
|
13
|
+
const response_js_1 = require("./response.js");
|
|
14
|
+
/**
|
|
15
|
+
* Renders the nested tree block:
|
|
16
|
+
*
|
|
17
|
+
* GET /users/1
|
|
18
|
+
* │
|
|
19
|
+
* │ response:
|
|
20
|
+
* │ ├── time: 65ms
|
|
21
|
+
* │ ├── status: 200 OK
|
|
22
|
+
* │ └── size: 848 B
|
|
23
|
+
* │
|
|
24
|
+
* │ body:
|
|
25
|
+
* │ ├── id: 1
|
|
26
|
+
* │ └── name: Leanne Graham
|
|
27
|
+
*/
|
|
28
|
+
function buildBlock(label, ms, res, body, useColor) {
|
|
29
|
+
const paint = (s, c) => useColor ? (0, color_js_1.colorize)(s, c) : s;
|
|
30
|
+
const pipe = paint("│", "gray");
|
|
31
|
+
const branch = paint("├──", "gray");
|
|
32
|
+
const last = paint("└──", "gray");
|
|
33
|
+
const indent = `${pipe} `;
|
|
34
|
+
const timeLine = `${indent}${branch} time: ${(0, format_js_1.formatDuration)(ms, useColor)}`;
|
|
35
|
+
const statusLine = `${indent}${branch} status: ${(0, response_js_1.formatStatus)(res, useColor)}`;
|
|
36
|
+
const sizeLine = `${indent}${last} size: ${body.size}`;
|
|
37
|
+
const responseLines = [
|
|
38
|
+
`${pipe}`,
|
|
39
|
+
`${indent}response:`,
|
|
40
|
+
timeLine,
|
|
41
|
+
statusLine,
|
|
42
|
+
sizeLine,
|
|
43
|
+
];
|
|
44
|
+
const head = label === undefined ? "" : `${label}\n`;
|
|
45
|
+
if (body.data === undefined) {
|
|
46
|
+
return [`${head}${responseLines.join("\n")}`];
|
|
47
|
+
}
|
|
48
|
+
const bodyText = (0, node_util_1.formatWithOptions)({ colors: useColor }, body.data);
|
|
49
|
+
const bodyLines = bodyText.split("\n");
|
|
50
|
+
const lastIdx = bodyLines.length - 1;
|
|
51
|
+
const bodyBlock = bodyLines
|
|
52
|
+
.map((line, i) => `${indent}${i === lastIdx ? last : branch} ${line}`)
|
|
53
|
+
.join("\n");
|
|
54
|
+
const full = [...responseLines, `${pipe}`, `${indent}body:`, bodyBlock].join("\n");
|
|
55
|
+
return [`${head}${full}`];
|
|
56
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* format.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.formatDuration = formatDuration;
|
|
10
|
+
exports.formatBytes = formatBytes;
|
|
11
|
+
const color_js_1 = require("../../../colors/color.js");
|
|
12
|
+
/** `65ms` (green) · `1.2s` (yellow) · `5.8s` (red). */
|
|
13
|
+
function formatDuration(ms, useColor) {
|
|
14
|
+
const text = ms >= 1000 ? `${(ms / 1000).toFixed(2)}s` : `${ms}ms`;
|
|
15
|
+
if (!useColor)
|
|
16
|
+
return text;
|
|
17
|
+
if (ms >= 2000)
|
|
18
|
+
return (0, color_js_1.colorize)(text, "red");
|
|
19
|
+
if (ms >= 500)
|
|
20
|
+
return (0, color_js_1.colorize)(text, "yellow");
|
|
21
|
+
return (0, color_js_1.colorize)(text, "green");
|
|
22
|
+
}
|
|
23
|
+
/** `848 B` / `1.84 KB` / `2.10 MB`. */
|
|
24
|
+
function formatBytes(bytes) {
|
|
25
|
+
if (bytes < 1024)
|
|
26
|
+
return `${bytes} B`;
|
|
27
|
+
if (bytes < 1024 * 1024)
|
|
28
|
+
return `${(bytes / 1024).toFixed(2)} KB`;
|
|
29
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
30
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* index.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.formatBytes = exports.formatDuration = exports.isThenable = exports.buildBlock = exports.formatStatus = exports.isResponse = exports.readBody = void 0;
|
|
10
|
+
var response_js_1 = require("./response.js");
|
|
11
|
+
Object.defineProperty(exports, "readBody", { enumerable: true, get: function () { return response_js_1.readBody; } });
|
|
12
|
+
Object.defineProperty(exports, "isResponse", { enumerable: true, get: function () { return response_js_1.isResponse; } });
|
|
13
|
+
Object.defineProperty(exports, "formatStatus", { enumerable: true, get: function () { return response_js_1.formatStatus; } });
|
|
14
|
+
var buildBlock_js_1 = require("./buildBlock.js");
|
|
15
|
+
Object.defineProperty(exports, "buildBlock", { enumerable: true, get: function () { return buildBlock_js_1.buildBlock; } });
|
|
16
|
+
var isThenable_js_1 = require("./isThenable.js");
|
|
17
|
+
Object.defineProperty(exports, "isThenable", { enumerable: true, get: function () { return isThenable_js_1.isThenable; } });
|
|
18
|
+
var format_js_1 = require("./format.js");
|
|
19
|
+
Object.defineProperty(exports, "formatDuration", { enumerable: true, get: function () { return format_js_1.formatDuration; } });
|
|
20
|
+
Object.defineProperty(exports, "formatBytes", { enumerable: true, get: function () { return format_js_1.formatBytes; } });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* isThenable.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.isThenable = isThenable;
|
|
10
|
+
/** Whether `value` is thenable (a promise we can await + time). */
|
|
11
|
+
function isThenable(value) {
|
|
12
|
+
return (typeof value === "object" &&
|
|
13
|
+
value !== null &&
|
|
14
|
+
typeof value.then === "function");
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type ResponseLike = {
|
|
2
|
+
status: number;
|
|
3
|
+
statusText?: unknown;
|
|
4
|
+
headers?: {
|
|
5
|
+
get?: (name: string) => string | null;
|
|
6
|
+
};
|
|
7
|
+
clone: () => ResponseLike;
|
|
8
|
+
text: () => Promise<string>;
|
|
9
|
+
};
|
|
10
|
+
/** Whether the resolved value is a fetch `Response` we can read. */
|
|
11
|
+
export declare function isResponse(value: unknown): value is ResponseLike;
|
|
12
|
+
export declare function formatStatus(res: ResponseLike, useColor: boolean): string;
|
|
13
|
+
/**
|
|
14
|
+
* Reads a (cloned) response body and returns both the parsed value and the
|
|
15
|
+
* actual byte size. Size is calculated from the body text — not `Content-Length`,
|
|
16
|
+
* which is absent on compressed responses — so size is always shown.
|
|
17
|
+
*/
|
|
18
|
+
export declare function readBody(res: ResponseLike): Promise<{
|
|
19
|
+
data: unknown;
|
|
20
|
+
size: string;
|
|
21
|
+
}>;
|