diff --git a/.gitignore b/.gitignore index 18f2b36..6f1bc5c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ coverage dist node_modules +.eslintcache diff --git a/README.md b/README.md index fa4776b..45fe84e 100644 --- a/README.md +++ b/README.md @@ -12,21 +12,18 @@ Here is an example server with log tracing enabled. ```js import { - fetchGcpProjectId, getHttpTraceHeader, middleware, - logger as BNLogger + logger as buildLogger } from "@bonniernews/logger"; import express from "express"; -const logger = BNLogger(); +const logger = buildLogger(); const app = express(); -app.use(middleware); - -// Fetches the project ID from the GCP metadata server in the background on startup. -// This is only necessary if you don't set the `GCP_PROJECT` environment variable. -fetchGcpProjectId(); +// This middleware will create a request context and +// automatically decorate all logs with tracing data: +app.use(middleware()); app.get("/", async (req, res) => { logger.info("Hello, world!"); @@ -39,6 +36,12 @@ app.get("/", async (req, res) => { }); ``` +The `middleware` should be put as early as possible, since only logs after this middleware will get the tracing data. The middleware will lookup the active project ID from GCP. Alternatively, you can set the `GCP_PROJECT` environment variable for this purpose. + +Use the `getHttpTraceHeader` function to pass tracing headers to downstream services. + +If you want to decorate logs with custom data, use the exported `decorateLogs` function. In order to use this, the middleware needs to be installed first. + ### Logger Interface #### Options diff --git a/index.ts b/index.ts index 2e3c3a8..a5a18a4 100644 --- a/index.ts +++ b/index.ts @@ -1,5 +1,4 @@ -export { fetchGcpProjectId } from "./lib/gcp"; export { getHttpTraceHeader } from "./lib/http"; -export { getLoggingTraceData, logger } from "./lib/logging"; +export { decorateLogs, logger } from "./lib/logging"; export { middleware } from "./lib/middleware"; export { createTraceparent } from "./lib/traceparent"; diff --git a/lib/gcp.ts b/lib/gcp.ts index 8293b27..77c78fd 100644 --- a/lib/gcp.ts +++ b/lib/gcp.ts @@ -1,26 +1,17 @@ import gcpMetaData from "gcp-metadata"; -let gcpProjectId: string | undefined = undefined; - -export function getGcpProjectId() { - return process.env.GCP_PROJECT || gcpProjectId; -} - /** * Fetches the Google Cloud Platform (GCP) project ID from the GCP metadata server. * - * You only need to call this function if you're not setting the `GCP_PROJECT` environment variable. + * You can alternatively set the `GCP_PROJECT` environment variable, which takes precedence. */ -export async function fetchGcpProjectId() { +export async function getGcpProjectId(): Promise { + if (process.env.GCP_PROJECT) { + return process.env.GCP_PROJECT; + } + const isAvailable = await gcpMetaData.isAvailable(); if (!isAvailable) return; - gcpProjectId = await gcpMetaData.project("project-id"); -} - -/** - * Resets the GCP project ID, for testing. - */ -export function reset() { - gcpProjectId = undefined; + return await gcpMetaData.project("project-id"); } diff --git a/lib/http.ts b/lib/http.ts index 8d481f2..9c4285f 100644 --- a/lib/http.ts +++ b/lib/http.ts @@ -1,7 +1,6 @@ import { getStore } from "./middleware"; export function getHttpTraceHeader() { - const { traceparent } = getStore(); - if (traceparent) return { traceparent }; - return {}; + const { traceparent } = getStore() || {}; + return traceparent ? { traceparent } : {}; } diff --git a/lib/logging.ts b/lib/logging.ts index 53e4aaa..0809e9c 100644 --- a/lib/logging.ts +++ b/lib/logging.ts @@ -1,26 +1,23 @@ import pino, { DestinationStream, LoggerOptions } from "pino"; -import { getGcpProjectId } from "./gcp"; import { getStore } from "./middleware"; -import { getTraceFromTraceparent } from "./traceparent"; -export function getLoggingTraceData() { - const { traceparent, ...rest } = getStore(); - if (!traceparent) return rest; - - const trace = getTraceFromTraceparent(traceparent); - if (!trace) return rest; +function getLoggingData() { + const store = getStore(); + return store ? store.logFields : {}; +} - const logData = { traceId: trace.traceId, spanId: trace.parentId, ...rest }; +/** + * Add any additional log data to the request context. To use this feature, you must enable the + * request storage by initializing the built-in middleware. + */ +export function decorateLogs(obj: Record) { + const store = getStore(); - const gcpProjectId = getGcpProjectId(); - if (!gcpProjectId) return logData; + if (!store) throw new Error("@bonniernews/logger middleware has not been initialized"); - return { - ...logData, - "logging.googleapis.com/trace": `projects/${gcpProjectId}/traces/${trace.traceId}`, - "logging.googleapis.com/spanId": trace.parentId, - "logging.googleapis.com/trace_sampled": trace.isSampled, - }; + for (const key in obj) { + store.logFields[key] = obj[key]; + } } type BnLoggerOptions = Omit & { @@ -68,7 +65,7 @@ export function logger(options: BnLoggerOptions = {}, stream?: DestinationStream ...(formatLog && { log: formatLog }), }, transport, - mixin: (...args) => ({ ...getLoggingTraceData(), ...mixin?.(...args) }), + mixin: (...args) => ({ ...getLoggingData(), ...mixin?.(...args) }), ...rest, }, stream diff --git a/lib/middleware.ts b/lib/middleware.ts index 5073a46..cb05241 100644 --- a/lib/middleware.ts +++ b/lib/middleware.ts @@ -1,23 +1,55 @@ import type { RequestHandler } from "express"; import { AsyncLocalStorage } from "node:async_hooks"; -import { createTraceparent } from "./traceparent"; +import { getGcpProjectId } from "./gcp"; +import { getTraceFromTraceparent, createTraceparent } from "./traceparent"; + +type LogFields = { + traceId?: string; + "logging.googleapis.com/trace"?: string; + "logging.googleapis.com/spanId"?: string; + "logging.googleapis.com/trace_sampled"?: boolean; + [key: string]: unknown; +}; type Store = { traceparent?: string; - clientServiceAccount?: string; - [key: string]: unknown; + logFields: LogFields; }; const storage = new AsyncLocalStorage(); -export const middleware: RequestHandler = (req, _res, next) => { - const traceparent = req.header("traceparent") || createTraceparent(); +export type Middleware = () => RequestHandler; + +export const middleware: Middleware = () => { + let initialized = false; + let projectId: string | undefined; + + return async (req, _res, next) => { + if (!initialized) { + initialized = true; + projectId = await getGcpProjectId(); + } + + const traceparent = req.header("traceparent") || createTraceparent(); + const trace = getTraceFromTraceparent(traceparent); + const logFields: LogFields = {}; + + if (trace) { + logFields.traceId = trace.traceId; + + if (projectId) { + logFields["logging.googleapis.com/trace"] = `projects/${projectId}/traces/${trace.traceId}`; + logFields["logging.googleapis.com/spanId"] = trace.parentId; + logFields["logging.googleapis.com/trace_sampled"] = trace.isSampled; + } + } - storage.run({ traceparent }, () => { - next(); - }); + storage.run({ traceparent, logFields }, () => { + next(); + }); + }; }; -export function getStore() { - return storage.getStore() || {}; +export function getStore(): Store | undefined { + return storage.getStore(); } diff --git a/package-lock.json b/package-lock.json index ff83337..648a199 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "gcp-metadata": "^6.1.0", "pino": "^9.5.0", - "pino-pretty": "^11.3.0" + "pino-pretty": "^12.1.0" }, "devDependencies": { "@bonniernews/tsconfig": "^0.0.2", @@ -19,19 +19,22 @@ "@types/eslint__js": "^8.42.3", "@types/express": "^5.0.0", "@types/mocha": "^10.0.8", - "@types/node": "^22.7.3", + "@types/node": "^22.9.0", "@types/sinon": "^17.0.3", "c8": "^10.1.2", "chai": "^5.1.1", - "eslint": "^9.13.0", + "eslint": "^9.14.0", "express": "^4.21.0", - "mocha": "^10.7.3", + "mocha": "^10.8.2", "mocha-cakes-2": "^3.3.0", "prettier": "^3.3.3", "sinon": "^19.0.2", "tsx": "^4.19.1", "typescript": "^5.6.3", - "typescript-eslint": "^8.12.1" + "typescript-eslint": "^8.13.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/@bcoe/v8-coverage": { @@ -551,9 +554,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, "license": "MIT", "engines": { @@ -1002,9 +1005,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.8.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.2.tgz", - "integrity": "sha512-NzaRNFV+FZkvK/KLCsNdTvID0SThyrs5SHB6tsD/lajr22FGC73N2QeDPM2wHtVde8mgcXuSsHQkH5cX1pbPLw==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1066,17 +1069,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.1.tgz", - "integrity": "sha512-gNg/inLRcPoBsKKIe4Vv38SVSOhk4BKWNO0T56sVff33gRqtTpOsrhHtiOKD1lmIOmCtZMPaW2x/h2FlM+sCEg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", + "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.12.1", - "@typescript-eslint/type-utils": "8.12.1", - "@typescript-eslint/utils": "8.12.1", - "@typescript-eslint/visitor-keys": "8.12.1", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/type-utils": "8.13.0", + "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1100,16 +1103,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.1.tgz", - "integrity": "sha512-I/I9Bg7qFa8rOgBnUUHIWTgzbB5wVkSLX+04xGUzTcJUtdq/I2uHWR9mbW6qUYJG/UmkuDcTax5JHvoEWOAHOQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", + "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.12.1", - "@typescript-eslint/types": "8.12.1", - "@typescript-eslint/typescript-estree": "8.12.1", - "@typescript-eslint/visitor-keys": "8.12.1", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4" }, "engines": { @@ -1129,14 +1132,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.1.tgz", - "integrity": "sha512-bma6sD1iViTt+y9MAwDlBdPTMCqoH/BNdcQk4rKhIZWv3eM0xHmzeSrPJA663PAqFqfpOmtdugycpr0E1mZDVA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.1", - "@typescript-eslint/visitor-keys": "8.12.1" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1147,14 +1150,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.1.tgz", - "integrity": "sha512-zJzrvbDVjIzVKV2TGHcjembEhws8RWXJhmqfO9hS2gRXBN0gDwGhRPEdJ6AZglzfJ+YA1q09EWpSLSXjBJpIMQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", + "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.12.1", - "@typescript-eslint/utils": "8.12.1", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/utils": "8.13.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1172,9 +1175,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.1.tgz", - "integrity": "sha512-anMS4es5lxBe4UVcDXOkcDb3csnm5BvaNIbOFfvy/pJEohorsggdVB8MFbl5EZiEuBnZZ0ei1z7W5b6FdFiV1Q==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", "dev": true, "license": "MIT", "engines": { @@ -1186,14 +1189,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.1.tgz", - "integrity": "sha512-k/o9khHOckPeDXilFTIPsP9iAYhhdMh3OsOL3i2072PNpFqhqzRHx472/0DeC8H/WZee3bZG0z2ddGRSPgeOKw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.12.1", - "@typescript-eslint/visitor-keys": "8.12.1", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1241,16 +1244,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.1.tgz", - "integrity": "sha512-sDv9yFHrhKe1WN8EYuzfhKCh/sFRupe9P+m/lZ5YgVvPoCUGHNN50IO4llSu7JAbftUM/QcCh+GeCortXPrBYQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", + "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.12.1", - "@typescript-eslint/types": "8.12.1", - "@typescript-eslint/typescript-estree": "8.12.1" + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1264,13 +1267,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.1.tgz", - "integrity": "sha512-2RwdwnNGuOQKdGjuhujQHUqBZhEuodg2sLVPvOfWktvA9sOXOVqARjOyHSyhN2LiJGKxV6c8oOcmOtRcAnEeFw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.1", + "@typescript-eslint/types": "8.13.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2119,22 +2122,22 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -2142,9 +2145,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2180,9 +2183,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2197,9 +2200,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2209,16 +2212,30 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3440,9 +3457,9 @@ } }, "node_modules/mocha": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", - "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", "dev": true, "license": "MIT", "dependencies": { @@ -3868,9 +3885,9 @@ } }, "node_modules/pino-pretty": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.3.0.tgz", - "integrity": "sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-12.1.0.tgz", + "integrity": "sha512-Z7JdCPqggoRyo0saJyCe1BN8At5qE+ZBElNbyx+znCaCVN+ohOqlWb+/WSYnamzfi2e6P6pXq/3H66KwFQHXWg==", "license": "MIT", "dependencies": { "colorette": "^2.0.7", @@ -4625,9 +4642,9 @@ "license": "MIT" }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", "dev": true, "license": "MIT", "engines": { @@ -4709,15 +4726,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.12.1.tgz", - "integrity": "sha512-SsKedZnq4TStkrpqnk+OqTnmkC9CkYBRNKjQ965CLpFruGcRkPF5UhKxbcbF6c/m2r6YAgKw/UtQxdlMjh3mug==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.13.0.tgz", + "integrity": "sha512-vIMpDRJrQd70au2G8w34mPps0ezFSPMEX4pXkTzUkrNbRX+36ais2ksGWN0esZL+ZMaFJEneOBHzCgSqle7DHw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.12.1", - "@typescript-eslint/parser": "8.12.1", - "@typescript-eslint/utils": "8.12.1" + "@typescript-eslint/eslint-plugin": "8.13.0", + "@typescript-eslint/parser": "8.13.0", + "@typescript-eslint/utils": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/package.json b/package.json index 0b157a8..45836d2 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,15 @@ ], "repository": { "type": "git", - "url": "github:BonnierNews/logger" + "url": "git+https://github.com/BonnierNews/logger.git" }, + "bugs": { + "url": "https://github.com/BonnierNews/logger/issues" + }, + "homepage": "https://github.com/BonnierNews/logger#readme", "scripts": { "build": "tsc", - "lint": "eslint .", + "lint": "eslint . --cache", "format": "prettier --write . && eslint --fix .", "typecheck": "tsc --noEmit", "test": "mocha --exit --reporter ${REPORTER:-spec}", @@ -22,12 +26,12 @@ "local-coverage": "c8 --reporter html npm test && c8 check-coverage || open ./coverage/index.html", "prepublishOnly": "npm run build" }, - "author": "", + "author": "Bonnier News", "license": "MIT", "dependencies": { "gcp-metadata": "^6.1.0", "pino": "^9.5.0", - "pino-pretty": "^11.3.0" + "pino-pretty": "^12.1.0" }, "devDependencies": { "@bonniernews/tsconfig": "^0.0.2", @@ -35,18 +39,21 @@ "@types/eslint__js": "^8.42.3", "@types/express": "^5.0.0", "@types/mocha": "^10.0.8", - "@types/node": "^22.7.3", + "@types/node": "^22.9.0", "@types/sinon": "^17.0.3", "c8": "^10.1.2", "chai": "^5.1.1", - "eslint": "^9.13.0", + "eslint": "^9.14.0", "express": "^4.21.0", - "mocha": "^10.7.3", + "mocha": "^10.8.2", "mocha-cakes-2": "^3.3.0", "prettier": "^3.3.3", "sinon": "^19.0.2", "tsx": "^4.19.1", "typescript": "^5.6.3", - "typescript-eslint": "^8.12.1" + "typescript-eslint": "^8.13.0" + }, + "engines": { + "node": ">=18" } }