Skip to content

Commit 0519b4f

Browse files
fix(analytics): move middleware after pre-parser routes and decouple billing events
- Analytics middleware now mounts after initPreParserRoutes so webhooks and other pre-parser endpoints are not tracked (fixes overhead/noise). - Billing plan-change listener moved to modules/billing/billing.init.js to eliminate the lib→module dependency (correct direction: module→lib). - Added JSDoc to the init function.
1 parent f7ad3b3 commit 0519b4f

2 files changed

Lines changed: 25 additions & 10 deletions

File tree

lib/services/express.js

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import requestId from '../middlewares/requestId.js';
2323
import sentry from './sentry.js';
2424
import AnalyticsService from './analytics.js';
2525
import analyticsMiddleware from '../middlewares/analytics.js';
26-
import billingEvents from '../../modules/billing/lib/events.js';
2726

2827
/**
2928
* Initialize Swagger
@@ -206,7 +205,9 @@ const initErrorRoutes = (app) => {
206205
};
207206

208207
/**
209-
* Initialize the Express application
208+
* Initialize the Express application.
209+
*
210+
* @returns {Promise<import('express').Express>} Configured Express app
210211
*/
211212
const init = async () => {
212213
// Initialize express app
@@ -217,17 +218,12 @@ const init = async () => {
217218
initLocalVariables(app);
218219
// Assign a unique request ID before any route registration
219220
app.use(requestId);
221+
// Initialize pre-parser routes (before body parsing, CSRF, and analytics)
222+
await initPreParserRoutes(app);
220223
// Initialize analytics (PostHog) and mount auto-capture middleware
224+
// Mounted after pre-parser routes so webhooks are not tracked
221225
await AnalyticsService.init();
222226
app.use(analyticsMiddleware);
223-
// Listen for billing plan changes and update group properties
224-
billingEvents.on('plan.changed', ({ organizationId, newPlan }) => {
225-
try {
226-
AnalyticsService.groupIdentify('company', String(organizationId), { plan: newPlan });
227-
} catch (_) { /* analytics must not break billing flow */ }
228-
});
229-
// Initialize pre-parser routes (before body parsing and CSRF)
230-
await initPreParserRoutes(app);
231227
// Initialize Express middleware
232228
initMiddleware(app);
233229
// Initialize Helmet security headers

modules/billing/billing.init.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Module dependencies
3+
*/
4+
import AnalyticsService from '../../lib/services/analytics.js';
5+
import billingEvents from './lib/events.js';
6+
7+
/**
8+
* Billing module initialisation.
9+
* Wires cross-module integrations that depend on services from lib.
10+
*/
11+
// eslint-disable-next-line no-unused-vars
12+
export default async (app) => {
13+
// Update analytics group properties when a subscription plan changes
14+
billingEvents.on('plan.changed', ({ organizationId, newPlan }) => {
15+
try {
16+
AnalyticsService.groupIdentify('company', String(organizationId), { plan: newPlan });
17+
} catch (_) { /* analytics must not break billing flow */ }
18+
});
19+
};

0 commit comments

Comments
 (0)