@reliverse/relinka 1.5.2 → 1.5.4

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/bin/impl.d.ts CHANGED
@@ -1,115 +1,10 @@
1
- import type { DefaultColorKeys } from "@reliverse/relico";
2
- /** Configuration for special directory handling. */
3
- export type RelinkaSpecialDirsConfig = {
4
- distDirNames?: string[];
5
- useParentConfigInDist?: boolean;
6
- };
7
- /** Configuration for directory-related settings. */
8
- export type RelinkaDirsConfig = {
9
- dailyLogs?: boolean;
10
- logDir?: string;
11
- maxLogFiles?: number;
12
- specialDirs?: RelinkaSpecialDirsConfig;
13
- };
14
- /** Configuration for a single log level. */
15
- export type LogLevelConfig = {
16
- /**
17
- * Symbol to display for this log level.
18
- * @see https://symbl.cc
19
- */
20
- symbol: string;
21
- /**
22
- * Fallback symbol to use if Unicode is not supported.
23
- */
24
- fallbackSymbol: string;
25
- /**
26
- * Color to use for this log level.
27
- */
28
- color: DefaultColorKeys;
29
- /**
30
- * Number of spaces after the symbol/fallback
31
- */
32
- spacing?: number;
33
- };
34
- /** Configuration for all log levels. */
35
- export type LogLevelsConfig = Partial<Record<LogLevel, LogLevelConfig>>;
36
- /** Log level types used by the logger. */
37
- export type LogLevel = "error" | "fatal" | "info" | "success" | "verbose" | "warn" | "log" | "internal" | "null" | "step" | "box" | "message";
1
+ import { type LogLevel, type RelinkaConfig, type RelinkaConfigOptions, type RelinkaFunction } from "./setup";
2
+ /** Promise resolved once the user's config (if any) is merged. */
3
+ export declare const loadRelinkaConfig: Promise<RelinkaConfig>;
38
4
  /**
39
- * Configuration options for the Relinka logger.
40
- * All properties are optional to allow for partial configuration.
41
- * Defaults will be applied during initialization.
5
+ * Enhanced relinkaConfig function that accepts options
42
6
  */
43
- export type RelinkaConfig = {
44
- /**
45
- * Enables verbose (aka debug) mode for detailed logging.
46
- *
47
- * `true` here works only for end-users of CLIs/libs when theirs developers
48
- * has been awaited for user's config via `@reliverse/relinka`'s `await relinkaConfig;`
49
- */
50
- verbose?: boolean;
51
- /**
52
- * Configuration for directory-related settings.
53
- * - `dailyLogs`: If true, logs will be stored in a daily subdirectory.
54
- * - `logDir`: The base directory for logs.
55
- * - `maxLogFiles`: The maximum number of log files to keep before cleanup.
56
- * - `specialDirs`: Configuration for special directory handling.
57
- * - `distDirNames`: An array of directory names to check for special handling.
58
- * - `useParentConfigInDist`: If true, use the parent config in dist directories.
59
- */
60
- dirs?: RelinkaDirsConfig;
61
- /**
62
- * Disables color output in the console.
63
- */
64
- disableColors?: boolean;
65
- /**
66
- * Path to the log file.
67
- */
68
- logFilePath?: string;
69
- /**
70
- * If true, logs will be saved to a file.
71
- */
72
- saveLogsToFile?: boolean;
73
- /**
74
- * Configuration for timestamp in log messages.
75
- */
76
- timestamp?: {
77
- /**
78
- * If true, timestamps will be added to log messages.
79
- */
80
- enabled: boolean;
81
- /**
82
- * The format for timestamps. Default is YYYY-MM-DD HH:mm:ss.SSS
83
- */
84
- format?: string;
85
- };
86
- /**
87
- * Allows to customize the log levels.
88
- */
89
- levels?: LogLevelsConfig;
90
- /**
91
- * Controls how often the log cleanup runs (in milliseconds)
92
- * Default: 10000 (10 seconds)
93
- */
94
- cleanupInterval?: number;
95
- /**
96
- * Maximum size of the log write buffer before flushing to disk (in bytes)
97
- * Default: 4096 (4KB)
98
- */
99
- bufferSize?: number;
100
- /**
101
- * Maximum time to hold logs in buffer before flushing to disk (in milliseconds)
102
- * Default: 5000 (5 seconds)
103
- */
104
- maxBufferAge?: number;
105
- };
106
- /** Represents information about a log file for cleanup purposes. */
107
- export type LogFileInfo = {
108
- path: string;
109
- mtime: number;
110
- };
111
- /** Promise resolved once the user's config (if any) is merged. */
112
- export declare const relinkaConfig: Promise<RelinkaConfig>;
7
+ export declare function relinkaConfig(options?: RelinkaConfigOptions): Promise<RelinkaConfig>;
113
8
  /**
114
9
  * Shuts down the logger, flushing all buffers and clearing timers.
115
10
  * As Relinka user - call this at the end of your program to prevent hanging.
@@ -131,25 +26,6 @@ export declare function truncateString(msg: string, maxLength?: number): string;
131
26
  * Exhaustiveness check. If we land here, we missed a union case.
132
27
  */
