@baukit/analytics-posthog-native 0.3.0 → 0.5.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 +28 -0
- package/dist/storage.d.ts +25 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +55 -0
- package/dist/storage.js.map +1 -0
- package/package.json +23 -11
package/README.md
CHANGED
|
@@ -52,6 +52,34 @@ The adapter exports a minimal structural `PostHogNativeClient` interface for moc
|
|
|
52
52
|
while its initializer options compile against `posthog-react-native`'s published types. This keeps
|
|
53
53
|
unit tests runnable without installing or booting a React Native runtime.
|
|
54
54
|
|
|
55
|
+
## Persisted identity storage
|
|
56
|
+
|
|
57
|
+
`AnalyticsClient` reads storage synchronously, while React Native storage is asynchronous. The
|
|
58
|
+
`/storage` subpath bridges the two. `HydratedAnalyticsStorage.load` reads the listed keys once,
|
|
59
|
+
serves later reads from memory, and writes those keys through without waiting. Other keys stay in
|
|
60
|
+
memory. The subpath does not import `posthog-react-native`, so apps with another transport can use
|
|
61
|
+
it without the SDK.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
65
|
+
import { AnalyticsClient, analyticsStorageKeys } from '@baukit/analytics-core';
|
|
66
|
+
import { HydratedAnalyticsStorage } from '@baukit/analytics-posthog-native/storage';
|
|
67
|
+
|
|
68
|
+
const keys = analyticsStorageKeys(storageKeyPrefix);
|
|
69
|
+
const storage = await HydratedAnalyticsStorage.load({
|
|
70
|
+
persistence: AsyncStorage,
|
|
71
|
+
persistentKeys: [keys.anonymousId, keys.userId, keys.aliasedUserId],
|
|
72
|
+
});
|
|
73
|
+
const analytics = new AnalyticsClient({ context, allowlist, storage, storageKeyPrefix });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Include `keys.consent` only when analytics consent has no other durable home. A key that fails to
|
|
77
|
+
read starts absent, and the other keys still load. A failed write keeps the in-memory value and is
|
|
78
|
+
not reported. The storage holds only what the client writes: the consent state and pseudonymous
|
|
79
|
+
UUIDs.
|
|
80
|
+
|
|
81
|
+
`posthog-react-native` is an optional peer. Install it only when you use the transport.
|
|
82
|
+
|
|
55
83
|
## Mapping
|
|
56
84
|
|
|
57
85
|
- `capture` flattens the core-stamped context and already-scrubbed event properties, preserving the
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AnalyticsStorage } from '@baukit/analytics-core';
|
|
2
|
+
/** Asynchronous key-value store, such as React Native AsyncStorage. */
|
|
3
|
+
export interface AsyncKeyValueStorage {
|
|
4
|
+
getItem(key: string): Promise<string | null>;
|
|
5
|
+
setItem(key: string, value: string): Promise<void>;
|
|
6
|
+
removeItem(key: string): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export interface HydratedAnalyticsStorageOptions {
|
|
9
|
+
readonly persistence: AsyncKeyValueStorage;
|
|
10
|
+
/** Keys copied from and written through to `persistence`. Other keys stay in memory. */
|
|
11
|
+
readonly persistentKeys: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Synchronous `AnalyticsStorage` over an asynchronous store. `load` reads the persistent keys
|
|
15
|
+
* once, then reads are served from memory and writes go through without being awaited.
|
|
16
|
+
*/
|
|
17
|
+
export declare class HydratedAnalyticsStorage implements AnalyticsStorage {
|
|
18
|
+
#private;
|
|
19
|
+
private constructor();
|
|
20
|
+
static load(options: HydratedAnalyticsStorageOptions): Promise<HydratedAnalyticsStorage>;
|
|
21
|
+
getItem(key: string): string | undefined;
|
|
22
|
+
setItem(key: string, value: string): void;
|
|
23
|
+
removeItem(key: string): void;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAC3C,wFAAwF;IACxF,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED;;;GAGG;AACH,qBAAa,wBAAyB,YAAW,gBAAgB;;IAK/D,OAAO;WASa,IAAI,CACtB,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,wBAAwB,CAAC;IAU7B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIxC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAMzC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAKrC"}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synchronous `AnalyticsStorage` over an asynchronous store. `load` reads the persistent keys
|
|
3
|
+
* once, then reads are served from memory and writes go through without being awaited.
|
|
4
|
+
*/
|
|
5
|
+
export class HydratedAnalyticsStorage {
|
|
6
|
+
#values;
|
|
7
|
+
#persistence;
|
|
8
|
+
#persistentKeys;
|
|
9
|
+
constructor(options, entries) {
|
|
10
|
+
this.#persistence = options.persistence;
|
|
11
|
+
this.#persistentKeys = new Set(options.persistentKeys);
|
|
12
|
+
this.#values = new Map(entries);
|
|
13
|
+
}
|
|
14
|
+
static async load(options) {
|
|
15
|
+
const keys = [...new Set(options.persistentKeys)];
|
|
16
|
+
const stored = await Promise.all(keys.map((key) => readOrAbsent(options.persistence, key)));
|
|
17
|
+
const entries = keys.flatMap((key, index) => {
|
|
18
|
+
const value = stored[index];
|
|
19
|
+
return value === undefined ? [] : [[key, value]];
|
|
20
|
+
});
|
|
21
|
+
return new HydratedAnalyticsStorage(options, entries);
|
|
22
|
+
}
|
|
23
|
+
getItem(key) {
|
|
24
|
+
return this.#values.get(key);
|
|
25
|
+
}
|
|
26
|
+
setItem(key, value) {
|
|
27
|
+
this.#values.set(key, value);
|
|
28
|
+
if (!this.#persistentKeys.has(key))
|
|
29
|
+
return;
|
|
30
|
+
ignoreFailure(() => this.#persistence.setItem(key, value));
|
|
31
|
+
}
|
|
32
|
+
removeItem(key) {
|
|
33
|
+
this.#values.delete(key);
|
|
34
|
+
if (!this.#persistentKeys.has(key))
|
|
35
|
+
return;
|
|
36
|
+
ignoreFailure(() => this.#persistence.removeItem(key));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function readOrAbsent(persistence, key) {
|
|
40
|
+
try {
|
|
41
|
+
return (await persistence.getItem(key)) ?? undefined;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function ignoreFailure(write) {
|
|
48
|
+
try {
|
|
49
|
+
void write().catch(() => undefined);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IAC1B,OAAO,CAAsB;IAC7B,YAAY,CAAuB;IACnC,eAAe,CAAsB;IAE9C,YACE,OAAwC,EACxC,OAA+C;QAE/C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;QACxC,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,IAAI,CACtB,OAAwC;QAExC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5F,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAU,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAEM,OAAO,CAAC,GAAW;QACxB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAEM,OAAO,CAAC,GAAW,EAAE,KAAa;QACvC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC3C,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7D,CAAC;IAEM,UAAU,CAAC,GAAW;QAC3B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC3C,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;CACF;AAED,KAAK,UAAU,YAAY,CACzB,WAAiC,EACjC,GAAW;IAEX,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,SAAS,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,KAA0B;IAC/C,IAAI,CAAC;QACH,KAAK,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baukit/analytics-posthog-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "PostHog React Native transport for @baukit/analytics-core.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Patrick Koss",
|
|
@@ -24,7 +24,13 @@
|
|
|
24
24
|
"exports": {
|
|
25
25
|
".": {
|
|
26
26
|
"types": "./dist/index.d.ts",
|
|
27
|
-
"import": "./dist/index.js"
|
|
27
|
+
"import": "./dist/index.js",
|
|
28
|
+
"default": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./storage": {
|
|
31
|
+
"types": "./dist/storage.d.ts",
|
|
32
|
+
"import": "./dist/storage.js",
|
|
33
|
+
"default": "./dist/storage.js"
|
|
28
34
|
}
|
|
29
35
|
},
|
|
30
36
|
"files": [
|
|
@@ -32,19 +38,25 @@
|
|
|
32
38
|
"README.md",
|
|
33
39
|
"LICENSE"
|
|
34
40
|
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsc -p tsconfig.json",
|
|
43
|
+
"prepare": "pnpm run build",
|
|
44
|
+
"test": "tsc -p tsconfig.test.json && vitest run --config ../../vitest.config.ts && node ../../scripts/test-packed-exports.mjs",
|
|
45
|
+
"lint": "eslint src --max-warnings=0",
|
|
46
|
+
"format:check": "prettier --check src package.json tsconfig.json tsconfig.test.json"
|
|
47
|
+
},
|
|
35
48
|
"devDependencies": {
|
|
49
|
+
"@baukit/analytics-core": "workspace:*",
|
|
36
50
|
"posthog-react-native": "4.62.0",
|
|
37
|
-
"typescript": "6.0.3"
|
|
38
|
-
"@baukit/analytics-core": "0.3.0"
|
|
51
|
+
"typescript": "6.0.3"
|
|
39
52
|
},
|
|
40
53
|
"peerDependencies": {
|
|
41
|
-
"@baukit/analytics-core": "^0.
|
|
54
|
+
"@baukit/analytics-core": "^0.5.0",
|
|
42
55
|
"posthog-react-native": "^4.62.0"
|
|
43
56
|
},
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"format:check": "prettier --check src package.json tsconfig.json"
|
|
57
|
+
"peerDependenciesMeta": {
|
|
58
|
+
"posthog-react-native": {
|
|
59
|
+
"optional": true
|
|
60
|
+
}
|
|
49
61
|
}
|
|
50
|
-
}
|
|
62
|
+
}
|