feat(logging): add log level env variable (#2299)
This commit is contained in:
@@ -12,6 +12,8 @@ AUTH_SECRET="supersecret"
|
||||
# or starting the project without any (which will show a randomly generated one).
|
||||
SECRET_ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000
|
||||
|
||||
LOG_LEVEL='info'
|
||||
|
||||
# This is how you can use the sqlite driver:
|
||||
DB_DRIVER='better-sqlite3'
|
||||
DB_URL='FULL_PATH_TO_YOUR_SQLITE_DB_FILE'
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
import "@homarr/auth/env";
|
||||
import "@homarr/db/env";
|
||||
import "@homarr/common/env";
|
||||
import "@homarr/log/env";
|
||||
import "@homarr/docker/env";
|
||||
|
||||
import type { NextConfig } from "next";
|
||||
import MillionLint from "@million/lint";
|
||||
import createNextIntlPlugin from "next-intl/plugin";
|
||||
|
||||
import "./src/env.ts";
|
||||
|
||||
// Package path does not work... so we need to use relative path
|
||||
const withNextIntl = createNextIntlPlugin("../../packages/translation/src/request.ts");
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
"@mantine/modals": "^7.17.0",
|
||||
"@mantine/tiptap": "^7.17.0",
|
||||
"@million/lint": "1.0.14",
|
||||
"@t3-oss/env-nextjs": "^0.12.0",
|
||||
"@tabler/icons-react": "^3.30.0",
|
||||
"@tanstack/react-query": "^5.66.7",
|
||||
"@tanstack/react-query-devtools": "^5.66.7",
|
||||
|
||||
@@ -20,8 +20,7 @@ import type { SuperJSONResult } from "superjson";
|
||||
import type { AppRouter } from "@homarr/api";
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import { createHeadersCallbackForSource, getTrpcUrl } from "@homarr/api/shared";
|
||||
|
||||
import { env } from "~/env";
|
||||
import { env } from "@homarr/common/env";
|
||||
|
||||
const getWebSocketProtocol = () => {
|
||||
// window is not defined on server side
|
||||
@@ -66,7 +65,7 @@ export function TRPCReactProvider(props: PropsWithChildren) {
|
||||
links: [
|
||||
loggerLink({
|
||||
enabled: (opts) =>
|
||||
process.env.NODE_ENV === "development" || (opts.direction === "down" && opts.result instanceof Error),
|
||||
env.NODE_ENV === "development" || (opts.direction === "down" && opts.result instanceof Error),
|
||||
}),
|
||||
splitLink({
|
||||
condition: ({ type }) => type === "subscription",
|
||||
|
||||
@@ -23,6 +23,7 @@ import { clientApi } from "@homarr/api/client";
|
||||
import { useRequiredBoard } from "@homarr/boards/context";
|
||||
import { useEditMode } from "@homarr/boards/edit-mode";
|
||||
import { revalidatePathActionAsync } from "@homarr/common/client";
|
||||
import { env } from "@homarr/common/env";
|
||||
import { useConfirmModal, useModalAction } from "@homarr/modals";
|
||||
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
|
||||
import { useI18n, useScopedI18n } from "@homarr/translation/client";
|
||||
@@ -33,7 +34,6 @@ import { useCategoryActions } from "~/components/board/sections/category/categor
|
||||
import { CategoryEditModal } from "~/components/board/sections/category/category-edit-modal";
|
||||
import { useDynamicSectionActions } from "~/components/board/sections/dynamic/dynamic-actions";
|
||||
import { HeaderButton } from "~/components/layout/header/button";
|
||||
import { env } from "~/env";
|
||||
|
||||
export const BoardContentHeaderActions = () => {
|
||||
const [isEditMode] = useEditMode();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import { Center } from "@mantine/core";
|
||||
|
||||
import { env } from "@homarr/common/env";
|
||||
import { db } from "@homarr/db";
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
import { widgetImports } from "@homarr/widgets";
|
||||
|
||||
import { env } from "~/env";
|
||||
import { WidgetPreviewPageContent } from "./_content";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
import { shouldSkipEnvValidation } from "@homarr/common/env-validation";
|
||||
|
||||
export const env = createEnv({
|
||||
shared: {
|
||||
PORT: z.coerce.number().default(3000),
|
||||
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
||||
},
|
||||
/**
|
||||
* Specify your server-side environment variables schema here. This way you can ensure the app isn't
|
||||
* built with invalid env vars.
|
||||
*/
|
||||
server: {},
|
||||
/**
|
||||
* Specify your client-side environment variables schema here.
|
||||
* For them to be exposed to the client, prefix them with `NEXT_PUBLIC_`.
|
||||
*/
|
||||
client: {
|
||||
// NEXT_PUBLIC_CLIENTVAR: z.string(),
|
||||
},
|
||||
/**
|
||||
* Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
|
||||
*/
|
||||
runtimeEnv: {
|
||||
PORT: process.env.PORT,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
|
||||
},
|
||||
skipValidation: shouldSkipEnvValidation(),
|
||||
emptyStringAsUndefined: true,
|
||||
});
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
import { createBooleanSchema, createDurationSchema, shouldSkipEnvValidation } from "@homarr/common/env-validation";
|
||||
import { supportedAuthProviders } from "@homarr/definitions";
|
||||
import { createEnv } from "@homarr/env";
|
||||
import { createBooleanSchema, createDurationSchema } from "@homarr/env/schemas";
|
||||
|
||||
const authProvidersSchema = z
|
||||
.string()
|
||||
@@ -22,8 +22,7 @@ const authProvidersSchema = z
|
||||
)
|
||||
.default("credentials");
|
||||
|
||||
const skipValidation = shouldSkipEnvValidation();
|
||||
const authProviders = skipValidation ? [] : authProvidersSchema.parse(process.env.AUTH_PROVIDERS);
|
||||
const authProviders = authProvidersSchema.safeParse(process.env.AUTH_PROVIDERS).data ?? [];
|
||||
|
||||
export const env = createEnv({
|
||||
server: {
|
||||
@@ -59,32 +58,5 @@ export const env = createEnv({
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
client: {},
|
||||
runtimeEnv: {
|
||||
AUTH_LOGOUT_REDIRECT_URL: process.env.AUTH_LOGOUT_REDIRECT_URL,
|
||||
AUTH_SESSION_EXPIRY_TIME: process.env.AUTH_SESSION_EXPIRY_TIME,
|
||||
AUTH_PROVIDERS: process.env.AUTH_PROVIDERS,
|
||||
AUTH_LDAP_BASE: process.env.AUTH_LDAP_BASE,
|
||||
AUTH_LDAP_BIND_DN: process.env.AUTH_LDAP_BIND_DN,
|
||||
AUTH_LDAP_BIND_PASSWORD: process.env.AUTH_LDAP_BIND_PASSWORD,
|
||||
AUTH_LDAP_GROUP_CLASS: process.env.AUTH_LDAP_GROUP_CLASS,
|
||||
AUTH_LDAP_GROUP_FILTER_EXTRA_ARG: process.env.AUTH_LDAP_GROUP_FILTER_EXTRA_ARG,
|
||||
AUTH_LDAP_GROUP_MEMBER_ATTRIBUTE: process.env.AUTH_LDAP_GROUP_MEMBER_ATTRIBUTE,
|
||||
AUTH_LDAP_GROUP_MEMBER_USER_ATTRIBUTE: process.env.AUTH_LDAP_GROUP_MEMBER_USER_ATTRIBUTE,
|
||||
AUTH_LDAP_SEARCH_SCOPE: process.env.AUTH_LDAP_SEARCH_SCOPE,
|
||||
AUTH_LDAP_URI: process.env.AUTH_LDAP_URI,
|
||||
AUTH_OIDC_CLIENT_ID: process.env.AUTH_OIDC_CLIENT_ID,
|
||||
AUTH_OIDC_CLIENT_NAME: process.env.AUTH_OIDC_CLIENT_NAME,
|
||||
AUTH_OIDC_CLIENT_SECRET: process.env.AUTH_OIDC_CLIENT_SECRET,
|
||||
AUTH_OIDC_ISSUER: process.env.AUTH_OIDC_ISSUER,
|
||||
AUTH_OIDC_SCOPE_OVERWRITE: process.env.AUTH_OIDC_SCOPE_OVERWRITE,
|
||||
AUTH_OIDC_GROUPS_ATTRIBUTE: process.env.AUTH_OIDC_GROUPS_ATTRIBUTE,
|
||||
AUTH_LDAP_USERNAME_ATTRIBUTE: process.env.AUTH_LDAP_USERNAME_ATTRIBUTE,
|
||||
AUTH_LDAP_USER_MAIL_ATTRIBUTE: process.env.AUTH_LDAP_USER_MAIL_ATTRIBUTE,
|
||||
AUTH_LDAP_USERNAME_FILTER_EXTRA_ARG: process.env.AUTH_LDAP_USERNAME_FILTER_EXTRA_ARG,
|
||||
AUTH_OIDC_AUTO_LOGIN: process.env.AUTH_OIDC_AUTO_LOGIN,
|
||||
AUTH_OIDC_NAME_ATTRIBUTE_OVERWRITE: process.env.AUTH_OIDC_NAME_ATTRIBUTE_OVERWRITE,
|
||||
},
|
||||
skipValidation,
|
||||
emptyStringAsUndefined: true,
|
||||
experimental__runtimeEnv: process.env,
|
||||
});
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
"@homarr/common": "workspace:^0.1.0",
|
||||
"@homarr/db": "workspace:^0.1.0",
|
||||
"@homarr/definitions": "workspace:^0.1.0",
|
||||
"@homarr/env": "workspace:^0.1.0",
|
||||
"@homarr/log": "workspace:^0.1.0",
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@t3-oss/env-nextjs": "^0.12.0",
|
||||
"bcrypt": "^5.1.1",
|
||||
"cookies": "^0.9.1",
|
||||
"ldapts": "7.3.1",
|
||||
|
||||
@@ -6,10 +6,11 @@ import { rootCertificates } from "node:tls";
|
||||
import axios from "axios";
|
||||
import { fetch } from "undici";
|
||||
|
||||
import { env } from "@homarr/common/env";
|
||||
import { LoggingAgent } from "@homarr/common/server";
|
||||
|
||||
const getCertificateFolder = () => {
|
||||
return process.env.NODE_ENV === "production"
|
||||
return env.NODE_ENV === "production"
|
||||
? path.join("/appdata", "trusted-certificates")
|
||||
: process.env.LOCAL_CERTIFICATE_PATH;
|
||||
};
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { randomBytes } from "crypto";
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
import { shouldSkipEnvValidation } from "./src/env-validation";
|
||||
import { createEnv } from "@homarr/env";
|
||||
|
||||
const errorSuffix = `, please generate a 64 character secret in hex format or use the following: "${randomBytes(32).toString("hex")}"`;
|
||||
|
||||
export const env = createEnv({
|
||||
shared: {
|
||||
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
||||
},
|
||||
server: {
|
||||
SECRET_ENCRYPTION_KEY: z
|
||||
.string({
|
||||
@@ -24,7 +26,6 @@ export const env = createEnv({
|
||||
},
|
||||
runtimeEnv: {
|
||||
SECRET_ENCRYPTION_KEY: process.env.SECRET_ENCRYPTION_KEY,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
},
|
||||
skipValidation: shouldSkipEnvValidation(),
|
||||
emptyStringAsUndefined: true,
|
||||
});
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
},
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
"@homarr/env": "workspace:^0.1.0",
|
||||
"@homarr/log": "workspace:^0.1.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"next": "15.1.7",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
import { shouldSkipEnvValidation } from "@homarr/common/env-validation";
|
||||
import { env as commonEnv } from "@homarr/common/env";
|
||||
import { createEnv } from "@homarr/env";
|
||||
|
||||
const drivers = {
|
||||
betterSqlite3: "better-sqlite3",
|
||||
@@ -29,7 +29,7 @@ export const env = createEnv({
|
||||
? {
|
||||
DB_URL:
|
||||
// Fallback to the default sqlite file path in production
|
||||
process.env.NODE_ENV === "production" && isDriver("better-sqlite3")
|
||||
commonEnv.NODE_ENV === "production" && isDriver("better-sqlite3")
|
||||
? z.string().default("/appdata/db/db.sqlite")
|
||||
: z.string().nonempty(),
|
||||
}
|
||||
@@ -49,18 +49,5 @@ export const env = createEnv({
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
/**
|
||||
* Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
|
||||
*/
|
||||
runtimeEnv: {
|
||||
DB_DRIVER: process.env.DB_DRIVER,
|
||||
DB_URL: process.env.DB_URL,
|
||||
DB_HOST: process.env.DB_HOST,
|
||||
DB_USER: process.env.DB_USER,
|
||||
DB_PASSWORD: process.env.DB_PASSWORD,
|
||||
DB_NAME: process.env.DB_NAME,
|
||||
DB_PORT: process.env.DB_PORT,
|
||||
},
|
||||
skipValidation: shouldSkipEnvValidation(),
|
||||
emptyStringAsUndefined: true,
|
||||
experimental__runtimeEnv: process.env,
|
||||
});
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
"@auth/core": "^0.37.4",
|
||||
"@homarr/common": "workspace:^0.1.0",
|
||||
"@homarr/definitions": "workspace:^0.1.0",
|
||||
"@homarr/env": "workspace:^0.1.0",
|
||||
"@homarr/log": "workspace:^0.1.0",
|
||||
"@homarr/server-settings": "workspace:^0.1.0",
|
||||
"@mantine/core": "^7.17.0",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@t3-oss/env-nextjs": "^0.12.0",
|
||||
"@testcontainers/mysql": "^10.18.0",
|
||||
"better-sqlite3": "^11.8.1",
|
||||
"dotenv": "^16.4.7",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
"@homarr/common": "workspace:^0.1.0",
|
||||
"@t3-oss/env-nextjs": "^0.12.0",
|
||||
"@homarr/env": "workspace:^0.1.0",
|
||||
"dockerode": "^4.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
import { shouldSkipEnvValidation } from "@homarr/common/env-validation";
|
||||
import { createEnv } from "@homarr/env";
|
||||
|
||||
export const env = createEnv({
|
||||
server: {
|
||||
@@ -9,10 +8,5 @@ export const env = createEnv({
|
||||
DOCKER_HOSTNAMES: z.string().optional(),
|
||||
DOCKER_PORTS: z.string().optional(),
|
||||
},
|
||||
runtimeEnv: {
|
||||
DOCKER_HOSTNAMES: process.env.DOCKER_HOSTNAMES,
|
||||
DOCKER_PORTS: process.env.DOCKER_PORTS,
|
||||
},
|
||||
skipValidation: shouldSkipEnvValidation(),
|
||||
emptyStringAsUndefined: true,
|
||||
experimental__runtimeEnv: process.env,
|
||||
});
|
||||
|
||||
9
packages/env/eslint.config.js
vendored
Normal file
9
packages/env/eslint.config.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import baseConfig from "@homarr/eslint-config/base";
|
||||
|
||||
/** @type {import('typescript-eslint').Config} */
|
||||
export default [
|
||||
{
|
||||
ignores: [],
|
||||
},
|
||||
...baseConfig,
|
||||
];
|
||||
1
packages/env/index.ts
vendored
Normal file
1
packages/env/index.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./src";
|
||||
36
packages/env/package.json
vendored
Normal file
36
packages/env/package.json
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "@homarr/env",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./index.ts",
|
||||
"./schemas": "./src/schemas.ts"
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"*": [
|
||||
"src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rm -rf .turbo node_modules",
|
||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||
"lint": "eslint",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
"@t3-oss/env-nextjs": "^0.12.0",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
"@homarr/prettier-config": "workspace:^0.1.0",
|
||||
"@homarr/tsconfig": "workspace:^0.1.0",
|
||||
"eslint": "^9.20.1",
|
||||
"typescript": "^5.7.3"
|
||||
}
|
||||
}
|
||||
9
packages/env/src/index.ts
vendored
Normal file
9
packages/env/src/index.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createEnv as createEnvT3 } from "@t3-oss/env-nextjs";
|
||||
|
||||
export const defaultEnvOptions = {
|
||||
emptyStringAsUndefined: true,
|
||||
skipValidation:
|
||||
Boolean(process.env.CI) || Boolean(process.env.SKIP_ENV_VALIDATION) || process.env.npm_lifecycle_event === "lint",
|
||||
} satisfies Partial<Parameters<typeof createEnvT3>[0]>;
|
||||
|
||||
export const createEnv: typeof createEnvT3 = (options) => createEnvT3({ ...defaultEnvOptions, ...options });
|
||||
39
packages/env/src/schemas.ts
vendored
Normal file
39
packages/env/src/schemas.ts
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const trueStrings = ["1", "yes", "t", "true"];
|
||||
const falseStrings = ["0", "no", "f", "false"];
|
||||
|
||||
export const createBooleanSchema = (defaultValue: boolean) =>
|
||||
z
|
||||
.string()
|
||||
.default(defaultValue.toString())
|
||||
.transform((value, ctx) => {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (trueStrings.includes(normalized)) return true;
|
||||
if (falseStrings.includes(normalized)) return false;
|
||||
|
||||
throw new Error(`Invalid boolean value for ${ctx.path.join(".")}`);
|
||||
});
|
||||
|
||||
export const createDurationSchema = (defaultValue: `${number}${"s" | "m" | "h" | "d"}`) =>
|
||||
z
|
||||
.string()
|
||||
.regex(/^\d+[smhd]?$/)
|
||||
.default(defaultValue)
|
||||
.transform((duration) => {
|
||||
const lastChar = duration[duration.length - 1] as "s" | "m" | "h" | "d";
|
||||
if (!isNaN(Number(lastChar))) {
|
||||
return Number(defaultValue);
|
||||
}
|
||||
|
||||
const multipliers = {
|
||||
s: 1,
|
||||
m: 60,
|
||||
h: 60 * 60,
|
||||
d: 60 * 60 * 24,
|
||||
};
|
||||
const numberDuration = Number(duration.slice(0, -1));
|
||||
const multiplier = multipliers[lastChar];
|
||||
|
||||
return numberDuration * multiplier;
|
||||
});
|
||||
8
packages/env/tsconfig.json
vendored
Normal file
8
packages/env/tsconfig.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "@homarr/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
|
||||
},
|
||||
"include": ["*.ts", "src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
@@ -5,11 +5,8 @@
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./src/index.d.ts",
|
||||
"default": "./src/index.mjs"
|
||||
},
|
||||
"./override": "./src/override.cjs"
|
||||
".": "./src/index.ts",
|
||||
"./env": "./src/env.ts"
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
@@ -26,9 +23,11 @@
|
||||
},
|
||||
"prettier": "@homarr/prettier-config",
|
||||
"dependencies": {
|
||||
"@homarr/env": "workspace:^0.1.0",
|
||||
"ioredis": "5.5.0",
|
||||
"superjson": "2.2.2",
|
||||
"winston": "3.17.0"
|
||||
"winston": "3.17.0",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
|
||||
10
packages/log/src/env.ts
Normal file
10
packages/log/src/env.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { createEnv } from "@homarr/env";
|
||||
|
||||
export const env = createEnv({
|
||||
server: {
|
||||
LOG_LEVEL: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
||||
},
|
||||
experimental__runtimeEnv: process.env,
|
||||
});
|
||||
4
packages/log/src/index.d.ts
vendored
4
packages/log/src/index.d.ts
vendored
@@ -1,4 +0,0 @@
|
||||
import type { Logger } from "winston";
|
||||
|
||||
// The following is just to make prettier happy
|
||||
export const logger: Logger = undefined as unknown as Logger;
|
||||
@@ -1,12 +1,14 @@
|
||||
import type { transport as Transport } from "winston";
|
||||
import winston, { format, transports } from "winston";
|
||||
|
||||
import { RedisTransport } from "./redis-transport.mjs";
|
||||
import { env } from "./env";
|
||||
import { RedisTransport } from "./redis-transport";
|
||||
|
||||
const logMessageFormat = format.printf(({ level, message, timestamp }) => {
|
||||
return `${timestamp} ${level}: ${message}`;
|
||||
return `${timestamp as string} ${level}: ${message as string}`;
|
||||
});
|
||||
|
||||
const logTransports = [new transports.Console()];
|
||||
const logTransports: Transport[] = [new transports.Console()];
|
||||
|
||||
// Only add the Redis transport if we are not in CI
|
||||
if (!(Boolean(process.env.CI) || Boolean(process.env.DISABLE_REDIS_LOGS))) {
|
||||
@@ -16,6 +18,7 @@ if (!(Boolean(process.env.CI) || Boolean(process.env.DISABLE_REDIS_LOGS))) {
|
||||
const logger = winston.createLogger({
|
||||
format: format.combine(format.colorize(), format.timestamp(), logMessageFormat),
|
||||
transports: logTransports,
|
||||
level: env.LOG_LEVEL,
|
||||
});
|
||||
|
||||
export { logger };
|
||||
@@ -1,42 +0,0 @@
|
||||
void (async () => {
|
||||
const { logger } = await import("./index.mjs");
|
||||
|
||||
const nextLogger = require("next/dist/build/output/log");
|
||||
|
||||
const getWinstonMethodForConsole = (consoleMethod) => {
|
||||
switch (consoleMethod) {
|
||||
case "error":
|
||||
return (...messages) => logger.error(messages.join(" "));
|
||||
case "warn":
|
||||
return (...messages) => logger.warn(messages.join(" "));
|
||||
case "debug":
|
||||
return (...messages) => logger.debug(messages.join(" "));
|
||||
case "log":
|
||||
case "info":
|
||||
default:
|
||||
return (...messages) => logger.info(messages.join(" "));
|
||||
}
|
||||
};
|
||||
|
||||
const consoleMethods = ["log", "debug", "info", "warn", "error"];
|
||||
consoleMethods.forEach((method) => {
|
||||
console[method] = getWinstonMethodForConsole(method);
|
||||
});
|
||||
|
||||
const getWinstonMethodForNext = (nextMethod) => {
|
||||
switch (nextMethod) {
|
||||
case "error":
|
||||
return (...messages) => logger.error(messages.join(" "));
|
||||
case "warn":
|
||||
return (...messages) => logger.warn(messages.join(" "));
|
||||
case "trace":
|
||||
return (...messages) => logger.info(messages.join(" "));
|
||||
default:
|
||||
return (...messages) => logger.info(messages.join(" "));
|
||||
}
|
||||
};
|
||||
|
||||
Object.keys(nextLogger.prefixes).forEach((method) => {
|
||||
nextLogger[method] = getWinstonMethodForNext(method);
|
||||
});
|
||||
})();
|
||||
@@ -7,15 +7,12 @@ import Transport from "winston-transport";
|
||||
// of the base functionality and `.exceptions.handle()`.
|
||||
//
|
||||
export class RedisTransport extends Transport {
|
||||
/** @type {Redis} */
|
||||
redis;
|
||||
private redis: Redis | null = null;
|
||||
|
||||
/**
|
||||
* Log the info to the Redis channel
|
||||
* @param {{ message: string; timestamp: string; level: string; }} info
|
||||
* @param {() => void} callback
|
||||
*/
|
||||
log(info, callback) {
|
||||
log(info: { message: string; timestamp: string; level: string }, callback: () => void) {
|
||||
setImmediate(() => {
|
||||
this.emit("logged", info);
|
||||
});
|
||||
@@ -3,6 +3,6 @@
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
|
||||
},
|
||||
"include": ["*.ts", "src", "index.mjs"],
|
||||
"include": ["*.ts", "src"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
63
pnpm-lock.yaml
generated
63
pnpm-lock.yaml
generated
@@ -202,9 +202,6 @@ importers:
|
||||
'@million/lint':
|
||||
specifier: 1.0.14
|
||||
version: 1.0.14(rollup@4.21.3)(webpack-sources@3.2.3)
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.12.0
|
||||
version: 0.12.0(typescript@5.7.3)(zod@3.24.2)
|
||||
'@tabler/icons-react':
|
||||
specifier: ^3.30.0
|
||||
version: 3.30.0(react@19.0.0)
|
||||
@@ -651,15 +648,15 @@ importers:
|
||||
'@homarr/definitions':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../definitions
|
||||
'@homarr/env':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../env
|
||||
'@homarr/log':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../log
|
||||
'@homarr/validation':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../validation
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.12.0
|
||||
version: 0.12.0(typescript@5.7.3)(zod@3.24.2)
|
||||
bcrypt:
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1
|
||||
@@ -802,6 +799,9 @@ importers:
|
||||
|
||||
packages/common:
|
||||
dependencies:
|
||||
'@homarr/env':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../env
|
||||
'@homarr/log':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../log
|
||||
@@ -999,6 +999,9 @@ importers:
|
||||
'@homarr/definitions':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../definitions
|
||||
'@homarr/env':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../env
|
||||
'@homarr/log':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../log
|
||||
@@ -1011,9 +1014,6 @@ importers:
|
||||
'@paralleldrive/cuid2':
|
||||
specifier: ^2.2.2
|
||||
version: 2.2.2
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.12.0
|
||||
version: 0.12.0(typescript@5.7.3)(zod@3.24.2)
|
||||
'@testcontainers/mysql':
|
||||
specifier: ^10.18.0
|
||||
version: 10.18.0
|
||||
@@ -1091,9 +1091,9 @@ importers:
|
||||
'@homarr/common':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../common
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.12.0
|
||||
version: 0.12.0(typescript@5.7.3)(zod@3.24.2)
|
||||
'@homarr/env':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../env
|
||||
dockerode:
|
||||
specifier: ^4.0.4
|
||||
version: 4.0.4
|
||||
@@ -1117,6 +1117,31 @@ importers:
|
||||
specifier: ^5.7.3
|
||||
version: 5.7.3
|
||||
|
||||
packages/env:
|
||||
dependencies:
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.12.0
|
||||
version: 0.12.0(typescript@5.7.3)(zod@3.24.2)
|
||||
zod:
|
||||
specifier: ^3.24.2
|
||||
version: 3.24.2
|
||||
devDependencies:
|
||||
'@homarr/eslint-config':
|
||||
specifier: workspace:^0.2.0
|
||||
version: link:../../tooling/eslint
|
||||
'@homarr/prettier-config':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../../tooling/prettier
|
||||
'@homarr/tsconfig':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../../tooling/typescript
|
||||
eslint:
|
||||
specifier: ^9.20.1
|
||||
version: 9.20.1
|
||||
typescript:
|
||||
specifier: ^5.7.3
|
||||
version: 5.7.3
|
||||
|
||||
packages/form:
|
||||
dependencies:
|
||||
'@homarr/common':
|
||||
@@ -1300,6 +1325,9 @@ importers:
|
||||
|
||||
packages/log:
|
||||
dependencies:
|
||||
'@homarr/env':
|
||||
specifier: workspace:^0.1.0
|
||||
version: link:../env
|
||||
ioredis:
|
||||
specifier: 5.5.0
|
||||
version: 5.5.0
|
||||
@@ -1309,6 +1337,9 @@ importers:
|
||||
winston:
|
||||
specifier: 3.17.0
|
||||
version: 3.17.0
|
||||
zod:
|
||||
specifier: ^3.24.2
|
||||
version: 3.24.2
|
||||
devDependencies:
|
||||
'@homarr/eslint-config':
|
||||
specifier: workspace:^0.2.0
|
||||
@@ -16475,7 +16506,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.26.2
|
||||
index-to-position: 0.1.2
|
||||
type-fest: 4.34.1
|
||||
type-fest: 4.30.2
|
||||
|
||||
parse-ms@3.0.0: {}
|
||||
|
||||
@@ -17039,14 +17070,14 @@ snapshots:
|
||||
dependencies:
|
||||
find-up-simple: 1.0.0
|
||||
read-pkg: 9.0.1
|
||||
type-fest: 4.34.1
|
||||
type-fest: 4.30.2
|
||||
|
||||
read-pkg@9.0.1:
|
||||
dependencies:
|
||||
'@types/normalize-package-data': 2.4.4
|
||||
normalize-package-data: 6.0.2
|
||||
parse-json: 8.1.0
|
||||
type-fest: 4.34.1
|
||||
type-fest: 4.30.2
|
||||
unicorn-magic: 0.1.0
|
||||
|
||||
readable-stream@2.3.8:
|
||||
@@ -18354,7 +18385,7 @@ snapshots:
|
||||
consola: 3.2.3
|
||||
defu: 6.1.4
|
||||
mime: 3.0.0
|
||||
node-fetch-native: 1.6.6
|
||||
node-fetch-native: 1.6.4
|
||||
pathe: 1.1.2
|
||||
|
||||
unicode-emoji-modifier-base@1.0.0: {}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"NODE_ENV",
|
||||
"PORT",
|
||||
"LOCAL_CERTIFICATE_PATH",
|
||||
"LOG_LEVEL",
|
||||
"SECRET_ENCRYPTION_KEY",
|
||||
"SKIP_ENV_VALIDATION"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user