@posthog/browser-common 0.0.0 → 0.2.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.
Files changed (97) hide show
  1. package/README.md +114 -28
  2. package/dist/client.d.ts +136 -0
  3. package/dist/client.js +18 -0
  4. package/dist/client.mjs +0 -0
  5. package/dist/config.d.ts +9 -0
  6. package/dist/config.js +43 -0
  7. package/dist/config.mjs +9 -0
  8. package/dist/constants.d.ts +3 -0
  9. package/dist/constants.js +44 -0
  10. package/dist/constants.mjs +4 -0
  11. package/dist/disposable.d.ts +13 -0
  12. package/dist/disposable.js +18 -0
  13. package/dist/disposable.mjs +0 -0
  14. package/dist/extension.d.ts +45 -0
  15. package/dist/extension.js +18 -0
  16. package/dist/extension.mjs +0 -0
  17. package/dist/index.d.ts +11 -0
  18. package/dist/index.js +36 -0
  19. package/dist/index.mjs +2 -0
  20. package/dist/persistence.d.ts +24 -0
  21. package/dist/persistence.js +18 -0
  22. package/dist/persistence.mjs +0 -0
  23. package/dist/pubsub.d.ts +28 -0
  24. package/dist/pubsub.js +67 -0
  25. package/dist/pubsub.mjs +33 -0
  26. package/dist/token.d.ts +21 -0
  27. package/dist/token.js +18 -0
  28. package/dist/token.mjs +0 -0
  29. package/dist/utils/array-at-polyfill.d.ts +1 -0
  30. package/dist/utils/array-at-polyfill.js +16 -0
  31. package/dist/utils/array-at-polyfill.mjs +11 -0
  32. package/dist/utils/autocapture-utils.d.ts +23 -0
  33. package/dist/utils/autocapture-utils.js +479 -0
  34. package/dist/utils/autocapture-utils.mjs +385 -0
  35. package/dist/utils/blocked-uas.d.ts +17 -0
  36. package/dist/utils/blocked-uas.js +54 -0
  37. package/dist/utils/blocked-uas.mjs +14 -0
  38. package/dist/utils/cookie-utils.d.ts +1 -0
  39. package/dist/utils/cookie-utils.js +49 -0
  40. package/dist/utils/cookie-utils.mjs +15 -0
  41. package/dist/utils/device-model-utils.d.ts +8 -0
  42. package/dist/utils/device-model-utils.js +52 -0
  43. package/dist/utils/device-model-utils.mjs +18 -0
  44. package/dist/utils/element-utils.d.ts +5 -0
  45. package/dist/utils/element-utils.js +67 -0
  46. package/dist/utils/element-utils.mjs +21 -0
  47. package/dist/utils/elements-chain-utils.d.ts +4 -0
  48. package/dist/utils/elements-chain-utils.js +79 -0
  49. package/dist/utils/elements-chain-utils.mjs +36 -0
  50. package/dist/utils/encode-utils.d.ts +8 -0
  51. package/dist/utils/encode-utils.js +39 -0
  52. package/dist/utils/encode-utils.mjs +5 -0
  53. package/dist/utils/event-utils.d.ts +24 -0
  54. package/dist/utils/event-utils.js +344 -0
  55. package/dist/utils/event-utils.mjs +246 -0
  56. package/dist/utils/general-utils.d.ts +30 -0
  57. package/dist/utils/general-utils.js +191 -0
  58. package/dist/utils/general-utils.mjs +118 -0
  59. package/dist/utils/globals.d.ts +25 -0
  60. package/dist/utils/globals.js +75 -0
  61. package/dist/utils/globals.mjs +14 -0
  62. package/dist/utils/logger.d.ts +16 -0
  63. package/dist/utils/logger.js +83 -0
  64. package/dist/utils/logger.mjs +36 -0
  65. package/dist/utils/matcher-utils.d.ts +3 -0
  66. package/dist/utils/matcher-utils.js +63 -0
  67. package/dist/utils/matcher-utils.mjs +26 -0
  68. package/dist/utils/property-utils.d.ts +23 -0
  69. package/dist/utils/property-utils.js +108 -0
  70. package/dist/utils/property-utils.mjs +65 -0
  71. package/dist/utils/prototype-utils.d.ts +7 -0
  72. package/dist/utils/prototype-utils.js +64 -0
  73. package/dist/utils/prototype-utils.mjs +27 -0
  74. package/dist/utils/regex-utils.d.ts +2 -0
  75. package/dist/utils/regex-utils.js +54 -0
  76. package/dist/utils/regex-utils.mjs +17 -0
  77. package/dist/utils/request-utils.d.ts +15 -0
  78. package/dist/utils/request-utils.js +153 -0
  79. package/dist/utils/request-utils.mjs +95 -0
  80. package/dist/utils/simple-event-emitter.d.ts +5 -0
  81. package/dist/utils/simple-event-emitter.js +51 -0
  82. package/dist/utils/simple-event-emitter.mjs +17 -0
  83. package/dist/utils/stylesheet-loader.d.ts +7 -0
  84. package/dist/utils/stylesheet-loader.js +53 -0
  85. package/dist/utils/stylesheet-loader.mjs +19 -0
  86. package/dist/utils/type-utils.d.ts +2 -0
  87. package/dist/utils/type-utils.js +41 -0
  88. package/dist/utils/type-utils.mjs +4 -0
  89. package/dist/utils/url-targeting-utils.d.ts +28 -0
  90. package/dist/utils/url-targeting-utils.js +56 -0
  91. package/dist/utils/url-targeting-utils.mjs +19 -0
  92. package/dist/utils/uuidv7.d.ts +43 -0
  93. package/dist/utils/uuidv7.js +172 -0
  94. package/dist/utils/uuidv7.js.LICENSE.txt +9 -0
  95. package/dist/utils/uuidv7.mjs +132 -0
  96. package/dist/utils/uuidv7.mjs.LICENSE.txt +9 -0
  97. package/package.json +79 -8
