@posthog/core 1.28.7 → 1.29.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.
- package/dist/cookie.d.ts +69 -0
- package/dist/cookie.d.ts.map +1 -0
- package/dist/cookie.js +137 -0
- package/dist/cookie.mjs +82 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -16
- package/dist/index.mjs +1 -0
- package/package.json +2 -2
- package/src/cookie.ts +173 -0
- package/src/index.ts +1 -0
package/dist/cookie.d.ts
ADDED
|
@@ -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
|
+
});
|
package/dist/cookie.mjs
ADDED
|
@@ -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/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,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,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,11 +89,11 @@ 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: ()=>
|
|
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: ()=>
|
|
93
|
-
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,
|
|
95
98
|
isNativeAsyncGzipError: ()=>_gzip__WEBPACK_IMPORTED_MODULE_1__.isNativeAsyncGzipError,
|
|
96
99
|
isNativeAsyncGzipReadError: ()=>_gzip__WEBPACK_IMPORTED_MODULE_1__.isNativeAsyncGzipReadError,
|
|
@@ -128,9 +131,33 @@ var __webpack_exports__ = {};
|
|
|
128
131
|
var _logs_logs_utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./logs/logs-utils");
|
|
129
132
|
var _logs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./logs");
|
|
130
133
|
var _vendor_uuidv7__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./vendor/uuidv7");
|
|
131
|
-
var
|
|
134
|
+
var _cookie__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./cookie");
|
|
135
|
+
var __WEBPACK_REEXPORT_OBJECT__ = {};
|
|
136
|
+
for(var __WEBPACK_IMPORT_KEY__ in _cookie__WEBPACK_IMPORTED_MODULE_7__)if ([
|
|
137
|
+
"toOtlpKeyValueList",
|
|
138
|
+
"PostHogLogs",
|
|
139
|
+
"isNativeAsyncGzipError",
|
|
140
|
+
"getOtlpSeverityText",
|
|
141
|
+
"isNativeAsyncGzipReadError",
|
|
142
|
+
"getFeatureFlagValue",
|
|
143
|
+
"uuidv7",
|
|
144
|
+
"getValidationError",
|
|
145
|
+
"ErrorTracking",
|
|
146
|
+
"gzipCompress",
|
|
147
|
+
"default",
|
|
148
|
+
"getRequirementsHint",
|
|
149
|
+
"getOtlpSeverityNumber",
|
|
150
|
+
"getLengthFromRules",
|
|
151
|
+
"buildOtlpLogsPayload",
|
|
152
|
+
"buildOtlpLogRecord",
|
|
153
|
+
"toOtlpAnyValue"
|
|
154
|
+
].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
|
|
155
|
+
return _cookie__WEBPACK_IMPORTED_MODULE_7__[key];
|
|
156
|
+
}).bind(0, __WEBPACK_IMPORT_KEY__);
|
|
157
|
+
__webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
|
|
158
|
+
var _posthog_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./posthog-core");
|
|
132
159
|
var __WEBPACK_REEXPORT_OBJECT__ = {};
|
|
133
|
-
for(var __WEBPACK_IMPORT_KEY__ in
|
|
160
|
+
for(var __WEBPACK_IMPORT_KEY__ in _posthog_core__WEBPACK_IMPORTED_MODULE_8__)if ([
|
|
134
161
|
"toOtlpKeyValueList",
|
|
135
162
|
"PostHogLogs",
|
|
136
163
|
"isNativeAsyncGzipError",
|
|
@@ -149,12 +176,12 @@ var __webpack_exports__ = {};
|
|
|
149
176
|
"buildOtlpLogRecord",
|
|
150
177
|
"toOtlpAnyValue"
|
|
151
178
|
].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
|
|
152
|
-
return
|
|
179
|
+
return _posthog_core__WEBPACK_IMPORTED_MODULE_8__[key];
|
|
153
180
|
}).bind(0, __WEBPACK_IMPORT_KEY__);
|
|
154
181
|
__webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
|
|
155
|
-
var
|
|
182
|
+
var _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./posthog-core-stateless");
|
|
156
183
|
var __WEBPACK_REEXPORT_OBJECT__ = {};
|
|
157
|
-
for(var __WEBPACK_IMPORT_KEY__ in
|
|
184
|
+
for(var __WEBPACK_IMPORT_KEY__ in _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_9__)if ([
|
|
158
185
|
"toOtlpKeyValueList",
|
|
159
186
|
"PostHogLogs",
|
|
160
187
|
"isNativeAsyncGzipError",
|
|
@@ -173,12 +200,12 @@ var __webpack_exports__ = {};
|
|
|
173
200
|
"buildOtlpLogRecord",
|
|
174
201
|
"toOtlpAnyValue"
|
|
175
202
|
].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
|
|
176
|
-
return
|
|
203
|
+
return _posthog_core_stateless__WEBPACK_IMPORTED_MODULE_9__[key];
|
|
177
204
|
}).bind(0, __WEBPACK_IMPORT_KEY__);
|
|
178
205
|
__webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
|
|
179
|
-
var
|
|
206
|
+
var _tracing_headers__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__("./tracing-headers");
|
|
180
207
|
var __WEBPACK_REEXPORT_OBJECT__ = {};
|
|
181
|
-
for(var __WEBPACK_IMPORT_KEY__ in
|
|
208
|
+
for(var __WEBPACK_IMPORT_KEY__ in _tracing_headers__WEBPACK_IMPORTED_MODULE_10__)if ([
|
|
182
209
|
"toOtlpKeyValueList",
|
|
183
210
|
"PostHogLogs",
|
|
184
211
|
"isNativeAsyncGzipError",
|
|
@@ -197,12 +224,12 @@ var __webpack_exports__ = {};
|
|
|
197
224
|
"buildOtlpLogRecord",
|
|
198
225
|
"toOtlpAnyValue"
|
|
199
226
|
].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
|
|
200
|
-
return
|
|
227
|
+
return _tracing_headers__WEBPACK_IMPORTED_MODULE_10__[key];
|
|
201
228
|
}).bind(0, __WEBPACK_IMPORT_KEY__);
|
|
202
229
|
__webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
|
|
203
|
-
var
|
|
230
|
+
var _types__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__("./types");
|
|
204
231
|
var __WEBPACK_REEXPORT_OBJECT__ = {};
|
|
205
|
-
for(var __WEBPACK_IMPORT_KEY__ in
|
|
232
|
+
for(var __WEBPACK_IMPORT_KEY__ in _types__WEBPACK_IMPORTED_MODULE_11__)if ([
|
|
206
233
|
"toOtlpKeyValueList",
|
|
207
234
|
"PostHogLogs",
|
|
208
235
|
"isNativeAsyncGzipError",
|
|
@@ -221,10 +248,10 @@ var __webpack_exports__ = {};
|
|
|
221
248
|
"buildOtlpLogRecord",
|
|
222
249
|
"toOtlpAnyValue"
|
|
223
250
|
].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = (function(key) {
|
|
224
|
-
return
|
|
251
|
+
return _types__WEBPACK_IMPORTED_MODULE_11__[key];
|
|
225
252
|
}).bind(0, __WEBPACK_IMPORT_KEY__);
|
|
226
253
|
__webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
|
|
227
|
-
var
|
|
254
|
+
var _surveys_validation__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__("./surveys/validation");
|
|
228
255
|
})();
|
|
229
256
|
exports.ErrorTracking = __webpack_exports__.ErrorTracking;
|
|
230
257
|
exports.PostHogLogs = __webpack_exports__.PostHogLogs;
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ 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";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.0",
|
|
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.
|
|
70
|
+
"@posthog/types": "1.373.3"
|
|
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/index.ts
CHANGED
|
@@ -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'
|