@fgv/ts-utils 5.1.0-30 → 5.1.0-31

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.
@@ -3137,6 +3137,28 @@ declare class Collectible<TKEY extends string = string, TINDEX extends number =
3137
3137
  warnWithDetail(message: string, detail: unknown): Success<string | undefined>;
3138
3138
  }
3139
3139
 
3140
+ /**
3141
+ * Options for {@link Logging.RetainingLogger.getRecords | RetainingLogger.getRecords}.
3142
+ * @public
3143
+ */
3144
+ declare interface IGetRecordsOptions {
3145
+ /**
3146
+ * If supplied, only records whose level would be emitted at this threshold
3147
+ * (per {@link Logging.shouldLog | shouldLog}) are returned.
3148
+ */
3149
+ readonly minLevel?: ReporterLogLevel;
3150
+ /**
3151
+ * If supplied, only records with `seq > sinceSeq` are returned, enabling
3152
+ * incremental paging from a previously-held cursor.
3153
+ */
3154
+ readonly sinceSeq?: number;
3155
+ /**
3156
+ * If supplied, returns at most this many records — the most recent N (tail),
3157
+ * still ordered oldest-first.
3158
+ */
3159
+ readonly limit?: number;
3160
+ }
3161
+
3140
3162
  /**
3141
3163
  * Parameters for constructing a {@link Collections.KeyValueConverters | KeyValueConverters} instance.
3142
3164
  * @public
@@ -3206,6 +3228,34 @@ declare class Collectible<TKEY extends string = string, TINDEX extends number =
3206
3228
  error(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
3207
3229
  }
3208
3230
 
3231
+ /**
3232
+ * A retained log record. Preserves the level and an ordering cursor so consumers
3233
+ * can filter by severity and page incrementally.
3234
+ * @public
3235
+ */
3236
+ declare interface ILogRecord {
3237
+ /**
3238
+ * Monotonic 1-based sequence number, stable across ring eviction.
3239
+ */
3240
+ readonly seq: number;
3241
+ /**
3242
+ * Milliseconds since epoch when the record was logged (from the injected clock).
3243
+ */
3244
+ readonly timestamp: number;
3245
+ /**
3246
+ * The level the record was logged at.
3247
+ */
3248
+ readonly level: MessageLogLevel;
3249
+ /**
3250
+ * The formatted message (same formatting {@link Logging.LoggerBase._format | LoggerBase._format} produces).
3251
+ */
3252
+ readonly message: string;
3253
+ /**
3254
+ * The raw structured inputs `[message, ...parameters]` before formatting.
3255
+ */
3256
+ readonly args?: readonly unknown[];
3257
+ }
3258
+
3209
3259
  /**
3210
3260
  * Parameters for creating a {@link Logging.LogReporter | LogReporter}.
3211
3261
  * @public
@@ -4307,6 +4357,19 @@ declare class Collectible<TKEY extends string = string, TINDEX extends number =
4307
4357
  * @public
4308
4358
  */
4309
4359
  protected _format(message?: unknown, ...parameters: unknown[]): string;
4360
+ /**
4361
+ * Inner hook called for logged messages alongside {@link Logging.LoggerBase._log | _log},
4362
+ * exposing the structured `(level, formatted, message, parameters)` form before it is
4363
+ * collapsed to the formatted string. The default implementation is a no-op; subclasses
4364
+ * that need to retain structured records (e.g. {@link Logging.RetainingLogger | RetainingLogger})
4365
+ * override this. Fired only in the `shouldLog` branch, so suppressed messages never reach it.
4366
+ * @param __level - The {@link MessageLogLevel | level} of the message.
4367
+ * @param __formatted - The formatted message (same string passed to `_log`).
4368
+ * @param __message - The raw message argument before formatting.
4369
+ * @param __parameters - The raw parameter arguments before formatting.
4370
+ * @public
4371
+ */
4372
+ protected _logStructured(__level: MessageLogLevel, __formatted: string, __message?: unknown, __parameters?: readonly unknown[]): void;
4310
4373
  /**
4311
4374
  * Inner method called for suppressed log messages.
4312
4375
  * @public
@@ -4338,7 +4401,11 @@ declare class Collectible<TKEY extends string = string, TINDEX extends number =
4338
4401
  LogValueFormatter,
4339
4402
  LogMessageFormatter,
4340
4403
  ILogReporterCreateParams,
4341
- LogReporter
4404
+ LogReporter,
4405
+ MultiLogger,
4406
+ ILogRecord,
4407
+ IGetRecordsOptions,
4408
+ RetainingLogger
4342
4409
  }
4343
4410
  }
4344
4411
  export { Logging }
@@ -4632,6 +4699,58 @@ declare class Collectible<TKEY extends string = string, TINDEX extends number =
4632
4699
  */
4633
4700
  export declare type MessageLogLevel = 'quiet' | 'detail' | 'info' | 'warning' | 'error';
4634
4701
 
