@posthog/browser-common 0.5.2 → 0.6.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/README.md CHANGED
@@ -56,17 +56,37 @@ What an extension is given in `setup` — the adapter shared by extensions on th
56
56
 
57
57
  - **identity and session**: `distinctId`, `anonymousId`, `deviceId`, `groups`, `session`, `initialPersonProperties`
58
58
  - **SDK metadata**: `library`
59
+ - **capture permission**: `canCapture`
59
60
  - **events**: `capture(...)`, `registerDynamicEventProperties(...)`, `onEvent(...)`
61
+ - **extensions**: `getExtension(token)`
60
62
  - **server config**: `onRemoteConfig(...)`
61
63
  - **transport**: `projectToken`, `sendRequest(path, init?)`, including `compression` and `sentAt` options
62
64
  - **storage and logging**: `kv`, `logger`
63
65
 
64
- Identity, session, SDK metadata, and the public project token are always-ready synchronous reads. `capture` and
65
- `sendRequest` are awaitable. For `sendRequest`, `sentAt` controls `sent_at` placement on POST requests; GET query mode
66
+ Identity, session, SDK metadata, capture permission, and the public project token are always-ready synchronous reads.
67
+ `capture` and `sendRequest` are awaitable. For `sendRequest`, `sentAt` controls `sent_at` placement on POST requests; GET query mode
66
68
  uses the cache-busting `_` parameter instead, and GET body mode has no effect. `onRemoteConfig` immediately replays the
67
69
  latest known success or failure and then reports subsequent outcomes. Extensions that want a named log prefix can
68
70
  create a child with `client.logger.createLogger('[myExtension]')`.
69
71
 
72
+ Extensions that expose controls to other extensions should export a typed stable-name token:
73
+
74
+ ```ts
75
+ import type { Extension, ExtensionToken } from '@posthog/browser-common'
76
+
77
+ export interface DiagnosticsExtension extends Extension {
78
+ flush(): void
79
+ }
80
+
81
+ export const DiagnosticsExtension = 'diagnostics' as ExtensionToken<DiagnosticsExtension>
82
+
83
+ const diagnostics = client.getExtension(DiagnosticsExtension)
84
+ diagnostics?.flush()
85
+ ```
86
+
87
+ Tokens are strings at runtime and must match the installed extension's `Extension.name`. Lookup is per-client and optional; a
88
+ returned extension may still be running `setup`, so consumers must not create mandatory startup cycles.
89
+
70
90
  Initialize KV during asynchronous setup before using its synchronous buffer:
71
91
 
