vite-plugin-automock 1.1.5 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -232
- package/dist/{chunk-DJWYFFPU.mjs → chunk-2KRAWI7J.mjs} +35 -11
- package/dist/chunk-2KRAWI7J.mjs.map +1 -0
- package/dist/client/index.d.mts +3 -2
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.js +34 -10
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +1 -1
- package/dist/index.d.mts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +65 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +32 -10
- package/dist/index.mjs.map +1 -1
- package/docs/API_CN.md +398 -0
- package/docs/CONFIGURATION_CN.md +196 -0
- package/package.json +3 -2
- package/dist/chunk-DJWYFFPU.mjs.map +0 -1
|
@@ -4,6 +4,24 @@ var MockInterceptor = class {
|
|
|
4
4
|
constructor(options) {
|
|
5
5
|
this.options = options;
|
|
6
6
|
}
|
|
7
|
+
normalizeUrlPath(url, baseURL) {
|
|
8
|
+
if (!url) return "";
|
|
9
|
+
try {
|
|
10
|
+
const isAbsoluteUrl = /^[a-z][a-z\d+\-.]*:\/\//i.test(url);
|
|
11
|
+
const browserOrigin = typeof window !== "undefined" && window.location?.origin ? window.location.origin : "http://localhost";
|
|
12
|
+
if (isAbsoluteUrl) {
|
|
13
|
+
return new URL(url).pathname;
|
|
14
|
+
}
|
|
15
|
+
if (baseURL) {
|
|
16
|
+
const normalizedBase = baseURL.endsWith("/") ? baseURL : `${baseURL}/`;
|
|
17
|
+
const normalizedUrl = url.replace(/^\/+/, "");
|
|
18
|
+
return new URL(normalizedUrl, normalizedBase).pathname;
|
|
19
|
+
}
|
|
20
|
+
return new URL(url, browserOrigin).pathname;
|
|
21
|
+
} catch {
|
|
22
|
+
return url.split(/[?#]/)[0] || "";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
7
25
|
/**
|
|
8
26
|
* Check if mock is enabled
|
|
9
27
|
*/
|
|
@@ -22,14 +40,19 @@ var MockInterceptor = class {
|
|
|
22
40
|
* - "GET /api/v1/asset/xxx" (HTTP method + URL)
|
|
23
41
|
* - "/api/v1/asset/xxx/get.js" (File path format from automock plugin)
|
|
24
42
|
*/
|
|
25
|
-
findMock(url, method) {
|
|
43
|
+
findMock(url, method, baseURL) {
|
|
26
44
|
const methodUpper = method.toUpperCase();
|
|
27
45
|
const methodLower = method.toLowerCase();
|
|
46
|
+
const normalizedPath = this.normalizeUrlPath(url, baseURL);
|
|
28
47
|
const httpMethodKey = `${methodUpper} ${url}`;
|
|
29
48
|
if (this.options.mockData[httpMethodKey]) {
|
|
30
49
|
return this.options.mockData[httpMethodKey];
|
|
31
50
|
}
|
|
32
|
-
const
|
|
51
|
+
const normalizedHttpMethodKey = `${methodUpper} ${normalizedPath}`;
|
|
52
|
+
if (this.options.mockData[normalizedHttpMethodKey]) {
|
|
53
|
+
return this.options.mockData[normalizedHttpMethodKey];
|
|
54
|
+
}
|
|
55
|
+
const filePathKey = `${normalizedPath}/${methodLower}.js`;
|
|
33
56
|
if (this.options.mockData[filePathKey]) {
|
|
34
57
|
return this.options.mockData[filePathKey];
|
|
35
58
|
}
|
|
@@ -38,21 +61,21 @@ var MockInterceptor = class {
|
|
|
38
61
|
/**
|
|
39
62
|
* Determine if request should be mocked
|
|
40
63
|
*/
|
|
41
|
-
shouldMock(url, method) {
|
|
64
|
+
shouldMock(url, method, baseURL) {
|
|
42
65
|
if (!this.isEnabled()) {
|
|
43
66
|
return false;
|
|
44
67
|
}
|
|
45
|
-
const mock = this.findMock(url, method);
|
|
68
|
+
const mock = this.findMock(url, method, baseURL);
|
|
46
69
|
return mock !== null && mock.enable;
|
|
47
70
|
}
|
|
48
71
|
/**
|
|
49
72
|
* Get mock data for request
|
|
50
73
|
*/
|
|
51
|
-
getMock(url, method) {
|
|
52
|
-
if (!this.shouldMock(url, method)) {
|
|
74
|
+
getMock(url, method, baseURL) {
|
|
75
|
+
if (!this.shouldMock(url, method, baseURL)) {
|
|
53
76
|
return null;
|
|
54
77
|
}
|
|
55
|
-
return this.findMock(url, method);
|
|
78
|
+
return this.findMock(url, method, baseURL);
|
|
56
79
|
}
|
|
57
80
|
/**
|
|
58
81
|
* Setup axios interceptor
|
|
@@ -62,9 +85,10 @@ var MockInterceptor = class {
|
|
|
62
85
|
async (config) => {
|
|
63
86
|
const url = config.url || "";
|
|
64
87
|
const method = config.method?.toUpperCase() || "GET";
|
|
65
|
-
const
|
|
88
|
+
const normalizedUrl = this.normalizeUrlPath(url, config.baseURL);
|
|
89
|
+
const mock = this.getMock(url, method, config.baseURL);
|
|
66
90
|
if (mock) {
|
|
67
|
-
this.options.onMockHit?.(
|
|
91
|
+
this.options.onMockHit?.(normalizedUrl, method, mock);
|
|
68
92
|
config.adapter = async () => {
|
|
69
93
|
const { data, delay = 0, status = 200 } = mock;
|
|
70
94
|
if (delay > 0) {
|
|
@@ -80,7 +104,7 @@ var MockInterceptor = class {
|
|
|
80
104
|
};
|
|
81
105
|
} else {
|
|
82
106
|
const reason = !this.isEnabled() ? "Mock disabled globally" : "No matching mock found or mock disabled";
|
|
83
|
-
this.options.onBypass?.(
|
|
107
|
+
this.options.onBypass?.(normalizedUrl, method, reason);
|
|
84
108
|
}
|
|
85
109
|
return config;
|
|
86
110
|
},
|
|
@@ -160,4 +184,4 @@ export {
|
|
|
160
184
|
registerHttpInstance,
|
|
161
185
|
initMockInterceptorForPureHttp
|
|
162
186
|
};
|
|
163
|
-
//# sourceMappingURL=chunk-
|
|
187
|
+
//# sourceMappingURL=chunk-2KRAWI7J.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/interceptor.ts"],"sourcesContent":["import type {\n AxiosInstance,\n AxiosResponse,\n InternalAxiosRequestConfig,\n} from \"axios\";\n\ndeclare const __AUTOMOCK_ENABLED__: boolean;\n\nexport type MockBundleData = {\n enable: boolean;\n data: unknown;\n delay?: number;\n status?: number;\n isBinary?: boolean;\n};\n\nexport type MockInterceptorOptions = {\n mockData: Record<string, MockBundleData>;\n enabled?: boolean | (() => boolean);\n onMockHit?: (url: string, method: string, mock: MockBundleData) => void;\n onBypass?: (url: string, method: string, reason: string) => void;\n};\n\ntype MockEnabledState = boolean | undefined;\n\ndeclare global {\n interface Window {\n __MOCK_ENABLED__?: MockEnabledState;\n }\n}\n\nclass MockInterceptor {\n private options: MockInterceptorOptions;\n\n constructor(options: MockInterceptorOptions) {\n this.options = options;\n }\n\n private normalizeUrlPath(url: string, baseURL?: string): string {\n if (!url) return \"\";\n\n try {\n const isAbsoluteUrl = /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n const browserOrigin =\n typeof window !== \"undefined\" && window.location?.origin\n ? window.location.origin\n : \"http://localhost\";\n\n if (isAbsoluteUrl) {\n return new URL(url).pathname;\n }\n\n if (baseURL) {\n const normalizedBase = baseURL.endsWith(\"/\") ? baseURL : `${baseURL}/`;\n const normalizedUrl = url.replace(/^\\/+/, \"\");\n return new URL(normalizedUrl, normalizedBase).pathname;\n }\n\n return new URL(url, browserOrigin).pathname;\n } catch {\n return url.split(/[?#]/)[0] || \"\";\n }\n }\n\n /**\n * Check if mock is enabled\n */\n isEnabled(): boolean {\n // Check runtime flag first\n if (window.__MOCK_ENABLED__ !== undefined) {\n return window.__MOCK_ENABLED__;\n }\n // Check environment variable\n if (typeof this.options.enabled === \"function\") {\n return this.options.enabled();\n }\n return this.options.enabled ?? false;\n }\n\n /**\n * Find matching mock data for the request\n * Supports both formats:\n * - \"GET /api/v1/asset/xxx\" (HTTP method + URL)\n * - \"/api/v1/asset/xxx/get.js\" (File path format from automock plugin)\n */\n private findMock(url: string, method: string, baseURL?: string): MockBundleData | null {\n const methodUpper = method.toUpperCase();\n const methodLower = method.toLowerCase();\n const normalizedPath = this.normalizeUrlPath(url, baseURL);\n\n // Try HTTP method + URL format first (for compatibility)\n const httpMethodKey = `${methodUpper} ${url}`;\n if (this.options.mockData[httpMethodKey]) {\n return this.options.mockData[httpMethodKey];\n }\n\n const normalizedHttpMethodKey = `${methodUpper} ${normalizedPath}`;\n if (this.options.mockData[normalizedHttpMethodKey]) {\n return this.options.mockData[normalizedHttpMethodKey];\n }\n\n // Try file path format from automock plugin: /api/v1/asset/xxx/get.js\n const filePathKey = `${normalizedPath}/${methodLower}.js`;\n if (this.options.mockData[filePathKey]) {\n return this.options.mockData[filePathKey];\n }\n\n return null;\n }\n\n /**\n * Determine if request should be mocked\n */\n shouldMock(url: string, method: string, baseURL?: string): boolean {\n if (!this.isEnabled()) {\n return false;\n }\n\n const mock = this.findMock(url, method, baseURL);\n return mock !== null && mock.enable;\n }\n\n /**\n * Get mock data for request\n */\n getMock(url: string, method: string, baseURL?: string): MockBundleData | null {\n if (!this.shouldMock(url, method, baseURL)) {\n return null;\n }\n return this.findMock(url, method, baseURL);\n }\n\n /**\n * Setup axios interceptor\n */\n setupAxios(axiosInstance: AxiosInstance): void {\n axiosInstance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig) => {\n const url = config.url || \"\";\n const method = config.method?.toUpperCase() || \"GET\";\n const normalizedUrl = this.normalizeUrlPath(url, config.baseURL);\n\n const mock = this.getMock(url, method, config.baseURL);\n\n if (mock) {\n // Trigger mock hit callback\n this.options.onMockHit?.(normalizedUrl, method, mock);\n\n // Set adapter to return mock data\n (config as InternalAxiosRequestConfig & { adapter: () => Promise<AxiosResponse> }).adapter = async () => {\n const { data, delay = 0, status = 200 } = mock;\n\n // Simulate delay\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n\n return {\n data,\n status,\n statusText: \"OK\",\n headers: {},\n config,\n };\n };\n } else {\n // Trigger bypass callback\n const reason = !this.isEnabled()\n ? \"Mock disabled globally\"\n : \"No matching mock found or mock disabled\";\n this.options.onBypass?.(normalizedUrl, method, reason);\n }\n\n return config;\n },\n (error: unknown) => Promise.reject(error),\n );\n }\n}\n\n/**\n * Create mock interceptor instance\n */\nexport function createMockInterceptor(\n options: MockInterceptorOptions,\n): MockInterceptor {\n return new MockInterceptor(options);\n}\n\n/**\n * Load mock data from bundled JSON file\n */\nexport async function loadMockData(): Promise<Record<string, MockBundleData>> {\n try {\n // In production, mock-data.json is generated by automock plugin\n // Use absolute path to load it from dist directory\n const response = await fetch(\"/mock-data.json\");\n if (!response.ok) {\n console.warn(\n \"[MockInterceptor] Failed to load mock-data.json:\",\n response.statusText,\n );\n return {};\n }\n const data = (await response.json()) as Record<string, MockBundleData>;\n return data;\n } catch (error) {\n console.warn(\"[MockInterceptor] Failed to load mock-data.json:\", error);\n return {};\n }\n}\n\nasync function createInterceptorFromBundle(): Promise<MockInterceptor> {\n const mockData = await loadMockData();\n const isEnabled = typeof __AUTOMOCK_ENABLED__ !== \"undefined\" && __AUTOMOCK_ENABLED__;\n\n return new MockInterceptor({\n mockData,\n enabled: isEnabled,\n onMockHit: (url: string, method: string) => {\n console.log(`[MOCK HIT] ${method} ${url}`);\n },\n onBypass: (url: string, method: string, reason: string) => {\n console.log(`[MOCK BYPASS] ${method} ${url} - ${reason}`);\n },\n });\n}\n\nexport async function initMockInterceptor(\n axiosInstance?: AxiosInstance,\n): Promise<void> {\n if (!axiosInstance) {\n throw new Error(\n \"[MockInterceptor] axiosInstance is required. Please provide an axios instance.\",\n );\n }\n\n const interceptor = await createInterceptorFromBundle();\n interceptor.setupAxios(axiosInstance);\n}\n\nexport function setMockEnabled(enabled: boolean): void {\n window.__MOCK_ENABLED__ = enabled;\n}\n\nexport function isMockEnabled(): boolean {\n return !!window.__MOCK_ENABLED__;\n}\n\ntype HttpInstance = {\n constructor: { axiosInstance: AxiosInstance };\n};\n\nlet httpInstanceRef: HttpInstance | undefined;\n\nexport function registerHttpInstance(http: HttpInstance): void {\n httpInstanceRef = http;\n}\n\nexport async function initMockInterceptorForPureHttp(): Promise<void> {\n if (!httpInstanceRef) {\n throw new Error(\n \"[MockInterceptor] http instance not registered. Call registerHttpInstance(http) first.\",\n );\n }\n\n const interceptor = await createInterceptorFromBundle();\n interceptor.setupAxios(httpInstanceRef.constructor.axiosInstance);\n}\n"],"mappings":"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","names":[]}
|
package/dist/client/index.d.mts
CHANGED
|
@@ -22,6 +22,7 @@ declare global {
|
|
|
22
22
|
declare class MockInterceptor {
|
|
23
23
|
private options;
|
|
24
24
|
constructor(options: MockInterceptorOptions);
|
|
25
|
+
private normalizeUrlPath;
|
|
25
26
|
/**
|
|
26
27
|
* Check if mock is enabled
|
|
27
28
|
*/
|
|
@@ -36,11 +37,11 @@ declare class MockInterceptor {
|
|
|
36
37
|
/**
|
|
37
38
|
* Determine if request should be mocked
|
|
38
39
|
*/
|
|
39
|
-
shouldMock(url: string, method: string): boolean;
|
|
40
|
+
shouldMock(url: string, method: string, baseURL?: string): boolean;
|
|
40
41
|
/**
|
|
41
42
|
* Get mock data for request
|
|
42
43
|
*/
|
|
43
|
-
getMock(url: string, method: string): MockBundleData | null;
|
|
44
|
+
getMock(url: string, method: string, baseURL?: string): MockBundleData | null;
|
|
44
45
|
/**
|
|
45
46
|
* Setup axios interceptor
|
|
46
47
|
*/
|
package/dist/client/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ declare global {
|
|
|
22
22
|
declare class MockInterceptor {
|
|
23
23
|
private options;
|
|
24
24
|
constructor(options: MockInterceptorOptions);
|
|
25
|
+
private normalizeUrlPath;
|
|
25
26
|
/**
|
|
26
27
|
* Check if mock is enabled
|
|
27
28
|
*/
|
|
@@ -36,11 +37,11 @@ declare class MockInterceptor {
|
|
|
36
37
|
/**
|
|
37
38
|
* Determine if request should be mocked
|
|
38
39
|
*/
|
|
39
|
-
shouldMock(url: string, method: string): boolean;
|
|
40
|
+
shouldMock(url: string, method: string, baseURL?: string): boolean;
|
|
40
41
|
/**
|
|
41
42
|
* Get mock data for request
|
|
42
43
|
*/
|
|
43
|
-
getMock(url: string, method: string): MockBundleData | null;
|
|
44
|
+
getMock(url: string, method: string, baseURL?: string): MockBundleData | null;
|
|
44
45
|
/**
|
|
45
46
|
* Setup axios interceptor
|
|
46
47
|
*/
|
package/dist/client/index.js
CHANGED
|
@@ -36,6 +36,24 @@ var MockInterceptor = class {
|
|
|
36
36
|
constructor(options) {
|
|
37
37
|
this.options = options;
|
|
38
38
|
}
|
|
39
|
+
normalizeUrlPath(url, baseURL) {
|
|
40
|
+
if (!url) return "";
|
|
41
|
+
try {
|
|
42
|
+
const isAbsoluteUrl = /^[a-z][a-z\d+\-.]*:\/\//i.test(url);
|
|
43
|
+
const browserOrigin = typeof window !== "undefined" && window.location?.origin ? window.location.origin : "http://localhost";
|
|
44
|
+
if (isAbsoluteUrl) {
|
|
45
|
+
return new URL(url).pathname;
|
|
46
|
+
}
|
|
47
|
+
if (baseURL) {
|
|
48
|
+
const normalizedBase = baseURL.endsWith("/") ? baseURL : `${baseURL}/`;
|
|
49
|
+
const normalizedUrl = url.replace(/^\/+/, "");
|
|
50
|
+
return new URL(normalizedUrl, normalizedBase).pathname;
|
|
51
|
+
}
|
|
52
|
+
return new URL(url, browserOrigin).pathname;
|
|
53
|
+
} catch {
|
|
54
|
+
return url.split(/[?#]/)[0] || "";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
39
57
|
/**
|
|
40
58
|
* Check if mock is enabled
|
|
41
59
|
*/
|
|
@@ -54,14 +72,19 @@ var MockInterceptor = class {
|
|
|
54
72
|
* - "GET /api/v1/asset/xxx" (HTTP method + URL)
|
|
55
73
|
* - "/api/v1/asset/xxx/get.js" (File path format from automock plugin)
|
|
56
74
|
*/
|
|
57
|
-
findMock(url, method) {
|
|
75
|
+
findMock(url, method, baseURL) {
|
|
58
76
|
const methodUpper = method.toUpperCase();
|
|
59
77
|
const methodLower = method.toLowerCase();
|
|
78
|
+
const normalizedPath = this.normalizeUrlPath(url, baseURL);
|
|
60
79
|
const httpMethodKey = `${methodUpper} ${url}`;
|
|
61
80
|
if (this.options.mockData[httpMethodKey]) {
|
|
62
81
|
return this.options.mockData[httpMethodKey];
|
|
63
82
|
}
|
|
64
|
-
const
|
|
83
|
+
const normalizedHttpMethodKey = `${methodUpper} ${normalizedPath}`;
|
|
84
|
+
if (this.options.mockData[normalizedHttpMethodKey]) {
|
|
85
|
+
return this.options.mockData[normalizedHttpMethodKey];
|
|
86
|
+
}
|
|
87
|
+
const filePathKey = `${normalizedPath}/${methodLower}.js`;
|
|
65
88
|
if (this.options.mockData[filePathKey]) {
|
|
66
89
|
return this.options.mockData[filePathKey];
|
|
67
90
|
}
|
|
@@ -70,21 +93,21 @@ var MockInterceptor = class {
|
|
|
70
93
|
/**
|
|
71
94
|
* Determine if request should be mocked
|
|
72
95
|
*/
|
|
73
|
-
shouldMock(url, method) {
|
|
96
|
+
shouldMock(url, method, baseURL) {
|
|
74
97
|
if (!this.isEnabled()) {
|
|
75
98
|
return false;
|
|
76
99
|
}
|
|
77
|
-
const mock = this.findMock(url, method);
|
|
100
|
+
const mock = this.findMock(url, method, baseURL);
|
|
78
101
|
return mock !== null && mock.enable;
|
|
79
102
|
}
|
|
80
103
|
/**
|
|
81
104
|
* Get mock data for request
|
|
82
105
|
*/
|
|
83
|
-
getMock(url, method) {
|
|
84
|
-
if (!this.shouldMock(url, method)) {
|
|
106
|
+
getMock(url, method, baseURL) {
|
|
107
|
+
if (!this.shouldMock(url, method, baseURL)) {
|
|
85
108
|
return null;
|
|
86
109
|
}
|
|
87
|
-
return this.findMock(url, method);
|
|
110
|
+
return this.findMock(url, method, baseURL);
|
|
88
111
|
}
|
|
89
112
|
/**
|
|
90
113
|
* Setup axios interceptor
|
|
@@ -94,9 +117,10 @@ var MockInterceptor = class {
|
|
|
94
117
|
async (config) => {
|
|
95
118
|
const url = config.url || "";
|
|
96
119
|
const method = config.method?.toUpperCase() || "GET";
|
|
97
|
-
const
|
|
120
|
+
const normalizedUrl = this.normalizeUrlPath(url, config.baseURL);
|
|
121
|
+
const mock = this.getMock(url, method, config.baseURL);
|
|
98
122
|
if (mock) {
|
|
99
|
-
this.options.onMockHit?.(
|
|
123
|
+
this.options.onMockHit?.(normalizedUrl, method, mock);
|
|
100
124
|
config.adapter = async () => {
|
|
101
125
|
const { data, delay = 0, status = 200 } = mock;
|
|
102
126
|
if (delay > 0) {
|
|
@@ -112,7 +136,7 @@ var MockInterceptor = class {
|
|
|
112
136
|
};
|
|
113
137
|
} else {
|
|
114
138
|
const reason = !this.isEnabled() ? "Mock disabled globally" : "No matching mock found or mock disabled";
|
|
115
|
-
this.options.onBypass?.(
|
|
139
|
+
this.options.onBypass?.(normalizedUrl, method, reason);
|
|
116
140
|
}
|
|
117
141
|
return config;
|
|
118
142
|
},
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/index.ts","../../src/client/interceptor.ts"],"sourcesContent":["export {\n createMockInterceptor,\n initMockInterceptor,\n initMockInterceptorForPureHttp,\n setMockEnabled,\n isMockEnabled,\n loadMockData,\n registerHttpInstance\n} from './interceptor'\n\nexport type { MockInterceptorOptions, MockBundleData } from './interceptor'\n","import type {\n AxiosInstance,\n AxiosResponse,\n InternalAxiosRequestConfig,\n} from \"axios\";\n\ndeclare const __AUTOMOCK_ENABLED__: boolean;\n\nexport type MockBundleData = {\n enable: boolean;\n data: unknown;\n delay?: number;\n status?: number;\n isBinary?: boolean;\n};\n\nexport type MockInterceptorOptions = {\n mockData: Record<string, MockBundleData>;\n enabled?: boolean | (() => boolean);\n onMockHit?: (url: string, method: string, mock: MockBundleData) => void;\n onBypass?: (url: string, method: string, reason: string) => void;\n};\n\ntype MockEnabledState = boolean | undefined;\n\ndeclare global {\n interface Window {\n __MOCK_ENABLED__?: MockEnabledState;\n }\n}\n\nclass MockInterceptor {\n private options: MockInterceptorOptions;\n\n constructor(options: MockInterceptorOptions) {\n this.options = options;\n }\n\n /**\n * Check if mock is enabled\n */\n isEnabled(): boolean {\n // Check runtime flag first\n if (window.__MOCK_ENABLED__ !== undefined) {\n return window.__MOCK_ENABLED__;\n }\n // Check environment variable\n if (typeof this.options.enabled === \"function\") {\n return this.options.enabled();\n }\n return this.options.enabled ?? false;\n }\n\n /**\n * Find matching mock data for the request\n * Supports both formats:\n * - \"GET /api/v1/asset/xxx\" (HTTP method + URL)\n * - \"/api/v1/asset/xxx/get.js\" (File path format from automock plugin)\n */\n private findMock(url: string, method: string): MockBundleData | null {\n const methodUpper = method.toUpperCase();\n const methodLower = method.toLowerCase();\n\n // Try HTTP method + URL format first (for compatibility)\n const httpMethodKey = `${methodUpper} ${url}`;\n if (this.options.mockData[httpMethodKey]) {\n return this.options.mockData[httpMethodKey];\n }\n\n // Try file path format from automock plugin: /api/v1/asset/xxx/get.js\n const filePathKey = `${url}/${methodLower}.js`;\n if (this.options.mockData[filePathKey]) {\n return this.options.mockData[filePathKey];\n }\n\n return null;\n }\n\n /**\n * Determine if request should be mocked\n */\n shouldMock(url: string, method: string): boolean {\n if (!this.isEnabled()) {\n return false;\n }\n\n const mock = this.findMock(url, method);\n return mock !== null && mock.enable;\n }\n\n /**\n * Get mock data for request\n */\n getMock(url: string, method: string): MockBundleData | null {\n if (!this.shouldMock(url, method)) {\n return null;\n }\n return this.findMock(url, method);\n }\n\n /**\n * Setup axios interceptor\n */\n setupAxios(axiosInstance: AxiosInstance): void {\n axiosInstance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig) => {\n const url = config.url || \"\";\n const method = config.method?.toUpperCase() || \"GET\";\n\n const mock = this.getMock(url, method);\n\n if (mock) {\n // Trigger mock hit callback\n this.options.onMockHit?.(url, method, mock);\n\n // Set adapter to return mock data\n (config as InternalAxiosRequestConfig & { adapter: () => Promise<AxiosResponse> }).adapter = async () => {\n const { data, delay = 0, status = 200 } = mock;\n\n // Simulate delay\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n\n return {\n data,\n status,\n statusText: \"OK\",\n headers: {},\n config,\n };\n };\n } else {\n // Trigger bypass callback\n const reason = !this.isEnabled()\n ? \"Mock disabled globally\"\n : \"No matching mock found or mock disabled\";\n this.options.onBypass?.(url, method, reason);\n }\n\n return config;\n },\n (error: unknown) => Promise.reject(error),\n );\n }\n}\n\n/**\n * Create mock interceptor instance\n */\nexport function createMockInterceptor(\n options: MockInterceptorOptions,\n): MockInterceptor {\n return new MockInterceptor(options);\n}\n\n/**\n * Load mock data from bundled JSON file\n */\nexport async function loadMockData(): Promise<Record<string, MockBundleData>> {\n try {\n // In production, mock-data.json is generated by automock plugin\n // Use absolute path to load it from dist directory\n const response = await fetch(\"/mock-data.json\");\n if (!response.ok) {\n console.warn(\n \"[MockInterceptor] Failed to load mock-data.json:\",\n response.statusText,\n );\n return {};\n }\n const data = (await response.json()) as Record<string, MockBundleData>;\n return data;\n } catch (error) {\n console.warn(\"[MockInterceptor] Failed to load mock-data.json:\", error);\n return {};\n }\n}\n\nasync function createInterceptorFromBundle(): Promise<MockInterceptor> {\n const mockData = await loadMockData();\n const isEnabled = typeof __AUTOMOCK_ENABLED__ !== \"undefined\" && __AUTOMOCK_ENABLED__;\n\n return new MockInterceptor({\n mockData,\n enabled: isEnabled,\n onMockHit: (url: string, method: string) => {\n console.log(`[MOCK HIT] ${method} ${url}`);\n },\n onBypass: (url: string, method: string, reason: string) => {\n console.log(`[MOCK BYPASS] ${method} ${url} - ${reason}`);\n },\n });\n}\n\nexport async function initMockInterceptor(\n axiosInstance?: AxiosInstance,\n): Promise<void> {\n if (!axiosInstance) {\n throw new Error(\n \"[MockInterceptor] axiosInstance is required. Please provide an axios instance.\",\n );\n }\n\n const interceptor = await createInterceptorFromBundle();\n interceptor.setupAxios(axiosInstance);\n}\n\nexport function setMockEnabled(enabled: boolean): void {\n window.__MOCK_ENABLED__ = enabled;\n}\n\nexport function isMockEnabled(): boolean {\n return !!window.__MOCK_ENABLED__;\n}\n\ntype HttpInstance = {\n constructor: { axiosInstance: AxiosInstance };\n};\n\nlet httpInstanceRef: HttpInstance | undefined;\n\nexport function registerHttpInstance(http: HttpInstance): void {\n httpInstanceRef = http;\n}\n\nexport async function initMockInterceptorForPureHttp(): Promise<void> {\n if (!httpInstanceRef) {\n throw new Error(\n \"[MockInterceptor] http instance not registered. Call registerHttpInstance(http) first.\",\n );\n }\n\n const interceptor = await createInterceptorFromBundle();\n interceptor.setupAxios(httpInstanceRef.constructor.axiosInstance);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/index.ts","../../src/client/interceptor.ts"],"sourcesContent":["export {\n createMockInterceptor,\n initMockInterceptor,\n initMockInterceptorForPureHttp,\n setMockEnabled,\n isMockEnabled,\n loadMockData,\n registerHttpInstance\n} from './interceptor'\n\nexport type { MockInterceptorOptions, MockBundleData } from './interceptor'\n","import type {\n AxiosInstance,\n AxiosResponse,\n InternalAxiosRequestConfig,\n} from \"axios\";\n\ndeclare const __AUTOMOCK_ENABLED__: boolean;\n\nexport type MockBundleData = {\n enable: boolean;\n data: unknown;\n delay?: number;\n status?: number;\n isBinary?: boolean;\n};\n\nexport type MockInterceptorOptions = {\n mockData: Record<string, MockBundleData>;\n enabled?: boolean | (() => boolean);\n onMockHit?: (url: string, method: string, mock: MockBundleData) => void;\n onBypass?: (url: string, method: string, reason: string) => void;\n};\n\ntype MockEnabledState = boolean | undefined;\n\ndeclare global {\n interface Window {\n __MOCK_ENABLED__?: MockEnabledState;\n }\n}\n\nclass MockInterceptor {\n private options: MockInterceptorOptions;\n\n constructor(options: MockInterceptorOptions) {\n this.options = options;\n }\n\n private normalizeUrlPath(url: string, baseURL?: string): string {\n if (!url) return \"\";\n\n try {\n const isAbsoluteUrl = /^[a-z][a-z\\d+\\-.]*:\\/\\//i.test(url);\n const browserOrigin =\n typeof window !== \"undefined\" && window.location?.origin\n ? window.location.origin\n : \"http://localhost\";\n\n if (isAbsoluteUrl) {\n return new URL(url).pathname;\n }\n\n if (baseURL) {\n const normalizedBase = baseURL.endsWith(\"/\") ? baseURL : `${baseURL}/`;\n const normalizedUrl = url.replace(/^\\/+/, \"\");\n return new URL(normalizedUrl, normalizedBase).pathname;\n }\n\n return new URL(url, browserOrigin).pathname;\n } catch {\n return url.split(/[?#]/)[0] || \"\";\n }\n }\n\n /**\n * Check if mock is enabled\n */\n isEnabled(): boolean {\n // Check runtime flag first\n if (window.__MOCK_ENABLED__ !== undefined) {\n return window.__MOCK_ENABLED__;\n }\n // Check environment variable\n if (typeof this.options.enabled === \"function\") {\n return this.options.enabled();\n }\n return this.options.enabled ?? false;\n }\n\n /**\n * Find matching mock data for the request\n * Supports both formats:\n * - \"GET /api/v1/asset/xxx\" (HTTP method + URL)\n * - \"/api/v1/asset/xxx/get.js\" (File path format from automock plugin)\n */\n private findMock(url: string, method: string, baseURL?: string): MockBundleData | null {\n const methodUpper = method.toUpperCase();\n const methodLower = method.toLowerCase();\n const normalizedPath = this.normalizeUrlPath(url, baseURL);\n\n // Try HTTP method + URL format first (for compatibility)\n const httpMethodKey = `${methodUpper} ${url}`;\n if (this.options.mockData[httpMethodKey]) {\n return this.options.mockData[httpMethodKey];\n }\n\n const normalizedHttpMethodKey = `${methodUpper} ${normalizedPath}`;\n if (this.options.mockData[normalizedHttpMethodKey]) {\n return this.options.mockData[normalizedHttpMethodKey];\n }\n\n // Try file path format from automock plugin: /api/v1/asset/xxx/get.js\n const filePathKey = `${normalizedPath}/${methodLower}.js`;\n if (this.options.mockData[filePathKey]) {\n return this.options.mockData[filePathKey];\n }\n\n return null;\n }\n\n /**\n * Determine if request should be mocked\n */\n shouldMock(url: string, method: string, baseURL?: string): boolean {\n if (!this.isEnabled()) {\n return false;\n }\n\n const mock = this.findMock(url, method, baseURL);\n return mock !== null && mock.enable;\n }\n\n /**\n * Get mock data for request\n */\n getMock(url: string, method: string, baseURL?: string): MockBundleData | null {\n if (!this.shouldMock(url, method, baseURL)) {\n return null;\n }\n return this.findMock(url, method, baseURL);\n }\n\n /**\n * Setup axios interceptor\n */\n setupAxios(axiosInstance: AxiosInstance): void {\n axiosInstance.interceptors.request.use(\n async (config: InternalAxiosRequestConfig) => {\n const url = config.url || \"\";\n const method = config.method?.toUpperCase() || \"GET\";\n const normalizedUrl = this.normalizeUrlPath(url, config.baseURL);\n\n const mock = this.getMock(url, method, config.baseURL);\n\n if (mock) {\n // Trigger mock hit callback\n this.options.onMockHit?.(normalizedUrl, method, mock);\n\n // Set adapter to return mock data\n (config as InternalAxiosRequestConfig & { adapter: () => Promise<AxiosResponse> }).adapter = async () => {\n const { data, delay = 0, status = 200 } = mock;\n\n // Simulate delay\n if (delay > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n\n return {\n data,\n status,\n statusText: \"OK\",\n headers: {},\n config,\n };\n };\n } else {\n // Trigger bypass callback\n const reason = !this.isEnabled()\n ? \"Mock disabled globally\"\n : \"No matching mock found or mock disabled\";\n this.options.onBypass?.(normalizedUrl, method, reason);\n }\n\n return config;\n },\n (error: unknown) => Promise.reject(error),\n );\n }\n}\n\n/**\n * Create mock interceptor instance\n */\nexport function createMockInterceptor(\n options: MockInterceptorOptions,\n): MockInterceptor {\n return new MockInterceptor(options);\n}\n\n/**\n * Load mock data from bundled JSON file\n */\nexport async function loadMockData(): Promise<Record<string, MockBundleData>> {\n try {\n // In production, mock-data.json is generated by automock plugin\n // Use absolute path to load it from dist directory\n const response = await fetch(\"/mock-data.json\");\n if (!response.ok) {\n console.warn(\n \"[MockInterceptor] Failed to load mock-data.json:\",\n response.statusText,\n );\n return {};\n }\n const data = (await response.json()) as Record<string, MockBundleData>;\n return data;\n } catch (error) {\n console.warn(\"[MockInterceptor] Failed to load mock-data.json:\", error);\n return {};\n }\n}\n\nasync function createInterceptorFromBundle(): Promise<MockInterceptor> {\n const mockData = await loadMockData();\n const isEnabled = typeof __AUTOMOCK_ENABLED__ !== \"undefined\" && __AUTOMOCK_ENABLED__;\n\n return new MockInterceptor({\n mockData,\n enabled: isEnabled,\n onMockHit: (url: string, method: string) => {\n console.log(`[MOCK HIT] ${method} ${url}`);\n },\n onBypass: (url: string, method: string, reason: string) => {\n console.log(`[MOCK BYPASS] ${method} ${url} - ${reason}`);\n },\n });\n}\n\nexport async function initMockInterceptor(\n axiosInstance?: AxiosInstance,\n): Promise<void> {\n if (!axiosInstance) {\n throw new Error(\n \"[MockInterceptor] axiosInstance is required. Please provide an axios instance.\",\n );\n }\n\n const interceptor = await createInterceptorFromBundle();\n interceptor.setupAxios(axiosInstance);\n}\n\nexport function setMockEnabled(enabled: boolean): void {\n window.__MOCK_ENABLED__ = enabled;\n}\n\nexport function isMockEnabled(): boolean {\n return !!window.__MOCK_ENABLED__;\n}\n\ntype HttpInstance = {\n constructor: { axiosInstance: AxiosInstance };\n};\n\nlet httpInstanceRef: HttpInstance | undefined;\n\nexport function registerHttpInstance(http: HttpInstance): void {\n httpInstanceRef = http;\n}\n\nexport async function initMockInterceptorForPureHttp(): Promise<void> {\n if (!httpInstanceRef) {\n throw new Error(\n \"[MockInterceptor] http instance not registered. Call registerHttpInstance(http) first.\",\n );\n }\n\n const interceptor = await createInterceptorFromBundle();\n interceptor.setupAxios(httpInstanceRef.constructor.axiosInstance);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC+BA,IAAM,kBAAN,MAAsB;AAAA,EACZ;AAAA,EAER,YAAY,SAAiC;AAC3C,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,iBAAiB,KAAa,SAA0B;AAC9D,QAAI,CAAC,IAAK,QAAO;AAEjB,QAAI;AACF,YAAM,gBAAgB,2BAA2B,KAAK,GAAG;AACzD,YAAM,gBACJ,OAAO,WAAW,eAAe,OAAO,UAAU,SAC9C,OAAO,SAAS,SAChB;AAEN,UAAI,eAAe;AACjB,eAAO,IAAI,IAAI,GAAG,EAAE;AAAA,MACtB;AAEA,UAAI,SAAS;AACX,cAAM,iBAAiB,QAAQ,SAAS,GAAG,IAAI,UAAU,GAAG,OAAO;AACnE,cAAM,gBAAgB,IAAI,QAAQ,QAAQ,EAAE;AAC5C,eAAO,IAAI,IAAI,eAAe,cAAc,EAAE;AAAA,MAChD;AAEA,aAAO,IAAI,IAAI,KAAK,aAAa,EAAE;AAAA,IACrC,QAAQ;AACN,aAAO,IAAI,MAAM,MAAM,EAAE,CAAC,KAAK;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AAEnB,QAAI,OAAO,qBAAqB,QAAW;AACzC,aAAO,OAAO;AAAA,IAChB;AAEA,QAAI,OAAO,KAAK,QAAQ,YAAY,YAAY;AAC9C,aAAO,KAAK,QAAQ,QAAQ;AAAA,IAC9B;AACA,WAAO,KAAK,QAAQ,WAAW;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,SAAS,KAAa,QAAgB,SAAyC;AACrF,UAAM,cAAc,OAAO,YAAY;AACvC,UAAM,cAAc,OAAO,YAAY;AACvC,UAAM,iBAAiB,KAAK,iBAAiB,KAAK,OAAO;AAGzD,UAAM,gBAAgB,GAAG,WAAW,IAAI,GAAG;AAC3C,QAAI,KAAK,QAAQ,SAAS,aAAa,GAAG;AACxC,aAAO,KAAK,QAAQ,SAAS,aAAa;AAAA,IAC5C;AAEA,UAAM,0BAA0B,GAAG,WAAW,IAAI,cAAc;AAChE,QAAI,KAAK,QAAQ,SAAS,uBAAuB,GAAG;AAClD,aAAO,KAAK,QAAQ,SAAS,uBAAuB;AAAA,IACtD;AAGA,UAAM,cAAc,GAAG,cAAc,IAAI,WAAW;AACpD,QAAI,KAAK,QAAQ,SAAS,WAAW,GAAG;AACtC,aAAO,KAAK,QAAQ,SAAS,WAAW;AAAA,IAC1C;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,KAAa,QAAgB,SAA2B;AACjE,QAAI,CAAC,KAAK,UAAU,GAAG;AACrB,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,KAAK,SAAS,KAAK,QAAQ,OAAO;AAC/C,WAAO,SAAS,QAAQ,KAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,KAAa,QAAgB,SAAyC;AAC5E,QAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,OAAO,GAAG;AAC1C,aAAO;AAAA,IACT;AACA,WAAO,KAAK,SAAS,KAAK,QAAQ,OAAO;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,eAAoC;AAC7C,kBAAc,aAAa,QAAQ;AAAA,MACjC,OAAO,WAAuC;AAC5C,cAAM,MAAM,OAAO,OAAO;AAC1B,cAAM,SAAS,OAAO,QAAQ,YAAY,KAAK;AAC/C,cAAM,gBAAgB,KAAK,iBAAiB,KAAK,OAAO,OAAO;AAE/D,cAAM,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,OAAO;AAErD,YAAI,MAAM;AAER,eAAK,QAAQ,YAAY,eAAe,QAAQ,IAAI;AAGpD,UAAC,OAAkF,UAAU,YAAY;AACvG,kBAAM,EAAE,MAAM,QAAQ,GAAG,SAAS,IAAI,IAAI;AAG1C,gBAAI,QAAQ,GAAG;AACb,oBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAAA,YAC3D;AAEA,mBAAO;AAAA,cACL;AAAA,cACA;AAAA,cACA,YAAY;AAAA,cACZ,SAAS,CAAC;AAAA,cACV;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AAEL,gBAAM,SAAS,CAAC,KAAK,UAAU,IAC3B,2BACA;AACJ,eAAK,QAAQ,WAAW,eAAe,QAAQ,MAAM;AAAA,QACvD;AAEA,eAAO;AAAA,MACT;AAAA,MACA,CAAC,UAAmB,QAAQ,OAAO,KAAK;AAAA,IAC1C;AAAA,EACF;AACF;AAKO,SAAS,sBACd,SACiB;AACjB,SAAO,IAAI,gBAAgB,OAAO;AACpC;AAKA,eAAsB,eAAwD;AAC5E,MAAI;AAGF,UAAM,WAAW,MAAM,MAAM,iBAAiB;AAC9C,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ;AAAA,QACN;AAAA,QACA,SAAS;AAAA,MACX;AACA,aAAO,CAAC;AAAA,IACV;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,KAAK,oDAAoD,KAAK;AACtE,WAAO,CAAC;AAAA,EACV;AACF;AAEA,eAAe,8BAAwD;AACrE,QAAM,WAAW,MAAM,aAAa;AACpC,QAAM,YAAY,OAAO,yBAAyB,eAAe;AAEjE,SAAO,IAAI,gBAAgB;AAAA,IACzB;AAAA,IACA,SAAS;AAAA,IACT,WAAW,CAAC,KAAa,WAAmB;AAC1C,cAAQ,IAAI,cAAc,MAAM,IAAI,GAAG,EAAE;AAAA,IAC3C;AAAA,IACA,UAAU,CAAC,KAAa,QAAgB,WAAmB;AACzD,cAAQ,IAAI,iBAAiB,MAAM,IAAI,GAAG,MAAM,MAAM,EAAE;AAAA,IAC1D;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,oBACpB,eACe;AACf,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,4BAA4B;AACtD,cAAY,WAAW,aAAa;AACtC;AAEO,SAAS,eAAe,SAAwB;AACrD,SAAO,mBAAmB;AAC5B;AAEO,SAAS,gBAAyB;AACvC,SAAO,CAAC,CAAC,OAAO;AAClB;AAMA,IAAI;AAEG,SAAS,qBAAqB,MAA0B;AAC7D,oBAAkB;AACpB;AAEA,eAAsB,iCAAgD;AACpE,MAAI,CAAC,iBAAiB;AACpB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,4BAA4B;AACtD,cAAY,WAAW,gBAAgB,YAAY,aAAa;AAClE;","names":[]}
|
package/dist/client/index.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -7,17 +7,22 @@ interface InspectorOptions {
|
|
|
7
7
|
enableToggle?: boolean;
|
|
8
8
|
}
|
|
9
9
|
interface AutomockPluginOptions {
|
|
10
|
+
/** Directory for mock files, default "mock". */
|
|
10
11
|
mockDir?: string;
|
|
12
|
+
/** API path prefix handled by automock, default "/api". */
|
|
11
13
|
apiPrefix?: string;
|
|
14
|
+
/** Rewrite request path before proxying to proxyBaseUrl. */
|
|
12
15
|
pathRewrite?: (path: string) => string;
|
|
16
|
+
/** Real backend base URL. Required only when automock proxy/capture is used. */
|
|
13
17
|
proxyBaseUrl?: string;
|
|
14
18
|
inspector?: boolean | InspectorOptions;
|
|
19
|
+
/** Client-side production mock switch. Default false; "auto" enables outside production mode. */
|
|
15
20
|
productionMock?: boolean | 'auto';
|
|
16
|
-
/** Global switch, default true. When false, middleware passes through all requests. */
|
|
21
|
+
/** Global switch, default true. When false, middleware passes through all requests without proxy/capture. */
|
|
17
22
|
enabled?: boolean;
|
|
18
23
|
/** Whether to proxy unmatched requests to proxyBaseUrl, default true. */
|
|
19
24
|
proxy?: boolean;
|
|
20
|
-
/** Whether to capture and save
|
|
25
|
+
/** Whether to capture and save JSON proxy responses as mock files, default true. */
|
|
21
26
|
capture?: boolean;
|
|
22
27
|
}
|
|
23
28
|
|
package/dist/index.d.ts
CHANGED
|
@@ -7,17 +7,22 @@ interface InspectorOptions {
|
|
|
7
7
|
enableToggle?: boolean;
|
|
8
8
|
}
|
|
9
9
|
interface AutomockPluginOptions {
|
|
10
|
+
/** Directory for mock files, default "mock". */
|
|
10
11
|
mockDir?: string;
|
|
12
|
+
/** API path prefix handled by automock, default "/api". */
|
|
11
13
|
apiPrefix?: string;
|
|
14
|
+
/** Rewrite request path before proxying to proxyBaseUrl. */
|
|
12
15
|
pathRewrite?: (path: string) => string;
|
|
16
|
+
/** Real backend base URL. Required only when automock proxy/capture is used. */
|
|
13
17
|
proxyBaseUrl?: string;
|
|
14
18
|
inspector?: boolean | InspectorOptions;
|
|
19
|
+
/** Client-side production mock switch. Default false; "auto" enables outside production mode. */
|
|
15
20
|
productionMock?: boolean | 'auto';
|
|
16
|
-
/** Global switch, default true. When false, middleware passes through all requests. */
|
|
21
|
+
/** Global switch, default true. When false, middleware passes through all requests without proxy/capture. */
|
|
17
22
|
enabled?: boolean;
|
|
18
23
|
/** Whether to proxy unmatched requests to proxyBaseUrl, default true. */
|
|
19
24
|
proxy?: boolean;
|
|
20
|
-
/** Whether to capture and save
|
|
25
|
+
/** Whether to capture and save JSON proxy responses as mock files, default true. */
|
|
21
26
|
capture?: boolean;
|
|
22
27
|
}
|
|
23
28
|
|
package/dist/index.js
CHANGED
|
@@ -759,6 +759,11 @@ function serveMockResponse(res, mockFilePath, mockResult) {
|
|
|
759
759
|
}
|
|
760
760
|
}, delay);
|
|
761
761
|
}
|
|
762
|
+
function matchesApiPrefix(pathname, apiPrefix) {
|
|
763
|
+
if (!apiPrefix || apiPrefix === "/") return true;
|
|
764
|
+
const normalizedPrefix = apiPrefix.endsWith("/") && apiPrefix !== "/" ? apiPrefix.slice(0, -1) : apiPrefix;
|
|
765
|
+
return pathname === normalizedPrefix || pathname.startsWith(`${normalizedPrefix}/`);
|
|
766
|
+
}
|
|
762
767
|
function proxyAndCapture(req, res, options) {
|
|
763
768
|
const { proxyBaseUrl, pathRewrite, shouldSave, method, pathname, mockDir, onMockSaved } = options;
|
|
764
769
|
const targetUrl = proxyBaseUrl + pathRewrite(req.url || "");
|
|
@@ -934,7 +939,8 @@ function automock(options) {
|
|
|
934
939
|
const absolutePath = resolveAbsolutePath(mockFilePath);
|
|
935
940
|
if (!import_fs_extra3.default.existsSync(absolutePath)) return null;
|
|
936
941
|
const { default: mockModule } = await import(`${absolutePath}?t=${Date.now()}`);
|
|
937
|
-
const
|
|
942
|
+
const exportedConfig = typeof mockModule === "function" ? await mockModule() : mockModule;
|
|
943
|
+
const mockResult = typeof exportedConfig?.data === "function" ? { ...exportedConfig, data: await exportedConfig.data() } : exportedConfig;
|
|
938
944
|
const { enable = true } = mockResult || {};
|
|
939
945
|
return enable ? { absolutePath, mockResult } : null;
|
|
940
946
|
}
|
|
@@ -945,7 +951,11 @@ function automock(options) {
|
|
|
945
951
|
const handled = await inspectorHandler(req, res);
|
|
946
952
|
if (handled) return;
|
|
947
953
|
}
|
|
948
|
-
if (!req.url
|
|
954
|
+
if (!req.url) {
|
|
955
|
+
return next();
|
|
956
|
+
}
|
|
957
|
+
const pathname = new URL(req.url, "http://localhost").pathname;
|
|
958
|
+
if (!matchesApiPrefix(pathname, apiPrefix)) {
|
|
949
959
|
return next();
|
|
950
960
|
}
|
|
951
961
|
const accept = req.headers.accept || "";
|
|
@@ -954,7 +964,6 @@ function automock(options) {
|
|
|
954
964
|
return next();
|
|
955
965
|
}
|
|
956
966
|
const method = (req.method || "GET").toLowerCase();
|
|
957
|
-
const pathname = new URL(req.url, "http://localhost").pathname;
|
|
958
967
|
const key = `${pathname}/${method}.js`.toLowerCase();
|
|
959
968
|
try {
|
|
960
969
|
const mock = await tryLoadMock(key);
|
|
@@ -1061,6 +1070,24 @@ var MockInterceptor = class {
|
|
|
1061
1070
|
constructor(options) {
|
|
1062
1071
|
this.options = options;
|
|
1063
1072
|
}
|
|
1073
|
+
normalizeUrlPath(url, baseURL) {
|
|
1074
|
+
if (!url) return "";
|
|
1075
|
+
try {
|
|
1076
|
+
const isAbsoluteUrl = /^[a-z][a-z\d+\-.]*:\/\//i.test(url);
|
|
1077
|
+
const browserOrigin = typeof window !== "undefined" && window.location?.origin ? window.location.origin : "http://localhost";
|
|
1078
|
+
if (isAbsoluteUrl) {
|
|
1079
|
+
return new URL(url).pathname;
|
|
1080
|
+
}
|
|
1081
|
+
if (baseURL) {
|
|
1082
|
+
const normalizedBase = baseURL.endsWith("/") ? baseURL : `${baseURL}/`;
|
|
1083
|
+
const normalizedUrl = url.replace(/^\/+/, "");
|
|
1084
|
+
return new URL(normalizedUrl, normalizedBase).pathname;
|
|
1085
|
+
}
|
|
1086
|
+
return new URL(url, browserOrigin).pathname;
|
|
1087
|
+
} catch {
|
|
1088
|
+
return url.split(/[?#]/)[0] || "";
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1064
1091
|
/**
|
|
1065
1092
|
* Check if mock is enabled
|
|
1066
1093
|
*/
|
|
@@ -1079,14 +1106,19 @@ var MockInterceptor = class {
|
|
|
1079
1106
|
* - "GET /api/v1/asset/xxx" (HTTP method + URL)
|
|
1080
1107
|
* - "/api/v1/asset/xxx/get.js" (File path format from automock plugin)
|
|
1081
1108
|
*/
|
|
1082
|
-
findMock(url, method) {
|
|
1109
|
+
findMock(url, method, baseURL) {
|
|
1083
1110
|
const methodUpper = method.toUpperCase();
|
|
1084
1111
|
const methodLower = method.toLowerCase();
|
|
1112
|
+
const normalizedPath = this.normalizeUrlPath(url, baseURL);
|
|
1085
1113
|
const httpMethodKey = `${methodUpper} ${url}`;
|
|
1086
1114
|
if (this.options.mockData[httpMethodKey]) {
|
|
1087
1115
|
return this.options.mockData[httpMethodKey];
|
|
1088
1116
|
}
|
|
1089
|
-
const
|
|
1117
|
+
const normalizedHttpMethodKey = `${methodUpper} ${normalizedPath}`;
|
|
1118
|
+
if (this.options.mockData[normalizedHttpMethodKey]) {
|
|
1119
|
+
return this.options.mockData[normalizedHttpMethodKey];
|
|
1120
|
+
}
|
|
1121
|
+
const filePathKey = `${normalizedPath}/${methodLower}.js`;
|
|
1090
1122
|
if (this.options.mockData[filePathKey]) {
|
|
1091
1123
|
return this.options.mockData[filePathKey];
|
|
1092
1124
|
}
|
|
@@ -1095,21 +1127,21 @@ var MockInterceptor = class {
|
|
|
1095
1127
|
/**
|
|
1096
1128
|
* Determine if request should be mocked
|
|
1097
1129
|
*/
|
|
1098
|
-
shouldMock(url, method) {
|
|
1130
|
+
shouldMock(url, method, baseURL) {
|
|
1099
1131
|
if (!this.isEnabled()) {
|
|
1100
1132
|
return false;
|
|
1101
1133
|
}
|
|
1102
|
-
const mock = this.findMock(url, method);
|
|
1134
|
+
const mock = this.findMock(url, method, baseURL);
|
|
1103
1135
|
return mock !== null && mock.enable;
|
|
1104
1136
|
}
|
|
1105
1137
|
/**
|
|
1106
1138
|
* Get mock data for request
|
|
1107
1139
|
*/
|
|
1108
|
-
getMock(url, method) {
|
|
1109
|
-
if (!this.shouldMock(url, method)) {
|
|
1140
|
+
getMock(url, method, baseURL) {
|
|
1141
|
+
if (!this.shouldMock(url, method, baseURL)) {
|
|
1110
1142
|
return null;
|
|
1111
1143
|
}
|
|
1112
|
-
return this.findMock(url, method);
|
|
1144
|
+
return this.findMock(url, method, baseURL);
|
|
1113
1145
|
}
|
|
1114
1146
|
/**
|
|
1115
1147
|
* Setup axios interceptor
|
|
@@ -1119,9 +1151,10 @@ var MockInterceptor = class {
|
|
|
1119
1151
|
async (config) => {
|
|
1120
1152
|
const url = config.url || "";
|
|
1121
1153
|
const method = config.method?.toUpperCase() || "GET";
|
|
1122
|
-
const
|
|
1154
|
+
const normalizedUrl = this.normalizeUrlPath(url, config.baseURL);
|
|
1155
|
+
const mock = this.getMock(url, method, config.baseURL);
|
|
1123
1156
|
if (mock) {
|
|
1124
|
-
this.options.onMockHit?.(
|
|
1157
|
+
this.options.onMockHit?.(normalizedUrl, method, mock);
|
|
1125
1158
|
config.adapter = async () => {
|
|
1126
1159
|
const { data, delay = 0, status = 200 } = mock;
|
|
1127
1160
|
if (delay > 0) {
|
|
@@ -1137,7 +1170,7 @@ var MockInterceptor = class {
|
|
|
1137
1170
|
};
|
|
1138
1171
|
} else {
|
|
1139
1172
|
const reason = !this.isEnabled() ? "Mock disabled globally" : "No matching mock found or mock disabled";
|
|
1140
|
-
this.options.onBypass?.(
|
|
1173
|
+
this.options.onBypass?.(normalizedUrl, method, reason);
|
|
1141
1174
|
}
|
|
1142
1175
|
return config;
|
|
1143
1176
|
},
|
|
@@ -1209,6 +1242,11 @@ async function initMockInterceptorForPureHttp() {
|
|
|
1209
1242
|
}
|
|
1210
1243
|
|
|
1211
1244
|
// src/index.ts
|
|
1245
|
+
function resolveProductionMockEnabled(productionMock, mode = process.env.NODE_ENV) {
|
|
1246
|
+
if (productionMock === true) return true;
|
|
1247
|
+
if (productionMock === "auto") return mode !== "production";
|
|
1248
|
+
return false;
|
|
1249
|
+
}
|
|
1212
1250
|
function automock2(options = {}) {
|
|
1213
1251
|
const {
|
|
1214
1252
|
bundleMockData = true,
|
|
@@ -1217,8 +1255,10 @@ function automock2(options = {}) {
|
|
|
1217
1255
|
} = options;
|
|
1218
1256
|
const basePlugin = automock(pluginOptions);
|
|
1219
1257
|
let cachedBundle = null;
|
|
1258
|
+
let productionMockEnabled = resolveProductionMockEnabled(pluginOptions.productionMock);
|
|
1259
|
+
const resolveBundleOutputPath = () => import_path6.default.isAbsolute(bundleOutputPath) ? bundleOutputPath : import_path6.default.join(process.cwd(), bundleOutputPath);
|
|
1220
1260
|
const ensureBundleExists = () => {
|
|
1221
|
-
const outputPath =
|
|
1261
|
+
const outputPath = resolveBundleOutputPath();
|
|
1222
1262
|
if (!import_fs_extra5.default.existsSync(outputPath) && cachedBundle) {
|
|
1223
1263
|
console.log("[automock] Re-writing mock bundle...");
|
|
1224
1264
|
writeMockBundle(cachedBundle, outputPath);
|
|
@@ -1227,16 +1267,22 @@ function automock2(options = {}) {
|
|
|
1227
1267
|
return {
|
|
1228
1268
|
...basePlugin,
|
|
1229
1269
|
name: "vite-plugin-automock-with-bundle",
|
|
1230
|
-
config() {
|
|
1231
|
-
|
|
1270
|
+
config(userConfig, env) {
|
|
1271
|
+
if (typeof basePlugin.config === "function") {
|
|
1272
|
+
basePlugin.config.call(this, userConfig, env);
|
|
1273
|
+
}
|
|
1274
|
+
productionMockEnabled = resolveProductionMockEnabled(
|
|
1275
|
+
pluginOptions.productionMock,
|
|
1276
|
+
env.mode
|
|
1277
|
+
);
|
|
1232
1278
|
return {
|
|
1233
1279
|
define: {
|
|
1234
|
-
__AUTOMOCK_ENABLED__: JSON.stringify(
|
|
1280
|
+
__AUTOMOCK_ENABLED__: JSON.stringify(productionMockEnabled)
|
|
1235
1281
|
}
|
|
1236
1282
|
};
|
|
1237
1283
|
},
|
|
1238
1284
|
buildEnd: async () => {
|
|
1239
|
-
if (bundleMockData &&
|
|
1285
|
+
if (bundleMockData && productionMockEnabled) {
|
|
1240
1286
|
try {
|
|
1241
1287
|
const mockDir = pluginOptions.mockDir || import_path6.default.join(process.cwd(), "mock");
|
|
1242
1288
|
if (!import_fs_extra5.default.existsSync(mockDir)) {
|
|
@@ -1250,7 +1296,7 @@ function automock2(options = {}) {
|
|
|
1250
1296
|
return;
|
|
1251
1297
|
}
|
|
1252
1298
|
cachedBundle = await bundleMockFiles({ mockDir });
|
|
1253
|
-
const outputPath =
|
|
1299
|
+
const outputPath = resolveBundleOutputPath();
|
|
1254
1300
|
writeMockBundle(cachedBundle, outputPath);
|
|
1255
1301
|
console.log(`[automock] Mock bundle written to: ${outputPath}`);
|
|
1256
1302
|
} catch (error) {
|