@devmoods/express-extras 0.67.0 → 0.68.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.
@@ -1,7 +1,6 @@
1
1
  import { startTimer } from '@devmoods/observability';
2
2
  import argon2 from 'argon2';
3
3
  import bcrypt from 'bcrypt';
4
- import {} from 'express';
5
4
  import { createTokenResponse, tokenSchema } from './token.js';
6
5
  import {} from './types.js';
7
6
  import { Unauthorized } from '../errors.js';
@@ -1,6 +1,5 @@
1
1
  import { config } from '@devmoods/config';
2
2
  import { type } from 'arktype';
3
- import {} from 'express';
4
3
  import { OAuth2Client } from 'google-auth-library';
5
4
  import { BadRequest, Unauthorized } from '../errors.js';
6
5
  import { getLogger } from '../logger.js';
@@ -1,5 +1,4 @@
1
1
  import { DoesNotExistError } from '@devmoods/postgres';
2
- import {} from 'express';
3
2
  import { createTokenResponse } from './token.js';
4
3
  import {} from './types.js';
5
4
  import { getLogger } from '../logger.js';
@@ -6,28 +6,28 @@ export declare function createTokenResponse(accessToken: AccessToken): readonly
6
6
  }, {
7
7
  readonly 'Cache-Control': "no-store";
8
8
  }];
9
- export type AccessToken = ReturnType<typeof createAccessToken>;
9
+ export type AccessToken = Awaited<ReturnType<typeof createAccessToken>>;
10
10
  /**
11
11
  * Returns a signed JWT token.
12
12
  */
13
- export declare function createAccessToken(payload: any, version?: string, secret?: string): {
13
+ export declare function createAccessToken(payload: any, version?: string, secret?: string): Promise<{
14
14
  token: string;
15
15
  tokenType: "Bearer";
16
16
  expiresIn: number;
17
- };
17
+ }>;
18
18
  /**
19
19
  * Decode the given JWT token.
20
20
  */
21
- export declare function decodeAccessToken(token: string, secret?: string): {
22
- [key: string]: any;
23
- iss?: string | undefined;
24
- sub?: string | undefined;
25
- aud?: string | string[] | undefined;
26
- exp?: number | undefined;
27
- nbf?: number | undefined;
28
- iat?: number | undefined;
29
- jti?: string | undefined;
30
- };
21
+ export declare function decodeAccessToken(token: string, secret?: string): Promise<{
22
+ [propName: string]: unknown;
23
+ iss?: string;
24
+ sub?: string;
25
+ aud?: string | string[];
26
+ jti?: string;
27
+ nbf?: number;
28
+ exp?: number;
29
+ iat?: number;
30
+ }>;
31
31
  /**
32
32
  * Extract a Bearer token from the HTTP Authorization header
33
33
  * of `req`.
@@ -1,6 +1,6 @@
1
1
  import { config } from '@devmoods/config';
2
2
  import {} from 'express';
3
- import jwt from 'jsonwebtoken';
3
+ import { SignJWT, jwtVerify } from 'jose';
4
4
  import { v4 } from 'uuid';
5
5
  import { InvalidToken } from './errors.js';
6
6
  import {} from '../validate.js';
@@ -24,24 +24,24 @@ export function createTokenResponse(accessToken) {
24
24
  /**
25
25
  * Returns a signed JWT token.
26
26
  */
