@optique/logtape 0.8.0-dev.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/LICENSE +20 -0
- package/README.md +285 -0
- package/dist/index.cjs +570 -0
- package/dist/index.d.cts +615 -0
- package/dist/index.d.ts +615 -0
- package/dist/index.js +539 -0
- package/package.json +81 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
import { choice } from "@optique/core/valueparser";
|
|
2
|
+
import { flag, option } from "@optique/core/primitives";
|
|
3
|
+
import { map, multiple, optional, withDefault } from "@optique/core/modifiers";
|
|
4
|
+
import { message } from "@optique/core/message";
|
|
5
|
+
import { group, object } from "@optique/core/constructs";
|
|
6
|
+
|
|
7
|
+
//#region src/loglevel.ts
|
|
8
|
+
/**
|
|
9
|
+
* All valid log levels in order from lowest to highest severity.
|
|
10
|
+
*/
|
|
11
|
+
const LOG_LEVELS = [
|
|
12
|
+
"trace",
|
|
13
|
+
"debug",
|
|
14
|
+
"info",
|
|
15
|
+
"warning",
|
|
16
|
+
"error",
|
|
17
|
+
"fatal"
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Creates a {@link ValueParser} for LogTape log levels.
|
|
21
|
+
*
|
|
22
|
+
* This parser validates that the input is one of the valid LogTape severity
|
|
23
|
+
* levels: `"trace"`, `"debug"`, `"info"`, `"warning"`, `"error"`, or `"fatal"`.
|
|
24
|
+
* The parsing is case-insensitive.
|
|
25
|
+
*
|
|
26
|
+
* @param options Configuration options for the log level parser.
|
|
27
|
+
* @returns A {@link ValueParser} that converts string input to {@link LogLevel}.
|
|
28
|
+
*
|
|
29
|
+
* @example Basic usage
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { logLevel } from "@optique/logtape";
|
|
32
|
+
* import { option, withDefault } from "@optique/core";
|
|
33
|
+
*
|
|
34
|
+
* const parser = object({
|
|
35
|
+
* level: withDefault(
|
|
36
|
+
* option("--log-level", "-l", logLevel()),
|
|
37
|
+
* "info"
|
|
38
|
+
* ),
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @example Custom metavar
|
|
43
|
+
* ```typescript
|
|
44
|
+
* import { logLevel } from "@optique/logtape";
|
|
45
|
+
*
|
|
46
|
+
* const parser = logLevel({ metavar: "LOG_LEVEL" });
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @since 0.8.0
|
|
50
|
+
*/
|
|
51
|
+
function logLevel(options = {}) {
|
|
52
|
+
return choice(LOG_LEVELS, {
|
|
53
|
+
metavar: options.metavar ?? "LEVEL",
|
|
54
|
+
caseInsensitive: true,
|
|
55
|
+
errors: options.errors?.invalidLevel != null ? { invalidChoice: typeof options.errors.invalidLevel === "function" ? (input, _choices) => options.errors.invalidLevel(input) : options.errors.invalidLevel } : void 0
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/verbosity.ts
|
|
61
|
+
/**
|
|
62
|
+
* Mapping from verbosity count (offset from base) to log level.
|
|
63
|
+
* Index 0 is base, 1 is base+1 flag, 2 is base+2 flags, etc.
|
|
64
|
+
*/
|
|
65
|
+
const VERBOSITY_LEVELS = [
|
|
66
|
+
"fatal",
|
|
67
|
+
"error",
|
|
68
|
+
"warning",
|
|
69
|
+
"info",
|
|
70
|
+
"debug",
|
|
71
|
+
"trace"
|
|
72
|
+
];
|
|
73
|
+
/**
|
|
74
|
+
* Index of "warning" in VERBOSITY_LEVELS (the default base level).
|
|
75
|
+
*/
|
|
76
|
+
const WARNING_INDEX = 2;
|
|
77
|
+
/**
|
|
78
|
+
* Creates a parser for verbosity flags (`-v`, `-vv`, `-vvv`, etc.).
|
|
79
|
+
*
|
|
80
|
+
* This parser accumulates `-v` flags to determine the log level.
|
|
81
|
+
* Each additional `-v` flag increases the verbosity (decreases the log level
|
|
82
|
+
* severity).
|
|
83
|
+
*
|
|
84
|
+
* Default level mapping with `baseLevel: "warning"`:
|
|
85
|
+
* - No flags: `"warning"`
|
|
86
|
+
* - `-v`: `"info"`
|
|
87
|
+
* - `-vv`: `"debug"`
|
|
88
|
+
* - `-vvv` or more: `"trace"`
|
|
89
|
+
*
|
|
90
|
+
* @param options Configuration options for the verbosity parser.
|
|
91
|
+
* @returns A {@link Parser} that produces a {@link LogLevel}.
|
|
92
|
+
*
|
|
93
|
+
* @example Basic usage
|
|
94
|
+
* ```typescript
|
|
95
|
+
* import { verbosity } from "@optique/logtape";
|
|
96
|
+
* import { object } from "@optique/core/constructs";
|
|
97
|
+
*
|
|
98
|
+
* const parser = object({
|
|
99
|
+
* logLevel: verbosity(),
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* // No flags -> "warning"
|
|
103
|
+
* // -v -> "info"
|
|
104
|
+
* // -vv -> "debug"
|
|
105
|
+
* // -vvv -> "trace"
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example Custom base level
|
|
109
|
+
* ```typescript
|
|
110
|
+
* import { verbosity } from "@optique/logtape";
|
|
111
|
+
*
|
|
112
|
+
* const parser = verbosity({ baseLevel: "error" });
|
|
113
|
+
* // No flags -> "error"
|
|
114
|
+
* // -v -> "warning"
|
|
115
|
+
* // -vv -> "info"
|
|
116
|
+
* // -vvv -> "debug"
|
|
117
|
+
* // -vvvv -> "trace"
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @since 0.8.0
|
|
121
|
+
*/
|
|
122
|
+
function verbosity(options = {}) {
|
|
123
|
+
const short = options.short ?? "-v";
|
|
124
|
+
const long = options.long ?? "--verbose";
|
|
125
|
+
const baseLevel = options.baseLevel ?? "warning";
|
|
126
|
+
const baseIndex = VERBOSITY_LEVELS.indexOf(baseLevel);
|
|
127
|
+
const effectiveBaseIndex = baseIndex >= 0 ? baseIndex : WARNING_INDEX;
|
|
128
|
+
const flagParser = flag(short, long, { description: options.description });
|
|
129
|
+
const multipleFlags = multiple(flagParser);
|
|
130
|
+
return map(multipleFlags, (flags) => {
|
|
131
|
+
const count = flags.length;
|
|
132
|
+
const targetIndex = Math.min(effectiveBaseIndex + count, VERBOSITY_LEVELS.length - 1);
|
|
133
|
+
return VERBOSITY_LEVELS[targetIndex];
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/debug.ts
|
|
139
|
+
/**
|
|
140
|
+
* Creates a parser for a debug flag (`-d`, `--debug`).
|
|
141
|
+
*
|
|
142
|
+
* This parser provides a simple boolean toggle for enabling debug-level
|
|
143
|
+
* logging. When the flag is present, it returns the debug level; otherwise,
|
|
144
|
+
* it returns the normal level.
|
|
145
|
+
*
|
|
146
|
+
* @param options Configuration options for the debug flag parser.
|
|
147
|
+
* @returns A {@link Parser} that produces a {@link LogLevel}.
|
|
148
|
+
*
|
|
149
|
+
* @example Basic usage
|
|
150
|
+
* ```typescript
|
|
151
|
+
* import { debug } from "@optique/logtape";
|
|
152
|
+
* import { object } from "@optique/core/constructs";
|
|
153
|
+
*
|
|
154
|
+
* const parser = object({
|
|
155
|
+
* logLevel: debug(),
|
|
156
|
+
* });
|
|
157
|
+
*
|
|
158
|
+
* // No flag -> "info"
|
|
159
|
+
* // --debug or -d -> "debug"
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @example Custom levels
|
|
163
|
+
* ```typescript
|
|
164
|
+
* import { debug } from "@optique/logtape";
|
|
165
|
+
*
|
|
166
|
+
* const parser = debug({
|
|
167
|
+
* debugLevel: "trace",
|
|
168
|
+
* normalLevel: "warning",
|
|
169
|
+
* });
|
|
170
|
+
* // No flag -> "warning"
|
|
171
|
+
* // --debug -> "trace"
|
|
172
|
+
* ```
|
|
173
|
+
*
|
|
174
|
+
* @since 0.8.0
|
|
175
|
+
*/
|
|
176
|
+
function debug(options = {}) {
|
|
177
|
+
const short = options.short ?? "-d";
|
|
178
|
+
const long = options.long ?? "--debug";
|
|
179
|
+
const debugLevel = options.debugLevel ?? "debug";
|
|
180
|
+
const normalLevel = options.normalLevel ?? "info";
|
|
181
|
+
const flagParser = flag(short, long, { description: options.description });
|
|
182
|
+
return map(optional(flagParser), (value) => {
|
|
183
|
+
return value === true ? debugLevel : normalLevel;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/output.ts
|
|
189
|
+
/**
|
|
190
|
+
* Creates a value parser for log output destinations.
|
|
191
|
+
*
|
|
192
|
+
* This parser accepts either `-` for console output or a file path for file
|
|
193
|
+
* output. The `-` value follows the common CLI convention for representing
|
|
194
|
+
* standard output/error.
|
|
195
|
+
*
|
|
196
|
+
* @param options Configuration options for the parser.
|
|
197
|
+
* @returns A {@link ValueParser} that produces a {@link LogOutput}.
|
|
198
|
+
*/
|
|
199
|
+
function logOutputValueParser(options = {}) {
|
|
200
|
+
return {
|
|
201
|
+
metavar: options.metavar ?? "FILE",
|
|
202
|
+
parse(input) {
|
|
203
|
+
if (input === "-") return {
|
|
204
|
+
success: true,
|
|
205
|
+
value: { type: "console" }
|
|
206
|
+
};
|
|
207
|
+
if (input.trim() === "") return {
|
|
208
|
+
success: false,
|
|
209
|
+
error: options.errors?.emptyPath ? typeof options.errors.emptyPath === "function" ? options.errors.emptyPath(input) : options.errors.emptyPath : message`Log output path cannot be empty.`
|
|
210
|
+
};
|
|
211
|
+
return {
|
|
212
|
+
success: true,
|
|
213
|
+
value: {
|
|
214
|
+
type: "file",
|
|
215
|
+
path: input
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
},
|
|
219
|
+
format(value) {
|
|
220
|
+
return value.type === "console" ? "-" : value.path;
|
|
221
|
+
},
|
|
222
|
+
*suggest(prefix) {
|
|
223
|
+
if ("-".startsWith(prefix)) yield {
|
|
224
|
+
kind: "literal",
|
|
225
|
+
text: "-"
|
|
226
|
+
};
|
|
227
|
+
yield {
|
|
228
|
+
kind: "file",
|
|
229
|
+
type: "file",
|
|
230
|
+
pattern: prefix
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Creates a parser for log output destination (`--log-output`).
|
|
237
|
+
*
|
|
238
|
+
* This parser accepts either `-` for console output (following CLI convention)
|
|
239
|
+
* or a file path for file output.
|
|
240
|
+
*
|
|
241
|
+
* @param options Configuration options for the log output parser.
|
|
242
|
+
* @returns A {@link Parser} that produces a {@link LogOutput} or `undefined`.
|
|
243
|
+
*
|
|
244
|
+
* @example Basic usage
|
|
245
|
+
* ```typescript
|
|
246
|
+
* import { logOutput } from "@optique/logtape";
|
|
247
|
+
* import { object } from "@optique/core/constructs";
|
|
248
|
+
*
|
|
249
|
+
* const parser = object({
|
|
250
|
+
* output: logOutput(),
|
|
251
|
+
* });
|
|
252
|
+
*
|
|
253
|
+
* // --log-output=- -> console output
|
|
254
|
+
* // --log-output=/var/log/app.log -> file output
|
|
255
|
+
* ```
|
|
256
|
+
*
|
|
257
|
+
* @since 0.8.0
|
|
258
|
+
*/
|
|
259
|
+
function logOutput(options = {}) {
|
|
260
|
+
const long = options.long ?? "--log-output";
|
|
261
|
+
const valueParser = logOutputValueParser(options);
|
|
262
|
+
if (options.short) {
|
|
263
|
+
const short = options.short;
|
|
264
|
+
return optional(option(short, long, valueParser, { description: options.description }));
|
|
265
|
+
}
|
|
266
|
+
return optional(option(long, valueParser, { description: options.description }));
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Creates a console sink with configurable stream selection.
|
|
270
|
+
*
|
|
271
|
+
* This function creates a LogTape sink that writes to the console. The target
|
|
272
|
+
* stream (stdout or stderr) can be configured statically or dynamically per
|
|
273
|
+
* log record.
|
|
274
|
+
*
|
|
275
|
+
* @param options Configuration options for the console sink.
|
|
276
|
+
* @returns A {@link Sink} function.
|
|
277
|
+
*
|
|
278
|
+
* @example Static stream selection
|
|
279
|
+
* ```typescript
|
|
280
|
+
* import { createConsoleSink } from "@optique/logtape";
|
|
281
|
+
*
|
|
282
|
+
* const sink = createConsoleSink({ stream: "stderr" });
|
|
283
|
+
* ```
|
|
284
|
+
*
|
|
285
|
+
* @example Dynamic stream selection based on level
|
|
286
|
+
* ```typescript
|
|
287
|
+
* import { createConsoleSink } from "@optique/logtape";
|
|
288
|
+
*
|
|
289
|
+
* const sink = createConsoleSink({
|
|
290
|
+
* streamResolver: (level) =>
|
|
291
|
+
* level === "error" || level === "fatal" ? "stderr" : "stdout"
|
|
292
|
+
* });
|
|
293
|
+
* ```
|
|
294
|
+
*
|
|
295
|
+
* @since 0.8.0
|
|
296
|
+
*/
|
|
297
|
+
function createConsoleSink(options = {}) {
|
|
298
|
+
const defaultStream = options.stream ?? "stderr";
|
|
299
|
+
const streamResolver = options.streamResolver;
|
|
300
|
+
return (record) => {
|
|
301
|
+
const stream = streamResolver ? streamResolver(record.level) : defaultStream;
|
|
302
|
+
const messageParts = [];
|
|
303
|
+
for (let i = 0; i < record.message.length; i++) {
|
|
304
|
+
const part = record.message[i];
|
|
305
|
+
if (typeof part === "string") messageParts.push(part);
|
|
306
|
+
else messageParts.push(String(part));
|
|
307
|
+
}
|
|
308
|
+
const formattedMessage = messageParts.join("");
|
|
309
|
+
const timestamp = record.timestamp ? new Date(record.timestamp).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
|
|
310
|
+
const category = record.category.join(".");
|
|
311
|
+
const level = record.level.toUpperCase().padEnd(7);
|
|
312
|
+
const line = `${timestamp} [${level}] ${category}: ${formattedMessage}`;
|
|
313
|
+
if (stream === "stderr") console.error(line);
|
|
314
|
+
else console.log(line);
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Creates a sink from a {@link LogOutput} destination.
|
|
319
|
+
*
|
|
320
|
+
* For console output, this creates a console sink. For file output, this
|
|
321
|
+
* dynamically imports `@logtape/file` and creates a file sink.
|
|
322
|
+
*
|
|
323
|
+
* @param output The log output destination.
|
|
324
|
+
* @param consoleSinkOptions Options for console sink (only used when output is console).
|
|
325
|
+
* @returns A promise that resolves to a {@link Sink}.
|
|
326
|
+
* @throws {Error} If file output is requested but `@logtape/file` is not installed.
|
|
327
|
+
*
|
|
328
|
+
* @example Console output
|
|
329
|
+
* ```typescript
|
|
330
|
+
* import { createSink } from "@optique/logtape";
|
|
331
|
+
*
|
|
332
|
+
* const sink = await createSink({ type: "console" }, { stream: "stderr" });
|
|
333
|
+
* ```
|
|
334
|
+
*
|
|
335
|
+
* @example File output
|
|
336
|
+
* ```typescript
|
|
337
|
+
* import { createSink } from "@optique/logtape";
|
|
338
|
+
*
|
|
339
|
+
* const sink = await createSink({ type: "file", path: "/var/log/app.log" });
|
|
340
|
+
* ```
|
|
341
|
+
*
|
|
342
|
+
* @since 0.8.0
|
|
343
|
+
*/
|
|
344
|
+
async function createSink(output, consoleSinkOptions = {}) {
|
|
345
|
+
if (output.type === "console") return createConsoleSink(consoleSinkOptions);
|
|
346
|
+
try {
|
|
347
|
+
const { getFileSink } = await import("@logtape/file");
|
|
348
|
+
return getFileSink(output.path);
|
|
349
|
+
} catch (e) {
|
|
350
|
+
throw new Error(`File sink requires @logtape/file package. Install it with:
|
|
351
|
+
npm install @logtape/file
|
|
352
|
+
# or
|
|
353
|
+
deno add jsr:@logtape/file
|
|
354
|
+
|
|
355
|
+
Original error: ${e}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
//#endregion
|
|
360
|
+
//#region src/preset.ts
|
|
361
|
+
/**
|
|
362
|
+
* Creates a logging options parser preset.
|
|
363
|
+
*
|
|
364
|
+
* This function creates a parser that combines log level and log output
|
|
365
|
+
* options into a single group. The log level can be configured using one of
|
|
366
|
+
* three methods (mutually exclusive):
|
|
367
|
+
*
|
|
368
|
+
* - `"option"`: Explicit `--log-level=LEVEL` option
|
|
369
|
+
* - `"verbosity"`: `-v`/`-vv`/`-vvv` flags for increasing verbosity
|
|
370
|
+
* - `"debug"`: Simple `--debug` flag toggle
|
|
371
|
+
*
|
|
372
|
+
* @param config Configuration for the logging options.
|
|
373
|
+
* @returns A {@link Parser} that produces a {@link LoggingOptionsResult}.
|
|
374
|
+
*
|
|
375
|
+
* @example Using log level option
|
|
376
|
+
* ```typescript
|
|
377
|
+
* import { loggingOptions } from "@optique/logtape";
|
|
378
|
+
* import { object } from "@optique/core/constructs";
|
|
379
|
+
*
|
|
380
|
+
* const parser = object({
|
|
381
|
+
* logging: loggingOptions({ level: "option" }),
|
|
382
|
+
* });
|
|
383
|
+
* // --log-level=debug --log-output=/var/log/app.log
|
|
384
|
+
* ```
|
|
385
|
+
*
|
|
386
|
+
* @example Using verbosity flags
|
|
387
|
+
* ```typescript
|
|
388
|
+
* import { loggingOptions } from "@optique/logtape";
|
|
389
|
+
* import { object } from "@optique/core/constructs";
|
|
390
|
+
*
|
|
391
|
+
* const parser = object({
|
|
392
|
+
* logging: loggingOptions({ level: "verbosity" }),
|
|
393
|
+
* });
|
|
394
|
+
* // -vv --log-output=-
|
|
395
|
+
* ```
|
|
396
|
+
*
|
|
397
|
+
* @example Using debug flag
|
|
398
|
+
* ```typescript
|
|
399
|
+
* import { loggingOptions } from "@optique/logtape";
|
|
400
|
+
* import { object } from "@optique/core/constructs";
|
|
401
|
+
*
|
|
402
|
+
* const parser = object({
|
|
403
|
+
* logging: loggingOptions({ level: "debug" }),
|
|
404
|
+
* });
|
|
405
|
+
* // --debug
|
|
406
|
+
* ```
|
|
407
|
+
*
|
|
408
|
+
* @since 0.8.0
|
|
409
|
+
*/
|
|
410
|
+
function loggingOptions(config) {
|
|
411
|
+
const groupLabel = config.groupLabel ?? "Logging options";
|
|
412
|
+
const outputEnabled = config.output?.enabled !== false;
|
|
413
|
+
const outputLong = config.output?.long ?? "--log-output";
|
|
414
|
+
let levelParser;
|
|
415
|
+
switch (config.level) {
|
|
416
|
+
case "option": {
|
|
417
|
+
const long = config.long ?? "--log-level";
|
|
418
|
+
const short = config.short ?? "-l";
|
|
419
|
+
const defaultLevel = config.default ?? "info";
|
|
420
|
+
levelParser = withDefault(option(short, long, logLevel()), defaultLevel);
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
case "verbosity": {
|
|
424
|
+
const verbosityOptions = {
|
|
425
|
+
short: config.short,
|
|
426
|
+
long: config.long,
|
|
427
|
+
baseLevel: config.baseLevel
|
|
428
|
+
};
|
|
429
|
+
levelParser = verbosity(verbosityOptions);
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
case "debug": {
|
|
433
|
+
const debugOptions = {
|
|
434
|
+
short: config.short,
|
|
435
|
+
long: config.long,
|
|
436
|
+
debugLevel: config.debugLevel,
|
|
437
|
+
normalLevel: config.normalLevel
|
|
438
|
+
};
|
|
439
|
+
levelParser = debug(debugOptions);
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
const defaultOutput = { type: "console" };
|
|
444
|
+
const outputParser = withDefault(logOutput({ long: outputLong }), defaultOutput);
|
|
445
|
+
if (!outputEnabled) {
|
|
446
|
+
const constantOutputParser = {
|
|
447
|
+
$valueType: [],
|
|
448
|
+
$stateType: [],
|
|
449
|
+
priority: 0,
|
|
450
|
+
usage: [],
|
|
451
|
+
initialState: void 0,
|
|
452
|
+
parse: (context) => ({
|
|
453
|
+
success: true,
|
|
454
|
+
next: context,
|
|
455
|
+
consumed: []
|
|
456
|
+
}),
|
|
457
|
+
complete: () => ({
|
|
458
|
+
success: true,
|
|
459
|
+
value: defaultOutput
|
|
460
|
+
}),
|
|
461
|
+
suggest: () => [],
|
|
462
|
+
getDocFragments: () => ({ fragments: [] })
|
|
463
|
+
};
|
|
464
|
+
return group(groupLabel, object({
|
|
465
|
+
logLevel: levelParser,
|
|
466
|
+
logOutput: constantOutputParser
|
|
467
|
+
}));
|
|
468
|
+
}
|
|
469
|
+
const innerParser = object({
|
|
470
|
+
logLevel: levelParser,
|
|
471
|
+
logOutput: outputParser
|
|
472
|
+
});
|
|
473
|
+
return group(groupLabel, innerParser);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Creates a LogTape configuration from parsed logging options.
|
|
477
|
+
*
|
|
478
|
+
* This helper function converts the result of {@link loggingOptions} parser
|
|
479
|
+
* into a configuration object that can be passed to LogTape's `configure()`
|
|
480
|
+
* function.
|
|
481
|
+
*
|
|
482
|
+
* @param options The parsed logging options.
|
|
483
|
+
* @param consoleSinkOptions Options for console sink (only used when output is console).
|
|
484
|
+
* @param additionalConfig Additional LogTape configuration to merge.
|
|
485
|
+
* @returns A promise that resolves to a LogTape {@link Config}.
|
|
486
|
+
*
|
|
487
|
+
* @example Basic usage
|
|
488
|
+
* ```typescript
|
|
489
|
+
* import { loggingOptions, createLoggingConfig } from "@optique/logtape";
|
|
490
|
+
* import { configure } from "@logtape/logtape";
|
|
491
|
+
* import { object, parse } from "@optique/core";
|
|
492
|
+
*
|
|
493
|
+
* const parser = object({
|
|
494
|
+
* logging: loggingOptions({ level: "option" }),
|
|
495
|
+
* });
|
|
496
|
+
*
|
|
497
|
+
* const result = parse(parser, ["--log-level=debug"]);
|
|
498
|
+
* if (result.success) {
|
|
499
|
+
* const config = await createLoggingConfig(result.value.logging);
|
|
500
|
+
* await configure(config);
|
|
501
|
+
* }
|
|
502
|
+
* ```
|
|
503
|
+
*
|
|
504
|
+
* @example With additional configuration
|
|
505
|
+
* ```typescript
|
|
506
|
+
* import { loggingOptions, createLoggingConfig } from "@optique/logtape";
|
|
507
|
+
* import { configure } from "@logtape/logtape";
|
|
508
|
+
*
|
|
509
|
+
* const config = await createLoggingConfig(result.value.logging, {
|
|
510
|
+
* stream: "stderr",
|
|
511
|
+
* }, {
|
|
512
|
+
* loggers: [
|
|
513
|
+
* { category: ["my-app", "database"], lowestLevel: "debug", sinks: ["default"] },
|
|
514
|
+
* ],
|
|
515
|
+
* });
|
|
516
|
+
* await configure(config);
|
|
517
|
+
* ```
|
|
518
|
+
*
|
|
519
|
+
* @since 0.8.0
|
|
520
|
+
*/
|
|
521
|
+
async function createLoggingConfig(options, consoleSinkOptions = {}, additionalConfig = {}) {
|
|
522
|
+
const sink = await createSink(options.logOutput, consoleSinkOptions);
|
|
523
|
+
return {
|
|
524
|
+
sinks: {
|
|
525
|
+
default: sink,
|
|
526
|
+
...additionalConfig.sinks
|
|
527
|
+
},
|
|
528
|
+
loggers: [{
|
|
529
|
+
category: [],
|
|
530
|
+
lowestLevel: options.logLevel,
|
|
531
|
+
sinks: ["default"]
|
|
532
|
+
}, ...additionalConfig.loggers ?? []],
|
|
533
|
+
filters: additionalConfig.filters,
|
|
534
|
+
reset: additionalConfig.reset
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
//#endregion
|
|
539
|
+
export { LOG_LEVELS, createConsoleSink, createLoggingConfig, createSink, debug, logLevel, logOutput, loggingOptions, verbosity };
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@optique/logtape",
|
|
3
|
+
"version": "0.8.0-dev.1",
|
|
4
|
+
"description": "LogTape logging integration for Optique CLI parser",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"CLI",
|
|
7
|
+
"command-line",
|
|
8
|
+
"commandline",
|
|
9
|
+
"parser",
|
|
10
|
+
"logging",
|
|
11
|
+
"logtape"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "Hong Minhee",
|
|
16
|
+
"email": "hong@minhee.org",
|
|
17
|
+
"url": "https://hongminhee.org/"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://optique.dev/",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/dahlia/optique.git",
|
|
23
|
+
"directory": "packages/logtape/"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/dahlia/optique/issues"
|
|
27
|
+
},
|
|
28
|
+
"funding": [
|
|
29
|
+
"https://github.com/sponsors/dahlia"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=20.0.0",
|
|
33
|
+
"bun": ">=1.2.0",
|
|
34
|
+
"deno": ">=2.3.0"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist/",
|
|
38
|
+
"package.json",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
41
|
+
"type": "module",
|
|
42
|
+
"module": "./dist/index.js",
|
|
43
|
+
"main": "./dist/index.cjs",
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"exports": {
|
|
46
|
+
".": {
|
|
47
|
+
"types": {
|
|
48
|
+
"import": "./dist/index.d.ts",
|
|
49
|
+
"require": "./dist/index.d.cts"
|
|
50
|
+
},
|
|
51
|
+
"import": "./dist/index.js",
|
|
52
|
+
"require": "./dist/index.cjs"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"sideEffects": false,
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@logtape/logtape": "^1.2.2"
|
|
58
|
+
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"@logtape/file": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@optique/core": ""
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@logtape/logtape": "^1.2.2",
|
|
69
|
+
"@types/node": "^20.19.9",
|
|
70
|
+
"tsdown": "^0.13.0",
|
|
71
|
+
"typescript": "^5.8.3"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"build": "tsdown",
|
|
75
|
+
"prepublish": "tsdown",
|
|
76
|
+
"test": "tsdown && node --experimental-transform-types --test",
|
|
77
|
+
"test:bun": "tsdown && bun test",
|
|
78
|
+
"test:deno": "deno test",
|
|
79
|
+
"test-all": "tsdown && node --experimental-transform-types --test && bun test && deno test"
|
|
80
|
+
}
|
|
81
|
+
}
|