@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 CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  set -e
4
4
 
5
- node_modules/.bin/ts-node --esm node_modules/@devmoods/express-extras/dist/cli/migrate.js ${*:1}
5
+ node --no-warnings --loader ts-node/esm node_modules/@devmoods/express-extras/dist/cli/migrate.js ${*:1}
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) => void | Promise<any>>(fn: T) => {
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-ignore
64
+ // @ts-expect-error any
65
65
  server.stop = stop;
66
- // @ts-ignore
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-ignore
128
+ // @ts-expect-error any
129
129
  return server.address().port;
130
130
  },
131
131
  };
@@ -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
  *
@@ -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<string> | Promise<void> | string | void;
10
- down(fn: any): Promise<string> | Promise<void> | string | void;
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
  };
@@ -1,9 +1,3 @@
1
1
  import 'dotenv/config';
2
- import * as crypto from 'node:crypto';
3
- try {
4
- // @ts-ignore
5
- globalThis.crypto = crypto;
6
- }
7
- catch (e) {
8
- // empty
9
- }
2
+ import failOnConsole from 'vitest-fail-on-console';
3
+ failOnConsole();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devmoods/express-extras",
3
- "version": "0.28.7",
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.8.0",
26
+ "@devmoods/eslint-config": "^1.12.0",
27
27
  "@types/koa-compose": "^3.2.8",
28
- "@types/node": "20.9.0",
29
- "@types/supertest": "^2.0.16",
30
- "@typescript-eslint/eslint-plugin": "^6.10.0",
31
- "@typescript-eslint/parser": "^6.10.0",
32
- "@vitest/coverage-v8": "^0.34.6",
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.53.0",
35
- "eslint-plugin-import": "^2.29.0",
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.0.1",
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.0.3",
42
- "supertest": "6.3.3",
43
- "ts-node": "10.9.1",
44
- "typescript": "5.2.2",
45
- "vitest": "^0.34.6"
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.80.0",
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.6",
52
+ "@types/cookie-parser": "^1.4.7",
53
53
  "@types/express": "^4.17.21",
54
- "@types/jsonwebtoken": "^9.0.5",
54
+ "@types/jsonwebtoken": "^9.0.6",
55
55
  "@types/nodemailer": "^6.4.14",
56
- "@types/pg": "^8.10.9",
57
- "@types/superagent": "^4.1.21",
58
- "@types/uuid": "^9.0.7",
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": "^11.1.0",
62
+ "commander": "^12.0.0",
63
63
  "compose-middleware": "^5.0.1",
64
64
  "cookie-parser": "^1.4.6",
65
- "dotenv": "^16.3.1",
66
- "express": "^4.18.2",
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": "^12.1.1",
71
- "nodemailer": "^6.9.7",
70
+ "meow": "^13.2.0",
71
+ "nodemailer": "^6.9.11",
72
72
  "pg": "^8.11.3",
73
- "redis": "^4.6.10",
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",