@lobehub/chat 0.160.4 → 0.160.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/CHANGELOG.md +25 -0
- package/docs/self-hosting/environment-variables/analytics.mdx +12 -35
- package/docs/self-hosting/environment-variables/analytics.zh-CN.mdx +13 -34
- package/package.json +2 -2
- package/src/app/layout.tsx +3 -1
- package/src/components/Analytics/Clarity.tsx +28 -0
- package/src/components/Analytics/Google.tsx +2 -9
- package/src/components/Analytics/Plausible.tsx +7 -12
- package/src/components/Analytics/Posthog.tsx +9 -10
- package/src/components/Analytics/Umami.tsx +7 -6
- package/src/components/Analytics/Vercel.tsx +2 -4
- package/src/components/Analytics/index.tsx +29 -14
- package/src/config/__tests__/analytics.test.ts +70 -0
- package/src/config/__tests__/client.test.ts +0 -6
- package/src/config/analytics.ts +148 -0
- package/src/config/client.ts +0 -35
- package/src/config/server/index.ts +1 -3
- package/src/store/market/action.ts +1 -0
- package/src/config/server/analytics.ts +0 -32
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.160.5](https://github.com/lobehub/lobe-chat/compare/v0.160.4...v0.160.5)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-05-20**</sup>
|
|
8
|
+
|
|
9
|
+
#### ♻ Code Refactoring
|
|
10
|
+
|
|
11
|
+
- **misc**: Refactor analytics env.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Code refactoring
|
|
19
|
+
|
|
20
|
+
- **misc**: Refactor analytics env, closes [#2570](https://github.com/lobehub/lobe-chat/issues/2570) ([d809d3f](https://github.com/lobehub/lobe-chat/commit/d809d3f))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
### [Version 0.160.4](https://github.com/lobehub/lobe-chat/compare/v0.160.3...v0.160.4)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2024-05-20**</sup>
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
Integrating Data Analytics Services in LobeChat: Environment Variables and
|
|
4
|
-
Configuration
|
|
2
|
+
title: Integrating Analytics in LobeChat
|
|
5
3
|
description: >-
|
|
6
4
|
Learn how to configure environment variables for Vercel Analytics, Google
|
|
7
5
|
Analytics, PostHog Analytics, and Umami Analytics in LobeChat for data
|
|
@@ -36,44 +34,30 @@ We have integrated several free/open-source data analytics services in LobeChat
|
|
|
36
34
|
|
|
37
35
|
## Google Analytics
|
|
38
36
|
|
|
39
|
-
### `ENABLE_GOOGLE_ANALYTICS`
|
|
40
|
-
|
|
41
|
-
- Type: Optional
|
|
42
|
-
- Description: Used to configure the environment variable for Google Analytics. Set to `1` to enable Google Analytics.
|
|
43
|
-
- Default: `-`
|
|
44
|
-
- Example: `1`
|
|
45
|
-
|
|
46
37
|
### `GOOGLE_ANALYTICS_MEASUREMENT_ID`
|
|
47
38
|
|
|
48
39
|
- Type: Required
|
|
49
|
-
- Description: Google Analytics Measurement ID,you can get it from the Google Analytics dashboard.
|
|
40
|
+
- Description: Google Analytics Measurement ID,you can get it from the Google Analytics dashboard. Add it will auto enable Google Analytics.
|
|
50
41
|
- Default: `-`
|
|
51
42
|
- Example: `G-63LP2TV03T`
|
|
52
43
|
|
|
53
44
|
## Posthog Analytics
|
|
54
45
|
|
|
55
|
-
### `
|
|
46
|
+
### `POSTHOG_KEY`
|
|
56
47
|
|
|
57
|
-
- Type:
|
|
58
|
-
- Description:
|
|
59
|
-
- Default: `-`
|
|
60
|
-
- Example: `1`
|
|
61
|
-
|
|
62
|
-
### `NEXT_PUBLIC_POSTHOG_KEY`
|
|
63
|
-
|
|
64
|
-
- Type: Optional
|
|
65
|
-
- Description: Set the PostHog project Key.
|
|
48
|
+
- Type: Required
|
|
49
|
+
- Description: Set the PostHog project Key. Add it will auto enable PostHog Analytics.
|
|
66
50
|
- Default: `-`
|
|
67
51
|
- Example: `phc_xxxxxxxx`
|
|
68
52
|
|
|
69
|
-
### `
|
|
53
|
+
### `POSTHOG_HOST`
|
|
70
54
|
|
|
71
55
|
- Type: Optional
|
|
72
56
|
- Description: Set the deployment address of the PostHog service, defaulting to the official SAAS address.
|
|
73
57
|
- Default: `https://app.posthog.com`
|
|
74
58
|
- Example: `https://example.com`
|
|
75
59
|
|
|
76
|
-
### `
|
|
60
|
+
### `DEBUG_POSTHOG_ANALYTICS`
|
|
77
61
|
|
|
78
62
|
- Type: Optional
|
|
79
63
|
- Description: Enable the debug mode for PostHog.
|
|
@@ -82,26 +66,19 @@ We have integrated several free/open-source data analytics services in LobeChat
|
|
|
82
66
|
|
|
83
67
|
## Umami Analytics
|
|
84
68
|
|
|
85
|
-
### `
|
|
69
|
+
### `UMAMI_WEBSITE_ID`
|
|
86
70
|
|
|
87
|
-
- Type:
|
|
88
|
-
- Description:
|
|
71
|
+
- Type: Required
|
|
72
|
+
- Description: Your Umami Website ID. Add it will auto enable Umami Analytics.
|
|
89
73
|
- Default: `-`
|
|
90
|
-
- Example: `
|
|
74
|
+
- Example: `E738D82A-EE9E-4806-A81F-0CA3CAE57F65`
|
|
91
75
|
|
|
92
|
-
### `
|
|
76
|
+
### `UMAMI_SCRIPT_URL`
|
|
93
77
|
|
|
94
78
|
- Type: Optional
|
|
95
79
|
- Description: The URL of the Umami script, defaulting to the script URL provided by Umami Cloud.
|
|
96
80
|
- Default: `https://analytics.umami.is/script.js`
|
|
97
81
|
- Example: `https://umami.your-site.com/script.js`
|
|
98
82
|
|
|
99
|
-
### `NEXT_PUBLIC_UMAMI_WEBSITE_ID`
|
|
100
|
-
|
|
101
|
-
- Type: Required
|
|
102
|
-
- Description: Your Umami Website ID.
|
|
103
|
-
- Default: `-`
|
|
104
|
-
- Example: `E738D82A-EE9E-4806-A81F-0CA3CAE57F65`
|
|
105
|
-
|
|
106
83
|
[posthog-analytics-url]: https://posthog.com
|
|
107
84
|
[umami-analytics-url]: https://umami.is
|
|
@@ -32,44 +32,30 @@ tags:
|
|
|
32
32
|
|
|
33
33
|
## Google Analytics
|
|
34
34
|
|
|
35
|
-
### `ENABLE_GOOGLE_ANALYTICS`
|
|
36
|
-
|
|
37
|
-
- 类型:必选
|
|
38
|
-
- 描述:用于配置 Google Analytics 的环境变量,当设为 `1` 时开启 Google Analytics
|
|
39
|
-
- 默认值: `-`
|
|
40
|
-
- 示例:`1`
|
|
41
|
-
|
|
42
35
|
### `GOOGLE_ANALYTICS_MEASUREMENT_ID`
|
|
43
36
|
|
|
44
37
|
- 类型:必选
|
|
45
|
-
- 描述:Google Analytics 的 Measurement ID
|
|
38
|
+
- 描述:Google Analytics 的 Measurement ID,填写此项后将自动开启 Google Analytics
|
|
46
39
|
- 默认值: `-`
|
|
47
40
|
- 示例:`G-63LP2TV03T`
|
|
48
41
|
|
|
49
42
|
## Posthog Analytics
|
|
50
43
|
|
|
51
|
-
### `
|
|
52
|
-
|
|
53
|
-
- 类型:可选
|
|
54
|
-
- 描述:用于开启 [PostHog Analytics][posthog-analytics-url] 的环境变量,设为 `1` 时开启 PostHog Analytics
|
|
55
|
-
- 默认值: `-`
|
|
56
|
-
- 示例:`1`
|
|
44
|
+
### `POSTHOG_KEY`
|
|
57
45
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- 类型:可选
|
|
61
|
-
- 描述:设置 PostHog 项目 Key
|
|
46
|
+
- 类型:必选
|
|
47
|
+
- 描述:设置 PostHog 项目 Key,设置此项后将自动开启 PostHog Analytics
|
|
62
48
|
- 默认值: `-`
|
|
63
49
|
- 示例:`phc_xxxxxxxx`
|
|
64
50
|
|
|
65
|
-
### `
|
|
51
|
+
### `POSTHOG_HOST`
|
|
66
52
|
|
|
67
53
|
- 类型:可选
|
|
68
|
-
- 描述:设置 PostHog 服务的部署地址,默认为官方的
|
|
54
|
+
- 描述:设置 PostHog 服务的部署地址,默认为官方的 SaaS 地址
|
|
69
55
|
- 默认值:`https://app.posthog.com`
|
|
70
56
|
- 示例:`https://example.com`
|
|
71
57
|
|
|
72
|
-
### `
|
|
58
|
+
### `POSTHOG_DEBUG`
|
|
73
59
|
|
|
74
60
|
- 类型:可选
|
|
75
61
|
- 描述:开启 PostHog 的调试模式
|
|
@@ -78,26 +64,19 @@ tags:
|
|
|
78
64
|
|
|
79
65
|
## Umami Analytics
|
|
80
66
|
|
|
81
|
-
### `
|
|
67
|
+
### `UMAMI_WEBSITE_ID`
|
|
82
68
|
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
- 示例:`
|
|
69
|
+
- 类型:必选
|
|
70
|
+
- 描述:你的 Umami 的 Website ID,填写此项后将自动开启 Umami Analytics
|
|
71
|
+
- 默认值:`-`
|
|
72
|
+
- 示例:`E738D82A-EE9E-4806-A81F-0CA3CAE57F65`
|
|
87
73
|
|
|
88
|
-
### `
|
|
74
|
+
### `UMAMI_SCRIPT_URL`
|
|
89
75
|
|
|
90
76
|
- 类型:可选
|
|
91
77
|
- 描述:Umami 脚本的网址,默认为 Umami Cloud 提供的脚本网址
|
|
92
78
|
- 默认值:`https://analytics.umami.is/script.js`
|
|
93
79
|
- 示例:`https://umami.your-site.com/script.js`
|
|
94
80
|
|
|
95
|
-
### `NEXT_PUBLIC_UMAMI_WEBSITE_ID`
|
|
96
|
-
|
|
97
|
-
- 类型:必选
|
|
98
|
-
- 描述:你的 Umami 的 Website ID
|
|
99
|
-
- 默认值:`-`
|
|
100
|
-
- 示例:`E738D82A-EE9E-4806-A81F-0CA3CAE57F65`
|
|
101
|
-
|
|
102
81
|
[posthog-analytics-url]: https://posthog.com
|
|
103
82
|
[umami-analytics-url]: https://umami.is
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.160.
|
|
3
|
+
"version": "0.160.5",
|
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"@icons-pack/react-simple-icons": "^9.5.0",
|
|
97
97
|
"@lobehub/chat-plugin-sdk": "latest",
|
|
98
98
|
"@lobehub/chat-plugins-gateway": "latest",
|
|
99
|
-
"@lobehub/icons": "
|
|
99
|
+
"@lobehub/icons": "^1.21.0",
|
|
100
100
|
"@lobehub/tts": "latest",
|
|
101
101
|
"@lobehub/ui": "^1.138.24",
|
|
102
102
|
"@microsoft/fetch-event-source": "^2.0.1",
|
package/src/app/layout.tsx
CHANGED
|
@@ -10,6 +10,8 @@ import AuthProvider from '@/layout/AuthProvider';
|
|
|
10
10
|
import GlobalProvider from '@/layout/GlobalProvider';
|
|
11
11
|
import { isMobileDevice } from '@/utils/responsive';
|
|
12
12
|
|
|
13
|
+
const inVercel = process.env.VERCEL === '1';
|
|
14
|
+
|
|
13
15
|
type RootLayoutProps = {
|
|
14
16
|
children: ReactNode;
|
|
15
17
|
modal: ReactNode;
|
|
@@ -31,7 +33,7 @@ const RootLayout = async ({ children, modal }: RootLayoutProps) => {
|
|
|
31
33
|
</AuthProvider>
|
|
32
34
|
</GlobalProvider>
|
|
33
35
|
<Analytics />
|
|
34
|
-
<SpeedInsights />
|
|
36
|
+
{inVercel && <SpeedInsights />}
|
|
35
37
|
</body>
|
|
36
38
|
</html>
|
|
37
39
|
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import Script from 'next/script';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
|
|
6
|
+
interface ClarityProps {
|
|
7
|
+
projectId?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Clarity = memo<ClarityProps>(
|
|
11
|
+
({ projectId }) =>
|
|
12
|
+
projectId && (
|
|
13
|
+
<Script
|
|
14
|
+
dangerouslySetInnerHTML={{
|
|
15
|
+
__html: `
|
|
16
|
+
(function(c,l,a,r,i,t,y){
|
|
17
|
+
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
|
18
|
+
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
|
19
|
+
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
|
20
|
+
})(window, document, "clarity", "script", "${projectId}");
|
|
21
|
+
`,
|
|
22
|
+
}}
|
|
23
|
+
id="clarity-script"
|
|
24
|
+
/>
|
|
25
|
+
),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export default Clarity;
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import { GoogleAnalytics as GA } from '@next/third-parties/google';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { analyticsEnv } from '@/config/analytics';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
if (ENABLE_GOOGLE_ANALYTICS && !GOOGLE_ANALYTICS_MEASUREMENT_ID)
|
|
8
|
-
throw new Error(
|
|
9
|
-
'You have enable the google analytics but not provided the google analytics id. Please provide the google analytics id in your env',
|
|
10
|
-
);
|
|
11
|
-
|
|
12
|
-
const GoogleAnalytics = () => <GA gaId={GOOGLE_ANALYTICS_MEASUREMENT_ID!} />;
|
|
5
|
+
const GoogleAnalytics = () => <GA gaId={analyticsEnv.GOOGLE_ANALYTICS_MEASUREMENT_ID!} />;
|
|
13
6
|
|
|
14
7
|
export default GoogleAnalytics;
|
|
@@ -3,19 +3,14 @@
|
|
|
3
3
|
import Script from 'next/script';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
interface PlausibleAnalyticsProps {
|
|
7
|
+
domain?: string;
|
|
8
|
+
scriptBaseUrl: string;
|
|
9
|
+
}
|
|
7
10
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
() =>
|
|
12
|
-
PLAUSIBLE_DOMAIN && (
|
|
13
|
-
<Script
|
|
14
|
-
data-domain={PLAUSIBLE_DOMAIN}
|
|
15
|
-
defer
|
|
16
|
-
src={`${PLAUSIBLE_SCRIPT_BASE_URL}/js/script.js`}
|
|
17
|
-
/>
|
|
18
|
-
),
|
|
11
|
+
const PlausibleAnalytics = memo<PlausibleAnalyticsProps>(
|
|
12
|
+
({ domain, scriptBaseUrl }) =>
|
|
13
|
+
domain && <Script data-domain={domain} defer src={`${scriptBaseUrl}/js/script.js`} />,
|
|
19
14
|
);
|
|
20
15
|
|
|
21
16
|
export default PlausibleAnalytics;
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import posthog from 'posthog-js';
|
|
4
|
-
import {
|
|
4
|
+
import { memo, useEffect } from 'react';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
interface PostHogProps {
|
|
7
|
+
debug: boolean;
|
|
8
|
+
host: string;
|
|
9
|
+
token?: string;
|
|
10
|
+
}
|
|
7
11
|
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
const PostHog: FC = memo(() => {
|
|
12
|
+
const PostHog = memo<PostHogProps>(({ token, host, debug }) => {
|
|
11
13
|
useEffect(() => {
|
|
12
|
-
if (!
|
|
14
|
+
if (!token) return;
|
|
13
15
|
|
|
14
|
-
posthog.init(
|
|
15
|
-
api_host: POSTHOG_HOST ?? 'https://app.posthog.com',
|
|
16
|
-
debug: POSTHOG_DEBUG,
|
|
17
|
-
});
|
|
16
|
+
posthog.init(token, { api_host: host, debug });
|
|
18
17
|
}, []);
|
|
19
18
|
|
|
20
19
|
return null;
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
import Script from 'next/script';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
interface UmamiAnalyticsProps {
|
|
7
|
+
scriptUrl: string;
|
|
8
|
+
websiteId?: string;
|
|
9
|
+
}
|
|
7
10
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
() =>
|
|
12
|
-
UMAMI_WEBSITE_ID && <Script data-website-id={UMAMI_WEBSITE_ID} defer src={UMAMI_SCRIPT_URL} />,
|
|
11
|
+
const UmamiAnalytics = memo<UmamiAnalyticsProps>(
|
|
12
|
+
({ scriptUrl, websiteId }) =>
|
|
13
|
+
websiteId && <Script data-website-id={websiteId} defer src={scriptUrl} />,
|
|
13
14
|
);
|
|
14
15
|
|
|
15
16
|
export default UmamiAnalytics;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { Analytics } from '@vercel/analytics/react';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { analyticsEnv } from '@/config/analytics';
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const VercelAnalytics = memo(() => <Analytics debug={VERCEL_DEBUG} />);
|
|
6
|
+
const VercelAnalytics = memo(() => <Analytics debug={analyticsEnv.DEBUG_VERCEL_ANALYTICS} />);
|
|
9
7
|
|
|
10
8
|
export default VercelAnalytics;
|
|
@@ -1,27 +1,42 @@
|
|
|
1
1
|
import dynamic from 'next/dynamic';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { getServerConfig } from '@/config/server';
|
|
3
|
+
import { analyticsEnv } from '@/config/analytics';
|
|
5
4
|
|
|
6
5
|
import Google from './Google';
|
|
7
6
|
import Vercel from './Vercel';
|
|
8
7
|
|
|
9
|
-
const Plausible = dynamic(() => import('./Plausible')
|
|
10
|
-
const Posthog = dynamic(() => import('./Posthog')
|
|
11
|
-
const Umami = dynamic(() => import('./Umami')
|
|
12
|
-
|
|
13
|
-
const { ANALYTICS_POSTHOG, ANALYTICS_PLAUSIBLE, ANALYTICS_UMAMI } = getClientConfig();
|
|
14
|
-
|
|
15
|
-
const { ENABLE_VERCEL_ANALYTICS, ENABLE_GOOGLE_ANALYTICS } = getServerConfig();
|
|
8
|
+
const Plausible = dynamic(() => import('./Plausible'));
|
|
9
|
+
const Posthog = dynamic(() => import('./Posthog'));
|
|
10
|
+
const Umami = dynamic(() => import('./Umami'));
|
|
11
|
+
const Clarity = dynamic(() => import('./Clarity'));
|
|
16
12
|
|
|
17
13
|
const Analytics = () => {
|
|
18
14
|
return (
|
|
19
15
|
<>
|
|
20
|
-
{ENABLE_VERCEL_ANALYTICS && <Vercel />}
|
|
21
|
-
{ENABLE_GOOGLE_ANALYTICS && <Google />}
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
{analyticsEnv.ENABLE_VERCEL_ANALYTICS && <Vercel />}
|
|
17
|
+
{analyticsEnv.ENABLE_GOOGLE_ANALYTICS && <Google />}
|
|
18
|
+
{analyticsEnv.ENABLED_PLAUSIBLE_ANALYTICS && (
|
|
19
|
+
<Plausible
|
|
20
|
+
domain={analyticsEnv.PLAUSIBLE_DOMAIN}
|
|
21
|
+
scriptBaseUrl={analyticsEnv.PLAUSIBLE_SCRIPT_BASE_URL}
|
|
22
|
+
/>
|
|
23
|
+
)}
|
|
24
|
+
{analyticsEnv.ENABLED_POSTHOG_ANALYTICS && (
|
|
25
|
+
<Posthog
|
|
26
|
+
debug={analyticsEnv.DEBUG_POSTHOG_ANALYTICS}
|
|
27
|
+
host={analyticsEnv.POSTHOG_HOST!}
|
|
28
|
+
token={analyticsEnv.POSTHOG_KEY}
|
|
29
|
+
/>
|
|
30
|
+
)}
|
|
31
|
+
{analyticsEnv.ENABLED_UMAMI_ANALYTICS && (
|
|
32
|
+
<Umami
|
|
33
|
+
scriptUrl={analyticsEnv.UMAMI_SCRIPT_URL}
|
|
34
|
+
websiteId={analyticsEnv.UMAMI_WEBSITE_ID}
|
|
35
|
+
/>
|
|
36
|
+
)}
|
|
37
|
+
{analyticsEnv.ENABLED_CLARITY_ANALYTICS && (
|
|
38
|
+
<Clarity projectId={analyticsEnv.CLARITY_PROJECT_ID} />
|
|
39
|
+
)}
|
|
25
40
|
</>
|
|
26
41
|
);
|
|
27
42
|
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// @vitest-environment node
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { analyticsEnv, getAnalyticsConfig } from '../analytics';
|
|
5
|
+
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
// 在每个测试用例之前,清除所有的 console.warn mock
|
|
8
|
+
console.warn = vi.fn();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
// 在每个测试用例之后,恢复所有的环境变量
|
|
13
|
+
vi.resetModules();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('getAnalyticsConfig', () => {
|
|
17
|
+
it('should return the correct analytics config', () => {
|
|
18
|
+
// 设置环境变量
|
|
19
|
+
process.env.PLAUSIBLE_DOMAIN = 'example.com';
|
|
20
|
+
process.env.POSTHOG_KEY = 'posthog_key';
|
|
21
|
+
process.env.UMAMI_WEBSITE_ID = 'umami_id';
|
|
22
|
+
process.env.CLARITY_PROJECT_ID = 'clarity_id';
|
|
23
|
+
process.env.ENABLE_VERCEL_ANALYTICS = '1';
|
|
24
|
+
process.env.GOOGLE_ANALYTICS_MEASUREMENT_ID = 'ga_id';
|
|
25
|
+
|
|
26
|
+
const config = getAnalyticsConfig();
|
|
27
|
+
|
|
28
|
+
expect(config).toEqual({
|
|
29
|
+
ENABLED_PLAUSIBLE_ANALYTICS: true,
|
|
30
|
+
PLAUSIBLE_DOMAIN: 'example.com',
|
|
31
|
+
PLAUSIBLE_SCRIPT_BASE_URL: 'https://plausible.io',
|
|
32
|
+
ENABLED_POSTHOG_ANALYTICS: true,
|
|
33
|
+
POSTHOG_KEY: 'posthog_key',
|
|
34
|
+
POSTHOG_HOST: 'https://app.posthog.com',
|
|
35
|
+
DEBUG_POSTHOG_ANALYTICS: false,
|
|
36
|
+
ENABLED_UMAMI_ANALYTICS: true,
|
|
37
|
+
UMAMI_SCRIPT_URL: 'https://analytics.umami.is/script.js',
|
|
38
|
+
UMAMI_WEBSITE_ID: 'umami_id',
|
|
39
|
+
ENABLED_CLARITY_ANALYTICS: true,
|
|
40
|
+
CLARITY_PROJECT_ID: 'clarity_id',
|
|
41
|
+
ENABLE_VERCEL_ANALYTICS: true,
|
|
42
|
+
DEBUG_VERCEL_ANALYTICS: false,
|
|
43
|
+
ENABLE_GOOGLE_ANALYTICS: true,
|
|
44
|
+
GOOGLE_ANALYTICS_MEASUREMENT_ID: 'ga_id',
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should use deprecated env vars and log warnings', () => {
|
|
49
|
+
process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN = 'deprecated.com';
|
|
50
|
+
process.env.NEXT_PUBLIC_POSTHOG_KEY = 'deprecated_key';
|
|
51
|
+
process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID = 'deprecated_id';
|
|
52
|
+
|
|
53
|
+
const config = getAnalyticsConfig();
|
|
54
|
+
|
|
55
|
+
expect(config.ENABLED_PLAUSIBLE_ANALYTICS).toBeTruthy();
|
|
56
|
+
expect(config.ENABLED_POSTHOG_ANALYTICS).toBeTruthy();
|
|
57
|
+
expect(config.ENABLED_UMAMI_ANALYTICS).toBeTruthy();
|
|
58
|
+
|
|
59
|
+
expect(console.warn).toHaveBeenCalledTimes(3);
|
|
60
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
61
|
+
'NEXT_PUBLIC_PLAUSIBLE_DOMAIN is deprecated. Please use PLAUSIBLE_DOMAIN instead. We will remove it in LobeChat 1.0',
|
|
62
|
+
);
|
|
63
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
64
|
+
'NEXT_PUBLIC_POSTHOG_KEY is deprecated. Please use POSTHOG_KEY instead. We will remove it in LobeChat 1.0',
|
|
65
|
+
);
|
|
66
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
67
|
+
'NEXT_PUBLIC_UMAMI_WEBSITE_ID is deprecated. Please use UMAMI_WEBSITE_ID instead. We will remove it in LobeChat 1.0',
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -18,9 +18,6 @@ describe('getClientConfig', () => {
|
|
|
18
18
|
process.env.NEXT_PUBLIC_I18N_DEBUG_SERVER = '1';
|
|
19
19
|
|
|
20
20
|
const config = getClientConfig();
|
|
21
|
-
expect(config.ANALYTICS_PLAUSIBLE).toBe(true);
|
|
22
|
-
expect(config.ANALYTICS_POSTHOG).toBe(true);
|
|
23
|
-
expect(config.POSTHOG_DEBUG).toBe(true);
|
|
24
21
|
expect(config.I18N_DEBUG).toBe(true);
|
|
25
22
|
expect(config.I18N_DEBUG_BROWSER).toBe(true);
|
|
26
23
|
expect(config.I18N_DEBUG_SERVER).toBe(true);
|
|
@@ -36,9 +33,6 @@ describe('getClientConfig', () => {
|
|
|
36
33
|
|
|
37
34
|
const config = getClientConfig();
|
|
38
35
|
|
|
39
|
-
expect(config.ANALYTICS_PLAUSIBLE).toBe(false);
|
|
40
|
-
expect(config.ANALYTICS_POSTHOG).toBe(false);
|
|
41
|
-
expect(config.POSTHOG_DEBUG).toBe(false);
|
|
42
36
|
expect(config.I18N_DEBUG).toBe(false);
|
|
43
37
|
expect(config.I18N_DEBUG_BROWSER).toBe(false);
|
|
44
38
|
expect(config.I18N_DEBUG_SERVER).toBe(false);
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
2
|
+
import { createEnv } from '@t3-oss/env-nextjs';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
7
|
+
namespace NodeJS {
|
|
8
|
+
interface ProcessEnv {
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated
|
|
11
|
+
*/
|
|
12
|
+
NEXT_PUBLIC_ANALYTICS_PLAUSIBLE?: string;
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated
|
|
15
|
+
*/
|
|
16
|
+
NEXT_PUBLIC_ANALYTICS_POSTHOG: string;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated
|
|
19
|
+
*/
|
|
20
|
+
NEXT_PUBLIC_PLAUSIBLE_DOMAIN?: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated
|
|
24
|
+
*/
|
|
25
|
+
NEXT_PUBLIC_PLAUSIBLE_SCRIPT_BASE_URL?: string;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated
|
|
28
|
+
*/
|
|
29
|
+
NEXT_PUBLIC_POSTHOG_HOST: string;
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated
|
|
32
|
+
*/
|
|
33
|
+
NEXT_PUBLIC_POSTHOG_KEY: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated
|
|
37
|
+
*/
|
|
38
|
+
NEXT_PUBLIC_UMAMI_SCRIPT_URL?: string;
|
|
39
|
+
/**
|
|
40
|
+
* @deprecated
|
|
41
|
+
*/
|
|
42
|
+
NEXT_PUBLIC_UMAMI_WEBSITE_ID?: string;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const getAnalyticsConfig = () => {
|
|
48
|
+
if (process.env.NEXT_PUBLIC_PLAUSIBLE_SCRIPT_BASE_URL) {
|
|
49
|
+
console.warn(
|
|
50
|
+
'NEXT_PUBLIC_PLAUSIBLE_SCRIPT_BASE_URL is deprecated. Please use PLAUSIBLE_SCRIPT_BASE_URL instead. We will remove it in LobeChat 1.0',
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
if (process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN) {
|
|
54
|
+
console.warn(
|
|
55
|
+
'NEXT_PUBLIC_PLAUSIBLE_DOMAIN is deprecated. Please use PLAUSIBLE_DOMAIN instead. We will remove it in LobeChat 1.0',
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (process.env.NEXT_PUBLIC_POSTHOG_KEY) {
|
|
60
|
+
console.warn(
|
|
61
|
+
'NEXT_PUBLIC_POSTHOG_KEY is deprecated. Please use POSTHOG_KEY instead. We will remove it in LobeChat 1.0',
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
if (process.env.NEXT_PUBLIC_POSTHOG_HOST) {
|
|
65
|
+
console.warn(
|
|
66
|
+
'NEXT_PUBLIC_POSTHOG_HOST is deprecated. Please use POSTHOG_HOST instead. We will remove it in LobeChat 1.0',
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL) {
|
|
71
|
+
console.warn(
|
|
72
|
+
'NEXT_PUBLIC_UMAMI_SCRIPT_URL is deprecated. Please use UMAMI_SCRIPT_URL instead. We will remove it in LobeChat 1.0',
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
if (process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID) {
|
|
76
|
+
console.warn(
|
|
77
|
+
'NEXT_PUBLIC_UMAMI_WEBSITE_ID is deprecated. Please use UMAMI_WEBSITE_ID instead. We will remove it in LobeChat 1.0',
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return createEnv({
|
|
82
|
+
server: {
|
|
83
|
+
ENABLED_PLAUSIBLE_ANALYTICS: z.boolean(),
|
|
84
|
+
PLAUSIBLE_SCRIPT_BASE_URL: z.string(),
|
|
85
|
+
PLAUSIBLE_DOMAIN: z.string().optional(),
|
|
86
|
+
|
|
87
|
+
ENABLED_POSTHOG_ANALYTICS: z.boolean(),
|
|
88
|
+
POSTHOG_KEY: z.string().optional(),
|
|
89
|
+
POSTHOG_HOST: z.string(),
|
|
90
|
+
DEBUG_POSTHOG_ANALYTICS: z.boolean(),
|
|
91
|
+
|
|
92
|
+
ENABLED_UMAMI_ANALYTICS: z.boolean(),
|
|
93
|
+
UMAMI_WEBSITE_ID: z.string().optional(),
|
|
94
|
+
UMAMI_SCRIPT_URL: z.string(),
|
|
95
|
+
|
|
96
|
+
ENABLED_CLARITY_ANALYTICS: z.boolean(),
|
|
97
|
+
CLARITY_PROJECT_ID: z.string().optional(),
|
|
98
|
+
|
|
99
|
+
ENABLE_VERCEL_ANALYTICS: z.boolean(),
|
|
100
|
+
DEBUG_VERCEL_ANALYTICS: z.boolean(),
|
|
101
|
+
|
|
102
|
+
ENABLE_GOOGLE_ANALYTICS: z.boolean(),
|
|
103
|
+
GOOGLE_ANALYTICS_MEASUREMENT_ID: z.string().optional(),
|
|
104
|
+
},
|
|
105
|
+
runtimeEnv: {
|
|
106
|
+
// Plausible Analytics
|
|
107
|
+
ENABLED_PLAUSIBLE_ANALYTICS:
|
|
108
|
+
!!process.env.PLAUSIBLE_DOMAIN || !!process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN,
|
|
109
|
+
PLAUSIBLE_DOMAIN: process.env.PLAUSIBLE_DOMAIN || process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN,
|
|
110
|
+
PLAUSIBLE_SCRIPT_BASE_URL:
|
|
111
|
+
process.env.PLAUSIBLE_SCRIPT_BASE_URL ||
|
|
112
|
+
process.env.NEXT_PUBLIC_PLAUSIBLE_SCRIPT_BASE_URL ||
|
|
113
|
+
'https://plausible.io',
|
|
114
|
+
|
|
115
|
+
// Posthog Analytics
|
|
116
|
+
ENABLED_POSTHOG_ANALYTICS: !!process.env.POSTHOG_KEY || !!process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
|
117
|
+
POSTHOG_KEY: process.env.POSTHOG_KEY || process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
|
118
|
+
POSTHOG_HOST:
|
|
119
|
+
process.env.POSTHOG_HOST ||
|
|
120
|
+
process.env.NEXT_PUBLIC_POSTHOG_HOST ||
|
|
121
|
+
'https://app.posthog.com',
|
|
122
|
+
DEBUG_POSTHOG_ANALYTICS: process.env.DEBUG_POSTHOG_ANALYTICS === '1',
|
|
123
|
+
|
|
124
|
+
// Umami Analytics
|
|
125
|
+
ENABLED_UMAMI_ANALYTICS:
|
|
126
|
+
!!process.env.UMAMI_WEBSITE_ID || !!process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID,
|
|
127
|
+
UMAMI_SCRIPT_URL:
|
|
128
|
+
process.env.UMAMI_SCRIPT_URL ||
|
|
129
|
+
process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL ||
|
|
130
|
+
'https://analytics.umami.is/script.js',
|
|
131
|
+
UMAMI_WEBSITE_ID: process.env.UMAMI_WEBSITE_ID || process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID,
|
|
132
|
+
|
|
133
|
+
// Clarity Analytics
|
|
134
|
+
ENABLED_CLARITY_ANALYTICS: !!process.env.CLARITY_PROJECT_ID,
|
|
135
|
+
CLARITY_PROJECT_ID: process.env.CLARITY_PROJECT_ID,
|
|
136
|
+
|
|
137
|
+
// Vercel Analytics
|
|
138
|
+
ENABLE_VERCEL_ANALYTICS: process.env.ENABLE_VERCEL_ANALYTICS === '1',
|
|
139
|
+
DEBUG_VERCEL_ANALYTICS: process.env.DEBUG_VERCEL_ANALYTICS === '1',
|
|
140
|
+
|
|
141
|
+
// Google Analytics
|
|
142
|
+
ENABLE_GOOGLE_ANALYTICS: !!process.env.GOOGLE_ANALYTICS_MEASUREMENT_ID,
|
|
143
|
+
GOOGLE_ANALYTICS_MEASUREMENT_ID: process.env.GOOGLE_ANALYTICS_MEASUREMENT_ID,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const analyticsEnv = getAnalyticsConfig();
|
package/src/config/client.ts
CHANGED
|
@@ -8,23 +8,6 @@ declare global {
|
|
|
8
8
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
9
9
|
namespace NodeJS {
|
|
10
10
|
interface ProcessEnv {
|
|
11
|
-
NEXT_PUBLIC_ANALYTICS_MIXPANEL?: string;
|
|
12
|
-
NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN?: string;
|
|
13
|
-
NEXT_PUBLIC_MIXPANEL_DEBUG?: string;
|
|
14
|
-
|
|
15
|
-
NEXT_PUBLIC_ANALYTICS_PLAUSIBLE?: string;
|
|
16
|
-
NEXT_PUBLIC_PLAUSIBLE_DOMAIN?: string;
|
|
17
|
-
NEXT_PUBLIC_PLAUSIBLE_SCRIPT_BASE_URL?: string;
|
|
18
|
-
|
|
19
|
-
NEXT_PUBLIC_ANALYTICS_POSTHOG: string;
|
|
20
|
-
NEXT_PUBLIC_POSTHOG_KEY: string;
|
|
21
|
-
NEXT_PUBLIC_POSTHOG_HOST: string;
|
|
22
|
-
NEXT_PUBLIC_POSTHOG_DEBUG: string;
|
|
23
|
-
|
|
24
|
-
NEXT_PUBLIC_ANALYTICS_UMAMI?: string;
|
|
25
|
-
NEXT_PUBLIC_UMAMI_SCRIPT_URL?: string;
|
|
26
|
-
NEXT_PUBLIC_UMAMI_WEBSITE_ID?: string;
|
|
27
|
-
|
|
28
11
|
NEXT_PUBLIC_I18N_DEBUG: string;
|
|
29
12
|
NEXT_PUBLIC_I18N_DEBUG_BROWSER: string;
|
|
30
13
|
NEXT_PUBLIC_I18N_DEBUG_SERVER: string;
|
|
@@ -41,24 +24,6 @@ export const getClientConfig = () => ({
|
|
|
41
24
|
|
|
42
25
|
BASE_PATH: process.env.NEXT_PUBLIC_BASE_PATH || '',
|
|
43
26
|
|
|
44
|
-
// Plausible Analytics
|
|
45
|
-
ANALYTICS_PLAUSIBLE: process.env.NEXT_PUBLIC_ANALYTICS_PLAUSIBLE === '1',
|
|
46
|
-
PLAUSIBLE_DOMAIN: process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN,
|
|
47
|
-
PLAUSIBLE_SCRIPT_BASE_URL:
|
|
48
|
-
process.env.NEXT_PUBLIC_PLAUSIBLE_SCRIPT_BASE_URL || 'https://plausible.io',
|
|
49
|
-
|
|
50
|
-
// Posthog Analytics
|
|
51
|
-
ANALYTICS_POSTHOG: process.env.NEXT_PUBLIC_ANALYTICS_POSTHOG === '1',
|
|
52
|
-
POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
|
53
|
-
POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
|
54
|
-
POSTHOG_DEBUG: process.env.NEXT_PUBLIC_POSTHOG_DEBUG === '1',
|
|
55
|
-
|
|
56
|
-
// Umami Analytics
|
|
57
|
-
ANALYTICS_UMAMI: process.env.NEXT_PUBLIC_ANALYTICS_UMAMI === '1',
|
|
58
|
-
UMAMI_SCRIPT_URL:
|
|
59
|
-
process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL || 'https://analytics.umami.is/script.js',
|
|
60
|
-
UMAMI_WEBSITE_ID: process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID,
|
|
61
|
-
|
|
62
27
|
// Sentry
|
|
63
28
|
ENABLE_SENTRY: !!process.env.NEXT_PUBLIC_SENTRY_DSN,
|
|
64
29
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getAnalyticsConfig } from './analytics';
|
|
2
1
|
import { getAppConfig } from './app';
|
|
3
2
|
import { getProviderConfig } from './provider';
|
|
4
3
|
|
|
@@ -9,7 +8,6 @@ export const getServerConfig = () => {
|
|
|
9
8
|
|
|
10
9
|
const provider = getProviderConfig();
|
|
11
10
|
const app = getAppConfig();
|
|
12
|
-
const analytics = getAnalyticsConfig();
|
|
13
11
|
|
|
14
|
-
return { ...provider, ...app
|
|
12
|
+
return { ...provider, ...app };
|
|
15
13
|
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/* eslint-disable sort-keys-fix/sort-keys-fix , typescript-sort-keys/interface */
|
|
2
|
-
|
|
3
|
-
declare global {
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
5
|
-
namespace NodeJS {
|
|
6
|
-
interface ProcessEnv {
|
|
7
|
-
// Vercel Analytics
|
|
8
|
-
ENABLE_VERCEL_ANALYTICS?: string;
|
|
9
|
-
DEBUG_VERCEL_ANALYTICS?: string;
|
|
10
|
-
|
|
11
|
-
// Google Analytics
|
|
12
|
-
ENABLE_GOOGLE_ANALYTICS?: string;
|
|
13
|
-
GOOGLE_ANALYTICS_MEASUREMENT_ID?: string;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const getAnalyticsConfig = () => {
|
|
19
|
-
if (typeof process === 'undefined') {
|
|
20
|
-
throw new Error('[Server Config] you are importing a server-only module outside of server');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
// Vercel Analytics
|
|
25
|
-
ENABLE_VERCEL_ANALYTICS: process.env.ENABLE_VERCEL_ANALYTICS === '1',
|
|
26
|
-
VERCEL_DEBUG: process.env.DEBUG_VERCEL_ANALYTICS === '1',
|
|
27
|
-
|
|
28
|
-
// Google Analytics
|
|
29
|
-
ENABLE_GOOGLE_ANALYTICS: process.env.ENABLE_GOOGLE_ANALYTICS === '1',
|
|
30
|
-
GOOGLE_ANALYTICS_MEASUREMENT_ID: process.env.GOOGLE_ANALYTICS_MEASUREMENT_ID,
|
|
31
|
-
};
|
|
32
|
-
};
|