tpaga-logger 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +8 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
createLogger: () => createLogger,
|
|
36
36
|
getLog: () => getLog,
|
|
37
37
|
serializeError: () => serializeError,
|
|
38
|
+
tpagaExpressErrorLogger: () => tpagaExpressErrorLogger,
|
|
38
39
|
withLogger: () => withLogger,
|
|
39
40
|
withTpagaExpressLogger: () => withTpagaExpressLogger
|
|
40
41
|
});
|
|
@@ -47,7 +48,7 @@ var serializeError = (err) => err instanceof Error ? {
|
|
|
47
48
|
type: err.name,
|
|
48
49
|
message: err.message,
|
|
49
50
|
code: err.code,
|
|
50
|
-
|
|
51
|
+
details: err.issues
|
|
51
52
|
} : { type: "UnknownError", message: String(err) };
|
|
52
53
|
var createWideEventBuilder = (base, log) => {
|
|
53
54
|
const ctx = { ...base };
|
|
@@ -85,6 +86,7 @@ var withTpagaExpressLogger = (logger) => (req, res, next) => {
|
|
|
85
86
|
const correlationId = resolveCorrelationId(req.headers);
|
|
86
87
|
const log = logger.startOperation(req.path, { correlationId, method: req.method });
|
|
87
88
|
req.log = log;
|
|
89
|
+
res.log = log;
|
|
88
90
|
res.locals[EXPRESS_LOG_KEY] = log;
|
|
89
91
|
res.on("finish", () => {
|
|
90
92
|
log.emit("info", "request completed", {
|
|
@@ -95,6 +97,10 @@ var withTpagaExpressLogger = (logger) => (req, res, next) => {
|
|
|
95
97
|
});
|
|
96
98
|
next();
|
|
97
99
|
};
|
|
100
|
+
var tpagaExpressErrorLogger = (err, req, _res, next) => {
|
|
101
|
+
req.log.with({ error: serializeError(err) });
|
|
102
|
+
next(err);
|
|
103
|
+
};
|
|
98
104
|
var getLog = (res) => res.locals[EXPRESS_LOG_KEY];
|
|
99
105
|
var withLogger = (logger, operationName, handler) => async (event, ..._rest) => {
|
|
100
106
|
const start = Date.now();
|
|
@@ -137,6 +143,7 @@ var OUTCOMES = [
|
|
|
137
143
|
createLogger,
|
|
138
144
|
getLog,
|
|
139
145
|
serializeError,
|
|
146
|
+
tpagaExpressErrorLogger,
|
|
140
147
|
withLogger,
|
|
141
148
|
withTpagaExpressLogger
|
|
142
149
|
});
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/logger.ts","../src/constants.ts"],"sourcesContent":["export { createLogger, serializeError, withLogger, withTpagaExpressLogger, getLog } from './logger.js';\nexport { LOG_LEVELS, OUTCOMES } from './constants.js';\nexport type {\n Logger,\n LoggerConfig,\n LogLevel,\n Outcome,\n SerializedError,\n TerminalFields,\n WideEventBuilder,\n} from './types.js';\n","import { randomUUID } from 'crypto';\nimport pino from 'pino';\nimport type { NextFunction, Request, Response } from 'express';\nimport type { Logger, LoggerConfig, SerializedError, TerminalFields, WideEventBuilder } from './types.js';\n\ndeclare global {\n namespace Express {\n interface Request {\n log: WideEventBuilder;\n }\n }\n}\n\nexport const serializeError = (err: unknown): SerializedError =>\n err instanceof Error\n ? {\n type: err.name,\n message: err.message,\n code: (err as { code?: string }).code,\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/logger.ts","../src/constants.ts"],"sourcesContent":["export { createLogger, serializeError, withLogger, withTpagaExpressLogger, tpagaExpressErrorLogger, getLog } from './logger.js';\nexport { LOG_LEVELS, OUTCOMES } from './constants.js';\nexport type {\n Logger,\n LoggerConfig,\n LogLevel,\n Outcome,\n SerializedError,\n TerminalFields,\n WideEventBuilder,\n} from './types.js';\n","import { randomUUID } from 'crypto';\nimport pino from 'pino';\nimport type { NextFunction, Request, Response } from 'express';\nimport type { Logger, LoggerConfig, SerializedError, TerminalFields, WideEventBuilder } from './types.js';\n\ndeclare global {\n namespace Express {\n interface Request {\n log: WideEventBuilder;\n }\n interface Response {\n log: WideEventBuilder;\n }\n }\n}\n\nexport const serializeError = (err: unknown): SerializedError =>\n err instanceof Error\n ? {\n type: err.name,\n message: err.message,\n code: (err as { code?: string }).code,\n details: (err as { issues?: unknown }).issues,\n }\n : { type: 'UnknownError', message: String(err) };\n\nconst createWideEventBuilder = (\n base: Record<string, unknown>,\n log: pino.Logger,\n): WideEventBuilder => {\n const ctx = { ...base };\n return {\n with: (fields) => Object.assign(ctx, fields),\n emit: (level, message, terminal: TerminalFields) => log[level]({ ...ctx, ...terminal }, message),\n };\n};\n\nexport const createLogger = (config: LoggerConfig): Logger => {\n const pretty = process.env.LOG_PRETTY === 'true';\n const log = pino({\n level: process.env.LOG_LEVEL ?? 'info',\n base: { service: config.service, environment: config.environment },\n formatters: {\n level: (label) => ({ level: label }),\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n redact: {\n paths: (config.redactKeys as string[]) ?? [],\n censor: '[REDACTED]',\n },\n ...(pretty ? { transport: { target: 'pino-pretty', options: { colorize: true } } } : {}),\n });\n\n return {\n startOperation: (functionName, base = {}) =>\n createWideEventBuilder({ function: functionName, ...base }, log),\n };\n};\n\ntype EventWithHeaders = { headers?: Record<string, string | undefined> };\ntype HandlerWithBuilder<TEvent> = (event: TEvent, builder: WideEventBuilder) => Promise<unknown>;\n\nconst resolveCorrelationId = (headers: Record<string, string | undefined> = {}): string => {\n const h = Object.fromEntries(Object.entries(headers).map(([k, v]) => [k.toLowerCase(), v]));\n return h['x-correlation-id'] ?? h['x-request-id'] ?? randomUUID();\n};\n\nconst EXPRESS_LOG_KEY = 'tpagaLog';\n\nexport const withTpagaExpressLogger = (logger: Logger) =>\n (req: Request, res: Response, next: NextFunction): void => {\n const start = Date.now();\n const correlationId = resolveCorrelationId(req.headers as Record<string, string | undefined>);\n const log = logger.startOperation(req.path, { correlationId, method: req.method });\n\n req.log = log;\n res.log = log;\n res.locals[EXPRESS_LOG_KEY] = log;\n\n res.on('finish', () => {\n log.emit('info', 'request completed', {\n outcome: res.statusCode < 400 ? 'success' : 'error',\n durationMs: Date.now() - start,\n statusCode: res.statusCode,\n });\n });\n\n next();\n };\n\nexport const tpagaExpressErrorLogger = (err: unknown, req: Request, _res: Response, next: NextFunction): void => {\n req.log.with({ error: serializeError(err) });\n next(err);\n};\n\nexport const getLog = (res: Response): WideEventBuilder =>\n res.locals[EXPRESS_LOG_KEY] as WideEventBuilder;\n\nexport const withLogger = <TEvent extends EventWithHeaders>(\n logger: Logger,\n operationName: string,\n handler: HandlerWithBuilder<TEvent>,\n) =>\n async (event: TEvent, ..._rest: unknown[]): Promise<unknown> => {\n const start = Date.now();\n const correlationId = resolveCorrelationId(event.headers);\n const builder = logger.startOperation(operationName, { correlationId });\n\n try {\n const result = await handler(event, builder);\n const statusCode =\n result != null &&\n typeof result === 'object' &&\n 'statusCode' in result &&\n typeof (result as { statusCode: unknown }).statusCode === 'number'\n ? (result as { statusCode: number }).statusCode\n : undefined;\n builder.emit('info', `${operationName} completed`, {\n outcome: 'success',\n durationMs: Date.now() - start,\n ...(statusCode !== undefined ? { statusCode } : {}),\n });\n return result;\n } catch (err) {\n builder.emit('error', `${operationName} failed`, {\n outcome: 'error',\n durationMs: Date.now() - start,\n error: serializeError(err),\n });\n throw err;\n }\n };\n","export const LOG_LEVELS = ['info', 'warn', 'error', 'debug'] as const;\n\nexport const OUTCOMES = [\n 'success',\n 'error',\n 'validation_failed',\n 'not_found',\n 'conflict',\n 'timeout',\n 'skipped',\n] as const;\n"],"mappings":"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","names":["pino"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -14,7 +14,7 @@ type SerializedError = {
|
|
|
14
14
|
type: string;
|
|
15
15
|
message: string;
|
|
16
16
|
code?: string;
|
|
17
|
-
|
|
17
|
+
details?: unknown;
|
|
18
18
|
};
|
|
19
19
|
type TerminalFields = {
|
|
20
20
|
outcome: Outcome | string;
|
|
@@ -35,6 +35,9 @@ declare global {
|
|
|
35
35
|
interface Request {
|
|
36
36
|
log: WideEventBuilder;
|
|
37
37
|
}
|
|
38
|
+
interface Response {
|
|
39
|
+
log: WideEventBuilder;
|
|
40
|
+
}
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
43
|
declare const serializeError: (err: unknown) => SerializedError;
|
|
@@ -44,7 +47,8 @@ type EventWithHeaders = {
|
|
|
44
47
|
};
|
|
45
48
|
type HandlerWithBuilder<TEvent> = (event: TEvent, builder: WideEventBuilder) => Promise<unknown>;
|
|
46
49
|
declare const withTpagaExpressLogger: (logger: Logger) => (req: Request, res: Response, next: NextFunction) => void;
|
|
50
|
+
declare const tpagaExpressErrorLogger: (err: unknown, req: Request, _res: Response, next: NextFunction) => void;
|
|
47
51
|
declare const getLog: (res: Response) => WideEventBuilder;
|
|
48
52
|
declare const withLogger: <TEvent extends EventWithHeaders>(logger: Logger, operationName: string, handler: HandlerWithBuilder<TEvent>) => (event: TEvent, ..._rest: unknown[]) => Promise<unknown>;
|
|
49
53
|
|
|
50
|
-
export { LOG_LEVELS, type LogLevel, type Logger, type LoggerConfig, OUTCOMES, type Outcome, type SerializedError, type TerminalFields, type WideEventBuilder, createLogger, getLog, serializeError, withLogger, withTpagaExpressLogger };
|
|
54
|
+
export { LOG_LEVELS, type LogLevel, type Logger, type LoggerConfig, OUTCOMES, type Outcome, type SerializedError, type TerminalFields, type WideEventBuilder, createLogger, getLog, serializeError, tpagaExpressErrorLogger, withLogger, withTpagaExpressLogger };
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ type SerializedError = {
|
|
|
14
14
|
type: string;
|
|
15
15
|
message: string;
|
|
16
16
|
code?: string;
|
|
17
|
-
|
|
17
|
+
details?: unknown;
|
|
18
18
|
};
|
|
19
19
|
type TerminalFields = {
|
|
20
20
|
outcome: Outcome | string;
|
|
@@ -35,6 +35,9 @@ declare global {
|
|
|
35
35
|
interface Request {
|
|
36
36
|
log: WideEventBuilder;
|
|
37
37
|
}
|
|
38
|
+
interface Response {
|
|
39
|
+
log: WideEventBuilder;
|
|
40
|
+
}
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
43
|
declare const serializeError: (err: unknown) => SerializedError;
|
|
@@ -44,7 +47,8 @@ type EventWithHeaders = {
|
|
|
44
47
|
};
|
|
45
48
|
type HandlerWithBuilder<TEvent> = (event: TEvent, builder: WideEventBuilder) => Promise<unknown>;
|
|
46
49
|
declare const withTpagaExpressLogger: (logger: Logger) => (req: Request, res: Response, next: NextFunction) => void;
|
|
50
|
+
declare const tpagaExpressErrorLogger: (err: unknown, req: Request, _res: Response, next: NextFunction) => void;
|
|
47
51
|
declare const getLog: (res: Response) => WideEventBuilder;
|
|
48
52
|
declare const withLogger: <TEvent extends EventWithHeaders>(logger: Logger, operationName: string, handler: HandlerWithBuilder<TEvent>) => (event: TEvent, ..._rest: unknown[]) => Promise<unknown>;
|
|
49
53
|
|
|
50
|
-
export { LOG_LEVELS, type LogLevel, type Logger, type LoggerConfig, OUTCOMES, type Outcome, type SerializedError, type TerminalFields, type WideEventBuilder, createLogger, getLog, serializeError, withLogger, withTpagaExpressLogger };
|
|
54
|
+
export { LOG_LEVELS, type LogLevel, type Logger, type LoggerConfig, OUTCOMES, type Outcome, type SerializedError, type TerminalFields, type WideEventBuilder, createLogger, getLog, serializeError, tpagaExpressErrorLogger, withLogger, withTpagaExpressLogger };
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var serializeError = (err) => err instanceof Error ? {
|
|
|
5
5
|
type: err.name,
|
|
6
6
|
message: err.message,
|
|
7
7
|
code: err.code,
|
|
8
|
-
|
|
8
|
+
details: err.issues
|
|
9
9
|
} : { type: "UnknownError", message: String(err) };
|
|
10
10
|
var createWideEventBuilder = (base, log) => {
|
|
11
11
|
const ctx = { ...base };
|
|
@@ -43,6 +43,7 @@ var withTpagaExpressLogger = (logger) => (req, res, next) => {
|
|
|
43
43
|
const correlationId = resolveCorrelationId(req.headers);
|
|
44
44
|
const log = logger.startOperation(req.path, { correlationId, method: req.method });
|
|
45
45
|
req.log = log;
|
|
46
|
+
res.log = log;
|
|
46
47
|
res.locals[EXPRESS_LOG_KEY] = log;
|
|
47
48
|
res.on("finish", () => {
|
|
48
49
|
log.emit("info", "request completed", {
|
|
@@ -53,6 +54,10 @@ var withTpagaExpressLogger = (logger) => (req, res, next) => {
|
|
|
53
54
|
});
|
|
54
55
|
next();
|
|
55
56
|
};
|
|
57
|
+
var tpagaExpressErrorLogger = (err, req, _res, next) => {
|
|
58
|
+
req.log.with({ error: serializeError(err) });
|
|
59
|
+
next(err);
|
|
60
|
+
};
|
|
56
61
|
var getLog = (res) => res.locals[EXPRESS_LOG_KEY];
|
|
57
62
|
var withLogger = (logger, operationName, handler) => async (event, ..._rest) => {
|
|
58
63
|
const start = Date.now();
|
|
@@ -94,6 +99,7 @@ export {
|
|
|
94
99
|
createLogger,
|
|
95
100
|
getLog,
|
|
96
101
|
serializeError,
|
|
102
|
+
tpagaExpressErrorLogger,
|
|
97
103
|
withLogger,
|
|
98
104
|
withTpagaExpressLogger
|
|
99
105
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logger.ts","../src/constants.ts"],"sourcesContent":["import { randomUUID } from 'crypto';\nimport pino from 'pino';\nimport type { NextFunction, Request, Response } from 'express';\nimport type { Logger, LoggerConfig, SerializedError, TerminalFields, WideEventBuilder } from './types.js';\n\ndeclare global {\n namespace Express {\n interface Request {\n log: WideEventBuilder;\n }\n }\n}\n\nexport const serializeError = (err: unknown): SerializedError =>\n err instanceof Error\n ? {\n type: err.name,\n message: err.message,\n code: (err as { code?: string }).code,\n
|
|
1
|
+
{"version":3,"sources":["../src/logger.ts","../src/constants.ts"],"sourcesContent":["import { randomUUID } from 'crypto';\nimport pino from 'pino';\nimport type { NextFunction, Request, Response } from 'express';\nimport type { Logger, LoggerConfig, SerializedError, TerminalFields, WideEventBuilder } from './types.js';\n\ndeclare global {\n namespace Express {\n interface Request {\n log: WideEventBuilder;\n }\n interface Response {\n log: WideEventBuilder;\n }\n }\n}\n\nexport const serializeError = (err: unknown): SerializedError =>\n err instanceof Error\n ? {\n type: err.name,\n message: err.message,\n code: (err as { code?: string }).code,\n details: (err as { issues?: unknown }).issues,\n }\n : { type: 'UnknownError', message: String(err) };\n\nconst createWideEventBuilder = (\n base: Record<string, unknown>,\n log: pino.Logger,\n): WideEventBuilder => {\n const ctx = { ...base };\n return {\n with: (fields) => Object.assign(ctx, fields),\n emit: (level, message, terminal: TerminalFields) => log[level]({ ...ctx, ...terminal }, message),\n };\n};\n\nexport const createLogger = (config: LoggerConfig): Logger => {\n const pretty = process.env.LOG_PRETTY === 'true';\n const log = pino({\n level: process.env.LOG_LEVEL ?? 'info',\n base: { service: config.service, environment: config.environment },\n formatters: {\n level: (label) => ({ level: label }),\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n redact: {\n paths: (config.redactKeys as string[]) ?? [],\n censor: '[REDACTED]',\n },\n ...(pretty ? { transport: { target: 'pino-pretty', options: { colorize: true } } } : {}),\n });\n\n return {\n startOperation: (functionName, base = {}) =>\n createWideEventBuilder({ function: functionName, ...base }, log),\n };\n};\n\ntype EventWithHeaders = { headers?: Record<string, string | undefined> };\ntype HandlerWithBuilder<TEvent> = (event: TEvent, builder: WideEventBuilder) => Promise<unknown>;\n\nconst resolveCorrelationId = (headers: Record<string, string | undefined> = {}): string => {\n const h = Object.fromEntries(Object.entries(headers).map(([k, v]) => [k.toLowerCase(), v]));\n return h['x-correlation-id'] ?? h['x-request-id'] ?? randomUUID();\n};\n\nconst EXPRESS_LOG_KEY = 'tpagaLog';\n\nexport const withTpagaExpressLogger = (logger: Logger) =>\n (req: Request, res: Response, next: NextFunction): void => {\n const start = Date.now();\n const correlationId = resolveCorrelationId(req.headers as Record<string, string | undefined>);\n const log = logger.startOperation(req.path, { correlationId, method: req.method });\n\n req.log = log;\n res.log = log;\n res.locals[EXPRESS_LOG_KEY] = log;\n\n res.on('finish', () => {\n log.emit('info', 'request completed', {\n outcome: res.statusCode < 400 ? 'success' : 'error',\n durationMs: Date.now() - start,\n statusCode: res.statusCode,\n });\n });\n\n next();\n };\n\nexport const tpagaExpressErrorLogger = (err: unknown, req: Request, _res: Response, next: NextFunction): void => {\n req.log.with({ error: serializeError(err) });\n next(err);\n};\n\nexport const getLog = (res: Response): WideEventBuilder =>\n res.locals[EXPRESS_LOG_KEY] as WideEventBuilder;\n\nexport const withLogger = <TEvent extends EventWithHeaders>(\n logger: Logger,\n operationName: string,\n handler: HandlerWithBuilder<TEvent>,\n) =>\n async (event: TEvent, ..._rest: unknown[]): Promise<unknown> => {\n const start = Date.now();\n const correlationId = resolveCorrelationId(event.headers);\n const builder = logger.startOperation(operationName, { correlationId });\n\n try {\n const result = await handler(event, builder);\n const statusCode =\n result != null &&\n typeof result === 'object' &&\n 'statusCode' in result &&\n typeof (result as { statusCode: unknown }).statusCode === 'number'\n ? (result as { statusCode: number }).statusCode\n : undefined;\n builder.emit('info', `${operationName} completed`, {\n outcome: 'success',\n durationMs: Date.now() - start,\n ...(statusCode !== undefined ? { statusCode } : {}),\n });\n return result;\n } catch (err) {\n builder.emit('error', `${operationName} failed`, {\n outcome: 'error',\n durationMs: Date.now() - start,\n error: serializeError(err),\n });\n throw err;\n }\n };\n","export const LOG_LEVELS = ['info', 'warn', 'error', 'debug'] as const;\n\nexport const OUTCOMES = [\n 'success',\n 'error',\n 'validation_failed',\n 'not_found',\n 'conflict',\n 'timeout',\n 'skipped',\n] as const;\n"],"mappings":"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","names":[]}
|