@devmoods/express-extras 0.19.0 → 0.20.1
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/README.md +5 -5
- package/dist/auth.d.ts +8 -0
- package/dist/auth.js +20 -4
- package/dist/context.d.ts +1 -9
- package/dist/context.js +15 -17
- package/dist/email.js +1 -1
- package/dist/errors.js +1 -2
- package/dist/listen.js +1 -1
- package/dist/logger.d.ts +6 -18
- package/dist/logger.js +39 -20
- package/dist/middleware.js +4 -2
- package/dist/slack.js +1 -1
- package/package.json +13 -16
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ app.get(
|
|
|
77
77
|
route(async () => {
|
|
78
78
|
const posts = await postgres.query('SELECT * FROM posts LIMIT 10');
|
|
79
79
|
return posts;
|
|
80
|
-
})
|
|
80
|
+
}),
|
|
81
81
|
);
|
|
82
82
|
|
|
83
83
|
app.post(
|
|
@@ -100,13 +100,13 @@ app.post(
|
|
|
100
100
|
const post = { title, content };
|
|
101
101
|
|
|
102
102
|
await postgres.insert(
|
|
103
|
-
sql`INSERT INTO posts (title, content) VALUES (${title}, ${content})
|
|
103
|
+
sql`INSERT INTO posts (title, content) VALUES (${title}, ${content})`,
|
|
104
104
|
);
|
|
105
105
|
|
|
106
106
|
slack.postMessage(`New post created with title ${title}`);
|
|
107
107
|
|
|
108
108
|
return [201, post];
|
|
109
|
-
})
|
|
109
|
+
}),
|
|
110
110
|
);
|
|
111
111
|
|
|
112
112
|
app.use((req, res, next) => {
|
|
@@ -118,7 +118,7 @@ app.use(
|
|
|
118
118
|
shouldHandleError(error) {
|
|
119
119
|
return true;
|
|
120
120
|
},
|
|
121
|
-
})
|
|
121
|
+
}),
|
|
122
122
|
);
|
|
123
123
|
|
|
124
124
|
app.use(
|
|
@@ -130,7 +130,7 @@ app.use(
|
|
|
130
130
|
logger.error(error);
|
|
131
131
|
}
|
|
132
132
|
},
|
|
133
|
-
})
|
|
133
|
+
}),
|
|
134
134
|
);
|
|
135
135
|
|
|
136
136
|
listen(server, {
|
package/dist/auth.d.ts
CHANGED
|
@@ -24,6 +24,14 @@ export declare function createAuth<UserModel extends Record<string, any>>({ getU
|
|
|
24
24
|
* of `req`.
|
|
25
25
|
*/
|
|
26
26
|
export declare function parseAuthorizationHeader(req: Request): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Extract an access token from the `Request`-object.
|
|
29
|
+
*
|
|
30
|
+
* Checks multiple places and uses the first match. Priority:
|
|
31
|
+
* 1. Request header `Authorization: `
|
|
32
|
+
* 2. Cookie named `access_token`
|
|
33
|
+
*/
|
|
34
|
+
export declare function extractAccessTokenFromRequest(req: Request): string | null;
|
|
27
35
|
export declare function setAccessTokenCookie(res: Response, token: string | null): void;
|
|
28
36
|
export declare function checkIfPasswordsMatch(realPassword: string, attemptedPassword: string): Promise<boolean>;
|
|
29
37
|
export declare function hashPassword(password: string): Promise<string>;
|
package/dist/auth.js
CHANGED
|
@@ -16,6 +16,7 @@ export function createAuthToken(payload, secret = process.env.APP_JWT_SECRET) {
|
|
|
16
16
|
}
|
|
17
17
|
export function createAuth({ getUserByToken, methods: { emailAndPassword }, filterUser = (x) => x, redis, tokenExpiry = TOKEN_EXPIRES_IN, onResetRequested, onPasswordChanged, }) {
|
|
18
18
|
const useCurrentUser = () => useContext('currentUser');
|
|
19
|
+
const setCurrentUser = (user) => setContext('currentUser', user);
|
|
19
20
|
const createRouter = () => {
|
|
20
21
|
const router = Router();
|
|
21
22
|
router.get('/me', middleware(), route(() => {
|
|
@@ -36,6 +37,8 @@ export function createAuth({ getUserByToken, methods: { emailAndPassword }, filt
|
|
|
36
37
|
const token = createAuthToken(filterUser(user));
|
|
37
38
|
await redis.set(token, '1', { EX: tokenExpiry });
|
|
38
39
|
setAccessTokenCookie(res, token);
|
|
40
|
+
setCurrentUser(user);
|
|
41
|
+
logger.info('access token created');
|
|
39
42
|
return [201, { token }];
|
|
40
43
|
}
|
|
41
44
|
catch (error) {
|
|
@@ -75,12 +78,14 @@ export function createAuth({ getUserByToken, methods: { emailAndPassword }, filt
|
|
|
75
78
|
const { token } = req.params;
|
|
76
79
|
const email = await redis.get(token);
|
|
77
80
|
if (!email) {
|
|
81
|
+
logger.info('invalid reset token', { token });
|
|
78
82
|
throw BadRequest('invalid reset token');
|
|
79
83
|
}
|
|
80
84
|
const user = await emailAndPassword(email, skipPasswordCheck);
|
|
85
|
+
setCurrentUser(user);
|
|
81
86
|
await onPasswordChanged?.(user, await hashPassword(password));
|
|
82
87
|
await redis.del(token);
|
|
83
|
-
logger.info('user changed password'
|
|
88
|
+
logger.info('user changed password');
|
|
84
89
|
return 200;
|
|
85
90
|
}));
|
|
86
91
|
}
|
|
@@ -88,6 +93,7 @@ export function createAuth({ getUserByToken, methods: { emailAndPassword }, filt
|
|
|
88
93
|
const token = req.params.token;
|
|
89
94
|
const email = await redis.get(token);
|
|
90
95
|
if (!email) {
|
|
96
|
+
logger.info('invalid reset token', { token });
|
|
91
97
|
throw NotFound();
|
|
92
98
|
}
|
|
93
99
|
return 200;
|
|
@@ -110,6 +116,7 @@ export function createAuth({ getUserByToken, methods: { emailAndPassword }, filt
|
|
|
110
116
|
EX: TEMP_TOKEN_EXIRES_IN,
|
|
111
117
|
});
|
|
112
118
|
await onResetRequested?.(user, temporaryToken);
|
|
119
|
+
logger.info('password reset request', { email });
|
|
113
120
|
}
|
|
114
121
|
catch (error) {
|
|
115
122
|
logger.error(error, 'auth reset failed');
|
|
@@ -125,6 +132,7 @@ export function createAuth({ getUserByToken, methods: { emailAndPassword }, filt
|
|
|
125
132
|
const token = createAuthToken(rest);
|
|
126
133
|
await redis.set(token, '1', { EX: tokenExpiry });
|
|
127
134
|
setAccessTokenCookie(res, token);
|
|
135
|
+
logger.info('refreshed token', { user });
|
|
128
136
|
return { token };
|
|
129
137
|
}));
|
|
130
138
|
return router;
|
|
@@ -142,6 +150,7 @@ export function createAuth({ getUserByToken, methods: { emailAndPassword }, filt
|
|
|
142
150
|
const valid = await redis.get(token);
|
|
143
151
|
if (!valid) {
|
|
144
152
|
if (!authorize) {
|
|
153
|
+
logger.warn('request with invalid access token');
|
|
145
154
|
return next();
|
|
146
155
|
}
|
|
147
156
|
throw new InvalidToken('token expired');
|
|
@@ -151,7 +160,7 @@ export function createAuth({ getUserByToken, methods: { emailAndPassword }, filt
|
|
|
151
160
|
throw new Error('Failed to decode token');
|
|
152
161
|
}
|
|
153
162
|
const user = await getUserByToken({ ...decoded });
|
|
154
|
-
|
|
163
|
+
setCurrentUser(user);
|
|
155
164
|
next();
|
|
156
165
|
}
|
|
157
166
|
catch (error) {
|
|
@@ -190,7 +199,14 @@ export function parseAuthorizationHeader(req) {
|
|
|
190
199
|
}
|
|
191
200
|
return token;
|
|
192
201
|
}
|
|
193
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Extract an access token from the `Request`-object.
|
|
204
|
+
*
|
|
205
|
+
* Checks multiple places and uses the first match. Priority:
|
|
206
|
+
* 1. Request header `Authorization: `
|
|
207
|
+
* 2. Cookie named `access_token`
|
|
208
|
+
*/
|
|
209
|
+
export function extractAccessTokenFromRequest(req) {
|
|
194
210
|
const authorizationHeader = parseAuthorizationHeader(req);
|
|
195
211
|
if (authorizationHeader) {
|
|
196
212
|
return authorizationHeader;
|
|
@@ -226,7 +242,7 @@ export async function checkIfPasswordsMatch(realPassword, attemptedPassword) {
|
|
|
226
242
|
}
|
|
227
243
|
const validPassword = await bcrypt.compare(attemptedPassword, realPassword);
|
|
228
244
|
if (!validPassword) {
|
|
229
|
-
throw new Error(`Passwords
|
|
245
|
+
throw new Error(`Passwords do not match`);
|
|
230
246
|
}
|
|
231
247
|
return true;
|
|
232
248
|
}
|
package/dist/context.d.ts
CHANGED
|
@@ -10,16 +10,8 @@ export declare function withRequestContext({ getRequestId, }?: RequestContextOpt
|
|
|
10
10
|
* Return a value from the request context
|
|
11
11
|
*/
|
|
12
12
|
export declare function useContext<T>(key: string): T | undefined;
|
|
13
|
-
/**
|
|
14
|
-
* @deprecated
|
|
15
|
-
*/
|
|
16
|
-
export declare const getContext: typeof useContext;
|
|
17
13
|
/**
|
|
18
14
|
* Set a value on the request context
|
|
19
15
|
*/
|
|
20
|
-
export declare function setContext<T>(key: string, value: T): any;
|
|
16
|
+
export declare function setContext<T>(key: string, value: T): Map<string, any> | undefined;
|
|
21
17
|
export declare function useRequestId(): string | undefined;
|
|
22
|
-
/**
|
|
23
|
-
* @deprecated
|
|
24
|
-
*/
|
|
25
|
-
export declare const getRequestId: typeof useRequestId;
|
package/dist/context.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
2
|
import { v4 as uuid } from 'uuid';
|
|
3
|
-
const requestContext =
|
|
3
|
+
const requestContext = new AsyncLocalStorage();
|
|
4
|
+
const REQUEST_ID = 'requestId';
|
|
4
5
|
/**
|
|
5
6
|
* Middleware for setting a `requestId` on the request context.
|
|
6
7
|
*/
|
|
7
8
|
export function withRequestContext({ getRequestId = (req) => req.headers['X-Request-ID'], } = {}) {
|
|
8
9
|
return (req, res, next) => {
|
|
9
10
|
const requestId = getRequestId(req) || uuid();
|
|
10
|
-
requestContext.run(() => {
|
|
11
|
-
requestContext.
|
|
11
|
+
requestContext.run(new Map(), () => {
|
|
12
|
+
const store = requestContext.getStore();
|
|
13
|
+
if (store) {
|
|
14
|
+
store.set(REQUEST_ID, requestId);
|
|
15
|
+
}
|
|
12
16
|
next();
|
|
13
17
|
});
|
|
14
18
|
};
|
|
@@ -17,26 +21,20 @@ export function withRequestContext({ getRequestId = (req) => req.headers['X-Requ
|
|
|
17
21
|
* Return a value from the request context
|
|
18
22
|
*/
|
|
19
23
|
export function useContext(key) {
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
const store = requestContext.getStore();
|
|
25
|
+
if (store) {
|
|
26
|
+
return store.get(key);
|
|
22
27
|
}
|
|
23
28
|
}
|
|
24
|
-
/**
|
|
25
|
-
* @deprecated
|
|
26
|
-
*/
|
|
27
|
-
export const getContext = useContext;
|
|
28
29
|
/**
|
|
29
30
|
* Set a value on the request context
|
|
30
31
|
*/
|
|
31
32
|
export function setContext(key, value) {
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const store = requestContext.getStore();
|
|
34
|
+
if (store) {
|
|
35
|
+
return store.set(key, value);
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
export function useRequestId() {
|
|
37
|
-
return useContext(
|
|
39
|
+
return useContext(REQUEST_ID);
|
|
38
40
|
}
|
|
39
|
-
/**
|
|
40
|
-
* @deprecated
|
|
41
|
-
*/
|
|
42
|
-
export const getRequestId = useRequestId;
|
package/dist/email.js
CHANGED
|
@@ -15,7 +15,7 @@ export function createEmail({ host, port, user, pass, senderName, senderAddress,
|
|
|
15
15
|
text: message,
|
|
16
16
|
...rest,
|
|
17
17
|
});
|
|
18
|
-
getLogger('
|
|
18
|
+
getLogger('email').info('email-sent', { email: result });
|
|
19
19
|
};
|
|
20
20
|
return { send, transporter };
|
|
21
21
|
}
|
package/dist/errors.js
CHANGED
package/dist/listen.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createTerminus } from '@godaddy/terminus';
|
|
2
2
|
import { getLogger } from './logger.js';
|
|
3
|
-
const logger = getLogger();
|
|
3
|
+
const logger = getLogger('core');
|
|
4
4
|
const READINESS_PERIOD_MS = parseInt(process.env.DM_READINESS_PERIOD_MS || '', 10) || 0;
|
|
5
5
|
const FORCE_EXIT_TIMEOUT = parseInt(process.env.DM_FORCE_EXIT_TIMEOUT || '', 10) || 1000;
|
|
6
6
|
/**
|
package/dist/logger.d.ts
CHANGED
|
@@ -18,29 +18,17 @@ export declare function attachSentryClientToLoggers(sentryClient: CreateSentry['
|
|
|
18
18
|
export declare function setGlobalLoggerContext(getContext: () => LoggerContext): void;
|
|
19
19
|
export type Logger = ReturnType<typeof createLogger>;
|
|
20
20
|
export declare function createLogger({ name, getContext, silent, }: LoggerOptions): {
|
|
21
|
-
debug(message: string, context?:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
info(message: string, context?: {
|
|
25
|
-
[key: string]: any;
|
|
26
|
-
}): void;
|
|
27
|
-
warn(message: string, context?: {
|
|
28
|
-
[key: string]: any;
|
|
29
|
-
}): void;
|
|
21
|
+
debug(message: string, context?: LoggerContext): void;
|
|
22
|
+
info(message: string, context?: LoggerContext): void;
|
|
23
|
+
warn(message: string, context?: LoggerContext): void;
|
|
30
24
|
error(error: Error | null, message?: string): void;
|
|
31
25
|
fatal(error: Error | null, message?: string): void;
|
|
32
26
|
};
|
|
33
27
|
export declare function getLogger(name?: string): Logger;
|
|
34
28
|
export declare function getLoggers(): Map<string, {
|
|
35
|
-
debug(message: string, context?:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
info(message: string, context?: {
|
|
39
|
-
[key: string]: any;
|
|
40
|
-
}): void;
|
|
41
|
-
warn(message: string, context?: {
|
|
42
|
-
[key: string]: any;
|
|
43
|
-
}): void;
|
|
29
|
+
debug(message: string, context?: LoggerContext): void;
|
|
30
|
+
info(message: string, context?: LoggerContext): void;
|
|
31
|
+
warn(message: string, context?: LoggerContext): void;
|
|
44
32
|
error(error: Error | null, message?: string | undefined): void;
|
|
45
33
|
fatal(error: Error | null, message?: string | undefined): void;
|
|
46
34
|
}>;
|
package/dist/logger.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as os from 'node:os';
|
|
2
2
|
import { useRequestId } from './context.js';
|
|
3
|
+
const LEVELS = {
|
|
4
|
+
TRACE: 10,
|
|
5
|
+
DEBUG: 20,
|
|
6
|
+
INFO: 30,
|
|
7
|
+
WARN: 40,
|
|
8
|
+
ERROR: 50,
|
|
9
|
+
FATAL: 60,
|
|
10
|
+
};
|
|
11
|
+
const LEVELS_TO_NAME = Object.fromEntries(Object.entries(LEVELS).map(([name, level]) => [level, name.toLowerCase()]));
|
|
3
12
|
const _loggers = new Map();
|
|
4
13
|
let _sentryClient;
|
|
5
14
|
export function attachSentryClientToLoggers(sentryClient) {
|
|
@@ -19,51 +28,61 @@ export function createLogger({ name, getContext, silent = () => process.env.NODE
|
|
|
19
28
|
if (_loggers.has(name)) {
|
|
20
29
|
throw new Error(`A logger named ${name} already exists`);
|
|
21
30
|
}
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
_loggers.set(name, logger);
|
|
27
|
-
if (silent()) {
|
|
28
|
-
logger.level(bunyan.FATAL + 1);
|
|
29
|
-
}
|
|
30
|
-
function getFinalContext() {
|
|
31
|
+
const hostname = os.hostname();
|
|
32
|
+
const pid = process.pid;
|
|
33
|
+
const logLevel = silent() ? LEVELS.FATAL + 1 : LEVELS.INFO;
|
|
34
|
+
function getFinalContext(context) {
|
|
31
35
|
return {
|
|
32
36
|
...defaultGetContext(),
|
|
33
37
|
...getContext?.(),
|
|
38
|
+
...context,
|
|
34
39
|
};
|
|
35
40
|
}
|
|
36
|
-
|
|
41
|
+
function log(level, message, context) {
|
|
42
|
+
const payload = JSON.stringify({
|
|
43
|
+
level: LEVELS_TO_NAME[level],
|
|
44
|
+
hostname,
|
|
45
|
+
pid,
|
|
46
|
+
message,
|
|
47
|
+
...context,
|
|
48
|
+
time: new Date().toISOString(),
|
|
49
|
+
v: 1,
|
|
50
|
+
});
|
|
51
|
+
if (level >= logLevel) {
|
|
52
|
+
console.log(payload);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const api = {
|
|
37
56
|
debug(message, context = {}) {
|
|
38
|
-
return
|
|
57
|
+
return log(LEVELS.DEBUG, message, getFinalContext(context));
|
|
39
58
|
},
|
|
40
59
|
info(message, context = {}) {
|
|
41
|
-
return
|
|
60
|
+
return log(LEVELS.INFO, message, getFinalContext(context));
|
|
42
61
|
},
|
|
43
62
|
warn(message, context = {}) {
|
|
44
|
-
return
|
|
63
|
+
return log(LEVELS.WARN, message, getFinalContext(context));
|
|
45
64
|
},
|
|
46
65
|
error(error, message) {
|
|
47
|
-
const context = getFinalContext();
|
|
66
|
+
const context = getFinalContext({ err: error?.stack });
|
|
48
67
|
if (_sentryClient != null) {
|
|
49
68
|
_sentryClient.captureException(error, {
|
|
50
69
|
tags: context,
|
|
51
70
|
});
|
|
52
71
|
}
|
|
53
|
-
return
|
|
54
|
-
.child(context, true)
|
|
55
|
-
.error(error, message || error?.message);
|
|
72
|
+
return log(LEVELS.ERROR, message || error?.message || '', context);
|
|
56
73
|
},
|
|
57
74
|
fatal(error, message) {
|
|
58
|
-
const context = getFinalContext();
|
|
75
|
+
const context = getFinalContext({ err: error });
|
|
59
76
|
if (_sentryClient != null) {
|
|
60
77
|
_sentryClient.captureException(error, {
|
|
61
78
|
tags: context,
|
|
62
79
|
});
|
|
63
80
|
}
|
|
64
|
-
return
|
|
81
|
+
return log(LEVELS.FATAL, message || error?.message || '', context);
|
|
65
82
|
},
|
|
66
83
|
};
|
|
84
|
+
_loggers.set(name, api);
|
|
85
|
+
return api;
|
|
67
86
|
}
|
|
68
87
|
export function getLogger(name = 'default') {
|
|
69
88
|
const logger = _loggers.get(name);
|
package/dist/middleware.js
CHANGED
|
@@ -48,9 +48,9 @@ export function before({ cookies = false, helmet: useHelmet = true, json: useJso
|
|
|
48
48
|
function logRequestDuration() {
|
|
49
49
|
const getDurationInMilliseconds = (start) => {
|
|
50
50
|
const NS_PER_SEC = 1e9;
|
|
51
|
-
const
|
|
51
|
+
const NS_TO_S = 1e9;
|
|
52
52
|
const diff = process.hrtime(start);
|
|
53
|
-
return (diff[0] * NS_PER_SEC + diff[1]) /
|
|
53
|
+
return (diff[0] * NS_PER_SEC + diff[1]) / NS_TO_S;
|
|
54
54
|
};
|
|
55
55
|
return (req, res, next) => {
|
|
56
56
|
const start = process.hrtime();
|
|
@@ -58,6 +58,7 @@ function logRequestDuration() {
|
|
|
58
58
|
method: req.method,
|
|
59
59
|
url: req.originalUrl,
|
|
60
60
|
path: req.path,
|
|
61
|
+
ip: req.ip,
|
|
61
62
|
});
|
|
62
63
|
res.on('finish', () => {
|
|
63
64
|
const duration = getDurationInMilliseconds(start);
|
|
@@ -66,6 +67,7 @@ function logRequestDuration() {
|
|
|
66
67
|
url: req.originalUrl,
|
|
67
68
|
path: req.path,
|
|
68
69
|
duration,
|
|
70
|
+
status: res.statusCode,
|
|
69
71
|
});
|
|
70
72
|
});
|
|
71
73
|
next();
|
package/dist/slack.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devmoods/express-extras",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "Kubernetes-ready utilities for rapid Node.js application development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -8,6 +8,17 @@
|
|
|
8
8
|
"bin": {
|
|
9
9
|
"migrate": "bin/migrate"
|
|
10
10
|
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "ts-node --esm example/index.ts",
|
|
13
|
+
"clean": "rm -rf dist",
|
|
14
|
+
"lint": "eslint src",
|
|
15
|
+
"test": "NODE_ENV=test vitest",
|
|
16
|
+
"build": "pnpm run clean && tsc --project tsconfig.build.json",
|
|
17
|
+
"prepublishOnly": "pnpm run clean && pnpm run build",
|
|
18
|
+
"prettier": "prettier --write '**/*.{js,css,md,ts,tsx}'",
|
|
19
|
+
"import-sort": "import-sort --write '**/*.{js,jsx,ts,tsx}'",
|
|
20
|
+
"format": "pnpm run import-sort && pnpm run prettier"
|
|
21
|
+
},
|
|
11
22
|
"author": {
|
|
12
23
|
"name": "hanse",
|
|
13
24
|
"email": "hanse@koren.im"
|
|
@@ -51,8 +62,6 @@
|
|
|
51
62
|
"@sentry/node": "^7.60.1",
|
|
52
63
|
"@types/bcrypt": "^5.0.0",
|
|
53
64
|
"@types/body-parser": "^1.19.2",
|
|
54
|
-
"@types/bunyan": "^1.8.8",
|
|
55
|
-
"@types/cls-hooked": "^4.3.4",
|
|
56
65
|
"@types/cookie-parser": "^1.4.3",
|
|
57
66
|
"@types/express": "^4.17.17",
|
|
58
67
|
"@types/jsonwebtoken": "^9.0.2",
|
|
@@ -62,8 +71,6 @@
|
|
|
62
71
|
"ajv": "^8.12.0",
|
|
63
72
|
"bcrypt": "^5.1.0",
|
|
64
73
|
"body-parser": "^1.20.2",
|
|
65
|
-
"bunyan": "^1.8.15",
|
|
66
|
-
"cls-hooked": "^4.2.2",
|
|
67
74
|
"compose-middleware": "^5.0.1",
|
|
68
75
|
"cookie-parser": "^1.4.6",
|
|
69
76
|
"dotenv": "^16.3.1",
|
|
@@ -92,15 +99,5 @@
|
|
|
92
99
|
"@typescript-eslint/no-shadow": "off",
|
|
93
100
|
"react-hooks/rules-of-hooks": "off"
|
|
94
101
|
}
|
|
95
|
-
},
|
|
96
|
-
"scripts": {
|
|
97
|
-
"start": "ts-node --esm example/index.ts",
|
|
98
|
-
"clean": "rm -rf dist",
|
|
99
|
-
"lint": "eslint src",
|
|
100
|
-
"test": "NODE_ENV=test vitest",
|
|
101
|
-
"build": "pnpm run clean && tsc --project tsconfig.build.json",
|
|
102
|
-
"prettier": "prettier --write '**/*.{js,css,md,ts,tsx}'",
|
|
103
|
-
"import-sort": "import-sort --write '**/*.{js,jsx,ts,tsx}'",
|
|
104
|
-
"format": "pnpm run import-sort && pnpm run prettier"
|
|
105
102
|
}
|
|
106
|
-
}
|
|
103
|
+
}
|