72
92
  ```ts
@@ -89,9 +109,10 @@ store sensitive values unless their transmission is approved.
89
109
  PostHog browser SDK implementations share extension registration and teardown
90
110
  through `ExtensionRuntime`, imported from the dedicated
91
111
  `@posthog/browser-common/extension-runtime` subpath. It reserves extension names
92
- during setup, rolls back failed setup, and disposes extensions once in reverse
93
- registration order without waiting for pending setup. Concrete SDKs still own
94
- their `Client` adapter and SDK lifecycle hooks.
112
+ during setup, exposes registered extensions by typed stable name through `Client`,
113
+ rolls back failed setup, and disposes extensions once in reverse registration
114
+ order without waiting for pending setup. Concrete SDKs still own their `Client`
115
+ adapter and SDK lifecycle hooks.
95
116
 
96
117
  `ExtensionRuntime` is host infrastructure, not part of the extension-author
97
118
  surface exported from the package root.
package/dist/client.d.ts CHANGED
@@ -2,7 +2,9 @@ import type { Logger } from '@posthog/core';
2
2
  import type { Properties } from '@posthog/types';
3
3
  import type { Compression } from './types/compression';
4
4
  import type { Disposable } from './disposable';
5
+ import type { Extension } from './extension';
5
6
  import type { KeyValueStore } from './persistence';
7
+ import type { ExtensionToken } from './token';
6
8
  import type { Listener } from './pubsub';
7
9
  import type { RemoteConfigResult } from './types/remote-config';
8
10
  /** Recursively marks object properties as readonly while preserving callable values. */
@@ -95,10 +97,16 @@ export interface Client {
95
97
  readonly groups: DeepReadonly<Record<string, string>>;
96
98
  /** The current session, created on first read if needed. */
97
99
  readonly session: SessionContext;
100
+ /** Whether the host currently permits data capture. */
101
+ readonly canCapture: boolean;
98
102
  /** Records an analytics event through the client's normal pipeline. */
99
103
  capture(event: string, properties?: Properties | null, options?: CaptureOptions): Promise<void>;
100
104
  /** Registers a synchronous producer of properties merged into every captured event. */
101
105
  registerDynamicEventProperties(producer: () => Record<string, unknown>): Disposable;
106
+ /** Returns the extension registered under a typed stable name, or `undefined` when it is not installed. */
107
+ getExtension<T extends Extension>(token: ExtensionToken<T>): T | undefined;
108
+ /** Returns the extension registered under a stable name, or `undefined` when it is not installed. */
109
+ getExtension<T extends Extension = Extension>(name: string): T | undefined;
102
110
  /** Fires for every captured event through a deeply readonly view. */
103
111
  readonly onEvent: Listener<CapturedEventInfo>;
104
112
  /** Replays the latest remote-config outcome on subscription and fires for subsequent outcomes. */
package/dist/config.js CHANGED
@@ -26,7 +26,7 @@ __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
27
  default: ()=>__WEBPACK_DEFAULT_EXPORT__
28
28
  });
29
- const packageVersion = "0.5.2";
29
+ const packageVersion = "0.6.0";
30
30
  const Config = {
31
31
  DEBUG: false,
32
32
  LIB_VERSION: packageVersion,
package/dist/config.mjs CHANGED
@@ -1,4 +1,4 @@
1
- const packageVersion = "0.5.2";
1
+ const packageVersion = "0.6.0";
2
2
  const Config = {
3
3
  DEBUG: false,
4
4
  LIB_VERSION: packageVersion,
@@ -2,6 +2,7 @@ import { type Logger } from '@posthog/core';
2
2
  import type { Client } from './client';
3
3
  import type { Disposable } from './disposable';
4
4
  import type { Extension } from './extension';
5
+ import type { ExtensionToken } from './token';
5
6
  /** Shared setup and lifecycle registry for browser extension hosts. */
6
7
  export declare class ExtensionRuntime implements Disposable {
7
8
  private readonly _logger;
@@ -11,6 +12,10 @@ export declare class ExtensionRuntime implements Disposable {
11
12
  constructor(_logger: Logger, _client: Client);
12
13
  /** Reserves an extension name and sets it up with the host client adapter. */
13
14
  add(extension: Extension): Promise<void>;
15
+ /** Returns a registered extension by its typed stable name, including while setup is in progress. */
16
+ getExtension<T extends Extension>(token: ExtensionToken<T>): T | undefined;
17
+ /** Returns a registered extension by its stable name, including while setup is in progress. */
18
+ getExtension<T extends Extension = Extension>(name: string): T | undefined;
14
19
  /** Releases every registered extension once in reverse registration order without waiting for pending setup. */
15
20
  dispose(): void;
16
21
  private _disposeExtension;
@@ -48,6 +48,9 @@ class ExtensionRuntime {
48
48
  if (active) this._disposeExtension(extension);
49
49
  }
50
50
  }
51
+ getExtension(name) {
52
+ return this._extensions.get(name);
53
+ }
51
54
  dispose() {
52
55
  if (this._disposed) return;
53
56
  this._disposed = true;
@@ -20,6 +20,9 @@ class ExtensionRuntime {
20
20
  if (active) this._disposeExtension(extension);
21
21
  }
22
22
  }
23
+ getExtension(name) {
24
+ return this._extensions.get(name);
25
+ }
23
26
  dispose() {
24
27
  if (this._disposed) return;
25
28
  this._disposed = true;
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  * clients.
4
4
  */
5
5
  export type { Extension } from './extension';
6
+ export type { ExtensionToken } from './token';
6
7
  export * from './types';
7
8
  export { createDisposable, type Disposable } from './disposable';
8
9
  export type { Listener } from './pubsub';
@@ -0,0 +1,14 @@
1
+ /** Phantom brand carrying an extension type without emitting runtime code. */
2
+ declare const extensionTokenType: unique symbol;
3
+ /**
4
+ * A typed stable name for resolving an installed extension.
5
+ *
6
+ * Tokens are plain strings at runtime, so independently compiled scripts can
7
+ * share them without a registry or object-identity contract. The generic brand
8
+ * lets `Client.getExtension` infer the extension type. A token's string
9
+ * value must exactly match its extension's stable `name`.
10
+ */
11
+ export type ExtensionToken<T> = string & {
12
+ readonly [extensionTokenType]: T;
13
+ };
14
+ export {};
package/dist/token.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
+ });
package/dist/token.mjs ADDED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/browser-common",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "Internal shared browser utilities and extension primitives for PostHog Browser SDKs",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@posthog/core": "^1.48.11",
69
- "@posthog/types": "^1.405.3"
69
+ "@posthog/types": "^1.406.1"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@rslib/core": "0.10.6",