@devmoods/express-extras 0.69.0 → 0.71.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.
@@ -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 next -- @preserve */
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 next -- @preserve */
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 next -- @preserve */
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
- /* c8 ignore next 1 */
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
  ],
@@ -97,16 +97,13 @@ function logRequestDuration() {
97
97
  path: req.path,
98
98
  query: req.query,
99
99
  ip: req.ip,
100
- /* v8 ignore next -- @preserve */
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();
@@ -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
- /* c8 ignore next 1 */
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, type RequestHandler } from 'express';
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
- /* c8 ignore next 1 */
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
- import { eventLoopBlockIntegration } from '@sentry/node-native';
3
- import { nodeProfilingIntegration } from '@sentry/profiling-node';
4
- export function sentryOptions(options = {}) {
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 next -- @preserve */
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,5 +1,5 @@
1
1
  import { type UserConfig } from 'vite';
2
- export declare function defineViteConfig({ base, reactCompiler, ssr, analyze, }: {
2
+ export declare function defineViteConfig({ base, ssr, analyze, }: {
3
3
  base?: string;
4
4
  reactCompiler?: boolean;
5
5
  ssr?: boolean;
@@ -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 react from '@vitejs/plugin-react';
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 = '', reactCompiler = false, ssr = false, analyze = readEnv.boolean('VITE_ANALYZE', false), }) {
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
- ...(reactCompiler
29
- ? {
30
- babel: {
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.69.0",
3
+ "version": "0.71.0",
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": "^5.1.0",
64
- "arktype": "^2.1.25",
63
+ "@rolldown/plugin-babel": "^0.2.1",
64
+ "@vitejs/plugin-react": "^6.0.1",
65
+ "arktype": "^2.2.0",
65
66
  "faktory-worker": "^4.7.1",
66
- "react": "^19.2.0",
67
- "react-dom": "^19.2.0",
68
- "vite": "^7.1.12"
67
+ "react": "^19.2.4",
68
+ "react-dom": "^19.2.4",
69
+ "vite": "^8.0.0"
69
70
  },
70
71
  "dependencies": {
71
72
  "@devmoods/config": "0.2.0",
72
73
  "@devmoods/fetch": "^4.2.0",
73
74
  "@devmoods/observability": "0.1.1",
74
- "@devmoods/postgres": "0.2.2",
75
- "@hey-api/openapi-ts": "^0.86.11",
76
- "@sentry/node": "^10.22.0",
77
- "@sentry/node-native": "^10.22.0",
78
- "@sentry/profiling-node": "^10.22.0",
79
- "@standard-schema/spec": "^1.0.0",
75
+ "@devmoods/postgres": "0.3.0",
76
+ "@hey-api/openapi-ts": "^0.94.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.5",
83
+ "@types/express": "^5.0.6",
83
84
  "@types/koa-compose": "^3.2.9",
84
- "@types/nodemailer": "^7.0.3",
85
- "@types/qs": "^6.14.0",
86
- "ajv": "^8.17.1",
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.2",
91
+ "commander": "^14.0.3",
91
92
  "cookie-parser": "^1.4.7",
92
- "dotenv": "^17.2.3",
93
+ "dotenv": "^17.3.1",
93
94
  "express": "^4.21.2",
94
- "google-auth-library": "^10.5.0",
95
+ "google-auth-library": "^10.6.1",
95
96
  "helmet": "^8.1.0",
96
- "jose": "^6.1.0",
97
- "nodemailer": "^7.0.10",
98
- "redis": "^5.9.0",
99
- "sonda": "^0.9.0",
100
- "tough-cookie": "^6.0.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 <25"
113
+ "node": ">=20 <26"
113
114
  },
114
- "gitHead": "eb2f12e0a86234754ebf2977be7f4a14ccf8bed3"
115
+ "gitHead": "1b5505c96b70ee96e05b2db07b5e8aa494d45f4e"
115
116
  }