@fgv/ts-utils 5.1.0-3 → 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.
- package/README.md +21 -0
- package/dist/index.js.map +1 -0
- package/dist/packlets/base/brand.js.map +1 -0
- package/dist/packlets/base/index.js +2 -0
- package/dist/packlets/base/index.js.map +1 -0
- package/dist/packlets/base/mapResults.js.map +1 -0
- package/dist/packlets/base/messageAggregator.js.map +1 -0
- package/dist/packlets/base/normalize.js +54 -1
- package/dist/packlets/base/normalize.js.map +1 -0
- package/dist/packlets/base/result.js +299 -2
- package/dist/packlets/base/result.js.map +1 -0
- package/dist/packlets/base/shouldNotFail.js +123 -0
- package/dist/packlets/base/shouldNotFail.js.map +1 -0
- package/dist/packlets/base/utils.js.map +1 -0
- package/dist/packlets/base/uuid.js +55 -0
- package/dist/packlets/base/uuid.js.map +1 -0
- package/dist/packlets/collections/aggregatedResultMap.js.map +1 -0
- package/dist/packlets/collections/collectible.js.map +1 -0
- package/dist/packlets/collections/collector.js +23 -9
- package/dist/packlets/collections/collector.js.map +1 -0
- package/dist/packlets/collections/collectorValidator.js +6 -1
- package/dist/packlets/collections/collectorValidator.js.map +1 -0
- package/dist/packlets/collections/common.js.map +1 -0
- package/dist/packlets/collections/converters.js.map +1 -0
- package/dist/packlets/collections/convertingCollector.js.map +1 -0
- package/dist/packlets/collections/convertingCollectorValidator.js.map +1 -0
- package/dist/packlets/collections/convertingResultMap.js.map +1 -0
- package/dist/packlets/collections/index.js.map +1 -0
- package/dist/packlets/collections/keyValueConverters.js.map +1 -0
- package/dist/packlets/collections/readOnlyConvertingResultMap.js.map +1 -0
- package/dist/packlets/collections/readonlyResultMap.js.map +1 -0
- package/dist/packlets/collections/resultMap.js.map +1 -0
- package/dist/packlets/collections/resultMapValidator.js.map +1 -0
- package/dist/packlets/collections/utils.js.map +1 -0
- package/dist/packlets/collections/validatingCollector.js.map +1 -0
- package/dist/packlets/collections/validatingConvertingCollector.js.map +1 -0
- package/dist/packlets/collections/validatingConvertingResultMap.js.map +1 -0
- package/dist/packlets/collections/validatingResultMap.js.map +1 -0
- package/dist/packlets/conversion/advancedConverters.js.map +1 -0
- package/dist/packlets/conversion/baseConverter.js +102 -16
- package/dist/packlets/conversion/baseConverter.js.map +1 -0
- package/dist/packlets/conversion/basicConverters.js.map +1 -0
- package/dist/packlets/conversion/converter.js.map +1 -0
- package/dist/packlets/conversion/converters.js.map +1 -0
- package/dist/packlets/conversion/defaultingConverter.js.map +1 -0
- package/dist/packlets/conversion/index.js.map +1 -0
- package/dist/packlets/conversion/objectConverter.js.map +1 -0
- package/dist/packlets/conversion/stringConverter.js.map +1 -0
- package/dist/packlets/hash/crcNormalizer.js.map +1 -0
- package/dist/packlets/hash/hashingNormalizer.js.map +1 -0
- package/dist/packlets/hash/index.js.map +1 -0
- package/dist/packlets/logging/bootLogger.js.map +1 -0
- package/dist/packlets/logging/index.js +2 -0
- package/dist/packlets/logging/index.js.map +1 -0
- package/dist/packlets/logging/logReporter.js.map +1 -0
- package/dist/packlets/logging/logger.js +49 -8
- package/dist/packlets/logging/logger.js.map +1 -0
- package/dist/packlets/logging/multiLogger.js +104 -0
- package/dist/packlets/logging/multiLogger.js.map +1 -0
- package/dist/packlets/logging/retainingLogger.js +161 -0
- package/dist/packlets/logging/retainingLogger.js.map +1 -0
- package/dist/packlets/validation/array.js.map +1 -0
- package/dist/packlets/validation/boolean.js.map +1 -0
- package/dist/packlets/validation/classes.js.map +1 -0
- package/dist/packlets/validation/common.js.map +1 -0
- package/dist/packlets/validation/compositeId.js.map +1 -0
- package/dist/packlets/validation/field.js.map +1 -0
- package/dist/packlets/validation/genericValidator.js.map +1 -0
- package/dist/packlets/validation/index.js.map +1 -0
- package/dist/packlets/validation/number.js.map +1 -0
- package/dist/packlets/validation/object.js.map +1 -0
- package/dist/packlets/validation/oneOf.js.map +1 -0
- package/dist/packlets/validation/string.js.map +1 -0
- package/dist/packlets/validation/traits.js.map +1 -0
- package/dist/packlets/validation/typeGuard.js.map +1 -0
- package/dist/packlets/validation/validator.js.map +1 -0
- package/dist/packlets/validation/validatorBase.js.map +1 -0
- package/dist/packlets/validation/validators.js.map +1 -0
- package/dist/ts-utils.d.ts +861 -57
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js.map +1 -0
- package/lib/packlets/base/brand.d.ts.map +1 -0
- package/lib/packlets/base/brand.js.map +1 -0
- package/lib/packlets/base/index.d.ts +2 -0
- package/lib/packlets/base/index.d.ts.map +1 -0
- package/lib/packlets/base/index.js +2 -0
- package/lib/packlets/base/index.js.map +1 -0
- package/lib/packlets/base/mapResults.d.ts.map +1 -0
- package/lib/packlets/base/mapResults.js.map +1 -0
- package/lib/packlets/base/messageAggregator.d.ts.map +1 -0
- package/lib/packlets/base/messageAggregator.js.map +1 -0
- package/lib/packlets/base/normalize.d.ts +24 -0
- package/lib/packlets/base/normalize.d.ts.map +1 -0
- package/lib/packlets/base/normalize.js +53 -0
- package/lib/packlets/base/normalize.js.map +1 -0
- package/lib/packlets/base/result.d.ts +263 -1
- package/lib/packlets/base/result.d.ts.map +1 -0
- package/lib/packlets/base/result.js +303 -3
- package/lib/packlets/base/result.js.map +1 -0
- package/lib/packlets/base/shouldNotFail.d.ts +53 -0
- package/lib/packlets/base/shouldNotFail.d.ts.map +1 -0
- package/lib/packlets/base/shouldNotFail.js +129 -0
- package/lib/packlets/base/shouldNotFail.js.map +1 -0
- package/lib/packlets/base/utils.d.ts +12 -0
- package/lib/packlets/base/utils.d.ts.map +1 -0
- package/lib/packlets/base/utils.js.map +1 -0
- package/lib/packlets/base/uuid.d.ts +27 -0
- package/lib/packlets/base/uuid.d.ts.map +1 -0
- package/lib/packlets/base/uuid.js +59 -0
- package/lib/packlets/base/uuid.js.map +1 -0
- package/lib/packlets/collections/aggregatedResultMap.d.ts.map +1 -0
- package/lib/packlets/collections/aggregatedResultMap.js.map +1 -0
- package/lib/packlets/collections/collectible.d.ts.map +1 -0
- package/lib/packlets/collections/collectible.js.map +1 -0
- package/lib/packlets/collections/collector.d.ts +23 -9
- package/lib/packlets/collections/collector.d.ts.map +1 -0
- package/lib/packlets/collections/collector.js +23 -9
- package/lib/packlets/collections/collector.js.map +1 -0
- package/lib/packlets/collections/collectorValidator.d.ts +29 -5
- package/lib/packlets/collections/collectorValidator.d.ts.map +1 -0
- package/lib/packlets/collections/collectorValidator.js +6 -1
- package/lib/packlets/collections/collectorValidator.js.map +1 -0
- package/lib/packlets/collections/common.d.ts.map +1 -0
- package/lib/packlets/collections/common.js.map +1 -0
- package/lib/packlets/collections/converters.d.ts.map +1 -0
- package/lib/packlets/collections/converters.js.map +1 -0
- package/lib/packlets/collections/convertingCollector.d.ts +21 -3
- package/lib/packlets/collections/convertingCollector.d.ts.map +1 -0
- package/lib/packlets/collections/convertingCollector.js.map +1 -0
- package/lib/packlets/collections/convertingCollectorValidator.d.ts +22 -3
- package/lib/packlets/collections/convertingCollectorValidator.d.ts.map +1 -0
- package/lib/packlets/collections/convertingCollectorValidator.js.map +1 -0
- package/lib/packlets/collections/convertingResultMap.d.ts.map +1 -0
- package/lib/packlets/collections/convertingResultMap.js.map +1 -0
- package/lib/packlets/collections/index.d.ts.map +1 -0
- package/lib/packlets/collections/index.js.map +1 -0
- package/lib/packlets/collections/keyValueConverters.d.ts.map +1 -0
- package/lib/packlets/collections/keyValueConverters.js.map +1 -0
- package/lib/packlets/collections/readOnlyConvertingResultMap.d.ts.map +1 -0
- package/lib/packlets/collections/readOnlyConvertingResultMap.js.map +1 -0
- package/lib/packlets/collections/readonlyResultMap.d.ts +18 -7
- package/lib/packlets/collections/readonlyResultMap.d.ts.map +1 -0
- package/lib/packlets/collections/readonlyResultMap.js.map +1 -0
- package/lib/packlets/collections/resultMap.d.ts.map +1 -0
- package/lib/packlets/collections/resultMap.js.map +1 -0
- package/lib/packlets/collections/resultMapValidator.d.ts.map +1 -0
- package/lib/packlets/collections/resultMapValidator.js.map +1 -0
- package/lib/packlets/collections/utils.d.ts.map +1 -0
- package/lib/packlets/collections/utils.js.map +1 -0
- package/lib/packlets/collections/validatingCollector.d.ts +7 -3
- package/lib/packlets/collections/validatingCollector.d.ts.map +1 -0
- package/lib/packlets/collections/validatingCollector.js.map +1 -0
- package/lib/packlets/collections/validatingConvertingCollector.d.ts.map +1 -0
- package/lib/packlets/collections/validatingConvertingCollector.js.map +1 -0
- package/lib/packlets/collections/validatingConvertingResultMap.d.ts.map +1 -0
- package/lib/packlets/collections/validatingConvertingResultMap.js.map +1 -0
- package/lib/packlets/collections/validatingResultMap.d.ts +2 -1
- package/lib/packlets/collections/validatingResultMap.d.ts.map +1 -0
- package/lib/packlets/collections/validatingResultMap.js.map +1 -0
- package/lib/packlets/conversion/advancedConverters.d.ts.map +1 -0
- package/lib/packlets/conversion/advancedConverters.js.map +1 -0
- package/lib/packlets/conversion/baseConverter.d.ts +102 -16
- package/lib/packlets/conversion/baseConverter.d.ts.map +1 -0
- package/lib/packlets/conversion/baseConverter.js +102 -16
- package/lib/packlets/conversion/baseConverter.js.map +1 -0
- package/lib/packlets/conversion/basicConverters.d.ts.map +1 -0
- package/lib/packlets/conversion/basicConverters.js.map +1 -0
- package/lib/packlets/conversion/converter.d.ts.map +1 -0
- package/lib/packlets/conversion/converter.js.map +1 -0
- package/lib/packlets/conversion/converters.d.ts.map +1 -0
- package/lib/packlets/conversion/converters.js.map +1 -0
- package/lib/packlets/conversion/defaultingConverter.d.ts.map +1 -0
- package/lib/packlets/conversion/defaultingConverter.js.map +1 -0
- package/lib/packlets/conversion/index.d.ts.map +1 -0
- package/lib/packlets/conversion/index.js.map +1 -0
- package/lib/packlets/conversion/objectConverter.d.ts.map +1 -0
- package/lib/packlets/conversion/objectConverter.js.map +1 -0
- package/lib/packlets/conversion/stringConverter.d.ts.map +1 -0
- package/lib/packlets/conversion/stringConverter.js.map +1 -0
- package/lib/packlets/hash/crcNormalizer.d.ts.map +1 -0
- package/lib/packlets/hash/crcNormalizer.js.map +1 -0
- package/lib/packlets/hash/hashingNormalizer.d.ts.map +1 -0
- package/lib/packlets/hash/hashingNormalizer.js.map +1 -0
- package/lib/packlets/hash/index.d.ts.map +1 -0
- package/lib/packlets/hash/index.js.map +1 -0
- package/lib/packlets/logging/bootLogger.d.ts.map +1 -0
- package/lib/packlets/logging/bootLogger.js.map +1 -0
- package/lib/packlets/logging/index.d.ts +2 -0
- package/lib/packlets/logging/index.d.ts.map +1 -0
- package/lib/packlets/logging/index.js +2 -0
- package/lib/packlets/logging/index.js.map +1 -0
- package/lib/packlets/logging/logReporter.d.ts.map +1 -0
- package/lib/packlets/logging/logReporter.js.map +1 -0
- package/lib/packlets/logging/logger.d.ts +46 -8
- package/lib/packlets/logging/logger.d.ts.map +1 -0
- package/lib/packlets/logging/logger.js +49 -8
- package/lib/packlets/logging/logger.js.map +1 -0
- package/lib/packlets/logging/multiLogger.d.ts +54 -0
- package/lib/packlets/logging/multiLogger.d.ts.map +1 -0
- package/lib/packlets/logging/multiLogger.js +108 -0
- package/lib/packlets/logging/multiLogger.js.map +1 -0
- package/lib/packlets/logging/retainingLogger.d.ts +143 -0
- package/lib/packlets/logging/retainingLogger.d.ts.map +1 -0
- package/lib/packlets/logging/retainingLogger.js +165 -0
- package/lib/packlets/logging/retainingLogger.js.map +1 -0
- package/lib/packlets/validation/array.d.ts.map +1 -0
- package/lib/packlets/validation/array.js.map +1 -0
- package/lib/packlets/validation/boolean.d.ts.map +1 -0
- package/lib/packlets/validation/boolean.js.map +1 -0
- package/lib/packlets/validation/classes.d.ts.map +1 -0
- package/lib/packlets/validation/classes.js.map +1 -0
- package/lib/packlets/validation/common.d.ts.map +1 -0
- package/lib/packlets/validation/common.js.map +1 -0
- package/lib/packlets/validation/compositeId.d.ts.map +1 -0
- package/lib/packlets/validation/compositeId.js.map +1 -0
- package/lib/packlets/validation/field.d.ts.map +1 -0
- package/lib/packlets/validation/field.js.map +1 -0
- package/lib/packlets/validation/genericValidator.d.ts.map +1 -0
- package/lib/packlets/validation/genericValidator.js.map +1 -0
- package/lib/packlets/validation/index.d.ts.map +1 -0
- package/lib/packlets/validation/index.js.map +1 -0
- package/lib/packlets/validation/number.d.ts.map +1 -0
- package/lib/packlets/validation/number.js.map +1 -0
- package/lib/packlets/validation/object.d.ts.map +1 -0
- package/lib/packlets/validation/object.js.map +1 -0
- package/lib/packlets/validation/oneOf.d.ts.map +1 -0
- package/lib/packlets/validation/oneOf.js.map +1 -0
- package/lib/packlets/validation/string.d.ts.map +1 -0
- package/lib/packlets/validation/string.js.map +1 -0
- package/lib/packlets/validation/traits.d.ts.map +1 -0
- package/lib/packlets/validation/traits.js.map +1 -0
- package/lib/packlets/validation/typeGuard.d.ts.map +1 -0
- package/lib/packlets/validation/typeGuard.js.map +1 -0
- package/lib/packlets/validation/validator.d.ts.map +1 -0
- package/lib/packlets/validation/validator.js.map +1 -0
- package/lib/packlets/validation/validatorBase.d.ts +2 -1
- package/lib/packlets/validation/validatorBase.d.ts.map +1 -0
- package/lib/packlets/validation/validatorBase.js.map +1 -0
- package/lib/packlets/validation/validators.d.ts.map +1 -0
- package/lib/packlets/validation/validators.js.map +1 -0
- package/package.json +6 -4
- package/dist/test/helpers/jest/helpers/fsHelpers.js +0 -139
- package/dist/test/helpers/jest/helpers/index.js +0 -2
- package/dist/test/helpers/jest/index.js +0 -17
- package/dist/test/helpers/jest/matchers/index.js +0 -14
- package/dist/test/helpers/jest/matchers/toFail/index.js +0 -23
- package/dist/test/helpers/jest/matchers/toFail/predicate.js +0 -5
- package/dist/test/helpers/jest/matchers/toFailTest/index.js +0 -28
- package/dist/test/helpers/jest/matchers/toFailTest/predicate.js +0 -8
- package/dist/test/helpers/jest/matchers/toFailTestAndMatchSnapshot/index.js +0 -24
- package/dist/test/helpers/jest/matchers/toFailTestAndMatchSnapshot/predicate.js +0 -11
- package/dist/test/helpers/jest/matchers/toFailTestWith/index.js +0 -29
- package/dist/test/helpers/jest/matchers/toFailTestWith/predicate.js +0 -26
- package/dist/test/helpers/jest/matchers/toFailWith/index.js +0 -27
- package/dist/test/helpers/jest/matchers/toFailWith/predicate.js +0 -16
- package/dist/test/helpers/jest/matchers/toFailWithDetail/index.js +0 -27
- package/dist/test/helpers/jest/matchers/toFailWithDetail/predicate.js +0 -22
- package/dist/test/helpers/jest/matchers/toSucceed/index.js +0 -23
- package/dist/test/helpers/jest/matchers/toSucceed/predicate.js +0 -5
- package/dist/test/helpers/jest/matchers/toSucceedAndMatchInlineSnapshot/index.js +0 -24
- package/dist/test/helpers/jest/matchers/toSucceedAndMatchSnapshot/index.js +0 -24
- package/dist/test/helpers/jest/matchers/toSucceedAndSatisfy/index.js +0 -53
- package/dist/test/helpers/jest/matchers/toSucceedAndSatisfy/predicate.js +0 -17
- package/dist/test/helpers/jest/matchers/toSucceedWith/index.js +0 -27
- package/dist/test/helpers/jest/matchers/toSucceedWith/predicate.js +0 -12
- package/dist/test/helpers/jest/matchers/toSucceedWithDetail/index.js +0 -27
- package/dist/test/helpers/jest/matchers/toSucceedWithDetail/predicate.js +0 -17
- package/dist/test/helpers/jest/resolvers/cli.js +0 -10
- package/dist/test/helpers/jest/resolvers/ide.js +0 -10
- package/dist/test/helpers/jest/ts-utils.js +0 -2
- package/dist/test/helpers/jest/types/index.js +0 -3
- package/dist/test/helpers/jest/utils/matcherHelpers.js +0 -47
- package/dist/test/helpers/jest/utils/snapshotResolver.js +0 -11
- package/dist/test/unit/collections/helpers.js +0 -106
- package/dist/test/unit/hashTextEncodeCompat.js +0 -23
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootLogger.js","sourceRoot":"","sources":["../../../src/packlets/logging/bootLogger.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 } from '../base';\nimport { IDetailLogger, ILogger, InMemoryLogger, isDetailLogger, ReporterLogLevel } from './logger';\n\n/**\n * A recorded log entry capturing the raw arguments before formatting.\n * @internal\n */\ninterface IBootLogEntry {\n readonly level: MessageLogLevel;\n readonly message: unknown;\n readonly parameters: unknown[];\n}\n\n/**\n * A logger that buffers log entries during startup, then replays them\n * to a real logger once it becomes available.\n *\n * @remarks\n * During application bootstrap, the real logger (e.g. one backed by\n * toast notifications) may not be available yet. `BootLogger` solves\n * this by:\n * 1. Buffering all log calls in memory during the boot phase.\n * 2. When {@link BootLogger.ready | ready()} is called with the real\n * logger, replaying all buffered entries and then forwarding all\n * subsequent calls directly.\n *\n * @example\n * ```typescript\n * // Create early, before the real logger exists\n * const bootLogger = new BootLogger('detail');\n * bootLogger.info('Starting up...');\n *\n * // Later, when the real logger is available\n * bootLogger.ready(realLogger);\n * // 'Starting up...' is replayed to realLogger\n * // All future calls go directly to realLogger\n * ```\n *\n * @public\n */\nexport class BootLogger implements IDetailLogger {\n private _buffer: IBootLogEntry[] = [];\n private _delegate: ILogger;\n private _isReady: boolean = false;\n\n /**\n * Creates a new boot logger.\n * @param logLevel - The log level for the initial in-memory buffer phase.\n * Defaults to 'detail' to capture everything during boot.\n */\n public constructor(logLevel?: ReporterLogLevel) {\n this._delegate = new InMemoryLogger(logLevel ?? 'detail');\n }\n\n /**\n * {@inheritDoc Logging.ILogger.logLevel}\n */\n public get logLevel(): ReporterLogLevel {\n return this._delegate.logLevel;\n }\n\n /**\n * Whether the boot logger has been connected to a real logger.\n */\n public get isReady(): boolean {\n return this._isReady;\n }\n\n /**\n * Connects this boot logger to a real logger.\n * All buffered entries are replayed to the new logger in order,\n * and all subsequent calls are forwarded directly.\n * @param logger - The real logger to forward to.\n */\n public ready(logger: ILogger): void {\n // Replay buffered entries\n for (const entry of this._buffer) {\n logger.log(entry.level, entry.message, ...entry.parameters);\n }\n\n // Switch to the real logger and discard the buffer\n this._delegate = logger;\n this._buffer = [];\n this._isReady = true;\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 if (!this._isReady) {\n this._buffer.push({ level, message, parameters });\n }\n return this._delegate.log(level, message, ...parameters);\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 /**\n * {@inheritDoc Logging.IDetailLogger.errorWithDetail}\n */\n public errorWithDetail(message: string, detail: unknown): Success<string | undefined> {\n if (isDetailLogger(this._delegate)) {\n return this._delegate.errorWithDetail(message, detail);\n }\n this.log('detail', detail);\n return this.log('error', message);\n }\n\n /**\n * {@inheritDoc Logging.IDetailLogger.warnWithDetail}\n */\n public warnWithDetail(message: string, detail: unknown): Success<string | undefined> {\n if (isDetailLogger(this._delegate)) {\n return this._delegate.warnWithDetail(message, detail);\n }\n this.log('detail', detail);\n return this.log('warning', message);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/logging/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC","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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logReporter.js","sourceRoot":"","sources":["../../../src/packlets/logging/logReporter.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 {\n IDetailLogger,\n ILogger,\n isDetailLogger,\n ReporterLogLevel,\n NoOpLogger,\n stringifyLogValue\n} from './logger';\nimport { captureResult, ErrorFormatter, IResultReporter, MessageLogLevel, Result, Success } from '../base';\n\n/**\n * A function that formats a value for logging.\n * @public\n */\nexport type LogValueFormatter<T, TD = unknown> = (value: T, detail?: TD) => string;\n\n/**\n * A function that formats a message for logging.\n * @public\n */\nexport type LogMessageFormatter<TD = unknown> = (message: string, detail?: TD) => string;\n\n/**\n * Parameters for creating a {@link Logging.LogReporter | LogReporter}.\n * @public\n */\nexport interface ILogReporterCreateParams<T, TD = unknown> {\n logger?: ILogger;\n valueFormatter?: LogValueFormatter<T, TD>;\n messageFormatter?: LogMessageFormatter<TD>;\n}\n\n/**\n * Abstract base class which wraps an existing {@link Logging.ILogger | ILogger} to implement\n * both {@link Logging.ILogger | ILogger} and {@link IResultReporter | IResultReporter}.\n * @public\n */\nexport class LogReporter<T, TD = unknown> implements IDetailLogger, IResultReporter<T, TD> {\n /**\n * Base logger used to by this reporter.\n * @public\n */\n public readonly logger: ILogger;\n\n /**\n * The formatter to use for values.\n * @internal\n */\n protected readonly _valueFormatter: LogValueFormatter<T, TD>;\n\n /**\n * The formatter to use for messages.\n * @internal\n */\n protected readonly _messageFormatter: LogMessageFormatter<TD>;\n\n /**\n * Creates a new {@link Logging.LogReporter | LogReporter}.\n * @param params - The parameters for creating the {@link Logging.LogReporter | LogReporter}.\n */\n public constructor(params?: ILogReporterCreateParams<T, TD>) {\n /* c8 ignore next 1 */\n params = params ?? {};\n this.logger = params.logger ?? new NoOpLogger();\n this._valueFormatter = params.valueFormatter ?? LogReporter.tryFormatObject;\n this._messageFormatter = params.messageFormatter ?? ((message, __detail) => message);\n }\n\n /**\n * Creates a default {@link Logging.LogReporter | LogReporter} with a {@link Logging.NoOpLogger | NoOpLogger} with the\n * supplied parameters, returning both the logger and reporter.\n * @param logger - Optional logger to use; defaults to a new {@link Logging.NoOpLogger | NoOpLogger} if not provided.\n * @returns\n */\n public static createDefault(logger?: ILogger): Result<LogReporter<unknown>> {\n logger = logger ?? new NoOpLogger();\n return captureResult(() => new LogReporter<unknown>({ logger }));\n }\n\n /**\n * {@inheritDoc Logging.ILogger.logLevel}\n */\n public get logLevel(): ReporterLogLevel {\n return this.logger.logLevel;\n }\n\n /**\n * {@inheritDoc Logging.ILogger.detail}\n */\n public detail(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.logger.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.logger.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.logger.warn(message, ...parameters);\n }\n\n /**\n * {@inheritDoc Logging.ILogger.error}\n */\n public error(message?: unknown, ...parameters: unknown[]): Success<string | undefined> {\n return this.logger.error(message, ...parameters);\n }\n\n /**\n * {@inheritDoc Logging.IDetailLogger.errorWithDetail}\n */\n public errorWithDetail(message: string, detail: unknown): Success<string | undefined> {\n if (isDetailLogger(this.logger)) {\n return this.logger.errorWithDetail(message, detail);\n }\n this.logger.detail(detail);\n return this.logger.error(message);\n }\n\n /**\n * {@inheritDoc Logging.IDetailLogger.warnWithDetail}\n */\n public warnWithDetail(message: string, detail: unknown): Success<string | undefined> {\n if (isDetailLogger(this.logger)) {\n return this.logger.warnWithDetail(message, detail);\n }\n this.logger.detail(detail);\n return this.logger.warn(message);\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 return this.logger.log(level, message, ...parameters);\n }\n\n /**\n * {@inheritDoc IResultReporter.reportSuccess}\n */\n public reportSuccess(level: MessageLogLevel, value: T, detail?: TD, message?: ErrorFormatter<TD>): void {\n const formattedValue = this._valueFormatter(value, detail);\n const formatted = message ? message(formattedValue, detail) : formattedValue;\n this.log(level, formatted);\n }\n\n /**\n * {@inheritDoc IResultReporter.reportFailure}\n */\n public reportFailure(level: MessageLogLevel, message: string, detail?: TD): void {\n const formatted = this._messageFormatter(message, detail);\n this.log(level, formatted);\n }\n\n /**\n * Creates a new {@link Logging.LogReporter | LogReporter} with the same logger but a different value formatter.\n * @param valueFormatter - The value formatter to use.\n * @returns A new {@link Logging.LogReporter | LogReporter} with the same logger but a different value formatter.\n */\n public withValueFormatter<TN>(valueFormatter: LogValueFormatter<TN, TD>): LogReporter<TN, TD> {\n return new LogReporter<TN, TD>({\n logger: this.logger,\n valueFormatter,\n messageFormatter: this._messageFormatter\n });\n }\n\n /**\n * Generic method to try to format an object for logging.\n * @param value - The value to format.\n * @param detail - The detail to format.\n * @returns\n */\n public static tryFormatObject<T = unknown, TD = unknown>(value: T, detail?: TD): string {\n return stringifyLogValue(value);\n }\n}\n"]}
|
|
@@ -86,55 +86,81 @@ export function isDetailLogger(logger) {
|
|
|
86
86
|
export class LoggerBase {
|
|
87
87
|
constructor(logLevel) {
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
89
|
+
* The level of logging to be used.
|
|
90
90
|
*/
|
|
91
91
|
this.logLevel = 'info';
|
|
92
92
|
this.logLevel = logLevel !== null && logLevel !== void 0 ? logLevel : 'info';
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
|
-
*
|
|
95
|
+
* Logs a detail message.
|
|
96
|
+
* @param message - The message to log.
|
|
97
|
+
* @param parameters - The parameters to log.
|
|
98
|
+
* @returns `Success` with the logged message if the level is enabled, or
|
|
99
|
+
* `Success` with `undefined` if the message is suppressed.
|
|
96
100
|
*/
|
|
97
101
|
detail(message, ...parameters) {
|
|
98
102
|
return this.log('detail', message, ...parameters);
|
|
99
103
|
}
|
|
100
104
|
/**
|
|
101
|
-
*
|
|
105
|
+
* Logs an info message.
|
|
106
|
+
* @param message - The message to log.
|
|
107
|
+
* @param parameters - The parameters to log.
|
|
108
|
+
* @returns `Success` with the logged message if the level is enabled, or
|
|
109
|
+
* `Success` with `undefined` if the message is suppressed.
|
|
102
110
|
*/
|
|
103
111
|
info(message, ...parameters) {
|
|
104
112
|
return this.log('info', message, ...parameters);
|
|
105
113
|
}
|
|
106
114
|
/**
|
|
107
|
-
*
|
|
115
|
+
* Logs a warning message.
|
|
116
|
+
* @param message - The message to log.
|
|
117
|
+
* @param parameters - The parameters to log.
|
|
118
|
+
* @returns `Success` with the logged message if the level is enabled, or
|
|
119
|
+
* `Success` with `undefined` if the message is suppressed.
|
|
108
120
|
*/
|
|
109
121
|
warn(message, ...parameters) {
|
|
110
122
|
return this.log('warning', message, ...parameters);
|
|
111
123
|
}
|
|
112
124
|
/**
|
|
113
|
-
*
|
|
125
|
+
* Logs an error message.
|
|
126
|
+
* @param message - The message to log.
|
|
127
|
+
* @param parameters - The parameters to log.
|
|
128
|
+
* @returns `Success` with the logged message if the level is enabled, or
|
|
129
|
+
* `Success` with `undefined` if the message is suppressed.
|
|
114
130
|
*/
|
|
115
131
|
error(message, ...parameters) {
|
|
116
132
|
return this.log('error', message, ...parameters);
|
|
117
133
|
}
|
|
118
134
|
/**
|
|
119
|
-
*
|
|
135
|
+
* Logs a short error summary at `error` level, then emits `detail` at `detail` level.
|
|
136
|
+
* @param message - Short human-readable summary.
|
|
137
|
+
* @param detail - Full detail (e.g. raw converter error) logged at `detail` level.
|
|
120
138
|
*/
|
|
121
139
|
errorWithDetail(message, detail) {
|
|
122
140
|
this.detail(detail);
|
|
123
141
|
return this.error(message);
|
|
124
142
|
}
|
|
125
143
|
/**
|
|
126
|
-
*
|
|
144
|
+
* Logs a short warning summary at `warning` level, then emits `detail` at `detail` level.
|
|
145
|
+
* @param message - Short human-readable summary.
|
|
146
|
+
* @param detail - Full detail logged at `detail` level.
|
|
127
147
|
*/
|
|
128
148
|
warnWithDetail(message, detail) {
|
|
129
149
|
this.detail(detail);
|
|
130
150
|
return this.warn(message);
|
|
131
151
|
}
|
|
132
152
|
/**
|
|
133
|
-
*
|
|
153
|
+
* Logs a message at the given level.
|
|
154
|
+
* @param level - The level of the message.
|
|
155
|
+
* @param message - The message to log.
|
|
156
|
+
* @param parameters - The parameters to log.
|
|
157
|
+
* @returns `Success` with the logged message if the level is enabled, or
|
|
158
|
+
* `Success` with `undefined` if the message is suppressed.
|
|
134
159
|
*/
|
|
135
160
|
log(level, message, ...parameters) {
|
|
136
161
|
if (shouldLog(level, this.logLevel)) {
|
|
137
162
|
const formatted = this._format(message, ...parameters);
|
|
163
|
+
this._logStructured(level, formatted, message, parameters);
|
|
138
164
|
return this._log(formatted, level);
|
|
139
165
|
}
|
|
140
166
|
return this._suppressLog(level, message, ...parameters);
|
|
@@ -153,6 +179,21 @@ export class LoggerBase {
|
|
|
153
179
|
const joined = strings.join('');
|
|
154
180
|
return joined;
|
|
155
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Inner hook called for logged messages alongside {@link Logging.LoggerBase._log | _log},
|
|
184
|
+
* exposing the structured `(level, formatted, message, parameters)` form before it is
|
|
185
|
+
* collapsed to the formatted string. The default implementation is a no-op; subclasses
|
|
186
|
+
* that need to retain structured records (e.g. {@link Logging.RetainingLogger | RetainingLogger})
|
|
187
|
+
* override this. Fired only in the `shouldLog` branch, so suppressed messages never reach it.
|
|
188
|
+
* @param __level - The {@link MessageLogLevel | level} of the message.
|
|
189
|
+
* @param __formatted - The formatted message (same string passed to `_log`).
|
|
190
|
+
* @param __message - The raw message argument before formatting.
|
|
191
|
+
* @param __parameters - The raw parameter arguments before formatting.
|
|
192
|
+
* @public
|
|
193
|
+
*/
|
|
194
|
+
_logStructured(__level, __formatted, __message, __parameters) {
|
|
195
|
+
/* no-op; subclasses that retain structured records override this */
|
|
196
|
+
}
|
|
156
197
|
/**
|
|
157
198
|
* Inner method called for suppressed log messages.
|
|
158
199
|
* @public
|
|
@@ -0,0 +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 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,104 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2020 Erik Fortune
|
|
3
|
+
*
|
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
* furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
* copies or substantial portions of the Software.
|
|
13
|
+
*
|
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
* SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
import { succeed } from '../base';
|
|
23
|
+
/**
|
|
24
|
+
* Verbosity rank for each {@link Logging.ReporterLogLevel | ReporterLogLevel}, materializing
|
|
25
|
+
* the {@link Logging.shouldLog | shouldLog} ordering. A higher rank is more permissive
|
|
26
|
+
* (emits strictly more message levels).
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
const verbosityRank = {
|
|
30
|
+
silent: 0,
|
|
31
|
+
error: 1,
|
|
32
|
+
warning: 2,
|
|
33
|
+
info: 3,
|
|
34
|
+
detail: 4,
|
|
35
|
+
all: 5
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* An {@link Logging.ILogger | ILogger} that fans every log call out to N child loggers,
|
|
39
|
+
* each applying its own threshold.
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* The composite does not pre-filter — it forwards the raw `(level, message, ...params)`
|
|
43
|
+
* to each child's public method so each child formats and filters per its own rules.
|
|
44
|
+
* This lets a single pinned logger feed, for example, a {@link Logging.ConsoleLogger | ConsoleLogger}
|
|
45
|
+
* (stdout) and a {@link Logging.RetainingLogger | RetainingLogger} (observability buffer)
|
|
46
|
+
* with independent log levels.
|
|
47
|
+
*
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
export class MultiLogger {
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new multi logger.
|
|
53
|
+
* @param loggers - The child loggers to fan calls out to.
|
|
54
|
+
*/
|
|
55
|
+
constructor(loggers) {
|
|
56
|
+
this._loggers = [...loggers];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The most-verbose (most-permissive) level among the children, so an upstream
|
|
60
|
+
* `shouldLog` gate does not suppress a call before it can fan out to a more
|
|
61
|
+
* permissive child. Computed on access, since a child's level may change.
|
|
62
|
+
*/
|
|
63
|
+
get logLevel() {
|
|
64
|
+
return this._loggers.reduce((most, logger) => (verbosityRank[logger.logLevel] > verbosityRank[most] ? logger.logLevel : most), 'silent');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* {@inheritDoc Logging.ILogger.log}
|
|
68
|
+
*/
|
|
69
|
+
log(level, message, ...parameters) {
|
|
70
|
+
let logged;
|
|
71
|
+
for (const logger of this._loggers) {
|
|
72
|
+
const value = logger.log(level, message, ...parameters).value;
|
|
73
|
+
if (value !== undefined) {
|
|
74
|
+
logged = value;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return succeed(logged);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* {@inheritDoc Logging.ILogger.detail}
|
|
81
|
+
*/
|
|
82
|
+
detail(message, ...parameters) {
|
|
83
|
+
return this.log('detail', message, ...parameters);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* {@inheritDoc Logging.ILogger.info}
|
|
87
|
+
*/
|
|
88
|
+
info(message, ...parameters) {
|
|
89
|
+
return this.log('info', message, ...parameters);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* {@inheritDoc Logging.ILogger.warn}
|
|
93
|
+
*/
|
|
94
|
+
warn(message, ...parameters) {
|
|
95
|
+
return this.log('warning', message, ...parameters);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* {@inheritDoc Logging.ILogger.error}
|
|
99
|
+
*/
|
|
100
|
+
error(message, ...parameters) {
|
|
101
|
+
return this.log('error', message, ...parameters);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# 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,OAAO,EAA4B,OAAO,EAAE,MAAM,SAAS,CAAC;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,MAAM,OAAO,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,OAAO,CAAC,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","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"]}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2020 Erik Fortune
|
|
3
|
+
*
|
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
* furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
* copies or substantial portions of the Software.
|
|
13
|
+
*
|
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
* SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
import { succeed } from '../base';
|
|
23
|
+
import { LoggerBase, shouldLog } from './logger';
|
|
24
|
+
/**
|
|
25
|
+
* An {@link Logging.ILogger | ILogger} that retains structured log records in a bounded
|
|
26
|
+
* most-recent-N ring, with a query API supporting min-severity filtering and
|
|
27
|
+
* since-cursor incremental paging.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* Records are captured via the {@link Logging.LoggerBase._logStructured | _logStructured} hook,
|
|
31
|
+
* so the full structured form (`level` + formatted `message` + raw `args`) is retained.
|
|
32
|
+
* The logger emits nowhere itself — pair it with a {@link Logging.MultiLogger | MultiLogger}
|
|
33
|
+
* to also feed a {@link Logging.ConsoleLogger | ConsoleLogger} or other durable sink.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export class RetainingLogger extends LoggerBase {
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new retaining logger.
|
|
40
|
+
* @param logLevel - The level of logging to retain. Defaults to `'detail'` to capture
|
|
41
|
+
* broadly and filter at query time.
|
|
42
|
+
* @param maxRecords - The maximum number of records to retain. Defaults to `1000`.
|
|
43
|
+
* @param now - Injected clock returning milliseconds since epoch. Defaults to `Date.now`.
|
|
44
|
+
*/
|
|
45
|
+
constructor(logLevel = 'detail', maxRecords = 1000, now = () => Date.now()) {
|
|
46
|
+
super(logLevel);
|
|
47
|
+
/**
|
|
48
|
+
* The backing store, used as a circular buffer. Grows lazily up to `_capacity`,
|
|
49
|
+
* after which records overwrite the oldest slot in place — eviction is O(1), with
|
|
50
|
+
* no `shift()` re-indexing regardless of capacity.
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
this._buffer = [];
|
|
54
|
+
/**
|
|
55
|
+
* Index of the oldest retained record within `_buffer` once the ring is full.
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
58
|
+
this._head = 0;
|
|
59
|
+
/**
|
|
60
|
+
* The number of valid records currently retained (`<= _capacity`).
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
this._count = 0;
|
|
64
|
+
/**
|
|
65
|
+
* The most recently assigned sequence number; monotonic, stable across eviction
|
|
66
|
+
* and {@link Logging.RetainingLogger.clear | clear()}.
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
this._lastSeq = 0;
|
|
70
|
+
// The ring requires a positive integer capacity to be well-defined; a non-finite
|
|
71
|
+
// or sub-1 value would make the modular index arithmetic meaningless, so floor it
|
|
72
|
+
// to a sane minimum of 1 rather than crash on degenerate input.
|
|
73
|
+
this._capacity = Number.isFinite(maxRecords) && maxRecords >= 1 ? Math.floor(maxRecords) : 1;
|
|
74
|
+
this._now = now;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The retained records, oldest-first.
|
|
78
|
+
*/
|
|
79
|
+
get records() {
|
|
80
|
+
return this._toOrderedArray();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The most recently assigned sequence number. A client can hold this value and
|
|
84
|
+
* pass it as `sinceSeq` to page only records logged afterward.
|
|
85
|
+
*/
|
|
86
|
+
get lastSeq() {
|
|
87
|
+
return this._lastSeq;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Returns retained records, oldest-first, optionally filtered.
|
|
91
|
+
* @param options - {@link Logging.IGetRecordsOptions | Filtering and paging options}.
|
|
92
|
+
* @returns The matching records, oldest-first.
|
|
93
|
+
*/
|
|
94
|
+
getRecords(options) {
|
|
95
|
+
let result = this._toOrderedArray();
|
|
96
|
+
if ((options === null || options === void 0 ? void 0 : options.minLevel) !== undefined) {
|
|
97
|
+
const minLevel = options.minLevel;
|
|
98
|
+
result = result.filter((r) => shouldLog(r.level, minLevel));
|
|
99
|
+
}
|
|
100
|
+
if ((options === null || options === void 0 ? void 0 : options.sinceSeq) !== undefined) {
|
|
101
|
+
const sinceSeq = options.sinceSeq;
|
|
102
|
+
result = result.filter((r) => r.seq > sinceSeq);
|
|
103
|
+
}
|
|
104
|
+
if ((options === null || options === void 0 ? void 0 : options.limit) !== undefined && result.length > options.limit) {
|
|
105
|
+
result = result.slice(result.length - options.limit);
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Clears all retained records. Does NOT reset the sequence counter, so a client
|
|
111
|
+
* holding a `sinceSeq` cursor never re-sees a sequence number.
|
|
112
|
+
*/
|
|
113
|
+
clear() {
|
|
114
|
+
this._buffer = [];
|
|
115
|
+
this._head = 0;
|
|
116
|
+
this._count = 0;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Materializes the ring into a plain oldest-first array.
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
_toOrderedArray() {
|
|
123
|
+
const result = [];
|
|
124
|
+
for (let i = 0; i < this._count; i++) {
|
|
125
|
+
result.push(this._buffer[(this._head + i) % this._capacity]);
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* {@inheritDoc Logging.LoggerBase._logStructured}
|
|
131
|
+
* @internal
|
|
132
|
+
*/
|
|
133
|
+
_logStructured(level, formatted, message, parameters) {
|
|
134
|
+
this._lastSeq += 1;
|
|
135
|
+
const record = {
|
|
136
|
+
seq: this._lastSeq,
|
|
137
|
+
timestamp: this._now(),
|
|
138
|
+
level,
|
|
139
|
+
message: formatted,
|
|
140
|
+
args: [message, ...parameters]
|
|
141
|
+
};
|
|
142
|
+
if (this._count < this._capacity) {
|
|
143
|
+
// Still filling: append to the next free slot (head stays 0 during this phase).
|
|
144
|
+
this._buffer.push(record);
|
|
145
|
+
this._count += 1;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// Full: overwrite the oldest record in place and advance the head.
|
|
149
|
+
this._buffer[this._head] = record;
|
|
150
|
+
this._head = (this._head + 1) % this._capacity;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* {@inheritDoc Logging.LoggerBase._log}
|
|
155
|
+
* @internal
|
|
156
|
+
*/
|
|
157
|
+
_log(message, __level) {
|
|
158
|
+
return succeed(message);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=retainingLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retainingLogger.js","sourceRoot":"","sources":["../../../src/packlets/logging/retainingLogger.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, succeed } from '../base';\nimport { LoggerBase, ReporterLogLevel, shouldLog } from './logger';\n\n/**\n * A retained log record. Preserves the level and an ordering cursor so consumers\n * can filter by severity and page incrementally.\n * @public\n */\nexport interface ILogRecord {\n /**\n * Monotonic 1-based sequence number, stable across ring eviction.\n */\n readonly seq: number;\n /**\n * Milliseconds since epoch when the record was logged (from the injected clock).\n */\n readonly timestamp: number;\n /**\n * The level the record was logged at.\n */\n readonly level: MessageLogLevel;\n /**\n * The formatted message (same formatting {@link Logging.LoggerBase._format | LoggerBase._format} produces).\n */\n readonly message: string;\n /**\n * The raw structured inputs `[message, ...parameters]` before formatting.\n */\n readonly args?: readonly unknown[];\n}\n\n/**\n * Options for {@link Logging.RetainingLogger.getRecords | RetainingLogger.getRecords}.\n * @public\n */\nexport interface IGetRecordsOptions {\n /**\n * If supplied, only records whose level would be emitted at this threshold\n * (per {@link Logging.shouldLog | shouldLog}) are returned.\n */\n readonly minLevel?: ReporterLogLevel;\n /**\n * If supplied, only records with `seq > sinceSeq` are returned, enabling\n * incremental paging from a previously-held cursor.\n */\n readonly sinceSeq?: number;\n /**\n * If supplied, returns at most this many records — the most recent N (tail),\n * still ordered oldest-first.\n */\n readonly limit?: number;\n}\n\n/**\n * An {@link Logging.ILogger | ILogger} that retains structured log records in a bounded\n * most-recent-N ring, with a query API supporting min-severity filtering and\n * since-cursor incremental paging.\n *\n * @remarks\n * Records are captured via the {@link Logging.LoggerBase._logStructured | _logStructured} hook,\n * so the full structured form (`level` + formatted `message` + raw `args`) is retained.\n * The logger emits nowhere itself — pair it with a {@link Logging.MultiLogger | MultiLogger}\n * to also feed a {@link Logging.ConsoleLogger | ConsoleLogger} or other durable sink.\n *\n * @public\n */\nexport class RetainingLogger extends LoggerBase {\n /**\n * The fixed ring capacity — the maximum number of records retained before the\n * oldest is overwritten. A positive integer (see the constructor normalization).\n * @internal\n */\n private readonly _capacity: number;\n\n /**\n * Injected clock used to timestamp records.\n * @internal\n */\n private readonly _now: () => number;\n\n /**\n * The backing store, used as a circular buffer. Grows lazily up to `_capacity`,\n * after which records overwrite the oldest slot in place — eviction is O(1), with\n * no `shift()` re-indexing regardless of capacity.\n * @internal\n */\n private _buffer: ILogRecord[] = [];\n\n /**\n * Index of the oldest retained record within `_buffer` once the ring is full.\n * @internal\n */\n private _head: number = 0;\n\n /**\n * The number of valid records currently retained (`<= _capacity`).\n * @internal\n */\n private _count: number = 0;\n\n /**\n * The most recently assigned sequence number; monotonic, stable across eviction\n * and {@link Logging.RetainingLogger.clear | clear()}.\n * @internal\n */\n private _lastSeq: number = 0;\n\n /**\n * Creates a new retaining logger.\n * @param logLevel - The level of logging to retain. Defaults to `'detail'` to capture\n * broadly and filter at query time.\n * @param maxRecords - The maximum number of records to retain. Defaults to `1000`.\n * @param now - Injected clock returning milliseconds since epoch. Defaults to `Date.now`.\n */\n public constructor(\n logLevel: ReporterLogLevel = 'detail',\n maxRecords: number = 1000,\n now: () => number = () => Date.now()\n ) {\n super(logLevel);\n // The ring requires a positive integer capacity to be well-defined; a non-finite\n // or sub-1 value would make the modular index arithmetic meaningless, so floor it\n // to a sane minimum of 1 rather than crash on degenerate input.\n this._capacity = Number.isFinite(maxRecords) && maxRecords >= 1 ? Math.floor(maxRecords) : 1;\n this._now = now;\n }\n\n /**\n * The retained records, oldest-first.\n */\n public get records(): ReadonlyArray<ILogRecord> {\n return this._toOrderedArray();\n }\n\n /**\n * The most recently assigned sequence number. A client can hold this value and\n * pass it as `sinceSeq` to page only records logged afterward.\n */\n public get lastSeq(): number {\n return this._lastSeq;\n }\n\n /**\n * Returns retained records, oldest-first, optionally filtered.\n * @param options - {@link Logging.IGetRecordsOptions | Filtering and paging options}.\n * @returns The matching records, oldest-first.\n */\n public getRecords(options?: IGetRecordsOptions): ReadonlyArray<ILogRecord> {\n let result: ReadonlyArray<ILogRecord> = this._toOrderedArray();\n if (options?.minLevel !== undefined) {\n const minLevel = options.minLevel;\n result = result.filter((r) => shouldLog(r.level, minLevel));\n }\n if (options?.sinceSeq !== undefined) {\n const sinceSeq = options.sinceSeq;\n result = result.filter((r) => r.seq > sinceSeq);\n }\n if (options?.limit !== undefined && result.length > options.limit) {\n result = result.slice(result.length - options.limit);\n }\n return result;\n }\n\n /**\n * Clears all retained records. Does NOT reset the sequence counter, so a client\n * holding a `sinceSeq` cursor never re-sees a sequence number.\n */\n public clear(): void {\n this._buffer = [];\n this._head = 0;\n this._count = 0;\n }\n\n /**\n * Materializes the ring into a plain oldest-first array.\n * @internal\n */\n private _toOrderedArray(): ILogRecord[] {\n const result: ILogRecord[] = [];\n for (let i = 0; i < this._count; i++) {\n result.push(this._buffer[(this._head + i) % this._capacity]);\n }\n return result;\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._logStructured}\n * @internal\n */\n protected _logStructured(\n level: MessageLogLevel,\n formatted: string,\n message: unknown,\n parameters: readonly unknown[]\n ): void {\n this._lastSeq += 1;\n const record: ILogRecord = {\n seq: this._lastSeq,\n timestamp: this._now(),\n level,\n message: formatted,\n args: [message, ...parameters]\n };\n if (this._count < this._capacity) {\n // Still filling: append to the next free slot (head stays 0 during this phase).\n this._buffer.push(record);\n this._count += 1;\n } else {\n // Full: overwrite the oldest record in place and advance the head.\n this._buffer[this._head] = record;\n this._head = (this._head + 1) % this._capacity;\n }\n }\n\n /**\n * {@inheritDoc Logging.LoggerBase._log}\n * @internal\n */\n protected _log(message: string, __level: MessageLogLevel): Success<string | undefined> {\n return succeed(message);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array.js","sourceRoot":"","sources":["../../../src/packlets/validation/array.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAW,IAAI,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,aAAa,EAAkC,MAAM,iBAAiB,CAAC;AAYhF;;;;GAIG;AACH,MAAM,OAAO,cAAgC,SAAQ,aAAsB;IASzE;;;;OAIG;IACH,YAAmB,MAA8C;;QAC/D,KAAK,CAAC,MAAM,CAAC,CAAC;QACd,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,eAAe,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,MAAA,MAAM,CAAC,OAAO,mCAAI,EAAE,CAAC;IACtC,CAAC;IAED;;;;;;;;;OASG;IACO,SAAS,CAAC,IAAa,EAAE,OAAY,EAAE,IAAyB;QACxE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBAC7D,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;oBACxB,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAM,IAAI,IAAI,iBAAiB,CAAC,CAAC;IAC9C,CAAC;CACF","sourcesContent":["/*\n * Copyright (c) 2022 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\nimport { Failure, fail } from '../base';\nimport { Validator, ValidatorOptions } from './validator';\nimport { ValidatorBase, ValidatorBaseConstructorParams } from './validatorBase';\n\n/**\n * Parameters used to construct a {@link Validation.Classes.ArrayValidator | ArrayValidator}.\n * @public\n */\n\nexport interface ArrayValidatorConstructorParams<T, TC = unknown>\n extends ValidatorBaseConstructorParams<T[], TC> {\n validateElement: Validator<T, TC>;\n}\n\n/**\n * An in-place {@link Validator | Validator} for arrays of validated\n * values or objects.\n * @public\n */\nexport class ArrayValidator<T, TC = unknown> extends ValidatorBase<T[], TC> {\n /**\n * {@link Validation.ValidatorOptions | Options} which apply to this\n * validator.\n */\n public readonly options: ValidatorOptions<TC>;\n\n protected readonly _validateElement: Validator<T, TC>;\n\n /**\n * Constructs a new {@link Validation.Classes.ArrayValidator | ArrayValidator}.\n * @param params - Optional {@link Validation.Classes.ArrayValidatorConstructorParams | init params} for the\n * new {@link Validation.Classes.ArrayValidator | ArrayValidator}.\n */\n public constructor(params: ArrayValidatorConstructorParams<T, TC>) {\n super(params);\n this._validateElement = params.validateElement;\n this.options = params.options ?? {};\n }\n\n /**\n * Static method which validates that a supplied `unknown` value is a `array`\n * and that every element of the array can be validated by the supplied array\n * validator.\n * @param from - The `unknown` value to be tested.\n * @param context - Optional validation context will be propagated to element validator.\n * @param self - Optional self-reference for recursive validation.\n * @returns Returns `true` if `from` is an `array` of valid elements, or\n * {@link Failure} with an error message if not.\n */\n protected _validate(from: unknown, context?: TC, self?: Validator<T[], TC>): boolean | Failure<T[]> {\n if (Array.isArray(from)) {\n for (const elem of from) {\n const result = this._validateElement.validate(elem, context);\n if (!result.isSuccess()) {\n return fail(result.message);\n }\n }\n return true;\n }\n return fail<T[]>(`\"${from}\": not an array`);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boolean.js","sourceRoot":"","sources":["../../../src/packlets/validation/boolean.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAW,IAAI,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAqC,MAAM,oBAAoB,CAAC;AAQzF;;;GAGG;AACH,MAAM,OAAO,gBAA+B,SAAQ,gBAA6B;IAC/E;;;;OAIG;IACH,YAAmB,MAA8C;QAC/D,oBAAoB;QACpB,MAAM,GAAG,MAAM,aAAN,MAAM,cAAN,MAAM,GAAI,EAAE,CAAC;QACtB,KAAK,iBACH,SAAS,EAAE,gBAAgB,CAAC,eAAe,IACxC,MAAM,EACT,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,eAAe,CAAC,IAAa;QACzC,IAAI,OAAO,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,IAAI,kBAAkB,CAAC,CAAC;IAC1C,CAAC;CACF","sourcesContent":["/*\n * Copyright (c) 2021 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\nimport { Failure, fail } from '../base';\nimport { GenericValidator, GenericValidatorConstructorParams } from './genericValidator';\n\n/**\n * Parameters used to construct a {@link Validation.Classes.BooleanValidator | BooleanValidator}.\n * @public\n */\nexport type BooleanValidatorConstructorParams<TC = unknown> = GenericValidatorConstructorParams<boolean, TC>;\n\n/**\n * An in-place {@link Validation.Validator | Validator} for `boolean` values.\n * @public\n */\nexport class BooleanValidator<TC = unknown> extends GenericValidator<boolean, TC> {\n /**\n * Constructs a new {@link Validation.Classes.BooleanValidator | BooleanValidator}.\n * @param params - Optional {@link Validation.Classes.BooleanValidatorConstructorParams | init params} for the\n * new {@link Validation.Classes.BooleanValidator | BooleanValidator}.\n */\n public constructor(params?: BooleanValidatorConstructorParams<TC>) {\n /* c8 ignore next */\n params = params ?? {};\n super({\n validator: BooleanValidator.validateBoolean,\n ...params\n });\n }\n\n /**\n * Static method which validates that a supplied `unknown` value is a `boolean`.\n * @param from - The `unknown` value to be tested.\n * @returns Returns `true` if `from` is a `boolean`, or {@link Failure} with an error\n * message if not.\n */\n public static validateBoolean(from: unknown): boolean | Failure<boolean> {\n if (typeof from === 'boolean') {\n return true;\n }\n return fail(`\"${from}\": not a boolean`);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classes.js","sourceRoot":"","sources":["../../../src/packlets/validation/classes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,qBAAqB;AAErB,OAAO,EAAE,cAAc,EAAmC,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAqC,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAyC,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAoC,MAAM,UAAU,CAAC;AAC7E,OAAO,EAEL,eAAe,EAGhB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAmC,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAoC,MAAM,UAAU,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAuC,MAAM,aAAa,CAAC;AAEtF,oBAAoB","sourcesContent":["/*\n * Copyright (c) 2021 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\n/* c8 ignore start */\n\nexport { ArrayValidator, ArrayValidatorConstructorParams } from './array';\nexport { BooleanValidator, BooleanValidatorConstructorParams } from './boolean';\nexport { CompositeIdValidator, CompositeIdValidatorConstructorParams } from './compositeId';\nexport { NumberValidator, NumberValidatorConstructorParams } from './number';\nexport {\n FieldValidators,\n ObjectValidator,\n ObjectValidatorConstructorParams,\n ObjectValidatorOptions\n} from './object';\nexport { OneOfValidator, OneOfValidatorConstructorParams } from './oneOf';\nexport { StringValidator, StringValidatorConstructorParams } from './string';\nexport { TypeGuardValidator, TypeGuardValidatorConstructorParams } from './typeGuard';\n\n/* c8 ignore stop */\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/packlets/validation/common.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG","sourcesContent":["/*\n * Copyright (c) 2022 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\n/**\n * A type guard function which validates a specific type, with an optional context\n * that can be used to shape the validation.\n * @public\n */\nexport type TypeGuardWithContext<T, TC = unknown> = (from: unknown, context?: TC) => from is T;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compositeId.js","sourceRoot":"","sources":["../../../src/packlets/validation/compositeId.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,aAAa,EAAkC,MAAM,iBAAiB,CAAC;AAiBhF;;;GAGG;AACH,MAAM,OAAO,oBAKX,SAAQ,aAAoB;IAK5B;;;;OAIG;IACH,YAAmB,MAA4E;QAC7F,oBAAoB;QACpB,KAAK,mBACA,MAAM,EACT,CAAC;QACH,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QAEnD,IAAI,CAAC,sBAAsB,GAAG,YAAY,CAAC,kBAAkB,CAC3D,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,sCAAsC,GAAG,IAAI,CACtE,CAAC;QACF,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAC/C,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,gCAAgC,GAAG,IAAI,CAChE,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC9B,CAAC;IAEkB,SAAS,CAAC,KAAc,EAAE,OAAY;QACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,GAAG,KAAK,oCAAoC,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,GAAG,KAAK,uCAAuC,IAAI,CAAC,UAAU,cAAc,CAAC,CAAC;QAC5F,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,GAAG,KAAK,iDAAiD,IAAI,CAAC,UAAU,WAAW,CAAC,CAAC;QACnG,CAAC;QACD,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB;aACvC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;aAC/B,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QACpE,OAAO,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAI,GAAG,KAAK,4BAA4B,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3G,CAAC;CACF","sourcesContent":["/*\n * Copyright (c) 2026 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\nimport { Failure, fail } from '../base';\nimport { Validator } from './validator';\nimport { ValidatorBase, ValidatorBaseConstructorParams } from './validatorBase';\n\n/**\n * Parameters used to construct a {@link Validation.Classes.StringValidator | StringValidator}.\n * @public\n */\nexport interface CompositeIdValidatorConstructorParams<\n T extends string = string,\n TCOLLECTIONID extends string = string,\n TITEMID extends string = string,\n TC = unknown\n> extends ValidatorBaseConstructorParams<T, TC> {\n readonly collectionId: Validator<TCOLLECTIONID, TC>;\n readonly separator: string;\n readonly itemId: Validator<TITEMID, TC>;\n}\n\n/**\n * An in-place {@link Validation.Validator | Validator} for a strongly-typed composite ID.\n * @public\n */\nexport class CompositeIdValidator<\n T extends string = string,\n TCOLLECTIONID extends string = string,\n TITEMID extends string = string,\n TC = unknown\n> extends ValidatorBase<T, TC> {\n protected readonly _collectionIdValidator: Validator<TCOLLECTIONID, TC>;\n protected readonly _itemIdValidator: Validator<TITEMID, TC>;\n protected readonly _separator: string;\n\n /**\n * Constructs a new {@link Validation.Classes.StringValidator | StringValidator}.\n * @param params - Optional {@link Validation.Classes.StringValidatorConstructorParams | init params}\n * for the new {@link Validation.Classes.StringValidator | StringValidator}.\n */\n public constructor(params: CompositeIdValidatorConstructorParams<T, TCOLLECTIONID, TITEMID, TC>) {\n /* c8 ignore next */\n super({\n ...params\n });\n const { collectionId, separator, itemId } = params;\n\n this._collectionIdValidator = collectionId.withFormattedError(\n (value, err) => `${value}: invalid composite collection ID (${err}).`\n );\n this._itemIdValidator = itemId.withFormattedError(\n (value, err) => `${value}: invalid composite item ID (${err}).`\n );\n this._separator = separator;\n }\n\n protected override _validate(value: unknown, context?: TC): boolean | Failure<T> {\n if (typeof value !== 'string') {\n return fail(`${value}: invalid non-string composite ID.`);\n }\n const parts = value.split(this._separator);\n if (parts.length < 2) {\n return fail(`${value}: invalid composite ID - separator '${this._separator}' not found.`);\n } else if (parts.length > 2) {\n return fail(`${value}: invalid composite ID - multiple separators '${this._separator}.' found.`);\n }\n const [collectionId, itemId] = parts;\n const result = this._collectionIdValidator\n .validate(collectionId, context)\n .onSuccess(() => this._itemIdValidator.validate(itemId, context));\n return result.isSuccess() ? true : Failure.with<T>(`${value}: invalid composite ID - ${result.message}`);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.js","sourceRoot":"","sources":["../../../src/packlets/validation/field.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAW,IAAI,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAWhD;;;;GAIG;AACH,MAAM,OAAO,cAAgC,SAAQ,aAAoB;IAcvE;;;;;;;OAOG;IACH,YACE,SAAiB,EACjB,cAAgC,EAChC,OAAmC;QAEnC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,oBAAoB;QACpB,IAAI,CAAC,aAAa,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACO,SAAS,CAAC,IAAa,EAAE,OAAY,EAAE,IAAuB;QACtE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,KAAK,IAAI,CAAC;YAEtD,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC;gBAClC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,SAAS,EAAE,CAAC;oBACpD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc;yBAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;yBACvC,SAAS,CAAC,CAAC,OAAe,EAAE,EAAE;wBAC7B,OAAO,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC,CAAC;oBAC/C,CAAC,CAAC,CAAC;oBAEL,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;gBACxC,CAAC;YACH,CAAC;YAED,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,0BAA0B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpG,CAAC;QACD,0CAA0C;QAC1C,OAAO,IAAI,CAAC,0BAA0B,IAAI,CAAC,SAAS,sBAAsB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrG,CAAC;CACF","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\nimport { Failure, fail, isKeyOf } from '../base';\nimport { Validator, ValidatorOptions } from './validator';\nimport { ValidatorBase } from './validatorBase';\n\n/**\n * Parameters used to construct a {@link Validation.FieldValidator | FieldValidator}.\n * @public\n */\n\nexport interface FieldValidatorOptions<TC> extends ValidatorOptions<TC> {\n optional?: boolean;\n}\n\n/**\n * An in-place {@link Validation.Validator | Validator} for properties\n * an an object.\n * @public\n */\nexport class FieldValidator<T, TC = unknown> extends ValidatorBase<T, TC> {\n /**\n * The name of the property that this validator should validate.\n */\n public readonly fieldName: string;\n /**\n * The {@link Validation.Validator | Validator} to be applied against the named property.\n */\n public readonly fieldValidator: Validator<T, TC>;\n /**\n * @internal\n */\n protected readonly _fieldOptions: FieldValidatorOptions<TC>;\n\n /**\n * Constructs a new {@link Validation.FieldValidator | FieldValidator.}.\n * @param fieldName - The name of the property that this validator should validate.\n * @param fieldValidator - The {@link Validation.Validator | Validator} to be applied\n * against the named property.\n * @param options - Additional {@link Validation.FieldValidatorOptions | options} to be\n * applied to this validation.\n */\n public constructor(\n fieldName: string,\n fieldValidator: Validator<T, TC>,\n options?: FieldValidatorOptions<TC>\n ) {\n super({ options });\n this.fieldName = fieldName;\n this.fieldValidator = fieldValidator;\n /* c8 ignore next */\n this._fieldOptions = options ?? {};\n }\n\n /**\n * {@inheritDoc Validation.ValidatorBase._validate}\n */\n protected _validate(from: unknown, context?: TC, self?: Validator<T, TC>): boolean | Failure<T> {\n if (typeof from === 'object' && !Array.isArray(from) && from !== null) {\n const optional = this._fieldOptions.optional === true;\n\n if (isKeyOf(this.fieldName, from)) {\n if (!optional || from[this.fieldName] !== undefined) {\n const result = this.fieldValidator\n .validate(from[this.fieldName], context)\n .onFailure((message: string) => {\n return fail(`${this.fieldName}: ${message}`);\n });\n\n return result.success ? true : result;\n }\n }\n\n return optional ? true : fail(`\"${this.fieldName}\": Field not found in \"${JSON.stringify(from)}`);\n }\n /* c8 ignore next 2 -- defense in depth */\n return fail(`Cannot validate field '${this.fieldName}' from non-object \"${JSON.stringify(from)}\"`);\n }\n}\n"]}
|