27
- export function createAccessToken(payload, version = '1', secret = config.AUTH_JWT_SECRET) {
27
+ export async function createAccessToken(payload, version = '1', secret = config.AUTH_JWT_SECRET) {
28
28
  const expiresIn = config.AUTH_TOKEN_EXPIRES;
29
- const token = jwt.sign({ v: version, ...payload }, secret, {
30
- expiresIn,
31
- });
29
+ const secretKey = new TextEncoder().encode(secret);
30
+ const token = await new SignJWT({ v: version, ...payload })
31
+ .setProtectedHeader({ alg: 'HS256' })
32
+ .setExpirationTime(`${expiresIn}s`)
33
+ .setIssuedAt(new Date())
34
+ .sign(secretKey);
32
35
  return { token, tokenType: 'Bearer', expiresIn };
33
36
  }
34
37
  /**
35
38
  * Decode the given JWT token.
36
39
  */
37
- export function decodeAccessToken(token, secret = config.AUTH_JWT_SECRET) {
40
+ export async function decodeAccessToken(token, secret = config.AUTH_JWT_SECRET) {
38
41
  try {
39
- const decoded = jwt.verify(token.trim(), secret);
40
- /* c8 ignore next 3 */
41
- if (typeof decoded === 'string') {
42
- throw new Error('decoded value not an object');
43
- }
44
- return { ...decoded };
42
+ const secretKey = new TextEncoder().encode(secret);
43
+ const { payload } = await jwtVerify(token.trim(), secretKey);
44
+ return { ...payload };
45
45
  }
46
46
  catch (error) {
47
47
  throw new InvalidToken(`Failed to decode auth token: ${error.message}`, {
package/dist/auth.js CHANGED
@@ -22,7 +22,7 @@ export function createAuth({ getUserById, filterUser, tokenStorage, providers, l
22
22
  const useCurrentUser = () => useRequestContext('currentUser');
23
23
  const setCurrentUser = (user) => setRequestContext('currentUser', user);
24
24
  const login = async (req, res, user, isRefresh = false) => {
25
- const accessToken = createAccessToken({ uid: user.id }, sessionTokenVersion);
25
+ const accessToken = await createAccessToken({ uid: user.id }, sessionTokenVersion);
26
26
  const sessionId = sha256(accessToken.token);
27
27
  await tokenStorage.set(sessionId, String(user.id), accessToken.expiresIn);
28
28
  setAccessTokenCookie(res, accessToken.token);
@@ -138,7 +138,7 @@ export function createAuth({ getUserById, filterUser, tokenStorage, providers, l
138
138
  await logout(req, res);
139
139
  throw new InvalidToken('session token expired');
140
140
  }
141
- const decoded = decodeAccessToken(token);
141
+ const decoded = await decodeAccessToken(token);
142
142
  if (decoded.v !== sessionTokenVersion) {
143
143
  await logout(req, res);
144
144
  throw new InvalidToken('Invalid token version');
package/dist/router.d.ts CHANGED
@@ -12,7 +12,7 @@ export type ExtractParams<Path extends string> = Prettify<Path extends `${string
12
12
  } & ExtractParams<`/${Rest}`> : Path extends `${string}:${infer Param}` ? {
13
13
  [K in Param extends `${infer P}?` ? P : Param]: string;
14
14
  } : {}>;
15
- export type TypedRequestHandler<Params, ResponseBodySchema extends StandardSchemaV1 | undefined, RequestBodySchema extends StandardSchemaV1 | undefined, RequestQuery extends StandardSchemaV1 | undefined, RequestParamsSchema extends StandardSchemaV1 | undefined = undefined> = (req: Request<Params, never, RequestBodySchema extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<RequestBodySchema> : unknown, RequestQuery extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<RequestQuery> : Record<string, string | string[]>>, res: Response<ResponseBodySchema extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<ResponseBodySchema> : unknown>, next: NextFunction) => ResponseWrapper<ResponseBodySchema extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<ResponseBodySchema> : unknown> | Promise<ResponseWrapper<ResponseBodySchema extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<ResponseBodySchema> : unknown>>;
15
+ export type TypedRequestHandler<Params, ResponseBodySchema extends StandardSchemaV1 | undefined, RequestBodySchema extends StandardSchemaV1 | undefined, RequestQuery extends StandardSchemaV1 | undefined, RequestParamsSchema extends StandardSchemaV1 | undefined = undefined> = (req: Request<Params, any, RequestBodySchema extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<RequestBodySchema> : unknown, RequestQuery extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<RequestQuery> : Record<string, string | string[]>>, res: Response<ResponseBodySchema extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<ResponseBodySchema> : unknown>, next: NextFunction) => ResponseWrapper<ResponseBodySchema extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<ResponseBodySchema> : unknown> | Promise<ResponseWrapper<ResponseBodySchema extends StandardSchemaV1<any> ? StandardSchemaV1.InferOutput<ResponseBodySchema> : unknown>>;
16
16
  export declare class TypedRouter {
17
17
  #private;
18
18
  router: import("express-serve-static-core").Router;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devmoods/express-extras",
3
- "version": "0.67.0",
3
+ "version": "0.68.0",
4
4
  "description": "Kubernetes-ready utilities for rapid Node.js application development",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -65,22 +65,21 @@
65
65
  "faktory-worker": "^4.7.1",
66
66
  "react": "^19.2.0",
67
67
  "react-dom": "^19.2.0",
68
- "vite": "^7.1.10"
68
+ "vite": "^7.1.11"
69
69
  },
70
70
  "dependencies": {
71
71
  "@devmoods/config": "0.2.0",
72
72
  "@devmoods/fetch": "^4.2.0",
73
73
  "@devmoods/observability": "0.1.1",
74
74
  "@devmoods/postgres": "0.2.1",
75
- "@hey-api/openapi-ts": "^0.86.0",
76
- "@sentry/node": "^10.20.0",
77
- "@sentry/node-native": "^10.20.0",
78
- "@sentry/profiling-node": "^10.20.0",
75
+ "@hey-api/openapi-ts": "^0.86.1",
76
+ "@sentry/node": "^10.21.0",
77
+ "@sentry/node-native": "^10.21.0",
78
+ "@sentry/profiling-node": "^10.21.0",
79
79
  "@standard-schema/spec": "^1.0.0",
80
80
  "@types/bcrypt": "^6.0.0",
81
81
  "@types/cookie-parser": "^1.4.9",
82
82
  "@types/express": "^5.0.3",
83
- "@types/jsonwebtoken": "^9.0.10",
84
83
  "@types/koa-compose": "^3.2.8",
85
84
  "@types/nodemailer": "^7.0.2",
86
85
  "@types/qs": "^6.14.0",
@@ -94,7 +93,7 @@
94
93
  "express": "^4.21.2",
95
94
  "google-auth-library": "^10.4.1",
96
95
  "helmet": "^8.1.0",
97
- "jsonwebtoken": "^9.0.2",
96
+ "jose": "^6.1.0",
98
97
  "nodemailer": "^7.0.9",
99
98
  "redis": "^5.8.3",
100
99
  "sonda": "^0.9.0",
@@ -112,5 +111,5 @@
112
111
  "engines": {
113
112
  "node": ">=20 <25"
114
113
  },
115
- "gitHead": "ddc79e0157d354d9c25cfbb0ba86d8e61d560fbc"
114
+ "gitHead": "721a709c087904a5cc1332d28a62857a82295fea"
116
115
  }