aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.test.ts (renamed from src/util/config.test.ts)29
-rw-r--r--src/config.ts (renamed from src/util/config.ts)79
-rw-r--r--src/index.ts53
-rw-r--r--src/metadata.ts118
-rw-r--r--src/routes.test.ts25
-rw-r--r--src/routes.ts18
-rw-r--r--src/templates.ts6
-rw-r--r--src/util/logger.test.ts6
-rw-r--r--src/util/logger.ts9
9 files changed, 226 insertions, 117 deletions
diff --git a/src/util/config.test.ts b/src/config.test.ts
index 4343392..c7a8be4 100644
--- a/src/util/config.test.ts
+++ b/src/config.test.ts
@@ -4,10 +4,12 @@ const exit = jest
import { Writable } from "stream";
import winston from "winston";
+import loggerConfig from "./util/logger";
let output = "";
+const logger = winston.createLogger(loggerConfig("TEST", "debug"));
-jest.mock("./logger", () => {
+jest.mock("./util/logger", () => {
const stream = new Writable();
stream._write = (chunk, _encoding, next) => {
output = output += chunk.toString();
@@ -45,8 +47,8 @@ import {
import { Server } from "http";
import path from "path";
import fs from "fs";
-import * as templates from "../templates";
-import { EnvConfig } from "../metadata";
+import * as templates from "./templates";
+import { EnvConfig } from "./metadata";
const CommonMocks = {
connect: jest.fn(),
@@ -164,7 +166,7 @@ describe("initializeToken", () => {
output = "";
// Act
- const result = initializeToken();
+ const result = initializeToken(logger);
// Assert
expect(result).toMatch(/([a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8})/);
@@ -183,7 +185,7 @@ describe("configOrError", () => {
// Act
let result;
try {
- result = configOrError("APPLESAUCE");
+ result = configOrError("APPLESAUCE", logger);
} catch (err) {
//
}
@@ -198,7 +200,7 @@ describe("configOrError", () => {
process.env.CHRYSANTHEMUM = "hello";
// Act
- const result = configOrError("CHRYSANTHEMUM");
+ const result = configOrError("CHRYSANTHEMUM", logger);
// Assert
expect(result).toEqual(process.env.CHRYSANTHEMUM);
@@ -224,7 +226,7 @@ describe("persistTemplate", () => {
);
const fsAccess = jest.spyOn(fs.promises, "access").mockResolvedValue();
- await persistTemplate(template);
+ await persistTemplate(template, logger);
expect(processTemplate).toHaveBeenCalledWith(template);
expect(fsAccess).not.toHaveBeenCalled();
@@ -244,7 +246,7 @@ describe("persistTemplate", () => {
.mockRejectedValue("baa");
const fsAccess = jest.spyOn(fs.promises, "access").mockResolvedValue();
- await persistTemplate(template);
+ await persistTemplate(template, logger);
expect(processTemplate).toHaveBeenCalledWith(template);
expect(fsAccess).toHaveBeenCalledWith(
@@ -267,7 +269,7 @@ describe("persistTemplate", () => {
.mockRejectedValue("baz");
const fsAccess = jest.spyOn(fs.promises, "access").mockRejectedValue("bar");
- await persistTemplate(template);
+ await persistTemplate(template, logger);
expect(processTemplate).toHaveBeenCalledWith(template);
expect(fsAccess).toHaveBeenCalledWith(
@@ -288,9 +290,10 @@ describe("handleStartup", () => {
const config = {
hostDir: "/apple",
publicDir: "/public",
+ targetUrl: "localhost"
} as EnvConfig;
const confStartup = (): Promise<MongoClient> =>
- handleStartup("", config, "localhost");
+ handleStartup(config, logger);
it("should pass back MongoClient", async () => {
const superClient = {} as MongoClient;
@@ -429,7 +432,7 @@ describe("handleShutdown", () => {
// Act
try {
- await handleShutdown(mongo, server)("SIGINT");
+ await handleShutdown(mongo, server, logger)("SIGINT");
} catch (err) {
//
}
@@ -445,7 +448,7 @@ describe("handleShutdown", () => {
// Act
try {
- await handleShutdown(mongo, server)("SIGINT");
+ await handleShutdown(mongo, server, logger)("SIGINT");
} catch (err) {
//
}
@@ -461,7 +464,7 @@ describe("handleShutdown", () => {
// Act
try {
- await handleShutdown(mongo, server)("SIGINT");
+ await handleShutdown(mongo, server, logger)("SIGINT");
} catch (err) {
//
}
diff --git a/src/util/config.ts b/src/config.ts
index c8639fb..e836552 100644
--- a/src/util/config.ts
+++ b/src/config.ts
@@ -5,13 +5,13 @@ import path from "path";
import fs from "fs";
import { v4 as uuid } from "uuid";
-import loggerConfig from "./logger";
-import processTemplate, { Template } from "../templates";
-import { EnvConfig } from "../metadata";
+import processTemplate, { Template } from "./templates";
+import { EnvConfig } from "./metadata";
-const logger = winston.createLogger(loggerConfig("ROOT"));
-
-export const initializeToken = (): string => {
+/**
+ * Generate a token for use as the user self-identifier
+ */
+export const initializeToken = (logger: winston.Logger): string => {
//TODO check for token in hostDir/persist created token in hostDir so it's not regenerated on startup
const newToken = uuid();
@@ -26,7 +26,10 @@ export const initializeToken = (): string => {
return newToken;
};
-export const configOrError = (varName: string): string => {
+/**
+ * Get environment variable or exit application if it doesn't exist
+ */
+export const configOrError = (varName: string, logger: winston.Logger): string => {
const value = process.env[varName];
if (value !== undefined) {
return value;
@@ -36,7 +39,10 @@ export const configOrError = (varName: string): string => {
}
};
-export const persistTemplate = async (input: Template): Promise<void> => {
+/**
+ * Process a template and persist based on template.
+ */
+export const persistTemplate = async (input: Template, logger: winston.Logger): Promise<void> => {
try {
const template = await processTemplate(input);
logger.debug("Generated '%s' from template file", template.outputFile);
@@ -62,19 +68,23 @@ export const persistTemplate = async (input: Template): Promise<void> => {
}
};
-export const handleStartup = async (
- mongoUri: string,
- config: EnvConfig,
- targetUrl: string
-): Promise<MongoClient> => {
+/**
+ * Handle server start-up functions:
+ *
+ * - Open database connection
+ * - Generate documents from templates based on configuration
+ *
+ * If one of these actions cannot be performed, it will call `process.exit(1)`.
+ */
+export const handleStartup = async (config: EnvConfig, logger: winston.Logger): Promise<MongoClient> => {
try {
- const { hostDir, publicDir } = config;
+ const { hostDir, publicDir, dbUri, targetUrl } = config;
await fs.promises.access(hostDir, fs.constants.R_OK | fs.constants.W_OK);
if (!path.isAbsolute(hostDir)) {
await Promise.reject("hostDir must be an absolute path");
}
- const mongo = await MongoClient.connect(mongoUri).catch((err: MongoError) =>
+ const mongo = await MongoClient.connect(dbUri).catch((err: MongoError) =>
Promise.reject(err.message ?? "Unable to connect to database")
);
@@ -82,7 +92,7 @@ export const handleStartup = async (
inputFile: path.join(publicDir, "templates", "sh.tmpl"),
outputFile: path.join(hostDir, "sh"),
context: { TARGET_URL: targetUrl },
- } as Template);
+ } as Template, logger);
await persistTemplate({
inputFile: path.join(publicDir, "templates", "index.html.tmpl"),
outputFile: path.join(hostDir, "index.html"),
@@ -92,7 +102,7 @@ export const handleStartup = async (
? "--proto '=https' --tlsv1.2 "
: "",
},
- } as Template);
+ } as Template, logger);
return mongo;
} catch (err) {
@@ -101,22 +111,27 @@ export const handleStartup = async (
}
};
+/**
+ * Callback for NodeJS `process.on()` to handle shutdown signals
+ * and close open connections.
+ */
export const handleShutdown =
- (mongo: MongoClient, server: Server) =>
- (signal: NodeJS.Signals): Promise<void> => {
+ (mongo: MongoClient, server: Server, logger: winston.Logger) =>
+ async (signal: NodeJS.Signals): Promise<void> => {
logger.warn("%s signal received. Closing shop.", signal);
- return mongo
- .close()
- .then(() => {
- logger.info("MongoDB client connection closed.");
- return new Promise((res, rej) =>
- server.close((err) => {
- logger.info("Express down.");
- (err ? rej : res)(err);
- })
- );
- })
- .then(() => process.exit(0))
- .catch(() => process.exit(1));
+ try {
+ await mongo.close();
+ logger.info("MongoDB client connection closed.");
+
+ // must await for callback - wrapped in Promise
+ await new Promise((res, rej) => server.close((err) => {
+ logger.info("Express down.");
+ (err ? rej : res)(err);
+ }));
+
+ process.exit(0);
+ } catch (e) {
+ process.exit(1);
+ }
};
diff --git a/src/index.ts b/src/index.ts
index 1de4b10..d101ba3 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -4,8 +4,6 @@ import winston from "winston";
import expressWinston from "express-winston";
import path from "path";
-dotenv.config();
-
import routes from "./routes";
import Metadata, { EnvConfig } from "./metadata";
import loggerConfig from "./util/logger";
@@ -14,32 +12,45 @@ import {
handleStartup,
handleShutdown,
initializeToken,
-} from "./util/config";
-
-// Start-up configuration
-const BIND_ADDRESS = process.env.BIND_ADDRESS ?? "localhost";
-const MONGO_DB = process.env.MONGO_DB ?? "ao-coverage";
-const PORT = Number(process.env.PORT ?? 3000);
-const MONGO_URI = configOrError("MONGO_URI");
-const TARGET_URL = process.env.TARGET_URL ?? "http://localhost:3000";
+} from "./config";
+
+dotenv.config();
+
+const LOG_LEVEL = process.env.LOG_LEVEL ?? "info";
+const logger = winston.createLogger(loggerConfig("ROOT", LOG_LEVEL));
+
+// Application-wide configuration settings
const ENV_CONFIG: EnvConfig = {
- token: process.env.TOKEN ?? initializeToken(),
+ // Express configuration
+ bindAddress: process.env.BIND_ADDRESS ?? "localhost",
+ port: Number(process.env.PORT ?? 3000),
uploadLimit: Number(process.env.UPLOAD_LIMIT ?? 4194304),
+
+ // Database connection information
+ dbName: process.env.MONGO_DB ?? "ao-coverage",
+ dbUri: configOrError("MONGO_URI", logger),
+
+ // Where the server should say it's located
+ targetUrl: process.env.TARGET_URL ?? "http://localhost:3000",
+
+ // Directories used for serving static or uploaded files
publicDir: path.join(__dirname, "..", "public"),
- hostDir: configOrError("HOST_DIR"),
+ hostDir: configOrError("HOST_DIR", logger),
+
+ // Application configuration
+ token: process.env.TOKEN ?? initializeToken(logger),
stage1: Number(process.env.STAGE_1 ?? 95),
stage2: Number(process.env.STAGE_2 ?? 80),
+ logLevel: LOG_LEVEL,
};
-const logger = winston.createLogger(loggerConfig("ROOT"));
-
-handleStartup(MONGO_URI, ENV_CONFIG, TARGET_URL).then((mongo) => {
+handleStartup(ENV_CONFIG, logger).then((mongo) => {
const app: express.Application = express();
- const metadata = new Metadata(mongo.db(MONGO_DB), ENV_CONFIG);
+ const metadata = new Metadata(mongo.db(ENV_CONFIG.dbName), ENV_CONFIG);
app.use(
expressWinston.logger({
- ...loggerConfig("HTTP"),
+ ...loggerConfig("HTTP", ENV_CONFIG.logLevel),
colorize: true,
// filter out token query param from URL
msg: '{{req.method}} {{req.url.replace(/token=[-\\w.~]*(&*)/, "token=$1")}} - {{res.statusCode}} {{res.responseTime}}ms',
@@ -49,15 +60,15 @@ handleStartup(MONGO_URI, ENV_CONFIG, TARGET_URL).then((mongo) => {
// actual app routes
app.use(routes(metadata));
- app.use(expressWinston.errorLogger(loggerConfig("_ERR")));
+ app.use(expressWinston.errorLogger(loggerConfig("_ERR", ENV_CONFIG.logLevel)));
- const server = app.listen(PORT, BIND_ADDRESS, () => {
- logger.info("Express has started: http://%s:%d/", BIND_ADDRESS, PORT);
+ const server = app.listen(ENV_CONFIG.port, ENV_CONFIG.bindAddress, () => {
+ logger.info("Express has started: http://%s:%d/", ENV_CONFIG.bindAddress, ENV_CONFIG.port);
});
// application exit handling
const signalCodes: NodeJS.Signals[] = ["SIGTERM", "SIGHUP", "SIGINT"];
signalCodes.map((code: NodeJS.Signals) => {
- process.on(code, handleShutdown(mongo, server));
+ process.on(code, handleShutdown(mongo, server, logger));
});
});
diff --git a/src/metadata.ts b/src/metadata.ts
index 3cba605..6f6d401 100644
--- a/src/metadata.ts
+++ b/src/metadata.ts
@@ -10,12 +10,6 @@ interface HeadContext {
format: string;
}
-export const isError = (
- obj: HeadContext | BranchNotFoundError
-): obj is BranchNotFoundError => {
- return Object.keys(obj).includes("name");
-};
-
interface Branch {
head: HeadContext | string;
}
@@ -37,49 +31,62 @@ export interface Repository {
branches: BranchList;
}
-const logger = winston.createLogger(loggerConfig("META"));
-
+/**
+ * Holds environment configuration items for the application
+ */
export interface EnvConfig {
- token: string;
+ /** Express value to bind to a given address */
+ bindAddress: string;
+ /** Express value for port */
+ port: number;
+ /** Express value to limit uploads to server */
uploadLimit: number;
+ /** Configuration for the database name */
+ dbName: string;
+ /** Configuration for the database URI */
+ dbUri: string;
+ /** The address given for communicating back to the server */
+ targetUrl: string;
+ /** The host directory for uploaded files */
hostDir: string;
+ /** The public directory for static files */
publicDir: string;
+ /** The application server token to serve as user self-identifier */
+ token: string;
+ /** Gradient setting 1 */
stage1: number;
+ /** Gradient setting 2 */
stage2: number;
+ /** Log level across application */
+ logLevel: string;
}
+/**
+ * Check if provided response is a known application error
+ */
+export const isError = (
+ obj: HeadContext | BranchNotFoundError
+): obj is BranchNotFoundError => {
+ return Object.keys(obj).includes("name");
+};
+
+/**
+ * Handles data routing for application
+ */
class Metadata {
database: Db;
config: EnvConfig;
+ logger: winston.Logger;
constructor(client: Db, data: EnvConfig) {
+ this.logger = winston.createLogger(loggerConfig("META", data.logLevel));
this.database = client;
this.config = data;
}
- getToken(): string {
- return this.config.token;
- }
-
- getUploadLimit(): number {
- return this.config.uploadLimit;
- }
-
- getHostDir(): string {
- return this.config.hostDir;
- }
-
- getPublicDir(): string {
- return this.config.publicDir;
- }
-
- getGradientStyle(): GradientStyle {
- return {
- stage1: this.config.stage1,
- stage2: this.config.stage2,
- };
- }
-
+ /**
+ * Retrieve the latest commit to the given branch
+ */
async getHeadCommit(
organization: string,
repository: string,
@@ -98,7 +105,7 @@ class Metadata {
const head = typeof limb.head === "string" ? limb.head : limb.head.commit;
const format =
typeof limb.head === "string" ? "tarpaulin" : limb.head.format;
- logger.debug(
+ this.logger.debug(
"Found commit %s for ORB %s/%s/%s (format %s)",
head,
organization,
@@ -112,6 +119,9 @@ class Metadata {
}
}
+ /**
+ * Update the database with the latest commit to a branch
+ */
async updateBranch(identity: HeadIdentity): Promise<boolean> {
const { organization, repository: name, branch, head } = identity;
const result = await this.database
@@ -128,6 +138,9 @@ class Metadata {
return result.ok === 1;
}
+ /**
+ * Add a repository metadata document to the database
+ */
async createRepository(identity: HeadIdentity): Promise<boolean> {
const { organization, repository: name, branch, head } = identity;
const repo: Repository = {
@@ -142,6 +155,45 @@ class Metadata {
return result.acknowledged;
}
+
+ /**
+ * Retrieve the application token from configuration
+ */
+ getToken(): string {
+ return this.config.token;
+ }
+
+ /**
+ * Retrieve the upload limit for files from configuration
+ */
+ getUploadLimit(): number {
+ return this.config.uploadLimit;
+ }
+
+ /**
+ * Retrieve the host for uploaded documents directory from configuration
+ */
+ getHostDir(): string {
+ return this.config.hostDir;
+ }
+
+ /**
+ * Retrieve the public static file directory from configuration
+ */
+ getPublicDir(): string {
+ return this.config.publicDir;
+ }
+
+ /**
+ * Retrieve the gradient style from configuration
+ */
+ getGradientStyle(): GradientStyle {
+ return {
+ stage1: this.config.stage1,
+ stage2: this.config.stage2,
+ };
+ }
+
}
export default Metadata;
diff --git a/src/routes.test.ts b/src/routes.test.ts
index 12210bf..5d7839c 100644
--- a/src/routes.test.ts
+++ b/src/routes.test.ts
@@ -8,6 +8,8 @@ import express from "express";
import dotenv from "dotenv";
import fs from "fs";
import path from "path";
+import { Writable } from "stream";
+import winston from "winston";
dotenv.config();
@@ -23,9 +25,6 @@ test("HOST_DIR must be readable and writable", () => {
).not.toThrowError();
});
-import { Writable } from "stream";
-import winston from "winston";
-
let output = "";
jest.mock("./util/logger", () => {
@@ -48,7 +47,8 @@ jest.mock("./util/logger", () => {
};
});
-import { configOrError, persistTemplate } from "./util/config";
+import { configOrError, persistTemplate } from "./config";
+import loggerConfig from "./util/logger";
import routes from "./routes";
import Metadata, { EnvConfig } from "./metadata";
import { Template } from "./templates";
@@ -57,6 +57,7 @@ import { badgen } from "badgen";
import { BranchNotFoundError } from "./errors";
type MetadataMockType = {
+ logger: winston.Logger;
database: Db;
config: EnvConfig;
getHeadCommit: jest.Mock;
@@ -68,15 +69,22 @@ type MetadataMockType = {
updateBranch: jest.Mock;
createRepository: jest.Mock;
};
+const logger = winston.createLogger(loggerConfig("TEST", "debug"));
const config = {
token: "THISISCORRECT",
// should be just larger than the example report used
uploadLimit: Number(40000),
- hostDir: configOrError("HOST_DIR"),
+ hostDir: configOrError("HOST_DIR", logger),
publicDir: path.join(__dirname, "..", "public"),
stage1: 95,
stage2: 80,
+ bindAddress: "localhost",
+ targetUrl: "http://localhost:3000/",
+ port: 3000,
+ dbName: "ao-coverage",
+ dbUri: "localhost",
+ logLevel: "debug",
};
const mock = (
headCommit: jest.Mock = jest.fn(
@@ -85,6 +93,7 @@ const mock = (
),
updateBranch: jest.Mock = jest.fn(() => new Promise((solv) => solv(true)))
): MetadataMockType => ({
+ logger,
database: {} as Db,
config: config,
getToken: jest.fn(() => config.token),
@@ -109,7 +118,7 @@ const request = async (
return _request(app);
};
-const HOST_DIR = configOrError("HOST_DIR");
+const HOST_DIR = configOrError("HOST_DIR", logger);
const TARGET_URL = "https://localhost:3000";
describe("templates", () => {
@@ -119,7 +128,7 @@ describe("templates", () => {
inputFile: path.join(__dirname, "..", "public", "templates", "sh.tmpl"),
outputFile: path.join(HOST_DIR, "sh"),
context: { TARGET_URL },
- } as Template);
+ } as Template, logger);
const res = await (await request()).get("/sh").expect(200);
expect(exit).not.toHaveBeenCalled();
@@ -140,7 +149,7 @@ describe("templates", () => {
),
outputFile: path.join(HOST_DIR, "index.html"),
context: { TARGET_URL, CURL_HTTPS: "--https " },
- } as Template);
+ } as Template, logger);
const res = await (await request())
.get("/")
diff --git a/src/routes.ts b/src/routes.ts
index a8360ca..0998345 100644
--- a/src/routes.ts
+++ b/src/routes.ts
@@ -9,11 +9,16 @@ import Metadata, { HeadIdentity, isError } from "./metadata";
import loggerConfig from "./util/logger";
import { InvalidReportDocumentError, Messages } from "./errors";
-const logger = winston.createLogger(loggerConfig("HTTP"));
-
-export default (metadata: Metadata): Router => {
+/**
+ * Provide routes from application state
+ */
+const routes = (metadata: Metadata): Router => {
const router = Router();
+ const logger = winston.createLogger(loggerConfig("HTTP", metadata.logger.level));
+ /**
+ * Persist uploaded coverage report and creates coverage badge
+ */
const commitFormatDocs = async (
contents: string,
identity: HeadIdentity,
@@ -138,6 +143,9 @@ export default (metadata: Metadata): Router => {
});
});
+ /**
+ * Read a file from the host directory.
+ */
const retrieveFile = (
res: express.Response,
identity: HeadIdentity,
@@ -238,6 +246,7 @@ export default (metadata: Metadata): Router => {
retrieveFile(res, identity, format.fileName);
});
+ // provide hard link for commit
router.get("/v1/:org/:repo/:branch/:commit.xml", (req, res) => {
const { org, repo, branch, commit } = req.params;
const format = formats.formats.cobertura;
@@ -250,6 +259,7 @@ export default (metadata: Metadata): Router => {
retrieveFile(res, identity, format.fileName);
});
+ // return 404 for all other routes
router.use((_, res) => {
res.status(404);
res.sendFile(path.join(metadata.getPublicDir(), "static", "404.html"));
@@ -257,3 +267,5 @@ export default (metadata: Metadata): Router => {
return router;
};
+
+export default routes;
diff --git a/src/templates.ts b/src/templates.ts
index 648bb56..26451cf 100644
--- a/src/templates.ts
+++ b/src/templates.ts
@@ -1,6 +1,9 @@
import handlebars from "handlebars";
import fs from "fs";
+/**
+ * Information for processing a template file into the output file
+ */
export interface Template {
inputFile: string;
outputFile: string;
@@ -8,6 +11,9 @@ export interface Template {
data?: string;
}
+/**
+ * Process input file and produce file at given output location
+ */
export default async (_template: Template): Promise<Template> => {
const buffer = await fs.promises.readFile(_template.inputFile, "utf-8");
diff --git a/src/util/logger.test.ts b/src/util/logger.test.ts
index a673bad..a7e81c1 100644
--- a/src/util/logger.test.ts
+++ b/src/util/logger.test.ts
@@ -12,7 +12,7 @@ describe("Logger configurer", () => {
};
// Act
- const result = configureLogger(clazz);
+ const result = configureLogger(clazz, adapter.level);
const actual = result.format.transform(Object.assign({}, adapter));
// Assert
@@ -34,7 +34,7 @@ describe("Logger configurer", () => {
};
// Act
- const result = configureLogger(label);
+ const result = configureLogger(label, adapter.level);
const actual = result.format.transform(Object.assign({}, adapter));
// Assert
@@ -51,7 +51,7 @@ describe("Logger configurer", () => {
const label = "aaa";
// Act
- const result = configureLogger(label);
+ const result = configureLogger(label, "info");
// Assert
expect(result.transports).toBeInstanceOf(Array);
diff --git a/src/util/logger.ts b/src/util/logger.ts
index d779718..9b0957d 100644
--- a/src/util/logger.ts
+++ b/src/util/logger.ts
@@ -4,8 +4,7 @@ import * as Transport from "winston-transport";
const { combine, splat, timestamp, label, colorize, printf } = winston.format;
const { Console } = winston.transports;
-const LOG_LEVEL = process.env.LOG_LEVEL ?? "info";
-
+// Standard console message formatting
const consoleFormat = combine(
colorize(),
printf(({ level, message, label, timestamp }) => {
@@ -16,9 +15,9 @@ const consoleFormat = combine(
/**
* Provides standard logging format and output for the server.
*/
-export default (
+const loggerConfig = (
clazz: string,
- level: string = LOG_LEVEL
+ level: string
): {
format: Format;
transports: Transport[];
@@ -26,3 +25,5 @@ export default (
format: combine(splat(), timestamp(), label({ label: clazz })),
transports: [new Console({ level: level, format: consoleFormat })],
});
+
+export default loggerConfig;