@philcrp/analytics 1.6.3 → 1.6.5
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 +664 -6
- package/dist/global-CLXWNSdY.d.mts +587 -0
- package/dist/global-CLXWNSdY.d.ts +587 -0
- package/dist/index.d.mts +38 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +983 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +939 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react/index.d.mts +168 -0
- package/dist/react/index.d.ts +168 -0
- package/dist/react/index.js +269 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +233 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/server.d.mts +16 -0
- package/dist/server.d.ts +16 -0
- package/dist/server.js +766 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +729 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +8 -74
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/react/index.ts
|
|
21
|
+
var react_exports = {};
|
|
22
|
+
__export(react_exports, {
|
|
23
|
+
AnalyticsProvider: () => AnalyticsProvider,
|
|
24
|
+
getGlobalAnalytics: () => getGlobalAnalytics,
|
|
25
|
+
getGlobalAnalyticsOptional: () => getGlobalAnalyticsOptional,
|
|
26
|
+
getSingletonAnalytics: () => getSingletonAnalytics,
|
|
27
|
+
getSingletonAnalyticsOptional: () => getSingletonAnalyticsOptional,
|
|
28
|
+
useAnalytics: () => useAnalytics,
|
|
29
|
+
useAnalyticsOptional: () => useAnalyticsOptional,
|
|
30
|
+
useAnalyticsState: () => useAnalyticsState,
|
|
31
|
+
useAnalyticsStrict: () => useAnalyticsStrict,
|
|
32
|
+
useEventTracking: () => useEventTracking
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(react_exports);
|
|
35
|
+
|
|
36
|
+
// src/react/provider.tsx
|
|
37
|
+
var import_react = require("react");
|
|
38
|
+
|
|
39
|
+
// src/providers/posthog.ts
|
|
40
|
+
var import_posthog_js = require("posthog-js");
|
|
41
|
+
|
|
42
|
+
// src/global.ts
|
|
43
|
+
var GLOBAL_STATE_KEY = "__LOBE_ANALYTICS_GLOBAL_STATE__";
|
|
44
|
+
function getGlobalState() {
|
|
45
|
+
if (!globalThis[GLOBAL_STATE_KEY]) {
|
|
46
|
+
globalThis[GLOBAL_STATE_KEY] = {
|
|
47
|
+
instances: /* @__PURE__ */ new Map(),
|
|
48
|
+
singletonConfig: null,
|
|
49
|
+
singletonInstance: null
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return globalThis[GLOBAL_STATE_KEY];
|
|
53
|
+
}
|
|
54
|
+
var DEFAULT_INSTANCE_NAME = "__default__";
|
|
55
|
+
function setGlobalAnalytics(instance, name = DEFAULT_INSTANCE_NAME) {
|
|
56
|
+
const state = getGlobalState();
|
|
57
|
+
state.instances.set(name, instance);
|
|
58
|
+
}
|
|
59
|
+
function getGlobalAnalytics(name = DEFAULT_INSTANCE_NAME) {
|
|
60
|
+
const state = getGlobalState();
|
|
61
|
+
const instance = state.instances.get(name);
|
|
62
|
+
if (!instance) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Global analytics instance "${name}" not found. Make sure to register it first using setGlobalAnalytics() or use AnalyticsProvider.`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return instance;
|
|
68
|
+
}
|
|
69
|
+
function getGlobalAnalyticsOptional(name = DEFAULT_INSTANCE_NAME) {
|
|
70
|
+
const state = getGlobalState();
|
|
71
|
+
return state.instances.get(name) || null;
|
|
72
|
+
}
|
|
73
|
+
function getSingletonAnalytics() {
|
|
74
|
+
const state = getGlobalState();
|
|
75
|
+
if (!state.singletonInstance) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
"Singleton analytics instance not created. Call createSingletonAnalytics() first or use getGlobalAnalytics()."
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return state.singletonInstance;
|
|
81
|
+
}
|
|
82
|
+
function getSingletonAnalyticsOptional() {
|
|
83
|
+
const state = getGlobalState();
|
|
84
|
+
return state.singletonInstance;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/react/provider.tsx
|
|
88
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
89
|
+
var AnalyticsContext = (0, import_react.createContext)(void 0);
|
|
90
|
+
function AnalyticsProvider({
|
|
91
|
+
client,
|
|
92
|
+
children,
|
|
93
|
+
autoInitialize = true,
|
|
94
|
+
globalName = "__default__",
|
|
95
|
+
onInitializeError,
|
|
96
|
+
onInitializeSuccess,
|
|
97
|
+
registerGlobal = true
|
|
98
|
+
}) {
|
|
99
|
+
const [isInitialized, setIsInitialized] = (0, import_react.useState)(false);
|
|
100
|
+
const [isInitializing, setIsInitializing] = (0, import_react.useState)(false);
|
|
101
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
102
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
103
|
+
if (registerGlobal) {
|
|
104
|
+
setGlobalAnalytics(client, globalName);
|
|
105
|
+
}
|
|
106
|
+
}, [client, globalName, registerGlobal]);
|
|
107
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
108
|
+
if (!autoInitialize || isInitialized || isInitializing) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const initializeAnalytics = async () => {
|
|
112
|
+
setIsInitializing(true);
|
|
113
|
+
setError(null);
|
|
114
|
+
try {
|
|
115
|
+
await client.initialize();
|
|
116
|
+
setIsInitialized(true);
|
|
117
|
+
onInitializeSuccess == null ? void 0 : onInitializeSuccess();
|
|
118
|
+
} catch (error_) {
|
|
119
|
+
const error2 = error_ instanceof Error ? error_ : new Error("Analytics initialization failed");
|
|
120
|
+
setError(error2);
|
|
121
|
+
onInitializeError == null ? void 0 : onInitializeError(error2);
|
|
122
|
+
console.error("[AnalyticsProvider] Initialization failed:", error2);
|
|
123
|
+
} finally {
|
|
124
|
+
setIsInitializing(false);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
initializeAnalytics();
|
|
128
|
+
}, [
|
|
129
|
+
client,
|
|
130
|
+
autoInitialize,
|
|
131
|
+
isInitialized,
|
|
132
|
+
isInitializing,
|
|
133
|
+
onInitializeError,
|
|
134
|
+
onInitializeSuccess
|
|
135
|
+
]);
|
|
136
|
+
const contextValue = {
|
|
137
|
+
analytics: client,
|
|
138
|
+
error,
|
|
139
|
+
isInitialized,
|
|
140
|
+
isInitializing
|
|
141
|
+
};
|
|
142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AnalyticsContext.Provider, { value: contextValue, children });
|
|
143
|
+
}
|
|
144
|
+
function useAnalyticsContext() {
|
|
145
|
+
const context = (0, import_react.useContext)(AnalyticsContext);
|
|
146
|
+
if (context === void 0) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
"useAnalyticsContext must be used within an AnalyticsProvider. Wrap your component tree with <AnalyticsProvider client={analytics}>"
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
return context;
|
|
152
|
+
}
|
|
153
|
+
function useAnalytics() {
|
|
154
|
+
const { analytics, isInitialized, isInitializing, error } = useAnalyticsContext();
|
|
155
|
+
return {
|
|
156
|
+
/** Analytics 实例(仅在就绪时可用) */
|
|
157
|
+
analytics: isInitialized && !error ? analytics : null,
|
|
158
|
+
/** 是否发生错误 */
|
|
159
|
+
error,
|
|
160
|
+
/** 是否已初始化 */
|
|
161
|
+
isInitialized,
|
|
162
|
+
/** 是否正在初始化 */
|
|
163
|
+
isInitializing,
|
|
164
|
+
/** 是否就绪(已初始化且无错误) */
|
|
165
|
+
isReady: isInitialized && !error && analytics !== null
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function useAnalyticsStrict() {
|
|
169
|
+
const { analytics, isInitialized, isInitializing, error } = useAnalyticsContext();
|
|
170
|
+
if (error) {
|
|
171
|
+
throw new Error(`[useAnalyticsStrict] Analytics initialization failed: ${error.message}`);
|
|
172
|
+
}
|
|
173
|
+
if (!isInitialized) {
|
|
174
|
+
if (isInitializing) {
|
|
175
|
+
throw new Error(
|
|
176
|
+
"[useAnalyticsStrict] Analytics is still initializing. Use useAnalyticsState to check status."
|
|
177
|
+
);
|
|
178
|
+
} else {
|
|
179
|
+
throw new Error(
|
|
180
|
+
"[useAnalyticsStrict] Analytics not initialized. Set autoInitialize=true or call initialize manually."
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (!analytics) {
|
|
185
|
+
throw new Error("[useAnalyticsStrict] Analytics instance is null");
|
|
186
|
+
}
|
|
187
|
+
return analytics;
|
|
188
|
+
}
|
|
189
|
+
function useAnalyticsState() {
|
|
190
|
+
const { error, isInitialized, isInitializing } = useAnalyticsContext();
|
|
191
|
+
return {
|
|
192
|
+
error,
|
|
193
|
+
isInitialized,
|
|
194
|
+
isInitializing,
|
|
195
|
+
isReady: isInitialized && !error
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function useAnalyticsOptional() {
|
|
199
|
+
const { analytics } = useAnalytics();
|
|
200
|
+
return analytics;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/react/hooks.ts
|
|
204
|
+
var import_react2 = require("react");
|
|
205
|
+
function useAnalytics2(manager) {
|
|
206
|
+
const track = (0, import_react2.useCallback)((event) => manager.track(event), [manager]);
|
|
207
|
+
const trackEvent = (0, import_react2.useCallback)(
|
|
208
|
+
(eventName, properties) => manager.trackEvent(eventName, properties),
|
|
209
|
+
[manager]
|
|
210
|
+
);
|
|
211
|
+
const identify = (0, import_react2.useCallback)(
|
|
212
|
+
(userId, properties) => manager.identify(userId, properties),
|
|
213
|
+
[manager]
|
|
214
|
+
);
|
|
215
|
+
const trackPageView = (0, import_react2.useCallback)(
|
|
216
|
+
(page, properties) => manager.trackPageView(page, properties),
|
|
217
|
+
[manager]
|
|
218
|
+
);
|
|
219
|
+
const reset = (0, import_react2.useCallback)(() => manager.reset(), [manager]);
|
|
220
|
+
return {
|
|
221
|
+
identify,
|
|
222
|
+
reset,
|
|
223
|
+
track,
|
|
224
|
+
trackEvent,
|
|
225
|
+
trackPageView
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function useEventTracking(manager) {
|
|
229
|
+
const { trackEvent } = useAnalytics2(manager);
|
|
230
|
+
const trackButtonClick = (0, import_react2.useCallback)(
|
|
231
|
+
(buttonName, context) => trackEvent("button_click", { button_name: buttonName, ...context }),
|
|
232
|
+
[trackEvent]
|
|
233
|
+
);
|
|
234
|
+
const trackFormSubmit = (0, import_react2.useCallback)(
|
|
235
|
+
(formName, success) => manager.track({
|
|
236
|
+
name: "form_submit",
|
|
237
|
+
properties: { form_name: formName, success }
|
|
238
|
+
}),
|
|
239
|
+
[manager]
|
|
240
|
+
);
|
|
241
|
+
const trackUserSignup = (0, import_react2.useCallback)(
|
|
242
|
+
(spm, extraProperties) => trackEvent("user_signup", { spm, ...extraProperties }),
|
|
243
|
+
[trackEvent]
|
|
244
|
+
);
|
|
245
|
+
const trackUserLogin = (0, import_react2.useCallback)(
|
|
246
|
+
(spm, extraProperties) => trackEvent("user_login", { spm, ...extraProperties }),
|
|
247
|
+
[trackEvent]
|
|
248
|
+
);
|
|
249
|
+
return {
|
|
250
|
+
trackButtonClick,
|
|
251
|
+
trackFormSubmit,
|
|
252
|
+
trackUserLogin,
|
|
253
|
+
trackUserSignup
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
257
|
+
0 && (module.exports = {
|
|
258
|
+
AnalyticsProvider,
|
|
259
|
+
getGlobalAnalytics,
|
|
260
|
+
getGlobalAnalyticsOptional,
|
|
261
|
+
getSingletonAnalytics,
|
|
262
|
+
getSingletonAnalyticsOptional,
|
|
263
|
+
useAnalytics,
|
|
264
|
+
useAnalyticsOptional,
|
|
265
|
+
useAnalyticsState,
|
|
266
|
+
useAnalyticsStrict,
|
|
267
|
+
useEventTracking
|
|
268
|
+
});
|
|
269
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/provider.tsx","../../src/providers/posthog.ts","../../src/global.ts","../../src/react/hooks.ts"],"sourcesContent":["// React Provider & Hooks\nexport {\n AnalyticsProvider,\n useAnalytics,\n useAnalyticsOptional,\n useAnalyticsState,\n useAnalyticsStrict,\n} from './provider';\n\n// Legacy Hooks (for backward compatibility)\nexport { useEventTracking } from './hooks';\n\n// Global Instance Management (Re-export for convenience)\nexport {\n getGlobalAnalytics,\n getGlobalAnalyticsOptional,\n getSingletonAnalytics,\n getSingletonAnalyticsOptional,\n} from '../global';\n\n// Re-export types that are commonly used with hooks\nexport type { AnalyticsManager } from '../manager';\nexport type { AnalyticsEvent, PredefinedEvents } from '../types';\n","'use client';\n\nimport React, { type ReactNode, createContext, useContext, useLayoutEffect, useState } from 'react';\n\nimport { setGlobalAnalytics } from '../global';\nimport type { AnalyticsManager } from '../manager';\n\n/**\n * Analytics Context 类型定义\n */\ninterface AnalyticsContextValue {\n analytics: AnalyticsManager | null;\n error: Error | null;\n isInitialized: boolean;\n isInitializing: boolean;\n}\n\n/**\n * Analytics Context\n */\nconst AnalyticsContext = createContext<AnalyticsContextValue | undefined>(undefined);\n\n/**\n * Analytics Provider Props\n */\ninterface AnalyticsProviderProps {\n /** 是否自动初始化(默认: true) */\n autoInitialize?: boolean;\n /** 子组件 */\n children: ReactNode;\n /** 配置好的 Analytics 实例 */\n client: AnalyticsManager;\n /** 全局实例名称,用于全局访问(默认: '__default__') */\n globalName?: string;\n /** 初始化失败时的回调 */\n onInitializeError?: (error: Error) => void;\n /** 初始化成功时的回调 */\n onInitializeSuccess?: () => void;\n /** 是否注册为全局实例(默认: true) */\n registerGlobal?: boolean;\n}\n\n/**\n * Analytics Provider 组件\n *\n * 提供 Analytics 实例给整个 React 应用树,并处理初始化逻辑\n *\n * @example\n * ```tsx\n * import { createAnalytics, AnalyticsProvider } from '@lobehub/analytics';\n *\n * const analytics = createAnalytics({\n * debug: true,\n * providers: {\n * posthog: {\n * enabled: true,\n * key: 'phc_your_key',\n * host: 'https://app.posthog.com',\n * },\n * },\n * });\n *\n * function App() {\n * return (\n * <AnalyticsProvider client={analytics}>\n * <MyApp />\n * </AnalyticsProvider>\n * );\n * }\n * ```\n */\nexport function AnalyticsProvider({\n client,\n children,\n autoInitialize = true,\n globalName = '__default__',\n onInitializeError,\n onInitializeSuccess,\n registerGlobal = true,\n}: AnalyticsProviderProps) {\n const [isInitialized, setIsInitialized] = useState(false);\n const [isInitializing, setIsInitializing] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // 注册为全局实例\n useLayoutEffect(() => {\n if (registerGlobal) {\n setGlobalAnalytics(client, globalName);\n }\n }, [client, globalName, registerGlobal]);\n\n useLayoutEffect(() => {\n if (!autoInitialize || isInitialized || isInitializing) {\n return;\n }\n\n const initializeAnalytics = async () => {\n setIsInitializing(true);\n setError(null);\n\n try {\n await client.initialize();\n setIsInitialized(true);\n onInitializeSuccess?.();\n } catch (error_) {\n const error =\n error_ instanceof Error ? error_ : new Error('Analytics initialization failed');\n setError(error);\n onInitializeError?.(error);\n console.error('[AnalyticsProvider] Initialization failed:', error);\n } finally {\n setIsInitializing(false);\n }\n };\n\n initializeAnalytics();\n }, [\n client,\n autoInitialize,\n isInitialized,\n isInitializing,\n onInitializeError,\n onInitializeSuccess,\n ]);\n\n const contextValue: AnalyticsContextValue = {\n analytics: client,\n error,\n isInitialized,\n isInitializing,\n };\n\n return <AnalyticsContext.Provider value={contextValue}>{children}</AnalyticsContext.Provider>;\n}\n\n/**\n * 获取 Analytics Context\n *\n * @throws {Error} 如果在 AnalyticsProvider 外使用\n */\nfunction useAnalyticsContext(): AnalyticsContextValue {\n const context = useContext(AnalyticsContext);\n\n if (context === undefined) {\n throw new Error(\n 'useAnalyticsContext must be used within an AnalyticsProvider. ' +\n 'Wrap your component tree with <AnalyticsProvider client={analytics}>',\n );\n }\n\n return context;\n}\n\n/**\n * 获取 Analytics 实例(安全版本,不抛出错误)\n *\n * @returns Analytics 实例或 null,以及状态信息\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { analytics, isReady, error } = useAnalytics();\n *\n * if (!isReady) {\n * return <div>Analytics not ready</div>;\n * }\n *\n * const handleClick = () => {\n * analytics?.track({ name: 'button_click' });\n * };\n *\n * return <button onClick={handleClick}>Click me</button>;\n * }\n * ```\n */\nexport function useAnalytics() {\n const { analytics, isInitialized, isInitializing, error } = useAnalyticsContext();\n\n return {\n /** Analytics 实例(仅在就绪时可用) */\n analytics: isInitialized && !error ? analytics : null,\n /** 是否发生错误 */\n error,\n /** 是否已初始化 */\n isInitialized,\n /** 是否正在初始化 */\n isInitializing,\n /** 是否就绪(已初始化且无错误) */\n isReady: isInitialized && !error && analytics !== null,\n };\n}\n\n/**\n * 获取 Analytics 实例(严格版本,抛出错误)\n *\n * @returns Analytics 实例\n * @throws {Error} 如果在 AnalyticsProvider 外使用或实例未就绪\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const analytics = useAnalyticsStrict();\n *\n * const handleClick = () => {\n * analytics.track({ name: 'button_click' });\n * };\n *\n * return <button onClick={handleClick}>Click me</button>;\n * }\n * ```\n */\nexport function useAnalyticsStrict(): AnalyticsManager {\n const { analytics, isInitialized, isInitializing, error } = useAnalyticsContext();\n\n if (error) {\n throw new Error(`[useAnalyticsStrict] Analytics initialization failed: ${error.message}`);\n }\n\n if (!isInitialized) {\n if (isInitializing) {\n throw new Error(\n '[useAnalyticsStrict] Analytics is still initializing. Use useAnalyticsState to check status.',\n );\n } else {\n throw new Error(\n '[useAnalyticsStrict] Analytics not initialized. Set autoInitialize=true or call initialize manually.',\n );\n }\n }\n\n if (!analytics) {\n throw new Error('[useAnalyticsStrict] Analytics instance is null');\n }\n\n return analytics;\n}\n\n/**\n * 获取 Analytics 状态信息\n *\n * @returns Analytics 状态\n *\n * @example\n * ```tsx\n * function LoadingComponent() {\n * const { isInitialized, isInitializing, error } = useAnalyticsState();\n *\n * if (isInitializing) return <div>Loading analytics...</div>;\n * if (error) return <div>Analytics failed: {error.message}</div>;\n * if (!isInitialized) return <div>Analytics not ready</div>;\n *\n * return <MyApp />;\n * }\n * ```\n */\nexport function useAnalyticsState() {\n const { error, isInitialized, isInitializing } = useAnalyticsContext();\n\n return {\n error,\n isInitialized,\n isInitializing,\n isReady: isInitialized && !error,\n };\n}\n\n/**\n * 获取 Analytics 实例(可选,不抛出错误)\n *\n * @deprecated 请使用 `useAnalytics()` 代替,它现在提供相同的安全访问\n * @returns Analytics 实例或 null\n *\n * @example\n * ```tsx\n * function OptionalTracking() {\n * const analytics = useAnalyticsOptional();\n *\n * const handleOptionalEvent = () => {\n * analytics?.track({ name: 'optional_event' });\n * };\n *\n * return <button onClick={handleOptionalEvent}>Optional Track</button>;\n * }\n * ```\n */\nexport function useAnalyticsOptional(): AnalyticsManager | null {\n const { analytics } = useAnalytics();\n return analytics;\n}\n","import { BeforeSendFn, CaptureResult, posthog } from 'posthog-js';\n\nimport { BaseAnalytics } from '@/base';\nimport type { AnalyticsEvent, PostHogProviderAnalyticsConfig } from '@/types';\n\n/**\n * PostHog Analytics Provider\n * Uses official posthog-js SDK\n */\nexport class PostHogAnalyticsProvider extends BaseAnalytics {\n private readonly config: PostHogProviderAnalyticsConfig;\n private initialized = false;\n\n constructor(config: PostHogProviderAnalyticsConfig, business: string) {\n super({ business, debug: config.debug, enabled: config.enabled });\n this.config = config;\n }\n\n getProviderName(): string {\n return 'PostHog';\n }\n\n async initialize(): Promise<void> {\n if (!this.isEnabled() || this.initialized) {\n return;\n }\n\n try {\n // Extract provider-specific properties and prepare posthog config\n const { key, host, ...posthogConfig } = this.config;\n\n // Build init config: start with user's posthog config, then apply our defaults/overrides\n const initConfig = {\n ...posthogConfig, // User's posthog-js config options\n api_host: host || posthogConfig.api_host || 'https://app.posthog.com',\n // Use before_send to dynamically add business context to all events\n before_send: this.createBeforeSendHandler(posthogConfig.before_send),\n debug: this.debug,\n loaded: () => this.log('PostHog loaded and ready'),\n };\n\n posthog.init(key, initConfig);\n\n this.initialized = true;\n this.log('PostHog initialized successfully');\n this.log(`Using before_send to add business context: ${this.business}`);\n } catch (error) {\n this.logError('Failed to initialize PostHog', error);\n throw error;\n }\n }\n\n async track(event: AnalyticsEvent): Promise<void> {\n if (!this.isEnabled() || !this.initialized || !this.validateEvent(event)) {\n return;\n }\n\n try {\n const enrichedProperties = this.enrichProperties(event.properties);\n\n posthog.capture(event.name, {\n ...enrichedProperties,\n ...(event.userId && { distinct_id: event.userId }),\n });\n\n this.log(`Tracked event: ${event.name}`, { ...event, properties: enrichedProperties });\n } catch (error) {\n this.logError(`Failed to track event: ${event.name}`, error);\n }\n }\n\n async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n if (!this.isEnabled() || !this.initialized) {\n return;\n }\n\n try {\n const enrichedProperties = this.enrichProperties(properties);\n posthog.identify(userId, enrichedProperties);\n this.log(`Identified user: ${userId}`, enrichedProperties);\n } catch (error) {\n this.logError(`Failed to identify user: ${userId}`, error);\n }\n }\n\n async trackPageView(page: string, properties?: Record<string, any>): Promise<void> {\n if (!this.isEnabled() || !this.initialized) {\n return;\n }\n\n try {\n const enrichedProperties = this.enrichProperties(properties);\n await this.track({\n name: '$pageview',\n properties: { page, ...enrichedProperties },\n });\n\n this.log(`Tracked page view: ${page}`, enrichedProperties);\n } catch (error) {\n this.logError(`Failed to track page view: ${page}`, error);\n }\n }\n\n async reset(): Promise<void> {\n if (!this.isEnabled() || !this.initialized) {\n return;\n }\n\n try {\n posthog.reset();\n this.log('Reset user identity');\n } catch (error) {\n this.logError('Failed to reset user identity', error);\n }\n }\n\n /**\n * Check if feature flag is enabled\n */\n isFeatureEnabled(flag: string): boolean {\n if (!this.initialized) {\n return false;\n }\n\n try {\n return Boolean(posthog.isFeatureEnabled(flag));\n } catch (error) {\n this.logError(`Failed to check feature flag: ${flag}`, error);\n return false;\n }\n }\n\n /**\n * Get the native PostHog instance for direct access to PostHog APIs\n *\n * Note: When using the native instance directly, events will still include\n * the business spm prefix because it's registered as a global property.\n *\n * @returns PostHog native instance or null if not initialized\n *\n * @example\n * ```typescript\n * const analytics = createAnalytics({ business: 'myapp', ... });\n * const posthogProvider = analytics.getProvider('posthog');\n * const posthog = posthogProvider.getNativeInstance();\n *\n * // These calls will automatically include spm: 'myapp'\n * posthog?.capture('custom_event', { custom: 'data' });\n * posthog?.isFeatureEnabled('new_feature');\n * posthog?.group('company', 'company_123');\n * ```\n */\n getNativeInstance(): typeof posthog | null {\n if (!this.isEnabled() || !this.initialized) {\n this.log('Cannot get native instance: provider not enabled or not initialized');\n return null;\n }\n\n return posthog;\n }\n\n /**\n * Create a before_send handler that adds business context to all events\n * This ensures both wrapper calls and direct PostHog calls include business information\n */\n private createBeforeSendHandler(userBeforeSend?: BeforeSendFn | BeforeSendFn[]): BeforeSendFn {\n return (event: CaptureResult | null): CaptureResult | null => {\n // Return null if event is null\n if (!event) {\n return null;\n }\n\n // Record whether user originally had spm field\n const originallyHadSpm = event.properties?.spm !== undefined;\n\n // Call user's before_send first if provided\n let processedEvent: CaptureResult | null = event;\n if (userBeforeSend) {\n if (Array.isArray(userBeforeSend)) {\n // Handle array of before_send functions\n for (const fn of userBeforeSend) {\n processedEvent = fn(processedEvent);\n if (!processedEvent) {\n return null; // User function filtered out the event\n }\n }\n } else if (typeof userBeforeSend === 'function') {\n processedEvent = userBeforeSend(processedEvent);\n if (!processedEvent) {\n return null; // User function filtered out the event\n }\n }\n }\n\n // Ensure properties object exists\n if (!processedEvent.properties) {\n processedEvent.properties = {};\n }\n\n // Always ensure business field is present (final override to prevent user deletion)\n processedEvent.properties.business = this.business;\n\n // Set spm only if:\n // 1. User didn't originally have spm AND\n // 2. User's before_send didn't add spm OR added empty spm\n const currentSpm = processedEvent.properties.spm;\n const shouldSetDefaultSpm =\n !originallyHadSpm &&\n (!currentSpm || (typeof currentSpm === 'string' && !currentSpm.trim()));\n\n if (shouldSetDefaultSpm) {\n processedEvent.properties.spm = this.business;\n }\n\n return processedEvent;\n };\n }\n\n /**\n * Update the business context dynamically\n * This will affect all future events\n */\n updateBusiness(newBusiness: string): void {\n if (!this.isEnabled() || !this.initialized) {\n this.log('Cannot update business: provider not enabled or not initialized');\n return;\n }\n\n // Note: We can't change the readonly business field, but we could store it in a mutable field\n // For now, log that this feature would need architectural changes\n this.log(`Business update requested: ${newBusiness} (current: ${this.business})`);\n this.log('Note: Dynamic business updates require storing business in a mutable field');\n }\n\n /**\n * Get current business context\n */\n getCurrentBusiness(): string {\n return this.business;\n }\n}\n","/**\n * Global Analytics Instance Manager\n *\n * 提供全局实例管理功能,支持:\n * 1. 全局实例注册和获取\n * 2. 单例模式\n * 3. 命名空间支持\n *\n * 使用 globalThis 确保跨模块实例的状态一致性\n */\nimport { createAnalytics } from './config';\nimport type { AnalyticsManager } from './manager';\nimport type { AnalyticsConfig } from './types';\n\n/**\n * 全局状态键名,确保唯一性\n */\nconst GLOBAL_STATE_KEY = '__LOBE_ANALYTICS_GLOBAL_STATE__';\n\n/**\n * 扩展 globalThis 类型\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __LOBE_ANALYTICS_GLOBAL_STATE__: GlobalAnalyticsState | undefined;\n}\n\n/**\n * 全局状态接口\n */\ninterface GlobalAnalyticsState {\n instances: Map<string, AnalyticsManager>;\n singletonConfig: AnalyticsConfig | null;\n singletonInstance: AnalyticsManager | null;\n}\n\n/**\n * 获取全局状态,确保跨模块实例的一致性\n */\nfunction getGlobalState(): GlobalAnalyticsState {\n if (!globalThis[GLOBAL_STATE_KEY]) {\n globalThis[GLOBAL_STATE_KEY] = {\n instances: new Map<string, AnalyticsManager>(),\n singletonConfig: null,\n singletonInstance: null,\n };\n }\n return globalThis[GLOBAL_STATE_KEY];\n}\n\n/**\n * 默认实例名称\n */\nconst DEFAULT_INSTANCE_NAME = '__default__';\n\n/**\n * 注册全局 Analytics 实例\n *\n * @param instance Analytics 管理器实例\n * @param name 实例名称,默认为 '__default__'\n *\n * @example\n * ```typescript\n * const analytics = createAnalytics({ ... });\n * setGlobalAnalytics(analytics);\n * ```\n */\nexport function setGlobalAnalytics(\n instance: AnalyticsManager,\n name: string = DEFAULT_INSTANCE_NAME,\n): void {\n const state = getGlobalState();\n state.instances.set(name, instance);\n}\n\n/**\n * 获取全局 Analytics 实例\n *\n * @param name 实例名称,默认为 '__default__'\n * @returns Analytics 管理器实例\n * @throws {Error} 如果实例不存在\n *\n * @example\n * ```typescript\n * // 在任何文件中使用\n * const analytics = getGlobalAnalytics();\n * analytics.track({ name: 'some_event' });\n * ```\n */\nexport function getGlobalAnalytics(name: string = DEFAULT_INSTANCE_NAME): AnalyticsManager {\n const state = getGlobalState();\n const instance = state.instances.get(name);\n\n if (!instance) {\n throw new Error(\n `Global analytics instance \"${name}\" not found. ` +\n `Make sure to register it first using setGlobalAnalytics() or use AnalyticsProvider.`,\n );\n }\n\n return instance;\n}\n\n/**\n * 获取全局 Analytics 实例(可选,不抛出错误)\n *\n * @param name 实例名称,默认为 '__default__'\n * @returns Analytics 管理器实例或 null\n *\n * @example\n * ```typescript\n * const analytics = getGlobalAnalyticsOptional();\n * analytics?.track({ name: 'optional_event' });\n * ```\n */\nexport function getGlobalAnalyticsOptional(\n name: string = DEFAULT_INSTANCE_NAME,\n): AnalyticsManager | null {\n const state = getGlobalState();\n return state.instances.get(name) || null;\n}\n\n/**\n * 检查全局实例是否存在\n *\n * @param name 实例名称,默认为 '__default__'\n * @returns 是否存在\n */\nexport function hasGlobalAnalytics(name: string = DEFAULT_INSTANCE_NAME): boolean {\n const state = getGlobalState();\n return state.instances.has(name);\n}\n\n/**\n * 移除全局 Analytics 实例\n *\n * @param name 实例名称,默认为 '__default__'\n * @returns 是否成功移除\n */\nexport function removeGlobalAnalytics(name: string = DEFAULT_INSTANCE_NAME): boolean {\n const state = getGlobalState();\n return state.instances.delete(name);\n}\n\n/**\n * 清除所有全局实例\n */\nexport function clearGlobalAnalytics(): void {\n const state = getGlobalState();\n state.instances.clear();\n}\n\n/**\n * 获取所有已注册的实例名称\n *\n * @returns 实例名称数组\n */\nexport function getGlobalAnalyticsNames(): string[] {\n const state = getGlobalState();\n return Array.from(state.instances.keys());\n}\n\n/**\n * 简单的配置比较函数\n *\n * 注意:这是一个简化的实现,仅比较 JSON 序列化后的字符串\n * 对于复杂对象可能不够准确,但对于大多数配置场景是足够的\n */\nfunction isConfigEqual(config1: AnalyticsConfig, config2: AnalyticsConfig): boolean {\n try {\n return JSON.stringify(config1) === JSON.stringify(config2);\n } catch {\n return false;\n }\n}\n\n/**\n * 创建或获取单例 Analytics 实例\n *\n * 单例模式适用于整个应用只需要一个 Analytics 配置的场景。\n * 如果已存在单例且配置相同,返回现有实例;否则创建新实例。\n *\n * @param config Analytics 配置\n * @returns Analytics 管理器实例\n *\n * @example\n * ```typescript\n * // 在应用启动时创建\n * const analytics = createSingletonAnalytics({\n * debug: true,\n * providers: {\n * posthog: {\n * enabled: true,\n * key: 'your_key',\n * host: 'https://app.posthog.com',\n * },\n * },\n * });\n *\n * // 在其他地方获取同一实例\n * const sameAnalytics = getSingletonAnalytics();\n * ```\n */\nexport function createSingletonAnalytics(config: AnalyticsConfig): AnalyticsManager {\n const state = getGlobalState();\n\n // 检查是否已存在相同配置的单例\n if (\n state.singletonInstance &&\n state.singletonConfig &&\n isConfigEqual(state.singletonConfig, config)\n ) {\n return state.singletonInstance;\n }\n\n // 创建新的单例实例\n state.singletonInstance = createAnalytics(config);\n state.singletonConfig = config;\n\n // 同时注册为全局默认实例\n setGlobalAnalytics(state.singletonInstance);\n\n return state.singletonInstance;\n}\n\n/**\n * 获取单例 Analytics 实例\n *\n * @returns Analytics 管理器实例\n * @throws {Error} 如果单例未创建\n *\n * @example\n * ```typescript\n * const analytics = getSingletonAnalytics();\n * analytics.track({ name: 'some_event' });\n * ```\n */\nexport function getSingletonAnalytics(): AnalyticsManager {\n const state = getGlobalState();\n\n if (!state.singletonInstance) {\n throw new Error(\n 'Singleton analytics instance not created. ' +\n 'Call createSingletonAnalytics() first or use getGlobalAnalytics().',\n );\n }\n\n return state.singletonInstance;\n}\n\n/**\n * 获取单例 Analytics 实例(可选,不抛出错误)\n *\n * @returns Analytics 管理器实例或 null\n */\nexport function getSingletonAnalyticsOptional(): AnalyticsManager | null {\n const state = getGlobalState();\n return state.singletonInstance;\n}\n\n/**\n * 检查单例是否已创建\n *\n * @returns 是否存在单例\n */\nexport function hasSingletonAnalytics(): boolean {\n const state = getGlobalState();\n return state.singletonInstance !== null;\n}\n\n/**\n * 重置单例实例\n *\n * 主要用于测试场景\n */\nexport function resetSingletonAnalytics(): void {\n const state = getGlobalState();\n state.singletonInstance = null;\n state.singletonConfig = null;\n}\n","// React hooks for Analytics integration\n// Note: React is a peer dependency\nimport { useCallback } from 'react';\n\nimport type { AnalyticsEvent, PredefinedEvents } from '@/types';\n\nexport type AnalyticsManager = import('../manager').AnalyticsManager;\n\n/**\n * Analytics Hook\n * Provides core analytics functionality\n *\n * @param manager User-created AnalyticsManager instance\n * @example\n * ```typescript\n * const analytics = createAnalytics({ ... });\n * await analytics.initialize();\n *\n * function MyComponent() {\n * const { track, identify } = useAnalytics(analytics);\n * // ...\n * }\n * ```\n */\nexport function useAnalytics(manager: AnalyticsManager) {\n const track = useCallback((event: AnalyticsEvent) => manager.track(event), [manager]);\n\n const trackEvent = useCallback(\n <K extends keyof PredefinedEvents>(eventName: K, properties: PredefinedEvents[K]) =>\n manager.trackEvent(eventName, properties),\n [manager],\n );\n\n const identify = useCallback(\n (userId: string, properties?: Record<string, any>) => manager.identify(userId, properties),\n [manager],\n );\n\n const trackPageView = useCallback(\n (page: string, properties?: Record<string, any>) => manager.trackPageView(page, properties),\n [manager],\n );\n\n const reset = useCallback(() => manager.reset(), [manager]);\n\n return {\n identify,\n reset,\n track,\n trackEvent,\n trackPageView,\n };\n}\n\n/**\n * Event Tracking Hook\n * Provides convenient event tracking methods\n */\nexport function useEventTracking(manager: AnalyticsManager) {\n const { trackEvent } = useAnalytics(manager);\n\n const trackButtonClick = useCallback(\n (buttonName: string, context?: Record<string, any>) =>\n trackEvent('button_click', { button_name: buttonName, ...context }),\n [trackEvent],\n );\n\n const trackFormSubmit = useCallback(\n (formName: string, success: boolean) =>\n manager.track({\n name: 'form_submit',\n properties: { form_name: formName, success },\n }),\n [manager],\n );\n\n const trackUserSignup = useCallback(\n (spm?: string, extraProperties?: Record<string, any>) =>\n trackEvent('user_signup', { spm, ...extraProperties }),\n [trackEvent],\n );\n\n const trackUserLogin = useCallback(\n (spm?: string, extraProperties?: Record<string, any>) =>\n trackEvent('user_login', { spm, ...extraProperties }),\n [trackEvent],\n );\n\n return {\n trackButtonClick,\n trackFormSubmit,\n trackUserLogin,\n trackUserSignup,\n };\n}\n\n/**\n * 页面浏览追踪 Hook\n * 自动在组件挂载时追踪页面浏览\n *\n * @param manager 用户创建的 AnalyticsManager 实例\n * @param page 页面路径\n * @param properties 页面属性\n */\nexport function usePageTracking(\n manager: AnalyticsManager,\n page: string,\n properties?: Record<string, any>,\n) {\n const { trackPageView } = useAnalytics(manager);\n\n // 注意:在库中我们不自动调用 useEffect\n // 而是返回追踪函数,让用户决定何时调用\n return useCallback(() => {\n trackPageView(page, properties);\n }, [trackPageView, page, properties]);\n}\n"],"mappings":"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","names":["error","import_react","useAnalytics"]}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// src/react/provider.tsx
|
|
2
|
+
import { createContext, useContext, useLayoutEffect, useState } from "react";
|
|
3
|
+
|
|
4
|
+
// src/providers/posthog.ts
|
|
5
|
+
import { posthog } from "posthog-js";
|
|
6
|
+
|
|
7
|
+
// src/global.ts
|
|
8
|
+
var GLOBAL_STATE_KEY = "__LOBE_ANALYTICS_GLOBAL_STATE__";
|
|
9
|
+
function getGlobalState() {
|
|
10
|
+
if (!globalThis[GLOBAL_STATE_KEY]) {
|
|
11
|
+
globalThis[GLOBAL_STATE_KEY] = {
|
|
12
|
+
instances: /* @__PURE__ */ new Map(),
|
|
13
|
+
singletonConfig: null,
|
|
14
|
+
singletonInstance: null
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return globalThis[GLOBAL_STATE_KEY];
|
|
18
|
+
}
|
|
19
|
+
var DEFAULT_INSTANCE_NAME = "__default__";
|
|
20
|
+
function setGlobalAnalytics(instance, name = DEFAULT_INSTANCE_NAME) {
|
|
21
|
+
const state = getGlobalState();
|
|
22
|
+
state.instances.set(name, instance);
|
|
23
|
+
}
|
|
24
|
+
function getGlobalAnalytics(name = DEFAULT_INSTANCE_NAME) {
|
|
25
|
+
const state = getGlobalState();
|
|
26
|
+
const instance = state.instances.get(name);
|
|
27
|
+
if (!instance) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Global analytics instance "${name}" not found. Make sure to register it first using setGlobalAnalytics() or use AnalyticsProvider.`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return instance;
|
|
33
|
+
}
|
|
34
|
+
function getGlobalAnalyticsOptional(name = DEFAULT_INSTANCE_NAME) {
|
|
35
|
+
const state = getGlobalState();
|
|
36
|
+
return state.instances.get(name) || null;
|
|
37
|
+
}
|
|
38
|
+
function getSingletonAnalytics() {
|
|
39
|
+
const state = getGlobalState();
|
|
40
|
+
if (!state.singletonInstance) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
"Singleton analytics instance not created. Call createSingletonAnalytics() first or use getGlobalAnalytics()."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return state.singletonInstance;
|
|
46
|
+
}
|
|
47
|
+
function getSingletonAnalyticsOptional() {
|
|
48
|
+
const state = getGlobalState();
|
|
49
|
+
return state.singletonInstance;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/react/provider.tsx
|
|
53
|
+
import { jsx } from "react/jsx-runtime";
|
|
54
|
+
var AnalyticsContext = createContext(void 0);
|
|
55
|
+
function AnalyticsProvider({
|
|
56
|
+
client,
|
|
57
|
+
children,
|
|
58
|
+
autoInitialize = true,
|
|
59
|
+
globalName = "__default__",
|
|
60
|
+
onInitializeError,
|
|
61
|
+
onInitializeSuccess,
|
|
62
|
+
registerGlobal = true
|
|
63
|
+
}) {
|
|
64
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
65
|
+
const [isInitializing, setIsInitializing] = useState(false);
|
|
66
|
+
const [error, setError] = useState(null);
|
|
67
|
+
useLayoutEffect(() => {
|
|
68
|
+
if (registerGlobal) {
|
|
69
|
+
setGlobalAnalytics(client, globalName);
|
|
70
|
+
}
|
|
71
|
+
}, [client, globalName, registerGlobal]);
|
|
72
|
+
useLayoutEffect(() => {
|
|
73
|
+
if (!autoInitialize || isInitialized || isInitializing) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const initializeAnalytics = async () => {
|
|
77
|
+
setIsInitializing(true);
|
|
78
|
+
setError(null);
|
|
79
|
+
try {
|
|
80
|
+
await client.initialize();
|
|
81
|
+
setIsInitialized(true);
|
|
82
|
+
onInitializeSuccess == null ? void 0 : onInitializeSuccess();
|
|
83
|
+
} catch (error_) {
|
|
84
|
+
const error2 = error_ instanceof Error ? error_ : new Error("Analytics initialization failed");
|
|
85
|
+
setError(error2);
|
|
86
|
+
onInitializeError == null ? void 0 : onInitializeError(error2);
|
|
87
|
+
console.error("[AnalyticsProvider] Initialization failed:", error2);
|
|
88
|
+
} finally {
|
|
89
|
+
setIsInitializing(false);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
initializeAnalytics();
|
|
93
|
+
}, [
|
|
94
|
+
client,
|
|
95
|
+
autoInitialize,
|
|
96
|
+
isInitialized,
|
|
97
|
+
isInitializing,
|
|
98
|
+
onInitializeError,
|
|
99
|
+
onInitializeSuccess
|
|
100
|
+
]);
|
|
101
|
+
const contextValue = {
|
|
102
|
+
analytics: client,
|
|
103
|
+
error,
|
|
104
|
+
isInitialized,
|
|
105
|
+
isInitializing
|
|
106
|
+
};
|
|
107
|
+
return /* @__PURE__ */ jsx(AnalyticsContext.Provider, { value: contextValue, children });
|
|
108
|
+
}
|
|
109
|
+
function useAnalyticsContext() {
|
|
110
|
+
const context = useContext(AnalyticsContext);
|
|
111
|
+
if (context === void 0) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
"useAnalyticsContext must be used within an AnalyticsProvider. Wrap your component tree with <AnalyticsProvider client={analytics}>"
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return context;
|
|
117
|
+
}
|
|
118
|
+
function useAnalytics() {
|
|
119
|
+
const { analytics, isInitialized, isInitializing, error } = useAnalyticsContext();
|
|
120
|
+
return {
|
|
121
|
+
/** Analytics 实例(仅在就绪时可用) */
|
|
122
|
+
analytics: isInitialized && !error ? analytics : null,
|
|
123
|
+
/** 是否发生错误 */
|
|
124
|
+
error,
|
|
125
|
+
/** 是否已初始化 */
|
|
126
|
+
isInitialized,
|
|
127
|
+
/** 是否正在初始化 */
|
|
128
|
+
isInitializing,
|
|
129
|
+
/** 是否就绪(已初始化且无错误) */
|
|
130
|
+
isReady: isInitialized && !error && analytics !== null
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function useAnalyticsStrict() {
|
|
134
|
+
const { analytics, isInitialized, isInitializing, error } = useAnalyticsContext();
|
|
135
|
+
if (error) {
|
|
136
|
+
throw new Error(`[useAnalyticsStrict] Analytics initialization failed: ${error.message}`);
|
|
137
|
+
}
|
|
138
|
+
if (!isInitialized) {
|
|
139
|
+
if (isInitializing) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
"[useAnalyticsStrict] Analytics is still initializing. Use useAnalyticsState to check status."
|
|
142
|
+
);
|
|
143
|
+
} else {
|
|
144
|
+
throw new Error(
|
|
145
|
+
"[useAnalyticsStrict] Analytics not initialized. Set autoInitialize=true or call initialize manually."
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (!analytics) {
|
|
150
|
+
throw new Error("[useAnalyticsStrict] Analytics instance is null");
|
|
151
|
+
}
|
|
152
|
+
return analytics;
|
|
153
|
+
}
|
|
154
|
+
function useAnalyticsState() {
|
|
155
|
+
const { error, isInitialized, isInitializing } = useAnalyticsContext();
|
|
156
|
+
return {
|
|
157
|
+
error,
|
|
158
|
+
isInitialized,
|
|
159
|
+
isInitializing,
|
|
160
|
+
isReady: isInitialized && !error
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function useAnalyticsOptional() {
|
|
164
|
+
const { analytics } = useAnalytics();
|
|
165
|
+
return analytics;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// src/react/hooks.ts
|
|
169
|
+
import { useCallback } from "react";
|
|
170
|
+
function useAnalytics2(manager) {
|
|
171
|
+
const track = useCallback((event) => manager.track(event), [manager]);
|
|
172
|
+
const trackEvent = useCallback(
|
|
173
|
+
(eventName, properties) => manager.trackEvent(eventName, properties),
|
|
174
|
+
[manager]
|
|
175
|
+
);
|
|
176
|
+
const identify = useCallback(
|
|
177
|
+
(userId, properties) => manager.identify(userId, properties),
|
|
178
|
+
[manager]
|
|
179
|
+
);
|
|
180
|
+
const trackPageView = useCallback(
|
|
181
|
+
(page, properties) => manager.trackPageView(page, properties),
|
|
182
|
+
[manager]
|
|
183
|
+
);
|
|
184
|
+
const reset = useCallback(() => manager.reset(), [manager]);
|
|
185
|
+
return {
|
|
186
|
+
identify,
|
|
187
|
+
reset,
|
|
188
|
+
track,
|
|
189
|
+
trackEvent,
|
|
190
|
+
trackPageView
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function useEventTracking(manager) {
|
|
194
|
+
const { trackEvent } = useAnalytics2(manager);
|
|
195
|
+
const trackButtonClick = useCallback(
|
|
196
|
+
(buttonName, context) => trackEvent("button_click", { button_name: buttonName, ...context }),
|
|
197
|
+
[trackEvent]
|
|
198
|
+
);
|
|
199
|
+
const trackFormSubmit = useCallback(
|
|
200
|
+
(formName, success) => manager.track({
|
|
201
|
+
name: "form_submit",
|
|
202
|
+
properties: { form_name: formName, success }
|
|
203
|
+
}),
|
|
204
|
+
[manager]
|
|
205
|
+
);
|
|
206
|
+
const trackUserSignup = useCallback(
|
|
207
|
+
(spm, extraProperties) => trackEvent("user_signup", { spm, ...extraProperties }),
|
|
208
|
+
[trackEvent]
|
|
209
|
+
);
|
|
210
|
+
const trackUserLogin = useCallback(
|
|
211
|
+
(spm, extraProperties) => trackEvent("user_login", { spm, ...extraProperties }),
|
|
212
|
+
[trackEvent]
|
|
213
|
+
);
|
|
214
|
+
return {
|
|
215
|
+
trackButtonClick,
|
|
216
|
+
trackFormSubmit,
|
|
217
|
+
trackUserLogin,
|
|
218
|
+
trackUserSignup
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
export {
|
|
222
|
+
AnalyticsProvider,
|
|
223
|
+
getGlobalAnalytics,
|
|
224
|
+
getGlobalAnalyticsOptional,
|
|
225
|
+
getSingletonAnalytics,
|
|
226
|
+
getSingletonAnalyticsOptional,
|
|
227
|
+
useAnalytics,
|
|
228
|
+
useAnalyticsOptional,
|
|
229
|
+
useAnalyticsState,
|
|
230
|
+
useAnalyticsStrict,
|
|
231
|
+
useEventTracking
|
|
232
|
+
};
|
|
233
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/provider.tsx","../../src/providers/posthog.ts","../../src/global.ts","../../src/react/hooks.ts"],"sourcesContent":["'use client';\n\nimport React, { type ReactNode, createContext, useContext, useLayoutEffect, useState } from 'react';\n\nimport { setGlobalAnalytics } from '../global';\nimport type { AnalyticsManager } from '../manager';\n\n/**\n * Analytics Context 类型定义\n */\ninterface AnalyticsContextValue {\n analytics: AnalyticsManager | null;\n error: Error | null;\n isInitialized: boolean;\n isInitializing: boolean;\n}\n\n/**\n * Analytics Context\n */\nconst AnalyticsContext = createContext<AnalyticsContextValue | undefined>(undefined);\n\n/**\n * Analytics Provider Props\n */\ninterface AnalyticsProviderProps {\n /** 是否自动初始化(默认: true) */\n autoInitialize?: boolean;\n /** 子组件 */\n children: ReactNode;\n /** 配置好的 Analytics 实例 */\n client: AnalyticsManager;\n /** 全局实例名称,用于全局访问(默认: '__default__') */\n globalName?: string;\n /** 初始化失败时的回调 */\n onInitializeError?: (error: Error) => void;\n /** 初始化成功时的回调 */\n onInitializeSuccess?: () => void;\n /** 是否注册为全局实例(默认: true) */\n registerGlobal?: boolean;\n}\n\n/**\n * Analytics Provider 组件\n *\n * 提供 Analytics 实例给整个 React 应用树,并处理初始化逻辑\n *\n * @example\n * ```tsx\n * import { createAnalytics, AnalyticsProvider } from '@lobehub/analytics';\n *\n * const analytics = createAnalytics({\n * debug: true,\n * providers: {\n * posthog: {\n * enabled: true,\n * key: 'phc_your_key',\n * host: 'https://app.posthog.com',\n * },\n * },\n * });\n *\n * function App() {\n * return (\n * <AnalyticsProvider client={analytics}>\n * <MyApp />\n * </AnalyticsProvider>\n * );\n * }\n * ```\n */\nexport function AnalyticsProvider({\n client,\n children,\n autoInitialize = true,\n globalName = '__default__',\n onInitializeError,\n onInitializeSuccess,\n registerGlobal = true,\n}: AnalyticsProviderProps) {\n const [isInitialized, setIsInitialized] = useState(false);\n const [isInitializing, setIsInitializing] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // 注册为全局实例\n useLayoutEffect(() => {\n if (registerGlobal) {\n setGlobalAnalytics(client, globalName);\n }\n }, [client, globalName, registerGlobal]);\n\n useLayoutEffect(() => {\n if (!autoInitialize || isInitialized || isInitializing) {\n return;\n }\n\n const initializeAnalytics = async () => {\n setIsInitializing(true);\n setError(null);\n\n try {\n await client.initialize();\n setIsInitialized(true);\n onInitializeSuccess?.();\n } catch (error_) {\n const error =\n error_ instanceof Error ? error_ : new Error('Analytics initialization failed');\n setError(error);\n onInitializeError?.(error);\n console.error('[AnalyticsProvider] Initialization failed:', error);\n } finally {\n setIsInitializing(false);\n }\n };\n\n initializeAnalytics();\n }, [\n client,\n autoInitialize,\n isInitialized,\n isInitializing,\n onInitializeError,\n onInitializeSuccess,\n ]);\n\n const contextValue: AnalyticsContextValue = {\n analytics: client,\n error,\n isInitialized,\n isInitializing,\n };\n\n return <AnalyticsContext.Provider value={contextValue}>{children}</AnalyticsContext.Provider>;\n}\n\n/**\n * 获取 Analytics Context\n *\n * @throws {Error} 如果在 AnalyticsProvider 外使用\n */\nfunction useAnalyticsContext(): AnalyticsContextValue {\n const context = useContext(AnalyticsContext);\n\n if (context === undefined) {\n throw new Error(\n 'useAnalyticsContext must be used within an AnalyticsProvider. ' +\n 'Wrap your component tree with <AnalyticsProvider client={analytics}>',\n );\n }\n\n return context;\n}\n\n/**\n * 获取 Analytics 实例(安全版本,不抛出错误)\n *\n * @returns Analytics 实例或 null,以及状态信息\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { analytics, isReady, error } = useAnalytics();\n *\n * if (!isReady) {\n * return <div>Analytics not ready</div>;\n * }\n *\n * const handleClick = () => {\n * analytics?.track({ name: 'button_click' });\n * };\n *\n * return <button onClick={handleClick}>Click me</button>;\n * }\n * ```\n */\nexport function useAnalytics() {\n const { analytics, isInitialized, isInitializing, error } = useAnalyticsContext();\n\n return {\n /** Analytics 实例(仅在就绪时可用) */\n analytics: isInitialized && !error ? analytics : null,\n /** 是否发生错误 */\n error,\n /** 是否已初始化 */\n isInitialized,\n /** 是否正在初始化 */\n isInitializing,\n /** 是否就绪(已初始化且无错误) */\n isReady: isInitialized && !error && analytics !== null,\n };\n}\n\n/**\n * 获取 Analytics 实例(严格版本,抛出错误)\n *\n * @returns Analytics 实例\n * @throws {Error} 如果在 AnalyticsProvider 外使用或实例未就绪\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const analytics = useAnalyticsStrict();\n *\n * const handleClick = () => {\n * analytics.track({ name: 'button_click' });\n * };\n *\n * return <button onClick={handleClick}>Click me</button>;\n * }\n * ```\n */\nexport function useAnalyticsStrict(): AnalyticsManager {\n const { analytics, isInitialized, isInitializing, error } = useAnalyticsContext();\n\n if (error) {\n throw new Error(`[useAnalyticsStrict] Analytics initialization failed: ${error.message}`);\n }\n\n if (!isInitialized) {\n if (isInitializing) {\n throw new Error(\n '[useAnalyticsStrict] Analytics is still initializing. Use useAnalyticsState to check status.',\n );\n } else {\n throw new Error(\n '[useAnalyticsStrict] Analytics not initialized. Set autoInitialize=true or call initialize manually.',\n );\n }\n }\n\n if (!analytics) {\n throw new Error('[useAnalyticsStrict] Analytics instance is null');\n }\n\n return analytics;\n}\n\n/**\n * 获取 Analytics 状态信息\n *\n * @returns Analytics 状态\n *\n * @example\n * ```tsx\n * function LoadingComponent() {\n * const { isInitialized, isInitializing, error } = useAnalyticsState();\n *\n * if (isInitializing) return <div>Loading analytics...</div>;\n * if (error) return <div>Analytics failed: {error.message}</div>;\n * if (!isInitialized) return <div>Analytics not ready</div>;\n *\n * return <MyApp />;\n * }\n * ```\n */\nexport function useAnalyticsState() {\n const { error, isInitialized, isInitializing } = useAnalyticsContext();\n\n return {\n error,\n isInitialized,\n isInitializing,\n isReady: isInitialized && !error,\n };\n}\n\n/**\n * 获取 Analytics 实例(可选,不抛出错误)\n *\n * @deprecated 请使用 `useAnalytics()` 代替,它现在提供相同的安全访问\n * @returns Analytics 实例或 null\n *\n * @example\n * ```tsx\n * function OptionalTracking() {\n * const analytics = useAnalyticsOptional();\n *\n * const handleOptionalEvent = () => {\n * analytics?.track({ name: 'optional_event' });\n * };\n *\n * return <button onClick={handleOptionalEvent}>Optional Track</button>;\n * }\n * ```\n */\nexport function useAnalyticsOptional(): AnalyticsManager | null {\n const { analytics } = useAnalytics();\n return analytics;\n}\n","import { BeforeSendFn, CaptureResult, posthog } from 'posthog-js';\n\nimport { BaseAnalytics } from '@/base';\nimport type { AnalyticsEvent, PostHogProviderAnalyticsConfig } from '@/types';\n\n/**\n * PostHog Analytics Provider\n * Uses official posthog-js SDK\n */\nexport class PostHogAnalyticsProvider extends BaseAnalytics {\n private readonly config: PostHogProviderAnalyticsConfig;\n private initialized = false;\n\n constructor(config: PostHogProviderAnalyticsConfig, business: string) {\n super({ business, debug: config.debug, enabled: config.enabled });\n this.config = config;\n }\n\n getProviderName(): string {\n return 'PostHog';\n }\n\n async initialize(): Promise<void> {\n if (!this.isEnabled() || this.initialized) {\n return;\n }\n\n try {\n // Extract provider-specific properties and prepare posthog config\n const { key, host, ...posthogConfig } = this.config;\n\n // Build init config: start with user's posthog config, then apply our defaults/overrides\n const initConfig = {\n ...posthogConfig, // User's posthog-js config options\n api_host: host || posthogConfig.api_host || 'https://app.posthog.com',\n // Use before_send to dynamically add business context to all events\n before_send: this.createBeforeSendHandler(posthogConfig.before_send),\n debug: this.debug,\n loaded: () => this.log('PostHog loaded and ready'),\n };\n\n posthog.init(key, initConfig);\n\n this.initialized = true;\n this.log('PostHog initialized successfully');\n this.log(`Using before_send to add business context: ${this.business}`);\n } catch (error) {\n this.logError('Failed to initialize PostHog', error);\n throw error;\n }\n }\n\n async track(event: AnalyticsEvent): Promise<void> {\n if (!this.isEnabled() || !this.initialized || !this.validateEvent(event)) {\n return;\n }\n\n try {\n const enrichedProperties = this.enrichProperties(event.properties);\n\n posthog.capture(event.name, {\n ...enrichedProperties,\n ...(event.userId && { distinct_id: event.userId }),\n });\n\n this.log(`Tracked event: ${event.name}`, { ...event, properties: enrichedProperties });\n } catch (error) {\n this.logError(`Failed to track event: ${event.name}`, error);\n }\n }\n\n async identify(userId: string, properties?: Record<string, any>): Promise<void> {\n if (!this.isEnabled() || !this.initialized) {\n return;\n }\n\n try {\n const enrichedProperties = this.enrichProperties(properties);\n posthog.identify(userId, enrichedProperties);\n this.log(`Identified user: ${userId}`, enrichedProperties);\n } catch (error) {\n this.logError(`Failed to identify user: ${userId}`, error);\n }\n }\n\n async trackPageView(page: string, properties?: Record<string, any>): Promise<void> {\n if (!this.isEnabled() || !this.initialized) {\n return;\n }\n\n try {\n const enrichedProperties = this.enrichProperties(properties);\n await this.track({\n name: '$pageview',\n properties: { page, ...enrichedProperties },\n });\n\n this.log(`Tracked page view: ${page}`, enrichedProperties);\n } catch (error) {\n this.logError(`Failed to track page view: ${page}`, error);\n }\n }\n\n async reset(): Promise<void> {\n if (!this.isEnabled() || !this.initialized) {\n return;\n }\n\n try {\n posthog.reset();\n this.log('Reset user identity');\n } catch (error) {\n this.logError('Failed to reset user identity', error);\n }\n }\n\n /**\n * Check if feature flag is enabled\n */\n isFeatureEnabled(flag: string): boolean {\n if (!this.initialized) {\n return false;\n }\n\n try {\n return Boolean(posthog.isFeatureEnabled(flag));\n } catch (error) {\n this.logError(`Failed to check feature flag: ${flag}`, error);\n return false;\n }\n }\n\n /**\n * Get the native PostHog instance for direct access to PostHog APIs\n *\n * Note: When using the native instance directly, events will still include\n * the business spm prefix because it's registered as a global property.\n *\n * @returns PostHog native instance or null if not initialized\n *\n * @example\n * ```typescript\n * const analytics = createAnalytics({ business: 'myapp', ... });\n * const posthogProvider = analytics.getProvider('posthog');\n * const posthog = posthogProvider.getNativeInstance();\n *\n * // These calls will automatically include spm: 'myapp'\n * posthog?.capture('custom_event', { custom: 'data' });\n * posthog?.isFeatureEnabled('new_feature');\n * posthog?.group('company', 'company_123');\n * ```\n */\n getNativeInstance(): typeof posthog | null {\n if (!this.isEnabled() || !this.initialized) {\n this.log('Cannot get native instance: provider not enabled or not initialized');\n return null;\n }\n\n return posthog;\n }\n\n /**\n * Create a before_send handler that adds business context to all events\n * This ensures both wrapper calls and direct PostHog calls include business information\n */\n private createBeforeSendHandler(userBeforeSend?: BeforeSendFn | BeforeSendFn[]): BeforeSendFn {\n return (event: CaptureResult | null): CaptureResult | null => {\n // Return null if event is null\n if (!event) {\n return null;\n }\n\n // Record whether user originally had spm field\n const originallyHadSpm = event.properties?.spm !== undefined;\n\n // Call user's before_send first if provided\n let processedEvent: CaptureResult | null = event;\n if (userBeforeSend) {\n if (Array.isArray(userBeforeSend)) {\n // Handle array of before_send functions\n for (const fn of userBeforeSend) {\n processedEvent = fn(processedEvent);\n if (!processedEvent) {\n return null; // User function filtered out the event\n }\n }\n } else if (typeof userBeforeSend === 'function') {\n processedEvent = userBeforeSend(processedEvent);\n if (!processedEvent) {\n return null; // User function filtered out the event\n }\n }\n }\n\n // Ensure properties object exists\n if (!processedEvent.properties) {\n processedEvent.properties = {};\n }\n\n // Always ensure business field is present (final override to prevent user deletion)\n processedEvent.properties.business = this.business;\n\n // Set spm only if:\n // 1. User didn't originally have spm AND\n // 2. User's before_send didn't add spm OR added empty spm\n const currentSpm = processedEvent.properties.spm;\n const shouldSetDefaultSpm =\n !originallyHadSpm &&\n (!currentSpm || (typeof currentSpm === 'string' && !currentSpm.trim()));\n\n if (shouldSetDefaultSpm) {\n processedEvent.properties.spm = this.business;\n }\n\n return processedEvent;\n };\n }\n\n /**\n * Update the business context dynamically\n * This will affect all future events\n */\n updateBusiness(newBusiness: string): void {\n if (!this.isEnabled() || !this.initialized) {\n this.log('Cannot update business: provider not enabled or not initialized');\n return;\n }\n\n // Note: We can't change the readonly business field, but we could store it in a mutable field\n // For now, log that this feature would need architectural changes\n this.log(`Business update requested: ${newBusiness} (current: ${this.business})`);\n this.log('Note: Dynamic business updates require storing business in a mutable field');\n }\n\n /**\n * Get current business context\n */\n getCurrentBusiness(): string {\n return this.business;\n }\n}\n","/**\n * Global Analytics Instance Manager\n *\n * 提供全局实例管理功能,支持:\n * 1. 全局实例注册和获取\n * 2. 单例模式\n * 3. 命名空间支持\n *\n * 使用 globalThis 确保跨模块实例的状态一致性\n */\nimport { createAnalytics } from './config';\nimport type { AnalyticsManager } from './manager';\nimport type { AnalyticsConfig } from './types';\n\n/**\n * 全局状态键名,确保唯一性\n */\nconst GLOBAL_STATE_KEY = '__LOBE_ANALYTICS_GLOBAL_STATE__';\n\n/**\n * 扩展 globalThis 类型\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __LOBE_ANALYTICS_GLOBAL_STATE__: GlobalAnalyticsState | undefined;\n}\n\n/**\n * 全局状态接口\n */\ninterface GlobalAnalyticsState {\n instances: Map<string, AnalyticsManager>;\n singletonConfig: AnalyticsConfig | null;\n singletonInstance: AnalyticsManager | null;\n}\n\n/**\n * 获取全局状态,确保跨模块实例的一致性\n */\nfunction getGlobalState(): GlobalAnalyticsState {\n if (!globalThis[GLOBAL_STATE_KEY]) {\n globalThis[GLOBAL_STATE_KEY] = {\n instances: new Map<string, AnalyticsManager>(),\n singletonConfig: null,\n singletonInstance: null,\n };\n }\n return globalThis[GLOBAL_STATE_KEY];\n}\n\n/**\n * 默认实例名称\n */\nconst DEFAULT_INSTANCE_NAME = '__default__';\n\n/**\n * 注册全局 Analytics 实例\n *\n * @param instance Analytics 管理器实例\n * @param name 实例名称,默认为 '__default__'\n *\n * @example\n * ```typescript\n * const analytics = createAnalytics({ ... });\n * setGlobalAnalytics(analytics);\n * ```\n */\nexport function setGlobalAnalytics(\n instance: AnalyticsManager,\n name: string = DEFAULT_INSTANCE_NAME,\n): void {\n const state = getGlobalState();\n state.instances.set(name, instance);\n}\n\n/**\n * 获取全局 Analytics 实例\n *\n * @param name 实例名称,默认为 '__default__'\n * @returns Analytics 管理器实例\n * @throws {Error} 如果实例不存在\n *\n * @example\n * ```typescript\n * // 在任何文件中使用\n * const analytics = getGlobalAnalytics();\n * analytics.track({ name: 'some_event' });\n * ```\n */\nexport function getGlobalAnalytics(name: string = DEFAULT_INSTANCE_NAME): AnalyticsManager {\n const state = getGlobalState();\n const instance = state.instances.get(name);\n\n if (!instance) {\n throw new Error(\n `Global analytics instance \"${name}\" not found. ` +\n `Make sure to register it first using setGlobalAnalytics() or use AnalyticsProvider.`,\n );\n }\n\n return instance;\n}\n\n/**\n * 获取全局 Analytics 实例(可选,不抛出错误)\n *\n * @param name 实例名称,默认为 '__default__'\n * @returns Analytics 管理器实例或 null\n *\n * @example\n * ```typescript\n * const analytics = getGlobalAnalyticsOptional();\n * analytics?.track({ name: 'optional_event' });\n * ```\n */\nexport function getGlobalAnalyticsOptional(\n name: string = DEFAULT_INSTANCE_NAME,\n): AnalyticsManager | null {\n const state = getGlobalState();\n return state.instances.get(name) || null;\n}\n\n/**\n * 检查全局实例是否存在\n *\n * @param name 实例名称,默认为 '__default__'\n * @returns 是否存在\n */\nexport function hasGlobalAnalytics(name: string = DEFAULT_INSTANCE_NAME): boolean {\n const state = getGlobalState();\n return state.instances.has(name);\n}\n\n/**\n * 移除全局 Analytics 实例\n *\n * @param name 实例名称,默认为 '__default__'\n * @returns 是否成功移除\n */\nexport function removeGlobalAnalytics(name: string = DEFAULT_INSTANCE_NAME): boolean {\n const state = getGlobalState();\n return state.instances.delete(name);\n}\n\n/**\n * 清除所有全局实例\n */\nexport function clearGlobalAnalytics(): void {\n const state = getGlobalState();\n state.instances.clear();\n}\n\n/**\n * 获取所有已注册的实例名称\n *\n * @returns 实例名称数组\n */\nexport function getGlobalAnalyticsNames(): string[] {\n const state = getGlobalState();\n return Array.from(state.instances.keys());\n}\n\n/**\n * 简单的配置比较函数\n *\n * 注意:这是一个简化的实现,仅比较 JSON 序列化后的字符串\n * 对于复杂对象可能不够准确,但对于大多数配置场景是足够的\n */\nfunction isConfigEqual(config1: AnalyticsConfig, config2: AnalyticsConfig): boolean {\n try {\n return JSON.stringify(config1) === JSON.stringify(config2);\n } catch {\n return false;\n }\n}\n\n/**\n * 创建或获取单例 Analytics 实例\n *\n * 单例模式适用于整个应用只需要一个 Analytics 配置的场景。\n * 如果已存在单例且配置相同,返回现有实例;否则创建新实例。\n *\n * @param config Analytics 配置\n * @returns Analytics 管理器实例\n *\n * @example\n * ```typescript\n * // 在应用启动时创建\n * const analytics = createSingletonAnalytics({\n * debug: true,\n * providers: {\n * posthog: {\n * enabled: true,\n * key: 'your_key',\n * host: 'https://app.posthog.com',\n * },\n * },\n * });\n *\n * // 在其他地方获取同一实例\n * const sameAnalytics = getSingletonAnalytics();\n * ```\n */\nexport function createSingletonAnalytics(config: AnalyticsConfig): AnalyticsManager {\n const state = getGlobalState();\n\n // 检查是否已存在相同配置的单例\n if (\n state.singletonInstance &&\n state.singletonConfig &&\n isConfigEqual(state.singletonConfig, config)\n ) {\n return state.singletonInstance;\n }\n\n // 创建新的单例实例\n state.singletonInstance = createAnalytics(config);\n state.singletonConfig = config;\n\n // 同时注册为全局默认实例\n setGlobalAnalytics(state.singletonInstance);\n\n return state.singletonInstance;\n}\n\n/**\n * 获取单例 Analytics 实例\n *\n * @returns Analytics 管理器实例\n * @throws {Error} 如果单例未创建\n *\n * @example\n * ```typescript\n * const analytics = getSingletonAnalytics();\n * analytics.track({ name: 'some_event' });\n * ```\n */\nexport function getSingletonAnalytics(): AnalyticsManager {\n const state = getGlobalState();\n\n if (!state.singletonInstance) {\n throw new Error(\n 'Singleton analytics instance not created. ' +\n 'Call createSingletonAnalytics() first or use getGlobalAnalytics().',\n );\n }\n\n return state.singletonInstance;\n}\n\n/**\n * 获取单例 Analytics 实例(可选,不抛出错误)\n *\n * @returns Analytics 管理器实例或 null\n */\nexport function getSingletonAnalyticsOptional(): AnalyticsManager | null {\n const state = getGlobalState();\n return state.singletonInstance;\n}\n\n/**\n * 检查单例是否已创建\n *\n * @returns 是否存在单例\n */\nexport function hasSingletonAnalytics(): boolean {\n const state = getGlobalState();\n return state.singletonInstance !== null;\n}\n\n/**\n * 重置单例实例\n *\n * 主要用于测试场景\n */\nexport function resetSingletonAnalytics(): void {\n const state = getGlobalState();\n state.singletonInstance = null;\n state.singletonConfig = null;\n}\n","// React hooks for Analytics integration\n// Note: React is a peer dependency\nimport { useCallback } from 'react';\n\nimport type { AnalyticsEvent, PredefinedEvents } from '@/types';\n\nexport type AnalyticsManager = import('../manager').AnalyticsManager;\n\n/**\n * Analytics Hook\n * Provides core analytics functionality\n *\n * @param manager User-created AnalyticsManager instance\n * @example\n * ```typescript\n * const analytics = createAnalytics({ ... });\n * await analytics.initialize();\n *\n * function MyComponent() {\n * const { track, identify } = useAnalytics(analytics);\n * // ...\n * }\n * ```\n */\nexport function useAnalytics(manager: AnalyticsManager) {\n const track = useCallback((event: AnalyticsEvent) => manager.track(event), [manager]);\n\n const trackEvent = useCallback(\n <K extends keyof PredefinedEvents>(eventName: K, properties: PredefinedEvents[K]) =>\n manager.trackEvent(eventName, properties),\n [manager],\n );\n\n const identify = useCallback(\n (userId: string, properties?: Record<string, any>) => manager.identify(userId, properties),\n [manager],\n );\n\n const trackPageView = useCallback(\n (page: string, properties?: Record<string, any>) => manager.trackPageView(page, properties),\n [manager],\n );\n\n const reset = useCallback(() => manager.reset(), [manager]);\n\n return {\n identify,\n reset,\n track,\n trackEvent,\n trackPageView,\n };\n}\n\n/**\n * Event Tracking Hook\n * Provides convenient event tracking methods\n */\nexport function useEventTracking(manager: AnalyticsManager) {\n const { trackEvent } = useAnalytics(manager);\n\n const trackButtonClick = useCallback(\n (buttonName: string, context?: Record<string, any>) =>\n trackEvent('button_click', { button_name: buttonName, ...context }),\n [trackEvent],\n );\n\n const trackFormSubmit = useCallback(\n (formName: string, success: boolean) =>\n manager.track({\n name: 'form_submit',\n properties: { form_name: formName, success },\n }),\n [manager],\n );\n\n const trackUserSignup = useCallback(\n (spm?: string, extraProperties?: Record<string, any>) =>\n trackEvent('user_signup', { spm, ...extraProperties }),\n [trackEvent],\n );\n\n const trackUserLogin = useCallback(\n (spm?: string, extraProperties?: Record<string, any>) =>\n trackEvent('user_login', { spm, ...extraProperties }),\n [trackEvent],\n );\n\n return {\n trackButtonClick,\n trackFormSubmit,\n trackUserLogin,\n trackUserSignup,\n };\n}\n\n/**\n * 页面浏览追踪 Hook\n * 自动在组件挂载时追踪页面浏览\n *\n * @param manager 用户创建的 AnalyticsManager 实例\n * @param page 页面路径\n * @param properties 页面属性\n */\nexport function usePageTracking(\n manager: AnalyticsManager,\n page: string,\n properties?: Record<string, any>,\n) {\n const { trackPageView } = useAnalytics(manager);\n\n // 注意:在库中我们不自动调用 useEffect\n // 而是返回追踪函数,让用户决定何时调用\n return useCallback(() => {\n trackPageView(page, properties);\n }, [trackPageView, page, properties]);\n}\n"],"mappings":"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","names":["error","useAnalytics"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { A as AnalyticsConfig, a as AnalyticsManager } from './global-CLXWNSdY.mjs';
|
|
2
|
+
export { b as AnalyticsEvent, E as EventContext, c as GoogleAnalyticsProviderConfig, v as Platform, P as PostHogAnalyticsProvider, w as PostHogNodeAnalyticsProvider, d as PostHogNodeProviderAnalyticsConfig, e as PostHogProviderAnalyticsConfig, f as PredefinedEvents, g as ProviderConfig, x as ProviderTypeMap, U as UmamiProviderAnalyticsConfig, h as XAdsEventIdMap, i as XAdsProviderAnalyticsConfig, j as clearGlobalAnalytics, l as getGlobalAnalytics, m as getGlobalAnalyticsNames, n as getGlobalAnalyticsOptional, q as hasGlobalAnalytics, s as removeGlobalAnalytics, u as setGlobalAnalytics } from './global-CLXWNSdY.mjs';
|
|
3
|
+
import 'posthog-node';
|
|
4
|
+
import 'posthog-js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Server-side analytics entry point
|
|
8
|
+
* Includes all providers including posthog-node for server environments
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create server analytics with full provider support including posthog-node
|
|
13
|
+
*/
|
|
14
|
+
declare function createServerAnalytics(config: AnalyticsConfig): AnalyticsManager;
|
|
15
|
+
|
|
16
|
+
export { AnalyticsConfig, AnalyticsManager, createServerAnalytics };
|