where-log 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -3
- package/dist/index.cjs +560 -37
- package/dist/index.d.cts +107 -4
- package/dist/index.d.ts +107 -4
- package/dist/index.mjs +544 -37
- package/package.json +5 -2
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,152 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/core/context.ts
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function mergeContexts(base, incoming) {
|
|
6
|
+
if (!base && !incoming) return void 0;
|
|
7
|
+
return {
|
|
8
|
+
...base ?? {},
|
|
9
|
+
...incoming ?? {}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function injectContext(value, context) {
|
|
13
|
+
if (!context) return value;
|
|
14
|
+
if (isRecord(value)) {
|
|
15
|
+
const existing = isRecord(value.context) ? value.context : void 0;
|
|
16
|
+
return {
|
|
17
|
+
...value,
|
|
18
|
+
context: {
|
|
19
|
+
...existing ?? {},
|
|
20
|
+
...context
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
value,
|
|
26
|
+
context
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/core/format.ts
|
|
2
31
|
import util from "util";
|
|
3
|
-
import path from "path";
|
|
4
32
|
function isNodeRuntime() {
|
|
5
33
|
return typeof process !== "undefined" && !!process.versions?.node;
|
|
6
34
|
}
|
|
35
|
+
function safeFastStringify(value) {
|
|
36
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
37
|
+
return JSON.stringify(value, (_k, v) => {
|
|
38
|
+
if (typeof v === "object" && v !== null) {
|
|
39
|
+
if (seen.has(v)) return "[Circular]";
|
|
40
|
+
seen.add(v);
|
|
41
|
+
}
|
|
42
|
+
return v;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function formatFastValue(value) {
|
|
46
|
+
if (typeof value === "string") return value;
|
|
47
|
+
if (typeof value === "number") return String(value);
|
|
48
|
+
if (typeof value === "boolean") return String(value);
|
|
49
|
+
if (typeof value === "bigint") return value.toString();
|
|
50
|
+
if (typeof value === "undefined") return "undefined";
|
|
51
|
+
if (value === null) return "null";
|
|
52
|
+
if (typeof value === "symbol") return value.toString();
|
|
53
|
+
if (typeof value === "function") {
|
|
54
|
+
return `[Function ${value.name || "anonymous"}]`;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
return safeFastStringify(value);
|
|
58
|
+
} catch {
|
|
59
|
+
return "[Unserializable]";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function formatValue(value, options) {
|
|
63
|
+
const mode = options?.mode ?? "pretty";
|
|
64
|
+
if (mode === "fast") {
|
|
65
|
+
return formatFastValue(value);
|
|
66
|
+
}
|
|
67
|
+
if (!isNodeRuntime()) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
return util.inspect(value, {
|
|
71
|
+
depth: options?.inspectDepth ?? null,
|
|
72
|
+
colors: options?.colors ?? true,
|
|
73
|
+
compact: false
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function formatLabeledValue(label, formattedValue) {
|
|
77
|
+
if (!label) return formattedValue;
|
|
78
|
+
if (typeof formattedValue === "string") {
|
|
79
|
+
return `${label}: ${formattedValue}`;
|
|
80
|
+
}
|
|
81
|
+
return `${label}: ${String(formattedValue)}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/core/level.ts
|
|
85
|
+
var LEVEL_METHOD_MAP = {
|
|
86
|
+
info: "info",
|
|
87
|
+
success: "log",
|
|
88
|
+
warn: "warn",
|
|
89
|
+
error: "error",
|
|
90
|
+
debug: "debug"
|
|
91
|
+
};
|
|
92
|
+
function levelToConsoleMethod(level) {
|
|
93
|
+
return LEVEL_METHOD_MAP[level];
|
|
94
|
+
}
|
|
95
|
+
function levelToTag(level) {
|
|
96
|
+
return `[${level.toUpperCase()}]`;
|
|
97
|
+
}
|
|
98
|
+
function resolveConsoleMethod(level, override) {
|
|
99
|
+
if (override) return override;
|
|
100
|
+
if (!level) return "log";
|
|
101
|
+
return levelToConsoleMethod(level);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/core/session.ts
|
|
105
|
+
var onceKeys = /* @__PURE__ */ new Set();
|
|
106
|
+
var timers = /* @__PURE__ */ new Map();
|
|
107
|
+
function checkAndMarkOnce(key) {
|
|
108
|
+
if (onceKeys.has(key)) return false;
|
|
109
|
+
onceKeys.add(key);
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
function clearOnce(keys) {
|
|
113
|
+
if (!keys || keys.length === 0) {
|
|
114
|
+
onceKeys.clear();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
for (const key of keys) {
|
|
118
|
+
onceKeys.delete(key);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function startTimer(key, now) {
|
|
122
|
+
timers.set(key, { startedAt: now });
|
|
123
|
+
}
|
|
124
|
+
function endTimer(key, now) {
|
|
125
|
+
const entry = timers.get(key);
|
|
126
|
+
if (!entry) return null;
|
|
127
|
+
timers.delete(key);
|
|
128
|
+
return Math.max(0, now - entry.startedAt);
|
|
129
|
+
}
|
|
130
|
+
function clearTimers(keys) {
|
|
131
|
+
if (!keys || keys.length === 0) {
|
|
132
|
+
timers.clear();
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
for (const key of keys) {
|
|
136
|
+
timers.delete(key);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/core/stack.ts
|
|
7
141
|
function safeToInt(input) {
|
|
8
142
|
const n = Number.parseInt(input, 10);
|
|
9
143
|
return Number.isFinite(n) ? n : 0;
|
|
10
144
|
}
|
|
11
|
-
function
|
|
145
|
+
function basename(filePath) {
|
|
12
146
|
const clean = filePath.replace(/^file:\/\//, "");
|
|
13
|
-
|
|
147
|
+
const normalized = clean.replace(/\\/g, "/");
|
|
148
|
+
const last = normalized.lastIndexOf("/");
|
|
149
|
+
return last >= 0 ? normalized.slice(last + 1) : normalized;
|
|
14
150
|
}
|
|
15
151
|
function parseFrameLine(frame) {
|
|
16
152
|
const cleaned = frame.trim();
|
|
@@ -18,14 +154,14 @@ function parseFrameLine(frame) {
|
|
|
18
154
|
const v8Match = cleaned.match(/(?:at\s+)?(?:.+\s+\()?(.+):(\d+):(\d+)\)?$/);
|
|
19
155
|
if (v8Match) {
|
|
20
156
|
return {
|
|
21
|
-
file:
|
|
157
|
+
file: basename(v8Match[1]),
|
|
22
158
|
line: safeToInt(v8Match[2])
|
|
23
159
|
};
|
|
24
160
|
}
|
|
25
161
|
const ffMatch = cleaned.match(/@(.+):(\d+):(\d+)$/);
|
|
26
162
|
if (ffMatch) {
|
|
27
163
|
return {
|
|
28
|
-
file:
|
|
164
|
+
file: basename(ffMatch[1]),
|
|
29
165
|
line: safeToInt(ffMatch[2])
|
|
30
166
|
};
|
|
31
167
|
}
|
|
@@ -33,41 +169,105 @@ function parseFrameLine(frame) {
|
|
|
33
169
|
}
|
|
34
170
|
function getCallerFromStack(stack) {
|
|
35
171
|
if (!stack) return { file: "unknown", line: 0 };
|
|
36
|
-
const frames = stack.split("\n")
|
|
37
|
-
for (
|
|
172
|
+
const frames = stack.split("\n");
|
|
173
|
+
for (let i = 0; i < frames.length; i += 1) {
|
|
174
|
+
const frame = frames[i].trim();
|
|
175
|
+
if (!frame) continue;
|
|
38
176
|
if (frame.includes("getCallerFromStack")) continue;
|
|
39
177
|
if (frame.includes("at log")) continue;
|
|
40
178
|
if (frame.includes("at Object.log")) continue;
|
|
41
179
|
if (frame.includes("/src/index.ts")) continue;
|
|
42
180
|
if (frame.includes("\\src\\index.ts")) continue;
|
|
181
|
+
if (frame.includes("/src/core/")) continue;
|
|
182
|
+
if (frame.includes("\\src\\core\\")) continue;
|
|
43
183
|
const parsed = parseFrameLine(frame);
|
|
44
184
|
if (parsed) return parsed;
|
|
45
185
|
}
|
|
46
186
|
return { file: "unknown", line: 0 };
|
|
47
187
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return
|
|
188
|
+
|
|
189
|
+
// src/core/transform.ts
|
|
190
|
+
function isObjectLike(value) {
|
|
191
|
+
return typeof value === "object" && value !== null;
|
|
52
192
|
}
|
|
53
|
-
function
|
|
54
|
-
if (!
|
|
55
|
-
|
|
193
|
+
function cloneDeep(value, seen = /* @__PURE__ */ new WeakMap()) {
|
|
194
|
+
if (!isObjectLike(value)) return value;
|
|
195
|
+
if (seen.has(value)) return seen.get(value);
|
|
196
|
+
if (Array.isArray(value)) {
|
|
197
|
+
const arr = [];
|
|
198
|
+
seen.set(value, arr);
|
|
199
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
200
|
+
arr.push(cloneDeep(value[i], seen));
|
|
201
|
+
}
|
|
202
|
+
return arr;
|
|
56
203
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
204
|
+
const obj = {};
|
|
205
|
+
seen.set(value, obj);
|
|
206
|
+
for (const [k, v] of Object.entries(value)) {
|
|
207
|
+
obj[k] = cloneDeep(v, seen);
|
|
208
|
+
}
|
|
209
|
+
return obj;
|
|
62
210
|
}
|
|
63
|
-
function
|
|
64
|
-
if (!
|
|
65
|
-
|
|
66
|
-
|
|
211
|
+
function redactPath(target, path) {
|
|
212
|
+
if (!isObjectLike(target) || path.length === 0) return;
|
|
213
|
+
const [head, ...rest] = path;
|
|
214
|
+
if (Array.isArray(target)) {
|
|
215
|
+
const idx = Number.parseInt(head, 10);
|
|
216
|
+
if (!Number.isFinite(idx) || idx < 0 || idx >= target.length) return;
|
|
217
|
+
if (rest.length === 0) {
|
|
218
|
+
target[idx] = "[REDACTED]";
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
redactPath(target[idx], rest);
|
|
222
|
+
return;
|
|
67
223
|
}
|
|
68
|
-
|
|
224
|
+
if (!(head in target)) return;
|
|
225
|
+
if (rest.length === 0) {
|
|
226
|
+
target[head] = "[REDACTED]";
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
redactPath(target[head], rest);
|
|
69
230
|
}
|
|
70
|
-
function
|
|
231
|
+
function truncateArrays(target, maxArrayLength) {
|
|
232
|
+
if (!isObjectLike(target)) return target;
|
|
233
|
+
if (Array.isArray(target)) {
|
|
234
|
+
const sliced = target.slice(0, maxArrayLength).map((item) => truncateArrays(item, maxArrayLength));
|
|
235
|
+
if (target.length > maxArrayLength) {
|
|
236
|
+
sliced.push(`[... ${target.length - maxArrayLength} more items]`);
|
|
237
|
+
}
|
|
238
|
+
return sliced;
|
|
239
|
+
}
|
|
240
|
+
const out = {};
|
|
241
|
+
for (const [k, v] of Object.entries(target)) {
|
|
242
|
+
out[k] = truncateArrays(v, maxArrayLength);
|
|
243
|
+
}
|
|
244
|
+
return out;
|
|
245
|
+
}
|
|
246
|
+
function transformValue(value, options) {
|
|
247
|
+
if (!options?.redact?.length && options?.maxArrayLength == null) {
|
|
248
|
+
return value;
|
|
249
|
+
}
|
|
250
|
+
const cloned = cloneDeep(value);
|
|
251
|
+
if (options.redact?.length) {
|
|
252
|
+
for (const rawPath of options.redact) {
|
|
253
|
+
const path = rawPath.split(".").map((part) => part.trim()).filter(Boolean);
|
|
254
|
+
if (path.length === 0) continue;
|
|
255
|
+
redactPath(cloned, path);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (typeof options.maxArrayLength === "number" && options.maxArrayLength >= 0) {
|
|
259
|
+
return truncateArrays(cloned, options.maxArrayLength);
|
|
260
|
+
}
|
|
261
|
+
return cloned;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/index.ts
|
|
265
|
+
function isLogOptions(value) {
|
|
266
|
+
if (!value || typeof value !== "object") return false;
|
|
267
|
+
const record = value;
|
|
268
|
+
return "colors" in record || "formatter" in record || "enabled" in record || "mode" in record || "includeLocation" in record || "inspectDepth" in record || "maxArrayLength" in record || "redact" in record || "level" in record || "showLevelTag" in record || "levelTagStyle" in record || "consoleMethod" in record || "context" in record || "clockNow" in record || "warnThresholdMs" in record || "errorThresholdMs" in record || "includeDurationOnly" in record;
|
|
269
|
+
}
|
|
270
|
+
function resolveLogArgs(arg1, arg2, arg3) {
|
|
71
271
|
let label;
|
|
72
272
|
let value;
|
|
73
273
|
let options;
|
|
@@ -79,31 +279,338 @@ function log(arg1, arg2, arg3) {
|
|
|
79
279
|
value = arg1;
|
|
80
280
|
options = isLogOptions(arg2) ? arg2 : void 0;
|
|
81
281
|
}
|
|
82
|
-
|
|
83
|
-
|
|
282
|
+
return { label, value, options };
|
|
283
|
+
}
|
|
284
|
+
function resolveOnceArgs(key, arg2, arg3, arg4) {
|
|
285
|
+
if (typeof arg2 === "string" && arg3 !== void 0 && !isLogOptions(arg3)) {
|
|
286
|
+
return {
|
|
287
|
+
key,
|
|
288
|
+
label: arg2,
|
|
289
|
+
value: arg3,
|
|
290
|
+
options: arg4
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
key,
|
|
295
|
+
value: arg2,
|
|
296
|
+
options: isLogOptions(arg3) ? arg3 : void 0
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function resolveTimeEndArgs(key, arg2, arg3, arg4) {
|
|
300
|
+
if (arg2 === void 0) {
|
|
301
|
+
return { key };
|
|
302
|
+
}
|
|
303
|
+
if (isLogOptions(arg2)) {
|
|
304
|
+
return { key, options: arg2 };
|
|
305
|
+
}
|
|
306
|
+
if (typeof arg2 === "string" && arg3 !== void 0 && !isLogOptions(arg3)) {
|
|
307
|
+
return {
|
|
308
|
+
key,
|
|
309
|
+
label: arg2,
|
|
310
|
+
value: arg3,
|
|
311
|
+
options: arg4
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
key,
|
|
316
|
+
value: arg2,
|
|
317
|
+
options: isLogOptions(arg3) ? arg3 : void 0
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
function writeLine(method, line) {
|
|
321
|
+
const sink = console[method];
|
|
322
|
+
if (typeof sink === "function") {
|
|
323
|
+
sink(line);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
console.log(line);
|
|
327
|
+
}
|
|
328
|
+
function runLog(args, ctx) {
|
|
329
|
+
const { label, value, options } = args;
|
|
330
|
+
if (options?.enabled === false) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const level = options?.level ?? ctx?.forceLevel;
|
|
334
|
+
const consoleMethod = resolveConsoleMethod(level, options?.consoleMethod);
|
|
335
|
+
const showLevelTag = options?.showLevelTag ?? (ctx?.defaultShowLevelTag ?? false);
|
|
336
|
+
const includeLocation = options?.includeLocation ?? true;
|
|
337
|
+
const stack = includeLocation ? new Error().stack : void 0;
|
|
338
|
+
const caller = includeLocation ? getCallerFromStack(stack) : { file: "disabled", line: 0 };
|
|
84
339
|
const location = `${caller.file}:${caller.line}`;
|
|
85
|
-
const
|
|
340
|
+
const mergedContext = mergeContexts(ctx?.defaultContext, options?.context);
|
|
341
|
+
const contextualValue = injectContext(value, mergedContext);
|
|
342
|
+
const transformedValue = transformValue(contextualValue, {
|
|
343
|
+
redact: options?.redact,
|
|
344
|
+
maxArrayLength: options?.maxArrayLength
|
|
345
|
+
});
|
|
346
|
+
const formatOptions = {
|
|
347
|
+
colors: options?.colors,
|
|
348
|
+
mode: options?.mode,
|
|
349
|
+
inspectDepth: options?.inspectDepth
|
|
350
|
+
};
|
|
351
|
+
const formattedValue = formatValue(transformedValue, formatOptions);
|
|
352
|
+
const levelTag = level ? levelToTag(level) : void 0;
|
|
86
353
|
if (options?.formatter) {
|
|
87
354
|
const formatted = options.formatter({
|
|
88
355
|
location,
|
|
89
356
|
label,
|
|
90
|
-
value,
|
|
91
|
-
formattedValue
|
|
357
|
+
value: transformedValue,
|
|
358
|
+
formattedValue,
|
|
359
|
+
level,
|
|
360
|
+
levelTag
|
|
92
361
|
});
|
|
93
|
-
|
|
94
|
-
|
|
362
|
+
writeLine(consoleMethod, formatted.locationLine);
|
|
363
|
+
writeLine(consoleMethod, formatted.valueLine);
|
|
95
364
|
return;
|
|
96
365
|
}
|
|
97
|
-
|
|
98
|
-
|
|
366
|
+
if (includeLocation) {
|
|
367
|
+
writeLine(consoleMethod, location);
|
|
368
|
+
}
|
|
369
|
+
const labeledValue = formatLabeledValue(label, formattedValue);
|
|
370
|
+
const valueLine = showLevelTag && levelTag ? `${levelTag} ${String(labeledValue)}` : labeledValue;
|
|
371
|
+
writeLine(consoleMethod, valueLine);
|
|
372
|
+
}
|
|
373
|
+
var DEV_PRESET = {
|
|
374
|
+
mode: "pretty",
|
|
375
|
+
includeLocation: true,
|
|
376
|
+
colors: true
|
|
377
|
+
};
|
|
378
|
+
var PROD_PRESET = {
|
|
379
|
+
mode: "fast",
|
|
380
|
+
includeLocation: false,
|
|
381
|
+
colors: false
|
|
382
|
+
};
|
|
383
|
+
function mergeOptions(base, incoming) {
|
|
384
|
+
if (!base && !incoming) return void 0;
|
|
385
|
+
const merged = {
|
|
386
|
+
...base ?? {},
|
|
387
|
+
...incoming ?? {}
|
|
388
|
+
};
|
|
389
|
+
merged.context = mergeContexts(base?.context, incoming?.context);
|
|
390
|
+
return merged;
|
|
391
|
+
}
|
|
392
|
+
function resolveTimingLevel(durationMs, options) {
|
|
393
|
+
const errorThreshold = options?.errorThresholdMs;
|
|
394
|
+
const warnThreshold = options?.warnThresholdMs;
|
|
395
|
+
if (typeof errorThreshold === "number" && durationMs >= errorThreshold) return "error";
|
|
396
|
+
if (typeof warnThreshold === "number" && durationMs >= warnThreshold) return "warn";
|
|
397
|
+
return "info";
|
|
398
|
+
}
|
|
399
|
+
function log(arg1, arg2, arg3) {
|
|
400
|
+
runLog(resolveLogArgs(arg1, arg2, arg3));
|
|
401
|
+
}
|
|
402
|
+
function once(key, arg2, arg3, arg4) {
|
|
403
|
+
const resolved = resolveOnceArgs(key, arg2, arg3, arg4);
|
|
404
|
+
if (resolved.options?.enabled === false) return;
|
|
405
|
+
if (!checkAndMarkOnce(key)) return;
|
|
406
|
+
runLog({ label: resolved.label, value: resolved.value, options: resolved.options });
|
|
407
|
+
}
|
|
408
|
+
function resetOnce(keys) {
|
|
409
|
+
clearOnce(keys);
|
|
410
|
+
}
|
|
411
|
+
function time(key, options) {
|
|
412
|
+
if (options?.enabled === false) return;
|
|
413
|
+
const now = options?.clockNow?.() ?? Date.now();
|
|
414
|
+
startTimer(key, now);
|
|
415
|
+
}
|
|
416
|
+
function timeEnd(key, arg2, arg3, arg4) {
|
|
417
|
+
const resolved = resolveTimeEndArgs(key, arg2, arg3, arg4);
|
|
418
|
+
if (resolved.options?.enabled === false) return;
|
|
419
|
+
const now = resolved.options?.clockNow?.() ?? Date.now();
|
|
420
|
+
const durationMs = endTimer(key, now);
|
|
421
|
+
if (durationMs == null) {
|
|
422
|
+
runLog(
|
|
423
|
+
{
|
|
424
|
+
label: resolved.label ?? "timer",
|
|
425
|
+
value: {
|
|
426
|
+
key,
|
|
427
|
+
error: "timer_not_started"
|
|
428
|
+
},
|
|
429
|
+
options: resolved.options
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
forceLevel: "warn",
|
|
433
|
+
defaultShowLevelTag: true
|
|
434
|
+
}
|
|
435
|
+
);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const timedPayload = resolved.options?.includeDurationOnly ? { durationMs } : {
|
|
439
|
+
key,
|
|
440
|
+
durationMs,
|
|
441
|
+
...resolved.value !== void 0 ? { value: resolved.value } : {}
|
|
442
|
+
};
|
|
443
|
+
const timingLevel = resolveTimingLevel(durationMs, resolved.options);
|
|
444
|
+
runLog(
|
|
445
|
+
{
|
|
446
|
+
label: resolved.label ?? "timer",
|
|
447
|
+
value: timedPayload,
|
|
448
|
+
options: resolved.options
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
forceLevel: timingLevel,
|
|
452
|
+
defaultShowLevelTag: true
|
|
453
|
+
}
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
function resetTimers(keys) {
|
|
457
|
+
clearTimers(keys);
|
|
458
|
+
}
|
|
459
|
+
function logDev(arg1, arg2, arg3) {
|
|
460
|
+
const resolved = resolveLogArgs(arg1, arg2, arg3);
|
|
461
|
+
runLog({
|
|
462
|
+
...resolved,
|
|
463
|
+
options: mergeOptions(DEV_PRESET, resolved.options)
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
function logProd(arg1, arg2, arg3) {
|
|
467
|
+
const resolved = resolveLogArgs(arg1, arg2, arg3);
|
|
468
|
+
runLog({
|
|
469
|
+
...resolved,
|
|
470
|
+
options: mergeOptions(PROD_PRESET, resolved.options)
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
function makeLevelMethod(level, presetOptions, defaultContext) {
|
|
474
|
+
const method = (arg1, arg2, arg3) => {
|
|
475
|
+
const resolved = resolveLogArgs(arg1, arg2, arg3);
|
|
476
|
+
runLog(
|
|
477
|
+
{
|
|
478
|
+
...resolved,
|
|
479
|
+
options: mergeOptions(presetOptions, resolved.options)
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
forceLevel: level,
|
|
483
|
+
defaultShowLevelTag: true,
|
|
484
|
+
defaultContext
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
};
|
|
488
|
+
return method;
|
|
489
|
+
}
|
|
490
|
+
function createLogger(presetOptions) {
|
|
491
|
+
const baseContext = presetOptions?.context;
|
|
492
|
+
const fn = (arg1, arg2, arg3) => {
|
|
493
|
+
const resolved = resolveLogArgs(arg1, arg2, arg3);
|
|
494
|
+
runLog(
|
|
495
|
+
{
|
|
496
|
+
...resolved,
|
|
497
|
+
options: mergeOptions(presetOptions, resolved.options)
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
defaultContext: baseContext
|
|
501
|
+
}
|
|
502
|
+
);
|
|
503
|
+
};
|
|
504
|
+
const logger = fn;
|
|
505
|
+
logger.info = makeLevelMethod("info", presetOptions, baseContext);
|
|
506
|
+
logger.success = makeLevelMethod("success", presetOptions, baseContext);
|
|
507
|
+
logger.warn = makeLevelMethod("warn", presetOptions, baseContext);
|
|
508
|
+
logger.error = makeLevelMethod("error", presetOptions, baseContext);
|
|
509
|
+
logger.debug = makeLevelMethod("debug", presetOptions, baseContext);
|
|
510
|
+
logger.once = ((key, arg2, arg3, arg4) => {
|
|
511
|
+
const resolved = resolveOnceArgs(key, arg2, arg3, arg4);
|
|
512
|
+
const merged = mergeOptions(presetOptions, resolved.options);
|
|
513
|
+
if (merged?.enabled === false) return;
|
|
514
|
+
if (!checkAndMarkOnce(key)) return;
|
|
515
|
+
runLog(
|
|
516
|
+
{
|
|
517
|
+
label: resolved.label,
|
|
518
|
+
value: resolved.value,
|
|
519
|
+
options: merged
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
defaultContext: baseContext
|
|
523
|
+
}
|
|
524
|
+
);
|
|
525
|
+
});
|
|
526
|
+
logger.time = ((key, options) => {
|
|
527
|
+
const merged = mergeOptions(presetOptions, options);
|
|
528
|
+
if (merged?.enabled === false) return;
|
|
529
|
+
const now = merged?.clockNow?.() ?? Date.now();
|
|
530
|
+
startTimer(key, now);
|
|
531
|
+
});
|
|
532
|
+
logger.timeEnd = ((key, arg2, arg3, arg4) => {
|
|
533
|
+
const resolved = resolveTimeEndArgs(key, arg2, arg3, arg4);
|
|
534
|
+
const merged = mergeOptions(presetOptions, resolved.options);
|
|
535
|
+
if (merged?.enabled === false) return;
|
|
536
|
+
const now = merged?.clockNow?.() ?? Date.now();
|
|
537
|
+
const durationMs = endTimer(key, now);
|
|
538
|
+
if (durationMs == null) {
|
|
539
|
+
runLog(
|
|
540
|
+
{
|
|
541
|
+
label: resolved.label ?? "timer",
|
|
542
|
+
value: { key, error: "timer_not_started" },
|
|
543
|
+
options: merged
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
forceLevel: "warn",
|
|
547
|
+
defaultShowLevelTag: true,
|
|
548
|
+
defaultContext: baseContext
|
|
549
|
+
}
|
|
550
|
+
);
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
const timedPayload = merged?.includeDurationOnly ? { durationMs } : {
|
|
554
|
+
key,
|
|
555
|
+
durationMs,
|
|
556
|
+
...resolved.value !== void 0 ? { value: resolved.value } : {}
|
|
557
|
+
};
|
|
558
|
+
const level = resolveTimingLevel(durationMs, merged);
|
|
559
|
+
runLog(
|
|
560
|
+
{
|
|
561
|
+
label: resolved.label ?? "timer",
|
|
562
|
+
value: timedPayload,
|
|
563
|
+
options: merged
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
forceLevel: level,
|
|
567
|
+
defaultShowLevelTag: true,
|
|
568
|
+
defaultContext: baseContext
|
|
569
|
+
}
|
|
570
|
+
);
|
|
571
|
+
});
|
|
572
|
+
logger.withContext = (context) => {
|
|
573
|
+
return createLogger(mergeOptions(presetOptions, { context }));
|
|
574
|
+
};
|
|
575
|
+
logger.resetOnce = (keys) => clearOnce(keys);
|
|
576
|
+
logger.resetTimers = (keys) => clearTimers(keys);
|
|
577
|
+
return logger;
|
|
578
|
+
}
|
|
579
|
+
function withContext(context, presetOptions) {
|
|
580
|
+
return createLogger(mergeOptions(presetOptions, { context }));
|
|
99
581
|
}
|
|
582
|
+
var info = makeLevelMethod("info");
|
|
583
|
+
var success = makeLevelMethod("success");
|
|
584
|
+
var warn = makeLevelMethod("warn");
|
|
585
|
+
var error = makeLevelMethod("error");
|
|
586
|
+
var debug = makeLevelMethod("debug");
|
|
100
587
|
var __internal = {
|
|
101
588
|
getCallerFromStack,
|
|
102
589
|
parseFrameLine,
|
|
103
590
|
formatLabeledValue,
|
|
104
|
-
isLogOptions
|
|
591
|
+
isLogOptions,
|
|
592
|
+
resolveLogArgs,
|
|
593
|
+
mergeOptions,
|
|
594
|
+
writeLine,
|
|
595
|
+
resolveOnceArgs,
|
|
596
|
+
resolveTimeEndArgs,
|
|
597
|
+
resolveTimingLevel
|
|
105
598
|
};
|
|
106
599
|
export {
|
|
107
600
|
__internal,
|
|
108
|
-
|
|
601
|
+
createLogger,
|
|
602
|
+
debug,
|
|
603
|
+
error,
|
|
604
|
+
info,
|
|
605
|
+
log,
|
|
606
|
+
logDev,
|
|
607
|
+
logProd,
|
|
608
|
+
once,
|
|
609
|
+
resetOnce,
|
|
610
|
+
resetTimers,
|
|
611
|
+
success,
|
|
612
|
+
time,
|
|
613
|
+
timeEnd,
|
|
614
|
+
warn,
|
|
615
|
+
withContext
|
|
109
616
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "where-log",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Log values with caller file and line number.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
"build": "tsup --config tsup.config.ts",
|
|
24
24
|
"typecheck": "tsc --noEmit",
|
|
25
25
|
"test": "vitest run --pool=threads",
|
|
26
|
+
"smoke:imports": "node scripts/smoke-imports.mjs",
|
|
26
27
|
"dev": "vitest --pool=threads",
|
|
28
|
+
"bench": "node bench/run-bench.mjs",
|
|
29
|
+
"bench:ci": "node bench/run-bench.mjs --ci",
|
|
27
30
|
"pack:dry-run": "npm pack --dry-run --cache ./.npm-cache",
|
|
28
31
|
"publish:dry-run": "npm publish --dry-run --cache ./.npm-cache",
|
|
29
32
|
"release:check": "npm run pack:dry-run && npm run publish:dry-run"
|
|
@@ -43,4 +46,4 @@
|
|
|
43
46
|
"typescript": "^5.5.4",
|
|
44
47
|
"vitest": "^2.0.5"
|
|
45
48
|
}
|
|
46
|
-
}
|
|
49
|
+
}
|