@posthog/core 1.28.7 → 1.29.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.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Minimal cookie-reading interface compatible with Next.js `cookies()`,
3
+ * `request.cookies`, and plain objects.
4
+ */
5
+ export interface CookieStore {
6
+ get(name: string): {
7
+ value: string;
8
+ } | undefined;
9
+ }
10
+ /**
11
+ * Adapts a raw `Cookie` header string into a {@link CookieStore}.
12
+ */
13
+ export declare function cookieStoreFromHeader(cookieHeader: string): CookieStore;
14
+ export interface PostHogCookieState {
15
+ distinctId: string;
16
+ isIdentified: boolean;
17
+ sessionId?: string;
18
+ deviceId?: string;
19
+ }
20
+ /**
21
+ * Returns the PostHog cookie name for the given API key.
22
+ *
23
+ * PostHog-js stores state in a cookie named `ph_<sanitized_token>_posthog`.
24
+ * The token is sanitized by replacing `+` with `PL`, `/` with `SL`, `=` with `EQ`.
25
+ *
26
+ * @param apiKey - The PostHog project API key
27
+ * @returns The cookie name string
28
+ */
29
+ export declare function getPostHogCookieName(apiKey: string): string;
30
+ /**
31
+ * Serializes an anonymous ID into the JSON format posthog-js expects.
32
+ *
33
+ * When `distinct_id === $device_id`, posthog-js treats the user as anonymous.
34
+ *
35
+ * @param anonymousId - The anonymous distinct ID to serialize
36
+ * @returns JSON string suitable for the PostHog cookie value
37
+ */
38
+ export declare function serializePostHogCookie(anonymousId: string): string;
39
+ /**
40
+ * Reads and parses the PostHog cookie from a cookie store.
41
+ *
42
+ * Compatible with Next.js `cookies()`, `request.cookies`, and any object
43
+ * with a `get(name)` method that returns `{ value: string } | undefined`.
44
+ */
45
+ export declare function readPostHogCookie(cookies: CookieStore, apiKey: string): PostHogCookieState | null;
46
+ /**
47
+ * Converts cookie state into PostHog properties (e.g. `$session_id`, `$device_id`).
48
+ */
49
+ export declare function cookieStateToProperties(state: PostHogCookieState | null): Record<string, string> | undefined;
50
+ /**
51
+ * Parses a PostHog cookie value and extracts identity information.
52
+ *
53
+ * The cookie value is a JSON object containing `distinct_id` and `$user_state`.
54
+ * A user is considered identified if `$user_state` is `'identified'`.
55
+ *
56
+ * @param cookieValue - The raw cookie string value
57
+ * @returns Parsed identity state, or null if the cookie is missing/invalid
58
+ */
59
+ export declare function parsePostHogCookie(cookieValue: string): PostHogCookieState | null;
60
+ export interface ConsentCookieConfig {
61
+ consent_persistence_name?: string | null;
62
+ opt_out_capturing_cookie_prefix?: string | null;
63
+ }
64
+ export declare function getConsentCookieName(apiKey: string, config?: ConsentCookieConfig): string;
65
+ export interface ConsentConfig extends ConsentCookieConfig {
66
+ opt_out_capturing_by_default?: boolean;
67
+ }
68
+ export declare function isOptedOut(cookies: CookieStore, apiKey: string, config?: ConsentConfig): boolean;
69
+ //# sourceMappingURL=cookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie.d.ts","sourceRoot":"","sources":["../src/cookie.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;CACjD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,WAAW,CAmBvE;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CASlE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAIjG;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAY5G;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAuBjF;AAED,MAAM,WAAW,mBAAmB;IAClC,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxC,+BAA+B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD;AAID,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAQzF;AAED,MAAM,WAAW,aAAc,SAAQ,mBAAmB;IACxD,4BAA4B,CAAC,EAAE,OAAO,CAAA;CACvC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAUhG"}
package/dist/cookie.js ADDED
@@ -0,0 +1,137 @@
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
+ getConsentCookieName: ()=>getConsentCookieName,
28
+ parsePostHogCookie: ()=>parsePostHogCookie,
29
+ isOptedOut: ()=>isOptedOut,
30
+ readPostHogCookie: ()=>readPostHogCookie,
31
+ serializePostHogCookie: ()=>serializePostHogCookie,
32
+ cookieStateToProperties: ()=>cookieStateToProperties,
33
+ getPostHogCookieName: ()=>getPostHogCookieName,
34
+ cookieStoreFromHeader: ()=>cookieStoreFromHeader
35
+ });
36
+ const index_js_namespaceObject = require("./utils/index.js");
37
+ const uuidv7_js_namespaceObject = require("./vendor/uuidv7.js");
38
+ const COOKIE_PREFIX = 'ph_';
39
+ const COOKIE_SUFFIX = '_posthog';
40
+ function cookieStoreFromHeader(cookieHeader) {
41
+ const cookies = {};
42
+ if (cookieHeader) for (const pair of cookieHeader.split(';')){
43
+ const [key, ...valueParts] = pair.trim().split('=');
44
+ if (key) {
45
+ const raw = valueParts.join('=').trim();
46
+ try {
47
+ cookies[key.trim()] = decodeURIComponent(raw);
48
+ } catch {
49
+ cookies[key.trim()] = raw;
50
+ }
51
+ }
52
+ }
53
+ return {
54
+ get: (name)=>name in cookies ? {
55
+ value: cookies[name]
56
+ } : void 0
57
+ };
58
+ }
59
+ function getPostHogCookieName(apiKey) {
60
+ const sanitized = apiKey.replace(/\+/g, 'PL').replace(/\//g, 'SL').replace(/=/g, 'EQ');
61
+ return `${COOKIE_PREFIX}${sanitized}${COOKIE_SUFFIX}`;
62
+ }
63
+ function serializePostHogCookie(anonymousId) {
64
+ const now = Date.now();
65
+ const sessionId = (0, uuidv7_js_namespaceObject.uuidv7)();
66
+ return JSON.stringify({
67
+ distinct_id: anonymousId,
68
+ $device_id: anonymousId,
69
+ $user_state: 'anonymous',
70
+ $sesid: [
71
+ now,
72
+ sessionId,
73
+ now
74
+ ]
75
+ });
76
+ }
77
+ function readPostHogCookie(cookies, apiKey) {
78
+ const cookieName = getPostHogCookieName(apiKey);
79
+ const cookie = cookies.get(cookieName);
80
+ return cookie ? parsePostHogCookie(cookie.value) : null;
81
+ }
82
+ function cookieStateToProperties(state) {
83
+ if (!state) return;
84
+ const props = {};
85
+ if (state.sessionId) props.$session_id = state.sessionId;
86
+ if (state.deviceId) props.$device_id = state.deviceId;
87
+ return Object.keys(props).length > 0 ? props : void 0;
88
+ }
89
+ function parsePostHogCookie(cookieValue) {
90
+ if (!cookieValue) return null;
91
+ try {
92
+ const parsed = JSON.parse(cookieValue);
93
+ if (!parsed || 'object' != typeof parsed || !parsed.distinct_id) return null;
94
+ const sesid = (0, index_js_namespaceObject.isArray)(parsed.$sesid) ? parsed.$sesid[1] : void 0;
95
+ return {
96
+ distinctId: String(parsed.distinct_id),
97
+ isIdentified: 'identified' === parsed.$user_state,
98
+ sessionId: 'string' == typeof sesid ? sesid : void 0,
99
+ deviceId: 'string' == typeof parsed.$device_id ? parsed.$device_id : void 0
100
+ };
101
+ } catch {
102
+ return null;
103
+ }
104
+ }
105
+ const CONSENT_PREFIX = '__ph_opt_in_out_';
106
+ function getConsentCookieName(apiKey, config) {
107
+ if (config?.consent_persistence_name) return config.consent_persistence_name;
108
+ if (config?.opt_out_capturing_cookie_prefix) return config.opt_out_capturing_cookie_prefix + apiKey;
109
+ return CONSENT_PREFIX + apiKey;
110
+ }
111
+ function isOptedOut(cookies, apiKey, config) {
112
+ const cookieName = getConsentCookieName(apiKey, config);
113
+ const cookie = cookies.get(cookieName);
114
+ if (cookie) return (0, index_js_namespaceObject.isNoLike)(cookie.value);
115
+ return config?.opt_out_capturing_by_default ?? false;
116
+ }
117
+ exports.cookieStateToProperties = __webpack_exports__.cookieStateToProperties;
118
+ exports.cookieStoreFromHeader = __webpack_exports__.cookieStoreFromHeader;
119
+ exports.getConsentCookieName = __webpack_exports__.getConsentCookieName;
120
+ exports.getPostHogCookieName = __webpack_exports__.getPostHogCookieName;
121
+ exports.isOptedOut = __webpack_exports__.isOptedOut;
122
+ exports.parsePostHogCookie = __webpack_exports__.parsePostHogCookie;
123
+ exports.readPostHogCookie = __webpack_exports__.readPostHogCookie;
124
+ exports.serializePostHogCookie = __webpack_exports__.serializePostHogCookie;
125
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
126
+ "cookieStateToProperties",
127
+ "cookieStoreFromHeader",
128
+ "getConsentCookieName",
129
+ "getPostHogCookieName",
130
+ "isOptedOut",
131
+ "parsePostHogCookie",
132
+ "readPostHogCookie",
133
+ "serializePostHogCookie"
134
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
135
+ Object.defineProperty(exports, '__esModule', {
136
+ value: true
137
+ });
@@ -0,0 +1,82 @@
1
+ import { isArray, isNoLike } from "./utils/index.mjs";
2
+ import { uuidv7 } from "./vendor/uuidv7.mjs";
3
+ const COOKIE_PREFIX = 'ph_';
4
+ const COOKIE_SUFFIX = '_posthog';
5
+ function cookieStoreFromHeader(cookieHeader) {
6
+ const cookies = {};
7
+ if (cookieHeader) for (const pair of cookieHeader.split(';')){
8
+ const [key, ...valueParts] = pair.trim().split('=');
9
+ if (key) {
10
+ const raw = valueParts.join('=').trim();
11
+ try {
12
+ cookies[key.trim()] = decodeURIComponent(raw);
13
+ } catch {
14
+ cookies[key.trim()] = raw;
15
+ }
16
+ }
17
+ }
18
+ return {
19
+ get: (name)=>name in cookies ? {
20
+ value: cookies[name]
21
+ } : void 0
22
+ };
23
+ }
24
+ function getPostHogCookieName(apiKey) {
25
+ const sanitized = apiKey.replace(/\+/g, 'PL').replace(/\//g, 'SL').replace(/=/g, 'EQ');
26
+ return `${COOKIE_PREFIX}${sanitized}${COOKIE_SUFFIX}`;
27
+ }
28
+ function serializePostHogCookie(anonymousId) {
29
+ const now = Date.now();
30
+ const sessionId = uuidv7();
31
+ return JSON.stringify({
32
+ distinct_id: anonymousId,
33
+ $device_id: anonymousId,
34
+ $user_state: 'anonymous',
35
+ $sesid: [
36
+ now,
37
+ sessionId,
38
+ now
39
+ ]
40
+ });
41
+ }
42
+ function readPostHogCookie(cookies, apiKey) {
43
+ const cookieName = getPostHogCookieName(apiKey);
44
+ const cookie = cookies.get(cookieName);
45
+ return cookie ? parsePostHogCookie(cookie.value) : null;
46
+ }
47
+ function cookieStateToProperties(state) {
48
+ if (!state) return;
49
+ const props = {};
50
+ if (state.sessionId) props.$session_id = state.sessionId;
51
+ if (state.deviceId) props.$device_id = state.deviceId;
52
+ return Object.keys(props).length > 0 ? props : void 0;
53
+ }
54
+ function parsePostHogCookie(cookieValue) {
55
+ if (!cookieValue) return null;
56
+ try {
57
+ const parsed = JSON.parse(cookieValue);
58
+ if (!parsed || 'object' != typeof parsed || !parsed.distinct_id) return null;
59
+ const sesid = isArray(parsed.$sesid) ? parsed.$sesid[1] : void 0;
60
+ return {
61
+ distinctId: String(parsed.distinct_id),
62
+ isIdentified: 'identified' === parsed.$user_state,
63
+ sessionId: 'string' == typeof sesid ? sesid : void 0,
64
+ deviceId: 'string' == typeof parsed.$device_id ? parsed.$device_id : void 0
65
+ };
66
+ } catch {
67
+ return null;
68
+ }
69
+ }
70
+ const CONSENT_PREFIX = '__ph_opt_in_out_';
71
+ function getConsentCookieName(apiKey, config) {
72
+ if (config?.consent_persistence_name) return config.consent_persistence_name;
73
+ if (config?.opt_out_capturing_cookie_prefix) return config.opt_out_capturing_cookie_prefix + apiKey;
74
+ return CONSENT_PREFIX + apiKey;
75
+ }
76
+ function isOptedOut(cookies, apiKey, config) {
77
+ const cookieName = getConsentCookieName(apiKey, config);
78
+ const cookie = cookies.get(cookieName);
79
+ if (cookie) return isNoLike(cookie.value);
80
+ return config?.opt_out_capturing_by_default ?? false;
81
+ }
82
+ export { cookieStateToProperties, cookieStoreFromHeader, getConsentCookieName, getPostHogCookieName, isOptedOut, parsePostHogCookie, readPostHogCookie, serializePostHogCookie };
package/dist/gzip.d.ts CHANGED
@@ -3,6 +3,8 @@
3
3
  * This API (as of 2025-05-07) is not available on React Native.
4
4
  */
5
5
  export declare function isGzipSupported(): boolean;
6
+ export declare const isGzipData: (body: unknown) => boolean;
7
+ export declare const isGzipRequest: (compression?: unknown, urlCompression?: unknown) => boolean;
6
8
  export declare const isNativeAsyncGzipReadError: (error: unknown) => boolean;
7
9
  export declare const isNativeAsyncGzipError: (error: unknown) => boolean;
8
10
  export type GzipCompressOptions = {
@@ -1 +1 @@
1
- {"version":3,"file":"gzip.d.ts","sourceRoot":"","sources":["../src/gzip.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAOzC;AAID,eAAO,MAAM,0BAA0B,GAAI,OAAO,OAAO,KAAG,OAQ3D,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,OAQvD,CAAA;AA0DD,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,UAAO,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAgCrH"}
1
+ {"version":3,"file":"gzip.d.ts","sourceRoot":"","sources":["../src/gzip.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAOzC;AAWD,eAAO,MAAM,UAAU,GAAI,MAAM,OAAO,KAAG,OAU1C,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,cAAc,OAAO,EAAE,iBAAiB,OAAO,KAAG,OAE/E,CAAA;AAED,eAAO,MAAM,0BAA0B,GAAI,OAAO,OAAO,KAAG,OAQ3D,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,OAQvD,CAAA;AA0DD,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,UAAO,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAgCrH"}
package/dist/gzip.js CHANGED
@@ -24,15 +24,28 @@ var __webpack_require__ = {};
24
24
  var __webpack_exports__ = {};
25
25
  __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
- gzipCompress: ()=>gzipCompress,
28
- isGzipSupported: ()=>isGzipSupported,
29
27
  isNativeAsyncGzipError: ()=>isNativeAsyncGzipError,
30
- isNativeAsyncGzipReadError: ()=>isNativeAsyncGzipReadError
28
+ isNativeAsyncGzipReadError: ()=>isNativeAsyncGzipReadError,
29
+ isGzipRequest: ()=>isGzipRequest,
30
+ isGzipSupported: ()=>isGzipSupported,
31
+ gzipCompress: ()=>gzipCompress,
32
+ isGzipData: ()=>isGzipData
31
33
  });
34
+ const external_types_js_namespaceObject = require("./types.js");
32
35
  function isGzipSupported() {
33
36
  return 'CompressionStream' in globalThis && 'TextEncoder' in globalThis && 'Response' in globalThis && 'function' == typeof Response.prototype.blob;
34
37
  }
35
38
  const NATIVE_GZIP_VALIDATION_ERROR = 'NativeGzipValidationError';
39
+ const GZIP_MAGIC_FIRST_BYTE = 0x1f;
40
+ const GZIP_MAGIC_SECOND_BYTE = 0x8b;
41
+ const GZIP_DEFLATE_METHOD = 0x08;
42
+ const hasGzipMagic = (bytes)=>bytes.length >= 2 && bytes[0] === GZIP_MAGIC_FIRST_BYTE && bytes[1] === GZIP_MAGIC_SECOND_BYTE;
43
+ const isGzipData = (body)=>{
44
+ if (body instanceof ArrayBuffer) return hasGzipMagic(new Uint8Array(body));
45
+ if (ArrayBuffer.isView(body)) return hasGzipMagic(new Uint8Array(body.buffer, body.byteOffset, body.byteLength));
46
+ return false;
47
+ };
48
+ const isGzipRequest = (compression, urlCompression)=>compression === external_types_js_namespaceObject.Compression.GZipJS || urlCompression === external_types_js_namespaceObject.Compression.GZipJS || 'gzip' === urlCompression;
36
49
  const isNativeAsyncGzipReadError = (error)=>{
37
50
  if (!error || 'object' != typeof error) return false;
38
51
  const name = 'name' in error ? String(error.name) : '';
@@ -68,7 +81,7 @@ const throwNativeGzipValidationError = (reason)=>{
68
81
  const validateNativeGzip = async (compressed, inputBytes)=>{
69
82
  if (compressed.size < 18) throwNativeGzipValidationError('too-short');
70
83
  const header = new Uint8Array(await compressed.slice(0, 10).arrayBuffer());
71
- if (0x1f !== header[0] || 0x8b !== header[1] || 0x08 !== header[2]) throwNativeGzipValidationError('invalid-header');
84
+ if (!hasGzipMagic(header) || header[2] !== GZIP_DEFLATE_METHOD) throwNativeGzipValidationError('invalid-header');
72
85
  const trailer = new DataView(await compressed.slice(compressed.size - 8).arrayBuffer());
73
86
  if (trailer.getUint32(0, true) !== crc32(inputBytes)) throwNativeGzipValidationError('invalid-crc');
74
87
  const inputSize = inputBytes.length >>> 0;
@@ -99,11 +112,15 @@ async function gzipCompress(input, isDebug = true, options) {
99
112
  }
100
113
  }
101
114
  exports.gzipCompress = __webpack_exports__.gzipCompress;
115
+ exports.isGzipData = __webpack_exports__.isGzipData;
116
+ exports.isGzipRequest = __webpack_exports__.isGzipRequest;
102
117
  exports.isGzipSupported = __webpack_exports__.isGzipSupported;
103
118
  exports.isNativeAsyncGzipError = __webpack_exports__.isNativeAsyncGzipError;
104
119
  exports.isNativeAsyncGzipReadError = __webpack_exports__.isNativeAsyncGzipReadError;
105
120
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
106
121
  "gzipCompress",
122
+ "isGzipData",
123
+ "isGzipRequest",
107
124
  "isGzipSupported",
108
125
  "isNativeAsyncGzipError",
109
126
  "isNativeAsyncGzipReadError"
package/dist/gzip.mjs CHANGED
@@ -1,7 +1,18 @@
1
+ import { Compression } from "./types.mjs";
1
2
  function isGzipSupported() {
2
3
  return 'CompressionStream' in globalThis && 'TextEncoder' in globalThis && 'Response' in globalThis && 'function' == typeof Response.prototype.blob;
3
4
  }
4
5
  const NATIVE_GZIP_VALIDATION_ERROR = 'NativeGzipValidationError';
6
+ const GZIP_MAGIC_FIRST_BYTE = 0x1f;
7
+ const GZIP_MAGIC_SECOND_BYTE = 0x8b;
8
+ const GZIP_DEFLATE_METHOD = 0x08;
9
+ const hasGzipMagic = (bytes)=>bytes.length >= 2 && bytes[0] === GZIP_MAGIC_FIRST_BYTE && bytes[1] === GZIP_MAGIC_SECOND_BYTE;
10
+ const isGzipData = (body)=>{
11
+ if (body instanceof ArrayBuffer) return hasGzipMagic(new Uint8Array(body));
12
+ if (ArrayBuffer.isView(body)) return hasGzipMagic(new Uint8Array(body.buffer, body.byteOffset, body.byteLength));
13
+ return false;
14
+ };
15
+ const isGzipRequest = (compression, urlCompression)=>compression === Compression.GZipJS || urlCompression === Compression.GZipJS || 'gzip' === urlCompression;
5
16
  const isNativeAsyncGzipReadError = (error)=>{
6
17
  if (!error || 'object' != typeof error) return false;
7
18
  const name = 'name' in error ? String(error.name) : '';
@@ -37,7 +48,7 @@ const throwNativeGzipValidationError = (reason)=>{
37
48
  const validateNativeGzip = async (compressed, inputBytes)=>{
38
49
  if (compressed.size < 18) throwNativeGzipValidationError('too-short');
39
50
  const header = new Uint8Array(await compressed.slice(0, 10).arrayBuffer());
40
- if (0x1f !== header[0] || 0x8b !== header[1] || 0x08 !== header[2]) throwNativeGzipValidationError('invalid-header');
51
+ if (!hasGzipMagic(header) || header[2] !== GZIP_DEFLATE_METHOD) throwNativeGzipValidationError('invalid-header');
41
52
  const trailer = new DataView(await compressed.slice(compressed.size - 8).arrayBuffer());
42
53
  if (trailer.getUint32(0, true) !== crc32(inputBytes)) throwNativeGzipValidationError('invalid-crc');
43
54
  const inputSize = inputBytes.length >>> 0;
@@ -67,4 +78,4 @@ async function gzipCompress(input, isDebug = true, options) {
67
78
  return null;
68
79
  }
69
80
  }
70
- export { gzipCompress, isGzipSupported, isNativeAsyncGzipError, isNativeAsyncGzipReadError };
81
+ export { gzipCompress, isGzipData, isGzipRequest, isGzipSupported, isNativeAsyncGzipError, isNativeAsyncGzipReadError };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { getFeatureFlagValue } from './featureFlagUtils';
2
- export { gzipCompress, isNativeAsyncGzipError, isNativeAsyncGzipReadError } from './gzip';
2
+ export { gzipCompress, isGzipData, isGzipRequest, isNativeAsyncGzipError, isNativeAsyncGzipReadError } from './gzip';
3
3
  export * from './utils';
4
4
  export * as ErrorTracking from './error-tracking';
5
5
  export { buildOtlpLogRecord, buildOtlpLogsPayload, getOtlpSeverityNumber, getOtlpSeverityText, toOtlpAnyValue, toOtlpKeyValueList, } from './logs/logs-utils';
@@ -7,6 +7,7 @@ export { PostHogLogs } from './logs';
7
7
  export type { BeforeSendLogFn, BufferedLogEntry, CaptureLogger, LogSdkContext, PostHogLogsConfig, ResolvedPostHogLogsConfig, } from './logs/types';
8
8
  export type { CaptureLogOptions, LogAttributeValue, LogAttributes, LogSeverityLevel } from './logs/types';
9
9
  export { uuidv7 } from './vendor/uuidv7';
10
+ export * from './cookie';
10
11
  export * from './posthog-core';
11
12
  export * from './posthog-core-stateless';
12
13
  export * from './tracing-headers';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAA;AACzF,cAAc,SAAS,CAAA;AACvB,OAAO,KAAK,aAAa,MAAM,kBAAkB,CAAA;AACjD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AACpC,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,cAAc,CAAA;AAIrB,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,SAAS,CAAA;AACvB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAA;AACpH,cAAc,SAAS,CAAA;AACvB,OAAO,KAAK,aAAa,MAAM,kBAAkB,CAAA;AACjD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AACpC,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,cAAc,CAAA;AAIrB,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,SAAS,CAAA;AACvB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  var __webpack_modules__ = {
3
+ "./cookie": function(module) {
4
+ module.exports = require("./cookie.js");
5
+ },
3
6
  "./error-tracking": function(module) {
4
7
  module.exports = require("./error-tracking/index.js");
5
8
  },
@@ -86,12 +89,14 @@ var __webpack_exports__ = {};
86
89
  buildOtlpLogRecord: ()=>_logs_logs_utils__WEBPACK_IMPORTED_MODULE_4__.buildOtlpLogRecord,
87
90
  buildOtlpLogsPayload: ()=>_logs_logs_utils__WEBPACK_IMPORTED_MODULE_4__.buildOtlpLogsPayload,
88
91
  getFeatureFlagValue: ()=>_featureFlagUtils__WEBPACK_IMPORTED_MODULE_0__.getFeatureFlagValue,
89
- getLengthFromRules: ()=>_surveys_validation__WEBPACK_IMPORTED_MODULE_11__.getLengthFromRules,
92
+ getLengthFromRules: ()=>_surveys_validation__WEBPACK_IMPORTED_MODULE_12__.getLengthFromRules,
90
93
  getOtlpSeverityNumber: ()=>_logs_logs_utils__WEBPACK_IMPORTED_MODULE_4__.getOtlpSeverityNumber,
91
94
  getOtlpSeverityText: ()=>_logs_logs_utils__WEBPACK_IMPORTED_MODULE_4__.getOtlpSeverityText,
92
- getRequirementsHint: ()=>_surveys_validation__WEBPACK_IMPORTED_MODULE_11__.getRequirementsHint,
93
- getValidationError: ()=>_surveys_validation__WEBPACK_IMPORTED_MODULE_11__.getValidationError,
95
+ getRequirementsHint: ()=>_surveys_validation__WEBPACK_IMPORTED_MODULE_12__.getRequirementsHint,
96
+ getValidationError: ()=>_surveys_validation__WEBPACK_IMPORTED_MODULE_12__.getValidationError,
94
97
  gzipCompress: ()=>_gzip__WEBPACK_IMPORTED_MODULE_1__.gzipCompress,
98
+ isGzipData: ()=>_gzip__WEBPACK_IMPORTED_MODULE_1__.isGzipData,
99
+ isGzipRequest: ()=>_gzip__WEBPACK_IMPORTED_MODULE_1__.isGzipRequest,
95
100
  isNativeAsyncGzipError: ()=>_gzip__WEBPACK_IMPORTED_MODULE_1__.isNativeAsyncGzipError,
96
101
  isNativeAsyncGzipReadError: ()=>_gzip__WEBPACK_IMPORTED_MODULE_1__.isNativeAsyncGzipReadError,
97
102
  toOtlpAnyValue: ()=>_logs_logs_utils__WEBPACK_IMPORTED_MODULE_4__.toOtlpAnyValue,
@@ -109,12 +114,14 @@ var __webpack_exports__ = {};
109
114
  "getOtlpSeverityText",
110
115
  "isNativeAsyncGzipReadError",
111
116
  "getFeatureFlagValue",
117
+ "isGzipRequest",
118
+ "gzipCompress",
112
119
  "uuidv7",
113
- "getValidationError",
114
120
  "ErrorTracking",
115
- "gzipCompress",
121
+ "getValidationError",
116
122
  "default",
117
123
  "getRequirementsHint",
124
+ "isGzipData",
118
125
  "getOtlpSeverityNumber",
119
126
  "getLengthFromRules",
120
127
  "buildOtlpLogsPayload",
@@ -128,103 +135,137 @@ var __webpack_exports__ = {};
128
135
  var _logs_logs_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./logs/logs-utils");
129
136
  var _logs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./logs");
130
137
  var _vendor_uuidv7__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./vendor/uuidv7");
131
- var _posthog_core__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./posthog-core");
138
+ var _cookie__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./cookie");
132
139
  var __WEBPACK_REEXPORT_OBJECT__ = {};
133
- for(var __WEBPACK_IMPORT_KEY__ in _posthog_core__WEBPACK_IMPORTED_MODULE_7__)if ([
140
+ for(var __WEBPACK_IMPORT_KEY__ in _cookie__WEBPACK_IMPORTED_MODULE_7__)if ([
134
141
  "toOtlpKeyValueList",
135
142
  "PostHogLogs",
136
143
  "isNativeAsyncGzipError",
137
144
  "getOtlpSeverityText",
138
145
  "isNativeAsyncGzipReadError",
139
146
  "getFeatureFlagValue",
147
+ "isGzipRequest",
148
+ "gzipCompress",
140
149
  "uuidv7",
141
- "getValidationError",
142
150
  "ErrorTracking",
143
- "gzipCompress",
151
+ "getValidationError",
144
152
  "default",
145
153
  "getRequirementsHint",
154
+ "isGzipData",
146
155
  "getOtlpSeverityNumber",
147
156
  "getLengthFromRules",
148
157
  "buildOtlpLogsPayload",
149
158
  "buildOtlpLogRecord",
150
159
  "toOtlpAnyValue"
151
160
  ].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
152
- return _posthog_core__WEBPACK_IMPORTED_MODULE_7__[key];
161
+ return _cookie__WEBPACK_IMPORTED_MODULE_7__[key];
153
162
  }).bind(0, __WEBPACK_IMPORT_KEY__);
154
163
  __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
155
- var _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./posthog-core-stateless");
164
+ var _posthog_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./posthog-core");
156
165
  var __WEBPACK_REEXPORT_OBJECT__ = {};
157
- for(var __WEBPACK_IMPORT_KEY__ in _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_8__)if ([
166
+ for(var __WEBPACK_IMPORT_KEY__ in _posthog_core__WEBPACK_IMPORTED_MODULE_8__)if ([
158
167
  "toOtlpKeyValueList",
159
168
  "PostHogLogs",
160
169
  "isNativeAsyncGzipError",
161
170
  "getOtlpSeverityText",
162
171
  "isNativeAsyncGzipReadError",
163
172
  "getFeatureFlagValue",
173
+ "isGzipRequest",
174
+ "gzipCompress",
164
175
  "uuidv7",
165
- "getValidationError",
166
176
  "ErrorTracking",
167
- "gzipCompress",
177
+ "getValidationError",
168
178
  "default",
169
179
  "getRequirementsHint",
180
+ "isGzipData",
170
181
  "getOtlpSeverityNumber",
171
182
  "getLengthFromRules",
172
183
  "buildOtlpLogsPayload",
173
184
  "buildOtlpLogRecord",
174
185
  "toOtlpAnyValue"
175
186
  ].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
176
- return _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_8__[key];
187
+ return _posthog_core__WEBPACK_IMPORTED_MODULE_8__[key];
177
188
  }).bind(0, __WEBPACK_IMPORT_KEY__);
178
189
  __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
179
- var _tracing_headers__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./tracing-headers");
190
+ var _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./posthog-core-stateless");
180
191
  var __WEBPACK_REEXPORT_OBJECT__ = {};
181
- for(var __WEBPACK_IMPORT_KEY__ in _tracing_headers__WEBPACK_IMPORTED_MODULE_9__)if ([
192
+ for(var __WEBPACK_IMPORT_KEY__ in _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_9__)if ([
182
193
  "toOtlpKeyValueList",
183
194
  "PostHogLogs",
184
195
  "isNativeAsyncGzipError",
185
196
  "getOtlpSeverityText",
186
197
  "isNativeAsyncGzipReadError",
187
198
  "getFeatureFlagValue",
199
+ "isGzipRequest",
200
+ "gzipCompress",
188
201
  "uuidv7",
189
- "getValidationError",
190
202
  "ErrorTracking",
191
- "gzipCompress",
203
+ "getValidationError",
192
204
  "default",
193
205
  "getRequirementsHint",
206
+ "isGzipData",
194
207
  "getOtlpSeverityNumber",
195
208
  "getLengthFromRules",
196
209
  "buildOtlpLogsPayload",
197
210
  "buildOtlpLogRecord",
198
211
  "toOtlpAnyValue"
199
212
  ].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
200
- return _tracing_headers__WEBPACK_IMPORTED_MODULE_9__[key];
213
+ return _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_9__[key];
201
214
  }).bind(0, __WEBPACK_IMPORT_KEY__);
202
215
  __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
203
- var _types__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__("./types");
216
+ var _tracing_headers__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__("./tracing-headers");
204
217
  var __WEBPACK_REEXPORT_OBJECT__ = {};
205
- for(var __WEBPACK_IMPORT_KEY__ in _types__WEBPACK_IMPORTED_MODULE_10__)if ([
218
+ for(var __WEBPACK_IMPORT_KEY__ in _tracing_headers__WEBPACK_IMPORTED_MODULE_10__)if ([
206
219
  "toOtlpKeyValueList",
207
220
  "PostHogLogs",
208
221
  "isNativeAsyncGzipError",
209
222
  "getOtlpSeverityText",
210
223
  "isNativeAsyncGzipReadError",
211
224
  "getFeatureFlagValue",
225
+ "isGzipRequest",
226
+ "gzipCompress",
212
227
  "uuidv7",
213
- "getValidationError",
214
228
  "ErrorTracking",
229
+ "getValidationError",
230
+ "default",
231
+ "getRequirementsHint",
232
+ "isGzipData",
233
+ "getOtlpSeverityNumber",
234
+ "getLengthFromRules",
235
+ "buildOtlpLogsPayload",
236
+ "buildOtlpLogRecord",
237
+ "toOtlpAnyValue"
238
+ ].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
239
+ return _tracing_headers__WEBPACK_IMPORTED_MODULE_10__[key];
240
+ }).bind(0, __WEBPACK_IMPORT_KEY__);
241
+ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
242
+ var _types__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__("./types");
243
+ var __WEBPACK_REEXPORT_OBJECT__ = {};
244
+ for(var __WEBPACK_IMPORT_KEY__ in _types__WEBPACK_IMPORTED_MODULE_11__)if ([
245
+ "toOtlpKeyValueList",
246
+ "PostHogLogs",
247
+ "isNativeAsyncGzipError",
248
+ "getOtlpSeverityText",
249
+ "isNativeAsyncGzipReadError",
250
+ "getFeatureFlagValue",
251
+ "isGzipRequest",
215
252
  "gzipCompress",
253
+ "uuidv7",
254
+ "ErrorTracking",
255
+ "getValidationError",
216
256
  "default",
217
257
  "getRequirementsHint",
258
+ "isGzipData",
218
259
  "getOtlpSeverityNumber",
219
260
  "getLengthFromRules",
220
261
  "buildOtlpLogsPayload",
221
262
  "buildOtlpLogRecord",
222
263
  "toOtlpAnyValue"
223
264
  ].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
224
- return _types__WEBPACK_IMPORTED_MODULE_10__[key];
265
+ return _types__WEBPACK_IMPORTED_MODULE_11__[key];
225
266
  }).bind(0, __WEBPACK_IMPORT_KEY__);
226
267
  __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
227
- var _surveys_validation__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__("./surveys/validation");
268
+ var _surveys_validation__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__("./surveys/validation");
228
269
  })();
229
270
  exports.ErrorTracking = __webpack_exports__.ErrorTracking;
230
271
  exports.PostHogLogs = __webpack_exports__.PostHogLogs;
@@ -237,6 +278,8 @@ exports.getOtlpSeverityText = __webpack_exports__.getOtlpSeverityText;
237
278
  exports.getRequirementsHint = __webpack_exports__.getRequirementsHint;
238
279
  exports.getValidationError = __webpack_exports__.getValidationError;
239
280
  exports.gzipCompress = __webpack_exports__.gzipCompress;
281
+ exports.isGzipData = __webpack_exports__.isGzipData;
282
+ exports.isGzipRequest = __webpack_exports__.isGzipRequest;
240
283
  exports.isNativeAsyncGzipError = __webpack_exports__.isNativeAsyncGzipError;
241
284
  exports.isNativeAsyncGzipReadError = __webpack_exports__.isNativeAsyncGzipReadError;
242
285
  exports.toOtlpAnyValue = __webpack_exports__.toOtlpAnyValue;
@@ -254,6 +297,8 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
254
297
  "getRequirementsHint",
255
298
  "getValidationError",
256
299
  "gzipCompress",
300
+ "isGzipData",
301
+ "isGzipRequest",
257
302
  "isNativeAsyncGzipError",
258
303
  "isNativeAsyncGzipReadError",
259
304
  "toOtlpAnyValue",
package/dist/index.mjs CHANGED
@@ -1,13 +1,14 @@
1
1
  import { getFeatureFlagValue } from "./featureFlagUtils.mjs";
2
- import { gzipCompress, isNativeAsyncGzipError, isNativeAsyncGzipReadError } from "./gzip.mjs";
2
+ import { gzipCompress, isGzipData, isGzipRequest, isNativeAsyncGzipError, isNativeAsyncGzipReadError } from "./gzip.mjs";
3
3
  import { buildOtlpLogRecord, buildOtlpLogsPayload, getOtlpSeverityNumber, getOtlpSeverityText, toOtlpAnyValue, toOtlpKeyValueList } from "./logs/logs-utils.mjs";
4
4
  import { PostHogLogs } from "./logs/index.mjs";
5
5
  import { uuidv7 } from "./vendor/uuidv7.mjs";
6
6
  import { getLengthFromRules, getRequirementsHint, getValidationError } from "./surveys/validation.mjs";
7
7
  export * from "./utils/index.mjs";
8
+ export * from "./cookie.mjs";
8
9
  export * from "./posthog-core.mjs";
9
10
  export * from "./posthog-core-stateless.mjs";
10
11
  export * from "./tracing-headers.mjs";
11
12
  export * from "./types.mjs";
12
13
  import * as __WEBPACK_EXTERNAL_MODULE__error_tracking_index_mjs_b3406d6f__ from "./error-tracking/index.mjs";
13
- export { __WEBPACK_EXTERNAL_MODULE__error_tracking_index_mjs_b3406d6f__ as ErrorTracking, PostHogLogs, buildOtlpLogRecord, buildOtlpLogsPayload, getFeatureFlagValue, getLengthFromRules, getOtlpSeverityNumber, getOtlpSeverityText, getRequirementsHint, getValidationError, gzipCompress, isNativeAsyncGzipError, isNativeAsyncGzipReadError, toOtlpAnyValue, toOtlpKeyValueList, uuidv7 };
14
+ export { __WEBPACK_EXTERNAL_MODULE__error_tracking_index_mjs_b3406d6f__ as ErrorTracking, PostHogLogs, buildOtlpLogRecord, buildOtlpLogsPayload, getFeatureFlagValue, getLengthFromRules, getOtlpSeverityNumber, getOtlpSeverityText, getRequirementsHint, getValidationError, gzipCompress, isGzipData, isGzipRequest, isNativeAsyncGzipError, isNativeAsyncGzipReadError, toOtlpAnyValue, toOtlpKeyValueList, uuidv7 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/core",
3
- "version": "1.28.7",
3
+ "version": "1.29.1",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -67,7 +67,7 @@
67
67
  }
68
68
  },
69
69
  "dependencies": {
70
- "@posthog/types": "1.373.2"
70
+ "@posthog/types": "1.373.4"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@rslib/core": "0.10.6",
package/src/cookie.ts ADDED
@@ -0,0 +1,173 @@
1
+ import { isArray, isNoLike } from './utils'
2
+ import { uuidv7 } from './vendor/uuidv7'
3
+
4
+ const COOKIE_PREFIX = 'ph_'
5
+ const COOKIE_SUFFIX = '_posthog'
6
+
7
+ /**
8
+ * Minimal cookie-reading interface compatible with Next.js `cookies()`,
9
+ * `request.cookies`, and plain objects.
10
+ */
11
+ export interface CookieStore {
12
+ get(name: string): { value: string } | undefined
13
+ }
14
+
15
+ /**
16
+ * Adapts a raw `Cookie` header string into a {@link CookieStore}.
17
+ */
18
+ export function cookieStoreFromHeader(cookieHeader: string): CookieStore {
19
+ const cookies: Record<string, string> = {}
20
+ if (cookieHeader) {
21
+ for (const pair of cookieHeader.split(';')) {
22
+ const [key, ...valueParts] = pair.trim().split('=')
23
+ if (key) {
24
+ const raw = valueParts.join('=').trim()
25
+ // `decodeURIComponent` throws `URIError` on malformed sequences (e.g. `%gg`).
26
+ // The Cookie header is externally controlled, so fall back to the raw value
27
+ // rather than crashing the request handler.
28
+ try {
29
+ cookies[key.trim()] = decodeURIComponent(raw)
30
+ } catch {
31
+ cookies[key.trim()] = raw
32
+ }
33
+ }
34
+ }
35
+ }
36
+ return { get: (name: string) => (name in cookies ? { value: cookies[name] } : undefined) }
37
+ }
38
+
39
+ export interface PostHogCookieState {
40
+ distinctId: string
41
+ isIdentified: boolean
42
+ sessionId?: string
43
+ deviceId?: string
44
+ }
45
+
46
+ /**
47
+ * Returns the PostHog cookie name for the given API key.
48
+ *
49
+ * PostHog-js stores state in a cookie named `ph_<sanitized_token>_posthog`.
50
+ * The token is sanitized by replacing `+` with `PL`, `/` with `SL`, `=` with `EQ`.
51
+ *
52
+ * @param apiKey - The PostHog project API key
53
+ * @returns The cookie name string
54
+ */
55
+ export function getPostHogCookieName(apiKey: string): string {
56
+ const sanitized = apiKey.replace(/\+/g, 'PL').replace(/\//g, 'SL').replace(/=/g, 'EQ')
57
+ return `${COOKIE_PREFIX}${sanitized}${COOKIE_SUFFIX}`
58
+ }
59
+
60
+ /**
61
+ * Serializes an anonymous ID into the JSON format posthog-js expects.
62
+ *
63
+ * When `distinct_id === $device_id`, posthog-js treats the user as anonymous.
64
+ *
65
+ * @param anonymousId - The anonymous distinct ID to serialize
66
+ * @returns JSON string suitable for the PostHog cookie value
67
+ */
68
+ export function serializePostHogCookie(anonymousId: string): string {
69
+ const now = Date.now()
70
+ const sessionId = uuidv7()
71
+ return JSON.stringify({
72
+ distinct_id: anonymousId,
73
+ $device_id: anonymousId,
74
+ $user_state: 'anonymous',
75
+ $sesid: [now, sessionId, now],
76
+ })
77
+ }
78
+
79
+ /**
80
+ * Reads and parses the PostHog cookie from a cookie store.
81
+ *
82
+ * Compatible with Next.js `cookies()`, `request.cookies`, and any object
83
+ * with a `get(name)` method that returns `{ value: string } | undefined`.
84
+ */
85
+ export function readPostHogCookie(cookies: CookieStore, apiKey: string): PostHogCookieState | null {
86
+ const cookieName = getPostHogCookieName(apiKey)
87
+ const cookie = cookies.get(cookieName)
88
+ return cookie ? parsePostHogCookie(cookie.value) : null
89
+ }
90
+
91
+ /**
92
+ * Converts cookie state into PostHog properties (e.g. `$session_id`, `$device_id`).
93
+ */
94
+ export function cookieStateToProperties(state: PostHogCookieState | null): Record<string, string> | undefined {
95
+ if (!state) {
96
+ return undefined
97
+ }
98
+ const props: Record<string, string> = {}
99
+ if (state.sessionId) {
100
+ props.$session_id = state.sessionId
101
+ }
102
+ if (state.deviceId) {
103
+ props.$device_id = state.deviceId
104
+ }
105
+ return Object.keys(props).length > 0 ? props : undefined
106
+ }
107
+
108
+ /**
109
+ * Parses a PostHog cookie value and extracts identity information.
110
+ *
111
+ * The cookie value is a JSON object containing `distinct_id` and `$user_state`.
112
+ * A user is considered identified if `$user_state` is `'identified'`.
113
+ *
114
+ * @param cookieValue - The raw cookie string value
115
+ * @returns Parsed identity state, or null if the cookie is missing/invalid
116
+ */
117
+ export function parsePostHogCookie(cookieValue: string): PostHogCookieState | null {
118
+ if (!cookieValue) {
119
+ return null
120
+ }
121
+
122
+ try {
123
+ const parsed = JSON.parse(cookieValue)
124
+ if (!parsed || typeof parsed !== 'object' || !parsed.distinct_id) {
125
+ return null
126
+ }
127
+
128
+ // $sesid is stored as [lastActivityTimestamp, sessionId, sessionStartTimestamp]
129
+ const sesid = isArray(parsed.$sesid) ? parsed.$sesid[1] : undefined
130
+
131
+ return {
132
+ distinctId: String(parsed.distinct_id),
133
+ isIdentified: parsed.$user_state === 'identified',
134
+ sessionId: typeof sesid === 'string' ? sesid : undefined,
135
+ deviceId: typeof parsed.$device_id === 'string' ? parsed.$device_id : undefined,
136
+ }
137
+ } catch {
138
+ return null
139
+ }
140
+ }
141
+
142
+ export interface ConsentCookieConfig {
143
+ consent_persistence_name?: string | null
144
+ opt_out_capturing_cookie_prefix?: string | null
145
+ }
146
+
147
+ const CONSENT_PREFIX = '__ph_opt_in_out_'
148
+
149
+ export function getConsentCookieName(apiKey: string, config?: ConsentCookieConfig): string {
150
+ if (config?.consent_persistence_name) {
151
+ return config.consent_persistence_name
152
+ }
153
+ if (config?.opt_out_capturing_cookie_prefix) {
154
+ return config.opt_out_capturing_cookie_prefix + apiKey
155
+ }
156
+ return CONSENT_PREFIX + apiKey
157
+ }
158
+
159
+ export interface ConsentConfig extends ConsentCookieConfig {
160
+ opt_out_capturing_by_default?: boolean
161
+ }
162
+
163
+ export function isOptedOut(cookies: CookieStore, apiKey: string, config?: ConsentConfig): boolean {
164
+ const cookieName = getConsentCookieName(apiKey, config)
165
+ const cookie = cookies.get(cookieName)
166
+
167
+ if (cookie) {
168
+ return isNoLike(cookie.value)
169
+ }
170
+
171
+ // No consent cookie means pending — defer to config
172
+ return config?.opt_out_capturing_by_default ?? false
173
+ }
package/src/gzip.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Compression } from './types'
2
+
1
3
  /**
2
4
  * Older browsers and some runtimes don't support this yet
3
5
  * This API (as of 2025-05-07) is not available on React Native.
@@ -12,6 +14,29 @@ export function isGzipSupported(): boolean {
12
14
  }
13
15
 
14
16
  const NATIVE_GZIP_VALIDATION_ERROR = 'NativeGzipValidationError'
17
+ const GZIP_MAGIC_FIRST_BYTE = 0x1f
18
+ const GZIP_MAGIC_SECOND_BYTE = 0x8b
19
+ const GZIP_DEFLATE_METHOD = 0x08
20
+
21
+ const hasGzipMagic = (bytes: Uint8Array): boolean => {
22
+ return bytes.length >= 2 && bytes[0] === GZIP_MAGIC_FIRST_BYTE && bytes[1] === GZIP_MAGIC_SECOND_BYTE
23
+ }
24
+
25
+ export const isGzipData = (body: unknown): boolean => {
26
+ if (body instanceof ArrayBuffer) {
27
+ return hasGzipMagic(new Uint8Array(body))
28
+ }
29
+
30
+ if (ArrayBuffer.isView(body)) {
31
+ return hasGzipMagic(new Uint8Array(body.buffer, body.byteOffset, body.byteLength))
32
+ }
33
+
34
+ return false
35
+ }
36
+
37
+ export const isGzipRequest = (compression?: unknown, urlCompression?: unknown): boolean => {
38
+ return compression === Compression.GZipJS || urlCompression === Compression.GZipJS || urlCompression === 'gzip'
39
+ }
15
40
 
16
41
  export const isNativeAsyncGzipReadError = (error: unknown): boolean => {
17
42
  if (!error || typeof error !== 'object') {
@@ -74,7 +99,7 @@ const validateNativeGzip = async (compressed: Blob, inputBytes: Uint8Array): Pro
74
99
  }
75
100
 
76
101
  const header = new Uint8Array(await compressed.slice(0, 10).arrayBuffer())
77
- if (header[0] !== 0x1f || header[1] !== 0x8b || header[2] !== 0x08) {
102
+ if (!hasGzipMagic(header) || header[2] !== GZIP_DEFLATE_METHOD) {
78
103
  throwNativeGzipValidationError('invalid-header')
79
104
  }
80
105
 
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { getFeatureFlagValue } from './featureFlagUtils'
2
- export { gzipCompress, isNativeAsyncGzipError, isNativeAsyncGzipReadError } from './gzip'
2
+ export { gzipCompress, isGzipData, isGzipRequest, isNativeAsyncGzipError, isNativeAsyncGzipReadError } from './gzip'
3
3
  export * from './utils'
4
4
  export * as ErrorTracking from './error-tracking'
5
5
  export {
@@ -24,6 +24,7 @@ export type {
24
24
  // packages to type their `captureLog` calls.
25
25
  export type { CaptureLogOptions, LogAttributeValue, LogAttributes, LogSeverityLevel } from './logs/types'
26
26
  export { uuidv7 } from './vendor/uuidv7'
27
+ export * from './cookie'
27
28
  export * from './posthog-core'
28
29
  export * from './posthog-core-stateless'
29
30
  export * from './tracing-headers'