posthog-node 5.30.7 → 5.31.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.
@@ -10,6 +10,9 @@ interface MiddlewareError extends Error {
10
10
  statusCode?: number | string;
11
11
  };
12
12
  }
13
+ export declare function setupExpressRequestContext(_posthog: PostHogBackendClient, app: {
14
+ use: (middleware: ExpressMiddleware) => unknown;
15
+ }): void;
13
16
  export declare function setupExpressErrorHandler(_posthog: PostHogBackendClient, app: {
14
17
  use: (middleware: ExpressMiddleware | ExpressErrorMiddleware) => unknown;
15
18
  }): void;
@@ -1 +1 @@
1
- {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/extensions/express.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAEhD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEhD,KAAK,iBAAiB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;AAEhF,KAAK,sBAAsB,GAAG,CAC5B,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,KACnC,IAAI,CAAA;AAET,UAAU,eAAgB,SAAQ,KAAK;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC7B,MAAM,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAC7B,CAAA;CACF;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,oBAAoB,EAC9B,GAAG,EAAE;IACH,GAAG,EAAE,CAAC,UAAU,EAAE,iBAAiB,GAAG,sBAAsB,KAAK,OAAO,CAAA;CACzE,GACA,IAAI,CAEN"}
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/extensions/express.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAGhD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGhD,KAAK,iBAAiB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;AAEhF,KAAK,sBAAsB,GAAG,CAC5B,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,KACnC,IAAI,CAAA;AAET,UAAU,eAAgB,SAAQ,KAAK;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC7B,MAAM,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAC7B,CAAA;CACF;AA4BD,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,oBAAoB,EAC9B,GAAG,EAAE;IACH,GAAG,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,OAAO,CAAA;CAChD,GACA,IAAI,CAEN;AAQD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,oBAAoB,EAC9B,GAAG,EAAE;IACH,GAAG,EAAE,CAAC,UAAU,EAAE,iBAAiB,GAAG,sBAAsB,KAAK,OAAO,CAAA;CACzE,GACA,IAAI,CAEN"}
@@ -33,18 +33,53 @@ var __webpack_require__ = {};
33
33
  var __webpack_exports__ = {};
34
34
  __webpack_require__.r(__webpack_exports__);
35
35
  __webpack_require__.d(__webpack_exports__, {
36
+ setupExpressRequestContext: ()=>setupExpressRequestContext,
36
37
  setupExpressErrorHandler: ()=>setupExpressErrorHandler
37
38
  });
38
39
  const index_js_namespaceObject = require("./error-tracking/index.js");
39
40
  var index_js_default = /*#__PURE__*/ __webpack_require__.n(index_js_namespaceObject);
41
+ const external_tracing_headers_js_namespaceObject = require("./tracing-headers.js");
42
+ function getClientIp(req) {
43
+ const forwarded = (0, external_tracing_headers_js_namespaceObject.getFirstHeaderValue)(req.headers['x-forwarded-for']);
44
+ if (forwarded) {
45
+ const ip = forwarded.split(',')[0].trim();
46
+ if (ip) return ip;
47
+ }
48
+ return req.socket?.remoteAddress;
49
+ }
50
+ function buildRequestContextData(req) {
51
+ const { sessionId, distinctId } = (0, external_tracing_headers_js_namespaceObject.getPostHogTracingHeaderValues)(req.headers);
52
+ const properties = {};
53
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$current_url', req.originalUrl || req.url);
54
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$request_method', req.method);
55
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$request_path', req.path);
56
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$user_agent', (0, external_tracing_headers_js_namespaceObject.getFirstHeaderValue)(req.headers['user-agent']));
57
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$ip', getClientIp(req));
58
+ return {
59
+ ...void 0 !== sessionId ? {
60
+ sessionId
61
+ } : {},
62
+ ...void 0 !== distinctId ? {
63
+ distinctId
64
+ } : {},
65
+ properties
66
+ };
67
+ }
68
+ function setupExpressRequestContext(_posthog, app) {
69
+ app.use(posthogRequestContext(_posthog));
70
+ }
71
+ function posthogRequestContext(posthog) {
72
+ return (req, _res, next)=>{
73
+ posthog.withContext(buildRequestContextData(req), ()=>next());
74
+ };
75
+ }
40
76
  function setupExpressErrorHandler(_posthog, app) {
41
77
  app.use(posthogErrorHandler(_posthog));
42
78
  }
43
79
  function posthogErrorHandler(posthog) {
44
80
  return (error, req, res, next)=>{
45
81
  if (index_js_default().isPreviouslyCapturedError(error)) return void next(error);
46
- const sessionId = req.headers['x-posthog-session-id'];
47
- const distinctId = req.headers['x-posthog-distinct-id'];
82
+ const contextData = buildRequestContextData(req);
48
83
  const syntheticException = new Error('Synthetic exception');
49
84
  const hint = {
50
85
  mechanism: {
@@ -53,23 +88,24 @@ function posthogErrorHandler(posthog) {
53
88
  },
54
89
  syntheticException
55
90
  };
56
- posthog.addPendingPromise(index_js_default().buildEventMessage(error, hint, distinctId, {
57
- $session_id: sessionId,
58
- $current_url: req.url,
59
- $request_method: req.method,
60
- $request_path: req.path,
61
- $user_agent: req.headers['user-agent'],
62
- $response_status_code: res.statusCode,
63
- $ip: req.headers['x-forwarded-for'] || req?.socket?.remoteAddress
64
- }).then((msg)=>{
91
+ const additionalProperties = {
92
+ ...void 0 !== contextData.sessionId ? {
93
+ $session_id: contextData.sessionId
94
+ } : {},
95
+ ...contextData.properties || {},
96
+ $response_status_code: res.statusCode
97
+ };
98
+ posthog.addPendingPromise(index_js_default().buildEventMessage(error, hint, contextData.distinctId, additionalProperties).then((msg)=>{
65
99
  posthog.capture(msg);
66
100
  }));
67
101
  next(error);
68
102
  };
69
103
  }
70
104
  exports.setupExpressErrorHandler = __webpack_exports__.setupExpressErrorHandler;
105
+ exports.setupExpressRequestContext = __webpack_exports__.setupExpressRequestContext;
71
106
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
72
- "setupExpressErrorHandler"
107
+ "setupExpressErrorHandler",
108
+ "setupExpressRequestContext"
73
109
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
74
110
  Object.defineProperty(exports, '__esModule', {
75
111
  value: true
@@ -1,12 +1,46 @@
1
1
  import error_tracking from "./error-tracking/index.mjs";
2
+ import { addProperty, getFirstHeaderValue, getPostHogTracingHeaderValues } from "./tracing-headers.mjs";
3
+ function getClientIp(req) {
4
+ const forwarded = getFirstHeaderValue(req.headers['x-forwarded-for']);
5
+ if (forwarded) {
6
+ const ip = forwarded.split(',')[0].trim();
7
+ if (ip) return ip;
8
+ }
9
+ return req.socket?.remoteAddress;
10
+ }
11
+ function buildRequestContextData(req) {
12
+ const { sessionId, distinctId } = getPostHogTracingHeaderValues(req.headers);
13
+ const properties = {};
14
+ addProperty(properties, '$current_url', req.originalUrl || req.url);
15
+ addProperty(properties, '$request_method', req.method);
16
+ addProperty(properties, '$request_path', req.path);
17
+ addProperty(properties, '$user_agent', getFirstHeaderValue(req.headers['user-agent']));
18
+ addProperty(properties, '$ip', getClientIp(req));
19
+ return {
20
+ ...void 0 !== sessionId ? {
21
+ sessionId
22
+ } : {},
23
+ ...void 0 !== distinctId ? {
24
+ distinctId
25
+ } : {},
26
+ properties
27
+ };
28
+ }
29
+ function setupExpressRequestContext(_posthog, app) {
30
+ app.use(posthogRequestContext(_posthog));
31
+ }
32
+ function posthogRequestContext(posthog) {
33
+ return (req, _res, next)=>{
34
+ posthog.withContext(buildRequestContextData(req), ()=>next());
35
+ };
36
+ }
2
37
  function setupExpressErrorHandler(_posthog, app) {
3
38
  app.use(posthogErrorHandler(_posthog));
4
39
  }
5
40
  function posthogErrorHandler(posthog) {
6
41
  return (error, req, res, next)=>{
7
42
  if (error_tracking.isPreviouslyCapturedError(error)) return void next(error);
8
- const sessionId = req.headers['x-posthog-session-id'];
9
- const distinctId = req.headers['x-posthog-distinct-id'];
43
+ const contextData = buildRequestContextData(req);
10
44
  const syntheticException = new Error('Synthetic exception');
11
45
  const hint = {
12
46
  mechanism: {
@@ -15,18 +49,17 @@ function posthogErrorHandler(posthog) {
15
49
  },
16
50
  syntheticException
17
51
  };
18
- posthog.addPendingPromise(error_tracking.buildEventMessage(error, hint, distinctId, {
19
- $session_id: sessionId,
20
- $current_url: req.url,
21
- $request_method: req.method,
22
- $request_path: req.path,
23
- $user_agent: req.headers['user-agent'],
24
- $response_status_code: res.statusCode,
25
- $ip: req.headers['x-forwarded-for'] || req?.socket?.remoteAddress
26
- }).then((msg)=>{
52
+ const additionalProperties = {
53
+ ...void 0 !== contextData.sessionId ? {
54
+ $session_id: contextData.sessionId
55
+ } : {},
56
+ ...contextData.properties || {},
57
+ $response_status_code: res.statusCode
58
+ };
59
+ posthog.addPendingPromise(error_tracking.buildEventMessage(error, hint, contextData.distinctId, additionalProperties).then((msg)=>{
27
60
  posthog.capture(msg);
28
61
  }));
29
62
  next(error);
30
63
  };
31
64
  }
32
- export { setupExpressErrorHandler };
65
+ export { setupExpressErrorHandler, setupExpressRequestContext };
@@ -1 +1 @@
1
- {"version":3,"file":"nestjs.d.ts","sourceRoot":"","sources":["../../src/extensions/nestjs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAc,MAAM,MAAM,CAAA;AAI7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAGhD,UAAU,iBAAiB;IACzB,UAAU,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAA;IACxB,WAAW,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAA;CAC1B;AAED,UAAU,gBAAgB;IACxB,YAAY,IAAI,iBAAiB,CAAA;CAClC;AAED,UAAU,WAAW,CAAC,CAAC,GAAG,GAAG;IAC3B,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;CACxB;AAED,UAAU,eAAe,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,GAAG;IACxC,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;CAC1E;AAED,MAAM,WAAW,uBAAuB;IACtC,+GAA+G;IAC/G,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC,mGAAmG;IACnG,iBAAiB,CAAC,EAAE,OAAO,GAAG,uBAAuB,CAAA;CACtD;AAwBD,qBAAa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,kBAAkB,CAAQ;gBAEtB,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,yBAAyB;IAO9E,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC;CAiDzE"}
1
+ {"version":3,"file":"nestjs.d.ts","sourceRoot":"","sources":["../../src/extensions/nestjs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAc,MAAM,MAAM,CAAA;AAK7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAGhD,UAAU,iBAAiB;IACzB,UAAU,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAA;IACxB,WAAW,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAA;CAC1B;AAED,UAAU,gBAAgB;IACxB,YAAY,IAAI,iBAAiB,CAAA;CAClC;AAED,UAAU,WAAW,CAAC,CAAC,GAAG,GAAG;IAC3B,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;CACxB;AAED,UAAU,eAAe,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,GAAG;IACxC,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;CAC1E;AAED,MAAM,WAAW,uBAAuB;IACtC,+GAA+G;IAC/G,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC,mGAAmG;IACnG,iBAAiB,CAAC,EAAE,OAAO,GAAG,uBAAuB,CAAA;CACtD;AAwBD,qBAAa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,kBAAkB,CAAQ;gBAEtB,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,EAAE,yBAAyB;IAO9E,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC;CA+CzE"}
@@ -39,10 +39,11 @@ const external_rxjs_namespaceObject = require("rxjs");
39
39
  const operators_namespaceObject = require("rxjs/operators");
40
40
  const index_js_namespaceObject = require("./error-tracking/index.js");
41
41
  var index_js_default = /*#__PURE__*/ __webpack_require__.n(index_js_namespaceObject);
42
+ const external_tracing_headers_js_namespaceObject = require("./tracing-headers.js");
42
43
  function getClientIp(headers, request) {
43
- const forwarded = headers['x-forwarded-for'];
44
+ const forwarded = (0, external_tracing_headers_js_namespaceObject.getFirstHeaderValue)(headers['x-forwarded-for']);
44
45
  if (forwarded) {
45
- const ip = String(forwarded).split(',')[0].trim();
46
+ const ip = forwarded.split(',')[0].trim();
46
47
  if (ip) return ip;
47
48
  }
48
49
  return request?.socket?.remoteAddress;
@@ -65,20 +66,21 @@ class PostHogInterceptor {
65
66
  const request = httpHost.getRequest();
66
67
  const response = httpHost.getResponse();
67
68
  const headers = request?.headers ?? {};
68
- const sessionId = headers['x-posthog-session-id'];
69
- const windowId = headers['x-posthog-window-id'];
70
- const distinctId = headers['x-posthog-distinct-id'];
69
+ const { sessionId, distinctId } = (0, external_tracing_headers_js_namespaceObject.getPostHogTracingHeaderValues)(headers);
70
+ const properties = {};
71
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$current_url', request?.url);
72
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$request_method', request?.method);
73
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$request_path', request?.path ?? request?.url);
74
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$user_agent', (0, external_tracing_headers_js_namespaceObject.getFirstHeaderValue)(headers['user-agent']));
75
+ (0, external_tracing_headers_js_namespaceObject.addProperty)(properties, '$ip', getClientIp(headers, request));
71
76
  const contextData = {
72
- sessionId,
73
- distinctId,
74
- properties: {
75
- $current_url: request?.url,
76
- $request_method: request?.method,
77
- $request_path: request?.path ?? request?.url,
78
- $window_id: windowId,
79
- $user_agent: headers['user-agent'],
80
- $ip: getClientIp(headers, request)
81
- }
77
+ ...void 0 !== sessionId ? {
78
+ sessionId
79
+ } : {},
80
+ ...void 0 !== distinctId ? {
81
+ distinctId
82
+ } : {},
83
+ properties
82
84
  };
83
85
  this.posthog.enterContext(contextData);
84
86
  let source = next.handle();
@@ -1,10 +1,11 @@
1
1
  import { throwError } from "rxjs";
2
2
  import { catchError } from "rxjs/operators";
3
3
  import error_tracking from "./error-tracking/index.mjs";
4
+ import { addProperty, getFirstHeaderValue, getPostHogTracingHeaderValues } from "./tracing-headers.mjs";
4
5
  function getClientIp(headers, request) {
5
- const forwarded = headers['x-forwarded-for'];
6
+ const forwarded = getFirstHeaderValue(headers['x-forwarded-for']);
6
7
  if (forwarded) {
7
- const ip = String(forwarded).split(',')[0].trim();
8
+ const ip = forwarded.split(',')[0].trim();
8
9
  if (ip) return ip;
9
10
  }
10
11
  return request?.socket?.remoteAddress;
@@ -27,20 +28,21 @@ class PostHogInterceptor {
27
28
  const request = httpHost.getRequest();
28
29
  const response = httpHost.getResponse();
29
30
  const headers = request?.headers ?? {};
30
- const sessionId = headers['x-posthog-session-id'];
31
- const windowId = headers['x-posthog-window-id'];
32
- const distinctId = headers['x-posthog-distinct-id'];
31
+ const { sessionId, distinctId } = getPostHogTracingHeaderValues(headers);
32
+ const properties = {};
33
+ addProperty(properties, '$current_url', request?.url);
34
+ addProperty(properties, '$request_method', request?.method);
35
+ addProperty(properties, '$request_path', request?.path ?? request?.url);
36
+ addProperty(properties, '$user_agent', getFirstHeaderValue(headers['user-agent']));
37
+ addProperty(properties, '$ip', getClientIp(headers, request));
33
38
  const contextData = {
34
- sessionId,
35
- distinctId,
36
- properties: {
37
- $current_url: request?.url,
38
- $request_method: request?.method,
39
- $request_path: request?.path ?? request?.url,
40
- $window_id: windowId,
41
- $user_agent: headers['user-agent'],
42
- $ip: getClientIp(headers, request)
43
- }
39
+ ...void 0 !== sessionId ? {
40
+ sessionId
41
+ } : {},
42
+ ...void 0 !== distinctId ? {
43
+ distinctId
44
+ } : {},
45
+ properties
44
46
  };
45
47
  this.posthog.enterContext(contextData);
46
48
  let source = next.handle();
@@ -0,0 +1,16 @@
1
+ import type { IncomingHttpHeaders } from 'node:http';
2
+ type HeaderValue = IncomingHttpHeaders[string];
3
+ export declare const POSTHOG_TRACING_HEADERS: {
4
+ readonly sessionId: "x-posthog-session-id";
5
+ readonly distinctId: "x-posthog-distinct-id";
6
+ };
7
+ export interface PostHogTracingHeaderValues {
8
+ sessionId?: string;
9
+ distinctId?: string;
10
+ }
11
+ export declare function addProperty(properties: Record<string, any>, key: string, value: unknown): void;
12
+ export declare function getFirstHeaderValue(value: HeaderValue): string | undefined;
13
+ export declare function sanitizeTracingHeaderValue(value: HeaderValue): string | undefined;
14
+ export declare function getPostHogTracingHeaderValues(headers?: IncomingHttpHeaders): PostHogTracingHeaderValues;
15
+ export {};
16
+ //# sourceMappingURL=tracing-headers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing-headers.d.ts","sourceRoot":"","sources":["../../src/extensions/tracing-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAOpD,KAAK,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;AAE9C,eAAO,MAAM,uBAAuB;;;CAG1B,CAAA;AAEV,MAAM,WAAW,0BAA0B;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAI9F;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAqBjF;AAED,wBAAgB,6BAA6B,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,0BAA0B,CAYvG"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ POSTHOG_TRACING_HEADERS: ()=>POSTHOG_TRACING_HEADERS,
28
+ addProperty: ()=>addProperty,
29
+ getFirstHeaderValue: ()=>getFirstHeaderValue,
30
+ getPostHogTracingHeaderValues: ()=>getPostHogTracingHeaderValues,
31
+ sanitizeTracingHeaderValue: ()=>sanitizeTracingHeaderValue
32
+ });
33
+ const TRACING_HEADER_MAX_LENGTH = 1000;
34
+ const TRACING_HEADER_CONTROL_CHARS_REGEX = /[\x00-\x1f\x7f-\x9f]/g;
35
+ const POSTHOG_TRACING_HEADERS = {
36
+ sessionId: 'x-posthog-session-id',
37
+ distinctId: 'x-posthog-distinct-id'
38
+ };
39
+ function addProperty(properties, key, value) {
40
+ if (null != value && '' !== value) properties[key] = value;
41
+ }
42
+ function getFirstHeaderValue(value) {
43
+ return Array.isArray(value) ? value[0] : value;
44
+ }
45
+ function sanitizeTracingHeaderValue(value) {
46
+ if (Array.isArray(value)) {
47
+ for (const item of value){
48
+ const sanitized = sanitizeTracingHeaderValue(item);
49
+ if (void 0 !== sanitized) return sanitized;
50
+ }
51
+ return;
52
+ }
53
+ if ('string' != typeof value) return;
54
+ const sanitized = value.replace(TRACING_HEADER_CONTROL_CHARS_REGEX, '').trim();
55
+ if (!sanitized) return;
56
+ return sanitized.length > TRACING_HEADER_MAX_LENGTH ? sanitized.slice(0, TRACING_HEADER_MAX_LENGTH) : sanitized;
57
+ }
58
+ function getPostHogTracingHeaderValues(headers) {
59
+ if (!headers) return {};
60
+ const sessionId = sanitizeTracingHeaderValue(headers[POSTHOG_TRACING_HEADERS.sessionId]);
61
+ const distinctId = sanitizeTracingHeaderValue(headers[POSTHOG_TRACING_HEADERS.distinctId]);
62
+ return {
63
+ ...void 0 !== sessionId ? {
64
+ sessionId
65
+ } : {},
66
+ ...void 0 !== distinctId ? {
67
+ distinctId
68
+ } : {}
69
+ };
70
+ }
71
+ exports.POSTHOG_TRACING_HEADERS = __webpack_exports__.POSTHOG_TRACING_HEADERS;
72
+ exports.addProperty = __webpack_exports__.addProperty;
73
+ exports.getFirstHeaderValue = __webpack_exports__.getFirstHeaderValue;
74
+ exports.getPostHogTracingHeaderValues = __webpack_exports__.getPostHogTracingHeaderValues;
75
+ exports.sanitizeTracingHeaderValue = __webpack_exports__.sanitizeTracingHeaderValue;
76
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
77
+ "POSTHOG_TRACING_HEADERS",
78
+ "addProperty",
79
+ "getFirstHeaderValue",
80
+ "getPostHogTracingHeaderValues",
81
+ "sanitizeTracingHeaderValue"
82
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
83
+ Object.defineProperty(exports, '__esModule', {
84
+ value: true
85
+ });
@@ -0,0 +1,39 @@
1
+ const TRACING_HEADER_MAX_LENGTH = 1000;
2
+ const TRACING_HEADER_CONTROL_CHARS_REGEX = /[\x00-\x1f\x7f-\x9f]/g;
3
+ const POSTHOG_TRACING_HEADERS = {
4
+ sessionId: 'x-posthog-session-id',
5
+ distinctId: 'x-posthog-distinct-id'
6
+ };
7
+ function addProperty(properties, key, value) {
8
+ if (null != value && '' !== value) properties[key] = value;
9
+ }
10
+ function getFirstHeaderValue(value) {
11
+ return Array.isArray(value) ? value[0] : value;
12
+ }
13
+ function sanitizeTracingHeaderValue(value) {
14
+ if (Array.isArray(value)) {
15
+ for (const item of value){
16
+ const sanitized = sanitizeTracingHeaderValue(item);
17
+ if (void 0 !== sanitized) return sanitized;
18
+ }
19
+ return;
20
+ }
21
+ if ('string' != typeof value) return;
22
+ const sanitized = value.replace(TRACING_HEADER_CONTROL_CHARS_REGEX, '').trim();
23
+ if (!sanitized) return;
24
+ return sanitized.length > TRACING_HEADER_MAX_LENGTH ? sanitized.slice(0, TRACING_HEADER_MAX_LENGTH) : sanitized;
25
+ }
26
+ function getPostHogTracingHeaderValues(headers) {
27
+ if (!headers) return {};
28
+ const sessionId = sanitizeTracingHeaderValue(headers[POSTHOG_TRACING_HEADERS.sessionId]);
29
+ const distinctId = sanitizeTracingHeaderValue(headers[POSTHOG_TRACING_HEADERS.distinctId]);
30
+ return {
31
+ ...void 0 !== sessionId ? {
32
+ sessionId
33
+ } : {},
34
+ ...void 0 !== distinctId ? {
35
+ distinctId
36
+ } : {}
37
+ };
38
+ }
39
+ export { POSTHOG_TRACING_HEADERS, addProperty, getFirstHeaderValue, getPostHogTracingHeaderValues, sanitizeTracingHeaderValue };
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const version = "5.30.7";
1
+ export declare const version = "5.31.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -26,7 +26,7 @@ __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
27
  version: ()=>version
28
28
  });
29
- const version = '5.30.7';
29
+ const version = '5.31.0';
30
30
  exports.version = __webpack_exports__.version;
31
31
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
32
32
  "version"
package/dist/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- const version = '5.30.7';
1
+ const version = '5.31.0';
2
2
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthog-node",
3
- "version": "5.30.7",
3
+ "version": "5.31.0",
4
4
  "description": "PostHog Node.js integration",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,7 +25,7 @@
25
25
  "module": "dist/entrypoints/index.node.mjs",
26
26
  "types": "dist/entrypoints/index.node.d.ts",
27
27
  "dependencies": {
28
- "@posthog/core": "1.27.8"
28
+ "@posthog/core": "1.27.9"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@edge-runtime/jest-environment": "^4.0.0",
@@ -1,7 +1,9 @@
1
1
  import ErrorTracking from './error-tracking'
2
2
  import { PostHogBackendClient } from '../client'
3
3
  import { ErrorTracking as CoreErrorTracking } from '@posthog/core'
4
+ import { addProperty, getFirstHeaderValue, getPostHogTracingHeaderValues } from './tracing-headers'
4
5
  import type { Request, Response } from 'express'
6
+ import type { ContextData } from './context/types'
5
7
 
6
8
  type ExpressMiddleware = (req: Request, res: Response, next: () => void) => void
7
9
 
@@ -21,6 +23,47 @@ interface MiddlewareError extends Error {
21
23
  }
22
24
  }
23
25
 
26
+ function getClientIp(req: Request): string | undefined {
27
+ const forwarded = getFirstHeaderValue(req.headers['x-forwarded-for'])
28
+ if (forwarded) {
29
+ const ip = forwarded.split(',')[0].trim()
30
+ if (ip) return ip
31
+ }
32
+ return req.socket?.remoteAddress
33
+ }
34
+
35
+ function buildRequestContextData(req: Request): Partial<ContextData> {
36
+ const { sessionId, distinctId } = getPostHogTracingHeaderValues(req.headers)
37
+ const properties: Record<string, any> = {}
38
+
39
+ addProperty(properties, '$current_url', req.originalUrl || req.url)
40
+ addProperty(properties, '$request_method', req.method)
41
+ addProperty(properties, '$request_path', req.path)
42
+ addProperty(properties, '$user_agent', getFirstHeaderValue(req.headers['user-agent']))
43
+ addProperty(properties, '$ip', getClientIp(req))
44
+
45
+ return {
46
+ ...(sessionId !== undefined ? { sessionId } : {}),
47
+ ...(distinctId !== undefined ? { distinctId } : {}),
48
+ properties,
49
+ }
50
+ }
51
+
52
+ export function setupExpressRequestContext(
53
+ _posthog: PostHogBackendClient,
54
+ app: {
55
+ use: (middleware: ExpressMiddleware) => unknown
56
+ }
57
+ ): void {
58
+ app.use(posthogRequestContext(_posthog))
59
+ }
60
+
61
+ function posthogRequestContext(posthog: PostHogBackendClient): ExpressMiddleware {
62
+ return (req, _res, next): void => {
63
+ posthog.withContext(buildRequestContextData(req), () => next())
64
+ }
65
+ }
66
+
24
67
  export function setupExpressErrorHandler(
25
68
  _posthog: PostHogBackendClient,
26
69
  app: {
@@ -37,21 +80,17 @@ function posthogErrorHandler(posthog: PostHogBackendClient): ExpressErrorMiddlew
37
80
  return
38
81
  }
39
82
 
40
- const sessionId: string | undefined = req.headers['x-posthog-session-id'] as string | undefined
41
- const distinctId: string | undefined = req.headers['x-posthog-distinct-id'] as string | undefined
83
+ const contextData = buildRequestContextData(req)
42
84
  const syntheticException = new Error('Synthetic exception')
43
85
  const hint: CoreErrorTracking.EventHint = { mechanism: { type: 'middleware', handled: false }, syntheticException }
86
+ const additionalProperties: Record<string, any> = {
87
+ ...(contextData.sessionId !== undefined ? { $session_id: contextData.sessionId } : {}),
88
+ ...(contextData.properties || {}),
89
+ $response_status_code: res.statusCode,
90
+ }
44
91
 
45
92
  posthog.addPendingPromise(
46
- ErrorTracking.buildEventMessage(error, hint, distinctId, {
47
- $session_id: sessionId,
48
- $current_url: req.url,
49
- $request_method: req.method,
50
- $request_path: req.path,
51
- $user_agent: req.headers['user-agent'],
52
- $response_status_code: res.statusCode,
53
- $ip: req.headers['x-forwarded-for'] || req?.socket?.remoteAddress,
54
- }).then((msg) => {
93
+ ErrorTracking.buildEventMessage(error, hint, contextData.distinctId, additionalProperties).then((msg) => {
55
94
  posthog.capture(msg)
56
95
  })
57
96
  )
@@ -1,7 +1,9 @@
1
+ import type { IncomingHttpHeaders } from 'node:http'
1
2
  import { Observable, throwError } from 'rxjs'
2
3
  import { catchError } from 'rxjs/operators'
3
4
 
4
5
  import ErrorTracking from './error-tracking'
6
+ import { addProperty, getFirstHeaderValue, getPostHogTracingHeaderValues } from './tracing-headers'
5
7
  import { PostHogBackendClient } from '../client'
6
8
 
7
9
  // Local interfaces to avoid runtime dependency on @nestjs/common
@@ -32,10 +34,10 @@ export interface PostHogInterceptorOptions {
32
34
  captureExceptions?: boolean | ExceptionCaptureOptions
33
35
  }
34
36
 
35
- function getClientIp(headers: Record<string, any>, request: any): string | undefined {
36
- const forwarded = headers['x-forwarded-for']
37
+ function getClientIp(headers: IncomingHttpHeaders, request: any): string | undefined {
38
+ const forwarded = getFirstHeaderValue(headers['x-forwarded-for'])
37
39
  if (forwarded) {
38
- const ip = String(forwarded).split(',')[0].trim()
40
+ const ip = forwarded.split(',')[0].trim()
39
41
  if (ip) return ip
40
42
  }
41
43
  return request?.socket?.remoteAddress
@@ -71,22 +73,20 @@ export class PostHogInterceptor implements NestInterceptor {
71
73
  const request = httpHost.getRequest()
72
74
  const response = httpHost.getResponse()
73
75
 
74
- const headers = request?.headers ?? {}
75
- const sessionId: string | undefined = headers['x-posthog-session-id']
76
- const windowId: string | undefined = headers['x-posthog-window-id']
77
- const distinctId: string | undefined = headers['x-posthog-distinct-id']
76
+ const headers = (request?.headers ?? {}) as IncomingHttpHeaders
77
+ const { sessionId, distinctId } = getPostHogTracingHeaderValues(headers)
78
+
79
+ const properties: Record<string, any> = {}
80
+ addProperty(properties, '$current_url', request?.url)
81
+ addProperty(properties, '$request_method', request?.method)
82
+ addProperty(properties, '$request_path', request?.path ?? request?.url)
83
+ addProperty(properties, '$user_agent', getFirstHeaderValue(headers['user-agent']))
84
+ addProperty(properties, '$ip', getClientIp(headers, request))
78
85
 
79
86
  const contextData = {
80
- sessionId,
81
- distinctId,
82
- properties: {
83
- $current_url: request?.url,
84
- $request_method: request?.method,
85
- $request_path: request?.path ?? request?.url,
86
- $window_id: windowId,
87
- $user_agent: headers['user-agent'],
88
- $ip: getClientIp(headers, request),
89
- },
87
+ ...(sessionId !== undefined ? { sessionId } : {}),
88
+ ...(distinctId !== undefined ? { distinctId } : {}),
89
+ properties,
90
90
  }
91
91
 
92
92
  // Use enterContext so the context propagates through RxJS Observable
@@ -0,0 +1,65 @@
1
+ import type { IncomingHttpHeaders } from 'node:http'
2
+
3
+ const TRACING_HEADER_MAX_LENGTH = 1000
4
+ // Remove C0 controls, DEL, and C1 controls from PostHog tracing IDs only.
5
+ // eslint-disable-next-line no-control-regex
6
+ const TRACING_HEADER_CONTROL_CHARS_REGEX = /[\x00-\x1f\x7f-\x9f]/g
7
+
8
+ type HeaderValue = IncomingHttpHeaders[string]
9
+
10
+ export const POSTHOG_TRACING_HEADERS = {
11
+ sessionId: 'x-posthog-session-id',
12
+ distinctId: 'x-posthog-distinct-id',
13
+ } as const
14
+
15
+ export interface PostHogTracingHeaderValues {
16
+ sessionId?: string
17
+ distinctId?: string
18
+ }
19
+
20
+ export function addProperty(properties: Record<string, any>, key: string, value: unknown): void {
21
+ if (value !== undefined && value !== null && value !== '') {
22
+ properties[key] = value
23
+ }
24
+ }
25
+
26
+ export function getFirstHeaderValue(value: HeaderValue): string | undefined {
27
+ return Array.isArray(value) ? value[0] : value
28
+ }
29
+
30
+ export function sanitizeTracingHeaderValue(value: HeaderValue): string | undefined {
31
+ if (Array.isArray(value)) {
32
+ for (const item of value) {
33
+ const sanitized = sanitizeTracingHeaderValue(item)
34
+ if (sanitized !== undefined) {
35
+ return sanitized
36
+ }
37
+ }
38
+ return undefined
39
+ }
40
+
41
+ if (typeof value !== 'string') {
42
+ return undefined
43
+ }
44
+
45
+ const sanitized = value.replace(TRACING_HEADER_CONTROL_CHARS_REGEX, '').trim()
46
+ if (!sanitized) {
47
+ return undefined
48
+ }
49
+
50
+ return sanitized.length > TRACING_HEADER_MAX_LENGTH ? sanitized.slice(0, TRACING_HEADER_MAX_LENGTH) : sanitized
51
+ }
52
+
53
+ export function getPostHogTracingHeaderValues(headers?: IncomingHttpHeaders): PostHogTracingHeaderValues {
54
+ if (!headers) {
55
+ return {}
56
+ }
57
+
58
+ const sessionId = sanitizeTracingHeaderValue(headers[POSTHOG_TRACING_HEADERS.sessionId])
59
+ const distinctId = sanitizeTracingHeaderValue(headers[POSTHOG_TRACING_HEADERS.distinctId])
60
+
61
+ return {
62
+ ...(sessionId !== undefined ? { sessionId } : {}),
63
+ ...(distinctId !== undefined ? { distinctId } : {}),
64
+ }
65
+ }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '5.30.7'
1
+ export const version = '5.31.0'