Merge pull request #22 from SELab-2/chore/logging

feat: Logging met Loki
This commit is contained in:
Tibo De Peuter 2025-03-06 13:41:33 +01:00 committed by GitHub
commit 3cd7496989
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 952 additions and 105 deletions

View file

@ -1 +1,11 @@
PORT=3000
#
# Basic configuration
#
PORT=3000 # The port the backend will listen on
#
# Advanced configuration
#
# LOKI_HOST=http://localhost:3102 # The address of the Loki instance, used for logging

View file

@ -5,9 +5,9 @@
"private": true,
"type": "module",
"scripts": {
"build": "tsc --project tsconfig.json",
"dev": "tsx watch --env-file=.env.development.local src/app.ts",
"start": "node --env-file=.env dist/app.js",
"build": "NODE_ENV=production tsc --project tsconfig.json",
"dev": "NODE_ENV=development tsx watch --env-file=.env.development.local src/app.ts",
"start": "NODE_ENV=production node --env-file=.env dist/app.js",
"format": "prettier --write src/",
"format-check": "prettier --check src/",
"lint": "eslint . --fix",
@ -17,19 +17,23 @@
"@mikro-orm/core": "^6.4.6",
"@mikro-orm/postgresql": "^6.4.6",
"@mikro-orm/reflection": "^6.4.6",
"@mikro-orm/sqlite": "6.4.6",
"@types/js-yaml": "^4.0.9",
"axios": "^1.8.1",
"@mikro-orm/sqlite": "6.4.6",
"dotenv": "^16.4.7",
"express": "^5.0.1",
"uuid": "^11.1.0",
"js-yaml": "^4.1.0",
"@types/js-yaml": "^4.0.9"
"loki-logger-ts": "^1.0.2",
"response-time": "^2.3.3",
"uuid": "^11.1.0",
"winston": "^3.17.0",
"winston-loki": "^6.1.3"
},
"devDependencies": {
"@mikro-orm/cli": "^6.4.6",
"@types/express": "^5.0.0",
"@types/node": "^22.13.4",
"@types/response-time": "^2.3.8",
"globals": "^15.15.0",
"ts-node": "^10.9.2",
"tsx": "^4.19.3",

View file

@ -1,6 +1,5 @@
import express, { Express, Response } from 'express';
import { initORM } from './orm.js';
import { EnvVars, getNumericEnvVar } from './util/envvars.js';
import themeRoutes from './routes/themes.js';
import learningPathRoutes from './routes/learningPaths.js';
@ -13,12 +12,22 @@ import submissionRouter from './routes/submission.js';
import classRouter from './routes/class.js';
import questionRouter from './routes/question.js';
import loginRouter from './routes/login.js';
import { getLogger, Logger } from './logging/initalize.js';
import { responseTimeLogger } from './logging/responseTimeLogger.js';
import responseTime from 'response-time';
import { EnvVars, getNumericEnvVar } from './util/envvars.js';
const logger: Logger = getLogger();
const app: Express = express();
const port: string | number = getNumericEnvVar(EnvVars.Port);
app.use(express.json());
app.use(responseTime(responseTimeLogger));
// TODO Replace with Express routes
app.get('/', (_, res: Response) => {
logger.debug('GET /');
res.json({
message: 'Hello Dwengo!🚀',
});
@ -40,7 +49,7 @@ async function startServer() {
await initORM();
app.listen(port, () => {
console.log(`Server is running at http://localhost:${port}`);
logger.info(`Server is running at http://localhost:${port}`);
});
}

View file

@ -1,10 +1,12 @@
// Can be placed in dotenv but found it redundant
export const FALLBACK_LANG: string = 'nl';
// Import dotenv from "dotenv";
// API
// Load .env file
// Dotenv.config();
export const DWENGO_API_BASE: string = 'https://dwengo.org/backend/api';
export const DWENGO_API_BASE = 'https://dwengo.org/backend/api';
// Logging
export const FALLBACK_LANG = 'nl';
export const LOG_LEVEL: string =
'development' === process.env.NODE_ENV ? 'debug' : 'info';
export const LOKI_HOST: string =
process.env.LOKI_HOST || 'http://localhost:3102';

View file

@ -5,7 +5,8 @@ import {
getLearningObjectsFromPath,
} from '../services/learningObjects.js';
import { FALLBACK_LANG } from '../config.js';
import { FilteredLearningObject } from '../interfaces/learningPath';
import { FilteredLearningObject } from '../interfaces/learningPath.js';
import { getLogger } from '../logging/initalize.js';
export async function getAllLearningObjects(
req: Request,
@ -33,7 +34,7 @@ export async function getAllLearningObjects(
res.json(learningObjects);
} catch (error) {
console.error('Error fetching learning objects:', error);
getLogger().error('Error fetching learning objects:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
@ -54,7 +55,7 @@ export async function getLearningObject(
const learningObject = await getLearningObjectById(hruid, language);
res.json(learningObject);
} catch (error) {
console.error('Error fetching learning object:', error);
getLogger().error('Error fetching learning object:', error);
res.status(500).json({ error: 'Internal server error' });
}
}

View file

@ -5,6 +5,7 @@ import {
fetchLearningPaths,
searchLearningPaths,
} from '../services/learningPaths.js';
import { getLogger } from '../logging/initalize.js';
/**
* Fetch learning paths based on query parameters.
*/
@ -56,7 +57,10 @@ export async function getLearningPaths(
);
res.json(learningPaths.data);
} catch (error) {
console.error('❌ Unexpected error fetching learning paths:', error);
getLogger().error(
'❌ Unexpected error fetching learning paths:',
error
);
res.status(500).json({ error: 'Internal server error' });
}
}

View file

@ -1,7 +1,6 @@
import { Request, Response } from 'express';
import { themes } from '../data/themes.js';
import { loadTranslations } from '../util/translationHelper.js';
import { FALLBACK_LANG } from '../config.js';
interface Translations {
curricula_page: {

View file

@ -0,0 +1,60 @@
import {
createLogger,
format,
Logger as WinstonLogger,
transports,
} from 'winston';
import LokiTransport from 'winston-loki';
import { LokiLabels } from 'loki-logger-ts';
import { LOG_LEVEL, LOKI_HOST } from '../config.js';
export class Logger extends WinstonLogger {
constructor() {
super();
}
}
const Labels: LokiLabels = {
source: 'Dwengo-Backend',
service: 'API',
host: 'localhost',
};
let logger: Logger;
function initializeLogger(): Logger {
if (logger !== undefined) {
return logger;
}
const lokiTransport: LokiTransport = new LokiTransport({
host: LOKI_HOST,
labels: Labels,
level: LOG_LEVEL,
json: true,
format: format.combine(format.timestamp(), format.json()),
onConnectionError: (err) => {
// eslint-disable-next-line no-console
console.error(`Connection error: ${err}`);
},
});
const consoleTransport = new transports.Console({
level: LOG_LEVEL,
format: format.combine(format.cli(), format.colorize()),
});
logger = createLogger({
transports: [lokiTransport, consoleTransport],
});
logger.debug(
`Logger initialized with level ${LOG_LEVEL}, Loki host ${LOKI_HOST}`
);
return logger;
}
export function getLogger(): Logger {
logger ||= initializeLogger();
return logger;
}

View file

@ -0,0 +1,87 @@
import { DefaultLogger, LogContext, LoggerNamespace } from '@mikro-orm/core';
import { getLogger, Logger } from './initalize.js';
import { LokiLabels } from 'loki-logger-ts';
export class MikroOrmLogger extends DefaultLogger {
private logger: Logger = getLogger();
log(namespace: LoggerNamespace, message: string, context?: LogContext) {
if (!this.isEnabled(namespace, context)) {
return;
}
switch (namespace) {
case 'query':
this.logger.debug(
this.createMessage(namespace, message, context)
);
break;
case 'query-params':
// TODO Which log level should this be?
this.logger.info(
this.createMessage(namespace, message, context)
);
break;
case 'schema':
this.logger.info(
this.createMessage(namespace, message, context)
);
break;
case 'discovery':
this.logger.debug(
this.createMessage(namespace, message, context)
);
break;
case 'info':
this.logger.info(
this.createMessage(namespace, message, context)
);
break;
case 'deprecated':
this.logger.warn(
this.createMessage(namespace, message, context)
);
break;
default:
switch (context?.level) {
case 'info':
this.logger.info(
this.createMessage(namespace, message, context)
);
break;
case 'warning':
this.logger.warn(message);
break;
case 'error':
this.logger.error(message);
break;
default:
this.logger.debug(message);
break;
}
}
}
private createMessage(
namespace: LoggerNamespace,
messageArg: string,
context?: LogContext
) {
const labels: LokiLabels = {
service: 'ORM',
};
let message: string;
if (context?.label) {
message = `[${namespace}] (${context?.label}) ${messageArg}`;
} else {
message = `[${namespace}] ${messageArg}`;
}
return {
message: message,
labels: labels,
context: context,
};
}
}

View file

@ -0,0 +1,21 @@
import { getLogger, Logger } from './initalize.js';
import { Request, Response } from 'express';
export function responseTimeLogger(req: Request, res: Response, time: number) {
const logger: Logger = getLogger();
const method = req.method;
const url = req.url;
const status = res.statusCode;
logger.info({
message: 'Request completed',
method: method,
url: url,
status: status,
responseTime: Number(time),
labels: {
type: 'responseTime',
},
});
}

View file

@ -1,7 +1,9 @@
import { Options } from '@mikro-orm/core';
import { LoggerOptions, Options } from '@mikro-orm/core';
import { PostgreSqlDriver } from '@mikro-orm/postgresql';
import { EnvVars, getEnvVar, getNumericEnvVar } from './util/envvars.js';
import { SqliteDriver } from '@mikro-orm/sqlite';
import { MikroOrmLogger } from './logging/mikroOrmLogger.js';
import { LOG_LEVEL } from './config.js';
// Import alle entity-bestanden handmatig
import { User } from './entities/users/user.entity.js';
@ -55,6 +57,7 @@ function config(testingMode: boolean = false): Options {
},
};
}
return {
driver: PostgreSqlDriver,
host: getEnvVar(EnvVars.DbHost),
@ -63,8 +66,13 @@ function config(testingMode: boolean = false): Options {
user: getEnvVar(EnvVars.DbUsername),
password: getEnvVar(EnvVars.DbPassword),
entities: entities,
//EntitiesTs: entitiesTs,
debug: true,
// EntitiesTs: entitiesTs,
// Logging
debug: LOG_LEVEL === 'debug',
loggerFactory: (options: LoggerOptions) => {
return new MikroOrmLogger(options);
},
};
}

View file

@ -1,9 +1,15 @@
import { EntityManager, MikroORM } from '@mikro-orm/core';
import config from './mikro-orm.config.js';
import { EnvVars, getEnvVar } from './util/envvars.js';
import { getLogger, Logger } from './logging/initalize.js';
let orm: MikroORM | undefined;
export async function initORM(testingMode: boolean = false) {
const logger: Logger = getLogger();
logger.info('Initializing ORM');
logger.debug('MikroORM config is', config);
orm = await MikroORM.init(config(testingMode));
// Update the database scheme if necessary and enabled.
if (getEnvVar(EnvVars.DbUpdate)) {

View file

@ -7,6 +7,9 @@ import {
LearningPathResponse,
} from '../interfaces/learningPath.js';
import { fetchLearningPaths } from './learningPaths.js';
import { getLogger, Logger } from '../logging/initalize.js';
const logger: Logger = getLogger();
function filterData(
data: LearningObjectMetadata,
@ -49,7 +52,7 @@ export async function getLearningObjectById(
);
if (!metadata) {
console.error(`⚠️ WARNING: Learning object "${hruid}" not found.`);
logger.warn(`⚠️ WARNING: Learning object "${hruid}" not found.`);
return null;
}
@ -77,7 +80,7 @@ async function fetchLearningObjects(
!learningPathResponse.success ||
!learningPathResponse.data?.length
) {
console.error(
logger.warn(
`⚠️ WARNING: Learning path "${hruid}" exists but contains no learning objects.`
);
return [];
@ -104,7 +107,7 @@ async function fetchLearningObjects(
});
});
} catch (error) {
console.error('❌ Error fetching learning objects:', error);
logger.error('❌ Error fetching learning objects:', error);
return [];
}
}

View file

@ -4,6 +4,9 @@ import {
LearningPath,
LearningPathResponse,
} from '../interfaces/learningPath.js';
import { getLogger, Logger } from '../logging/initalize.js';
const logger: Logger = getLogger();
export async function fetchLearningPaths(
hruids: string[],
@ -29,7 +32,7 @@ export async function fetchLearningPaths(
);
if (!learningPaths || learningPaths.length === 0) {
console.error(`⚠️ WARNING: No learning paths found for ${source}.`);
logger.warn(`⚠️ WARNING: No learning paths found for ${source}.`);
return {
success: false,
source,

View file

@ -1,6 +1,7 @@
import axios, { AxiosRequestConfig } from 'axios';
import { getLogger, Logger } from '../logging/initalize.js';
// !!!! when logger is done -> change
const logger: Logger = getLogger();
/**
* Utility function to fetch data from an API endpoint with error handling.
@ -24,16 +25,16 @@ export async function fetchWithLogging<T>(
} catch (error: any) {
if (error.response) {
if (error.response.status === 404) {
console.error(
logger.debug(
`❌ ERROR: ${description} not found (404) at "${url}".`
);
} else {
console.error(
logger.debug(
`❌ ERROR: Failed to fetch ${description}. Status: ${error.response.status} - ${error.response.statusText} (URL: "${url}")`
);
}
} else {
console.error(
logger.debug(
`❌ ERROR: Network or unexpected error when fetching ${description}:`,
error.message
);

View file

@ -1,7 +1,10 @@
import fs from 'fs';
import path from 'path';
import yaml from 'js-yaml';
import { FALLBACK_LANG } from '../../config';
import { FALLBACK_LANG } from '../../config.js';
import { getLogger, Logger } from '../logging/initalize.js';
const logger: Logger = getLogger();
export function loadTranslations<T>(language: string): T {
try {
@ -9,10 +12,10 @@ export function loadTranslations<T>(language: string): T {
const yamlFile = fs.readFileSync(filePath, 'utf8');
return yaml.load(yamlFile) as T;
} catch (error) {
console.error(
`Cannot load translation for ${language}, fallen back to dutch`
logger.warn(
`Cannot load translation for ${language}, fallen back to dutch`,
error
);
console.error(error);
const fallbackPath = path.join(
process.cwd(),
'_i18n',

29
config/loki/config.yml Normal file
View file

@ -0,0 +1,29 @@
# This is a complete configuration to deploy Loki backed by the filesystem.
# The index will be shipped to the storage via tsdb-shipper.
auth_enabled: false
server:
http_listen_port: 3102
common:
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
replication_factor: 1
path_prefix: /tmp/loki
schema_config:
configs:
- from: 2020-05-15
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
storage_config:
filesystem:
directory: /tmp/loki/chunks

View file

@ -8,7 +8,28 @@ services:
ports:
- '5431:5432'
volumes:
- postgres_data:/var/lib/postgresql/data
- dwengo_postgres_data:/var/lib/postgresql/data
logging:
image: grafana/loki:latest
ports:
- '3102:3102'
- '9095:9095'
volumes:
- ./config/loki/config.yml:/etc/loki/config.yaml
- dwengo_loki_data:/loki
command: -config.file=/etc/loki/config.yaml
restart: unless-stopped
dashboards:
image: grafana/grafana:latest
ports:
- '3100:3000'
volumes:
- dwengo_grafana_data:/var/lib/grafana
restart: unless-stopped
volumes:
postgres_data:
dwengo_postgres_data:
dwengo_loki_data:
dwengo_grafana_data:

708
package-lock.json generated
View file

@ -12,10 +12,6 @@
"backend",
"frontend"
],
"dependencies": {
"@types/js-yaml": "^4.0.9",
"vue-i18n": "^10.0.5"
},
"devDependencies": {
"@eslint/compat": "^1.2.6",
"@eslint/js": "^9.20.0",
@ -41,12 +37,17 @@
"dotenv": "^16.4.7",
"express": "^5.0.1",
"js-yaml": "^4.1.0",
"uuid": "^11.1.0"
"loki-logger-ts": "^1.0.2",
"response-time": "^2.3.3",
"uuid": "^11.1.0",
"winston": "^3.17.0",
"winston-loki": "^6.1.3"
},
"devDependencies": {
"@mikro-orm/cli": "^6.4.6",
"@types/express": "^5.0.0",
"@types/node": "^22.13.4",
"@types/response-time": "^2.3.8",
"globals": "^15.15.0",
"ts-node": "^10.9.2",
"tsx": "^4.19.3",
@ -589,6 +590,15 @@
"node": ">=6.9.0"
}
},
"node_modules/@colors/colors": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
"integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
"license": "MIT",
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"dev": true,
@ -705,6 +715,17 @@
"node": ">=18"
}
},
"node_modules/@dabh/diagnostics": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
"integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
"license": "MIT",
"dependencies": {
"colorspace": "1.1.x",
"enabled": "2.0.x",
"kuler": "^2.0.0"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.0",
"cpu": [
@ -937,44 +958,6 @@
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@intlify/core-base": {
"version": "10.0.5",
"license": "MIT",
"dependencies": {
"@intlify/message-compiler": "10.0.5",
"@intlify/shared": "10.0.5"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/message-compiler": {
"version": "10.0.5",
"license": "MIT",
"dependencies": {
"@intlify/shared": "10.0.5",
"source-map-js": "^1.0.2"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/shared": {
"version": "10.0.5",
"license": "MIT",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"dev": true,
@ -1151,6 +1134,214 @@
"@mikro-orm/core": "^6.0.0"
}
},
"node_modules/@napi-rs/snappy-android-arm-eabi": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm-eabi/-/snappy-android-arm-eabi-7.2.2.tgz",
"integrity": "sha512-H7DuVkPCK5BlAr1NfSU8bDEN7gYs+R78pSHhDng83QxRnCLmVIZk33ymmIwurmoA1HrdTxbkbuNl+lMvNqnytw==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-android-arm64": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm64/-/snappy-android-arm64-7.2.2.tgz",
"integrity": "sha512-2R/A3qok+nGtpVK8oUMcrIi5OMDckGYNoBLFyli3zp8w6IArPRfg1yOfVUcHvpUDTo9T7LOS1fXgMOoC796eQw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-darwin-arm64": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-arm64/-/snappy-darwin-arm64-7.2.2.tgz",
"integrity": "sha512-USgArHbfrmdbuq33bD5ssbkPIoT7YCXCRLmZpDS6dMDrx+iM7eD2BecNbOOo7/v1eu6TRmQ0xOzeQ6I/9FIi5g==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-darwin-x64": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-x64/-/snappy-darwin-x64-7.2.2.tgz",
"integrity": "sha512-0APDu8iO5iT0IJKblk2lH0VpWSl9zOZndZKnBYIc+ei1npw2L5QvuErFOTeTdHBtzvUHASB+9bvgaWnQo4PvTQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-freebsd-x64": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-freebsd-x64/-/snappy-freebsd-x64-7.2.2.tgz",
"integrity": "sha512-mRTCJsuzy0o/B0Hnp9CwNB5V6cOJ4wedDTWEthsdKHSsQlO7WU9W1yP7H3Qv3Ccp/ZfMyrmG98Ad7u7lG58WXA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-linux-arm-gnueabihf": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm-gnueabihf/-/snappy-linux-arm-gnueabihf-7.2.2.tgz",
"integrity": "sha512-v1uzm8+6uYjasBPcFkv90VLZ+WhLzr/tnfkZ/iD9mHYiULqkqpRuC8zvc3FZaJy5wLQE9zTDkTJN1IvUcZ+Vcg==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-linux-arm64-gnu": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-gnu/-/snappy-linux-arm64-gnu-7.2.2.tgz",
"integrity": "sha512-LrEMa5pBScs4GXWOn6ZYXfQ72IzoolZw5txqUHVGs8eK4g1HR9HTHhb2oY5ySNaKakG5sOgMsb1rwaEnjhChmQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-linux-arm64-musl": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-musl/-/snappy-linux-arm64-musl-7.2.2.tgz",
"integrity": "sha512-3orWZo9hUpGQcB+3aTLW7UFDqNCQfbr0+MvV67x8nMNYj5eAeUtMmUE/HxLznHO4eZ1qSqiTwLbVx05/Socdlw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-linux-x64-gnu": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-gnu/-/snappy-linux-x64-gnu-7.2.2.tgz",
"integrity": "sha512-jZt8Jit/HHDcavt80zxEkDpH+R1Ic0ssiVCoueASzMXa7vwPJeF4ZxZyqUw4qeSy7n8UUExomu8G8ZbP6VKhgw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-linux-x64-musl": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-musl/-/snappy-linux-x64-musl-7.2.2.tgz",
"integrity": "sha512-Dh96IXgcZrV39a+Tej/owcd9vr5ihiZ3KRix11rr1v0MWtVb61+H1GXXlz6+Zcx9y8jM1NmOuiIuJwkV4vZ4WA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-win32-arm64-msvc": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-arm64-msvc/-/snappy-win32-arm64-msvc-7.2.2.tgz",
"integrity": "sha512-9No0b3xGbHSWv2wtLEn3MO76Yopn1U2TdemZpCaEgOGccz1V+a/1d16Piz3ofSmnA13HGFz3h9NwZH9EOaIgYA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-win32-ia32-msvc": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-ia32-msvc/-/snappy-win32-ia32-msvc-7.2.2.tgz",
"integrity": "sha512-QiGe+0G86J74Qz1JcHtBwM3OYdTni1hX1PFyLRo3HhQUSpmi13Bzc1En7APn+6Pvo7gkrcy81dObGLDSxFAkQQ==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@napi-rs/snappy-win32-x64-msvc": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-x64-msvc/-/snappy-win32-x64-msvc-7.2.2.tgz",
"integrity": "sha512-a43cyx1nK0daw6BZxVcvDEXxKMFLSBSDTAhsFD0VqSKcC7MGUBMaqyoWUcMiI7LBSz4bxUmxDWKfCYzpEmeb3w==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"license": "MIT",
@ -1245,6 +1436,70 @@
"dev": true,
"license": "MIT"
},
"node_modules/@protobufjs/aspromise": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/base64": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/codegen": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/eventemitter": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
"integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/fetch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
"integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
"license": "BSD-3-Clause",
"dependencies": {
"@protobufjs/aspromise": "^1.1.1",
"@protobufjs/inquire": "^1.1.0"
}
},
"node_modules/@protobufjs/float": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/inquire": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
"integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/path": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/pool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/utf8": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
"license": "BSD-3-Clause"
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.4",
"dev": true,
@ -1439,7 +1694,6 @@
},
"node_modules/@types/node": {
"version": "22.13.4",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.20.0"
@ -1455,6 +1709,17 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/response-time": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/@types/response-time/-/response-time-2.3.8.tgz",
"integrity": "sha512-7qGaNYvdxc0zRab8oHpYx7AW17qj+G0xuag1eCrw3M2VWPJQ/HyKaaghWygiaOUl0y9x7QGQwppDpqLJ5V9pzw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/express": "*",
"@types/node": "*"
}
},
"node_modules/@types/send": {
"version": "0.17.4",
"dev": true,
@ -1479,6 +1744,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/triple-beam": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.24.1",
"dev": true,
@ -2262,6 +2533,21 @@
"node": ">=12"
}
},
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
"license": "MIT"
},
"node_modules/async-exit-hook": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz",
"integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==",
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"license": "MIT"
@ -2405,6 +2691,18 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/btoa": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
"license": "(MIT OR Apache-2.0)",
"bin": {
"btoa": "bin/btoa.js"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"funding": [
@ -2725,6 +3023,16 @@
"version": "13.0.3",
"license": "MIT"
},
"node_modules/color": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
"license": "MIT",
"dependencies": {
"color-convert": "^1.9.3",
"color-string": "^1.6.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"dev": true,
@ -2738,9 +3046,18 @@
},
"node_modules/color-name": {
"version": "1.1.4",
"dev": true,
"license": "MIT"
},
"node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"license": "MIT",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/color-support": {
"version": "1.1.3",
"license": "ISC",
@ -2749,10 +3066,35 @@
"color-support": "bin.js"
}
},
"node_modules/color/node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"license": "MIT",
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/color/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"license": "MIT"
},
"node_modules/colorette": {
"version": "2.0.19",
"license": "MIT"
},
"node_modules/colorspace": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
"integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
"license": "MIT",
"dependencies": {
"color": "^3.1.3",
"text-hex": "1.0.x"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"license": "MIT",
@ -3127,6 +3469,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/enabled": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
"license": "MIT"
},
"node_modules/encodeurl": {
"version": "2.0.0",
"license": "MIT",
@ -3760,6 +4108,12 @@
"reusify": "^1.0.4"
}
},
"node_modules/fecha": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
"license": "MIT"
},
"node_modules/figlet": {
"version": "1.8.0",
"dev": true,
@ -3876,6 +4230,12 @@
"dev": true,
"license": "ISC"
},
"node_modules/fn.name": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
"license": "MIT"
},
"node_modules/follow-redirects": {
"version": "1.15.9",
"funding": [
@ -4487,6 +4847,12 @@
"node": ">= 0.10"
}
},
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"license": "MIT"
},
"node_modules/is-core-module": {
"version": "2.16.1",
"license": "MIT",
@ -4900,6 +5266,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/kuler": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==",
"license": "MIT"
},
"node_modules/levn": {
"version": "0.4.1",
"dev": true,
@ -4935,6 +5307,37 @@
"dev": true,
"license": "MIT"
},
"node_modules/logform": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
"integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==",
"license": "MIT",
"dependencies": {
"@colors/colors": "1.6.0",
"@types/triple-beam": "^1.3.2",
"fecha": "^4.2.0",
"ms": "^2.1.1",
"safe-stable-stringify": "^2.3.1",
"triple-beam": "^1.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/loki-logger-ts": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/loki-logger-ts/-/loki-logger-ts-1.0.2.tgz",
"integrity": "sha512-SV/B5o+9jaxiThcU5N3LUxCNTx20IgR9xjCjx/ED/pVc/097mqKSRpmvSjvx9ezFcjJlUF7GBkrBBpR6veNp7Q==",
"dependencies": {
"axios": "^1.4.0"
}
},
"node_modules/long": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz",
"integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==",
"license": "Apache-2.0"
},
"node_modules/loupe": {
"version": "3.1.3",
"dev": true,
@ -5661,6 +6064,15 @@
"node": ">= 0.8"
}
},
"node_modules/on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"license": "ISC",
@ -5668,6 +6080,15 @@
"wrappy": "1"
}
},
"node_modules/one-time": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
"license": "MIT",
"dependencies": {
"fn.name": "1.x.x"
}
},
"node_modules/open": {
"version": "10.1.0",
"dev": true,
@ -6188,6 +6609,30 @@
"dev": true,
"license": "ISC"
},
"node_modules/protobufjs": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
"integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
"@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2",
"@protobufjs/codegen": "^2.0.4",
"@protobufjs/eventemitter": "^1.1.0",
"@protobufjs/fetch": "^1.1.0",
"@protobufjs/float": "^1.0.2",
"@protobufjs/inquire": "^1.1.0",
"@protobufjs/path": "^1.1.2",
"@protobufjs/pool": "^1.1.0",
"@protobufjs/utf8": "^1.1.0",
"@types/node": ">=13.7.0",
"long": "^5.0.0"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"license": "MIT",
@ -6380,6 +6825,19 @@
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
"node_modules/response-time": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.3.tgz",
"integrity": "sha512-SsjjOPHl/FfrTQNgmc5oen8Hr1Jxpn6LlHNXxCIFdYMHuK1kMeYMobb9XN3mvxaGQm3dbegqYFMX4+GDORfbWg==",
"license": "MIT",
"dependencies": {
"depd": "~2.0.0",
"on-headers": "~1.0.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/retry": {
"version": "0.12.0",
"license": "MIT",
@ -6558,6 +7016,15 @@
],
"license": "MIT"
},
"node_modules/safe-stable-stringify": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"license": "MIT"
@ -6801,6 +7268,15 @@
"simple-concat": "^1.0.0"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"license": "MIT",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/sirv": {
"version": "3.0.1",
"dev": true,
@ -6830,6 +7306,35 @@
"npm": ">= 3.0.0"
}
},
"node_modules/snappy": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/snappy/-/snappy-7.2.2.tgz",
"integrity": "sha512-iADMq1kY0v3vJmGTuKcFWSXt15qYUz7wFkArOrsSg0IFfI3nJqIJvK2/ZbEIndg7erIJLtAVX2nSOqPz7DcwbA==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
},
"optionalDependencies": {
"@napi-rs/snappy-android-arm-eabi": "7.2.2",
"@napi-rs/snappy-android-arm64": "7.2.2",
"@napi-rs/snappy-darwin-arm64": "7.2.2",
"@napi-rs/snappy-darwin-x64": "7.2.2",
"@napi-rs/snappy-freebsd-x64": "7.2.2",
"@napi-rs/snappy-linux-arm-gnueabihf": "7.2.2",
"@napi-rs/snappy-linux-arm64-gnu": "7.2.2",
"@napi-rs/snappy-linux-arm64-musl": "7.2.2",
"@napi-rs/snappy-linux-x64-gnu": "7.2.2",
"@napi-rs/snappy-linux-x64-musl": "7.2.2",
"@napi-rs/snappy-win32-arm64-msvc": "7.2.2",
"@napi-rs/snappy-win32-ia32-msvc": "7.2.2",
"@napi-rs/snappy-win32-x64-msvc": "7.2.2"
}
},
"node_modules/socks": {
"version": "2.8.4",
"license": "MIT",
@ -6957,6 +7462,15 @@
"license": "ISC",
"optional": true
},
"node_modules/stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/stackback": {
"version": "0.0.2",
"dev": true,
@ -7216,6 +7730,12 @@
"node": ">=8.0.0"
}
},
"node_modules/text-hex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
"license": "MIT"
},
"node_modules/tildify": {
"version": "2.0.0",
"license": "MIT",
@ -7320,6 +7840,15 @@
"node": ">=18"
}
},
"node_modules/triple-beam": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
"integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
"license": "MIT",
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/ts-api-utils": {
"version": "2.0.1",
"dev": true,
@ -7496,7 +8025,6 @@
},
"node_modules/undici-types": {
"version": "6.20.0",
"dev": true,
"license": "MIT"
},
"node_modules/unicorn-magic": {
@ -7577,6 +8105,12 @@
"punycode": "^2.1.0"
}
},
"node_modules/url-polyfill": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.13.tgz",
"integrity": "sha512-tXzkojrv2SujumYthZ/WjF7jaSfNhSXlYMpE5AYdL2I3D7DCeo+mch8KtW2rUuKjDg+3VXODXHVgipt8yGY/eQ==",
"license": "MIT"
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"license": "MIT"
@ -7987,24 +8521,6 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/vue-i18n": {
"version": "10.0.5",
"license": "MIT",
"dependencies": {
"@intlify/core-base": "10.0.5",
"@intlify/shared": "10.0.5",
"@vue/devtools-api": "^6.5.0"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-router": {
"version": "4.5.0",
"license": "MIT",
@ -8204,6 +8720,70 @@
"node": ">=8"
}
},
"node_modules/winston": {
"version": "3.17.0",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz",
"integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==",
"license": "MIT",
"dependencies": {
"@colors/colors": "^1.6.0",
"@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3",
"is-stream": "^2.0.0",
"logform": "^2.7.0",
"one-time": "^1.0.0",
"readable-stream": "^3.4.0",
"safe-stable-stringify": "^2.3.1",
"stack-trace": "0.0.x",
"triple-beam": "^1.3.0",
"winston-transport": "^4.9.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/winston-loki": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/winston-loki/-/winston-loki-6.1.3.tgz",
"integrity": "sha512-DjWtJ230xHyYQWr9mZJa93yhwHttn3JEtSYWP8vXZWJOahiQheUhf+88dSIidbGXB3u0oLweV6G1vkL/ouT62Q==",
"license": "MIT",
"dependencies": {
"async-exit-hook": "2.0.1",
"btoa": "^1.2.1",
"protobufjs": "^7.2.4",
"url-polyfill": "^1.1.12",
"winston-transport": "^4.3.0"
},
"optionalDependencies": {
"snappy": "^7.2.2"
}
},
"node_modules/winston-transport": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz",
"integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==",
"license": "MIT",
"dependencies": {
"logform": "^2.7.0",
"readable-stream": "^3.6.2",
"triple-beam": "^1.3.0"
},
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/winston/node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/word-wrap": {
"version": "1.2.5",
"dev": true,

View file

@ -35,9 +35,5 @@
"eslint-config-prettier": "^10.0.1",
"jiti": "^2.4.2",
"typescript-eslint": "^8.24.1"
},
"dependencies": {
"@types/js-yaml": "^4.0.9",
"vue-i18n": "^10.0.5"
}
}