@devmoods/express-extras 0.70.0 → 0.71.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/dist/auth/emailAndPassword.js +2 -2
- package/dist/auth.js +4 -3
- package/dist/listen.js +1 -1
- package/dist/manage.js +2 -1
- package/dist/middleware.js +2 -5
- package/dist/rate-limit.js +4 -2
- package/dist/routes.d.ts +13 -2
- package/dist/routes.js +2 -1
- package/dist/sentry.d.ts +1 -1
- package/dist/sentry.js +29 -9
- package/dist/validate.js +2 -1
- package/dist/vite/defineViteConfig.d.ts +1 -1
- package/dist/vite/defineViteConfig.js +7 -10
- package/package.json +27 -26
|
@@ -56,10 +56,10 @@ export function EmailAndPasswordAuthProvider(options) {
|
|
|
56
56
|
}
|
|
57
57
|
context.setCurrentUser(user);
|
|
58
58
|
await options.onPasswordChanged?.(user, await hashPassword(password), {
|
|
59
|
-
/* v8 ignore
|
|
59
|
+
/* v8 ignore start -- @preserve */
|
|
60
60
|
ip: req.ip ?? '',
|
|
61
|
-
/* v8 ignore next -- @preserve */
|
|
62
61
|
userAgent: req.headers['user-agent'] ?? '',
|
|
62
|
+
/* v8 ignore end -- @preserve */
|
|
63
63
|
});
|
|
64
64
|
logger.info('user changed password');
|
|
65
65
|
return 200;
|
package/dist/auth.js
CHANGED
|
@@ -29,10 +29,10 @@ export function createAuth({ getUserById, filterUser, tokenStorage, providers, l
|
|
|
29
29
|
setCurrentUser(user);
|
|
30
30
|
if (!isRefresh) {
|
|
31
31
|
await onUserLoggedIn?.(user, {
|
|
32
|
-
/* v8 ignore
|
|
32
|
+
/* v8 ignore start -- @preserve */
|
|
33
33
|
ip: req.ip ?? '',
|
|
34
|
-
/* v8 ignore next -- @preserve */
|
|
35
34
|
userAgent: req.headers['user-agent'] ?? '',
|
|
35
|
+
/* v8 ignore end -- @preserve */
|
|
36
36
|
sessionId,
|
|
37
37
|
});
|
|
38
38
|
}
|
|
@@ -292,8 +292,9 @@ export function createAuth({ getUserById, filterUser, tokenStorage, providers, l
|
|
|
292
292
|
}
|
|
293
293
|
return {
|
|
294
294
|
protect,
|
|
295
|
-
/* v8 ignore
|
|
295
|
+
/* v8 ignore start -- @preserve */
|
|
296
296
|
before: () => middleware(false),
|
|
297
|
+
/* v8 ignore end -- @preserve */
|
|
297
298
|
createRouter: () => createAuthRouter().getRouter(),
|
|
298
299
|
useCurrentUser,
|
|
299
300
|
middleware,
|
package/dist/listen.js
CHANGED
|
@@ -146,7 +146,7 @@ export function createExpressServer(app, options = {}) {
|
|
|
146
146
|
const validateType = (type) => {
|
|
147
147
|
return healthTypes.includes(type);
|
|
148
148
|
};
|
|
149
|
-
const type = req.params.type || req.query.type || 'ready';
|
|
149
|
+
const type = (req.params.type || req.query.type || 'ready');
|
|
150
150
|
if (!validateType(type)) {
|
|
151
151
|
throw BadRequest('Invalid health type');
|
|
152
152
|
}
|
package/dist/manage.js
CHANGED
|
@@ -93,8 +93,9 @@ export function registerDefaultCommands(app, program = defaultProgram) {
|
|
|
93
93
|
{
|
|
94
94
|
asClass: true,
|
|
95
95
|
classStructure: 'off',
|
|
96
|
-
/*
|
|
96
|
+
/* v8 ignore start -- @preserve */
|
|
97
97
|
classNameBuilder: (name) => `${name}Service`,
|
|
98
|
+
/* v8 ignore end -- @preserve */
|
|
98
99
|
name: '@hey-api/sdk',
|
|
99
100
|
},
|
|
100
101
|
],
|
package/dist/middleware.js
CHANGED
|
@@ -97,16 +97,13 @@ function logRequestDuration() {
|
|
|
97
97
|
path: req.path,
|
|
98
98
|
query: req.query,
|
|
99
99
|
ip: req.ip,
|
|
100
|
-
/* v8 ignore
|
|
100
|
+
/* v8 ignore start -- @preserve */
|
|
101
101
|
userAgent: req.headers['user-agent'] ?? 'unknown',
|
|
102
|
-
/* v8 ignore next -- @preserve */
|
|
103
102
|
accept: req.headers['accept'] ?? 'unknown',
|
|
104
|
-
/* v8 ignore next -- @preserve */
|
|
105
103
|
host: req.headers['host'] ?? 'unknown',
|
|
106
|
-
/* v8 ignore next -- @preserve */
|
|
107
104
|
referer: req.headers['referer'] ?? 'unknown',
|
|
108
|
-
/* v8 ignore next -- @preserve */
|
|
109
105
|
origin: req.headers['origin'] ?? 'unknown',
|
|
106
|
+
/* v8 ignore end -- @preserve */
|
|
110
107
|
});
|
|
111
108
|
res.on('finish', () => {
|
|
112
109
|
const duration = timer.getDuration();
|
package/dist/rate-limit.js
CHANGED
|
@@ -6,8 +6,10 @@ import {} from './redis.js';
|
|
|
6
6
|
* Returns a middleware for rate limiting requests.
|
|
7
7
|
*/
|
|
8
8
|
export function rateLimit(redis, { max = 100, windowSizeInSeconds = 60,
|
|
9
|
-
/*
|
|
10
|
-
getKey = (req) => req.ip || 'unknown',
|
|
9
|
+
/* v8 ignore start -- @preserve */
|
|
10
|
+
getKey = (req) => req.ip || 'unknown',
|
|
11
|
+
/* v8 ignore end -- @preserve */
|
|
12
|
+
} = {}) {
|
|
11
13
|
const keyPrefix = `${config.REDIS_KEY_PREFIX}rate-limit:`;
|
|
12
14
|
const middleware = async (req, res, next) => {
|
|
13
15
|
try {
|
package/dist/routes.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
import { type Application
|
|
2
|
-
export declare function createDocsRouter(app: Application, extras?: Record<string, any>): RequestHandler
|
|
1
|
+
import { type Application } from 'express';
|
|
2
|
+
export declare function createDocsRouter(app: Application, extras?: Record<string, any>): import("express").RequestHandler<Record<string, string>, {
|
|
3
|
+
openapi: string;
|
|
4
|
+
info: {
|
|
5
|
+
description?: string | undefined;
|
|
6
|
+
title: string;
|
|
7
|
+
version: string;
|
|
8
|
+
};
|
|
9
|
+
tags: {
|
|
10
|
+
name: string;
|
|
11
|
+
}[];
|
|
12
|
+
paths: Record<string, any>;
|
|
13
|
+
}, unknown, Record<string, any>, Record<string, any>>;
|
|
3
14
|
export declare function parseRoutes(app: Application): {
|
|
4
15
|
method: string;
|
|
5
16
|
path: string;
|
package/dist/routes.js
CHANGED
|
@@ -208,9 +208,10 @@ export function toOpenAPISpec(app, info = {
|
|
|
208
208
|
parameters.push(...Object.keys(params.properties).map((name) => ({
|
|
209
209
|
name,
|
|
210
210
|
in: 'path',
|
|
211
|
-
/*
|
|
211
|
+
/* v8 ignore start -- @preserve */
|
|
212
212
|
required: params.required?.includes(name) ?? true,
|
|
213
213
|
schema: params.properties[name],
|
|
214
|
+
/* v8 ignore end -- @preserve */
|
|
214
215
|
})));
|
|
215
216
|
}
|
|
216
217
|
// Add query parameters
|
package/dist/sentry.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ import type * as Sentry from '@sentry/node';
|
|
|
2
2
|
export type { Sentry };
|
|
3
3
|
export interface SentryOptions extends Sentry.NodeOptions {
|
|
4
4
|
}
|
|
5
|
-
export declare function sentryOptions(options?: SentryOptions): SentryOptions
|
|
5
|
+
export declare function sentryOptions(options?: SentryOptions): Promise<SentryOptions>;
|
package/dist/sentry.js
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
import { config } from '@devmoods/config';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Safely imports native Sentry integrations if available.
|
|
4
|
+
* Returns null if native modules are not available (e.g., on unsupported Node.js versions).
|
|
5
|
+
*/
|
|
6
|
+
async function getNativeIntegrations() {
|
|
7
|
+
const integrations = [];
|
|
8
|
+
/* v8 ignore next -- @preserve */
|
|
9
|
+
try {
|
|
10
|
+
const { nodeProfilingIntegration } = await import('@sentry/profiling-node');
|
|
11
|
+
integrations.push(nodeProfilingIntegration());
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// Native profiling integration not available
|
|
15
|
+
}
|
|
16
|
+
/* v8 ignore next -- @preserve */
|
|
17
|
+
try {
|
|
18
|
+
const { eventLoopBlockIntegration } = await import('@sentry/node-native');
|
|
19
|
+
integrations.push(eventLoopBlockIntegration({
|
|
20
|
+
threshold: config.SENTRY_EVENT_LOOP_THRESHOLD,
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Native event loop integration not available
|
|
25
|
+
}
|
|
26
|
+
return integrations;
|
|
27
|
+
}
|
|
28
|
+
export async function sentryOptions(options = {}) {
|
|
29
|
+
const nativeIntegrations = await getNativeIntegrations();
|
|
5
30
|
return {
|
|
6
31
|
dsn: config.SENTRY_DSN,
|
|
7
32
|
tracesSampleRate: config.SENTRY_TRACES_SAMPLE_RATE,
|
|
8
33
|
profilesSampleRate: config.SENTRY_PROFILES_SAMPLE_RATE,
|
|
9
|
-
integrations:
|
|
10
|
-
nodeProfilingIntegration(),
|
|
11
|
-
eventLoopBlockIntegration({
|
|
12
|
-
threshold: config.SENTRY_EVENT_LOOP_THRESHOLD,
|
|
13
|
-
}),
|
|
14
|
-
],
|
|
34
|
+
integrations: nativeIntegrations,
|
|
15
35
|
enableLogs: true,
|
|
16
36
|
...options,
|
|
17
37
|
};
|
package/dist/validate.js
CHANGED
|
@@ -27,7 +27,7 @@ export async function validateSchema(data, schema) {
|
|
|
27
27
|
catch (error) {
|
|
28
28
|
return {
|
|
29
29
|
isValid: false,
|
|
30
|
-
/* v8 ignore
|
|
30
|
+
/* v8 ignore start -- @preserve */
|
|
31
31
|
errors: (error instanceof ValidationError
|
|
32
32
|
? error.issues.map((issue) => [
|
|
33
33
|
String(issue.path ?? '/'),
|
|
@@ -43,6 +43,7 @@ export async function validateSchema(data, schema) {
|
|
|
43
43
|
}
|
|
44
44
|
return result;
|
|
45
45
|
}, {}),
|
|
46
|
+
/* v8 ignore end -- @preserve */
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
49
|
return { isValid: true, errors: null };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/// <reference types="vitest" />
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
-
import
|
|
4
|
+
import babel from '@rolldown/plugin-babel';
|
|
5
|
+
import react, { reactCompilerPreset } from '@vitejs/plugin-react';
|
|
5
6
|
import Sonda from 'sonda/vite';
|
|
6
7
|
import { defineConfig } from 'vite';
|
|
7
8
|
import { readEnv } from '../utils.js';
|
|
8
|
-
export function defineViteConfig({ base = '',
|
|
9
|
+
export function defineViteConfig({ base = '', ssr = false, analyze = readEnv.boolean('VITE_ANALYZE', false), }) {
|
|
9
10
|
const allowedHosts = [
|
|
10
11
|
'localhost',
|
|
11
12
|
'127.0.0.1',
|
|
@@ -24,14 +25,10 @@ export function defineViteConfig({ base = '', reactCompiler = false, ssr = false
|
|
|
24
25
|
const port = readEnv.number('VITE_PORT', 5173);
|
|
25
26
|
return defineConfig({
|
|
26
27
|
plugins: [
|
|
27
|
-
react(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
plugins: ['babel-plugin-react-compiler'],
|
|
32
|
-
},
|
|
33
|
-
}
|
|
34
|
-
: {}),
|
|
28
|
+
react(),
|
|
29
|
+
// @ts-expect-error something up
|
|
30
|
+
babel({
|
|
31
|
+
presets: [reactCompilerPreset()],
|
|
35
32
|
}),
|
|
36
33
|
Sonda({
|
|
37
34
|
enabled: analyze,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devmoods/express-extras",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.71.1",
|
|
4
4
|
"description": "Kubernetes-ready utilities for rapid Node.js application development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,44 +60,45 @@
|
|
|
60
60
|
],
|
|
61
61
|
"license": "ISC",
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@vitejs/plugin-react": "^
|
|
64
|
-
"arktype": "^2.
|
|
63
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
64
|
+
"arktype": "^2.2.0",
|
|
65
65
|
"faktory-worker": "^4.7.1",
|
|
66
|
-
"react": "^19.2.
|
|
67
|
-
"react-dom": "^19.2.
|
|
68
|
-
"vite": "^
|
|
66
|
+
"react": "^19.2.4",
|
|
67
|
+
"react-dom": "^19.2.4",
|
|
68
|
+
"vite": "^8.0.0"
|
|
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
|
-
"@devmoods/postgres": "0.
|
|
75
|
-
"@hey-api/openapi-ts": "^0.
|
|
76
|
-
"@
|
|
77
|
-
"@sentry/node
|
|
78
|
-
"@sentry/
|
|
79
|
-
"@
|
|
74
|
+
"@devmoods/postgres": "0.3.0",
|
|
75
|
+
"@hey-api/openapi-ts": "^0.94.1",
|
|
76
|
+
"@rolldown/plugin-babel": "^0.2.1",
|
|
77
|
+
"@sentry/node": "^10.43.0",
|
|
78
|
+
"@sentry/node-native": "^10.43.0",
|
|
79
|
+
"@sentry/profiling-node": "^10.43.0",
|
|
80
|
+
"@standard-schema/spec": "^1.1.0",
|
|
80
81
|
"@types/bcrypt": "^6.0.0",
|
|
81
82
|
"@types/cookie-parser": "^1.4.10",
|
|
82
|
-
"@types/express": "^5.0.
|
|
83
|
+
"@types/express": "^5.0.6",
|
|
83
84
|
"@types/koa-compose": "^3.2.9",
|
|
84
|
-
"@types/nodemailer": "^7.0.
|
|
85
|
-
"@types/qs": "^6.
|
|
86
|
-
"ajv": "^8.
|
|
85
|
+
"@types/nodemailer": "^7.0.11",
|
|
86
|
+
"@types/qs": "^6.15.0",
|
|
87
|
+
"ajv": "^8.18.0",
|
|
87
88
|
"argon2": "^0.44.0",
|
|
88
89
|
"bcrypt": "^6.0.0",
|
|
89
90
|
"chalk": "^5.6.2",
|
|
90
|
-
"commander": "^14.0.
|
|
91
|
+
"commander": "^14.0.3",
|
|
91
92
|
"cookie-parser": "^1.4.7",
|
|
92
|
-
"dotenv": "^17.
|
|
93
|
+
"dotenv": "^17.3.1",
|
|
93
94
|
"express": "^4.21.2",
|
|
94
|
-
"google-auth-library": "^10.
|
|
95
|
+
"google-auth-library": "^10.6.1",
|
|
95
96
|
"helmet": "^8.1.0",
|
|
96
|
-
"jose": "^6.
|
|
97
|
-
"nodemailer": "^
|
|
98
|
-
"redis": "^5.
|
|
99
|
-
"sonda": "^0.
|
|
100
|
-
"tough-cookie": "^6.0.
|
|
97
|
+
"jose": "^6.2.1",
|
|
98
|
+
"nodemailer": "^8.0.2",
|
|
99
|
+
"redis": "^5.11.0",
|
|
100
|
+
"sonda": "^0.11.1",
|
|
101
|
+
"tough-cookie": "^6.0.1",
|
|
101
102
|
"uuid": "^13.0.0",
|
|
102
103
|
"vitest-fail-on-console": "^0.10.1"
|
|
103
104
|
},
|
|
@@ -109,7 +110,7 @@
|
|
|
109
110
|
"vite": ">=6.0.5"
|
|
110
111
|
},
|
|
111
112
|
"engines": {
|
|
112
|
-
"node": ">=20 <
|
|
113
|
+
"node": ">=20 <26"
|
|
113
114
|
},
|
|
114
|
-
"gitHead": "
|
|
115
|
+
"gitHead": "4b74551d66a9fb898839dd9c889fc4e72328602c"
|
|
115
116
|
}
|