@wrelik/analytics 0.1.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/CHANGELOG.md +12 -0
- package/package.json +21 -0
- package/src/index.ts +51 -0
- package/tsconfig.json +7 -0
package/CHANGELOG.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wrelik/analytics",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"types": "./dist/index.d.ts",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"posthog-node": "^3.6.3",
|
|
8
|
+
"@wrelik/errors": "0.1.0"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"tsup": "^8.0.1",
|
|
12
|
+
"vitest": "^1.2.2",
|
|
13
|
+
"@wrelik/eslint-config": "0.1.0",
|
|
14
|
+
"@wrelik/tsconfig": "0.1.0"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
18
|
+
"lint": "eslint src/",
|
|
19
|
+
"test": "vitest run --passWithNoTests"
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { PostHog } from 'posthog-node';
|
|
2
|
+
import { ValidationError } from '@wrelik/errors';
|
|
3
|
+
|
|
4
|
+
let client: PostHog | null = null;
|
|
5
|
+
|
|
6
|
+
export function initAnalytics(apiKey: string, host = 'https://app.posthog.com') {
|
|
7
|
+
client = new PostHog(apiKey, { host });
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getClient(safe = false) {
|
|
11
|
+
if (!client && !safe) {
|
|
12
|
+
throw new Error('Analytics not initialized. Call initAnalytics first.');
|
|
13
|
+
}
|
|
14
|
+
return client;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function identify(userId: string, traits: Record<string, any>) {
|
|
18
|
+
getClient(true)?.identify({
|
|
19
|
+
distinctId: userId,
|
|
20
|
+
properties: traits,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function capture(
|
|
25
|
+
event: string,
|
|
26
|
+
properties: Record<string, any> = {},
|
|
27
|
+
options?: { userId?: string },
|
|
28
|
+
) {
|
|
29
|
+
// Validate naming convention: app.action.object
|
|
30
|
+
const parts = event.split('.');
|
|
31
|
+
if (parts.length < 3) {
|
|
32
|
+
throw new ValidationError(`Event name "${event}" must follow "app.action.object" format`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// If no user is provided, we can't capture server-side easily without anonymous ID
|
|
36
|
+
// But usually servers have a userId context.
|
|
37
|
+
if (!options?.userId) {
|
|
38
|
+
console.warn('Analytics capture called without userId');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getClient(true)?.capture({
|
|
43
|
+
distinctId: options.userId,
|
|
44
|
+
event,
|
|
45
|
+
properties,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function shutdown() {
|
|
50
|
+
await getClient(true)?.shutdown();
|
|
51
|
+
}
|