133
28
  export declare function casesHandled(unexpectedCase: never): never;
134
- /**
135
- * Enhanced relinka function type that supports both traditional and method syntax
136
- */
137
- export type RelinkaFunction = {
138
- (type: LogLevel | "clear", message: string, ...args: unknown[]): undefined | never;
139
- error(message: string, ...args: unknown[]): void;
140
- fatal(message: string, ...args: unknown[]): never;
141
- info(message: string, ...args: unknown[]): void;
142
- success(message: string, ...args: unknown[]): void;
143
- verbose(message: string, ...args: unknown[]): void;
144
- warn(message: string, ...args: unknown[]): void;
145
- log(message: string, ...args: unknown[]): void;
146
- internal(message: string, ...args: unknown[]): void;
147
- null(message: string, ...args: unknown[]): void;
148
- step(message: string, ...args: unknown[]): void;
149
- box(message: string, ...args: unknown[]): void;
150
- message(message: string, ...args: unknown[]): void;
151
- clear(): void;
152
- };
153
29
  /**
154
30
  * Logs a message synchronously using the current config.
155
31
  * If type === "fatal", logs a fatal error and throws (never returns).
package/bin/impl.js CHANGED
@@ -3,98 +3,11 @@ import { re } from "@reliverse/relico";
3
3
  import fs from "@reliverse/relifso";
4
4
  import { loadConfig } from "c12";
5
5
  import os from "node:os";
6
- const ENABLE_DEV_DEBUG = false;
7
- const EXIT_GUARD = Symbol.for("relinka.exitHandlersRegistered");
8
- const DEFAULT_RELINKA_CONFIG = {
9
- verbose: false,
10
- dirs: {
11
- dailyLogs: false,
12
- logDir: "logs",
13
- maxLogFiles: 0,
14
- specialDirs: {
15
- distDirNames: ["dist", "dist-jsr", "dist-npm", "dist-libs"],
16
- useParentConfigInDist: true
17
- }
18
- },
19
- disableColors: false,
20
- logFilePath: "relinka.log",
21
- saveLogsToFile: false,
22
- timestamp: {
23
- enabled: false,
24
- format: "YYYY-MM-DD HH:mm:ss.SSS"
25
- },
26
- cleanupInterval: 1e4,
27
- // 10 seconds
28
- bufferSize: 4096,
29
- // 4KB
30
- maxBufferAge: 5e3,
31
- // 5 seconds
32
- // A default set of levels, with fallback symbols for non-Unicode terminals:
33
- levels: {
34
- success: {
35
- symbol: "\u2713",
36
- fallbackSymbol: "[OK]",
37
- color: "greenBright",
38
- spacing: 3
39
- },
40
- info: {
41
- symbol: "\u25C8",
42
- fallbackSymbol: "[i]",
43
- color: "cyanBright",
44
- spacing: 3
45
- },
46
- error: {
47
- symbol: "\u2716",
48
- fallbackSymbol: "[ERR]",
49
- color: "redBright",
50
- spacing: 3
51
- },
52
- warn: {
53
- symbol: "\u26A0",
54
- fallbackSymbol: "[WARN]",
55
- color: "yellowBright",
56
- spacing: 3
57
- },
58
- fatal: {
59
- symbol: "\u203C",
60
- fallbackSymbol: "[FATAL]",
61
- color: "redBright",
62
- spacing: 3
63
- },
64
- verbose: {
65
- symbol: "\u2731",
66
- fallbackSymbol: "[VERBOSE]",
67
- color: "gray",
68
- spacing: 3
69
- },
70
- internal: {
71
- symbol: "\u2699",
72
- fallbackSymbol: "[INTERNAL]",
73
- color: "magentaBright",
74
- spacing: 3
75
- },
76
- log: { symbol: "\u2502", fallbackSymbol: "|", color: "dim", spacing: 3 },
77
- step: {
78
- symbol: "\u2192",
79
- fallbackSymbol: "[STEP]",
80
- color: "blueBright",
81
- spacing: 3
82
- },
83
- box: {
84
- symbol: "\u25A0",
85
- fallbackSymbol: "[BOX]",
86
- color: "whiteBright",
87
- spacing: 1
88
- },
89
- message: {
90
- symbol: "\u{1F7A0}",
91
- fallbackSymbol: "[MSG]",
92
- color: "cyan",
93
- spacing: 3
94
- },
95
- null: { symbol: "", fallbackSymbol: "", color: "dim", spacing: 0 }
96
- }
97
- };
6
+ import {
7
+ DEFAULT_RELINKA_CONFIG,
8
+ ENABLE_DEV_DEBUG,
9
+ EXIT_GUARD
10
+ } from "./setup.js";
98
11
  function isUnicodeSupported() {
99
12
  if (process.env.TERM_PROGRAM === "vscode" || process.env.WT_SESSION || process.env.TERM_PROGRAM === "iTerm.app" || process.env.TERM_PROGRAM === "hyper" || process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm" || process.env.ConEmuTask === "{cmd::Cmder}" || process.env.TERM === "xterm-256color") {
100
13
  return true;
@@ -115,9 +28,33 @@ function isUnicodeSupported() {
115
28
  let currentConfig = { ...DEFAULT_RELINKA_CONFIG };
116
29
  let isConfigInitialized = false;
117
30
  let resolveRelinkaConfig;
118
- export const relinkaConfig = new Promise((res) => {
31
+ let userTerminalCwd;
32
+ export const loadRelinkaConfig = new Promise((res) => {
119
33
  resolveRelinkaConfig = res;
120
34
  });
35
+ export async function relinkaConfig(options = {}) {
36
+ if (!userTerminalCwd) {
37
+ userTerminalCwd = process.cwd();
38
+ }
39
+ const config = await loadRelinkaConfig;
40
+ if (options.supportFreshLogFile && isFreshLogFileEnabled(config)) {
41
+ try {
42
+ const logFilePath = getLogFilePath(config);
43
+ await fs.ensureDir(path.dirname(logFilePath));
44
+ await fs.writeFile(logFilePath, "");
45
+ if (isVerboseEnabled(config)) {
46
+ console.log(`[Relinka Fresh Log] Cleared log file: ${logFilePath}`);
47
+ }
48
+ } catch (err) {
49
+ if (isVerboseEnabled(config)) {
50
+ console.error(
51
+ `[Relinka Fresh Log Error] Failed to clear log file: ${err instanceof Error ? err.message : String(err)}`
52
+ );
53
+ }
54
+ }
55
+ }
56
+ return config;
57
+ }
121
58
  const logBuffers = /* @__PURE__ */ new Map();
