From ea8fd991a09202199bf4d7c66cadc9c626f8efd0 Mon Sep 17 00:00:00 2001 From: Alexander Zinn Date: Sat, 16 Aug 2025 15:12:58 -0400 Subject: [PATCH] Initial Commit --- .gitignore | 5 ++ .npmrc | 4 ++ .nvmrc | 1 + .prettierrc | 12 ++++ README.md | 3 + bunfig.toml | 8 +++ eslint.config.js | 11 +++ package.json | 65 +++++++++++++++++ scripts/ci-build.sh | 29 ++++++++ scripts/ci-deploy.h | 0 scripts/ci-deploy.sh | 81 +++++++++++++++++++++ scripts/prepare-package-json.sh | 16 +++++ scripts/version-bump.sh | 37 ++++++++++ src/Defaults.ts | 11 +++ src/ILogger.ts | 8 +++ src/Logger.ts | 102 +++++++++++++++++++++++++++ src/LoggerFactory.ts | 49 +++++++++++++ src/appenders/ConsoleAppender.ts | 31 ++++++++ src/appenders/IAppender.ts | 5 ++ src/appenders/TechnikerMeAppender.ts | 60 ++++++++++++++++ src/index.ts | 8 +++ src/level/LoggingLevel.ts | 12 ++++ src/level/LoggingLevelMapping.ts | 51 ++++++++++++++ src/level/Threshold.ts | 21 ++++++ tsconfig.json | 26 +++++++ 25 files changed, 656 insertions(+) create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .nvmrc create mode 100644 .prettierrc create mode 100644 README.md create mode 100644 bunfig.toml create mode 100644 eslint.config.js create mode 100644 package.json create mode 100644 scripts/ci-build.sh create mode 100644 scripts/ci-deploy.h create mode 100755 scripts/ci-deploy.sh create mode 100644 scripts/prepare-package-json.sh create mode 100755 scripts/version-bump.sh create mode 100644 src/Defaults.ts create mode 100644 src/ILogger.ts create mode 100644 src/Logger.ts create mode 100644 src/LoggerFactory.ts create mode 100644 src/appenders/ConsoleAppender.ts create mode 100644 src/appenders/IAppender.ts create mode 100644 src/appenders/TechnikerMeAppender.ts create mode 100644 src/index.ts create mode 100644 src/level/LoggingLevel.ts create mode 100644 src/level/LoggingLevelMapping.ts create mode 100644 src/level/Threshold.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..33e67bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store + +.vscode +node_modules/ +dist/ diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..6e1b559 --- /dev/null +++ b/.npmrc @@ -0,0 +1,4 @@ +save-exact=true +package-lock=false +@techniker-me:registry=https://registry-node.techniker.me +//registry-node.techniker.me/:_authToken="${REGISTRY_AUTH_TOKEN}" diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..8fdd954 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..caa814d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "arrowParens": "avoid", + "bracketSameLine": true, + "bracketSpacing": false, + "printWidth": 160, + "semi": true, + "singleAttributePerLine": false, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": false +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..751cb55 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# @techniker-me/logger + +Logger package diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..62bd43b --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,8 @@ +[install] +exact = true + +[install.lockfile] +save = false + +[install.scopes] +"@techniker-me" = {url = "https://registry-node.techniker.me", token = "${REGISTRY_AUTH_TOKEN}"} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..d76408a --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,11 @@ +import globals from 'globals'; +import pluginJs from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + {files: ['**/*.{js,mjs,cjs,ts}']}, + {languageOptions: {globals: {...globals.browser, ...globals.node}}}, + pluginJs.configs.recommended, + ...tseslint.configs.recommended +]; diff --git a/package.json b/package.json new file mode 100644 index 0000000..256420d --- /dev/null +++ b/package.json @@ -0,0 +1,65 @@ +{ + "name": "@techniker-me/logger", + "version": "0.0.15", + "description": "A logger package for logging", + "type": "module", + "types": "./dist/types/index.d.ts", + "exports": { + "types": "./dist/types/index.d.ts", + "import": "./dist/browser/index.js", + "require": "./dist/node/index.js", + "default": "./dist/node/index.js" + }, + "private": false, + "author": { + "name": "Alexander Zinn", + "git+url": "https://git.techniker.me/techniker-me/tools.git" + }, + "publishConfig": { + "registry": "https://registry-node.techniker.me" + }, + "scripts": { + "ci-install": "bun install", + "ci-test": "bun test", + "ci-build": "bash scripts/ci-build.sh", + "ci-deploy:ga": "bash scripts/ci-deploy.sh --beta false", + "ci-deploy:beta": "bash scripts/ci-deploy.sh --beta true", + "format": "prettier ./ --write", + "prelint": "bun run format", + "lint": "eslint \"./src\"", + "lint:fix": "eslint \"./src\" --fix", + "test": "bun test", + "clean": "rm -rf dist", + "prebuild": "bun run clean", + "build": "bash scripts/ci-build.sh", + "build:node:debug": "bun build ./src/index.ts --target=node --sourcemap=none --format=esm --sourcemap=inline --outdir=dist/node", + "build:browser:debug": "bun build ./src/index.ts --target=browser --sourcemap=none --format=esm --sourcemap=inline --outdir=dist/browser", + "build:node": "bun build ./src/index.ts --target=node --sourcemap=none --format=cjs --splitting --minify --outdir=dist/node", + "build:browser": "bun build ./src/index.ts --target=browser --sourcemap=none --format=esm --splitting --minify --outdir=dist/browser", + "build:types": "tsc -p tsconfig.json", + "build:prepare-package-json": "bash scripts/prepare-package-json.sh", + "dev": "bun run build:types && bun --watch ./src/index.ts", + "versionbump:minor": "bash scripts/version-bump.sh minor", + "versionbump:major": "bash scripts/version-bump.sh major", + "versionbump:patch": "bash scripts/version-bump.sh patch" + }, + "devDependencies": { + "@eslint/js": "9.21.0", + "@types/node": "22.14.1", + "bun-types": "^1.2.4", + "eslint": "9.21.0", + "globals": "16.0.0", + "prettier": "3.5.3", + "tsx": "4.19.3", + "typescript": "5.8.2", + "typescript-eslint": "8.26.0" + }, + "dependencies": { + "@techniker-me/tools": "2025.0.16" + }, + "files": [ + "package.json", + "dist", + "README.md" + ] +} diff --git a/scripts/ci-build.sh b/scripts/ci-build.sh new file mode 100644 index 0000000..6cb0a60 --- /dev/null +++ b/scripts/ci-build.sh @@ -0,0 +1,29 @@ +#! /usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +distDirectory=${DIST_DIRECTORY:-"dist"} + +rm -rf ${distDirectory} + +bun run lint +bun run build:node +bun run build:browser +bun run build:types +bun run build:prepare-package-json + +echo "Copying [.npmrc] to [${distDirectory}]" +cp .npmrc ./${distDirectory} + +echo "Copying [.nvmrc] to [${distDirectory}]" +cp .nvmrc ./${distDirectory} + +echo "Copying [README.md] to [${distDirectory}]" +cp README.md ./${distDirectory} + +ls ${distDirectory} + +echo -e "\nci-build complete!" +exit 0 diff --git a/scripts/ci-deploy.h b/scripts/ci-deploy.h new file mode 100644 index 0000000..e69de29 diff --git a/scripts/ci-deploy.sh b/scripts/ci-deploy.sh new file mode 100755 index 0000000..7e77b0e --- /dev/null +++ b/scripts/ci-deploy.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +registryUrl="https://registry-node.techniker.me" +packageVersionToDeploy="" +isBeta="true" + +while [[ "${#}" -gt 0 ]]; do + case "${1}" in + --beta) + isBeta="${2}" + shift 2 + ;; + --version) + packageVersionToDeploy="${2}" + shift 2 + ;; + *) + echo "Unknown option [${1}]" + exit "${LINENO}" + ;; + esac +done + +function cleanDirectory { + local directory="${1}" + + if [ -d "${directory}" ]; then + echo "Deleting [${directory}]..." + + rm -rf "${directory}" + fi +} + +function removePackageJsonMember { + local packageJsonPath="dist/package.json" + local memberToRemove="${1}" + + if [ -f "${packageJsonPath}" ]; then + echo "Removing [${memberToRemove}] from the dist/package.json" + + jq "del(.${memberToRemove})" "${packageJsonPath}" > tmp.$$.json && mv tmp.$$.json "$packageJsonPath" + else + echo "Error: [${packageJsonPath}] not found." + fi +} + +function updatePackageJsonVersion { + local versionToUpdate="${1}" + + if [ isBeta == "true" ]; then + echo "Version to update [${versionToUpdate}] Contains beta" + echo "Updating package.json version to [${versionToUpdate}]" + + local packageJsonVersion=$(jq -r '.version' package.json) + + sed -i "s/\"version\": \"${packageJsonVersion}\"/\"version\": \"${versionToUpdate}\"/" dist/package.json + fi +} + + +echo "Deploying [${packageVersionToDeploy}]"; +echo "isBeta [${isBeta}]" + +cleanDirectory "dist" + +npm run ci-build + +removePackageJsonMember "devDependencies" +removePackageJsonMember "scripts" + + +if [ "${isBeta}" == "true" ]; then + updatePackageJsonVersion "${packageVersionToDeploy}" + npm publish --registry "${registryUrl}" --tag beta +else + npm publish --registry "${registryUrl}" +fi \ No newline at end of file diff --git a/scripts/prepare-package-json.sh b/scripts/prepare-package-json.sh new file mode 100644 index 0000000..a516f9a --- /dev/null +++ b/scripts/prepare-package-json.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +distDirectory=${DIST_DIRECTORY:-"dist"} +packageJsonPath=${PACKAGE_JSON_PATH:-"package.json"} + +if [ ! -d "${distDirectory}" ]; then + echo "Unable to prepare package.json, [${distDirectory}] not found" + exit $LINENO +fi + +echo "Preparing [package.json] to [${distDirectory}]" +jq '{name, version, author, type, types, exports, files, publishConfig}' "${packageJsonPath}" > "${distDirectory}/package.json" diff --git a/scripts/version-bump.sh b/scripts/version-bump.sh new file mode 100755 index 0000000..f4252c6 --- /dev/null +++ b/scripts/version-bump.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Check if a parameter was provided +if [ -z "$1" ]; then + echo "Usage: ./version-bump.sh [major|minor|patch]" + exit 1 +fi + +# Read current version +current_version=$(node -p "require('./package.json').version") +IFS='.' read -r major minor patch <<< "$current_version" + +# Update version based on parameter +case "$1" in + "major") + new_version="$((major + 1)).0.0" + ;; + "minor") + new_version="$major.$((minor + 1)).0" + ;; + "patch") + new_version="$major.$minor.$((patch + 1))" + ;; + *) + echo "Invalid parameter. Use: major, minor, or patch" + exit 1 + ;; +esac + +# Update package.json +node -e " +const pkg = require('./package.json'); +pkg.version = '$new_version'; +require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); +" + +echo "Version bumped from $current_version to $new_version" \ No newline at end of file diff --git a/src/Defaults.ts b/src/Defaults.ts new file mode 100644 index 0000000..6f210bf --- /dev/null +++ b/src/Defaults.ts @@ -0,0 +1,11 @@ +import {LoggingLevel} from './level/LoggingLevel'; + +export default class Defaults { + static get loggingLevel(): LoggingLevel { + return LoggingLevel.Info; + } + + private constructor() { + throw new Error('Defaults is a static class that may not be instantiated'); + } +} diff --git a/src/ILogger.ts b/src/ILogger.ts new file mode 100644 index 0000000..130839b --- /dev/null +++ b/src/ILogger.ts @@ -0,0 +1,8 @@ +export default interface ILogger { + info(message: string, ...optionalParameters: unknown[]): void; + warn(message: string, ...optionalParameters: unknown[]): void; + error(message: string, ...optionalParameters: unknown[]): void; + debug(message: string, ...optionalParameters: unknown[]): void; + trace(message: string, ...optionalParameters: unknown[]): void; + silly(message: string, ...optionalParameters: unknown[]): void; +} diff --git a/src/Logger.ts b/src/Logger.ts new file mode 100644 index 0000000..c08d17c --- /dev/null +++ b/src/Logger.ts @@ -0,0 +1,102 @@ +import IAppender from './appenders/IAppender'; +import {LoggingLevel} from './level/LoggingLevel'; +import LoggingLevelMapping from './level/LoggingLevelMapping'; +import Threshold from './level/Threshold'; + +export default class Logger { + private readonly _category: string; + private readonly _threshold: Threshold; + private readonly _appenders: Set; + + constructor(category: string, threshold: Threshold, appenders: Set) { + this._category = category; + this._threshold = threshold; + this._appenders = appenders; + } + + public info(message: string, ...optionalParameters: unknown[]): void { + if (this._threshold.value > LoggingLevel.Info) { + return; + } + + this.log(LoggingLevel.Info, message, ...optionalParameters); + } + + public warn(message: string, ...optionalParameters: unknown[]): void { + if (this._threshold.value > LoggingLevel.Warn) { + return; + } + + this.log(LoggingLevel.Warn, message, ...optionalParameters); + } + + public error(message: string, ...optionalParameters: unknown[]): void { + if (this._threshold.value > LoggingLevel.Error) { + return; + } + + this.log(LoggingLevel.Error, message, ...optionalParameters); + } + + public debug(message: string, ...optionalParameters: unknown[]): void { + if (this._threshold.value > LoggingLevel.Debug) { + return; + } + + this.log(LoggingLevel.Debug, message, ...optionalParameters); + } + + public trace(message: string, ...optionalParameters: unknown[]): void { + if (this._threshold.value > LoggingLevel.Trace) { + return; + } + + this.log(LoggingLevel.Trace, message, ...optionalParameters); + } + + public silly(message: string, ...optionalParameters: unknown[]): void { + if (this._threshold.value > LoggingLevel.Silly) { + return; + } + + this.log(LoggingLevel.Silly, message, ...optionalParameters); + } + + private formatMessage(message: string, ...optionalParameters: unknown[]): string { + let optionalParameterIndex = 0; + + return message.replace(/%[sdj]/g, match => { + if (optionalParameterIndex >= optionalParameters.length) { + return match; + } + + const param = optionalParameters[optionalParameterIndex++]; + + switch (match) { + case '%s': + return String(param); + case '%d': + return typeof param === 'number' ? param.toString() : 'NaN'; + case '%j': + try { + return JSON.stringify(param); + } catch { + return '[Circular]'; + } + + default: + return match; + } + }); + } + + private log(loggingLevel: LoggingLevel, message: string, ...optionalParameters: unknown[]): void { + const timestamp = new Date().toISOString(); + const formattedMessage = this.formatMessage(message, ...optionalParameters); + const level = LoggingLevelMapping.convertLoggingLevelToLoggingLevelType(loggingLevel); + + for (const appender of this._appenders) { + appender.log(timestamp, level, this._category, formattedMessage); + } + } +} diff --git a/src/LoggerFactory.ts b/src/LoggerFactory.ts new file mode 100644 index 0000000..a2d4b76 --- /dev/null +++ b/src/LoggerFactory.ts @@ -0,0 +1,49 @@ +import {Disposable} from '@techniker-me/tools'; +import ConsoleAppender from './appenders/ConsoleAppender'; +import IAppender from './appenders/IAppender'; +import Threshold from './level/Threshold'; +import Logger from './Logger'; +import {LoggingLevelType} from './level/LoggingLevel'; +import LoggingLevelMapping from './level/LoggingLevelMapping'; +import TechnikerMeAppender from './appenders/TechnikerMeAppender'; + +type Category = string; + +export default class LoggerFactory { + private static readonly _appenders: Set = new Set(); + private static readonly _threshold: Threshold = new Threshold(); + private static readonly _loggers: Map = new Map(); + + static { + this.applyConsoleAppender(); + this.applyRemoteAppender(); + } + + public static getLogger(category: string): Logger { + if (!LoggerFactory._loggers.has(category)) { + this._loggers.set(category, new Logger(category, LoggerFactory._threshold, LoggerFactory._appenders)); + } + + return LoggerFactory._loggers.get(category) as Logger; + } + + public static applyApppender(appender: IAppender): Disposable { + LoggerFactory._appenders.add(appender); + + return new Disposable(() => LoggerFactory._appenders.delete(appender)); + } + + public static setLoggingLevel(loggingLevelType: LoggingLevelType): void { + const loggingLevel = LoggingLevelMapping.convertLoggingLevelTypeToLoggingLevel(loggingLevelType); + + LoggerFactory._threshold.value = loggingLevel; + } + + private static applyConsoleAppender(): void { + LoggerFactory.applyApppender(new ConsoleAppender()); + } + + private static applyRemoteAppender(): void { + LoggerFactory.applyApppender(new TechnikerMeAppender()); + } +} diff --git a/src/appenders/ConsoleAppender.ts b/src/appenders/ConsoleAppender.ts new file mode 100644 index 0000000..8051ec4 --- /dev/null +++ b/src/appenders/ConsoleAppender.ts @@ -0,0 +1,31 @@ +import {LoggingLevel, LoggingLevelType} from '../level/LoggingLevel'; +import LoggingLevelMapping from '../level/LoggingLevelMapping'; +import IAppender from './IAppender'; +import {assertUnreachable} from '@techniker-me/tools'; + +export default class ConsoleAppender implements IAppender { + public log(timestamp: string, level: LoggingLevelType, category: string, message: string) { + const loggingLevel = LoggingLevelMapping.convertLoggingLevelTypeToLoggingLevel(level); + + switch (loggingLevel) { + case LoggingLevel.Off: + break; + + case LoggingLevel.Warn: + case LoggingLevel.Error: + console.error(`${timestamp} [${level}] [${category}] ${message}`); + break; + + case LoggingLevel.Info: + case LoggingLevel.Debug: + case LoggingLevel.Trace: + case LoggingLevel.Silly: + case LoggingLevel.All: + console.log(`${timestamp} [${level}] [${category}] ${message}`); + break; + + default: + assertUnreachable(loggingLevel); + } + } +} diff --git a/src/appenders/IAppender.ts b/src/appenders/IAppender.ts new file mode 100644 index 0000000..5a44771 --- /dev/null +++ b/src/appenders/IAppender.ts @@ -0,0 +1,5 @@ +import {LoggingLevelType} from '../level/LoggingLevel'; + +export default interface IAppender { + log(timestamp: string, level: LoggingLevelType, category: string, message: string): void; +} diff --git a/src/appenders/TechnikerMeAppender.ts b/src/appenders/TechnikerMeAppender.ts new file mode 100644 index 0000000..a18e57c --- /dev/null +++ b/src/appenders/TechnikerMeAppender.ts @@ -0,0 +1,60 @@ +import type {LoggingLevelType} from '../level/LoggingLevel'; +import type IAppender from './IAppender'; + +type LogMessage = { + timestamp: string; + level: string; + category: string; + message: string; +}; + +export default class TechnikerMeAppender implements IAppender { + private readonly _logRecorderUrl: string = 'https://logserver.techniker.me/api/logs'; + private readonly _domain: string = typeof window !== 'undefined' ? (window.location?.hostname ?? '') : ''; + private readonly _logMessageQueue: LogMessage[] = []; + private _pendingPostLogMessagePromise: Promise | undefined = undefined; + + public log(timestamp: string, level: LoggingLevelType, category: string, message: string): void { + const logMessage = { + timestamp, + domain: this._domain, + level, + category, + message + }; + this.queueMessage(logMessage); + this.postLogMessage(); + } + + private async postLogMessage(): Promise { + const logMessage = this._logMessageQueue.shift(); + + if (!logMessage || this._pendingPostLogMessagePromise !== undefined) { + return; + } + + try { + if (typeof fetch === 'undefined') { + console.error('Fetch API is not available in this environment'); + return; + } + + this._pendingPostLogMessagePromise = fetch(this._logRecorderUrl, { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + mode: 'no-cors', + method: 'POST', + body: JSON.stringify(logMessage) + }).then(() => (this._pendingPostLogMessagePromise = undefined)); + } catch (e) { + console.error('Unable to send logs due to [%o]', e); + return; + } + } + + private queueMessage(logMessage: LogMessage): void { + this._logMessageQueue.push(logMessage); + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a954adc --- /dev/null +++ b/src/index.ts @@ -0,0 +1,8 @@ +import type ILogger from './ILogger'; +import type IAppender from './appenders/IAppender'; +import LoggerFactory from './LoggerFactory'; +import LoggingLevelMapping from './level/LoggingLevelMapping'; + +export type {ILogger, IAppender}; +export {LoggerFactory, LoggingLevelMapping}; +export default {LoggerFactory, LoggingLevelMapping}; diff --git a/src/level/LoggingLevel.ts b/src/level/LoggingLevel.ts new file mode 100644 index 0000000..da47397 --- /dev/null +++ b/src/level/LoggingLevel.ts @@ -0,0 +1,12 @@ +export enum LoggingLevel { + Off = -1, + Info = 10, + Warn = 20, + Error = 30, + Debug = 40, + Trace = 50, + Silly = 60, + All = 100 +} + +export type LoggingLevelType = 'Off' | 'Info' | 'Warn' | 'Error' | 'Debug' | 'Trace' | 'Silly' | 'All'; diff --git a/src/level/LoggingLevelMapping.ts b/src/level/LoggingLevelMapping.ts new file mode 100644 index 0000000..05dab62 --- /dev/null +++ b/src/level/LoggingLevelMapping.ts @@ -0,0 +1,51 @@ +import {assertUnreachable} from '@techniker-me/tools'; +import {LoggingLevel, LoggingLevelType} from './LoggingLevel'; + +export default class LoggingLevelMapping { + public static convertLoggingLevelToLoggingLevelType(loggingLevel: LoggingLevel): LoggingLevelType { + switch (loggingLevel) { + case LoggingLevel.Off: + return 'Off'; + case LoggingLevel.Info: + return 'Info'; + case LoggingLevel.Warn: + return 'Warn'; + case LoggingLevel.Error: + return 'Error'; + case LoggingLevel.Debug: + return 'Debug'; + case LoggingLevel.Trace: + return 'Trace'; + case LoggingLevel.Silly: + return 'Silly'; + case LoggingLevel.All: + return 'All'; + + default: + assertUnreachable(loggingLevel); + } + } + + public static convertLoggingLevelTypeToLoggingLevel(loggingLevelType: LoggingLevelType): LoggingLevel { + switch (loggingLevelType) { + case 'Off': + return LoggingLevel.Off; + case 'Info': + return LoggingLevel.Info; + case 'Warn': + return LoggingLevel.Warn; + case 'Error': + return LoggingLevel.Error; + case 'Debug': + return LoggingLevel.Debug; + case 'Trace': + return LoggingLevel.Trace; + case 'Silly': + return LoggingLevel.Silly; + case 'All': + return LoggingLevel.All; + default: + assertUnreachable(loggingLevelType); + } + } +} diff --git a/src/level/Threshold.ts b/src/level/Threshold.ts new file mode 100644 index 0000000..f59be9e --- /dev/null +++ b/src/level/Threshold.ts @@ -0,0 +1,21 @@ +import {Subject} from '@techniker-me/tools'; +import Defaults from '../Defaults'; +import {LoggingLevel} from './LoggingLevel'; + +class Threshold { + private _threshold: Subject = new Subject(LoggingLevel.Debug); + + constructor(loggingLevel?: LoggingLevel) { + this._threshold = new Subject(loggingLevel ?? Defaults.loggingLevel); + } + + set value(value: LoggingLevel) { + this._threshold.value = value; + } + + get value(): LoggingLevel { + return this._threshold.value; + } +} + +export default Threshold; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5430fe3 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "outDir": "dist/types", + "rootDir": "src", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "emitDeclarationOnly": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "target": "ES2020", + "lib": ["DOM", "ES2020"], + "allowJs": false, + "strict": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "composite": true, + "isolatedModules": true, + "resolveJsonModule": true, + "noUnusedLocals": true, + "noUnusedParameters": true + }, + "include": ["src"], + "exclude": ["dist", "node_modules", "tests"] +}