@devmoods/express-extras 0.28.7 → 0.29.0
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/bin/migrate +1 -1
- package/dist/auth.js +2 -4
- package/dist/email.js +1 -1
- package/dist/faktory.d.ts +1 -1
- package/dist/listen.js +5 -5
- package/dist/middleware.d.ts +8 -1
- package/dist/middleware.js +3 -3
- package/dist/migrate.d.ts +2 -2
- package/dist/postgres.js +0 -1
- package/dist/sentry.d.ts +1 -0
- package/dist/setupTests.js +2 -8
- package/package.json +32 -28
package/bin/migrate
CHANGED
package/dist/auth.js
CHANGED
|
@@ -25,7 +25,6 @@ const emailSchema = { type: 'string', minLength: 4 };
|
|
|
25
25
|
* Returns a signed JWT token.
|
|
26
26
|
*/
|
|
27
27
|
export function createAuthToken(payload, secret = AUTH_SECRET) {
|
|
28
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
29
28
|
return jwt.sign(payload, secret, { expiresIn: TOKEN_EXPIRES_IN });
|
|
30
29
|
}
|
|
31
30
|
/**
|
|
@@ -33,7 +32,6 @@ export function createAuthToken(payload, secret = AUTH_SECRET) {
|
|
|
33
32
|
*/
|
|
34
33
|
export function decodeAuthToken(token, secret = AUTH_SECRET) {
|
|
35
34
|
try {
|
|
36
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
37
35
|
const decoded = jwt.verify(token.trim(), secret);
|
|
38
36
|
/* c8 ignore next 3 */
|
|
39
37
|
if (typeof decoded === 'string') {
|
|
@@ -307,6 +305,8 @@ export function setAccessTokenCookie(res, token) {
|
|
|
307
305
|
if (token == null) {
|
|
308
306
|
res.cookie('access_token', v4(), {
|
|
309
307
|
expires: new Date(1970, 0, 1),
|
|
308
|
+
sameSite: 'strict',
|
|
309
|
+
secure: process.env.NODE_ENV === 'production',
|
|
310
310
|
});
|
|
311
311
|
}
|
|
312
312
|
else {
|
|
@@ -330,7 +330,6 @@ export async function checkIfPasswordsMatch(realPassword, attemptedPassword) {
|
|
|
330
330
|
if (!realPassword) {
|
|
331
331
|
throw new Error('User has no defined password');
|
|
332
332
|
}
|
|
333
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
334
333
|
const validPassword = await bcrypt.compare(attemptedPassword, realPassword);
|
|
335
334
|
if (!validPassword) {
|
|
336
335
|
throw new Error(`Passwords do not match`);
|
|
@@ -341,6 +340,5 @@ export async function checkIfPasswordsMatch(realPassword, attemptedPassword) {
|
|
|
341
340
|
* Returns a hash of a password suitable for storage.
|
|
342
341
|
*/
|
|
343
342
|
export function hashPassword(password) {
|
|
344
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
345
343
|
return bcrypt.hash(password, 10);
|
|
346
344
|
}
|
package/dist/email.js
CHANGED
|
@@ -14,7 +14,7 @@ export function createEmail({ host, port, user, pass, senderName, senderAddress,
|
|
|
14
14
|
from: `${senderName} <${senderAddress}>`,
|
|
15
15
|
to,
|
|
16
16
|
subject,
|
|
17
|
-
text: message,
|
|
17
|
+
text: message, // plain text,
|
|
18
18
|
...rest,
|
|
19
19
|
};
|
|
20
20
|
const result = await transporter.sendMail(payload);
|
package/dist/faktory.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export interface JobsOptions {
|
|
|
4
4
|
faktory?: typeof create;
|
|
5
5
|
}
|
|
6
6
|
export declare function createJobs({ queueName, faktory: createFactory, }: JobsOptions): {
|
|
7
|
-
job: <K extends Record<string, any>, T extends (input: K) =>
|
|
7
|
+
job: <K extends Record<string, any>, T extends (input: K) => undefined | Promise<any>>(fn: T) => {
|
|
8
8
|
$job: boolean;
|
|
9
9
|
jobName: string;
|
|
10
10
|
readonly executionCount: number;
|
package/dist/listen.js
CHANGED
|
@@ -4,7 +4,7 @@ import {} from 'node:net';
|
|
|
4
4
|
import { delay } from '@devmoods/fetch';
|
|
5
5
|
import {} from 'express';
|
|
6
6
|
import { getLogger } from './logger.js';
|
|
7
|
-
import { route } from './middleware.js';
|
|
7
|
+
import { before, route } from './middleware.js';
|
|
8
8
|
import { envPort, readEnv } from './utils.js';
|
|
9
9
|
const logger = getLogger('http');
|
|
10
10
|
const READINESS_PERIOD = readEnv.number('READINESS_PERIOD_MS', 0);
|
|
@@ -61,9 +61,9 @@ export function stoppable(server, grace = Infinity) {
|
|
|
61
61
|
}
|
|
62
62
|
server.on('connection', onConnection);
|
|
63
63
|
server.on('request', onRequest);
|
|
64
|
-
// @ts-
|
|
64
|
+
// @ts-expect-error any
|
|
65
65
|
server.stop = stop;
|
|
66
|
-
// @ts-
|
|
66
|
+
// @ts-expect-error any
|
|
67
67
|
server.inspect = () => {
|
|
68
68
|
return {
|
|
69
69
|
sockets: requestsPerSocket.size,
|
|
@@ -95,7 +95,7 @@ export function createExpressServer(app, options = {}) {
|
|
|
95
95
|
for (const signal of ['SIGTERM', 'SIGINT']) {
|
|
96
96
|
process.on(signal, onSignal);
|
|
97
97
|
}
|
|
98
|
-
app.get('/health', route(async () => {
|
|
98
|
+
app.get('/health', before(), route(async () => {
|
|
99
99
|
const timestamp = new Date().toISOString();
|
|
100
100
|
try {
|
|
101
101
|
if (stopping) {
|
|
@@ -125,7 +125,7 @@ export function createExpressServer(app, options = {}) {
|
|
|
125
125
|
return onSignal('SIGTERM');
|
|
126
126
|
},
|
|
127
127
|
get port() {
|
|
128
|
-
// @ts-
|
|
128
|
+
// @ts-expect-error any
|
|
129
129
|
return server.address().port;
|
|
130
130
|
},
|
|
131
131
|
};
|
package/dist/middleware.d.ts
CHANGED
|
@@ -5,16 +5,23 @@ type JsonParser = typeof bodyParser.json;
|
|
|
5
5
|
export declare const urlencodedParser: UrlencodedParser;
|
|
6
6
|
export declare const jsonParser: JsonParser;
|
|
7
7
|
export { asyncMiddleware as route };
|
|
8
|
+
export interface BeforeMiddlewareCSPDirectives {
|
|
9
|
+
'script-src': string[];
|
|
10
|
+
'style-src': string[];
|
|
11
|
+
'connect-src': string[];
|
|
12
|
+
[key: string]: string[];
|
|
13
|
+
}
|
|
8
14
|
export interface BeforeMiddlewareOptions {
|
|
9
15
|
cookies?: boolean;
|
|
10
16
|
helmet?: boolean;
|
|
11
17
|
json?: boolean;
|
|
12
18
|
allowUnsafeInlineScripts?: boolean;
|
|
19
|
+
cspDirectives?: (defaults: BeforeMiddlewareCSPDirectives) => BeforeMiddlewareCSPDirectives;
|
|
13
20
|
}
|
|
14
21
|
/**
|
|
15
22
|
* Register middleware that must come before the app routes.
|
|
16
23
|
*/
|
|
17
|
-
export declare function before({ cookies, helmet: useHelmet, json: useJson, allowUnsafeInlineScripts, }?: BeforeMiddlewareOptions): import("compose-middleware").RequestHandler<unknown, unknown, void>;
|
|
24
|
+
export declare function before({ cookies, helmet: useHelmet, json: useJson, allowUnsafeInlineScripts, cspDirectives, }?: BeforeMiddlewareOptions): import("compose-middleware").RequestHandler<unknown, unknown, void>;
|
|
18
25
|
/**
|
|
19
26
|
* Middleware that sends a 404
|
|
20
27
|
*
|
package/dist/middleware.js
CHANGED
|
@@ -15,7 +15,7 @@ export { asyncMiddleware as route };
|
|
|
15
15
|
/**
|
|
16
16
|
* Register middleware that must come before the app routes.
|
|
17
17
|
*/
|
|
18
|
-
export function before({ cookies = false, helmet: useHelmet = true, json: useJson = true, allowUnsafeInlineScripts = false, } = {}) {
|
|
18
|
+
export function before({ cookies = false, helmet: useHelmet = true, json: useJson = true, allowUnsafeInlineScripts = false, cspDirectives = (x) => x, } = {}) {
|
|
19
19
|
return compose([
|
|
20
20
|
withRequestContext(),
|
|
21
21
|
logRequestDuration(),
|
|
@@ -24,7 +24,7 @@ export function before({ cookies = false, helmet: useHelmet = true, json: useJso
|
|
|
24
24
|
useHelmet &&
|
|
25
25
|
helmet({
|
|
26
26
|
contentSecurityPolicy: {
|
|
27
|
-
directives: {
|
|
27
|
+
directives: cspDirectives({
|
|
28
28
|
'default-src': ["'self'"],
|
|
29
29
|
'base-uri': ["'self'"],
|
|
30
30
|
'connect-src': [
|
|
@@ -46,7 +46,7 @@ export function before({ cookies = false, helmet: useHelmet = true, json: useJso
|
|
|
46
46
|
'script-src-attr': ["'none'"],
|
|
47
47
|
'style-src': ["'self'", 'https:', "'unsafe-inline'"],
|
|
48
48
|
'upgrade-insecure-requests': [],
|
|
49
|
-
},
|
|
49
|
+
}),
|
|
50
50
|
},
|
|
51
51
|
}),
|
|
52
52
|
useJson && jsonParser(),
|
package/dist/migrate.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ interface Migration {
|
|
|
6
6
|
}
|
|
7
7
|
interface MigrationFileAPI {
|
|
8
8
|
useTransaction?: boolean;
|
|
9
|
-
up(fn: any): Promise<
|
|
10
|
-
down(fn: any): Promise<string> | Promise<void> | string |
|
|
9
|
+
up(fn: any): Promise<void> | Promise<void> | string | undefined;
|
|
10
|
+
down(fn: any): Promise<string> | Promise<void> | string | undefined;
|
|
11
11
|
}
|
|
12
12
|
export declare function cli(): Promise<void>;
|
|
13
13
|
export declare function runCli(input: string[], flags: Record<string, any>, showHelp?: () => void): Promise<number>;
|
package/dist/postgres.js
CHANGED
|
@@ -70,7 +70,6 @@ export class Transaction extends Connection {
|
|
|
70
70
|
* @param config
|
|
71
71
|
*/
|
|
72
72
|
export function createPostgres({ onError, url = readEnv('POSTGRES_URL'), ...config } = {}) {
|
|
73
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
74
73
|
const pool = new pg.Pool({ connectionString: url, ...config });
|
|
75
74
|
if (onError) {
|
|
76
75
|
pool.on('error', onError);
|
package/dist/sentry.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ export declare function createSentryOptions(app: Application | null, options?: S
|
|
|
59
59
|
serverName?: string | undefined;
|
|
60
60
|
includeLocalVariables?: boolean | undefined;
|
|
61
61
|
clientClass?: typeof Sentry.NodeClient | undefined;
|
|
62
|
+
spotlight?: string | boolean | undefined;
|
|
62
63
|
shouldCreateSpanForRequest?(this: void, url: string): boolean;
|
|
63
64
|
onFatalError?(this: void, error: Error): void;
|
|
64
65
|
};
|
package/dist/setupTests.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devmoods/express-extras",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Kubernetes-ready utilities for rapid Node.js application development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,56 +23,57 @@
|
|
|
23
23
|
],
|
|
24
24
|
"license": "ISC",
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@devmoods/eslint-config": "^1.
|
|
26
|
+
"@devmoods/eslint-config": "^1.12.0",
|
|
27
27
|
"@types/koa-compose": "^3.2.8",
|
|
28
|
-
"@types/node": "20.
|
|
29
|
-
"@types/supertest": "^
|
|
30
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
31
|
-
"@typescript-eslint/parser": "^
|
|
32
|
-
"@vitest/coverage-v8": "^
|
|
28
|
+
"@types/node": "20.11.24",
|
|
29
|
+
"@types/supertest": "^6.0.2",
|
|
30
|
+
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
|
31
|
+
"@typescript-eslint/parser": "^7.1.0",
|
|
32
|
+
"@vitest/coverage-v8": "^1.3.1",
|
|
33
33
|
"chalk": "^5.3.0",
|
|
34
|
-
"eslint": "^8.
|
|
35
|
-
"eslint-plugin-import": "^2.29.
|
|
34
|
+
"eslint": "^8.57.0",
|
|
35
|
+
"eslint-plugin-import": "^2.29.1",
|
|
36
36
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
|
37
|
-
"eslint-plugin-prettier": "^5.
|
|
37
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
38
38
|
"eslint-plugin-react": "^7.33.2",
|
|
39
39
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
40
40
|
"faktory-worker": "^4.5.1",
|
|
41
|
-
"prettier": "3.
|
|
42
|
-
"supertest": "6.3.
|
|
43
|
-
"ts-node": "10.9.
|
|
44
|
-
"typescript": "5.
|
|
45
|
-
"vitest": "^
|
|
41
|
+
"prettier": "3.2.5",
|
|
42
|
+
"supertest": "6.3.4",
|
|
43
|
+
"ts-node": "10.9.2",
|
|
44
|
+
"typescript": "5.3.3",
|
|
45
|
+
"vitest": "^1.3.1"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@devmoods/fetch": "^4.0.1",
|
|
49
|
-
"@sentry/node": "^7.
|
|
49
|
+
"@sentry/node": "^7.104.0",
|
|
50
50
|
"@types/bcrypt": "^5.0.2",
|
|
51
51
|
"@types/body-parser": "^1.19.5",
|
|
52
|
-
"@types/cookie-parser": "^1.4.
|
|
52
|
+
"@types/cookie-parser": "^1.4.7",
|
|
53
53
|
"@types/express": "^4.17.21",
|
|
54
|
-
"@types/jsonwebtoken": "^9.0.
|
|
54
|
+
"@types/jsonwebtoken": "^9.0.6",
|
|
55
55
|
"@types/nodemailer": "^6.4.14",
|
|
56
|
-
"@types/pg": "^8.
|
|
57
|
-
"@types/superagent": "^
|
|
58
|
-
"@types/uuid": "^9.0.
|
|
56
|
+
"@types/pg": "^8.11.2",
|
|
57
|
+
"@types/superagent": "^8.1.4",
|
|
58
|
+
"@types/uuid": "^9.0.8",
|
|
59
59
|
"ajv": "^8.12.0",
|
|
60
60
|
"bcrypt": "^5.1.1",
|
|
61
61
|
"body-parser": "^1.20.2",
|
|
62
|
-
"commander": "^
|
|
62
|
+
"commander": "^12.0.0",
|
|
63
63
|
"compose-middleware": "^5.0.1",
|
|
64
64
|
"cookie-parser": "^1.4.6",
|
|
65
|
-
"dotenv": "^16.
|
|
66
|
-
"express": "^4.18.
|
|
65
|
+
"dotenv": "^16.4.5",
|
|
66
|
+
"express": "^4.18.3",
|
|
67
67
|
"express-route-parser": "^1.0.5",
|
|
68
68
|
"helmet": "^7.1.0",
|
|
69
69
|
"jsonwebtoken": "^9.0.2",
|
|
70
|
-
"meow": "^
|
|
71
|
-
"nodemailer": "^6.9.
|
|
70
|
+
"meow": "^13.2.0",
|
|
71
|
+
"nodemailer": "^6.9.11",
|
|
72
72
|
"pg": "^8.11.3",
|
|
73
|
-
"redis": "^4.6.
|
|
73
|
+
"redis": "^4.6.13",
|
|
74
74
|
"sql-template-strings": "^2.2.2",
|
|
75
|
-
"uuid": "^9.0.1"
|
|
75
|
+
"uuid": "^9.0.1",
|
|
76
|
+
"vitest-fail-on-console": "^0.6.2"
|
|
76
77
|
},
|
|
77
78
|
"prettier": {
|
|
78
79
|
"singleQuote": true
|
|
@@ -91,6 +92,9 @@
|
|
|
91
92
|
"peerDependencies": {
|
|
92
93
|
"faktory-worker": "^4.5.1"
|
|
93
94
|
},
|
|
95
|
+
"engines": {
|
|
96
|
+
"node": ">=20.3.0 <22"
|
|
97
|
+
},
|
|
94
98
|
"scripts": {
|
|
95
99
|
"start": "ts-node --esm example/index.ts",
|
|
96
100
|
"start:worker": "ts-node --esm example/worker.ts",
|