package/README.md CHANGED
@@ -1,45 +1,131 @@
1
1
  # @posthog/browser-common
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
3
+ Internal shared browser utilities and extension primitives for PostHog JavaScript
4
+ SDKs. This package is published so unbundled SDK outputs can resolve it at
5
+ runtime, but it is not a public API surface and does not provide compatibility
6
+ guarantees outside PostHog SDK packages.
4
7
 
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
8
+ The shared extension contract includes the interface an extension implements
9
+ (`Extension`), the host capabilities it is handed (`Client`), and small shared
10
+ runtime primitives such as `Publisher`.
6
11
 
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
12
+ An extension written against this contract runs unchanged across major versions of the web SDK:
8
13
 
9
- ## Purpose
14
+ - **v1** is synchronous; extensions are registered statically.
15
+ - **v2** is asynchronous; extensions are loaded dynamically.
10
16
 
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@posthog/browser-common`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
17
+ Each SDK provides a _client adapter_ that implements `Client` over its own
18
+ internals, so extension code never depends on a specific SDK.
15
19
 
16
- ## What is OIDC Trusted Publishing?
20
+ ## Concepts
17
21
 
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
22
+ ### `Extension`
19
23
 
20
- ## Setup Instructions
24
+ What you implement. The host calls only `setup` and `dispose`:
21
25
 
22
- To properly configure OIDC trusted publishing for this package:
26
+ ```ts
27
+ import type { Disposable, Extension } from '@posthog/browser-common'
23
28
 
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
29
+ export function webContext(): Extension {
30
+ let removeProperties: Disposable | undefined
28
31
 
29
- ## DO NOT USE THIS PACKAGE
32
+ return {
33
+ name: 'webContext',
34
+ setup(client) {
35
+ removeProperties = client.registerDynamicEventProperties(() => ({
36
+ $current_url: window.location.href,
37
+ }))
38
+ },
39
+ dispose() {
40
+ removeProperties?.dispose()
41
+ },
42
+ }
43
+ }
44
+ ```
30
45
 
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
46
+ `setup(client)` may be async (read async state before you're ready); `dispose()`
47
+ may be async (final flush). Static config the app sets goes in your constructor,
48
+ not on the `Client`.
36
49
 
37
- ## More Information
50
+ Anything in `setup` that returns a `Disposable` must be held by the extension
51
+ and disposed in `dispose()`.
38
52
 
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
53
+ ### `Client`
42
54
 
43
- ---
55
+ What an extension is given in `setup` — the host's capability surface:
44
56
 
45
- **Maintained for OIDC setup purposes only**
57
+ - **identity & session** (synchronous reads): `distinctId`, `anonymousId`, `groups`, `session`
58
+ - **events**: `capture(...)`, `registerDynamicEventProperties(...)` (contribute properties), `onEvent(...)` (observe)
59
+ - **transport**: `apiRequest(path, init?)`
60
+ - **server config**: `getRemoteConfig()` (current), `onRemoteConfig(...)` (changes)
61
+ - **lifecycle**: `onNewSession(...)`
62
+ - **registry**: `getExtension(token)`
63
+ - **storage & logging**: `kv`, `logger`
64
+
65
+ Synchronous members are always-ready in-memory reads; everything that does I/O
66
+ or waits for readiness (`capture`, `apiRequest`, `kv`, `getRemoteConfig`) is
67
+ asynchronous.
68
+
69
+ ### `Publisher`
70
+
71
+ Use `Publisher<T>` when an extension provides its own event stream to other
72
+ extensions or to app-facing controls. Keep the publisher private, expose only its
73
+ `listener`, and dispose it when the extension is torn down:
74
+
75
+ ```ts
76
+ import { Publisher, type Listener } from '@posthog/browser-common'
77
+
78
+ const changes = new Publisher<FeatureFlagsChange>()
79
+
80
+ export const onChange: Listener<FeatureFlagsChange> = changes.listener
81
+
82
+ changes.publish({ flag: 'beta-ui', value: true })
83
+ changes.dispose()
84
+ ```
85
+
86
+ ## Cross-extension dependencies
87
+
88
+ Extensions depend on one another through tokens, never implementation imports:
89
+
90
+ ```ts
91
+ import { FeatureFlags } from './feature-flags/token'
92
+
93
+ const flags = client.getExtension(FeatureFlags) // FeatureFlagsExtension | undefined
94
+ if (flags && (await flags.getFeatureFlag('beta-ui'))) {
95
+ /* … */
96
+ }
97
+ ```
98
+
99
+ A token is implementation-free, so importing it never pulls the provider's code
100
+ into your bundle — each extension stays independently tree-shakable and lazily
101
+ loadable. An extension that provides a capability declares its token(s) in
102
+ `provides`.
103
+
104
+ ## Utilities
105
+
106
+ Reusable browser utilities are exposed through `utils/*` subpaths, but they are
107
+ intentionally not re-exported from the package root or a utility barrel. Import
108
+ the exact file you need so lazy extension bundles do not pull in unrelated
109
+ helpers:
110
+
111
+ ```ts
112
+ import { createLogger } from '@posthog/browser-common/utils/logger'
113
+ import { formDataToQuery } from '@posthog/browser-common/utils/request-utils'
114
+ ```
115
+
116
+ ## Authoring
117
+
118
+ See the **`develop-extension`** skill
119
+ ([`.agents/skills/develop-extension/SKILL.md`](./.agents/skills/develop-extension/SKILL.md))
120
+ for the full guide: the capability cheatsheet, the rules (enrichers are
121
+ synchronous, dispose your disposables, design for asynchronous readiness,
122
+ cross-extension state goes through `getExtension`, not shared storage), and the
123
+ v1 → `Client` porting map.
124
+
125
+ ## Status
126
+
127
+ Early and internal. The package currently defines the extension contract, the
128
+ shared `Publisher` helper, and directly imported browser utilities under
129
+ `utils/*` subpaths. Additional shared runtime helpers — key-value stores, the
130
+ registry implementation, and a test `Client` — will land alongside the first
131
+ ported extension.
@@ -0,0 +1,136 @@
1
+ import type { Logger } from '@posthog/core';
2
+ import type { Disposable } from './disposable';
3
+ import type { KeyValueStore } from './persistence';
4
+ import type { Listener } from './pubsub';
5
+ import type { ExtensionToken } from './token';
6
+ /** The current session, stamped on events to tie them to a session and a browser tab. */
7
+ export interface SessionContext {
8
+ /** The stable session identifier attached to events captured during this session. */
9
+ sessionId: string;
10
+ /** The logical browser tab/window identifier attached alongside the session id. */
11
+ windowId: string;
12
+ /** When the session started, as a Unix timestamp in milliseconds. */
13
+ sessionStartTimestamp: number;
14
+ }
15
+ /** Why a new session started (a `reset` also starts a new session). */
16
+ export type NewSessionReason = 'initial' | 'reset' | 'idleTimeout' | 'maxLength' | 'crossTabAdoption';
17
+ /** Details emitted when the client starts or adopts a new session. */
18
+ export interface NewSessionInfo extends SessionContext {
19
+ /** The condition that caused this session to begin. */
20
+ reason: NewSessionReason;
21
+ }
22
+ /** A captured event, as observed by `onEvent`. */
23
+ export interface CapturedEventInfo {
24
+ /** The event name supplied to {@link Client.capture}. */
25
+ event: string;
26
+ /** The final event properties after client defaults and dynamic properties are applied. */
27
+ properties: Record<string, unknown>;
28
+ }
29
+ /** Per-call capture overrides, mirroring the client's public capture options. */
30
+ export interface CaptureOptions {
31
+ /** Override the event timestamp sent to PostHog. */
32
+ timestamp?: Date;
33
+ /** Override the event UUID used for de-duplication. */
34
+ uuid?: string;
35
+ /** Person properties to set, emitted as `$set`. */
36
+ set?: Record<string, unknown>;
37
+ /** Person properties to set if unset, emitted as `$set_once`. */
38
+ setOnce?: Record<string, unknown>;
39
+ }
40
+ /** A minimal response from {@link Client.apiRequest}. */
41
+ export interface ApiResponse {
42
+ /** Whether the request completed with a 2xx status, or was queued for best-effort unload transport. */
43
+ ok: boolean;
44
+ /** The HTTP status code returned by the transport, or a client-defined best-effort status for unload sends. */
45
+ status: number;
46
+ /** Parse the response body as JSON; may be unavailable for best-effort unload requests. */
47
+ json(): Promise<unknown>;
48
+ /** Read the response body as text; may be unavailable for best-effort unload requests. */
49
+ text(): Promise<string>;
50
+ }
51
+ /** Options for sending a request through {@link Client.apiRequest}. */
52
+ export interface ApiRequestInit {
53
+ /** HTTP method to use; defaults to the client's normal request method for the endpoint. */
54
+ method?: 'GET' | 'POST';
55
+ /** JSON-serialized by the client. */
56
+ body?: unknown;
57
+ /** Query string parameters appended to the request URL. */
58
+ query?: Record<string, string>;
59
+ /**
60
+ * Mark this as a teardown send (pagehide / shutdown): the client picks the
61
+ * most reliable fire-and-forget transport available — `sendBeacon`, fetch
62
+ * `keepalive`, or sync XHR. The response is best-effort: `.json()` may be
63
+ * unusable (e.g. `sendBeacon` only reports "queued"), so callers must not
64
+ * depend on it.
65
+ */
66
+ unload?: boolean;
67
+ /** Abort the request if it does not complete within this many milliseconds. */
68
+ timeoutMs?: number;
69
+ }
70
+ /**
71
+ * Server-provided configuration, as returned by the remote config response
72
+ * (sampling rates, suppression rules, feature enablement, quotas, …). A loose
73
+ * record by design — each extension reads only the keys it owns.
74
+ */
75
+ export type RemoteConfig = Record<string, unknown>;
76
+ /**
77
+ * The host SDK's capability surface as seen by an extension — the client an
78
+ * extension is handed in `setup`. Each SDK (v1, v2) provides it as a client
79
+ * adapter over its own internals.
80
+ *
81
+ * Synchronous members are always-ready in-memory reads (identity, session);
82
+ * asynchronous members do I/O or wait for something to become ready
83
+ * (`capture`, `apiRequest`, `kv`, `getRemoteConfig`).
84
+ */
85
+ export interface Client {
86
+ /** The id events are currently attributed to — the anonymous id, or the identified user's id after `identify`. */
87
+ readonly distinctId: string;
88
+ /** The anonymous device id; used before `identify` and carried on identify events as `$anon_distinct_id`. */
89
+ readonly anonymousId: string;
90
+ /** Active group memberships (group type → group key), attached to events as `$groups`. */
91
+ readonly groups: Record<string, string>;
92
+ /** The current session, created on first read if needed; reading does not extend or rotate it. */
93
+ readonly session: SessionContext;
94
+ /** Records an analytics event through the client's normal pipeline. */
95
+ capture(event: string, properties?: Record<string, unknown> | null, options?: CaptureOptions): Promise<void>;
96
+ /**
97
+ * Registers a producer of properties merged into every captured event.
98
+ * Returns a {@link Disposable} that removes it; an extension disposes it in
99
+ * its own `dispose`. May be called more than once. The producer runs inline
100
+ * during event build, so it must be cheap and synchronous; it may return
101
+ * different properties each time (e.g. the current URL), and is recomputed
102
+ * per event rather than stored.
103
+ */
104
+ registerDynamicEventProperties(producer: () => Record<string, unknown>): Disposable;
105
+ /**
106
+ * Sends a request to a PostHog endpoint; the client owns auth, headers, and
107
+ * transport (fetch / XHR / keepalive). `path` is relative to the configured
108
+ * API host, e.g. `/s/`, `/flags/`, `/api/surveys/`.
109
+ */
110
+ apiRequest(path: string, init?: ApiRequestInit): Promise<ApiResponse>;
111
+ /**
112
+ * Resolves with the client's remote config once available, or `undefined`
113
+ * if the fetch failed (never rejects, never hangs).
114
+ * Re-readable: each call resolves with the current config, awaiting the
115
+ * first fetch if none has landed. `await` it in `setup` to block until
116
+ * config is known, or `.then()` it to reconfigure once it arrives; later
117
+ * changes arrive via `onRemoteConfig`.
118
+ */
119
+ getRemoteConfig(): Promise<RemoteConfig | undefined>;
120
+ /** Fires when server-provided config arrives or changes. */
121
+ readonly onRemoteConfig: Listener<RemoteConfig>;
122
+ /** Fires for every captured event — hot path, keep handlers cheap and synchronous. */
123
+ readonly onEvent: Listener<CapturedEventInfo>;
124
+ /** Fires when a new session starts, including on reset (discriminate via `reason`). */
125
+ readonly onNewSession: Listener<NewSessionInfo>;
126
+ /**
127
+ * Resolves another registered extension by a capability token it provides, or
128
+ * `undefined` if nothing registered provides it (not installed, or not loaded
129
+ * yet). Lets one extension use another without importing its implementation.
130
+ */
131
+ getExtension<T>(token: ExtensionToken<T>): T | undefined;
132
+ /** Async key-value storage scoped to this client instance and extension. */
133
+ readonly kv: KeyValueStore;
134
+ /** Logger that follows the host client's debug/noise policy. */
135
+ readonly logger: Logger;
136
+ }
package/dist/client.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.r = (exports1)=>{
5
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
6
+ value: 'Module'
7
+ });
8
+ Object.defineProperty(exports1, '__esModule', {
9
+ value: true
10
+ });
11
+ };
12
+ })();
13
+ var __webpack_exports__ = {};
14
+ __webpack_require__.r(__webpack_exports__);
15
+ for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
16
+ Object.defineProperty(exports, '__esModule', {
17
+ value: true
18
+ });
File without changes
@@ -0,0 +1,9 @@
1
+ type SDKDistChannel = 'npm' | 'cdn';
2
+ declare const Config: {
3
+ DEBUG: boolean;
4
+ LIB_VERSION: string;
5
+ LIB_NAME: string;
6
+ SDK_DIST_CHANNEL?: SDKDistChannel;
7
+ JS_SDK_VERSION: string;
8
+ };
9
+ export default Config;
package/dist/config.js ADDED
@@ -0,0 +1,43 @@
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
+ default: ()=>__WEBPACK_DEFAULT_EXPORT__
28
+ });
29
+ const packageVersion = "0.2.0";
30
+ const Config = {
31
+ DEBUG: false,
32
+ LIB_VERSION: packageVersion,
33
+ LIB_NAME: 'browser-common',
34
+ JS_SDK_VERSION: packageVersion
35
+ };
36
+ const __WEBPACK_DEFAULT_EXPORT__ = Config;
37
+ exports["default"] = __webpack_exports__["default"];
38
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
39
+ "default"
40
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
41
+ Object.defineProperty(exports, '__esModule', {
42
+ value: true
43
+ });
@@ -0,0 +1,9 @@
1
+ const packageVersion = "0.2.0";
2
+ const Config = {
3
+ DEBUG: false,
4
+ LIB_VERSION: packageVersion,
5
+ LIB_NAME: 'browser-common',
6
+ JS_SDK_VERSION: packageVersion
7
+ };
8
+ const config = Config;
9
+ export { config as default };
@@ -0,0 +1,3 @@
1
+ export declare const TOOLBAR_ID = "__POSTHOG_TOOLBAR__";
2
+ export declare const TOOLBAR_CONTAINER_CLASS = "toolbar-global-fade-container";
3
+ export declare const SDK_DIST_CHANNEL = "$sdk_dist_channel";
@@ -0,0 +1,44 @@
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
+ SDK_DIST_CHANNEL: ()=>SDK_DIST_CHANNEL,
28
+ TOOLBAR_CONTAINER_CLASS: ()=>TOOLBAR_CONTAINER_CLASS,
29
+ TOOLBAR_ID: ()=>TOOLBAR_ID
30
+ });
31
+ const TOOLBAR_ID = '__POSTHOG_TOOLBAR__';
32
+ const TOOLBAR_CONTAINER_CLASS = 'toolbar-global-fade-container';
33
+ const SDK_DIST_CHANNEL = '$sdk_dist_channel';
34
+ exports.SDK_DIST_CHANNEL = __webpack_exports__.SDK_DIST_CHANNEL;
35
+ exports.TOOLBAR_CONTAINER_CLASS = __webpack_exports__.TOOLBAR_CONTAINER_CLASS;
36
+ exports.TOOLBAR_ID = __webpack_exports__.TOOLBAR_ID;
37
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
38
+ "SDK_DIST_CHANNEL",
39
+ "TOOLBAR_CONTAINER_CLASS",
40
+ "TOOLBAR_ID"
41
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
42
+ Object.defineProperty(exports, '__esModule', {
43
+ value: true
44
+ });
@@ -0,0 +1,4 @@
1
+ const TOOLBAR_ID = '__POSTHOG_TOOLBAR__';
2
+ const TOOLBAR_CONTAINER_CLASS = 'toolbar-global-fade-container';
3
+ const SDK_DIST_CHANNEL = '$sdk_dist_channel';
4
+ export { SDK_DIST_CHANNEL, TOOLBAR_CONTAINER_CLASS, TOOLBAR_ID };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Something with an async-capable teardown. `dispose` may be async so
3
+ * teardown can do final work — e.g. a last flush of buffered data — that the
4
+ * client can await before it finishes shutting down.
5
+ */
6
+ export interface Disposable {
7
+ /**
8
+ * Release resources owned by this object. Implementations should be
9
+ * idempotent so callers can safely dispose during both extension teardown
10
+ * and client shutdown.
11
+ */
12
+ dispose(): void | Promise<void>;
13
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.r = (exports1)=>{
5
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
6
+ value: 'Module'
7
+ });
8
+ Object.defineProperty(exports1, '__esModule', {
9
+ value: true
10
+ });
11
+ };
12
+ })();
13
+ var __webpack_exports__ = {};
14
+ __webpack_require__.r(__webpack_exports__);
15
+ for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
16
+ Object.defineProperty(exports, '__esModule', {
17
+ value: true
18
+ });
File without changes
@@ -0,0 +1,45 @@
1
+ import type { Disposable } from './disposable';
2
+ import type { Client } from './client';
3
+ import type { ExtensionToken } from './token';
4
+ /**
5
+ * A shared browser extension. The client calls only two things: `setup(client)`
6
+ * to start it and `dispose()` (from {@link Disposable}) to stop it. Everything
7
+ * an extension consumes flows the other way, through {@link Client}.
8
+ *
9
+ * `setup` may be async so an extension can read async-KV state or remote config
10
+ * before it is ready; the client awaits it. `name` is used for de-duplication
11
+ * and diagnostics. The `Disposable`s an extension creates in `setup` —
12
+ * enrichers, event listeners, timers — are its own to release: hold them and
13
+ * dispose them in `dispose`. The host disposes the extension; it does not track
14
+ * the extension's individual subscriptions.
15
+ *
16
+ * An extension that exposes app-facing controls extends `Extension` with named
17
+ * methods that share its state, e.g.:
18
+ *
19
+ * ```ts
20
+ * interface SessionReplayExtension extends Extension {
21
+ * startRecording(): void
22
+ * stopRecording(): void
23
+ * isActive(): boolean
24
+ * }
25
+ * ```
26
+ *
27
+ * The client still only calls `setup` and `dispose`; the controls are for the
28
+ * application that constructed the extension.
29
+ */
30
+ export interface Extension extends Disposable {
31
+ /** Stable extension name used for diagnostics and de-duplication within a client instance. */
32
+ readonly name: string;
33
+ /**
34
+ * Capability tokens this extension answers to, so others can resolve it via
35
+ * `client.getExtension(token)`. The extension must be assignable to each
36
+ * token's provided type. Most extensions provide nothing.
37
+ */
38
+ readonly provides?: readonly ExtensionToken<unknown>[];
39
+ /**
40
+ * Start the extension with the host client's capability surface. Called once
41
+ * after construction; return a promise when setup needs asynchronous state
42
+ * such as persisted data or remote config.
43
+ */
44
+ setup(client: Client): void | Promise<void>;
45
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.r = (exports1)=>{
5
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
6
+ value: 'Module'
7
+ });
8
+ Object.defineProperty(exports1, '__esModule', {
9
+ value: true
10
+ });
11
+ };
12
+ })();
13
+ var __webpack_exports__ = {};
14
+ __webpack_require__.r(__webpack_exports__);
15
+ for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
16
+ Object.defineProperty(exports, '__esModule', {
17
+ value: true
18
+ });
File without changes
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Public surface for browser extensions shared across PostHog JavaScript SDK
3
+ * clients.
4
+ */
5
+ export type { Extension } from './extension';
6
+ export type { Disposable } from './disposable';
7
+ export type { ExtensionToken } from './token';
8
+ export type { Listener } from './pubsub';
9
+ export { Publisher } from './pubsub';
10
+ export type { Client, SessionContext, NewSessionReason, NewSessionInfo, CapturedEventInfo, CaptureOptions, ApiResponse, ApiRequestInit, RemoteConfig, } from './client';
11
+ export type { KeyValueStore } from './persistence';
package/dist/index.js ADDED
@@ -0,0 +1,36 @@
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
+ Publisher: ()=>external_pubsub_js_namespaceObject.Publisher
28
+ });
29
+ const external_pubsub_js_namespaceObject = require("./pubsub.js");
30
+ exports.Publisher = __webpack_exports__.Publisher;
31
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
32
+ "Publisher"
33
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
34
+ Object.defineProperty(exports, '__esModule', {
35
+ value: true
36
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { Publisher } from "./pubsub.mjs";
2
+ export { Publisher };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Async key-value store for small extension state. Backed by whatever the
3
+ * client provides — a synchronous store resolves immediately, an asynchronous
4
+ * one (e.g. IndexedDB) does real I/O — so reads and writes are always awaited.
5
+ *
6
+ * The store is namespaced to the client instance, so keys are local to the
7
+ * extension and never collide with core SDK state. Values must be
8
+ * JSON-serializable; setting `null`/`undefined` removes the key.
9
+ */
10
+ export interface KeyValueStore {
11
+ /**
12
+ * Read a value by key.
13
+ *
14
+ * @returns The stored value, or `undefined` when the key is missing.
15
+ */
16
+ get<T = unknown>(key: string): Promise<T | undefined>;
17
+ /**
18
+ * Store a JSON-serializable value by key. Passing `null` or `undefined`
19
+ * removes the key instead of persisting that value.
20
+ */
21
+ set(key: string, value: unknown): Promise<void>;
22
+ /** Remove a value by key. Resolves successfully when the key is already absent. */
23
+ remove(key: string): Promise<void>;
24
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.r = (exports1)=>{
5
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
6
+ value: 'Module'
7
+ });
8
+ Object.defineProperty(exports1, '__esModule', {
9
+ value: true
10
+ });
11
+ };
12
+ })();
13
+ var __webpack_exports__ = {};
14
+ __webpack_require__.r(__webpack_exports__);
15
+ for(var __webpack_i__ in __webpack_exports__)exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
16
+ Object.defineProperty(exports, '__esModule', {
17
+ value: true
18
+ });
File without changes