4702
+ /**
4703
+ * An {@link Logging.ILogger | ILogger} that fans every log call out to N child loggers,
4704
+ * each applying its own threshold.
4705
+ *
4706
+ * @remarks
4707
+ * The composite does not pre-filter — it forwards the raw `(level, message, ...params)`
4708
+ * to each child's public method so each child formats and filters per its own rules.
4709
+ * This lets a single pinned logger feed, for example, a {@link Logging.ConsoleLogger | ConsoleLogger}
4710
+ * (stdout) and a {@link Logging.RetainingLogger | RetainingLogger} (observability buffer)
4711
+ * with independent log levels.
4712
+ *
4713
+ * @public
4714
+ */
4715
+ declare class MultiLogger implements ILogger {
4716
+ /**
4717
+ * The child loggers calls are fanned out to.
4718
+ * @internal
4719
+ */
4720
+ private readonly _loggers;
4721
+ /**
4722
+ * Creates a new multi logger.
4723
+ * @param loggers - The child loggers to fan calls out to.
4724
+ */
4725
+ constructor(loggers: ReadonlyArray<ILogger>);
4726
+ /**
4727
+ * The most-verbose (most-permissive) level among the children, so an upstream
4728
+ * `shouldLog` gate does not suppress a call before it can fan out to a more
4729
+ * permissive child. Computed on access, since a child's level may change.
4730
+ */
4731
+ get logLevel(): ReporterLogLevel;
4732
+ /**
4733
+ * {@inheritDoc Logging.ILogger.log}
4734
+ */
4735
+ log(level: MessageLogLevel, message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
4736
+ /**
4737
+ * {@inheritDoc Logging.ILogger.detail}
4738
+ */
4739
+ detail(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
4740
+ /**
4741
+ * {@inheritDoc Logging.ILogger.info}
4742
+ */
4743
+ info(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
4744
+ /**
4745
+ * {@inheritDoc Logging.ILogger.warn}
4746
+ */
4747
+ warn(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
4748
+ /**
4749
+ * {@inheritDoc Logging.ILogger.error}
4750
+ */
4751
+ error(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
4752
+ }
4753
+
4635
4754
  /**
4636
4755
  * A no-op {@link Logging.LoggerBase | LoggerBase} that does not log anything.
4637
4756
  * @public
@@ -5825,6 +5944,99 @@ declare class Collectible<TKEY extends string = string, TINDEX extends number =
5825
5944
  */
5826
5945
  export declare type ResultValueType<T> = T extends Result<infer TV> ? TV : never;
5827
5946
 
5947
+ /**
5948
+ * An {@link Logging.ILogger | ILogger} that retains structured log records in a bounded
5949
+ * most-recent-N ring, with a query API supporting min-severity filtering and
5950
+ * since-cursor incremental paging.
5951
+ *
5952
+ * @remarks
5953
+ * Records are captured via the {@link Logging.LoggerBase._logStructured | _logStructured} hook,
5954
+ * so the full structured form (`level` + formatted `message` + raw `args`) is retained.
5955
+ * The logger emits nowhere itself — pair it with a {@link Logging.MultiLogger | MultiLogger}
5956
+ * to also feed a {@link Logging.ConsoleLogger | ConsoleLogger} or other durable sink.
5957
+ *
5958
+ * @public
5959
+ */
5960
+ declare class RetainingLogger extends LoggerBase {
5961
+ /**
5962
+ * The fixed ring capacity — the maximum number of records retained before the
5963
+ * oldest is overwritten. A positive integer (see the constructor normalization).
5964
+ * @internal
5965
+ */
5966
+ private readonly _capacity;
5967
+ /**
5968
+ * Injected clock used to timestamp records.
5969
+ * @internal
5970
+ */
5971
+ private readonly _now;
5972
+ /**
5973
+ * The backing store, used as a circular buffer. Grows lazily up to `_capacity`,
5974
+ * after which records overwrite the oldest slot in place — eviction is O(1), with
5975
+ * no `shift()` re-indexing regardless of capacity.
5976
+ * @internal
5977
+ */
5978
+ private _buffer;
5979
+ /**
5980
+ * Index of the oldest retained record within `_buffer` once the ring is full.
5981
+ * @internal
5982
+ */
5983
+ private _head;
5984
+ /**
5985
+ * The number of valid records currently retained (`<= _capacity`).
5986
+ * @internal
5987
+ */
5988
+ private _count;
5989
+ /**
5990
+ * The most recently assigned sequence number; monotonic, stable across eviction
5991
+ * and {@link Logging.RetainingLogger.clear | clear()}.
5992
+ * @internal
5993
+ */
5994
+ private _lastSeq;
5995
+ /**
5996
+ * Creates a new retaining logger.
5997
+ * @param logLevel - The level of logging to retain. Defaults to `'detail'` to capture
5998
+ * broadly and filter at query time.
5999
+ * @param maxRecords - The maximum number of records to retain. Defaults to `1000`.
6000
+ * @param now - Injected clock returning milliseconds since epoch. Defaults to `Date.now`.
6001
+ */
6002
+ constructor(logLevel?: ReporterLogLevel, maxRecords?: number, now?: () => number);
6003
+ /**
6004
+ * The retained records, oldest-first.
6005
+ */
6006
+ get records(): ReadonlyArray<ILogRecord>;
6007
+ /**
6008
+ * The most recently assigned sequence number. A client can hold this value and
6009
+ * pass it as `sinceSeq` to page only records logged afterward.
6010
+ */
6011
+ get lastSeq(): number;
6012
+ /**
6013
+ * Returns retained records, oldest-first, optionally filtered.
6014
+ * @param options - {@link Logging.IGetRecordsOptions | Filtering and paging options}.
6015
+ * @returns The matching records, oldest-first.
6016
+ */
6017
+ getRecords(options?: IGetRecordsOptions): ReadonlyArray<ILogRecord>;
6018
+ /**
6019
+ * Clears all retained records. Does NOT reset the sequence counter, so a client
6020
+ * holding a `sinceSeq` cursor never re-sees a sequence number.
6021
+ */
6022
+ clear(): void;
6023
+ /**
6024
+ * Materializes the ring into a plain oldest-first array.
6025
+ * @internal
6026
+ */
6027
+ private _toOrderedArray;
6028
+ /**
6029
+ * {@inheritDoc Logging.LoggerBase._logStructured}
6030
+ * @internal
6031
+ */
6032
+ protected _logStructured(level: MessageLogLevel, formatted: string, message: unknown, parameters: readonly unknown[]): void;
6033
+ /**
6034
+ * {@inheritDoc Logging.LoggerBase._log}
6035
+ * @internal
6036
+ */
6037
+ protected _log(message: string, __level: MessageLogLevel): Success<string | undefined>;
6038
+ }
6039
+
5828
6040
  /**
5829
6041
  * Compares two log levels.
5830
6042
  * @param message - The first log level.
@@ -1,4 +1,6 @@
1
1
  export * from './bootLogger';
2
2
  export * from './logger';
3
3
  export * from './logReporter';
4
+ export * from './multiLogger';
5
+ export * from './retainingLogger';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/logging/index.ts"],"names":[],"mappings":"AAsBA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/logging/index.ts"],"names":[],"mappings":"AAsBA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC"}
@@ -38,4 +38,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
38
38
  __exportStar(require("./bootLogger"), exports);
39
39
  __exportStar(require("./logger"), exports);
40
40
  __exportStar(require("./logReporter"), exports);
41
+ __exportStar(require("./multiLogger"), exports);
42
+ __exportStar(require("./retainingLogger"), exports);
41
43
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/logging/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,2CAAyB;AACzB,gDAA8B","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nexport * from './bootLogger';\nexport * from './logger';\nexport * from './logReporter';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/logging/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,2CAAyB;AACzB,gDAA8B;AAC9B,gDAA8B;AAC9B,oDAAkC","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nexport * from './bootLogger';\nexport * from './logger';\nexport * from './logReporter';\nexport * from './multiLogger';\nexport * from './retainingLogger';\n"]}
@@ -171,6 +171,19 @@ export declare abstract class LoggerBase implements IDetailLogger {
171
171
  * @public
172
172
  */
173
173
  protected _format(message?: unknown, ...parameters: unknown[]): string;
174
+ /**
175
+ * Inner hook called for logged messages alongside {@link Logging.LoggerBase._log | _log},
176
+ * exposing the structured `(level, formatted, message, parameters)` form before it is
177
+ * collapsed to the formatted string. The default implementation is a no-op; subclasses
178
+ * that need to retain structured records (e.g. {@link Logging.RetainingLogger | RetainingLogger})
179
+ * override this. Fired only in the `shouldLog` branch, so suppressed messages never reach it.
180
+ * @param __level - The {@link MessageLogLevel | level} of the message.
181
+ * @param __formatted - The formatted message (same string passed to `_log`).
182
+ * @param __message - The raw message argument before formatting.
183
+ * @param __parameters - The raw parameter arguments before formatting.
184
+ * @public
185
+ */
186
+ protected _logStructured(__level: MessageLogLevel, __formatted: string, __message?: unknown, __parameters?: readonly unknown[]): void;
174
187
  /**
175
188
  * Inner method called for suppressed log messages.
176
189
  * @public
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/packlets/logging/logger.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,eAAe,EAAE,OAAO,EAA0B,MAAM,SAAS,CAAC;AAE3E;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1F;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAmBvF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAc5E;AAED;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IAEpC;;;;;;;OAOG;IACH,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEtG;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEjF;;;;;;OAMG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE/E;;;;;;OAMG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE/E;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACjF;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAc,SAAQ,OAAO;IAC5C;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE/E;;;;OAIG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC/E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,aAAa,CAKvE;AAED;;;GAGG;AACH,8BAAsB,UAAW,YAAW,aAAa;IACvD;;OAEG;IACI,QAAQ,EAAE,gBAAgB,CAAU;IAE3C,SAAS,aAAa,QAAQ,CAAC,EAAE,gBAAgB;IAIjD;;;;;;OAMG;IACI,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIvF;;;;;;OAMG;IACI,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIrF;;;;;;OAMG;IACI,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIrF;;;;;;OAMG;IACI,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAItF;;;;OAIG;IACI,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKrF;;;;OAIG;IACI,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKpF;;;;;;;OAOG;IACI,GAAG,CACR,KAAK,EAAE,eAAe,EACtB,OAAO,CAAC,EAAE,OAAO,EACjB,GAAG,UAAU,EAAE,OAAO,EAAE,GACvB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAQ9B;;;;;;OAMG;IACH,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM;IAQtE;;;OAGG;IACH,SAAS,CAAC,YAAY,CACpB,OAAO,EAAE,eAAe,EACxB,SAAS,CAAC,EAAE,OAAO,EACnB,GAAG,YAAY,EAAE,OAAO,EAAE,GACzB,OAAO,CAAC,SAAS,CAAC;IAIrB;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAC9F;AAED;;;GAGG;AACH,qBAAa,cAAe,SAAQ,UAAU;IAC5C;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAgB;IAE/B;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAgB;IAEnC;;;OAGG;gBACgB,QAAQ,CAAC,EAAE,gBAAgB;IAI9C;;OAEG;IACH,IAAW,MAAM,IAAI,MAAM,EAAE,CAE5B;IAED;;OAEG;IACH,IAAW,UAAU,IAAI,MAAM,EAAE,CAEhC;IAED;;OAEG;IACI,KAAK,IAAI,IAAI;IAKpB;;;OAGG;IACH,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKtF;;;OAGG;IACH,SAAS,CAAC,YAAY,CACpB,KAAK,EAAE,eAAe,EACtB,OAAO,CAAC,EAAE,OAAO,EACjB,GAAG,UAAU,EAAE,OAAO,EAAE,GACvB,OAAO,CAAC,SAAS,CAAC;CAKtB;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,UAAU;IAC3C;;;OAGG;gBACgB,QAAQ,CAAC,EAAE,gBAAgB;IAI9C;;;OAGG;IACH,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAiBrF;AAED;;;GAGG;AACH,qBAAa,UAAW,SAAQ,UAAU;IACxC;;;OAGG;gBACgB,QAAQ,CAAC,EAAE,gBAAgB;IAI9C;;;OAGG;IACH,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAIvF"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/packlets/logging/logger.ts"],"names":[],"mappings":"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"}
@@ -166,6 +166,7 @@ class LoggerBase {
166
166
  log(level, message, ...parameters) {
167
167
  if (shouldLog(level, this.logLevel)) {
168
168
  const formatted = this._format(message, ...parameters);
169
+ this._logStructured(level, formatted, message, parameters);
169
170
  return this._log(formatted, level);
170
171
  }
171
172
  return this._suppressLog(level, message, ...parameters);
@@ -184,6 +185,21 @@ class LoggerBase {
184
185
  const joined = strings.join('');
185
186
  return joined;
186
187
  }
188
+ /**
189
+ * Inner hook called for logged messages alongside {@link Logging.LoggerBase._log | _log},
190
+ * exposing the structured `(level, formatted, message, parameters)` form before it is
191
+ * collapsed to the formatted string. The default implementation is a no-op; subclasses
192
+ * that need to retain structured records (e.g. {@link Logging.RetainingLogger | RetainingLogger})
193
+ * override this. Fired only in the `shouldLog` branch, so suppressed messages never reach it.
194
+ * @param __level - The {@link MessageLogLevel | level} of the message.
195
+ * @param __formatted - The formatted message (same string passed to `_log`).
196
+ * @param __message - The raw message argument before formatting.
197
+ * @param __parameters - The raw parameter arguments before formatting.
198
+ * @public
199
+ */
200
+ _logStructured(__level, __formatted, __message, __parameters) {
201
+ /* no-op; subclasses that retain structured records override this */
202
+ }
187
203
  /**
188
204
  * Inner method called for suppressed log messages.
189
205
  * @public
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/packlets/logging/logger.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\nimport { MessageLogLevel, Success, captureResult, succeed } from '../base';\n\n/**\n * The level of logging to be used.\n * @public\n */\nexport type ReporterLogLevel = 'all' | 'detail' | 'info' | 'warning' | 'error' | 'silent';\n\n/**\n * Compares two log levels.\n * @param message - The first log level.\n * @param reporter - The second log level.\n * @returns `true` if the message should be logged, `false` if it should be suppressed.\n * @public\n */\nexport function shouldLog(message: MessageLogLevel, reporter: ReporterLogLevel): boolean {\n if (reporter === 'all') {\n return true; // 'all' logs everything, including 'quiet'\n }\n if (reporter === 'silent') {\n return false; // 'silent' suppresses everything\n }\n if (message === 'quiet') {\n return false; // 'quiet' messages only show when reporter is 'all'\n }\n switch (reporter) {\n case 'error':\n return message === 'error';\n case 'warning':\n return message === 'warning' || message === 'error';\n case 'info':\n return message !== 'detail';\n }\n return true;\n}\n\n/**\n * Stringifies an arbitrary value for logging.\n * @param value - The value to stringify.\n * @returns The stringified value.\n * @param maxLength - The maximum length of the stringified value.\n * @public\n */\nexport function stringifyLogValue(value: unknown, maxLength?: number): string {\n maxLength = maxLength ?? 40;\n if (typeof value === 'string') {\n return value;\n }\n const str = String(value);\n if (str === '[object Object]') {\n return captureResult(() => JSON.stringify(value))\n .onSuccess((s) => {\n return succeed(s.length < maxLength ? s : s.substring(0, maxLength - 3) + '...');\n })\n .orDefault(str);\n }\n return str;\n}\n\n/**\n * Generic Result-aware logger interface with multiple levels of logging.\n * @public\n */\nexport interface ILogger {\n /**\n * The level of logging to be used.\n */\n readonly logLevel: ReporterLogLevel;\n\n /**\n * Logs a message at the given level.\n * @param level - The level of the message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n log(level: MessageLogLevel, message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n\n /**\n * Logs a detail message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n detail(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n\n /**\n * Logs an info message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n info(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n\n /**\n * Logs a warning message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n warn(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n\n /**\n * Logs an error message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n error(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n}\n\n/**\n * Extended logger interface that supports logging a short summary message at a\n * primary level (error/warn) while emitting the full detail at `detail` level.\n *\n * The detail is suppressed by default (requires log level `'detail'` or `'all'`),\n * keeping the primary log clean while preserving the full context for debugging.\n * @public\n */\nexport interface IDetailLogger extends ILogger {\n /**\n * Logs a short error summary at `error` level, then emits `detail` at `detail` level.\n * @param message - Short human-readable summary.\n * @param detail - Full detail (e.g. raw converter error) logged at `detail` level.\n */\n errorWithDetail(message: string, detail: unknown): Success<string | undefined>;\n\n /**\n * Logs a short warning summary at `warning` level, then emits `detail` at `detail` level.\n * @param message - Short human-readable summary.\n * @param detail - Full detail logged at `detail` level.\n */\n warnWithDetail(message: string, detail: unknown): Success<string | undefined>;\n}\n\n/**\n * Type guard that checks whether a logger implements {@link IDetailLogger}.\n * @param logger - The logger to check.\n * @returns `true` if the logger implements `IDetailLogger`.\n * @public\n */\nexport function isDetailLogger(logger: ILogger): logger is IDetailLogger {\n return (\n typeof (logger as IDetailLogger).errorWithDetail === 'function' &&\n typeof (logger as IDetailLogger).warnWithDetail === 'function'\n );\n}\n\n/**\n * Abstract base class which implements {@link Logging.IDetailLogger | IDetailLogger}.\n * @public\n */\nexport abstract class LoggerBase implements IDetailLogger {\n /**\n * The level of logging to be used.\n */\n public logLevel: ReporterLogLevel = 'info';\n\n protected constructor(logLevel?: ReporterLogLevel) {\n this.logLevel = logLevel ?? 'info';\n }\n\n /**\n * Logs a detail message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public detail(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('detail', message, ...parameters);\n }\n\n /**\n * Logs an info message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public info(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('info', message, ...parameters);\n }\n\n /**\n * Logs a warning message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public warn(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('warning', message, ...parameters);\n }\n\n /**\n * Logs an error message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public error(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('error', message, ...parameters);\n }\n\n /**\n * Logs a short error summary at `error` level, then emits `detail` at `detail` level.\n * @param message - Short human-readable summary.\n * @param detail - Full detail (e.g. raw converter error) logged at `detail` level.\n */\n public errorWithDetail(message: string, detail: unknown): Success<string | undefined> {\n this.detail(detail);\n return this.error(message);\n }\n\n /**\n * Logs a short warning summary at `warning` level, then emits `detail` at `detail` level.\n * @param message - Short human-readable summary.\n * @param detail - Full detail logged at `detail` level.\n */\n public warnWithDetail(message: string, detail: unknown): Success<string | undefined> {\n this.detail(detail);\n return this.warn(message);\n }\n\n /**\n * Logs a message at the given level.\n * @param level - The level of the message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public log(\n level: MessageLogLevel,\n message?: unknown,\n ...parameters: unknown[]\n ): Success<string | undefined> {\n if (shouldLog(level, this.logLevel)) {\n const formatted = this._format(message, ...parameters);\n return this._log(formatted, level);\n }\n return this._suppressLog(level, message, ...parameters);\n }\n\n /**\n * Formats a message and parameters into a string.\n * @param message - The message to format.\n * @param parameters - The parameters to format.\n * @returns The formatted message.\n * @public\n */\n protected _format(message?: unknown, ...parameters: unknown[]): string {\n const raw = [message, ...parameters];\n const filtered = raw.filter((m): m is string => m !== undefined);\n const strings = filtered.map((m) => stringifyLogValue(m));\n const joined = strings.join('');\n return joined;\n }\n\n /**\n * Inner method called for suppressed log messages.\n * @public\n */\n protected _suppressLog(\n __level: MessageLogLevel,\n __message?: unknown,\n ...__parameters: unknown[]\n ): Success<undefined> {\n return succeed(undefined);\n }\n\n /**\n * Inner method called for logged messages. Should be implemented by derived classes.\n * @param message - The message to log.\n * @param level - The {@link MessageLogLevel | level} of the message.\n * @returns `Success` with the logged message, or `Success` with `undefined` if the message is suppressed.\n * @public\n */\n protected abstract _log(message: string, level: MessageLogLevel): Success<string | undefined>;\n}\n\n/**\n * An in-memory logger that stores logged and suppressed messages.\n * @public\n */\nexport class InMemoryLogger extends LoggerBase {\n /**\n * The messages that have been logged.\n * @internal\n */\n private _logged: string[] = [];\n\n /**\n * The messages that have been suppressed.\n * @internal\n */\n private _suppressed: string[] = [];\n\n /**\n * Creates a new in-memory logger.\n * @param logLevel - The level of logging to be used.\n */\n public constructor(logLevel?: ReporterLogLevel) {\n super(logLevel);\n }\n\n /**\n * The messages that have been logged.\n */\n public get logged(): string[] {\n return this._logged;\n }\n\n /**\n * The messages that have been suppressed.\n */\n public get suppressed(): string[] {\n return this._suppressed;\n }\n\n /**\n * Clears the logged and suppressed messages.\n */\n public clear(): void {\n this._logged = [];\n this._suppressed = [];\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._log}\n * @internal\n */\n protected _log(message: string, __level: MessageLogLevel): Success<string | undefined> {\n this._logged.push(message);\n return succeed(message);\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._suppressLog}\n * @internal\n */\n protected _suppressLog(\n level: MessageLogLevel,\n message?: unknown,\n ...parameters: unknown[]\n ): Success<undefined> {\n const formatted = this._format(message, ...parameters);\n this._suppressed.push(formatted);\n return succeed(undefined);\n }\n}\n\n/**\n * A console logger that outputs messages to the console.\n * @public\n */\nexport class ConsoleLogger extends LoggerBase {\n /**\n * Creates a new console logger.\n * @param logLevel - The level of logging to be used.\n */\n public constructor(logLevel?: ReporterLogLevel) {\n super(logLevel);\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._log}\n * @internal\n */\n protected _log(message: string, level: MessageLogLevel): Success<string | undefined> {\n switch (level) {\n case 'error':\n console.error(message);\n break;\n case 'warning':\n console.warn(message);\n break;\n case 'info':\n console.info(message);\n break;\n default:\n console.log(message);\n break;\n }\n return succeed(message);\n }\n}\n\n/**\n * A no-op {@link Logging.LoggerBase | LoggerBase} that does not log anything.\n * @public\n */\nexport class NoOpLogger extends LoggerBase {\n /**\n * Creates a new no-op logger.\n * @param logLevel - The level of logging to be used.\n */\n public constructor(logLevel?: ReporterLogLevel) {\n super(logLevel);\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._log}\n * @internal\n */\n protected _log(message: string, __level: MessageLogLevel): Success<string | undefined> {\n // no-op\n return succeed(message);\n }\n}\n"]}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/packlets/logging/logger.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\nimport { MessageLogLevel, Success, captureResult, succeed } from '../base';\n\n/**\n * The level of logging to be used.\n * @public\n */\nexport type ReporterLogLevel = 'all' | 'detail' | 'info' | 'warning' | 'error' | 'silent';\n\n/**\n * Compares two log levels.\n * @param message - The first log level.\n * @param reporter - The second log level.\n * @returns `true` if the message should be logged, `false` if it should be suppressed.\n * @public\n */\nexport function shouldLog(message: MessageLogLevel, reporter: ReporterLogLevel): boolean {\n if (reporter === 'all') {\n return true; // 'all' logs everything, including 'quiet'\n }\n if (reporter === 'silent') {\n return false; // 'silent' suppresses everything\n }\n if (message === 'quiet') {\n return false; // 'quiet' messages only show when reporter is 'all'\n }\n switch (reporter) {\n case 'error':\n return message === 'error';\n case 'warning':\n return message === 'warning' || message === 'error';\n case 'info':\n return message !== 'detail';\n }\n return true;\n}\n\n/**\n * Stringifies an arbitrary value for logging.\n * @param value - The value to stringify.\n * @returns The stringified value.\n * @param maxLength - The maximum length of the stringified value.\n * @public\n */\nexport function stringifyLogValue(value: unknown, maxLength?: number): string {\n maxLength = maxLength ?? 40;\n if (typeof value === 'string') {\n return value;\n }\n const str = String(value);\n if (str === '[object Object]') {\n return captureResult(() => JSON.stringify(value))\n .onSuccess((s) => {\n return succeed(s.length < maxLength ? s : s.substring(0, maxLength - 3) + '...');\n })\n .orDefault(str);\n }\n return str;\n}\n\n/**\n * Generic Result-aware logger interface with multiple levels of logging.\n * @public\n */\nexport interface ILogger {\n /**\n * The level of logging to be used.\n */\n readonly logLevel: ReporterLogLevel;\n\n /**\n * Logs a message at the given level.\n * @param level - The level of the message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n log(level: MessageLogLevel, message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n\n /**\n * Logs a detail message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n detail(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n\n /**\n * Logs an info message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n info(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n\n /**\n * Logs a warning message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n warn(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n\n /**\n * Logs an error message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n error(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;\n}\n\n/**\n * Extended logger interface that supports logging a short summary message at a\n * primary level (error/warn) while emitting the full detail at `detail` level.\n *\n * The detail is suppressed by default (requires log level `'detail'` or `'all'`),\n * keeping the primary log clean while preserving the full context for debugging.\n * @public\n */\nexport interface IDetailLogger extends ILogger {\n /**\n * Logs a short error summary at `error` level, then emits `detail` at `detail` level.\n * @param message - Short human-readable summary.\n * @param detail - Full detail (e.g. raw converter error) logged at `detail` level.\n */\n errorWithDetail(message: string, detail: unknown): Success<string | undefined>;\n\n /**\n * Logs a short warning summary at `warning` level, then emits `detail` at `detail` level.\n * @param message - Short human-readable summary.\n * @param detail - Full detail logged at `detail` level.\n */\n warnWithDetail(message: string, detail: unknown): Success<string | undefined>;\n}\n\n/**\n * Type guard that checks whether a logger implements {@link IDetailLogger}.\n * @param logger - The logger to check.\n * @returns `true` if the logger implements `IDetailLogger`.\n * @public\n */\nexport function isDetailLogger(logger: ILogger): logger is IDetailLogger {\n return (\n typeof (logger as IDetailLogger).errorWithDetail === 'function' &&\n typeof (logger as IDetailLogger).warnWithDetail === 'function'\n );\n}\n\n/**\n * Abstract base class which implements {@link Logging.IDetailLogger | IDetailLogger}.\n * @public\n */\nexport abstract class LoggerBase implements IDetailLogger {\n /**\n * The level of logging to be used.\n */\n public logLevel: ReporterLogLevel = 'info';\n\n protected constructor(logLevel?: ReporterLogLevel) {\n this.logLevel = logLevel ?? 'info';\n }\n\n /**\n * Logs a detail message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public detail(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('detail', message, ...parameters);\n }\n\n /**\n * Logs an info message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public info(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('info', message, ...parameters);\n }\n\n /**\n * Logs a warning message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public warn(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('warning', message, ...parameters);\n }\n\n /**\n * Logs an error message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public error(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('error', message, ...parameters);\n }\n\n /**\n * Logs a short error summary at `error` level, then emits `detail` at `detail` level.\n * @param message - Short human-readable summary.\n * @param detail - Full detail (e.g. raw converter error) logged at `detail` level.\n */\n public errorWithDetail(message: string, detail: unknown): Success<string | undefined> {\n this.detail(detail);\n return this.error(message);\n }\n\n /**\n * Logs a short warning summary at `warning` level, then emits `detail` at `detail` level.\n * @param message - Short human-readable summary.\n * @param detail - Full detail logged at `detail` level.\n */\n public warnWithDetail(message: string, detail: unknown): Success<string | undefined> {\n this.detail(detail);\n return this.warn(message);\n }\n\n /**\n * Logs a message at the given level.\n * @param level - The level of the message.\n * @param message - The message to log.\n * @param parameters - The parameters to log.\n * @returns `Success` with the logged message if the level is enabled, or\n * `Success` with `undefined` if the message is suppressed.\n */\n public log(\n level: MessageLogLevel,\n message?: unknown,\n ...parameters: unknown[]\n ): Success<string | undefined> {\n if (shouldLog(level, this.logLevel)) {\n const formatted = this._format(message, ...parameters);\n this._logStructured(level, formatted, message, parameters);\n return this._log(formatted, level);\n }\n return this._suppressLog(level, message, ...parameters);\n }\n\n /**\n * Formats a message and parameters into a string.\n * @param message - The message to format.\n * @param parameters - The parameters to format.\n * @returns The formatted message.\n * @public\n */\n protected _format(message?: unknown, ...parameters: unknown[]): string {\n const raw = [message, ...parameters];\n const filtered = raw.filter((m): m is string => m !== undefined);\n const strings = filtered.map((m) => stringifyLogValue(m));\n const joined = strings.join('');\n return joined;\n }\n\n /**\n * Inner hook called for logged messages alongside {@link Logging.LoggerBase._log | _log},\n * exposing the structured `(level, formatted, message, parameters)` form before it is\n * collapsed to the formatted string. The default implementation is a no-op; subclasses\n * that need to retain structured records (e.g. {@link Logging.RetainingLogger | RetainingLogger})\n * override this. Fired only in the `shouldLog` branch, so suppressed messages never reach it.\n * @param __level - The {@link MessageLogLevel | level} of the message.\n * @param __formatted - The formatted message (same string passed to `_log`).\n * @param __message - The raw message argument before formatting.\n * @param __parameters - The raw parameter arguments before formatting.\n * @public\n */\n protected _logStructured(\n __level: MessageLogLevel,\n __formatted: string,\n __message?: unknown,\n __parameters?: readonly unknown[]\n ): void {\n /* no-op; subclasses that retain structured records override this */\n }\n\n /**\n * Inner method called for suppressed log messages.\n * @public\n */\n protected _suppressLog(\n __level: MessageLogLevel,\n __message?: unknown,\n ...__parameters: unknown[]\n ): Success<undefined> {\n return succeed(undefined);\n }\n\n /**\n * Inner method called for logged messages. Should be implemented by derived classes.\n * @param message - The message to log.\n * @param level - The {@link MessageLogLevel | level} of the message.\n * @returns `Success` with the logged message, or `Success` with `undefined` if the message is suppressed.\n * @public\n */\n protected abstract _log(message: string, level: MessageLogLevel): Success<string | undefined>;\n}\n\n/**\n * An in-memory logger that stores logged and suppressed messages.\n * @public\n */\nexport class InMemoryLogger extends LoggerBase {\n /**\n * The messages that have been logged.\n * @internal\n */\n private _logged: string[] = [];\n\n /**\n * The messages that have been suppressed.\n * @internal\n */\n private _suppressed: string[] = [];\n\n /**\n * Creates a new in-memory logger.\n * @param logLevel - The level of logging to be used.\n */\n public constructor(logLevel?: ReporterLogLevel) {\n super(logLevel);\n }\n\n /**\n * The messages that have been logged.\n */\n public get logged(): string[] {\n return this._logged;\n }\n\n /**\n * The messages that have been suppressed.\n */\n public get suppressed(): string[] {\n return this._suppressed;\n }\n\n /**\n * Clears the logged and suppressed messages.\n */\n public clear(): void {\n this._logged = [];\n this._suppressed = [];\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._log}\n * @internal\n */\n protected _log(message: string, __level: MessageLogLevel): Success<string | undefined> {\n this._logged.push(message);\n return succeed(message);\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._suppressLog}\n * @internal\n */\n protected _suppressLog(\n level: MessageLogLevel,\n message?: unknown,\n ...parameters: unknown[]\n ): Success<undefined> {\n const formatted = this._format(message, ...parameters);\n this._suppressed.push(formatted);\n return succeed(undefined);\n }\n}\n\n/**\n * A console logger that outputs messages to the console.\n * @public\n */\nexport class ConsoleLogger extends LoggerBase {\n /**\n * Creates a new console logger.\n * @param logLevel - The level of logging to be used.\n */\n public constructor(logLevel?: ReporterLogLevel) {\n super(logLevel);\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._log}\n * @internal\n */\n protected _log(message: string, level: MessageLogLevel): Success<string | undefined> {\n switch (level) {\n case 'error':\n console.error(message);\n break;\n case 'warning':\n console.warn(message);\n break;\n case 'info':\n console.info(message);\n break;\n default:\n console.log(message);\n break;\n }\n return succeed(message);\n }\n}\n\n/**\n * A no-op {@link Logging.LoggerBase | LoggerBase} that does not log anything.\n * @public\n */\nexport class NoOpLogger extends LoggerBase {\n /**\n * Creates a new no-op logger.\n * @param logLevel - The level of logging to be used.\n */\n public constructor(logLevel?: ReporterLogLevel) {\n super(logLevel);\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._log}\n * @internal\n */\n protected _log(message: string, __level: MessageLogLevel): Success<string | undefined> {\n // no-op\n return succeed(message);\n }\n}\n"]}
@@ -0,0 +1,54 @@
1
+ import { MessageLogLevel, Success } from '../base';
2
+ import { ILogger, ReporterLogLevel } from './logger';
3
+ /**
4
+ * An {@link Logging.ILogger | ILogger} that fans every log call out to N child loggers,
5
+ * each applying its own threshold.
6
+ *
7
+ * @remarks
8
+ * The composite does not pre-filter — it forwards the raw `(level, message, ...params)`
9
+ * to each child's public method so each child formats and filters per its own rules.
10
+ * This lets a single pinned logger feed, for example, a {@link Logging.ConsoleLogger | ConsoleLogger}
11
+ * (stdout) and a {@link Logging.RetainingLogger | RetainingLogger} (observability buffer)
12
+ * with independent log levels.
13
+ *
14
+ * @public
15
+ */
16
+ export declare class MultiLogger implements ILogger {
17
+ /**
18
+ * The child loggers calls are fanned out to.
19
+ * @internal
20
+ */
21
+ private readonly _loggers;
22
+ /**
23
+ * Creates a new multi logger.
24
+ * @param loggers - The child loggers to fan calls out to.
25
+ */
26
+ constructor(loggers: ReadonlyArray<ILogger>);
27
+ /**
28
+ * The most-verbose (most-permissive) level among the children, so an upstream
29
+ * `shouldLog` gate does not suppress a call before it can fan out to a more
30
+ * permissive child. Computed on access, since a child's level may change.
31
+ */
32
+ get logLevel(): ReporterLogLevel;
33
+ /**
34
+ * {@inheritDoc Logging.ILogger.log}
35
+ */
36
+ log(level: MessageLogLevel, message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
37
+ /**
38
+ * {@inheritDoc Logging.ILogger.detail}
39
+ */
40
+ detail(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
41
+ /**
42
+ * {@inheritDoc Logging.ILogger.info}
43
+ */
44
+ info(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
45
+ /**
46
+ * {@inheritDoc Logging.ILogger.warn}
47
+ */
48
+ warn(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
49
+ /**
50
+ * {@inheritDoc Logging.ILogger.error}
51
+ */
52
+ error(message?: unknown, ...parameters: unknown[]): Success<string | undefined>;
53
+ }
54
+ //# sourceMappingURL=multiLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiLogger.d.ts","sourceRoot":"","sources":["../../../src/packlets/logging/multiLogger.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,eAAe,EAAE,OAAO,EAAW,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAiBrD;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAY,YAAW,OAAO;IACzC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAElD;;;OAGG;gBACgB,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC;IAIlD;;;;OAIG;IACH,IAAW,QAAQ,IAAI,gBAAgB,CAKtC;IAED;;OAEG;IACI,GAAG,CACR,KAAK,EAAE,eAAe,EACtB,OAAO,CAAC,EAAE,OAAO,EACjB,GAAG,UAAU,EAAE,OAAO,EAAE,GACvB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAW9B;;OAEG;IACI,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIvF;;OAEG;IACI,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIrF;;OAEG;IACI,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIrF;;OAEG;IACI,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAGvF"}
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MultiLogger = void 0;
4
+ /*
5
+ * Copyright (c) 2020 Erik Fortune
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in all
15
+ * copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ * SOFTWARE.
24
+ */
25
+ const base_1 = require("../base");
26
+ /**
27
+ * Verbosity rank for each {@link Logging.ReporterLogLevel | ReporterLogLevel}, materializing
28
+ * the {@link Logging.shouldLog | shouldLog} ordering. A higher rank is more permissive
29
+ * (emits strictly more message levels).
30
+ * @internal
31
+ */
32
+ const verbosityRank = {
33
+ silent: 0,
34
+ error: 1,
35
+ warning: 2,
36
+ info: 3,
37
+ detail: 4,
38
+ all: 5
39
+ };
40
+ /**
41
+ * An {@link Logging.ILogger | ILogger} that fans every log call out to N child loggers,
42
+ * each applying its own threshold.
43
+ *
44
+ * @remarks
45
+ * The composite does not pre-filter — it forwards the raw `(level, message, ...params)`
46
+ * to each child's public method so each child formats and filters per its own rules.
47
+ * This lets a single pinned logger feed, for example, a {@link Logging.ConsoleLogger | ConsoleLogger}
48
+ * (stdout) and a {@link Logging.RetainingLogger | RetainingLogger} (observability buffer)
49
+ * with independent log levels.
50
+ *
51
+ * @public
52
+ */
53
+ class MultiLogger {
54
+ /**
55
+ * Creates a new multi logger.
56
+ * @param loggers - The child loggers to fan calls out to.
57
+ */
58
+ constructor(loggers) {
59
+ this._loggers = [...loggers];
60
+ }
61
+ /**
62
+ * The most-verbose (most-permissive) level among the children, so an upstream
63
+ * `shouldLog` gate does not suppress a call before it can fan out to a more
64
+ * permissive child. Computed on access, since a child's level may change.
65
+ */
66
+ get logLevel() {
67
+ return this._loggers.reduce((most, logger) => (verbosityRank[logger.logLevel] > verbosityRank[most] ? logger.logLevel : most), 'silent');
68
+ }
69
+ /**
70
+ * {@inheritDoc Logging.ILogger.log}
71
+ */
72
+ log(level, message, ...parameters) {
73
+ let logged;
74
+ for (const logger of this._loggers) {
75
+ const value = logger.log(level, message, ...parameters).value;
76
+ if (value !== undefined) {
77
+ logged = value;
78
+ }
79
+ }
80
+ return (0, base_1.succeed)(logged);
81
+ }
82
+ /**
83
+ * {@inheritDoc Logging.ILogger.detail}
84
+ */
85
+ detail(message, ...parameters) {
86
+ return this.log('detail', message, ...parameters);
87
+ }
88
+ /**
89
+ * {@inheritDoc Logging.ILogger.info}
90
+ */
91
+ info(message, ...parameters) {
92
+ return this.log('info', message, ...parameters);
93
+ }
94
+ /**
95
+ * {@inheritDoc Logging.ILogger.warn}
96
+ */
97
+ warn(message, ...parameters) {
98
+ return this.log('warning', message, ...parameters);
99
+ }
100
+ /**
101
+ * {@inheritDoc Logging.ILogger.error}
102
+ */
103
+ error(message, ...parameters) {
104
+ return this.log('error', message, ...parameters);
105
+ }
106
+ }
107
+ exports.MultiLogger = MultiLogger;
108
+ //# sourceMappingURL=multiLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiLogger.js","sourceRoot":"","sources":["../../../src/packlets/logging/multiLogger.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,kCAA4D;AAG5D;;;;;GAKG;AACH,MAAM,aAAa,GAAqC;IACtD,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;CACP,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAa,WAAW;IAOtB;;;OAGG;IACH,YAAmB,OAA+B;QAChD,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACH,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CACzB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EACjG,QAAQ,CACT,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,GAAG,CACR,KAAsB,EACtB,OAAiB,EACjB,GAAG,UAAqB;QAExB,IAAI,MAA0B,CAAC;QAC/B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC,KAAK,CAAC;YAC9D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,GAAG,KAAK,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,IAAA,cAAO,EAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,OAAiB,EAAE,GAAG,UAAqB;QACvD,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACI,IAAI,CAAC,OAAiB,EAAE,GAAG,UAAqB;QACrD,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACI,IAAI,CAAC,OAAiB,EAAE,GAAG,UAAqB;QACrD,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAiB,EAAE,GAAG,UAAqB;QACtD,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,CAAC;IACnD,CAAC;CACF;AAxED,kCAwEC","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\nimport { MessageLogLevel, Success, succeed } from '../base';\nimport { ILogger, ReporterLogLevel } from './logger';\n\n/**\n * Verbosity rank for each {@link Logging.ReporterLogLevel | ReporterLogLevel}, materializing\n * the {@link Logging.shouldLog | shouldLog} ordering. A higher rank is more permissive\n * (emits strictly more message levels).\n * @internal\n */\nconst verbosityRank: Record<ReporterLogLevel, number> = {\n silent: 0,\n error: 1,\n warning: 2,\n info: 3,\n detail: 4,\n all: 5\n};\n\n/**\n * An {@link Logging.ILogger | ILogger} that fans every log call out to N child loggers,\n * each applying its own threshold.\n *\n * @remarks\n * The composite does not pre-filter — it forwards the raw `(level, message, ...params)`\n * to each child's public method so each child formats and filters per its own rules.\n * This lets a single pinned logger feed, for example, a {@link Logging.ConsoleLogger | ConsoleLogger}\n * (stdout) and a {@link Logging.RetainingLogger | RetainingLogger} (observability buffer)\n * with independent log levels.\n *\n * @public\n */\nexport class MultiLogger implements ILogger {\n /**\n * The child loggers calls are fanned out to.\n * @internal\n */\n private readonly _loggers: ReadonlyArray<ILogger>;\n\n /**\n * Creates a new multi logger.\n * @param loggers - The child loggers to fan calls out to.\n */\n public constructor(loggers: ReadonlyArray<ILogger>) {\n this._loggers = [...loggers];\n }\n\n /**\n * The most-verbose (most-permissive) level among the children, so an upstream\n * `shouldLog` gate does not suppress a call before it can fan out to a more\n * permissive child. Computed on access, since a child's level may change.\n */\n public get logLevel(): ReporterLogLevel {\n return this._loggers.reduce<ReporterLogLevel>(\n (most, logger) => (verbosityRank[logger.logLevel] > verbosityRank[most] ? logger.logLevel : most),\n 'silent'\n );\n }\n\n /**\n * {@inheritDoc Logging.ILogger.log}\n */\n public log(\n level: MessageLogLevel,\n message?: unknown,\n ...parameters: unknown[]\n ): Success<string | undefined> {\n let logged: string | undefined;\n for (const logger of this._loggers) {\n const value = logger.log(level, message, ...parameters).value;\n if (value !== undefined) {\n logged = value;\n }\n }\n return succeed(logged);\n }\n\n /**\n * {@inheritDoc Logging.ILogger.detail}\n */\n public detail(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('detail', message, ...parameters);\n }\n\n /**\n * {@inheritDoc Logging.ILogger.info}\n */\n public info(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('info', message, ...parameters);\n }\n\n /**\n * {@inheritDoc Logging.ILogger.warn}\n */\n public warn(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('warning', message, ...parameters);\n }\n\n /**\n * {@inheritDoc Logging.ILogger.error}\n */\n public error(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.log('error', message, ...parameters);\n }\n}\n"]}