Skip to content

Commit eaf45b8

Browse files
committed
feat(auth): implement JWT and OTP utilities for authentication; add password hashing functions; enhance observability with metrics and logging middleware
1 parent 9790600 commit eaf45b8

File tree

8 files changed

+57
-11
lines changed

8 files changed

+57
-11
lines changed

packages/create-tbk-app/src/constants/dependencies.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ export const CORE_DEPENDENCIES = {
1515
validator: '^13.12.0',
1616
'express-async-handler': '^1.2.0',
1717
formidable: '^3.5.4',
18+
// Logger dependencies (logger plugin is always included)
19+
pino: '^9.1.0',
20+
'pino-http': '^10.1.0',
21+
'pino-pretty': '^11.1.0',
22+
// Basic observability dependencies (requestId middleware)
23+
nanoid: '^3.3.7',
1824
};
1925

2026
export const CORE_DEV_DEPENDENCIES = {
@@ -71,12 +77,9 @@ export const FEATURE_DEPENDENCIES = {
7177
},
7278
observabilityFull: {
7379
dependencies: {
74-
pino: '^9.1.0',
75-
'pino-http': '^10.1.0',
76-
'pino-pretty': '^11.1.0',
80+
// pino, pino-http, pino-pretty, and nanoid are now in CORE_DEPENDENCIES
7781
'prom-client': '^15.1.3',
7882
morgan: '^1.10.0',
79-
nanoid: '^3.3.7',
8083
},
8184
devDependencies: {
8285
'@types/morgan': '^1.9.4',

packages/create-tbk-app/templates/base/src/plugins/logger/index.ts.hbs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pino from 'pino';
22
import pinoHttp from 'pino-http';
3+
import type { Request } from 'express';
34
import type { RequestExtended } from '@/types';
45
import { ServerResponse as ResponseHTTP } from 'node:http';
56
import type { ToolkitPlugin, PluginFactory } from '@/plugins/types';
@@ -60,7 +61,7 @@ function createLogger(options: LoggerOptions = {}) {
6061
}
6162
: undefined,
6263
formatters: {
63-
level: (label) => {
64+
level: (label: string) => {
6465
return { level: label.toUpperCase() };
6566
},
6667
},
@@ -82,7 +83,7 @@ export const logger = createLogger();
8283
*/
8384
export const httpLogger = pinoHttp({
8485
logger,
85-
customLogLevel: (_req, res, err) => {
86+
customLogLevel: (_req: Request, res: ResponseHTTP, err?: Error) => {
8687
if (res.statusCode >= 500 || err) {
8788
return 'error';
8889
}
@@ -91,10 +92,10 @@ export const httpLogger = pinoHttp({
9192
}
9293
return 'info';
9394
},
94-
customSuccessMessage: (req, res) => {
95+
customSuccessMessage: (req: Request, res: ResponseHTTP) => {
9596
return `${req.method} ${req.url} ${res.statusCode}`;
9697
},
97-
customErrorMessage: (req, res, err) => {
98+
customErrorMessage: (req: Request, res: ResponseHTTP, err: Error) => {
9899
return `${req.method} ${req.url} ${res.statusCode} - ${err.message}`;
99100
},
100101
customAttributeKeys: {
@@ -104,7 +105,7 @@ export const httpLogger = pinoHttp({
104105
responseTime: 'duration',
105106
},
106107
serializers: {
107-
req: (req) => {
108+
req: (req: Request) => {
108109
const extended = req as RequestExtended;
109110
return {
110111
id: extended.id,
@@ -116,8 +117,8 @@ export const httpLogger = pinoHttp({
116117
'user-agent': req.headers['user-agent'],
117118
'x-request-id': req.headers['x-request-id'],
118119
},
119-
remoteAddress: req.remoteAddress,
120-
remotePort: req.remotePort,
120+
remoteAddress: req.socket?.remoteAddress,
121+
remotePort: req.socket?.remotePort,
121122
};
122123
},
123124
res: (res: unknown) => ({

packages/create-tbk-app/templates/base/src/plugins/observability/metrics.ts renamed to packages/create-tbk-app/templates/base/src/plugins/observability/metrics.ts.hbs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{{#if OBSERVABILITY_FULL}}
12
import {
23
Registry,
34
Counter,
@@ -95,3 +96,44 @@ export class MetricsCollector {
9596
export const metricsCollector = new MetricsCollector();
9697

9798
export default metricsCollector;
99+
{{else}}
100+
// Stub implementation for basic observability (no metrics collection)
101+
export class MetricsCollector {
102+
public readonly register = {
103+
contentType: 'text/plain',
104+
};
105+
106+
recordRequest(
107+
_method: string,
108+
_route: string,
109+
_statusCode: number,
110+
_duration: number,
111+
): void {
112+
// No-op
113+
}
114+
115+
startRequest(_method: string, _route: string): void {
116+
// No-op
117+
}
118+
119+
endRequest(_method: string, _route: string): void {
120+
// No-op
121+
}
122+
123+
incrementCacheHits(_key: string): void {
124+
// No-op
125+
}
126+
127+
incrementCacheMisses(_key: string): void {
128+
// No-op
129+
}
130+
131+
async getMetrics(): Promise<string> {
132+
return '';
133+
}
134+
}
135+
136+
export const metricsCollector = new MetricsCollector();
137+
138+
export default metricsCollector;
139+
{{/if}}

0 commit comments

Comments
 (0)