@gylautorun/dev-proxy-cookie 1.0.0 → 1.0.2
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 +214 -2
- package/dist/index.d.mts +347 -31
- package/dist/index.d.ts +347 -31
- package/dist/index.js +411 -145
- package/dist/index.min.js +4 -4
- package/dist/index.min.mjs +4 -4
- package/dist/index.mjs +407 -140
- package/package.json +1 -1
- package/src/index.ts +13 -0
- package/src/proxy/apply-dev-cookie-header.ts +35 -5
- package/src/proxy/core.ts +214 -15
- package/src/proxy/index.ts +8 -3
- package/src/proxy/vite-middleware-plugin.ts +158 -0
- package/src/proxy/vue-proxy-config.ts +112 -9
- package/src/utils/cookie-reader.ts +74 -3
- package/src/utils/cookie-watcher.ts +50 -1
- package/src/utils/env-detector.ts +162 -0
- package/src/utils/index.ts +9 -1
- package/src/proxy/vite-adapter.ts +0 -77
- package/src/proxy/vite-cookie-plugin.ts +0 -60
- package/src/proxy/vite-plugin.ts +0 -55
|
@@ -1,41 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue CLI 代理配置模块
|
|
3
|
+
*
|
|
4
|
+
* 提供 Vue CLI 开发服务器的代理配置功能,支持从文件读取 Cookie 并注入代理请求。
|
|
5
|
+
* 核心函数包括 createFileCookieGetter 和 createVueProxyConfig。
|
|
6
|
+
*
|
|
7
|
+
* @module vue-proxy-config
|
|
8
|
+
*/
|
|
1
9
|
import type { IncomingMessage } from 'http';
|
|
2
10
|
import * as path from 'path';
|
|
3
|
-
import { CookieReader, watchCookieFile } from '../utils';
|
|
11
|
+
import { CookieReader, watchCookieFile, shouldEnableWatch } from '../utils';
|
|
4
12
|
import { applyDevCookieHeader } from './apply-dev-cookie-header';
|
|
5
13
|
|
|
6
14
|
/** Options for {@link createFileCookieGetter}. */
|
|
7
15
|
export interface CreateFileCookieGetterOptions {
|
|
8
16
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
17
|
+
* 是否监听文件变化
|
|
18
|
+
* - true: 始终监听
|
|
19
|
+
* - false: 从不监听
|
|
20
|
+
* - 'auto': 根据环境自动判断(默认)
|
|
21
|
+
*
|
|
22
|
+
* Cookie 值每次代理请求时都会从磁盘读取,因此即使 watch 为 false,
|
|
23
|
+
* 修改 cookie 文件后也不需要重启开发服务器。
|
|
24
|
+
* @default 'auto'
|
|
12
25
|
*/
|
|
13
|
-
watch?: boolean;
|
|
26
|
+
watch?: boolean | 'auto';
|
|
14
27
|
/** Log when the cookie file changes (only if `watch` is true). @default false */
|
|
15
28
|
debug?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 自定义生产环境变量名称列表,用于判断是否禁用监听
|
|
31
|
+
* 例如: ['MY_APP_ENV', 'BUILD_TYPE']
|
|
32
|
+
*/
|
|
33
|
+
productionEnvs?: string[];
|
|
34
|
+
/**
|
|
35
|
+
* 是否为开发环境(优先级最高)
|
|
36
|
+
* 设置此参数后,将直接决定是否启用文件监听:
|
|
37
|
+
* - true: 启用监听(开发模式)
|
|
38
|
+
* - false: 禁用监听(生产模式)
|
|
39
|
+
*
|
|
40
|
+
* 使用示例: isDev: process.env.NODE_ENV === 'development'
|
|
41
|
+
*/
|
|
42
|
+
isDev?: boolean;
|
|
16
43
|
}
|
|
17
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Vue 代理配置选项
|
|
47
|
+
*/
|
|
18
48
|
export interface VueProxyConfigOptions {
|
|
49
|
+
/** Cookie 获取函数 */
|
|
19
50
|
getCookie?: () => string;
|
|
51
|
+
/** 是否输出调试日志 */
|
|
20
52
|
debug?: boolean;
|
|
53
|
+
/** 自定义请求头 */
|
|
21
54
|
headers?: Record<string, string>;
|
|
55
|
+
/** 是否启用 WebSocket 代理 */
|
|
22
56
|
ws?: boolean;
|
|
57
|
+
/** 是否修改请求头中的 Origin */
|
|
23
58
|
changeOrigin?: boolean;
|
|
59
|
+
/** 是否验证 SSL 证书 */
|
|
24
60
|
secure?: boolean;
|
|
61
|
+
/** 错误回调函数 */
|
|
25
62
|
onError?: (err: Error) => void;
|
|
26
63
|
}
|
|
27
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Vue CLI 代理配置接口
|
|
67
|
+
*
|
|
68
|
+
* 符合 Vue CLI 代理配置格式的对象结构
|
|
69
|
+
*/
|
|
28
70
|
export interface ProxyConfig {
|
|
71
|
+
/** 是否启用 WebSocket 代理 */
|
|
29
72
|
ws: boolean;
|
|
73
|
+
/** 代理目标地址 */
|
|
30
74
|
target: string;
|
|
75
|
+
/** 是否修改请求头中的 Origin */
|
|
31
76
|
changeOrigin: boolean;
|
|
77
|
+
/** 是否验证 SSL 证书 */
|
|
32
78
|
secure: boolean;
|
|
79
|
+
/** 代理请求前的回调函数 */
|
|
33
80
|
onProxyReq: (proxyReq: any, req: IncomingMessage) => void;
|
|
81
|
+
/** 代理响应后的回调函数(可选) */
|
|
34
82
|
onProxyRes?: (proxyRes: any, req: IncomingMessage) => void;
|
|
83
|
+
/** 错误处理回调函数 */
|
|
35
84
|
onError: (err: Error) => void;
|
|
85
|
+
/** 自定义请求头 */
|
|
36
86
|
headers?: Record<string, string>;
|
|
37
87
|
}
|
|
38
88
|
|
|
89
|
+
/**
|
|
90
|
+
* 创建 Vue CLI 代理配置
|
|
91
|
+
*
|
|
92
|
+
* @param target - 代理目标地址
|
|
93
|
+
* @param options - 配置选项
|
|
94
|
+
* @returns Vue CLI 代理配置对象
|
|
95
|
+
*/
|
|
39
96
|
export function createVueProxyConfig(
|
|
40
97
|
target: string,
|
|
41
98
|
options: VueProxyConfigOptions = {}
|
|
@@ -74,14 +131,43 @@ export function createVueProxyConfig(
|
|
|
74
131
|
return config;
|
|
75
132
|
}
|
|
76
133
|
|
|
134
|
+
/**
|
|
135
|
+
* 创建文件 Cookie 获取器
|
|
136
|
+
*
|
|
137
|
+
* 从指定文件读取 Cookie 值,支持文件监听功能。
|
|
138
|
+
*
|
|
139
|
+
* @param cookieFile - Cookie 文件路径
|
|
140
|
+
* @param options - 配置选项
|
|
141
|
+
* @returns Cookie 获取函数
|
|
142
|
+
*/
|
|
77
143
|
export function createFileCookieGetter(
|
|
78
144
|
cookieFile: string,
|
|
79
145
|
options: CreateFileCookieGetterOptions = {}
|
|
80
146
|
): () => string {
|
|
81
|
-
const {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
147
|
+
const {
|
|
148
|
+
watch = 'auto',
|
|
149
|
+
debug = true,
|
|
150
|
+
productionEnvs = [],
|
|
151
|
+
isDev
|
|
152
|
+
} = options;
|
|
153
|
+
const reader = new CookieReader({ cookieFile: path.resolve(cookieFile) }, debug);
|
|
154
|
+
|
|
155
|
+
// 判断是否应该启用监听
|
|
156
|
+
// isDev 参数优先级最高,直接决定是否启用监听
|
|
157
|
+
let shouldWatch: boolean;
|
|
158
|
+
|
|
159
|
+
if (isDev !== undefined) {
|
|
160
|
+
// 用户显式设置了 isDev 参数
|
|
161
|
+
shouldWatch = isDev;
|
|
162
|
+
if (debug) {
|
|
163
|
+
console.log(`[CookieFile] isDev=${isDev}, ${shouldWatch ? 'enabling' : 'disabling'} watch`);
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
// 使用智能环境检测
|
|
167
|
+
shouldWatch = shouldEnableWatch(watch, productionEnvs, debug, '[CookieFile]');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (shouldWatch) {
|
|
85
171
|
watchCookieFile(
|
|
86
172
|
path.resolve(cookieFile),
|
|
87
173
|
(newCookie) => {
|
|
@@ -93,18 +179,35 @@ export function createFileCookieGetter(
|
|
|
93
179
|
console.error('[CookieFile] Watch error:', error.message);
|
|
94
180
|
}
|
|
95
181
|
);
|
|
182
|
+
} else if (debug) {
|
|
183
|
+
console.log('[CookieFile] File watch disabled');
|
|
96
184
|
}
|
|
97
185
|
|
|
98
186
|
return () => reader.readCookie();
|
|
99
187
|
}
|
|
100
188
|
|
|
189
|
+
/**
|
|
190
|
+
* 自动代理配置选项
|
|
191
|
+
*/
|
|
101
192
|
export interface AutoProxyConfigOptions extends VueProxyConfigOptions {
|
|
193
|
+
/** 代理目标地址 */
|
|
102
194
|
target: string;
|
|
195
|
+
/** 忽略的路径列表(不代理这些路径) */
|
|
103
196
|
ignorePaths?: string[];
|
|
197
|
+
/** 包含的路径列表(只代理这些路径) */
|
|
104
198
|
includePaths?: string[];
|
|
199
|
+
/** 额外的代理配置 */
|
|
105
200
|
additionalProxies?: Record<string, string>;
|
|
106
201
|
}
|
|
107
202
|
|
|
203
|
+
/**
|
|
204
|
+
* 创建自动代理配置
|
|
205
|
+
*
|
|
206
|
+
* 根据配置自动生成 Vue CLI 代理配置对象,支持忽略路径和包含路径两种模式。
|
|
207
|
+
*
|
|
208
|
+
* @param options - 配置选项
|
|
209
|
+
* @returns Vue CLI 代理配置对象映射
|
|
210
|
+
*/
|
|
108
211
|
export function createAutoProxyConfig(options: AutoProxyConfigOptions): Record<string, ProxyConfig> {
|
|
109
212
|
const { target, ignorePaths = [], includePaths = [], additionalProxies = {}, getCookie, debug, headers } = options;
|
|
110
213
|
|
|
@@ -1,39 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie 文件读取器模块
|
|
3
|
+
*
|
|
4
|
+
* 提供从文件读取 Cookie 的功能,支持注释过滤和自动文件创建。
|
|
5
|
+
*
|
|
6
|
+
* @module cookie-reader
|
|
7
|
+
*/
|
|
1
8
|
import * as fs from 'fs';
|
|
2
9
|
import * as path from 'path';
|
|
3
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Cookie 读取器配置选项
|
|
13
|
+
*/
|
|
4
14
|
export interface CookieReaderOptions {
|
|
5
15
|
cookieFile: string;
|
|
6
16
|
encoding?: BufferEncoding;
|
|
7
17
|
}
|
|
8
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Cookie 文件读取器类
|
|
21
|
+
*
|
|
22
|
+
* 提供从文件读取 Cookie 的功能,支持注释过滤和自动文件创建。
|
|
23
|
+
*/
|
|
9
24
|
export class CookieReader {
|
|
25
|
+
/** 配置选项 */
|
|
10
26
|
protected options: CookieReaderOptions;
|
|
27
|
+
/** 是否启用调试模式 */
|
|
28
|
+
protected debug: boolean;
|
|
11
29
|
|
|
12
|
-
|
|
30
|
+
/**
|
|
31
|
+
* 构造函数
|
|
32
|
+
* @param options - 配置选项
|
|
33
|
+
* @param debug - 是否启用调试模式
|
|
34
|
+
*/
|
|
35
|
+
constructor(options: CookieReaderOptions, debug: boolean = false) {
|
|
13
36
|
this.options = {
|
|
14
37
|
encoding: 'utf-8',
|
|
15
38
|
...options,
|
|
16
39
|
};
|
|
40
|
+
this.debug = debug;
|
|
17
41
|
}
|
|
18
42
|
|
|
43
|
+
/**
|
|
44
|
+
* 读取 Cookie 文件内容
|
|
45
|
+
*
|
|
46
|
+
* 支持过滤注释行(以 # 开头)和空行,将有效行用分号连接。
|
|
47
|
+
*
|
|
48
|
+
* @returns Cookie 字符串
|
|
49
|
+
*/
|
|
19
50
|
readCookie(): string {
|
|
20
51
|
try {
|
|
21
52
|
const filePath = path.resolve(this.options.cookieFile);
|
|
53
|
+
|
|
54
|
+
if (this.debug) {
|
|
55
|
+
console.log('[CookieReader] Resolved cookie file path:', filePath);
|
|
56
|
+
console.log('[CookieReader] File exists:', fs.existsSync(filePath));
|
|
57
|
+
}
|
|
58
|
+
|
|
22
59
|
if (fs.existsSync(filePath)) {
|
|
23
60
|
const content = fs.readFileSync(filePath, this.options.encoding || 'utf-8');
|
|
61
|
+
|
|
62
|
+
if (this.debug) {
|
|
63
|
+
console.log('[CookieReader] File content length:', content.length);
|
|
64
|
+
}
|
|
65
|
+
|
|
24
66
|
// 过滤注释行(以 # 开头)和空行,然后合并成一行
|
|
25
67
|
const lines = content.split('\n');
|
|
26
68
|
const cookieLines = lines
|
|
27
69
|
.map(line => line.trim())
|
|
28
70
|
.filter(line => line && !line.startsWith('#'));
|
|
29
|
-
|
|
71
|
+
|
|
72
|
+
const result = cookieLines.join('; ');
|
|
73
|
+
|
|
74
|
+
if (this.debug) {
|
|
75
|
+
console.log('[CookieReader] Parsed cookie:', result ? '(has cookie)' : '(empty)');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (this.debug) {
|
|
82
|
+
console.log('[CookieReader] Cookie file not found:', filePath);
|
|
30
83
|
}
|
|
84
|
+
|
|
31
85
|
return '';
|
|
32
|
-
} catch {
|
|
86
|
+
} catch (err) {
|
|
87
|
+
if (this.debug) {
|
|
88
|
+
console.error('[CookieReader] Error reading cookie file:', (err as Error).message);
|
|
89
|
+
}
|
|
33
90
|
return '';
|
|
34
91
|
}
|
|
35
92
|
}
|
|
36
93
|
|
|
94
|
+
/**
|
|
95
|
+
* 确保 Cookie 文件存在
|
|
96
|
+
*
|
|
97
|
+
* 如果文件不存在,会自动创建空文件。
|
|
98
|
+
* 如果父目录不存在,会自动创建目录。
|
|
99
|
+
*/
|
|
37
100
|
ensureCookieFile(): void {
|
|
38
101
|
const filePath = path.resolve(this.options.cookieFile);
|
|
39
102
|
const dir = path.dirname(filePath);
|
|
@@ -48,6 +111,14 @@ export class CookieReader {
|
|
|
48
111
|
}
|
|
49
112
|
}
|
|
50
113
|
|
|
114
|
+
/**
|
|
115
|
+
* 创建 Cookie 获取器函数
|
|
116
|
+
*
|
|
117
|
+
* 返回一个函数,每次调用时从文件读取最新的 Cookie 值。
|
|
118
|
+
*
|
|
119
|
+
* @param cookieFile - Cookie 文件路径
|
|
120
|
+
* @returns Cookie 获取函数
|
|
121
|
+
*/
|
|
51
122
|
export function createCookieGetter(cookieFile: string): () => string {
|
|
52
123
|
const reader = new CookieReader({ cookieFile });
|
|
53
124
|
return () => reader.readCookie();
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie 文件监听器模块
|
|
3
|
+
*
|
|
4
|
+
* 使用 chokidar 监听 Cookie 文件变化,当文件内容改变时触发回调。
|
|
5
|
+
* 支持自动创建文件和稳定性阈值配置。
|
|
6
|
+
*
|
|
7
|
+
* @module cookie-watcher
|
|
8
|
+
*/
|
|
1
9
|
import * as fs from 'fs';
|
|
2
10
|
import * as path from 'path';
|
|
3
11
|
import chokidar, { FSWatcher } from 'chokidar';
|
|
4
12
|
import { CookieReader } from './cookie-reader';
|
|
5
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Cookie 监听器配置选项
|
|
16
|
+
*/
|
|
6
17
|
export interface CookieWatcherOptions {
|
|
7
18
|
cookieFile: string;
|
|
8
19
|
onCookieChange: (cookie: string) => void;
|
|
@@ -10,12 +21,26 @@ export interface CookieWatcherOptions {
|
|
|
10
21
|
autoCreateFile?: boolean;
|
|
11
22
|
}
|
|
12
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Cookie 文件监听器类
|
|
26
|
+
*
|
|
27
|
+
* 使用 chokidar 监听 Cookie 文件变化,当文件内容改变时触发回调。
|
|
28
|
+
* 支持自动创建文件和稳定性阈值配置。
|
|
29
|
+
*/
|
|
13
30
|
export class CookieWatcher {
|
|
31
|
+
/** 文件监听器实例 */
|
|
14
32
|
private watcher: FSWatcher | null = null;
|
|
33
|
+
/** 配置选项 */
|
|
15
34
|
private options: CookieWatcherOptions;
|
|
35
|
+
/** Cookie 读取器 */
|
|
16
36
|
private cookieReader: CookieReader;
|
|
37
|
+
/** 上次读取的 Cookie 内容 */
|
|
17
38
|
private lastContent: string = '';
|
|
18
39
|
|
|
40
|
+
/**
|
|
41
|
+
* 构造函数
|
|
42
|
+
* @param options - 配置选项
|
|
43
|
+
*/
|
|
19
44
|
constructor(options: CookieWatcherOptions) {
|
|
20
45
|
this.options = {
|
|
21
46
|
autoCreateFile: true,
|
|
@@ -24,6 +49,11 @@ export class CookieWatcher {
|
|
|
24
49
|
this.cookieReader = new CookieReader({ cookieFile: options.cookieFile });
|
|
25
50
|
}
|
|
26
51
|
|
|
52
|
+
/**
|
|
53
|
+
* 文件变化处理函数
|
|
54
|
+
*
|
|
55
|
+
* 读取新的 Cookie 内容,如果与上次不同则触发回调。
|
|
56
|
+
*/
|
|
27
57
|
private handleChange = (): void => {
|
|
28
58
|
const newContent = this.cookieReader.readCookie();
|
|
29
59
|
if (newContent !== this.lastContent) {
|
|
@@ -33,6 +63,9 @@ export class CookieWatcher {
|
|
|
33
63
|
}
|
|
34
64
|
};
|
|
35
65
|
|
|
66
|
+
/**
|
|
67
|
+
* 启动文件监听
|
|
68
|
+
*/
|
|
36
69
|
start(): void {
|
|
37
70
|
if (this.options.autoCreateFile) {
|
|
38
71
|
this.cookieReader.ensureCookieFile();
|
|
@@ -52,7 +85,8 @@ export class CookieWatcher {
|
|
|
52
85
|
},
|
|
53
86
|
});
|
|
54
87
|
|
|
55
|
-
// "add" covers atomic replace (unlink + rename) used by some editors;
|
|
88
|
+
// "add" covers atomic replace (unlink + rename) used by some editors;
|
|
89
|
+
// "change" covers in-place writes
|
|
56
90
|
this.watcher.on('change', this.handleChange);
|
|
57
91
|
this.watcher.on('add', this.handleChange);
|
|
58
92
|
this.watcher.on('error', (error) => {
|
|
@@ -63,6 +97,9 @@ export class CookieWatcher {
|
|
|
63
97
|
}
|
|
64
98
|
}
|
|
65
99
|
|
|
100
|
+
/**
|
|
101
|
+
* 停止文件监听
|
|
102
|
+
*/
|
|
66
103
|
stop(): void {
|
|
67
104
|
if (this.watcher) {
|
|
68
105
|
this.watcher.close();
|
|
@@ -71,11 +108,23 @@ export class CookieWatcher {
|
|
|
71
108
|
}
|
|
72
109
|
}
|
|
73
110
|
|
|
111
|
+
/**
|
|
112
|
+
* 获取当前 Cookie 值
|
|
113
|
+
* @returns 当前 Cookie 字符串
|
|
114
|
+
*/
|
|
74
115
|
getCurrentCookie(): string {
|
|
75
116
|
return this.lastContent;
|
|
76
117
|
}
|
|
77
118
|
}
|
|
78
119
|
|
|
120
|
+
/**
|
|
121
|
+
* 创建并启动 Cookie 文件监听器
|
|
122
|
+
*
|
|
123
|
+
* @param cookieFile - Cookie 文件路径
|
|
124
|
+
* @param onCookieChange - Cookie 变化回调函数
|
|
125
|
+
* @param onError - 错误回调函数(可选)
|
|
126
|
+
* @returns CookieWatcher 实例
|
|
127
|
+
*/
|
|
79
128
|
export function watchCookieFile(
|
|
80
129
|
cookieFile: string,
|
|
81
130
|
onCookieChange: (cookie: string) => void,
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 环境检测工具模块
|
|
3
|
+
*
|
|
4
|
+
* 提供智能环境检测功能,用于判断当前是否为生产构建环境,
|
|
5
|
+
* 从而决定是否启用文件监听等开发环境特性。
|
|
6
|
+
*
|
|
7
|
+
* @module env-detector
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 判断环境变量值是否表示生产环境
|
|
12
|
+
*
|
|
13
|
+
* @param value - 环境变量值
|
|
14
|
+
* @returns 是否为生产环境值
|
|
15
|
+
*/
|
|
16
|
+
export function isProductionValue(value: string): boolean {
|
|
17
|
+
const productionValues = [
|
|
18
|
+
'production', // 生产环境
|
|
19
|
+
'prod', // 生产环境
|
|
20
|
+
'prd', // 生产环境
|
|
21
|
+
'release', // 发布环境
|
|
22
|
+
'staging', // 预发布环境
|
|
23
|
+
'uat', // 预发布环境
|
|
24
|
+
];
|
|
25
|
+
return productionValues.includes(value.toLowerCase().trim());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 智能检测当前是否为生产构建环境
|
|
30
|
+
* 通过多种方式综合判断,避免依赖单一环境变量
|
|
31
|
+
*
|
|
32
|
+
* @param customEnvs 用户自定义的环境变量名称列表
|
|
33
|
+
* @param debug 是否输出调试日志
|
|
34
|
+
* @param loggerPrefix 日志前缀,用于区分不同模块
|
|
35
|
+
* @returns 是否为生产环境
|
|
36
|
+
*/
|
|
37
|
+
export function detectProductionEnvironment(
|
|
38
|
+
customEnvs: string[] = [],
|
|
39
|
+
debug: boolean = false,
|
|
40
|
+
loggerPrefix: string = '[env-detector]'
|
|
41
|
+
): boolean {
|
|
42
|
+
const env = process.env;
|
|
43
|
+
|
|
44
|
+
// 1. 检查自定义环境变量
|
|
45
|
+
if (customEnvs.length > 0) {
|
|
46
|
+
for (const envName of customEnvs) {
|
|
47
|
+
const envValue = env[envName];
|
|
48
|
+
if (envValue && isProductionValue(envValue)) {
|
|
49
|
+
if (debug) {
|
|
50
|
+
console.log(`${loggerPrefix} Detected production via custom env: ${envName}=${envValue}`);
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 2. 检查常见的环境变量
|
|
58
|
+
const commonEnvNames = [
|
|
59
|
+
'NODE_ENV',
|
|
60
|
+
'BUILD_MODE',
|
|
61
|
+
'VUE_APP_ENV',
|
|
62
|
+
'VITE_NODE_ENV',
|
|
63
|
+
'WEBPACK_MODE',
|
|
64
|
+
'CI_ENV',
|
|
65
|
+
'APP_ENV',
|
|
66
|
+
'ENV',
|
|
67
|
+
'DEPLOY_ENV',
|
|
68
|
+
'RUN_MODE',
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
for (const envName of commonEnvNames) {
|
|
72
|
+
const envValue = env[envName];
|
|
73
|
+
if (envValue && isProductionValue(envValue)) {
|
|
74
|
+
if (debug) {
|
|
75
|
+
console.log(`${loggerPrefix} Detected production via env: ${envName}=${envValue}`);
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 3. 检查 CI/CD 环境标识
|
|
82
|
+
if (env.CI === 'true' || env.CI === '1' || env.CI === 'yes') {
|
|
83
|
+
if (debug) {
|
|
84
|
+
console.log(`${loggerPrefix} Detected production via CI env`);
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 4. 检查 npm 生命周期事件(构建命令)
|
|
90
|
+
if (env.npm_lifecycle_event) {
|
|
91
|
+
const lifecycleEvent = env.npm_lifecycle_event.toLowerCase();
|
|
92
|
+
if (lifecycleEvent.includes('build') ||
|
|
93
|
+
lifecycleEvent.includes('prod') ||
|
|
94
|
+
lifecycleEvent.includes('prd') ||
|
|
95
|
+
lifecycleEvent.includes('release')) {
|
|
96
|
+
if (debug) {
|
|
97
|
+
console.log(`${loggerPrefix} Detected production via lifecycle event: ${env.npm_lifecycle_event}`);
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 5. 检查进程参数(构建工具通常会传入特定参数)
|
|
104
|
+
const processArgs = process.argv.join('').toLowerCase();
|
|
105
|
+
if (processArgs.includes('build') ||
|
|
106
|
+
processArgs.includes('production') ||
|
|
107
|
+
processArgs.includes('--mode=production') ||
|
|
108
|
+
processArgs.includes('--prod') ||
|
|
109
|
+
processArgs.includes('--release')) {
|
|
110
|
+
if (debug) {
|
|
111
|
+
console.log(`${loggerPrefix} Detected production via process arguments`);
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 默认认为是开发环境
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 判断是否应该启用文件监听
|
|
122
|
+
*
|
|
123
|
+
* 注意:此函数仅在 isDev 参数未设置时调用,用于智能判断环境
|
|
124
|
+
* 如果用户已通过 isDev 参数明确指定环境,则不会调用此函数
|
|
125
|
+
*
|
|
126
|
+
* @param watch 用户设置的 watch 选项
|
|
127
|
+
* @param customEnvs 用户自定义的环境变量列表
|
|
128
|
+
* @param debug 是否输出调试日志
|
|
129
|
+
* @param loggerPrefix 日志前缀
|
|
130
|
+
* @returns 是否应该启用监听
|
|
131
|
+
*/
|
|
132
|
+
export function shouldEnableWatch(
|
|
133
|
+
watch: boolean | 'auto',
|
|
134
|
+
customEnvs: string[] = [],
|
|
135
|
+
debug: boolean = false,
|
|
136
|
+
loggerPrefix: string = '[env-detector]'
|
|
137
|
+
): boolean {
|
|
138
|
+
// 用户显式设置为 true 或 false,直接返回
|
|
139
|
+
if (typeof watch === 'boolean') {
|
|
140
|
+
if (debug && !watch) {
|
|
141
|
+
console.log(`${loggerPrefix} Watch disabled by user setting`);
|
|
142
|
+
}
|
|
143
|
+
return watch;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 'auto' 模式:智能检测环境
|
|
147
|
+
const isProduction = detectProductionEnvironment(customEnvs, debug, loggerPrefix);
|
|
148
|
+
|
|
149
|
+
if (isProduction) {
|
|
150
|
+
if (debug) {
|
|
151
|
+
console.log(`${loggerPrefix} Auto-detected production mode - disabling watch`);
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// 开发环境:启用监听
|
|
157
|
+
if (debug) {
|
|
158
|
+
console.log(`${loggerPrefix} Auto-detected development mode - enabling watch`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return true;
|
|
162
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from 'vite';
|
|
2
|
-
import { viteAutoProxyCookie, type ViteAutoProxyCookiePluginOptions } from './vite-plugin';
|
|
3
|
-
import { viteDevProxyCookie, type ViteDevProxyCookieOptions } from './vite-cookie-plugin';
|
|
4
|
-
|
|
5
|
-
let viteVersion: string = '';
|
|
6
|
-
let majorVersion: number | null = null;
|
|
7
|
-
|
|
8
|
-
function detectViteVersion(): number {
|
|
9
|
-
if (majorVersion !== null) {
|
|
10
|
-
return majorVersion;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
const pkg = require('vite/package.json');
|
|
15
|
-
viteVersion = pkg.version;
|
|
16
|
-
majorVersion = parseInt(viteVersion.split('.')[0], 10);
|
|
17
|
-
} catch {
|
|
18
|
-
majorVersion = 5;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return majorVersion;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface UnifiedProxyCookieOptions {
|
|
25
|
-
cookieFile: string;
|
|
26
|
-
target?: string;
|
|
27
|
-
debug?: boolean;
|
|
28
|
-
autoRestart?: boolean;
|
|
29
|
-
restartMarkerFile?: string;
|
|
30
|
-
proxyMap?: Record<string, string>;
|
|
31
|
-
ignorePaths?: string[];
|
|
32
|
-
includePaths?: string[];
|
|
33
|
-
onCookieChange?: (cookie: string) => void;
|
|
34
|
-
mode?: 'auto' | 'proxy' | 'cookie';
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function createDevProxyCookie(options: UnifiedProxyCookieOptions): Plugin {
|
|
38
|
-
const {
|
|
39
|
-
mode = 'auto',
|
|
40
|
-
...restOptions
|
|
41
|
-
} = options;
|
|
42
|
-
|
|
43
|
-
const version = detectViteVersion();
|
|
44
|
-
|
|
45
|
-
if (options.debug) {
|
|
46
|
-
console.log(`[dev-proxy-cookie] Detected Vite ${version}.x`);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (mode === 'cookie' || (mode === 'auto' && !options.target)) {
|
|
50
|
-
return viteDevProxyCookie({
|
|
51
|
-
cookieFile: options.cookieFile,
|
|
52
|
-
debug: options.debug,
|
|
53
|
-
onCookieChange: options.onCookieChange,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const pluginOptions: ViteAutoProxyCookiePluginOptions = {
|
|
58
|
-
cookieFile: options.cookieFile,
|
|
59
|
-
target: options.target!,
|
|
60
|
-
debug: options.debug,
|
|
61
|
-
autoRestart: options.autoRestart ?? true,
|
|
62
|
-
restartMarkerFile: options.restartMarkerFile,
|
|
63
|
-
proxyMap: options.proxyMap,
|
|
64
|
-
ignorePaths: options.ignorePaths,
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
return viteAutoProxyCookie(pluginOptions);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function getViteVersion(): string | null {
|
|
71
|
-
detectViteVersion();
|
|
72
|
-
return viteVersion;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function getViteMajorVersion(): number {
|
|
76
|
-
return detectViteVersion();
|
|
77
|
-
}
|