@devmoods/express-extras 0.28.8 → 0.30.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/bin/routes +0 -0
- package/dist/auth.js +0 -4
- package/dist/email.js +1 -1
- package/dist/faktory.d.ts +2 -2
- package/dist/listen.js +9 -6
- package/dist/middleware.d.ts +8 -1
- package/dist/middleware.js +4 -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 +42 -39
package/bin/migrate
CHANGED
package/bin/routes
CHANGED
|
File without changes
|
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') {
|
|
@@ -332,7 +330,6 @@ export async function checkIfPasswordsMatch(realPassword, attemptedPassword) {
|
|
|
332
330
|
if (!realPassword) {
|
|
333
331
|
throw new Error('User has no defined password');
|
|
334
332
|
}
|
|
335
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
336
333
|
const validPassword = await bcrypt.compare(attemptedPassword, realPassword);
|
|
337
334
|
if (!validPassword) {
|
|
338
335
|
throw new Error(`Passwords do not match`);
|
|
@@ -343,6 +340,5 @@ export async function checkIfPasswordsMatch(realPassword, attemptedPassword) {
|
|
|
343
340
|
* Returns a hash of a password suitable for storage.
|
|
344
341
|
*/
|
|
345
342
|
export function hashPassword(password) {
|
|
346
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
347
343
|
return bcrypt.hash(password, 10);
|
|
348
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,11 +4,11 @@ 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;
|
|
11
|
-
delay(args?: Parameters<T>[0]
|
|
11
|
+
delay(args?: Parameters<T>[0]): Promise<`${string}-${string}-${string}-${string}-${string}`>;
|
|
12
12
|
execute(args: Parameters<T>[0]): Promise<any>;
|
|
13
13
|
};
|
|
14
14
|
queueName: string;
|
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 attach stop
|
|
65
65
|
server.stop = stop;
|
|
66
|
-
// @ts-
|
|
66
|
+
// @ts-expect-error attach inspect
|
|
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,8 +125,11 @@ export function createExpressServer(app, options = {}) {
|
|
|
125
125
|
return onSignal('SIGTERM');
|
|
126
126
|
},
|
|
127
127
|
get port() {
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
const address = server.address();
|
|
129
|
+
if (address == null || typeof address === 'string') {
|
|
130
|
+
throw new Error('address was a string, should not happen');
|
|
131
|
+
}
|
|
132
|
+
return address.port;
|
|
130
133
|
},
|
|
131
134
|
};
|
|
132
135
|
}
|
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,13 +24,14 @@ 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': [
|
|
31
31
|
"'self'",
|
|
32
32
|
'ws:',
|
|
33
33
|
'*.sentry.io',
|
|
34
|
+
'*.ingest.sentry.io',
|
|
34
35
|
'*.cdn-apple.com',
|
|
35
36
|
],
|
|
36
37
|
'font-src': ["'self'", 'https:', 'data:'],
|
|
@@ -46,7 +47,7 @@ export function before({ cookies = false, helmet: useHelmet = true, json: useJso
|
|
|
46
47
|
'script-src-attr': ["'none'"],
|
|
47
48
|
'style-src': ["'self'", 'https:', "'unsafe-inline'"],
|
|
48
49
|
'upgrade-insecure-requests': [],
|
|
49
|
-
},
|
|
50
|
+
}),
|
|
50
51
|
},
|
|
51
52
|
}),
|
|
52
53
|
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.30.0",
|
|
4
4
|
"description": "Kubernetes-ready utilities for rapid Node.js application development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -8,16 +8,6 @@
|
|
|
8
8
|
"bin": {
|
|
9
9
|
"migrate": "bin/migrate"
|
|
10
10
|
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"start": "ts-node --esm example/index.ts",
|
|
13
|
-
"start:worker": "ts-node --esm example/worker.ts",
|
|
14
|
-
"clean": "rm -rf dist",
|
|
15
|
-
"lint": "eslint src",
|
|
16
|
-
"test": "./test.sh src",
|
|
17
|
-
"build": "pnpm run clean && tsc --project tsconfig.build.json",
|
|
18
|
-
"prepublishOnly": "pnpm run clean && pnpm run build",
|
|
19
|
-
"format": "prettier --write '**/*.{js,css,md,ts,tsx}'"
|
|
20
|
-
},
|
|
21
11
|
"author": {
|
|
22
12
|
"name": "hanse",
|
|
23
13
|
"email": "hanse@koren.im"
|
|
@@ -33,56 +23,57 @@
|
|
|
33
23
|
],
|
|
34
24
|
"license": "ISC",
|
|
35
25
|
"devDependencies": {
|
|
36
|
-
"@devmoods/eslint-config": "^1.
|
|
26
|
+
"@devmoods/eslint-config": "^1.12.0",
|
|
37
27
|
"@types/koa-compose": "^3.2.8",
|
|
38
|
-
"@types/node": "20.
|
|
39
|
-
"@types/supertest": "^
|
|
40
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
41
|
-
"@typescript-eslint/parser": "^
|
|
42
|
-
"@vitest/coverage-v8": "^
|
|
28
|
+
"@types/node": "20.12.12",
|
|
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",
|
|
43
33
|
"chalk": "^5.3.0",
|
|
44
|
-
"eslint": "^8.
|
|
45
|
-
"eslint-plugin-import": "^2.29.
|
|
34
|
+
"eslint": "^8.57.0",
|
|
35
|
+
"eslint-plugin-import": "^2.29.1",
|
|
46
36
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
|
47
|
-
"eslint-plugin-prettier": "^5.
|
|
37
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
48
38
|
"eslint-plugin-react": "^7.33.2",
|
|
49
39
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
50
40
|
"faktory-worker": "^4.5.1",
|
|
51
|
-
"prettier": "3.
|
|
52
|
-
"supertest": "
|
|
53
|
-
"ts-node": "10.9.
|
|
54
|
-
"typescript": "5.
|
|
55
|
-
"vitest": "^
|
|
41
|
+
"prettier": "3.2.5",
|
|
42
|
+
"supertest": "7.0.0",
|
|
43
|
+
"ts-node": "10.9.2",
|
|
44
|
+
"typescript": "5.4.5",
|
|
45
|
+
"vitest": "^1.3.1"
|
|
56
46
|
},
|
|
57
47
|
"dependencies": {
|
|
58
48
|
"@devmoods/fetch": "^4.0.1",
|
|
59
|
-
"@sentry/node": "^7.
|
|
49
|
+
"@sentry/node": "^7.116.0",
|
|
60
50
|
"@types/bcrypt": "^5.0.2",
|
|
61
51
|
"@types/body-parser": "^1.19.5",
|
|
62
|
-
"@types/cookie-parser": "^1.4.
|
|
52
|
+
"@types/cookie-parser": "^1.4.7",
|
|
63
53
|
"@types/express": "^4.17.21",
|
|
64
|
-
"@types/jsonwebtoken": "^9.0.
|
|
54
|
+
"@types/jsonwebtoken": "^9.0.6",
|
|
65
55
|
"@types/nodemailer": "^6.4.14",
|
|
66
|
-
"@types/pg": "^8.
|
|
67
|
-
"@types/superagent": "^
|
|
68
|
-
"@types/uuid": "^9.0.
|
|
56
|
+
"@types/pg": "^8.11.2",
|
|
57
|
+
"@types/superagent": "^8.1.4",
|
|
58
|
+
"@types/uuid": "^9.0.8",
|
|
69
59
|
"ajv": "^8.12.0",
|
|
70
60
|
"bcrypt": "^5.1.1",
|
|
71
61
|
"body-parser": "^1.20.2",
|
|
72
|
-
"commander": "^
|
|
62
|
+
"commander": "^12.0.0",
|
|
73
63
|
"compose-middleware": "^5.0.1",
|
|
74
64
|
"cookie-parser": "^1.4.6",
|
|
75
|
-
"dotenv": "^16.
|
|
76
|
-
"express": "^4.18.
|
|
65
|
+
"dotenv": "^16.4.5",
|
|
66
|
+
"express": "^4.18.3",
|
|
77
67
|
"express-route-parser": "^1.0.5",
|
|
78
68
|
"helmet": "^7.1.0",
|
|
79
69
|
"jsonwebtoken": "^9.0.2",
|
|
80
|
-
"meow": "^
|
|
81
|
-
"nodemailer": "^6.9.
|
|
70
|
+
"meow": "^13.2.0",
|
|
71
|
+
"nodemailer": "^6.9.11",
|
|
82
72
|
"pg": "^8.11.3",
|
|
83
|
-
"redis": "^4.6.
|
|
73
|
+
"redis": "^4.6.13",
|
|
84
74
|
"sql-template-strings": "^2.2.2",
|
|
85
|
-
"uuid": "^9.0.1"
|
|
75
|
+
"uuid": "^9.0.1",
|
|
76
|
+
"vitest-fail-on-console": "^0.7.0"
|
|
86
77
|
},
|
|
87
78
|
"prettier": {
|
|
88
79
|
"singleQuote": true
|
|
@@ -100,5 +91,17 @@
|
|
|
100
91
|
},
|
|
101
92
|
"peerDependencies": {
|
|
102
93
|
"faktory-worker": "^4.5.1"
|
|
94
|
+
},
|
|
95
|
+
"engines": {
|
|
96
|
+
"node": ">=20.3.0 <22"
|
|
97
|
+
},
|
|
98
|
+
"scripts": {
|
|
99
|
+
"start": "ts-node --esm example/index.ts",
|
|
100
|
+
"start:worker": "ts-node --esm example/worker.ts",
|
|
101
|
+
"clean": "rm -rf dist",
|
|
102
|
+
"lint": "eslint src",
|
|
103
|
+
"test": "./test.sh src",
|
|
104
|
+
"build": "pnpm run clean && tsc --project tsconfig.build.json",
|
|
105
|
+
"format": "prettier --write '**/*.{js,css,md,ts,tsx}'"
|
|
103
106
|
}
|
|
104
|
-
}
|
|
107
|
+
}
|