122
59
  const activeTimers = [];
123
60
  let bufferFlushTimer = null;
@@ -125,22 +62,52 @@ let lastCleanupTime = 0;
125
62
  let cleanupScheduled = false;
126
63
  async function initializeConfig() {
127
64
  try {
128
- const result = await loadConfig({
129
- name: "relinka",
130
- cwd: process.cwd(),
131
- dotenv: false,
132
- packageJson: false,
133
- rcFile: false,
134
- globalRc: false,
135
- defaults: DEFAULT_RELINKA_CONFIG
136
- });
137
- currentConfig = result.config;
65
+ let result;
66
+ try {
67
+ result = await loadConfig({
68
+ name: "dler",
69
+ // name: "relinka",
70
+ cwd: process.cwd(),
71
+ dotenv: false,
72
+ packageJson: false,
73
+ rcFile: false,
74
+ globalRc: false,
75
+ defaults: {}
76
+ });
77
+ if (result.config?.relinka) {
78
+ currentConfig = { ...DEFAULT_RELINKA_CONFIG, ...result.config.relinka };
79
+ if (ENABLE_DEV_DEBUG) {
80
+ console.log("[Dev Debug] Using relinka config from dler config");
81
+ }
82
+ } else {
83
+ currentConfig = { ...DEFAULT_RELINKA_CONFIG };
84
+ if (ENABLE_DEV_DEBUG) {
85
+ console.log(
86
+ "[Dev Debug] No relinka config in dler config, using defaults"
87
+ );
88
+ }
89
+ }
90
+ } catch {
91
+ const relinkaResult = await loadConfig({
92
+ name: "relinka",
93
+ cwd: process.cwd(),
94
+ dotenv: false,
95
+ packageJson: false,
96
+ rcFile: false,
97
+ globalRc: false,
98
+ defaults: DEFAULT_RELINKA_CONFIG
99
+ });
100
+ currentConfig = relinkaResult.config;
101
+ if (ENABLE_DEV_DEBUG) {
102
+ console.log(
103
+ "[Dev Debug] Dler config loading failed, using separate relinka config"
104
+ );
105
+ }
106
+ }
138
107
  isConfigInitialized = true;
139
108
  resolveRelinkaConfig?.(currentConfig);
140
109
  resolveRelinkaConfig = void 0;
141
110
  if (ENABLE_DEV_DEBUG) {
142
- console.log("[Dev Debug] Config file used:", result.configFile);
143
- console.log("[Dev Debug] All merged layers:", result.layers);
144
111
  console.log("[Dev Debug] Final configuration:", currentConfig);
145
112
  }
146
113
  } catch (err) {
@@ -193,20 +160,15 @@ function isVerboseEnabled(config) {
193
160
  function isColorEnabled(config) {
194
161
  return !(config.disableColors ?? DEFAULT_RELINKA_CONFIG.disableColors);
195
162
  }
196
- function getLogDir(config) {
197
- return config.dirs?.logDir ?? DEFAULT_RELINKA_CONFIG.dirs?.logDir ?? "logs";
198
- }
199
- function isDailyLogsEnabled(config) {
200
- return config.dirs?.dailyLogs ?? DEFAULT_RELINKA_CONFIG.dirs?.dailyLogs ?? false;
201
- }
202
163
  function shouldSaveLogs(config) {
203
164
  return config.saveLogsToFile ?? DEFAULT_RELINKA_CONFIG.saveLogsToFile ?? false;
204
165
  }
205
166
  function getMaxLogFiles(config) {
206
- return config.dirs?.maxLogFiles ?? DEFAULT_RELINKA_CONFIG.dirs?.maxLogFiles ?? 0;
167
+ return config.dirs?.maxLogFiles ?? 0;
207
168
  }
208
169
  function getBaseLogName(config) {
209
- return config.logFilePath ?? DEFAULT_RELINKA_CONFIG.logFilePath ?? "relinka.log";
170
+ const logFileConfig = config.logFile || DEFAULT_RELINKA_CONFIG.logFile || {};
171
+ return logFileConfig.outputPath ?? "logs.log";
210
172
  }
211
173
  function getBufferSize(config) {
212
174
  return config.bufferSize ?? DEFAULT_RELINKA_CONFIG.bufferSize ?? 4096;
@@ -217,6 +179,9 @@ function getMaxBufferAge(config) {
217
179
  function getCleanupInterval(config) {
218
180
  return config.cleanupInterval ?? DEFAULT_RELINKA_CONFIG.cleanupInterval ?? 1e4;
219
181
  }
182
+ function isFreshLogFileEnabled(config) {
183
+ return config.logFile?.freshLogFile ?? DEFAULT_RELINKA_CONFIG.logFile?.freshLogFile ?? false;
184
+ }
220
185
  function isDevEnv() {
221
186
  return process.env.NODE_ENV === "development";
222
187
  }
@@ -232,18 +197,27 @@ function getTimestamp(config) {
232
197
  return format.replace("YYYY", String(now.getFullYear())).replace("MM", String(now.getMonth() + 1).padStart(2, "0")).replace("DD", String(now.getDate()).padStart(2, "0")).replace("HH", String(now.getHours()).padStart(2, "0")).replace("mm", String(now.getMinutes()).padStart(2, "0")).replace("ss", String(now.getSeconds()).padStart(2, "0")).replace("SSS", String(now.getMilliseconds()).padStart(3, "0"));
233
198
  }
234
199
  function getLogFilePath(config) {
235
- const logDir = getLogDir(config);
236
- const daily = isDailyLogsEnabled(config);
237
- let finalLogName = getBaseLogName(config);
238
- if (daily) {
239
- const datePrefix = `${getDateString()}-`;
240
- finalLogName = datePrefix + finalLogName;
200
+ const logFileConfig = config.logFile || DEFAULT_RELINKA_CONFIG.logFile || {};
201
+ const nameWithDate = logFileConfig.nameWithDate || "disable";
202
+ const outputPath = getBaseLogName(config);
203
+ const dir = path.dirname(outputPath);
204
+ let filename = path.basename(outputPath);
205
+ if (nameWithDate !== "disable") {
206
+ const dateString = getDateString();
207
+ if (nameWithDate === "append-before") {
208
+ filename = `${dateString}-${filename}`;
209
+ } else if (nameWithDate === "append-after") {
210
+ const nameWithoutExt = filename.replace(/\.log$/, "");
211
+ filename = `${nameWithoutExt}-${dateString}.log`;
212
+ }
241
213
  }
242
- if (finalLogName && !finalLogName.endsWith(".log")) {
243
- finalLogName += ".log";
214
+ if (filename && !filename.endsWith(".log")) {
215
+ filename += ".log";
244
216
  }
245
- const effectiveLogName = finalLogName || "relinka.log";
246
- return path.resolve(process.cwd(), logDir, effectiveLogName);
217
+ const effectiveFilename = filename || "logs.log";
218
+ const finalPath = dir === "." ? effectiveFilename : path.join(dir, effectiveFilename);
219
+ const baseCwd = userTerminalCwd || process.cwd();
220
+ return path.resolve(baseCwd, finalPath);
247
221
  }
248
222
  function getLevelStyle(config, level) {
249
223
  const allLevels = config.levels || DEFAULT_RELINKA_CONFIG.levels || {};
@@ -305,6 +279,7 @@ const consoleMethodMap = {
305
279
  success: console.log,
306
280
  verbose: console.log,
307
281
  log: console.log,
282
+ internal: console.log,
308
283
  step: console.log,
309
284
  box: console.log,
310
285
  message: console.log,
@@ -322,16 +297,40 @@ function logToConsole(config, level, formattedMessage) {
322
297
  method(`${colorFn(formattedMessage)}\x1B[0m`);
323
298
  }
324
299
  async function getLogFilesSortedByDate(config) {
325
- const logDirectoryPath = path.resolve(process.cwd(), getLogDir(config));
300
+ const logDirectoryPath = userTerminalCwd || process.cwd();
326
301
  try {
327
- if (!await fs.pathExists(logDirectoryPath)) {
328
- if (ENABLE_DEV_DEBUG) {
329
- console.log(`[Dev Debug] Log directory not found: ${logDirectoryPath}`);
302
+ const files = await fs.readdir(logDirectoryPath);
303
+ const logFiles = [];
304
+ for (const file of files) {
305
+ const filePath = path.join(logDirectoryPath, file);
306
+ try {
307
+ const stats = await fs.stat(filePath);
308
+ if (stats.isFile() && file.endsWith(".log")) {
309
+ logFiles.push(file);
310
+ } else if (stats.isDirectory()) {
311
+ try {
312
+ const subFiles = await fs.readdir(filePath);
313
+ for (const subFile of subFiles) {
314
+ if (subFile.endsWith(".log")) {
315
+ logFiles.push(path.join(file, subFile));
316
+ }
317
+ }
318
+ } catch (subDirErr) {
319
+ if (isVerboseEnabled(config)) {
320
+ console.error(
321
+ `[Relinka FS Debug] Error reading subdirectory ${filePath}: ${subDirErr instanceof Error ? subDirErr.message : String(subDirErr)}`
322
+ );
323
+ }
324
+ }
325
+ }
326
+ } catch (err) {
327
+ if (isVerboseEnabled(config)) {
328
+ console.error(
329
+ `[Relinka FS Debug] Error accessing ${filePath}: ${err instanceof Error ? err.message : String(err)}`
330
+ );
331
+ }
330
332
  }
331
- return [];
332
333
  }
333
- const files = await fs.readdir(logDirectoryPath);
334
- const logFiles = files.filter((f) => f.endsWith(".log"));
335
334
  if (logFiles.length === 0) return [];
336
335
  const fileInfoPromises = logFiles.map(
337
336
  async (fileName) => {
@@ -357,7 +356,7 @@ async function getLogFilesSortedByDate(config) {
357
356
  } catch (readErr) {
358
357
  if (isVerboseEnabled(config)) {
359
358
  console.error(
360
- `[Relinka FS Error] Failed reading log directory ${logDirectoryPath}: ${readErr instanceof Error ? readErr.message : String(readErr)}`
359
+ `[Relinka FS Error] Failed reading directory ${logDirectoryPath}: ${readErr instanceof Error ? readErr.message : String(readErr)}`
361
360
  );
362
361
  }
363
362
  return [];
@@ -615,7 +614,7 @@ export async function relinkaAsync(type, message, ...args) {
615
614
  console.log();
616
615
  return;
617
616
  }
618
- await relinkaConfig;
617
+ await relinkaConfig({ supportFreshLogFile: false });
619
618
  const levelName = type.toLowerCase();
620
619
  if (levelName === "fatal") {
621
620
  shouldNeverHappen(message, ...args);
@@ -658,7 +657,7 @@ export function formatBox(text) {
658
657
  const bottom = `\u2514${"\u2500".repeat(width)}\u2518`;
659
658
  const content = lines.map((line) => {
660
659
  const padding = width - line.length;
661
- return `\u2502 ${line}${" ".repeat(padding)}\u2502`;
660
+ return `\u2502 ${line}${" ".repeat(padding - 2)}\u2502`;
662
661
  }).join("\n");
663
662
  return `${top}
664
663
  ${content}
package/bin/mod.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { message, step, log, logger } from "./alias.js";
2
- export type { RelinkaSpecialDirsConfig, RelinkaDirsConfig, LogLevelConfig, LogLevelsConfig, LogLevel, RelinkaConfig, LogFileInfo, RelinkaFunction, } from "./impl.js";
3
- export { relinkaConfig, relinkaShutdown, flushAllLogBuffers, shouldNeverHappen, truncateString, casesHandled, relinka, relinkaAsync, defineConfig, formatBox, } from "./impl.js";
2
+ export type { RelinkaDirsConfig, LogLevelConfig, LogLevelsConfig, LogLevel, RelinkaConfig, LogFileInfo, RelinkaFunction, RelinkaConfigOptions, } from "./setup.js";
3
+ export { loadRelinkaConfig, relinkaConfig, relinkaShutdown, flushAllLogBuffers, shouldNeverHappen, truncateString, casesHandled, relinka, relinkaAsync, defineConfig, formatBox, } from "./impl.js";
package/bin/mod.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { message, step, log, logger } from "./alias.js";
2
2
  export {
3
+ loadRelinkaConfig,
3
4
  relinkaConfig,
4
5
  relinkaShutdown,
5
6
  flushAllLogBuffers,
package/bin/setup.d.ts ADDED
@@ -0,0 +1,144 @@
1
+ import type { DefaultColorKeys } from "@reliverse/relico";
2
+ export declare const ENABLE_DEV_DEBUG = false;
3
+ export declare const EXIT_GUARD: unique symbol;
4
+ /** Configuration for directory-related settings. */
5
+ export type RelinkaDirsConfig = {
6
+ maxLogFiles?: number;
7
+ };
8
+ /** Configuration for a single log level. */
9
+ export type LogLevelConfig = {
10
+ /**
11
+ * Symbol to display for this log level.
12
+ * @see https://symbl.cc
13
+ */
14
+ symbol: string;
15
+ /**
16
+ * Fallback symbol to use if Unicode is not supported.
17
+ */
18
+ fallbackSymbol: string;
19
+ /**
20
+ * Color to use for this log level.
21
+ */
22
+ color: DefaultColorKeys;
23
+ /**
24
+ * Number of spaces after the symbol/fallback
25
+ */
26
+ spacing?: number;
27
+ };
28
+ /** Configuration for all log levels. */
29
+ export type LogLevelsConfig = Partial<Record<LogLevel, LogLevelConfig>>;
30
+ /** Log level types used by the logger. */
31
+ export type LogLevel = "error" | "fatal" | "info" | "success" | "verbose" | "warn" | "log" | "internal" | "null" | "step" | "box" | "message";
32
+ /**
33
+ * Configuration options for the Relinka logger.
34
+ * All properties are optional to allow for partial configuration.
35
+ * Defaults will be applied during initialization.
36
+ */
37
+ export type RelinkaConfig = {
38
+ /**
39
+ * Enables verbose (aka debug) mode for detailed logging.
40
+ *
41
+ * `true` here works only for end-users of CLIs/libs when theirs developers
42
+ * has been awaited for user's config via `@reliverse/relinka`'s `await relinkaConfig;`
43
+ */
44
+ verbose?: boolean;
45
+ /**
46
+ * Configuration for directory-related settings.
47
+ * - `maxLogFiles`: The maximum number of log files to keep before cleanup.
48
+ */
49
+ dirs?: RelinkaDirsConfig;
50
+ /**
51
+ * Disables color output in the console.
52
+ */
53
+ disableColors?: boolean;
54
+ /**
55
+ * Configuration for log file output.
56
+ */
57
+ logFile?: {
58
+ /**
59
+ * Path to the log file.
60
+ */
61
+ outputPath?: string;
62
+ /**
63
+ * How to handle date in the filename.
64
+ * - `disable`: No date prefix/suffix
65
+ * - `append-before`: Add date before the filename (e.g., "2024-01-15-log.txt")
66
+ * - `append-after`: Add date after the filename (e.g., "log-2024-01-15.txt")
67
+ */
68
+ nameWithDate?: "disable" | "append-before" | "append-after";
69
+ /**
70
+ * If true, clears the log file when relinkaConfig is executed with supportFreshLogFile: true.
71
+ * This is useful for starting with a clean log file on each run.
72
+ */
73
+ freshLogFile?: boolean;
74
+ };
75
+ /**
76
+ * If true, logs will be saved to a file.
77
+ */
78
+ saveLogsToFile?: boolean;
79
+ /**
80
+ * Configuration for timestamp in log messages.
81
+ */
82
+ timestamp?: {
83
+ /**
84
+ * If true, timestamps will be added to log messages.
85
+ */
86
+ enabled: boolean;
87
+ /**
88
+ * The format for timestamps. Default is YYYY-MM-DD HH:mm:ss.SSS
89
+ */
90
+ format?: string;
91
+ };
92
+ /**
93
+ * Allows to customize the log levels.
94
+ */
95
+ levels?: LogLevelsConfig;
96
+ /**
97
+ * Controls how often the log cleanup runs (in milliseconds)
98
+ * Default: 10000 (10 seconds)
99
+ */
100
+ cleanupInterval?: number;
101
+ /**
102
+ * Maximum size of the log write buffer before flushing to disk (in bytes)
103
+ * Default: 4096 (4KB)
104
+ */
105
+ bufferSize?: number;
106
+ /**
107
+ * Maximum time to hold logs in buffer before flushing to disk (in milliseconds)
108
+ * Default: 5000 (5 seconds)
109
+ */
110
+ maxBufferAge?: number;
111
+ };
112
+ /** Represents information about a log file for cleanup purposes. */
113
+ export type LogFileInfo = {
114
+ path: string;
115
+ mtime: number;
116
+ };
117
+ /**
118
+ * Default configuration object.
119
+ * `reconf` will merge this with a config file.
120
+ */
121
+ export declare const DEFAULT_RELINKA_CONFIG: RelinkaConfig;
122
+ /**
123
+ * Enhanced relinka function type that supports both traditional and method syntax
124
+ */
125
+ export type RelinkaFunction = {
126
+ (type: LogLevel | "clear", message: string, ...args: unknown[]): undefined | never;
127
+ error(message: string, ...args: unknown[]): void;
128
+ fatal(message: string, ...args: unknown[]): never;
129
+ info(message: string, ...args: unknown[]): void;
130
+ success(message: string, ...args: unknown[]): void;
131
+ verbose(message: string, ...args: unknown[]): void;
132
+ warn(message: string, ...args: unknown[]): void;
133
+ log(message: string, ...args: unknown[]): void;
134
+ internal(message: string, ...args: unknown[]): void;
135
+ null(message: string, ...args: unknown[]): void;
136
+ step(message: string, ...args: unknown[]): void;
137
+ box(message: string, ...args: unknown[]): void;
138
+ message(message: string, ...args: unknown[]): void;
139
+ clear(): void;
140
+ };
141
+ /** Options for relinkaConfig */
142
+ export type RelinkaConfigOptions = {
143
+ supportFreshLogFile?: boolean;
144
+ };