vite-plugin-ai-mock-generator 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +117 -91
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +63 -67
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.d.mts
CHANGED
|
@@ -186,9 +186,7 @@ declare class MockStorage {
|
|
|
186
186
|
*/
|
|
187
187
|
|
|
188
188
|
declare class MockDataGenerator {
|
|
189
|
-
private
|
|
190
|
-
private apiUrl;
|
|
191
|
-
private model;
|
|
189
|
+
private llm;
|
|
192
190
|
constructor(options: {
|
|
193
191
|
apiKey: string;
|
|
194
192
|
apiUrl: string;
|
|
@@ -269,4 +267,4 @@ declare class MockServer {
|
|
|
269
267
|
|
|
270
268
|
declare function vitePluginAIMockGenerator(options?: MockGeneratorOptions): Plugin;
|
|
271
269
|
|
|
272
|
-
export { type EndpointConfig, MockDataGenerator, type MockGeneratorOptions, MockServer, MockStorage, vitePluginAIMockGenerator };
|
|
270
|
+
export { type EndpointConfig, MockDataGenerator, type MockGeneratorOptions, MockServer, MockStorage, vitePluginAIMockGenerator as default, vitePluginAIMockGenerator };
|
package/dist/index.d.ts
CHANGED
|
@@ -186,9 +186,7 @@ declare class MockStorage {
|
|
|
186
186
|
*/
|
|
187
187
|
|
|
188
188
|
declare class MockDataGenerator {
|
|
189
|
-
private
|
|
190
|
-
private apiUrl;
|
|
191
|
-
private model;
|
|
189
|
+
private llm;
|
|
192
190
|
constructor(options: {
|
|
193
191
|
apiKey: string;
|
|
194
192
|
apiUrl: string;
|
|
@@ -269,4 +267,4 @@ declare class MockServer {
|
|
|
269
267
|
|
|
270
268
|
declare function vitePluginAIMockGenerator(options?: MockGeneratorOptions): Plugin;
|
|
271
269
|
|
|
272
|
-
export { type EndpointConfig, MockDataGenerator, type MockGeneratorOptions, MockServer, MockStorage, vitePluginAIMockGenerator };
|
|
270
|
+
export { type EndpointConfig, MockDataGenerator, type MockGeneratorOptions, MockServer, MockStorage, vitePluginAIMockGenerator as default, vitePluginAIMockGenerator };
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
7
29
|
|
|
8
|
-
|
|
9
|
-
var
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
MockDataGenerator: () => MockDataGenerator,
|
|
34
|
+
MockServer: () => MockServer,
|
|
35
|
+
MockStorage: () => MockStorage,
|
|
36
|
+
default: () => index_default,
|
|
37
|
+
vitePluginAIMockGenerator: () => vitePluginAIMockGenerator
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(index_exports);
|
|
10
40
|
|
|
11
41
|
// src/storage.ts
|
|
42
|
+
var import_fs = __toESM(require("fs"));
|
|
43
|
+
var import_path = __toESM(require("path"));
|
|
12
44
|
var MockStorage = class {
|
|
13
45
|
constructor(options = {}) {
|
|
14
46
|
this.storageDir = options.dir || "mock-data";
|
|
15
47
|
this.persist = options.persist !== false;
|
|
16
48
|
this.cache = /* @__PURE__ */ new Map();
|
|
17
|
-
if (this.persist && !
|
|
18
|
-
|
|
49
|
+
if (this.persist && !import_fs.default.existsSync(this.storageDir)) {
|
|
50
|
+
import_fs.default.mkdirSync(this.storageDir, { recursive: true });
|
|
19
51
|
}
|
|
20
52
|
this.load();
|
|
21
53
|
}
|
|
@@ -70,9 +102,9 @@ var MockStorage = class {
|
|
|
70
102
|
this.cache.delete(key);
|
|
71
103
|
if (this.persist) {
|
|
72
104
|
const fileName = this.getFileName(endpoint, method);
|
|
73
|
-
const filePath =
|
|
74
|
-
if (
|
|
75
|
-
|
|
105
|
+
const filePath = import_path.default.join(this.storageDir, fileName);
|
|
106
|
+
if (import_fs.default.existsSync(filePath)) {
|
|
107
|
+
import_fs.default.unlinkSync(filePath);
|
|
76
108
|
}
|
|
77
109
|
}
|
|
78
110
|
}
|
|
@@ -81,10 +113,10 @@ var MockStorage = class {
|
|
|
81
113
|
*/
|
|
82
114
|
clear() {
|
|
83
115
|
this.cache.clear();
|
|
84
|
-
if (this.persist &&
|
|
85
|
-
const files =
|
|
116
|
+
if (this.persist && import_fs.default.existsSync(this.storageDir)) {
|
|
117
|
+
const files = import_fs.default.readdirSync(this.storageDir);
|
|
86
118
|
for (const file of files) {
|
|
87
|
-
|
|
119
|
+
import_fs.default.unlinkSync(import_path.default.join(this.storageDir, file));
|
|
88
120
|
}
|
|
89
121
|
}
|
|
90
122
|
}
|
|
@@ -99,22 +131,22 @@ var MockStorage = class {
|
|
|
99
131
|
*/
|
|
100
132
|
save(endpoint, method, store) {
|
|
101
133
|
const fileName = this.getFileName(endpoint, method);
|
|
102
|
-
const filePath =
|
|
103
|
-
|
|
134
|
+
const filePath = import_path.default.join(this.storageDir, fileName);
|
|
135
|
+
import_fs.default.writeFileSync(filePath, JSON.stringify(store, null, 2), "utf-8");
|
|
104
136
|
}
|
|
105
137
|
/**
|
|
106
138
|
* 从文件加载
|
|
107
139
|
*/
|
|
108
140
|
load() {
|
|
109
|
-
if (!this.persist || !
|
|
141
|
+
if (!this.persist || !import_fs.default.existsSync(this.storageDir)) {
|
|
110
142
|
return;
|
|
111
143
|
}
|
|
112
|
-
const files =
|
|
144
|
+
const files = import_fs.default.readdirSync(this.storageDir);
|
|
113
145
|
for (const file of files) {
|
|
114
146
|
if (!file.endsWith(".json")) continue;
|
|
115
147
|
try {
|
|
116
|
-
const filePath =
|
|
117
|
-
const content =
|
|
148
|
+
const filePath = import_path.default.join(this.storageDir, file);
|
|
149
|
+
const content = import_fs.default.readFileSync(filePath, "utf-8");
|
|
118
150
|
const store = JSON.parse(content);
|
|
119
151
|
const key = this.getKey(store.endpoint, store.method);
|
|
120
152
|
this.cache.set(key, store);
|
|
@@ -128,13 +160,13 @@ var MockStorage = class {
|
|
|
128
160
|
*/
|
|
129
161
|
export(outputPath) {
|
|
130
162
|
const allData = this.getAll();
|
|
131
|
-
|
|
163
|
+
import_fs.default.writeFileSync(outputPath, JSON.stringify(allData, null, 2), "utf-8");
|
|
132
164
|
}
|
|
133
165
|
/**
|
|
134
166
|
* 导入数据
|
|
135
167
|
*/
|
|
136
168
|
import(inputPath) {
|
|
137
|
-
const content =
|
|
169
|
+
const content = import_fs.default.readFileSync(inputPath, "utf-8");
|
|
138
170
|
const allData = JSON.parse(content);
|
|
139
171
|
for (const store of allData) {
|
|
140
172
|
const key = this.getKey(store.endpoint, store.method);
|
|
@@ -147,11 +179,19 @@ var MockStorage = class {
|
|
|
147
179
|
};
|
|
148
180
|
|
|
149
181
|
// src/generator.ts
|
|
182
|
+
var import_openai = require("@langchain/openai");
|
|
183
|
+
var import_messages = require("@langchain/core/messages");
|
|
150
184
|
var MockDataGenerator = class {
|
|
151
185
|
constructor(options) {
|
|
152
|
-
this.
|
|
153
|
-
|
|
154
|
-
|
|
186
|
+
this.llm = new import_openai.ChatOpenAI({
|
|
187
|
+
openAIApiKey: options.apiKey,
|
|
188
|
+
configuration: {
|
|
189
|
+
baseURL: options.apiUrl
|
|
190
|
+
},
|
|
191
|
+
modelName: options.model,
|
|
192
|
+
temperature: 0.7,
|
|
193
|
+
maxTokens: 4e3
|
|
194
|
+
});
|
|
155
195
|
}
|
|
156
196
|
/**
|
|
157
197
|
* 生成 Mock 数据
|
|
@@ -168,34 +208,34 @@ var MockDataGenerator = class {
|
|
|
168
208
|
buildPrompt(type, count, locale, quality) {
|
|
169
209
|
const properties = type.properties.map((p) => this.formatProperty(p)).join("\n");
|
|
170
210
|
return `
|
|
171
|
-
|
|
211
|
+
你是一个专业的 Mock 数据生成器。请根据以下类型定义生成真实、合理的测试数据。
|
|
172
212
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
213
|
+
类型名称: ${type.name}
|
|
214
|
+
数据语言: ${locale === "zh-CN" ? "中文" : "英文"}
|
|
215
|
+
数据数量: ${count}
|
|
216
|
+
质量要求: ${quality === "high" ? "高质量(真实业务数据)" : quality === "fast" ? "快速生成" : "平衡质量和速度"}
|
|
177
217
|
|
|
178
|
-
|
|
218
|
+
类型定义:
|
|
179
219
|
${properties}
|
|
180
220
|
|
|
181
|
-
|
|
182
|
-
1.
|
|
183
|
-
2.
|
|
184
|
-
3.
|
|
185
|
-
4.
|
|
186
|
-
5.
|
|
187
|
-
6.
|
|
221
|
+
要求:
|
|
222
|
+
1. 生成 ${count} 条数据
|
|
223
|
+
2. 数据要符合业务逻辑和真实场景
|
|
224
|
+
3. 字段值要合理(如价格不能为负数,年龄在合理范围)
|
|
225
|
+
4. 日期格式使用 ISO 8601
|
|
226
|
+
5. 返回 JSON 数组格式,不要包含任何其他文字
|
|
227
|
+
6. 理解字段语义,生成真实数据(如 userName 生成真实姓名)
|
|
188
228
|
|
|
189
|
-
|
|
229
|
+
示例格式:
|
|
190
230
|
[
|
|
191
231
|
{
|
|
192
232
|
"id": 1,
|
|
193
|
-
"name": "
|
|
233
|
+
"name": "张三",
|
|
194
234
|
...
|
|
195
235
|
}
|
|
196
236
|
]
|
|
197
237
|
|
|
198
|
-
|
|
238
|
+
请生成数据:
|
|
199
239
|
`.trim();
|
|
200
240
|
}
|
|
201
241
|
/**
|
|
@@ -231,30 +271,16 @@ ${properties}
|
|
|
231
271
|
*/
|
|
232
272
|
async callAI(prompt) {
|
|
233
273
|
try {
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
messages: [
|
|
243
|
-
{
|
|
244
|
-
role: "user",
|
|
245
|
-
content: prompt
|
|
246
|
-
}
|
|
247
|
-
],
|
|
248
|
-
temperature: 0.7
|
|
249
|
-
})
|
|
250
|
-
});
|
|
251
|
-
if (!response.ok) {
|
|
252
|
-
throw new Error(`AI API error: ${response.statusText}`);
|
|
253
|
-
}
|
|
254
|
-
const data = await response.json();
|
|
255
|
-
return data.choices[0].message.content;
|
|
274
|
+
const messages = [
|
|
275
|
+
new import_messages.SystemMessage(
|
|
276
|
+
"你是一个专业的 Mock 数据生成器,擅长生成真实、合理的测试数据。"
|
|
277
|
+
),
|
|
278
|
+
new import_messages.HumanMessage(prompt)
|
|
279
|
+
];
|
|
280
|
+
const response = await this.llm.invoke(messages);
|
|
281
|
+
return response.content;
|
|
256
282
|
} catch (error) {
|
|
257
|
-
console.error("
|
|
283
|
+
console.error("❌ AI API 调用失败:", error.message);
|
|
258
284
|
throw error;
|
|
259
285
|
}
|
|
260
286
|
}
|
|
@@ -274,8 +300,8 @@ ${properties}
|
|
|
274
300
|
const data = JSON.parse(jsonMatch[0]);
|
|
275
301
|
return isArray ? data : data[0];
|
|
276
302
|
} catch (error) {
|
|
277
|
-
console.error("
|
|
278
|
-
console.error("
|
|
303
|
+
console.error("❌ 解析 AI 响应失败:", error.message);
|
|
304
|
+
console.error("响应内容:", response);
|
|
279
305
|
throw error;
|
|
280
306
|
}
|
|
281
307
|
}
|
|
@@ -433,7 +459,7 @@ var MockServer = class {
|
|
|
433
459
|
res.statusCode = 200;
|
|
434
460
|
res.end(JSON.stringify(data));
|
|
435
461
|
if (this.options.output?.logs) {
|
|
436
|
-
console.log(`[Mock] ${method} ${url}
|
|
462
|
+
console.log(`[Mock] ${method} ${url} → ${data ? "OK" : "Empty"}`);
|
|
437
463
|
}
|
|
438
464
|
} catch (error) {
|
|
439
465
|
console.error(`[Mock] Error handling ${method} ${url}:`, error);
|
|
@@ -446,8 +472,8 @@ var MockServer = class {
|
|
|
446
472
|
);
|
|
447
473
|
}
|
|
448
474
|
});
|
|
449
|
-
console.log("\n
|
|
450
|
-
console.log(
|
|
475
|
+
console.log("\n🎭 Mock 服务器已启动");
|
|
476
|
+
console.log(`📍 已注册 ${this.endpoints.length} 个端点
|
|
451
477
|
`);
|
|
452
478
|
}
|
|
453
479
|
/**
|
|
@@ -575,34 +601,32 @@ function vitePluginAIMockGenerator(options = {}) {
|
|
|
575
601
|
enforce: "pre",
|
|
576
602
|
configResolved(config) {
|
|
577
603
|
if (output.console) {
|
|
578
|
-
console.log("\n
|
|
579
|
-
console.log(
|
|
580
|
-
console.log(
|
|
581
|
-
console.log(
|
|
582
|
-
console.log(
|
|
583
|
-
console.log(
|
|
584
|
-
`\u{1F4CD} \u7AEF\u70B9\u6570\u91CF: ${options.endpoints?.length || 0}`
|
|
585
|
-
);
|
|
604
|
+
console.log("\n🤖 AI Mock Generator 已启动");
|
|
605
|
+
console.log(`📂 存储目录: ${storageOptions.dir}`);
|
|
606
|
+
console.log(`🌍 数据语言: ${generation.locale}`);
|
|
607
|
+
console.log(`📊 默认数量: ${generation.count}`);
|
|
608
|
+
console.log(`🔑 API Key: ${apiKey ? "已配置" : "未配置"}`);
|
|
609
|
+
console.log(`📍 端点数量: ${options.endpoints?.length || 0}`);
|
|
586
610
|
}
|
|
587
611
|
},
|
|
588
612
|
async buildStart() {
|
|
589
613
|
if (autoGenerate && options.endpoints) {
|
|
590
614
|
if (output.console) {
|
|
591
|
-
console.log("\n
|
|
615
|
+
console.log("\n🔄 开始自动生成 Mock 数据...\n");
|
|
592
616
|
}
|
|
593
617
|
for (const endpoint of options.endpoints) {
|
|
594
618
|
const existingData = storage.get(endpoint.path, endpoint.method);
|
|
595
619
|
if (existingData) {
|
|
596
620
|
if (output.console) {
|
|
597
621
|
console.log(
|
|
598
|
-
|
|
622
|
+
`⏭️ 跳过 ${endpoint.method} ${endpoint.path} (已有数据)`
|
|
599
623
|
);
|
|
600
624
|
}
|
|
601
625
|
continue;
|
|
602
626
|
}
|
|
603
627
|
try {
|
|
604
628
|
if (output.console) {
|
|
605
|
-
console.log(
|
|
629
|
+
console.log(`🎲 生成 ${endpoint.method} ${endpoint.path}...`);
|
|
606
630
|
}
|
|
607
631
|
const typeDefinition = parseTypeDefinition(endpoint.response);
|
|
608
632
|
const count = endpoint.count || generation.count || 20;
|
|
@@ -622,18 +646,18 @@ function vitePluginAIMockGenerator(options = {}) {
|
|
|
622
646
|
});
|
|
623
647
|
if (output.console) {
|
|
624
648
|
console.log(
|
|
625
|
-
|
|
649
|
+
`✅ 已生成 ${count} 条数据: ${endpoint.method} ${endpoint.path}`
|
|
626
650
|
);
|
|
627
651
|
}
|
|
628
652
|
} catch (error) {
|
|
629
653
|
console.error(
|
|
630
|
-
|
|
654
|
+
`❌ 生成失败 ${endpoint.method} ${endpoint.path}:`,
|
|
631
655
|
error.message
|
|
632
656
|
);
|
|
633
657
|
}
|
|
634
658
|
}
|
|
635
659
|
if (output.console) {
|
|
636
|
-
console.log("\n
|
|
660
|
+
console.log("\n✨ Mock 数据生成完成\n");
|
|
637
661
|
}
|
|
638
662
|
}
|
|
639
663
|
},
|
|
@@ -654,10 +678,12 @@ function parseTypeDefinition(typeStr) {
|
|
|
654
678
|
isArray
|
|
655
679
|
};
|
|
656
680
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
exports
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
681
|
+
var index_default = vitePluginAIMockGenerator;
|
|
682
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
683
|
+
0 && (module.exports = {
|
|
684
|
+
MockDataGenerator,
|
|
685
|
+
MockServer,
|
|
686
|
+
MockStorage,
|
|
687
|
+
vitePluginAIMockGenerator
|
|
688
|
+
});
|
|
663
689
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storage.ts","../src/generator.ts","../src/utils.ts","../src/server.ts","../src/index.ts"],"names":["fs","path"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * AI Mock Generator - 数据存储\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type { MockDataStore, HttpMethod } from './types';\r\n\r\nexport class MockStorage {\r\n private storageDir: string;\r\n private cache: Map<string, MockDataStore>;\r\n private persist: boolean;\r\n\r\n constructor(options: { dir?: string; persist?: boolean } = {}) {\r\n this.storageDir = options.dir || 'mock-data';\r\n this.persist = options.persist !== false;\r\n this.cache = new Map();\r\n\r\n // 确保存储目录存在\r\n if (this.persist && !fs.existsSync(this.storageDir)) {\r\n fs.mkdirSync(this.storageDir, { recursive: true });\r\n }\r\n\r\n // 加载已有数据\r\n this.load();\r\n }\r\n\r\n /**\r\n * 生成存储 key\r\n */\r\n private getKey(endpoint: string, method: HttpMethod): string {\r\n return `${method}:${endpoint}`;\r\n }\r\n\r\n /**\r\n * 生成文件名\r\n */\r\n private getFileName(endpoint: string, method: HttpMethod): string {\r\n const sanitized = endpoint\r\n .replace(/^\\//, '')\r\n .replace(/\\//g, '_')\r\n .replace(/:/g, '_');\r\n return `${method}_${sanitized}.json`;\r\n }\r\n\r\n /**\r\n * 获取数据\r\n */\r\n get(endpoint: string, method: HttpMethod = 'GET'): any {\r\n const key = this.getKey(endpoint, method);\r\n const store = this.cache.get(key);\r\n return store?.data;\r\n }\r\n\r\n /**\r\n * 设置数据\r\n */\r\n set(\r\n endpoint: string,\r\n method: HttpMethod,\r\n data: any,\r\n metadata?: Partial<MockDataStore['metadata']>\r\n ): void {\r\n const key = this.getKey(endpoint, method);\r\n\r\n const store: MockDataStore = {\r\n endpoint,\r\n method,\r\n data,\r\n metadata: {\r\n count: Array.isArray(data) ? data.length : 1,\r\n generatedAt: new Date().toISOString(),\r\n version: '1.0.0',\r\n type: typeof data,\r\n ...metadata,\r\n },\r\n };\r\n\r\n this.cache.set(key, store);\r\n\r\n // 持久化\r\n if (this.persist) {\r\n this.save(endpoint, method, store);\r\n }\r\n }\r\n\r\n /**\r\n * 删除数据\r\n */\r\n delete(endpoint: string, method: HttpMethod = 'GET'): void {\r\n const key = this.getKey(endpoint, method);\r\n this.cache.delete(key);\r\n\r\n // 删除文件\r\n if (this.persist) {\r\n const fileName = this.getFileName(endpoint, method);\r\n const filePath = path.join(this.storageDir, fileName);\r\n if (fs.existsSync(filePath)) {\r\n fs.unlinkSync(filePath);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 清空所有数据\r\n */\r\n clear(): void {\r\n this.cache.clear();\r\n\r\n // 清空目录\r\n if (this.persist && fs.existsSync(this.storageDir)) {\r\n const files = fs.readdirSync(this.storageDir);\r\n for (const file of files) {\r\n fs.unlinkSync(path.join(this.storageDir, file));\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 获取所有端点\r\n */\r\n getAll(): MockDataStore[] {\r\n return Array.from(this.cache.values());\r\n }\r\n\r\n /**\r\n * 保存到文件\r\n */\r\n private save(\r\n endpoint: string,\r\n method: HttpMethod,\r\n store: MockDataStore\r\n ): void {\r\n const fileName = this.getFileName(endpoint, method);\r\n const filePath = path.join(this.storageDir, fileName);\r\n\r\n fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * 从文件加载\r\n */\r\n private load(): void {\r\n if (!this.persist || !fs.existsSync(this.storageDir)) {\r\n return;\r\n }\r\n\r\n const files = fs.readdirSync(this.storageDir);\r\n\r\n for (const file of files) {\r\n if (!file.endsWith('.json')) continue;\r\n\r\n try {\r\n const filePath = path.join(this.storageDir, file);\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n const store: MockDataStore = JSON.parse(content);\r\n\r\n const key = this.getKey(store.endpoint, store.method);\r\n this.cache.set(key, store);\r\n } catch (error) {\r\n console.warn(`Failed to load mock data from ${file}:`, error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 导出所有数据\r\n */\r\n export(outputPath: string): void {\r\n const allData = this.getAll();\r\n fs.writeFileSync(outputPath, JSON.stringify(allData, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * 导入数据\r\n */\r\n import(inputPath: string): void {\r\n const content = fs.readFileSync(inputPath, 'utf-8');\r\n const allData: MockDataStore[] = JSON.parse(content);\r\n\r\n for (const store of allData) {\r\n const key = this.getKey(store.endpoint, store.method);\r\n this.cache.set(key, store);\r\n\r\n if (this.persist) {\r\n this.save(store.endpoint, store.method, store);\r\n }\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - 数据生成器\r\n */\r\n\r\nimport type {\r\n TypeDefinition,\r\n GenerationContext,\r\n PropertyDefinition,\r\n} from './types';\r\n\r\nexport class MockDataGenerator {\r\n private apiKey: string;\r\n private apiUrl: string;\r\n private model: string;\r\n\r\n constructor(options: { apiKey: string; apiUrl: string; model: string }) {\r\n this.apiKey = options.apiKey;\r\n this.apiUrl = options.apiUrl;\r\n this.model = options.model;\r\n }\r\n\r\n /**\r\n * 生成 Mock 数据\r\n */\r\n async generate(context: GenerationContext): Promise<any> {\r\n const { type, count, locale, quality } = context;\r\n\r\n // 构建 AI Prompt\r\n const prompt = this.buildPrompt(type, count, locale, quality);\r\n\r\n // 调用 AI API\r\n const response = await this.callAI(prompt);\r\n\r\n // 解析响应\r\n return this.parseResponse(response, type.isArray);\r\n }\r\n\r\n /**\r\n * 构建 AI Prompt\r\n */\r\n private buildPrompt(\r\n type: TypeDefinition,\r\n count: number,\r\n locale: string,\r\n quality: string\r\n ): string {\r\n const properties = type.properties\r\n .map((p) => this.formatProperty(p))\r\n .join('\\n');\r\n\r\n return `\r\n你是一个专业的 Mock 数据生成器。请根据以下类型定义生成真实、合理的测试数据。\r\n\r\n类型名称: ${type.name}\r\n数据语言: ${locale === 'zh-CN' ? '中文' : '英文'}\r\n数据数量: ${count}\r\n质量要求: ${quality === 'high' ? '高质量(真实业务数据)' : quality === 'fast' ? '快速生成' : '平衡质量和速度'}\r\n\r\n类型定义:\r\n${properties}\r\n\r\n要求:\r\n1. 生成 ${count} 条数据\r\n2. 数据要符合业务逻辑和真实场景\r\n3. 字段值要合理(如价格不能为负数,年龄在合理范围)\r\n4. 日期格式使用 ISO 8601\r\n5. 返回 JSON 数组格式,不要包含任何其他文字\r\n6. 理解字段语义,生成真实数据(如 userName 生成真实姓名)\r\n\r\n示例格式:\r\n[\r\n {\r\n \"id\": 1,\r\n \"name\": \"张三\",\r\n ...\r\n }\r\n]\r\n\r\n请生成数据:\r\n`.trim();\r\n }\r\n\r\n /**\r\n * 格式化属性\r\n */\r\n private formatProperty(prop: PropertyDefinition): string {\r\n let line = `- ${prop.name}: ${prop.type}`;\r\n\r\n if (prop.comment) {\r\n line += ` // ${prop.comment}`;\r\n }\r\n\r\n if (prop.constraints) {\r\n const constraints = [];\r\n if (prop.constraints.min !== undefined) {\r\n constraints.push(`min: ${prop.constraints.min}`);\r\n }\r\n if (prop.constraints.max !== undefined) {\r\n constraints.push(`max: ${prop.constraints.max}`);\r\n }\r\n if (prop.constraints.unique) {\r\n constraints.push('unique');\r\n }\r\n if (prop.constraints.enum) {\r\n constraints.push(`enum: [${prop.constraints.enum.join(', ')}]`);\r\n }\r\n if (constraints.length > 0) {\r\n line += ` (${constraints.join(', ')})`;\r\n }\r\n }\r\n\r\n return line;\r\n }\r\n\r\n /**\r\n * 调用 AI API\r\n */\r\n private async callAI(prompt: string): Promise<string> {\r\n try {\r\n const response = await fetch(`${this.apiUrl}/chat/completions`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n Authorization: `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: this.model,\r\n messages: [\r\n {\r\n role: 'user',\r\n content: prompt,\r\n },\r\n ],\r\n temperature: 0.7,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`AI API error: ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json();\r\n return data.choices[0].message.content;\r\n } catch (error: any) {\r\n console.error('Failed to call AI API:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 解析 AI 响应\r\n */\r\n private parseResponse(response: string, isArray: boolean = true): any {\r\n try {\r\n // 移除 markdown 代码块标记\r\n let cleanedResponse = response.trim();\r\n \r\n // 移除开头的 ```json 或 ```\r\n cleanedResponse = cleanedResponse.replace(/^```json\\s*/i, '');\r\n cleanedResponse = cleanedResponse.replace(/^```\\s*/, '');\r\n \r\n // 移除结尾的 ```\r\n cleanedResponse = cleanedResponse.replace(/\\s*```$/, '');\r\n \r\n // 提取 JSON 部分(查找数组或对象)\r\n const jsonMatch = cleanedResponse.match(/(\\[[\\s\\S]*\\]|\\{[\\s\\S]*\\})/);\r\n if (!jsonMatch) {\r\n throw new Error('No JSON array or object found in response');\r\n }\r\n\r\n const data = JSON.parse(jsonMatch[0]);\r\n\r\n return isArray ? data : data[0];\r\n } catch (error: any) {\r\n console.error('Failed to parse AI response:', error);\r\n console.error('Response:', response);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 生成基础数据(不使用 AI)\r\n */\r\n generateBasic(type: TypeDefinition, count: number): any[] {\r\n const data = [];\r\n\r\n for (let i = 0; i < count; i++) {\r\n const item: any = {};\r\n\r\n for (const prop of type.properties) {\r\n item[prop.name] = this.generateBasicValue(prop, i);\r\n }\r\n\r\n data.push(item);\r\n }\r\n\r\n return data;\r\n }\r\n\r\n /**\r\n * 生成基础值\r\n */\r\n private generateBasicValue(prop: PropertyDefinition, index: number): any {\r\n const { type, constraints } = prop;\r\n\r\n // 处理枚举\r\n if (constraints?.enum) {\r\n return constraints.enum[index % constraints.enum.length];\r\n }\r\n\r\n // 根据类型生成\r\n switch (type) {\r\n case 'number':\r\n const min = constraints?.min ?? 0;\r\n const max = constraints?.max ?? 100;\r\n return Math.floor(Math.random() * (max - min + 1)) + min;\r\n\r\n case 'string':\r\n return `${prop.name}_${index + 1}`;\r\n\r\n case 'boolean':\r\n return Math.random() > 0.5;\r\n\r\n case 'Date':\r\n return new Date().toISOString();\r\n\r\n default:\r\n return null;\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - 工具函数\r\n */\r\n\r\nimport type { HttpMethod, RequestParams } from './types';\r\n\r\n/**\r\n * 延迟函数\r\n */\r\nexport function delay(ms: number | [number, number]): Promise<void> {\r\n const delayTime = Array.isArray(ms)\r\n ? Math.random() * (ms[1] - ms[0]) + ms[0]\r\n : ms;\r\n\r\n return new Promise((resolve) => setTimeout(resolve, delayTime));\r\n}\r\n\r\n/**\r\n * 匹配路径参数\r\n * @example\r\n * matchPathParams('/api/users/:id', '/api/users/123') // { id: '123' }\r\n */\r\nexport function matchPathParams(\r\n pattern: string,\r\n path: string\r\n): Record<string, string> | null {\r\n const patternParts = pattern.split('/');\r\n const pathParts = path.split('/');\r\n\r\n if (patternParts.length !== pathParts.length) {\r\n return null;\r\n }\r\n\r\n const params: Record<string, string> = {};\r\n\r\n for (let i = 0; i < patternParts.length; i++) {\r\n const patternPart = patternParts[i];\r\n const pathPart = pathParts[i];\r\n\r\n if (patternPart.startsWith(':')) {\r\n // 路径参数\r\n const paramName = patternPart.slice(1);\r\n params[paramName] = pathPart;\r\n } else if (patternPart !== pathPart) {\r\n // 不匹配\r\n return null;\r\n }\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * 解析查询参数\r\n */\r\nexport function parseQueryParams(url: string): Record<string, any> {\r\n const queryString = url.split('?')[1];\r\n if (!queryString) return {};\r\n\r\n const params: Record<string, any> = {};\r\n const pairs = queryString.split('&');\r\n\r\n for (const pair of pairs) {\r\n const [key, value] = pair.split('=');\r\n params[decodeURIComponent(key)] = decodeURIComponent(value || '');\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * 生成唯一 ID\r\n */\r\nexport function generateId(): string {\r\n return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * 深度克隆\r\n */\r\nexport function deepClone<T>(obj: T): T {\r\n return JSON.parse(JSON.stringify(obj));\r\n}\r\n\r\n/**\r\n * 应用过滤\r\n */\r\nexport function applyFilters(data: any[], filters: Record<string, any>): any[] {\r\n if (!filters || Object.keys(filters).length === 0) {\r\n return data;\r\n }\r\n\r\n return data.filter((item) => {\r\n for (const [key, value] of Object.entries(filters)) {\r\n if (item[key] !== value) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n });\r\n}\r\n\r\n/**\r\n * 应用排序\r\n */\r\nexport function applySorting(\r\n data: any[],\r\n sort?: string | { field: string; order: 'asc' | 'desc' }\r\n): any[] {\r\n if (!sort) return data;\r\n\r\n const sortConfig =\r\n typeof sort === 'string'\r\n ? { field: sort, order: 'asc' as const }\r\n : sort;\r\n\r\n return [...data].sort((a, b) => {\r\n const aValue = a[sortConfig.field];\r\n const bValue = b[sortConfig.field];\r\n\r\n if (aValue < bValue) return sortConfig.order === 'asc' ? -1 : 1;\r\n if (aValue > bValue) return sortConfig.order === 'asc' ? 1 : -1;\r\n return 0;\r\n });\r\n}\r\n\r\n/**\r\n * 应用分页\r\n */\r\nexport function applyPagination(\r\n data: any[],\r\n page: number = 1,\r\n pageSize: number = 20\r\n): {\r\n data: any[];\r\n pagination: {\r\n page: number;\r\n pageSize: number;\r\n total: number;\r\n totalPages: number;\r\n };\r\n} {\r\n const total = data.length;\r\n const totalPages = Math.ceil(total / pageSize);\r\n const start = (page - 1) * pageSize;\r\n const end = start + pageSize;\r\n\r\n return {\r\n data: data.slice(start, end),\r\n pagination: {\r\n page,\r\n pageSize,\r\n total,\r\n totalPages,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 格式化响应\r\n */\r\nexport function formatResponse(\r\n data: any,\r\n success: boolean = true,\r\n message?: string\r\n) {\r\n return {\r\n code: success ? 200 : 500,\r\n data,\r\n message: message || (success ? 'Success' : 'Error'),\r\n };\r\n}\r\n\r\n/**\r\n * 生成随机种子\r\n */\r\nexport function generateSeed(): number {\r\n return Math.floor(Math.random() * 1000000);\r\n}\r\n\r\n/**\r\n * 设置随机种子\r\n */\r\nexport function setSeed(seed: number): void {\r\n // 简单的伪随机数生成器\r\n let currentSeed = seed;\r\n Math.random = () => {\r\n currentSeed = (currentSeed * 9301 + 49297) % 233280;\r\n return currentSeed / 233280;\r\n };\r\n}\r\n","/**\r\n * AI Mock Generator - Mock 服务器\r\n */\r\n\r\nimport type { ViteDevServer } from 'vite';\r\nimport type {\r\n EndpointConfig,\r\n HttpMethod,\r\n MockGeneratorOptions,\r\n} from './types';\r\nimport { MockStorage } from './storage';\r\nimport {\r\n delay,\r\n matchPathParams,\r\n parseQueryParams,\r\n applyFilters,\r\n applySorting,\r\n applyPagination,\r\n formatResponse,\r\n} from './utils';\r\n\r\nexport class MockServer {\r\n private storage: MockStorage;\r\n private endpoints: EndpointConfig[];\r\n private options: MockGeneratorOptions;\r\n\r\n constructor(storage: MockStorage, options: MockGeneratorOptions) {\r\n this.storage = storage;\r\n this.endpoints = options.endpoints || [];\r\n this.options = options;\r\n }\r\n\r\n /**\r\n * 配置服务器中间件\r\n */\r\n configureServer(server: ViteDevServer): void {\r\n server.middlewares.use(async (req, res, next) => {\r\n const url = req.url || '';\r\n const method = req.method as HttpMethod;\r\n\r\n // 检查是否匹配 Mock 端点\r\n const endpoint = this.matchEndpoint(url, method);\r\n\r\n if (!endpoint) {\r\n return next();\r\n }\r\n\r\n try {\r\n // 解析请求参数\r\n const params = this.parseRequest(req, url);\r\n\r\n // 获取 Mock 数据\r\n const data = await this.getMockData(endpoint, params);\r\n\r\n // 模拟延迟\r\n if (this.options.server?.delay) {\r\n await delay(this.options.server.delay);\r\n }\r\n\r\n // 设置响应头\r\n res.setHeader('Content-Type', 'application/json');\r\n if (this.options.server?.cors) {\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Allow-Methods', '*');\r\n res.setHeader('Access-Control-Allow-Headers', '*');\r\n }\r\n\r\n // 返回响应\r\n res.statusCode = 200;\r\n res.end(JSON.stringify(data));\r\n\r\n // 日志\r\n if (this.options.output?.logs) {\r\n console.log(`[Mock] ${method} ${url} → ${data ? 'OK' : 'Empty'}`);\r\n }\r\n } catch (error: any) {\r\n console.error(`[Mock] Error handling ${method} ${url}:`, error);\r\n res.statusCode = 500;\r\n res.end(\r\n JSON.stringify({\r\n code: 500,\r\n message: error.message,\r\n })\r\n );\r\n }\r\n });\r\n\r\n console.log('\\n🎭 Mock 服务器已启动');\r\n console.log(`📍 已注册 ${this.endpoints.length} 个端点\\n`);\r\n }\r\n\r\n /**\r\n * 匹配端点\r\n */\r\n private matchEndpoint(\r\n url: string,\r\n method: HttpMethod\r\n ): EndpointConfig | null {\r\n // 移除查询参数\r\n const path = url.split('?')[0];\r\n\r\n // 移除前缀\r\n const prefix = this.options.server?.prefix || '';\r\n const cleanPath = prefix ? path.replace(new RegExp(`^${prefix}`), '') : path;\r\n\r\n for (const endpoint of this.endpoints) {\r\n // 检查是否禁用\r\n if (endpoint.enabled === false) continue;\r\n\r\n // 检查方法\r\n if (endpoint.method !== method) continue;\r\n\r\n // 精确匹配\r\n if (endpoint.path === cleanPath) {\r\n return endpoint;\r\n }\r\n\r\n // 路径参数匹配\r\n if (matchPathParams(endpoint.path, cleanPath)) {\r\n return endpoint;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 解析请求\r\n */\r\n private parseRequest(req: any, url: string): any {\r\n const query = parseQueryParams(url);\r\n const path = url.split('?')[0];\r\n\r\n // 查找匹配的端点以提取路径参数\r\n const endpoint = this.matchEndpoint(path, req.method);\r\n const pathParams = endpoint\r\n ? matchPathParams(endpoint.path, path.split('?')[0])\r\n : null;\r\n\r\n return {\r\n query,\r\n params: pathParams || {},\r\n body: req.body,\r\n headers: req.headers,\r\n };\r\n }\r\n\r\n /**\r\n * 获取 Mock 数据\r\n */\r\n private async getMockData(\r\n endpoint: EndpointConfig,\r\n params: any\r\n ): Promise<any> {\r\n // 从存储获取数据\r\n let data = this.storage.get(endpoint.path, endpoint.method);\r\n\r\n if (!data) {\r\n console.warn(\r\n `[Mock] No data found for ${endpoint.method} ${endpoint.path}`\r\n );\r\n return formatResponse([], false, 'No mock data available');\r\n }\r\n\r\n // 如果是数组,应用过滤、排序、分页\r\n if (Array.isArray(data)) {\r\n // 过滤\r\n if (params.query.filter) {\r\n data = applyFilters(data, JSON.parse(params.query.filter));\r\n }\r\n\r\n // 排序\r\n if (params.query.sort) {\r\n data = applySorting(data, params.query.sort);\r\n }\r\n\r\n // 分页\r\n if (params.query.page || params.query.pageSize) {\r\n const page = parseInt(params.query.page) || 1;\r\n const pageSize = parseInt(params.query.pageSize) || 20;\r\n const result = applyPagination(data, page, pageSize);\r\n\r\n return formatResponse({\r\n list: result.data,\r\n pagination: result.pagination,\r\n });\r\n }\r\n }\r\n\r\n // 应用自定义处理\r\n if (endpoint.custom) {\r\n data = await endpoint.custom(data, params);\r\n }\r\n\r\n // 格式化响应\r\n return formatResponse(data);\r\n }\r\n\r\n /**\r\n * 添加端点\r\n */\r\n addEndpoint(endpoint: EndpointConfig): void {\r\n this.endpoints.push(endpoint);\r\n }\r\n\r\n /**\r\n * 移除端点\r\n */\r\n removeEndpoint(path: string, method: HttpMethod): void {\r\n this.endpoints = this.endpoints.filter(\r\n (e) => !(e.path === path && e.method === method)\r\n );\r\n }\r\n\r\n /**\r\n * 获取所有端点\r\n */\r\n getEndpoints(): EndpointConfig[] {\r\n return this.endpoints;\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - Vite 插件入口\r\n */\r\n\r\nimport type { Plugin } from 'vite';\r\nimport type { MockGeneratorOptions, TypeDefinition } from './types';\r\nimport { MockStorage } from './storage';\r\nimport { MockDataGenerator } from './generator';\r\nimport { MockServer } from './server';\r\n\r\nexport function vitePluginAIMockGenerator(\r\n options: MockGeneratorOptions = {}\r\n): Plugin {\r\n const {\r\n apiKey = process.env.OPENAI_API_KEY || '',\r\n apiUrl = process.env.OPENAI_API_URL || 'https://api.openai.com/v1',\r\n model = process.env.OPENAI_MODEL || 'gpt-4',\r\n enabled = true,\r\n autoGenerate = false,\r\n generation = {\r\n locale: 'zh-CN',\r\n count: 20,\r\n quality: 'balanced',\r\n },\r\n storage: storageOptions = {\r\n dir: 'mock-data',\r\n persist: true,\r\n cache: true,\r\n },\r\n output = {\r\n console: true,\r\n logs: false,\r\n },\r\n } = options;\r\n\r\n // 如果未启用,返回空插件\r\n if (!enabled) {\r\n return {\r\n name: 'vite-plugin-ai-mock-generator',\r\n };\r\n }\r\n\r\n // 初始化组件\r\n const storage = new MockStorage(storageOptions);\r\n const generator = new MockDataGenerator({ apiKey, apiUrl, model });\r\n const server = new MockServer(storage, options);\r\n\r\n return {\r\n name: 'vite-plugin-ai-mock-generator',\r\n enforce: 'pre',\r\n\r\n configResolved(config) {\r\n if (output.console) {\r\n console.log('\\n🤖 AI Mock Generator 已启动');\r\n console.log(`📂 存储目录: ${storageOptions.dir}`);\r\n console.log(`🌍 数据语言: ${generation.locale}`);\r\n console.log(`📊 默认数量: ${generation.count}`);\r\n console.log(`🔑 API Key: ${apiKey ? '已配置' : '未配置'}`);\r\n console.log(\r\n `📍 端点数量: ${options.endpoints?.length || 0}`\r\n );\r\n }\r\n },\r\n\r\n async buildStart() {\r\n // 如果启用自动生成\r\n if (autoGenerate && options.endpoints) {\r\n if (output.console) {\r\n console.log('\\n🔄 开始自动生成 Mock 数据...\\n');\r\n }\r\n\r\n for (const endpoint of options.endpoints) {\r\n // 检查是否已有数据\r\n const existingData = storage.get(endpoint.path, endpoint.method);\r\n if (existingData) {\r\n if (output.console) {\r\n console.log(\r\n `⏭️ 跳过 ${endpoint.method} ${endpoint.path} (已有数据)`\r\n );\r\n }\r\n continue;\r\n }\r\n\r\n try {\r\n if (output.console) {\r\n console.log(`🎲 生成 ${endpoint.method} ${endpoint.path}...`);\r\n }\r\n\r\n // 解析类型定义\r\n const typeDefinition = parseTypeDefinition(endpoint.response);\r\n\r\n // 生成数据\r\n const count = endpoint.count || generation.count || 20;\r\n let data;\r\n \r\n // 根据质量设置选择生成方式\r\n if (generation.quality === 'fast') {\r\n // 使用基础生成器(不需要 AI)\r\n data = generator.generateBasic(typeDefinition, count);\r\n } else {\r\n // 使用 AI 生成\r\n data = await generator.generate({\r\n type: typeDefinition,\r\n count,\r\n locale: generation.locale || 'zh-CN',\r\n quality: generation.quality || 'balanced',\r\n });\r\n }\r\n\r\n // 存储数据\r\n storage.set(endpoint.path, endpoint.method, data, {\r\n type: endpoint.response as string,\r\n });\r\n\r\n if (output.console) {\r\n console.log(\r\n `✅ 已生成 ${count} 条数据: ${endpoint.method} ${endpoint.path}`\r\n );\r\n }\r\n } catch (error: any) {\r\n console.error(\r\n `❌ 生成失败 ${endpoint.method} ${endpoint.path}:`,\r\n error.message\r\n );\r\n }\r\n }\r\n\r\n if (output.console) {\r\n console.log('\\n✨ Mock 数据生成完成\\n');\r\n }\r\n }\r\n },\r\n\r\n configureServer(viteServer) {\r\n // 配置 Mock 服务器中间件\r\n server.configureServer(viteServer);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 解析类型定义\r\n * 简化版本,实际应该使用 TypeScript Compiler API\r\n */\r\nfunction parseTypeDefinition(typeStr: string | TypeDefinition): TypeDefinition {\r\n if (typeof typeStr === 'object') {\r\n return typeStr;\r\n }\r\n\r\n // 简单解析(实际应该更复杂)\r\n const isArray = typeStr.endsWith('[]');\r\n const typeName = isArray ? typeStr.slice(0, -2) : typeStr;\r\n\r\n // 返回基础类型定义\r\n return {\r\n name: typeName,\r\n properties: [],\r\n isArray,\r\n };\r\n}\r\n\r\n// 导出类型\r\nexport type { MockGeneratorOptions, EndpointConfig } from './types';\r\nexport { MockStorage } from './storage';\r\nexport { MockDataGenerator } from './generator';\r\nexport { MockServer } from './server';\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/storage.ts","../src/generator.ts","../src/utils.ts","../src/server.ts"],"sourcesContent":["/**\r\n * AI Mock Generator - Vite 插件入口\r\n */\r\n\r\nimport type { Plugin } from \"vite\";\r\nimport type { MockGeneratorOptions, TypeDefinition } from \"./types\";\r\nimport { MockStorage } from \"./storage\";\r\nimport { MockDataGenerator } from \"./generator\";\r\nimport { MockServer } from \"./server\";\r\n\r\nexport function vitePluginAIMockGenerator(\r\n options: MockGeneratorOptions = {},\r\n): Plugin {\r\n const {\r\n apiKey = process.env.OPENAI_API_KEY || \"\",\r\n apiUrl = process.env.OPENAI_API_URL || \"https://api.openai.com/v1\",\r\n model = process.env.OPENAI_MODEL || \"gpt-4\",\r\n enabled = true,\r\n autoGenerate = false,\r\n generation = {\r\n locale: \"zh-CN\",\r\n count: 20,\r\n quality: \"balanced\",\r\n },\r\n storage: storageOptions = {\r\n dir: \"mock-data\",\r\n persist: true,\r\n cache: true,\r\n },\r\n output = {\r\n console: true,\r\n logs: false,\r\n },\r\n } = options;\r\n\r\n // 如果未启用,返回空插件\r\n if (!enabled) {\r\n return {\r\n name: \"vite-plugin-ai-mock-generator\",\r\n };\r\n }\r\n\r\n // 初始化组件\r\n const storage = new MockStorage(storageOptions);\r\n const generator = new MockDataGenerator({ apiKey, apiUrl, model });\r\n const server = new MockServer(storage, options);\r\n\r\n return {\r\n name: \"vite-plugin-ai-mock-generator\",\r\n enforce: \"pre\",\r\n\r\n configResolved(config) {\r\n if (output.console) {\r\n console.log(\"\\n🤖 AI Mock Generator 已启动\");\r\n console.log(`📂 存储目录: ${storageOptions.dir}`);\r\n console.log(`🌍 数据语言: ${generation.locale}`);\r\n console.log(`📊 默认数量: ${generation.count}`);\r\n console.log(`🔑 API Key: ${apiKey ? \"已配置\" : \"未配置\"}`);\r\n console.log(`📍 端点数量: ${options.endpoints?.length || 0}`);\r\n }\r\n },\r\n\r\n async buildStart() {\r\n // 如果启用自动生成\r\n if (autoGenerate && options.endpoints) {\r\n if (output.console) {\r\n console.log(\"\\n🔄 开始自动生成 Mock 数据...\\n\");\r\n }\r\n\r\n for (const endpoint of options.endpoints) {\r\n // 检查是否已有数据\r\n const existingData = storage.get(endpoint.path, endpoint.method);\r\n if (existingData) {\r\n if (output.console) {\r\n console.log(\r\n `⏭️ 跳过 ${endpoint.method} ${endpoint.path} (已有数据)`,\r\n );\r\n }\r\n continue;\r\n }\r\n\r\n try {\r\n if (output.console) {\r\n console.log(`🎲 生成 ${endpoint.method} ${endpoint.path}...`);\r\n }\r\n\r\n // 解析类型定义\r\n const typeDefinition = parseTypeDefinition(endpoint.response);\r\n\r\n // 生成数据\r\n const count = endpoint.count || generation.count || 20;\r\n let data;\r\n\r\n // 根据质量设置选择生成方式\r\n if (generation.quality === \"fast\") {\r\n // 使用基础生成器(不需要 AI)\r\n data = generator.generateBasic(typeDefinition, count);\r\n } else {\r\n // 使用 AI 生成\r\n data = await generator.generate({\r\n type: typeDefinition,\r\n count,\r\n locale: generation.locale || \"zh-CN\",\r\n quality: generation.quality || \"balanced\",\r\n });\r\n }\r\n\r\n // 存储数据\r\n storage.set(endpoint.path, endpoint.method, data, {\r\n type: endpoint.response as string,\r\n });\r\n\r\n if (output.console) {\r\n console.log(\r\n `✅ 已生成 ${count} 条数据: ${endpoint.method} ${endpoint.path}`,\r\n );\r\n }\r\n } catch (error: any) {\r\n console.error(\r\n `❌ 生成失败 ${endpoint.method} ${endpoint.path}:`,\r\n error.message,\r\n );\r\n }\r\n }\r\n\r\n if (output.console) {\r\n console.log(\"\\n✨ Mock 数据生成完成\\n\");\r\n }\r\n }\r\n },\r\n\r\n configureServer(viteServer) {\r\n // 配置 Mock 服务器中间件\r\n server.configureServer(viteServer);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 解析类型定义\r\n * 简化版本,实际应该使用 TypeScript Compiler API\r\n */\r\nfunction parseTypeDefinition(typeStr: string | TypeDefinition): TypeDefinition {\r\n if (typeof typeStr === \"object\") {\r\n return typeStr;\r\n }\r\n\r\n // 简单解析(实际应该更复杂)\r\n const isArray = typeStr.endsWith(\"[]\");\r\n const typeName = isArray ? typeStr.slice(0, -2) : typeStr;\r\n\r\n // 返回基础类型定义\r\n return {\r\n name: typeName,\r\n properties: [],\r\n isArray,\r\n };\r\n}\r\n\r\n// 导出类型\r\nexport type { MockGeneratorOptions, EndpointConfig } from \"./types\";\r\nexport { MockStorage } from \"./storage\";\r\nexport { MockDataGenerator } from \"./generator\";\r\nexport { MockServer } from \"./server\";\r\n\r\n// 默认导出\r\nexport default vitePluginAIMockGenerator;\r\n","/**\r\n * AI Mock Generator - 数据存储\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type { MockDataStore, HttpMethod } from './types';\r\n\r\nexport class MockStorage {\r\n private storageDir: string;\r\n private cache: Map<string, MockDataStore>;\r\n private persist: boolean;\r\n\r\n constructor(options: { dir?: string; persist?: boolean } = {}) {\r\n this.storageDir = options.dir || 'mock-data';\r\n this.persist = options.persist !== false;\r\n this.cache = new Map();\r\n\r\n // 确保存储目录存在\r\n if (this.persist && !fs.existsSync(this.storageDir)) {\r\n fs.mkdirSync(this.storageDir, { recursive: true });\r\n }\r\n\r\n // 加载已有数据\r\n this.load();\r\n }\r\n\r\n /**\r\n * 生成存储 key\r\n */\r\n private getKey(endpoint: string, method: HttpMethod): string {\r\n return `${method}:${endpoint}`;\r\n }\r\n\r\n /**\r\n * 生成文件名\r\n */\r\n private getFileName(endpoint: string, method: HttpMethod): string {\r\n const sanitized = endpoint\r\n .replace(/^\\//, '')\r\n .replace(/\\//g, '_')\r\n .replace(/:/g, '_');\r\n return `${method}_${sanitized}.json`;\r\n }\r\n\r\n /**\r\n * 获取数据\r\n */\r\n get(endpoint: string, method: HttpMethod = 'GET'): any {\r\n const key = this.getKey(endpoint, method);\r\n const store = this.cache.get(key);\r\n return store?.data;\r\n }\r\n\r\n /**\r\n * 设置数据\r\n */\r\n set(\r\n endpoint: string,\r\n method: HttpMethod,\r\n data: any,\r\n metadata?: Partial<MockDataStore['metadata']>\r\n ): void {\r\n const key = this.getKey(endpoint, method);\r\n\r\n const store: MockDataStore = {\r\n endpoint,\r\n method,\r\n data,\r\n metadata: {\r\n count: Array.isArray(data) ? data.length : 1,\r\n generatedAt: new Date().toISOString(),\r\n version: '1.0.0',\r\n type: typeof data,\r\n ...metadata,\r\n },\r\n };\r\n\r\n this.cache.set(key, store);\r\n\r\n // 持久化\r\n if (this.persist) {\r\n this.save(endpoint, method, store);\r\n }\r\n }\r\n\r\n /**\r\n * 删除数据\r\n */\r\n delete(endpoint: string, method: HttpMethod = 'GET'): void {\r\n const key = this.getKey(endpoint, method);\r\n this.cache.delete(key);\r\n\r\n // 删除文件\r\n if (this.persist) {\r\n const fileName = this.getFileName(endpoint, method);\r\n const filePath = path.join(this.storageDir, fileName);\r\n if (fs.existsSync(filePath)) {\r\n fs.unlinkSync(filePath);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 清空所有数据\r\n */\r\n clear(): void {\r\n this.cache.clear();\r\n\r\n // 清空目录\r\n if (this.persist && fs.existsSync(this.storageDir)) {\r\n const files = fs.readdirSync(this.storageDir);\r\n for (const file of files) {\r\n fs.unlinkSync(path.join(this.storageDir, file));\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 获取所有端点\r\n */\r\n getAll(): MockDataStore[] {\r\n return Array.from(this.cache.values());\r\n }\r\n\r\n /**\r\n * 保存到文件\r\n */\r\n private save(\r\n endpoint: string,\r\n method: HttpMethod,\r\n store: MockDataStore\r\n ): void {\r\n const fileName = this.getFileName(endpoint, method);\r\n const filePath = path.join(this.storageDir, fileName);\r\n\r\n fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * 从文件加载\r\n */\r\n private load(): void {\r\n if (!this.persist || !fs.existsSync(this.storageDir)) {\r\n return;\r\n }\r\n\r\n const files = fs.readdirSync(this.storageDir);\r\n\r\n for (const file of files) {\r\n if (!file.endsWith('.json')) continue;\r\n\r\n try {\r\n const filePath = path.join(this.storageDir, file);\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n const store: MockDataStore = JSON.parse(content);\r\n\r\n const key = this.getKey(store.endpoint, store.method);\r\n this.cache.set(key, store);\r\n } catch (error) {\r\n console.warn(`Failed to load mock data from ${file}:`, error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 导出所有数据\r\n */\r\n export(outputPath: string): void {\r\n const allData = this.getAll();\r\n fs.writeFileSync(outputPath, JSON.stringify(allData, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * 导入数据\r\n */\r\n import(inputPath: string): void {\r\n const content = fs.readFileSync(inputPath, 'utf-8');\r\n const allData: MockDataStore[] = JSON.parse(content);\r\n\r\n for (const store of allData) {\r\n const key = this.getKey(store.endpoint, store.method);\r\n this.cache.set(key, store);\r\n\r\n if (this.persist) {\r\n this.save(store.endpoint, store.method, store);\r\n }\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - 数据生成器\r\n */\r\n\r\nimport { ChatOpenAI } from \"@langchain/openai\";\r\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\r\nimport type {\r\n TypeDefinition,\r\n GenerationContext,\r\n PropertyDefinition,\r\n} from \"./types\";\r\n\r\nexport class MockDataGenerator {\r\n private llm: ChatOpenAI;\r\n\r\n constructor(options: { apiKey: string; apiUrl: string; model: string }) {\r\n this.llm = new ChatOpenAI({\r\n openAIApiKey: options.apiKey,\r\n configuration: {\r\n baseURL: options.apiUrl,\r\n },\r\n modelName: options.model,\r\n temperature: 0.7,\r\n maxTokens: 4000,\r\n });\r\n }\r\n\r\n /**\r\n * 生成 Mock 数据\r\n */\r\n async generate(context: GenerationContext): Promise<any> {\r\n const { type, count, locale, quality } = context;\r\n\r\n // 构建 AI Prompt\r\n const prompt = this.buildPrompt(type, count, locale, quality);\r\n\r\n // 调用 AI API\r\n const response = await this.callAI(prompt);\r\n\r\n // 解析响应\r\n return this.parseResponse(response, type.isArray);\r\n }\r\n\r\n /**\r\n * 构建 AI Prompt\r\n */\r\n private buildPrompt(\r\n type: TypeDefinition,\r\n count: number,\r\n locale: string,\r\n quality: string,\r\n ): string {\r\n const properties = type.properties\r\n .map((p) => this.formatProperty(p))\r\n .join(\"\\n\");\r\n\r\n return `\r\n你是一个专业的 Mock 数据生成器。请根据以下类型定义生成真实、合理的测试数据。\r\n\r\n类型名称: ${type.name}\r\n数据语言: ${locale === \"zh-CN\" ? \"中文\" : \"英文\"}\r\n数据数量: ${count}\r\n质量要求: ${\r\n quality === \"high\"\r\n ? \"高质量(真实业务数据)\"\r\n : quality === \"fast\"\r\n ? \"快速生成\"\r\n : \"平衡质量和速度\"\r\n }\r\n\r\n类型定义:\r\n${properties}\r\n\r\n要求:\r\n1. 生成 ${count} 条数据\r\n2. 数据要符合业务逻辑和真实场景\r\n3. 字段值要合理(如价格不能为负数,年龄在合理范围)\r\n4. 日期格式使用 ISO 8601\r\n5. 返回 JSON 数组格式,不要包含任何其他文字\r\n6. 理解字段语义,生成真实数据(如 userName 生成真实姓名)\r\n\r\n示例格式:\r\n[\r\n {\r\n \"id\": 1,\r\n \"name\": \"张三\",\r\n ...\r\n }\r\n]\r\n\r\n请生成数据:\r\n`.trim();\r\n }\r\n\r\n /**\r\n * 格式化属性\r\n */\r\n private formatProperty(prop: PropertyDefinition): string {\r\n let line = `- ${prop.name}: ${prop.type}`;\r\n\r\n if (prop.comment) {\r\n line += ` // ${prop.comment}`;\r\n }\r\n\r\n if (prop.constraints) {\r\n const constraints = [];\r\n if (prop.constraints.min !== undefined) {\r\n constraints.push(`min: ${prop.constraints.min}`);\r\n }\r\n if (prop.constraints.max !== undefined) {\r\n constraints.push(`max: ${prop.constraints.max}`);\r\n }\r\n if (prop.constraints.unique) {\r\n constraints.push(\"unique\");\r\n }\r\n if (prop.constraints.enum) {\r\n constraints.push(`enum: [${prop.constraints.enum.join(\", \")}]`);\r\n }\r\n if (constraints.length > 0) {\r\n line += ` (${constraints.join(\", \")})`;\r\n }\r\n }\r\n\r\n return line;\r\n }\r\n\r\n /**\r\n * 调用 AI API\r\n */\r\n private async callAI(prompt: string): Promise<string> {\r\n try {\r\n const messages = [\r\n new SystemMessage(\r\n \"你是一个专业的 Mock 数据生成器,擅长生成真实、合理的测试数据。\",\r\n ),\r\n new HumanMessage(prompt),\r\n ];\r\n\r\n const response = await this.llm.invoke(messages);\r\n return response.content as string;\r\n } catch (error: any) {\r\n console.error(\"❌ AI API 调用失败:\", error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 解析 AI 响应\r\n */\r\n private parseResponse(response: string, isArray: boolean = true): any {\r\n try {\r\n // 移除 markdown 代码块标记\r\n let cleanedResponse = response.trim();\r\n\r\n // 移除开头的 ```json 或 ```\r\n cleanedResponse = cleanedResponse.replace(/^```json\\s*/i, \"\");\r\n cleanedResponse = cleanedResponse.replace(/^```\\s*/, \"\");\r\n\r\n // 移除结尾的 ```\r\n cleanedResponse = cleanedResponse.replace(/\\s*```$/, \"\");\r\n\r\n // 提取 JSON 部分(查找数组或对象)\r\n const jsonMatch = cleanedResponse.match(/(\\[[\\s\\S]*\\]|\\{[\\s\\S]*\\})/);\r\n if (!jsonMatch) {\r\n throw new Error(\"No JSON array or object found in response\");\r\n }\r\n\r\n const data = JSON.parse(jsonMatch[0]);\r\n\r\n return isArray ? data : data[0];\r\n } catch (error: any) {\r\n console.error(\"❌ 解析 AI 响应失败:\", error.message);\r\n console.error(\"响应内容:\", response);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 生成基础数据(不使用 AI)\r\n */\r\n generateBasic(type: TypeDefinition, count: number): any[] {\r\n const data = [];\r\n\r\n for (let i = 0; i < count; i++) {\r\n const item: any = {};\r\n\r\n for (const prop of type.properties) {\r\n item[prop.name] = this.generateBasicValue(prop, i);\r\n }\r\n\r\n data.push(item);\r\n }\r\n\r\n return data;\r\n }\r\n\r\n /**\r\n * 生成基础值\r\n */\r\n private generateBasicValue(prop: PropertyDefinition, index: number): any {\r\n const { type, constraints } = prop;\r\n\r\n // 处理枚举\r\n if (constraints?.enum) {\r\n return constraints.enum[index % constraints.enum.length];\r\n }\r\n\r\n // 根据类型生成\r\n switch (type) {\r\n case \"number\":\r\n const min = constraints?.min ?? 0;\r\n const max = constraints?.max ?? 100;\r\n return Math.floor(Math.random() * (max - min + 1)) + min;\r\n\r\n case \"string\":\r\n return `${prop.name}_${index + 1}`;\r\n\r\n case \"boolean\":\r\n return Math.random() > 0.5;\r\n\r\n case \"Date\":\r\n return new Date().toISOString();\r\n\r\n default:\r\n return null;\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - 工具函数\r\n */\r\n\r\nimport type { HttpMethod, RequestParams } from './types';\r\n\r\n/**\r\n * 延迟函数\r\n */\r\nexport function delay(ms: number | [number, number]): Promise<void> {\r\n const delayTime = Array.isArray(ms)\r\n ? Math.random() * (ms[1] - ms[0]) + ms[0]\r\n : ms;\r\n\r\n return new Promise((resolve) => setTimeout(resolve, delayTime));\r\n}\r\n\r\n/**\r\n * 匹配路径参数\r\n * @example\r\n * matchPathParams('/api/users/:id', '/api/users/123') // { id: '123' }\r\n */\r\nexport function matchPathParams(\r\n pattern: string,\r\n path: string\r\n): Record<string, string> | null {\r\n const patternParts = pattern.split('/');\r\n const pathParts = path.split('/');\r\n\r\n if (patternParts.length !== pathParts.length) {\r\n return null;\r\n }\r\n\r\n const params: Record<string, string> = {};\r\n\r\n for (let i = 0; i < patternParts.length; i++) {\r\n const patternPart = patternParts[i];\r\n const pathPart = pathParts[i];\r\n\r\n if (patternPart.startsWith(':')) {\r\n // 路径参数\r\n const paramName = patternPart.slice(1);\r\n params[paramName] = pathPart;\r\n } else if (patternPart !== pathPart) {\r\n // 不匹配\r\n return null;\r\n }\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * 解析查询参数\r\n */\r\nexport function parseQueryParams(url: string): Record<string, any> {\r\n const queryString = url.split('?')[1];\r\n if (!queryString) return {};\r\n\r\n const params: Record<string, any> = {};\r\n const pairs = queryString.split('&');\r\n\r\n for (const pair of pairs) {\r\n const [key, value] = pair.split('=');\r\n params[decodeURIComponent(key)] = decodeURIComponent(value || '');\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * 生成唯一 ID\r\n */\r\nexport function generateId(): string {\r\n return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * 深度克隆\r\n */\r\nexport function deepClone<T>(obj: T): T {\r\n return JSON.parse(JSON.stringify(obj));\r\n}\r\n\r\n/**\r\n * 应用过滤\r\n */\r\nexport function applyFilters(data: any[], filters: Record<string, any>): any[] {\r\n if (!filters || Object.keys(filters).length === 0) {\r\n return data;\r\n }\r\n\r\n return data.filter((item) => {\r\n for (const [key, value] of Object.entries(filters)) {\r\n if (item[key] !== value) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n });\r\n}\r\n\r\n/**\r\n * 应用排序\r\n */\r\nexport function applySorting(\r\n data: any[],\r\n sort?: string | { field: string; order: 'asc' | 'desc' }\r\n): any[] {\r\n if (!sort) return data;\r\n\r\n const sortConfig =\r\n typeof sort === 'string'\r\n ? { field: sort, order: 'asc' as const }\r\n : sort;\r\n\r\n return [...data].sort((a, b) => {\r\n const aValue = a[sortConfig.field];\r\n const bValue = b[sortConfig.field];\r\n\r\n if (aValue < bValue) return sortConfig.order === 'asc' ? -1 : 1;\r\n if (aValue > bValue) return sortConfig.order === 'asc' ? 1 : -1;\r\n return 0;\r\n });\r\n}\r\n\r\n/**\r\n * 应用分页\r\n */\r\nexport function applyPagination(\r\n data: any[],\r\n page: number = 1,\r\n pageSize: number = 20\r\n): {\r\n data: any[];\r\n pagination: {\r\n page: number;\r\n pageSize: number;\r\n total: number;\r\n totalPages: number;\r\n };\r\n} {\r\n const total = data.length;\r\n const totalPages = Math.ceil(total / pageSize);\r\n const start = (page - 1) * pageSize;\r\n const end = start + pageSize;\r\n\r\n return {\r\n data: data.slice(start, end),\r\n pagination: {\r\n page,\r\n pageSize,\r\n total,\r\n totalPages,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 格式化响应\r\n */\r\nexport function formatResponse(\r\n data: any,\r\n success: boolean = true,\r\n message?: string\r\n) {\r\n return {\r\n code: success ? 200 : 500,\r\n data,\r\n message: message || (success ? 'Success' : 'Error'),\r\n };\r\n}\r\n\r\n/**\r\n * 生成随机种子\r\n */\r\nexport function generateSeed(): number {\r\n return Math.floor(Math.random() * 1000000);\r\n}\r\n\r\n/**\r\n * 设置随机种子\r\n */\r\nexport function setSeed(seed: number): void {\r\n // 简单的伪随机数生成器\r\n let currentSeed = seed;\r\n Math.random = () => {\r\n currentSeed = (currentSeed * 9301 + 49297) % 233280;\r\n return currentSeed / 233280;\r\n };\r\n}\r\n","/**\r\n * AI Mock Generator - Mock 服务器\r\n */\r\n\r\nimport type { ViteDevServer } from 'vite';\r\nimport type {\r\n EndpointConfig,\r\n HttpMethod,\r\n MockGeneratorOptions,\r\n} from './types';\r\nimport { MockStorage } from './storage';\r\nimport {\r\n delay,\r\n matchPathParams,\r\n parseQueryParams,\r\n applyFilters,\r\n applySorting,\r\n applyPagination,\r\n formatResponse,\r\n} from './utils';\r\n\r\nexport class MockServer {\r\n private storage: MockStorage;\r\n private endpoints: EndpointConfig[];\r\n private options: MockGeneratorOptions;\r\n\r\n constructor(storage: MockStorage, options: MockGeneratorOptions) {\r\n this.storage = storage;\r\n this.endpoints = options.endpoints || [];\r\n this.options = options;\r\n }\r\n\r\n /**\r\n * 配置服务器中间件\r\n */\r\n configureServer(server: ViteDevServer): void {\r\n server.middlewares.use(async (req, res, next) => {\r\n const url = req.url || '';\r\n const method = req.method as HttpMethod;\r\n\r\n // 检查是否匹配 Mock 端点\r\n const endpoint = this.matchEndpoint(url, method);\r\n\r\n if (!endpoint) {\r\n return next();\r\n }\r\n\r\n try {\r\n // 解析请求参数\r\n const params = this.parseRequest(req, url);\r\n\r\n // 获取 Mock 数据\r\n const data = await this.getMockData(endpoint, params);\r\n\r\n // 模拟延迟\r\n if (this.options.server?.delay) {\r\n await delay(this.options.server.delay);\r\n }\r\n\r\n // 设置响应头\r\n res.setHeader('Content-Type', 'application/json');\r\n if (this.options.server?.cors) {\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Allow-Methods', '*');\r\n res.setHeader('Access-Control-Allow-Headers', '*');\r\n }\r\n\r\n // 返回响应\r\n res.statusCode = 200;\r\n res.end(JSON.stringify(data));\r\n\r\n // 日志\r\n if (this.options.output?.logs) {\r\n console.log(`[Mock] ${method} ${url} → ${data ? 'OK' : 'Empty'}`);\r\n }\r\n } catch (error: any) {\r\n console.error(`[Mock] Error handling ${method} ${url}:`, error);\r\n res.statusCode = 500;\r\n res.end(\r\n JSON.stringify({\r\n code: 500,\r\n message: error.message,\r\n })\r\n );\r\n }\r\n });\r\n\r\n console.log('\\n🎭 Mock 服务器已启动');\r\n console.log(`📍 已注册 ${this.endpoints.length} 个端点\\n`);\r\n }\r\n\r\n /**\r\n * 匹配端点\r\n */\r\n private matchEndpoint(\r\n url: string,\r\n method: HttpMethod\r\n ): EndpointConfig | null {\r\n // 移除查询参数\r\n const path = url.split('?')[0];\r\n\r\n // 移除前缀\r\n const prefix = this.options.server?.prefix || '';\r\n const cleanPath = prefix ? path.replace(new RegExp(`^${prefix}`), '') : path;\r\n\r\n for (const endpoint of this.endpoints) {\r\n // 检查是否禁用\r\n if (endpoint.enabled === false) continue;\r\n\r\n // 检查方法\r\n if (endpoint.method !== method) continue;\r\n\r\n // 精确匹配\r\n if (endpoint.path === cleanPath) {\r\n return endpoint;\r\n }\r\n\r\n // 路径参数匹配\r\n if (matchPathParams(endpoint.path, cleanPath)) {\r\n return endpoint;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 解析请求\r\n */\r\n private parseRequest(req: any, url: string): any {\r\n const query = parseQueryParams(url);\r\n const path = url.split('?')[0];\r\n\r\n // 查找匹配的端点以提取路径参数\r\n const endpoint = this.matchEndpoint(path, req.method);\r\n const pathParams = endpoint\r\n ? matchPathParams(endpoint.path, path.split('?')[0])\r\n : null;\r\n\r\n return {\r\n query,\r\n params: pathParams || {},\r\n body: req.body,\r\n headers: req.headers,\r\n };\r\n }\r\n\r\n /**\r\n * 获取 Mock 数据\r\n */\r\n private async getMockData(\r\n endpoint: EndpointConfig,\r\n params: any\r\n ): Promise<any> {\r\n // 从存储获取数据\r\n let data = this.storage.get(endpoint.path, endpoint.method);\r\n\r\n if (!data) {\r\n console.warn(\r\n `[Mock] No data found for ${endpoint.method} ${endpoint.path}`\r\n );\r\n return formatResponse([], false, 'No mock data available');\r\n }\r\n\r\n // 如果是数组,应用过滤、排序、分页\r\n if (Array.isArray(data)) {\r\n // 过滤\r\n if (params.query.filter) {\r\n data = applyFilters(data, JSON.parse(params.query.filter));\r\n }\r\n\r\n // 排序\r\n if (params.query.sort) {\r\n data = applySorting(data, params.query.sort);\r\n }\r\n\r\n // 分页\r\n if (params.query.page || params.query.pageSize) {\r\n const page = parseInt(params.query.page) || 1;\r\n const pageSize = parseInt(params.query.pageSize) || 20;\r\n const result = applyPagination(data, page, pageSize);\r\n\r\n return formatResponse({\r\n list: result.data,\r\n pagination: result.pagination,\r\n });\r\n }\r\n }\r\n\r\n // 应用自定义处理\r\n if (endpoint.custom) {\r\n data = await endpoint.custom(data, params);\r\n }\r\n\r\n // 格式化响应\r\n return formatResponse(data);\r\n }\r\n\r\n /**\r\n * 添加端点\r\n */\r\n addEndpoint(endpoint: EndpointConfig): void {\r\n this.endpoints.push(endpoint);\r\n }\r\n\r\n /**\r\n * 移除端点\r\n */\r\n removeEndpoint(path: string, method: HttpMethod): void {\r\n this.endpoints = this.endpoints.filter(\r\n (e) => !(e.path === path && e.method === method)\r\n );\r\n }\r\n\r\n /**\r\n * 获取所有端点\r\n */\r\n getEndpoints(): EndpointConfig[] {\r\n return this.endpoints;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACIA,gBAAe;AACf,kBAAiB;AAGV,IAAM,cAAN,MAAkB;AAAA,EAKvB,YAAY,UAA+C,CAAC,GAAG;AAC7D,SAAK,aAAa,QAAQ,OAAO;AACjC,SAAK,UAAU,QAAQ,YAAY;AACnC,SAAK,QAAQ,oBAAI,IAAI;AAGrB,QAAI,KAAK,WAAW,CAAC,UAAAA,QAAG,WAAW,KAAK,UAAU,GAAG;AACnD,gBAAAA,QAAG,UAAU,KAAK,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,IACnD;AAGA,SAAK,KAAK;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAO,UAAkB,QAA4B;AAC3D,WAAO,GAAG,MAAM,IAAI,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,UAAkB,QAA4B;AAChE,UAAM,YAAY,SACf,QAAQ,OAAO,EAAE,EACjB,QAAQ,OAAO,GAAG,EAClB,QAAQ,MAAM,GAAG;AACpB,WAAO,GAAG,MAAM,IAAI,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAkB,SAAqB,OAAY;AACrD,UAAM,MAAM,KAAK,OAAO,UAAU,MAAM;AACxC,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IACE,UACA,QACA,MACA,UACM;AACN,UAAM,MAAM,KAAK,OAAO,UAAU,MAAM;AAExC,UAAM,QAAuB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,QACR,OAAO,MAAM,QAAQ,IAAI,IAAI,KAAK,SAAS;AAAA,QAC3C,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC,SAAS;AAAA,QACT,MAAM,OAAO;AAAA,QACb,GAAG;AAAA,MACL;AAAA,IACF;AAEA,SAAK,MAAM,IAAI,KAAK,KAAK;AAGzB,QAAI,KAAK,SAAS;AAChB,WAAK,KAAK,UAAU,QAAQ,KAAK;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAkB,SAAqB,OAAa;AACzD,UAAM,MAAM,KAAK,OAAO,UAAU,MAAM;AACxC,SAAK,MAAM,OAAO,GAAG;AAGrB,QAAI,KAAK,SAAS;AAChB,YAAM,WAAW,KAAK,YAAY,UAAU,MAAM;AAClD,YAAM,WAAW,YAAAC,QAAK,KAAK,KAAK,YAAY,QAAQ;AACpD,UAAI,UAAAD,QAAG,WAAW,QAAQ,GAAG;AAC3B,kBAAAA,QAAG,WAAW,QAAQ;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,MAAM;AAGjB,QAAI,KAAK,WAAW,UAAAA,QAAG,WAAW,KAAK,UAAU,GAAG;AAClD,YAAM,QAAQ,UAAAA,QAAG,YAAY,KAAK,UAAU;AAC5C,iBAAW,QAAQ,OAAO;AACxB,kBAAAA,QAAG,WAAW,YAAAC,QAAK,KAAK,KAAK,YAAY,IAAI,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAA0B;AACxB,WAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKQ,KACN,UACA,QACA,OACM;AACN,UAAM,WAAW,KAAK,YAAY,UAAU,MAAM;AAClD,UAAM,WAAW,YAAAA,QAAK,KAAK,KAAK,YAAY,QAAQ;AAEpD,cAAAD,QAAG,cAAc,UAAU,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,OAAO;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAa;AACnB,QAAI,CAAC,KAAK,WAAW,CAAC,UAAAA,QAAG,WAAW,KAAK,UAAU,GAAG;AACpD;AAAA,IACF;AAEA,UAAM,QAAQ,UAAAA,QAAG,YAAY,KAAK,UAAU;AAE5C,eAAW,QAAQ,OAAO;AACxB,UAAI,CAAC,KAAK,SAAS,OAAO,EAAG;AAE7B,UAAI;AACF,cAAM,WAAW,YAAAC,QAAK,KAAK,KAAK,YAAY,IAAI;AAChD,cAAM,UAAU,UAAAD,QAAG,aAAa,UAAU,OAAO;AACjD,cAAM,QAAuB,KAAK,MAAM,OAAO;AAE/C,cAAM,MAAM,KAAK,OAAO,MAAM,UAAU,MAAM,MAAM;AACpD,aAAK,MAAM,IAAI,KAAK,KAAK;AAAA,MAC3B,SAAS,OAAO;AACd,gBAAQ,KAAK,iCAAiC,IAAI,KAAK,KAAK;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,YAA0B;AAC/B,UAAM,UAAU,KAAK,OAAO;AAC5B,cAAAA,QAAG,cAAc,YAAY,KAAK,UAAU,SAAS,MAAM,CAAC,GAAG,OAAO;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAAyB;AAC9B,UAAM,UAAU,UAAAA,QAAG,aAAa,WAAW,OAAO;AAClD,UAAM,UAA2B,KAAK,MAAM,OAAO;AAEnD,eAAW,SAAS,SAAS;AAC3B,YAAM,MAAM,KAAK,OAAO,MAAM,UAAU,MAAM,MAAM;AACpD,WAAK,MAAM,IAAI,KAAK,KAAK;AAEzB,UAAI,KAAK,SAAS;AAChB,aAAK,KAAK,MAAM,UAAU,MAAM,QAAQ,KAAK;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AACF;;;ACzLA,oBAA2B;AAC3B,sBAA4C;AAOrC,IAAM,oBAAN,MAAwB;AAAA,EAG7B,YAAY,SAA4D;AACtE,SAAK,MAAM,IAAI,yBAAW;AAAA,MACxB,cAAc,QAAQ;AAAA,MACtB,eAAe;AAAA,QACb,SAAS,QAAQ;AAAA,MACnB;AAAA,MACA,WAAW,QAAQ;AAAA,MACnB,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,SAA0C;AACvD,UAAM,EAAE,MAAM,OAAO,QAAQ,QAAQ,IAAI;AAGzC,UAAM,SAAS,KAAK,YAAY,MAAM,OAAO,QAAQ,OAAO;AAG5D,UAAM,WAAW,MAAM,KAAK,OAAO,MAAM;AAGzC,WAAO,KAAK,cAAc,UAAU,KAAK,OAAO;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKQ,YACN,MACA,OACA,QACA,SACQ;AACR,UAAM,aAAa,KAAK,WACrB,IAAI,CAAC,MAAM,KAAK,eAAe,CAAC,CAAC,EACjC,KAAK,IAAI;AAEZ,WAAO;AAAA;AAAA;AAAA,QAGH,KAAK,IAAI;AAAA,QACT,WAAW,UAAU,OAAO,IAAI;AAAA,QAChC,KAAK;AAAA,QAEP,YAAY,SACR,gBACA,YAAY,SACZ,SACA,SACN;AAAA;AAAA;AAAA,EAGF,UAAU;AAAA;AAAA;AAAA,QAGJ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBX,KAAK;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,MAAkC;AACvD,QAAI,OAAO,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI;AAEvC,QAAI,KAAK,SAAS;AAChB,cAAQ,OAAO,KAAK,OAAO;AAAA,IAC7B;AAEA,QAAI,KAAK,aAAa;AACpB,YAAM,cAAc,CAAC;AACrB,UAAI,KAAK,YAAY,QAAQ,QAAW;AACtC,oBAAY,KAAK,QAAQ,KAAK,YAAY,GAAG,EAAE;AAAA,MACjD;AACA,UAAI,KAAK,YAAY,QAAQ,QAAW;AACtC,oBAAY,KAAK,QAAQ,KAAK,YAAY,GAAG,EAAE;AAAA,MACjD;AACA,UAAI,KAAK,YAAY,QAAQ;AAC3B,oBAAY,KAAK,QAAQ;AAAA,MAC3B;AACA,UAAI,KAAK,YAAY,MAAM;AACzB,oBAAY,KAAK,UAAU,KAAK,YAAY,KAAK,KAAK,IAAI,CAAC,GAAG;AAAA,MAChE;AACA,UAAI,YAAY,SAAS,GAAG;AAC1B,gBAAQ,KAAK,YAAY,KAAK,IAAI,CAAC;AAAA,MACrC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,OAAO,QAAiC;AACpD,QAAI;AACF,YAAM,WAAW;AAAA,QACf,IAAI;AAAA,UACF;AAAA,QACF;AAAA,QACA,IAAI,6BAAa,MAAM;AAAA,MACzB;AAEA,YAAM,WAAW,MAAM,KAAK,IAAI,OAAO,QAAQ;AAC/C,aAAO,SAAS;AAAA,IAClB,SAAS,OAAY;AACnB,cAAQ,MAAM,kBAAkB,MAAM,OAAO;AAC7C,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,UAAkB,UAAmB,MAAW;AACpE,QAAI;AAEF,UAAI,kBAAkB,SAAS,KAAK;AAGpC,wBAAkB,gBAAgB,QAAQ,gBAAgB,EAAE;AAC5D,wBAAkB,gBAAgB,QAAQ,WAAW,EAAE;AAGvD,wBAAkB,gBAAgB,QAAQ,WAAW,EAAE;AAGvD,YAAM,YAAY,gBAAgB,MAAM,2BAA2B;AACnE,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AAEA,YAAM,OAAO,KAAK,MAAM,UAAU,CAAC,CAAC;AAEpC,aAAO,UAAU,OAAO,KAAK,CAAC;AAAA,IAChC,SAAS,OAAY;AACnB,cAAQ,MAAM,iBAAiB,MAAM,OAAO;AAC5C,cAAQ,MAAM,SAAS,QAAQ;AAC/B,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,MAAsB,OAAsB;AACxD,UAAM,OAAO,CAAC;AAEd,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,OAAY,CAAC;AAEnB,iBAAW,QAAQ,KAAK,YAAY;AAClC,aAAK,KAAK,IAAI,IAAI,KAAK,mBAAmB,MAAM,CAAC;AAAA,MACnD;AAEA,WAAK,KAAK,IAAI;AAAA,IAChB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,MAA0B,OAAoB;AACvE,UAAM,EAAE,MAAM,YAAY,IAAI;AAG9B,QAAI,aAAa,MAAM;AACrB,aAAO,YAAY,KAAK,QAAQ,YAAY,KAAK,MAAM;AAAA,IACzD;AAGA,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,cAAM,MAAM,aAAa,OAAO;AAChC,cAAM,MAAM,aAAa,OAAO;AAChC,eAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;AAAA,MAEvD,KAAK;AACH,eAAO,GAAG,KAAK,IAAI,IAAI,QAAQ,CAAC;AAAA,MAElC,KAAK;AACH,eAAO,KAAK,OAAO,IAAI;AAAA,MAEzB,KAAK;AACH,gBAAO,oBAAI,KAAK,GAAE,YAAY;AAAA,MAEhC;AACE,eAAO;AAAA,IACX;AAAA,EACF;AACF;;;AC1NO,SAAS,MAAM,IAA8C;AAClE,QAAM,YAAY,MAAM,QAAQ,EAAE,IAC9B,KAAK,OAAO,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,IACtC;AAEJ,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,SAAS,CAAC;AAChE;AAOO,SAAS,gBACd,SACAE,OAC+B;AAC/B,QAAM,eAAe,QAAQ,MAAM,GAAG;AACtC,QAAM,YAAYA,MAAK,MAAM,GAAG;AAEhC,MAAI,aAAa,WAAW,UAAU,QAAQ;AAC5C,WAAO;AAAA,EACT;AAEA,QAAM,SAAiC,CAAC;AAExC,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,UAAM,cAAc,aAAa,CAAC;AAClC,UAAM,WAAW,UAAU,CAAC;AAE5B,QAAI,YAAY,WAAW,GAAG,GAAG;AAE/B,YAAM,YAAY,YAAY,MAAM,CAAC;AACrC,aAAO,SAAS,IAAI;AAAA,IACtB,WAAW,gBAAgB,UAAU;AAEnC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,iBAAiB,KAAkC;AACjE,QAAM,cAAc,IAAI,MAAM,GAAG,EAAE,CAAC;AACpC,MAAI,CAAC,YAAa,QAAO,CAAC;AAE1B,QAAM,SAA8B,CAAC;AACrC,QAAM,QAAQ,YAAY,MAAM,GAAG;AAEnC,aAAW,QAAQ,OAAO;AACxB,UAAM,CAAC,KAAK,KAAK,IAAI,KAAK,MAAM,GAAG;AACnC,WAAO,mBAAmB,GAAG,CAAC,IAAI,mBAAmB,SAAS,EAAE;AAAA,EAClE;AAEA,SAAO;AACT;AAmBO,SAAS,aAAa,MAAa,SAAqC;AAC7E,MAAI,CAAC,WAAW,OAAO,KAAK,OAAO,EAAE,WAAW,GAAG;AACjD,WAAO;AAAA,EACT;AAEA,SAAO,KAAK,OAAO,CAAC,SAAS;AAC3B,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,UAAI,KAAK,GAAG,MAAM,OAAO;AACvB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAKO,SAAS,aACd,MACA,MACO;AACP,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,aACJ,OAAO,SAAS,WACZ,EAAE,OAAO,MAAM,OAAO,MAAe,IACrC;AAEN,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,UAAM,SAAS,EAAE,WAAW,KAAK;AACjC,UAAM,SAAS,EAAE,WAAW,KAAK;AAEjC,QAAI,SAAS,OAAQ,QAAO,WAAW,UAAU,QAAQ,KAAK;AAC9D,QAAI,SAAS,OAAQ,QAAO,WAAW,UAAU,QAAQ,IAAI;AAC7D,WAAO;AAAA,EACT,CAAC;AACH;AAKO,SAAS,gBACd,MACA,OAAe,GACf,WAAmB,IASnB;AACA,QAAM,QAAQ,KAAK;AACnB,QAAM,aAAa,KAAK,KAAK,QAAQ,QAAQ;AAC7C,QAAM,SAAS,OAAO,KAAK;AAC3B,QAAM,MAAM,QAAQ;AAEpB,SAAO;AAAA,IACL,MAAM,KAAK,MAAM,OAAO,GAAG;AAAA,IAC3B,YAAY;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,eACd,MACA,UAAmB,MACnB,SACA;AACA,SAAO;AAAA,IACL,MAAM,UAAU,MAAM;AAAA,IACtB;AAAA,IACA,SAAS,YAAY,UAAU,YAAY;AAAA,EAC7C;AACF;;;ACtJO,IAAM,aAAN,MAAiB;AAAA,EAKtB,YAAY,SAAsB,SAA+B;AAC/D,SAAK,UAAU;AACf,SAAK,YAAY,QAAQ,aAAa,CAAC;AACvC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,QAA6B;AAC3C,WAAO,YAAY,IAAI,OAAO,KAAK,KAAK,SAAS;AAC/C,YAAM,MAAM,IAAI,OAAO;AACvB,YAAM,SAAS,IAAI;AAGnB,YAAM,WAAW,KAAK,cAAc,KAAK,MAAM;AAE/C,UAAI,CAAC,UAAU;AACb,eAAO,KAAK;AAAA,MACd;AAEA,UAAI;AAEF,cAAM,SAAS,KAAK,aAAa,KAAK,GAAG;AAGzC,cAAM,OAAO,MAAM,KAAK,YAAY,UAAU,MAAM;AAGpD,YAAI,KAAK,QAAQ,QAAQ,OAAO;AAC9B,gBAAM,MAAM,KAAK,QAAQ,OAAO,KAAK;AAAA,QACvC;AAGA,YAAI,UAAU,gBAAgB,kBAAkB;AAChD,YAAI,KAAK,QAAQ,QAAQ,MAAM;AAC7B,cAAI,UAAU,+BAA+B,GAAG;AAChD,cAAI,UAAU,gCAAgC,GAAG;AACjD,cAAI,UAAU,gCAAgC,GAAG;AAAA,QACnD;AAGA,YAAI,aAAa;AACjB,YAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAG5B,YAAI,KAAK,QAAQ,QAAQ,MAAM;AAC7B,kBAAQ,IAAI,UAAU,MAAM,IAAI,GAAG,MAAM,OAAO,OAAO,OAAO,EAAE;AAAA,QAClE;AAAA,MACF,SAAS,OAAY;AACnB,gBAAQ,MAAM,yBAAyB,MAAM,IAAI,GAAG,KAAK,KAAK;AAC9D,YAAI,aAAa;AACjB,YAAI;AAAA,UACF,KAAK,UAAU;AAAA,YACb,MAAM;AAAA,YACN,SAAS,MAAM;AAAA,UACjB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAED,YAAQ,IAAI,kBAAkB;AAC9B,YAAQ,IAAI,UAAU,KAAK,UAAU,MAAM;AAAA,CAAQ;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKQ,cACN,KACA,QACuB;AAEvB,UAAMC,QAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AAG7B,UAAM,SAAS,KAAK,QAAQ,QAAQ,UAAU;AAC9C,UAAM,YAAY,SAASA,MAAK,QAAQ,IAAI,OAAO,IAAI,MAAM,EAAE,GAAG,EAAE,IAAIA;AAExE,eAAW,YAAY,KAAK,WAAW;AAErC,UAAI,SAAS,YAAY,MAAO;AAGhC,UAAI,SAAS,WAAW,OAAQ;AAGhC,UAAI,SAAS,SAAS,WAAW;AAC/B,eAAO;AAAA,MACT;AAGA,UAAI,gBAAgB,SAAS,MAAM,SAAS,GAAG;AAC7C,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,KAAU,KAAkB;AAC/C,UAAM,QAAQ,iBAAiB,GAAG;AAClC,UAAMA,QAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AAG7B,UAAM,WAAW,KAAK,cAAcA,OAAM,IAAI,MAAM;AACpD,UAAM,aAAa,WACf,gBAAgB,SAAS,MAAMA,MAAK,MAAM,GAAG,EAAE,CAAC,CAAC,IACjD;AAEJ,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,cAAc,CAAC;AAAA,MACvB,MAAM,IAAI;AAAA,MACV,SAAS,IAAI;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YACZ,UACA,QACc;AAEd,QAAI,OAAO,KAAK,QAAQ,IAAI,SAAS,MAAM,SAAS,MAAM;AAE1D,QAAI,CAAC,MAAM;AACT,cAAQ;AAAA,QACN,4BAA4B,SAAS,MAAM,IAAI,SAAS,IAAI;AAAA,MAC9D;AACA,aAAO,eAAe,CAAC,GAAG,OAAO,wBAAwB;AAAA,IAC3D;AAGA,QAAI,MAAM,QAAQ,IAAI,GAAG;AAEvB,UAAI,OAAO,MAAM,QAAQ;AACvB,eAAO,aAAa,MAAM,KAAK,MAAM,OAAO,MAAM,MAAM,CAAC;AAAA,MAC3D;AAGA,UAAI,OAAO,MAAM,MAAM;AACrB,eAAO,aAAa,MAAM,OAAO,MAAM,IAAI;AAAA,MAC7C;AAGA,UAAI,OAAO,MAAM,QAAQ,OAAO,MAAM,UAAU;AAC9C,cAAM,OAAO,SAAS,OAAO,MAAM,IAAI,KAAK;AAC5C,cAAM,WAAW,SAAS,OAAO,MAAM,QAAQ,KAAK;AACpD,cAAM,SAAS,gBAAgB,MAAM,MAAM,QAAQ;AAEnD,eAAO,eAAe;AAAA,UACpB,MAAM,OAAO;AAAA,UACb,YAAY,OAAO;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF;AAGA,QAAI,SAAS,QAAQ;AACnB,aAAO,MAAM,SAAS,OAAO,MAAM,MAAM;AAAA,IAC3C;AAGA,WAAO,eAAe,IAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,UAAgC;AAC1C,SAAK,UAAU,KAAK,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAeA,OAAc,QAA0B;AACrD,SAAK,YAAY,KAAK,UAAU;AAAA,MAC9B,CAAC,MAAM,EAAE,EAAE,SAASA,SAAQ,EAAE,WAAW;AAAA,IAC3C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AACF;;;AJlNO,SAAS,0BACd,UAAgC,CAAC,GACzB;AACR,QAAM;AAAA,IACJ,SAAS,QAAQ,IAAI,kBAAkB;AAAA,IACvC,SAAS,QAAQ,IAAI,kBAAkB;AAAA,IACvC,QAAQ,QAAQ,IAAI,gBAAgB;AAAA,IACpC,UAAU;AAAA,IACV,eAAe;AAAA,IACf,aAAa;AAAA,MACX,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,IACA,SAAS,iBAAiB;AAAA,MACxB,KAAK;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,IACA,SAAS;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF,IAAI;AAGJ,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,UAAU,IAAI,YAAY,cAAc;AAC9C,QAAM,YAAY,IAAI,kBAAkB,EAAE,QAAQ,QAAQ,MAAM,CAAC;AACjE,QAAM,SAAS,IAAI,WAAW,SAAS,OAAO;AAE9C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IAET,eAAe,QAAQ;AACrB,UAAI,OAAO,SAAS;AAClB,gBAAQ,IAAI,4BAA4B;AACxC,gBAAQ,IAAI,YAAY,eAAe,GAAG,EAAE;AAC5C,gBAAQ,IAAI,YAAY,WAAW,MAAM,EAAE;AAC3C,gBAAQ,IAAI,YAAY,WAAW,KAAK,EAAE;AAC1C,gBAAQ,IAAI,eAAe,SAAS,QAAQ,KAAK,EAAE;AACnD,gBAAQ,IAAI,YAAY,QAAQ,WAAW,UAAU,CAAC,EAAE;AAAA,MAC1D;AAAA,IACF;AAAA,IAEA,MAAM,aAAa;AAEjB,UAAI,gBAAgB,QAAQ,WAAW;AACrC,YAAI,OAAO,SAAS;AAClB,kBAAQ,IAAI,0BAA0B;AAAA,QACxC;AAEA,mBAAW,YAAY,QAAQ,WAAW;AAExC,gBAAM,eAAe,QAAQ,IAAI,SAAS,MAAM,SAAS,MAAM;AAC/D,cAAI,cAAc;AAChB,gBAAI,OAAO,SAAS;AAClB,sBAAQ;AAAA,gBACN,UAAU,SAAS,MAAM,IAAI,SAAS,IAAI;AAAA,cAC5C;AAAA,YACF;AACA;AAAA,UACF;AAEA,cAAI;AACF,gBAAI,OAAO,SAAS;AAClB,sBAAQ,IAAI,SAAS,SAAS,MAAM,IAAI,SAAS,IAAI,KAAK;AAAA,YAC5D;AAGA,kBAAM,iBAAiB,oBAAoB,SAAS,QAAQ;AAG5D,kBAAM,QAAQ,SAAS,SAAS,WAAW,SAAS;AACpD,gBAAI;AAGJ,gBAAI,WAAW,YAAY,QAAQ;AAEjC,qBAAO,UAAU,cAAc,gBAAgB,KAAK;AAAA,YACtD,OAAO;AAEL,qBAAO,MAAM,UAAU,SAAS;AAAA,gBAC9B,MAAM;AAAA,gBACN;AAAA,gBACA,QAAQ,WAAW,UAAU;AAAA,gBAC7B,SAAS,WAAW,WAAW;AAAA,cACjC,CAAC;AAAA,YACH;AAGA,oBAAQ,IAAI,SAAS,MAAM,SAAS,QAAQ,MAAM;AAAA,cAChD,MAAM,SAAS;AAAA,YACjB,CAAC;AAED,gBAAI,OAAO,SAAS;AAClB,sBAAQ;AAAA,gBACN,SAAS,KAAK,SAAS,SAAS,MAAM,IAAI,SAAS,IAAI;AAAA,cACzD;AAAA,YACF;AAAA,UACF,SAAS,OAAY;AACnB,oBAAQ;AAAA,cACN,UAAU,SAAS,MAAM,IAAI,SAAS,IAAI;AAAA,cAC1C,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,YAAI,OAAO,SAAS;AAClB,kBAAQ,IAAI,mBAAmB;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAAA,IAEA,gBAAgB,YAAY;AAE1B,aAAO,gBAAgB,UAAU;AAAA,IACnC;AAAA,EACF;AACF;AAMA,SAAS,oBAAoB,SAAkD;AAC7E,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,EACT;AAGA,QAAM,UAAU,QAAQ,SAAS,IAAI;AACrC,QAAM,WAAW,UAAU,QAAQ,MAAM,GAAG,EAAE,IAAI;AAGlD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb;AAAA,EACF;AACF;AASA,IAAO,gBAAQ;","names":["fs","path","path","path"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
1
|
// src/storage.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
5
4
|
var MockStorage = class {
|
|
6
5
|
constructor(options = {}) {
|
|
7
6
|
this.storageDir = options.dir || "mock-data";
|
|
@@ -140,11 +139,19 @@ var MockStorage = class {
|
|
|
140
139
|
};
|
|
141
140
|
|
|
142
141
|
// src/generator.ts
|
|
142
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
143
|
+
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
|
|
143
144
|
var MockDataGenerator = class {
|
|
144
145
|
constructor(options) {
|
|
145
|
-
this.
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
this.llm = new ChatOpenAI({
|
|
147
|
+
openAIApiKey: options.apiKey,
|
|
148
|
+
configuration: {
|
|
149
|
+
baseURL: options.apiUrl
|
|
150
|
+
},
|
|
151
|
+
modelName: options.model,
|
|
152
|
+
temperature: 0.7,
|
|
153
|
+
maxTokens: 4e3
|
|
154
|
+
});
|
|
148
155
|
}
|
|
149
156
|
/**
|
|
150
157
|
* 生成 Mock 数据
|
|
@@ -161,34 +168,34 @@ var MockDataGenerator = class {
|
|
|
161
168
|
buildPrompt(type, count, locale, quality) {
|
|
162
169
|
const properties = type.properties.map((p) => this.formatProperty(p)).join("\n");
|
|
163
170
|
return `
|
|
164
|
-
|
|
171
|
+
你是一个专业的 Mock 数据生成器。请根据以下类型定义生成真实、合理的测试数据。
|
|
165
172
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
173
|
+
类型名称: ${type.name}
|
|
174
|
+
数据语言: ${locale === "zh-CN" ? "中文" : "英文"}
|
|
175
|
+
数据数量: ${count}
|
|
176
|
+
质量要求: ${quality === "high" ? "高质量(真实业务数据)" : quality === "fast" ? "快速生成" : "平衡质量和速度"}
|
|
170
177
|
|
|
171
|
-
|
|
178
|
+
类型定义:
|
|
172
179
|
${properties}
|
|
173
180
|
|
|
174
|
-
|
|
175
|
-
1.
|
|
176
|
-
2.
|
|
177
|
-
3.
|
|
178
|
-
4.
|
|
179
|
-
5.
|
|
180
|
-
6.
|
|
181
|
+
要求:
|
|
182
|
+
1. 生成 ${count} 条数据
|
|
183
|
+
2. 数据要符合业务逻辑和真实场景
|
|
184
|
+
3. 字段值要合理(如价格不能为负数,年龄在合理范围)
|
|
185
|
+
4. 日期格式使用 ISO 8601
|
|
186
|
+
5. 返回 JSON 数组格式,不要包含任何其他文字
|
|
187
|
+
6. 理解字段语义,生成真实数据(如 userName 生成真实姓名)
|
|
181
188
|
|
|
182
|
-
|
|
189
|
+
示例格式:
|
|
183
190
|
[
|
|
184
191
|
{
|
|
185
192
|
"id": 1,
|
|
186
|
-
"name": "
|
|
193
|
+
"name": "张三",
|
|
187
194
|
...
|
|
188
195
|
}
|
|
189
196
|
]
|
|
190
197
|
|
|
191
|
-
|
|
198
|
+
请生成数据:
|
|
192
199
|
`.trim();
|
|
193
200
|
}
|
|
194
201
|
/**
|
|
@@ -224,30 +231,16 @@ ${properties}
|
|
|
224
231
|
*/
|
|
225
232
|
async callAI(prompt) {
|
|
226
233
|
try {
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
messages: [
|
|
236
|
-
{
|
|
237
|
-
role: "user",
|
|
238
|
-
content: prompt
|
|
239
|
-
}
|
|
240
|
-
],
|
|
241
|
-
temperature: 0.7
|
|
242
|
-
})
|
|
243
|
-
});
|
|
244
|
-
if (!response.ok) {
|
|
245
|
-
throw new Error(`AI API error: ${response.statusText}`);
|
|
246
|
-
}
|
|
247
|
-
const data = await response.json();
|
|
248
|
-
return data.choices[0].message.content;
|
|
234
|
+
const messages = [
|
|
235
|
+
new SystemMessage(
|
|
236
|
+
"你是一个专业的 Mock 数据生成器,擅长生成真实、合理的测试数据。"
|
|
237
|
+
),
|
|
238
|
+
new HumanMessage(prompt)
|
|
239
|
+
];
|
|
240
|
+
const response = await this.llm.invoke(messages);
|
|
241
|
+
return response.content;
|
|
249
242
|
} catch (error) {
|
|
250
|
-
console.error("
|
|
243
|
+
console.error("❌ AI API 调用失败:", error.message);
|
|
251
244
|
throw error;
|
|
252
245
|
}
|
|
253
246
|
}
|
|
@@ -267,8 +260,8 @@ ${properties}
|
|
|
267
260
|
const data = JSON.parse(jsonMatch[0]);
|
|
268
261
|
return isArray ? data : data[0];
|
|
269
262
|
} catch (error) {
|
|
270
|
-
console.error("
|
|
271
|
-
console.error("
|
|
263
|
+
console.error("❌ 解析 AI 响应失败:", error.message);
|
|
264
|
+
console.error("响应内容:", response);
|
|
272
265
|
throw error;
|
|
273
266
|
}
|
|
274
267
|
}
|
|
@@ -426,7 +419,7 @@ var MockServer = class {
|
|
|
426
419
|
res.statusCode = 200;
|
|
427
420
|
res.end(JSON.stringify(data));
|
|
428
421
|
if (this.options.output?.logs) {
|
|
429
|
-
console.log(`[Mock] ${method} ${url}
|
|
422
|
+
console.log(`[Mock] ${method} ${url} → ${data ? "OK" : "Empty"}`);
|
|
430
423
|
}
|
|
431
424
|
} catch (error) {
|
|
432
425
|
console.error(`[Mock] Error handling ${method} ${url}:`, error);
|
|
@@ -439,8 +432,8 @@ var MockServer = class {
|
|
|
439
432
|
);
|
|
440
433
|
}
|
|
441
434
|
});
|
|
442
|
-
console.log("\n
|
|
443
|
-
console.log(
|
|
435
|
+
console.log("\n🎭 Mock 服务器已启动");
|
|
436
|
+
console.log(`📍 已注册 ${this.endpoints.length} 个端点
|
|
444
437
|
`);
|
|
445
438
|
}
|
|
446
439
|
/**
|
|
@@ -568,34 +561,32 @@ function vitePluginAIMockGenerator(options = {}) {
|
|
|
568
561
|
enforce: "pre",
|
|
569
562
|
configResolved(config) {
|
|
570
563
|
if (output.console) {
|
|
571
|
-
console.log("\n
|
|
572
|
-
console.log(
|
|
573
|
-
console.log(
|
|
574
|
-
console.log(
|
|
575
|
-
console.log(
|
|
576
|
-
console.log(
|
|
577
|
-
`\u{1F4CD} \u7AEF\u70B9\u6570\u91CF: ${options.endpoints?.length || 0}`
|
|
578
|
-
);
|
|
564
|
+
console.log("\n🤖 AI Mock Generator 已启动");
|
|
565
|
+
console.log(`📂 存储目录: ${storageOptions.dir}`);
|
|
566
|
+
console.log(`🌍 数据语言: ${generation.locale}`);
|
|
567
|
+
console.log(`📊 默认数量: ${generation.count}`);
|
|
568
|
+
console.log(`🔑 API Key: ${apiKey ? "已配置" : "未配置"}`);
|
|
569
|
+
console.log(`📍 端点数量: ${options.endpoints?.length || 0}`);
|
|
579
570
|
}
|
|
580
571
|
},
|
|
581
572
|
async buildStart() {
|
|
582
573
|
if (autoGenerate && options.endpoints) {
|
|
583
574
|
if (output.console) {
|
|
584
|
-
console.log("\n
|
|
575
|
+
console.log("\n🔄 开始自动生成 Mock 数据...\n");
|
|
585
576
|
}
|
|
586
577
|
for (const endpoint of options.endpoints) {
|
|
587
578
|
const existingData = storage.get(endpoint.path, endpoint.method);
|
|
588
579
|
if (existingData) {
|
|
589
580
|
if (output.console) {
|
|
590
581
|
console.log(
|
|
591
|
-
|
|
582
|
+
`⏭️ 跳过 ${endpoint.method} ${endpoint.path} (已有数据)`
|
|
592
583
|
);
|
|
593
584
|
}
|
|
594
585
|
continue;
|
|
595
586
|
}
|
|
596
587
|
try {
|
|
597
588
|
if (output.console) {
|
|
598
|
-
console.log(
|
|
589
|
+
console.log(`🎲 生成 ${endpoint.method} ${endpoint.path}...`);
|
|
599
590
|
}
|
|
600
591
|
const typeDefinition = parseTypeDefinition(endpoint.response);
|
|
601
592
|
const count = endpoint.count || generation.count || 20;
|
|
@@ -615,18 +606,18 @@ function vitePluginAIMockGenerator(options = {}) {
|
|
|
615
606
|
});
|
|
616
607
|
if (output.console) {
|
|
617
608
|
console.log(
|
|
618
|
-
|
|
609
|
+
`✅ 已生成 ${count} 条数据: ${endpoint.method} ${endpoint.path}`
|
|
619
610
|
);
|
|
620
611
|
}
|
|
621
612
|
} catch (error) {
|
|
622
613
|
console.error(
|
|
623
|
-
|
|
614
|
+
`❌ 生成失败 ${endpoint.method} ${endpoint.path}:`,
|
|
624
615
|
error.message
|
|
625
616
|
);
|
|
626
617
|
}
|
|
627
618
|
}
|
|
628
619
|
if (output.console) {
|
|
629
|
-
console.log("\n
|
|
620
|
+
console.log("\n✨ Mock 数据生成完成\n");
|
|
630
621
|
}
|
|
631
622
|
}
|
|
632
623
|
},
|
|
@@ -647,7 +638,12 @@ function parseTypeDefinition(typeStr) {
|
|
|
647
638
|
isArray
|
|
648
639
|
};
|
|
649
640
|
}
|
|
650
|
-
|
|
651
|
-
export {
|
|
652
|
-
|
|
641
|
+
var index_default = vitePluginAIMockGenerator;
|
|
642
|
+
export {
|
|
643
|
+
MockDataGenerator,
|
|
644
|
+
MockServer,
|
|
645
|
+
MockStorage,
|
|
646
|
+
index_default as default,
|
|
647
|
+
vitePluginAIMockGenerator
|
|
648
|
+
};
|
|
653
649
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storage.ts","../src/generator.ts","../src/utils.ts","../src/server.ts","../src/index.ts"],"names":["path"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * AI Mock Generator - 数据存储\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type { MockDataStore, HttpMethod } from './types';\r\n\r\nexport class MockStorage {\r\n private storageDir: string;\r\n private cache: Map<string, MockDataStore>;\r\n private persist: boolean;\r\n\r\n constructor(options: { dir?: string; persist?: boolean } = {}) {\r\n this.storageDir = options.dir || 'mock-data';\r\n this.persist = options.persist !== false;\r\n this.cache = new Map();\r\n\r\n // 确保存储目录存在\r\n if (this.persist && !fs.existsSync(this.storageDir)) {\r\n fs.mkdirSync(this.storageDir, { recursive: true });\r\n }\r\n\r\n // 加载已有数据\r\n this.load();\r\n }\r\n\r\n /**\r\n * 生成存储 key\r\n */\r\n private getKey(endpoint: string, method: HttpMethod): string {\r\n return `${method}:${endpoint}`;\r\n }\r\n\r\n /**\r\n * 生成文件名\r\n */\r\n private getFileName(endpoint: string, method: HttpMethod): string {\r\n const sanitized = endpoint\r\n .replace(/^\\//, '')\r\n .replace(/\\//g, '_')\r\n .replace(/:/g, '_');\r\n return `${method}_${sanitized}.json`;\r\n }\r\n\r\n /**\r\n * 获取数据\r\n */\r\n get(endpoint: string, method: HttpMethod = 'GET'): any {\r\n const key = this.getKey(endpoint, method);\r\n const store = this.cache.get(key);\r\n return store?.data;\r\n }\r\n\r\n /**\r\n * 设置数据\r\n */\r\n set(\r\n endpoint: string,\r\n method: HttpMethod,\r\n data: any,\r\n metadata?: Partial<MockDataStore['metadata']>\r\n ): void {\r\n const key = this.getKey(endpoint, method);\r\n\r\n const store: MockDataStore = {\r\n endpoint,\r\n method,\r\n data,\r\n metadata: {\r\n count: Array.isArray(data) ? data.length : 1,\r\n generatedAt: new Date().toISOString(),\r\n version: '1.0.0',\r\n type: typeof data,\r\n ...metadata,\r\n },\r\n };\r\n\r\n this.cache.set(key, store);\r\n\r\n // 持久化\r\n if (this.persist) {\r\n this.save(endpoint, method, store);\r\n }\r\n }\r\n\r\n /**\r\n * 删除数据\r\n */\r\n delete(endpoint: string, method: HttpMethod = 'GET'): void {\r\n const key = this.getKey(endpoint, method);\r\n this.cache.delete(key);\r\n\r\n // 删除文件\r\n if (this.persist) {\r\n const fileName = this.getFileName(endpoint, method);\r\n const filePath = path.join(this.storageDir, fileName);\r\n if (fs.existsSync(filePath)) {\r\n fs.unlinkSync(filePath);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 清空所有数据\r\n */\r\n clear(): void {\r\n this.cache.clear();\r\n\r\n // 清空目录\r\n if (this.persist && fs.existsSync(this.storageDir)) {\r\n const files = fs.readdirSync(this.storageDir);\r\n for (const file of files) {\r\n fs.unlinkSync(path.join(this.storageDir, file));\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 获取所有端点\r\n */\r\n getAll(): MockDataStore[] {\r\n return Array.from(this.cache.values());\r\n }\r\n\r\n /**\r\n * 保存到文件\r\n */\r\n private save(\r\n endpoint: string,\r\n method: HttpMethod,\r\n store: MockDataStore\r\n ): void {\r\n const fileName = this.getFileName(endpoint, method);\r\n const filePath = path.join(this.storageDir, fileName);\r\n\r\n fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * 从文件加载\r\n */\r\n private load(): void {\r\n if (!this.persist || !fs.existsSync(this.storageDir)) {\r\n return;\r\n }\r\n\r\n const files = fs.readdirSync(this.storageDir);\r\n\r\n for (const file of files) {\r\n if (!file.endsWith('.json')) continue;\r\n\r\n try {\r\n const filePath = path.join(this.storageDir, file);\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n const store: MockDataStore = JSON.parse(content);\r\n\r\n const key = this.getKey(store.endpoint, store.method);\r\n this.cache.set(key, store);\r\n } catch (error) {\r\n console.warn(`Failed to load mock data from ${file}:`, error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 导出所有数据\r\n */\r\n export(outputPath: string): void {\r\n const allData = this.getAll();\r\n fs.writeFileSync(outputPath, JSON.stringify(allData, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * 导入数据\r\n */\r\n import(inputPath: string): void {\r\n const content = fs.readFileSync(inputPath, 'utf-8');\r\n const allData: MockDataStore[] = JSON.parse(content);\r\n\r\n for (const store of allData) {\r\n const key = this.getKey(store.endpoint, store.method);\r\n this.cache.set(key, store);\r\n\r\n if (this.persist) {\r\n this.save(store.endpoint, store.method, store);\r\n }\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - 数据生成器\r\n */\r\n\r\nimport type {\r\n TypeDefinition,\r\n GenerationContext,\r\n PropertyDefinition,\r\n} from './types';\r\n\r\nexport class MockDataGenerator {\r\n private apiKey: string;\r\n private apiUrl: string;\r\n private model: string;\r\n\r\n constructor(options: { apiKey: string; apiUrl: string; model: string }) {\r\n this.apiKey = options.apiKey;\r\n this.apiUrl = options.apiUrl;\r\n this.model = options.model;\r\n }\r\n\r\n /**\r\n * 生成 Mock 数据\r\n */\r\n async generate(context: GenerationContext): Promise<any> {\r\n const { type, count, locale, quality } = context;\r\n\r\n // 构建 AI Prompt\r\n const prompt = this.buildPrompt(type, count, locale, quality);\r\n\r\n // 调用 AI API\r\n const response = await this.callAI(prompt);\r\n\r\n // 解析响应\r\n return this.parseResponse(response, type.isArray);\r\n }\r\n\r\n /**\r\n * 构建 AI Prompt\r\n */\r\n private buildPrompt(\r\n type: TypeDefinition,\r\n count: number,\r\n locale: string,\r\n quality: string\r\n ): string {\r\n const properties = type.properties\r\n .map((p) => this.formatProperty(p))\r\n .join('\\n');\r\n\r\n return `\r\n你是一个专业的 Mock 数据生成器。请根据以下类型定义生成真实、合理的测试数据。\r\n\r\n类型名称: ${type.name}\r\n数据语言: ${locale === 'zh-CN' ? '中文' : '英文'}\r\n数据数量: ${count}\r\n质量要求: ${quality === 'high' ? '高质量(真实业务数据)' : quality === 'fast' ? '快速生成' : '平衡质量和速度'}\r\n\r\n类型定义:\r\n${properties}\r\n\r\n要求:\r\n1. 生成 ${count} 条数据\r\n2. 数据要符合业务逻辑和真实场景\r\n3. 字段值要合理(如价格不能为负数,年龄在合理范围)\r\n4. 日期格式使用 ISO 8601\r\n5. 返回 JSON 数组格式,不要包含任何其他文字\r\n6. 理解字段语义,生成真实数据(如 userName 生成真实姓名)\r\n\r\n示例格式:\r\n[\r\n {\r\n \"id\": 1,\r\n \"name\": \"张三\",\r\n ...\r\n }\r\n]\r\n\r\n请生成数据:\r\n`.trim();\r\n }\r\n\r\n /**\r\n * 格式化属性\r\n */\r\n private formatProperty(prop: PropertyDefinition): string {\r\n let line = `- ${prop.name}: ${prop.type}`;\r\n\r\n if (prop.comment) {\r\n line += ` // ${prop.comment}`;\r\n }\r\n\r\n if (prop.constraints) {\r\n const constraints = [];\r\n if (prop.constraints.min !== undefined) {\r\n constraints.push(`min: ${prop.constraints.min}`);\r\n }\r\n if (prop.constraints.max !== undefined) {\r\n constraints.push(`max: ${prop.constraints.max}`);\r\n }\r\n if (prop.constraints.unique) {\r\n constraints.push('unique');\r\n }\r\n if (prop.constraints.enum) {\r\n constraints.push(`enum: [${prop.constraints.enum.join(', ')}]`);\r\n }\r\n if (constraints.length > 0) {\r\n line += ` (${constraints.join(', ')})`;\r\n }\r\n }\r\n\r\n return line;\r\n }\r\n\r\n /**\r\n * 调用 AI API\r\n */\r\n private async callAI(prompt: string): Promise<string> {\r\n try {\r\n const response = await fetch(`${this.apiUrl}/chat/completions`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n Authorization: `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: this.model,\r\n messages: [\r\n {\r\n role: 'user',\r\n content: prompt,\r\n },\r\n ],\r\n temperature: 0.7,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`AI API error: ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json();\r\n return data.choices[0].message.content;\r\n } catch (error: any) {\r\n console.error('Failed to call AI API:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 解析 AI 响应\r\n */\r\n private parseResponse(response: string, isArray: boolean = true): any {\r\n try {\r\n // 移除 markdown 代码块标记\r\n let cleanedResponse = response.trim();\r\n \r\n // 移除开头的 ```json 或 ```\r\n cleanedResponse = cleanedResponse.replace(/^```json\\s*/i, '');\r\n cleanedResponse = cleanedResponse.replace(/^```\\s*/, '');\r\n \r\n // 移除结尾的 ```\r\n cleanedResponse = cleanedResponse.replace(/\\s*```$/, '');\r\n \r\n // 提取 JSON 部分(查找数组或对象)\r\n const jsonMatch = cleanedResponse.match(/(\\[[\\s\\S]*\\]|\\{[\\s\\S]*\\})/);\r\n if (!jsonMatch) {\r\n throw new Error('No JSON array or object found in response');\r\n }\r\n\r\n const data = JSON.parse(jsonMatch[0]);\r\n\r\n return isArray ? data : data[0];\r\n } catch (error: any) {\r\n console.error('Failed to parse AI response:', error);\r\n console.error('Response:', response);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 生成基础数据(不使用 AI)\r\n */\r\n generateBasic(type: TypeDefinition, count: number): any[] {\r\n const data = [];\r\n\r\n for (let i = 0; i < count; i++) {\r\n const item: any = {};\r\n\r\n for (const prop of type.properties) {\r\n item[prop.name] = this.generateBasicValue(prop, i);\r\n }\r\n\r\n data.push(item);\r\n }\r\n\r\n return data;\r\n }\r\n\r\n /**\r\n * 生成基础值\r\n */\r\n private generateBasicValue(prop: PropertyDefinition, index: number): any {\r\n const { type, constraints } = prop;\r\n\r\n // 处理枚举\r\n if (constraints?.enum) {\r\n return constraints.enum[index % constraints.enum.length];\r\n }\r\n\r\n // 根据类型生成\r\n switch (type) {\r\n case 'number':\r\n const min = constraints?.min ?? 0;\r\n const max = constraints?.max ?? 100;\r\n return Math.floor(Math.random() * (max - min + 1)) + min;\r\n\r\n case 'string':\r\n return `${prop.name}_${index + 1}`;\r\n\r\n case 'boolean':\r\n return Math.random() > 0.5;\r\n\r\n case 'Date':\r\n return new Date().toISOString();\r\n\r\n default:\r\n return null;\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - 工具函数\r\n */\r\n\r\nimport type { HttpMethod, RequestParams } from './types';\r\n\r\n/**\r\n * 延迟函数\r\n */\r\nexport function delay(ms: number | [number, number]): Promise<void> {\r\n const delayTime = Array.isArray(ms)\r\n ? Math.random() * (ms[1] - ms[0]) + ms[0]\r\n : ms;\r\n\r\n return new Promise((resolve) => setTimeout(resolve, delayTime));\r\n}\r\n\r\n/**\r\n * 匹配路径参数\r\n * @example\r\n * matchPathParams('/api/users/:id', '/api/users/123') // { id: '123' }\r\n */\r\nexport function matchPathParams(\r\n pattern: string,\r\n path: string\r\n): Record<string, string> | null {\r\n const patternParts = pattern.split('/');\r\n const pathParts = path.split('/');\r\n\r\n if (patternParts.length !== pathParts.length) {\r\n return null;\r\n }\r\n\r\n const params: Record<string, string> = {};\r\n\r\n for (let i = 0; i < patternParts.length; i++) {\r\n const patternPart = patternParts[i];\r\n const pathPart = pathParts[i];\r\n\r\n if (patternPart.startsWith(':')) {\r\n // 路径参数\r\n const paramName = patternPart.slice(1);\r\n params[paramName] = pathPart;\r\n } else if (patternPart !== pathPart) {\r\n // 不匹配\r\n return null;\r\n }\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * 解析查询参数\r\n */\r\nexport function parseQueryParams(url: string): Record<string, any> {\r\n const queryString = url.split('?')[1];\r\n if (!queryString) return {};\r\n\r\n const params: Record<string, any> = {};\r\n const pairs = queryString.split('&');\r\n\r\n for (const pair of pairs) {\r\n const [key, value] = pair.split('=');\r\n params[decodeURIComponent(key)] = decodeURIComponent(value || '');\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * 生成唯一 ID\r\n */\r\nexport function generateId(): string {\r\n return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * 深度克隆\r\n */\r\nexport function deepClone<T>(obj: T): T {\r\n return JSON.parse(JSON.stringify(obj));\r\n}\r\n\r\n/**\r\n * 应用过滤\r\n */\r\nexport function applyFilters(data: any[], filters: Record<string, any>): any[] {\r\n if (!filters || Object.keys(filters).length === 0) {\r\n return data;\r\n }\r\n\r\n return data.filter((item) => {\r\n for (const [key, value] of Object.entries(filters)) {\r\n if (item[key] !== value) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n });\r\n}\r\n\r\n/**\r\n * 应用排序\r\n */\r\nexport function applySorting(\r\n data: any[],\r\n sort?: string | { field: string; order: 'asc' | 'desc' }\r\n): any[] {\r\n if (!sort) return data;\r\n\r\n const sortConfig =\r\n typeof sort === 'string'\r\n ? { field: sort, order: 'asc' as const }\r\n : sort;\r\n\r\n return [...data].sort((a, b) => {\r\n const aValue = a[sortConfig.field];\r\n const bValue = b[sortConfig.field];\r\n\r\n if (aValue < bValue) return sortConfig.order === 'asc' ? -1 : 1;\r\n if (aValue > bValue) return sortConfig.order === 'asc' ? 1 : -1;\r\n return 0;\r\n });\r\n}\r\n\r\n/**\r\n * 应用分页\r\n */\r\nexport function applyPagination(\r\n data: any[],\r\n page: number = 1,\r\n pageSize: number = 20\r\n): {\r\n data: any[];\r\n pagination: {\r\n page: number;\r\n pageSize: number;\r\n total: number;\r\n totalPages: number;\r\n };\r\n} {\r\n const total = data.length;\r\n const totalPages = Math.ceil(total / pageSize);\r\n const start = (page - 1) * pageSize;\r\n const end = start + pageSize;\r\n\r\n return {\r\n data: data.slice(start, end),\r\n pagination: {\r\n page,\r\n pageSize,\r\n total,\r\n totalPages,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 格式化响应\r\n */\r\nexport function formatResponse(\r\n data: any,\r\n success: boolean = true,\r\n message?: string\r\n) {\r\n return {\r\n code: success ? 200 : 500,\r\n data,\r\n message: message || (success ? 'Success' : 'Error'),\r\n };\r\n}\r\n\r\n/**\r\n * 生成随机种子\r\n */\r\nexport function generateSeed(): number {\r\n return Math.floor(Math.random() * 1000000);\r\n}\r\n\r\n/**\r\n * 设置随机种子\r\n */\r\nexport function setSeed(seed: number): void {\r\n // 简单的伪随机数生成器\r\n let currentSeed = seed;\r\n Math.random = () => {\r\n currentSeed = (currentSeed * 9301 + 49297) % 233280;\r\n return currentSeed / 233280;\r\n };\r\n}\r\n","/**\r\n * AI Mock Generator - Mock 服务器\r\n */\r\n\r\nimport type { ViteDevServer } from 'vite';\r\nimport type {\r\n EndpointConfig,\r\n HttpMethod,\r\n MockGeneratorOptions,\r\n} from './types';\r\nimport { MockStorage } from './storage';\r\nimport {\r\n delay,\r\n matchPathParams,\r\n parseQueryParams,\r\n applyFilters,\r\n applySorting,\r\n applyPagination,\r\n formatResponse,\r\n} from './utils';\r\n\r\nexport class MockServer {\r\n private storage: MockStorage;\r\n private endpoints: EndpointConfig[];\r\n private options: MockGeneratorOptions;\r\n\r\n constructor(storage: MockStorage, options: MockGeneratorOptions) {\r\n this.storage = storage;\r\n this.endpoints = options.endpoints || [];\r\n this.options = options;\r\n }\r\n\r\n /**\r\n * 配置服务器中间件\r\n */\r\n configureServer(server: ViteDevServer): void {\r\n server.middlewares.use(async (req, res, next) => {\r\n const url = req.url || '';\r\n const method = req.method as HttpMethod;\r\n\r\n // 检查是否匹配 Mock 端点\r\n const endpoint = this.matchEndpoint(url, method);\r\n\r\n if (!endpoint) {\r\n return next();\r\n }\r\n\r\n try {\r\n // 解析请求参数\r\n const params = this.parseRequest(req, url);\r\n\r\n // 获取 Mock 数据\r\n const data = await this.getMockData(endpoint, params);\r\n\r\n // 模拟延迟\r\n if (this.options.server?.delay) {\r\n await delay(this.options.server.delay);\r\n }\r\n\r\n // 设置响应头\r\n res.setHeader('Content-Type', 'application/json');\r\n if (this.options.server?.cors) {\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Allow-Methods', '*');\r\n res.setHeader('Access-Control-Allow-Headers', '*');\r\n }\r\n\r\n // 返回响应\r\n res.statusCode = 200;\r\n res.end(JSON.stringify(data));\r\n\r\n // 日志\r\n if (this.options.output?.logs) {\r\n console.log(`[Mock] ${method} ${url} → ${data ? 'OK' : 'Empty'}`);\r\n }\r\n } catch (error: any) {\r\n console.error(`[Mock] Error handling ${method} ${url}:`, error);\r\n res.statusCode = 500;\r\n res.end(\r\n JSON.stringify({\r\n code: 500,\r\n message: error.message,\r\n })\r\n );\r\n }\r\n });\r\n\r\n console.log('\\n🎭 Mock 服务器已启动');\r\n console.log(`📍 已注册 ${this.endpoints.length} 个端点\\n`);\r\n }\r\n\r\n /**\r\n * 匹配端点\r\n */\r\n private matchEndpoint(\r\n url: string,\r\n method: HttpMethod\r\n ): EndpointConfig | null {\r\n // 移除查询参数\r\n const path = url.split('?')[0];\r\n\r\n // 移除前缀\r\n const prefix = this.options.server?.prefix || '';\r\n const cleanPath = prefix ? path.replace(new RegExp(`^${prefix}`), '') : path;\r\n\r\n for (const endpoint of this.endpoints) {\r\n // 检查是否禁用\r\n if (endpoint.enabled === false) continue;\r\n\r\n // 检查方法\r\n if (endpoint.method !== method) continue;\r\n\r\n // 精确匹配\r\n if (endpoint.path === cleanPath) {\r\n return endpoint;\r\n }\r\n\r\n // 路径参数匹配\r\n if (matchPathParams(endpoint.path, cleanPath)) {\r\n return endpoint;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 解析请求\r\n */\r\n private parseRequest(req: any, url: string): any {\r\n const query = parseQueryParams(url);\r\n const path = url.split('?')[0];\r\n\r\n // 查找匹配的端点以提取路径参数\r\n const endpoint = this.matchEndpoint(path, req.method);\r\n const pathParams = endpoint\r\n ? matchPathParams(endpoint.path, path.split('?')[0])\r\n : null;\r\n\r\n return {\r\n query,\r\n params: pathParams || {},\r\n body: req.body,\r\n headers: req.headers,\r\n };\r\n }\r\n\r\n /**\r\n * 获取 Mock 数据\r\n */\r\n private async getMockData(\r\n endpoint: EndpointConfig,\r\n params: any\r\n ): Promise<any> {\r\n // 从存储获取数据\r\n let data = this.storage.get(endpoint.path, endpoint.method);\r\n\r\n if (!data) {\r\n console.warn(\r\n `[Mock] No data found for ${endpoint.method} ${endpoint.path}`\r\n );\r\n return formatResponse([], false, 'No mock data available');\r\n }\r\n\r\n // 如果是数组,应用过滤、排序、分页\r\n if (Array.isArray(data)) {\r\n // 过滤\r\n if (params.query.filter) {\r\n data = applyFilters(data, JSON.parse(params.query.filter));\r\n }\r\n\r\n // 排序\r\n if (params.query.sort) {\r\n data = applySorting(data, params.query.sort);\r\n }\r\n\r\n // 分页\r\n if (params.query.page || params.query.pageSize) {\r\n const page = parseInt(params.query.page) || 1;\r\n const pageSize = parseInt(params.query.pageSize) || 20;\r\n const result = applyPagination(data, page, pageSize);\r\n\r\n return formatResponse({\r\n list: result.data,\r\n pagination: result.pagination,\r\n });\r\n }\r\n }\r\n\r\n // 应用自定义处理\r\n if (endpoint.custom) {\r\n data = await endpoint.custom(data, params);\r\n }\r\n\r\n // 格式化响应\r\n return formatResponse(data);\r\n }\r\n\r\n /**\r\n * 添加端点\r\n */\r\n addEndpoint(endpoint: EndpointConfig): void {\r\n this.endpoints.push(endpoint);\r\n }\r\n\r\n /**\r\n * 移除端点\r\n */\r\n removeEndpoint(path: string, method: HttpMethod): void {\r\n this.endpoints = this.endpoints.filter(\r\n (e) => !(e.path === path && e.method === method)\r\n );\r\n }\r\n\r\n /**\r\n * 获取所有端点\r\n */\r\n getEndpoints(): EndpointConfig[] {\r\n return this.endpoints;\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - Vite 插件入口\r\n */\r\n\r\nimport type { Plugin } from 'vite';\r\nimport type { MockGeneratorOptions, TypeDefinition } from './types';\r\nimport { MockStorage } from './storage';\r\nimport { MockDataGenerator } from './generator';\r\nimport { MockServer } from './server';\r\n\r\nexport function vitePluginAIMockGenerator(\r\n options: MockGeneratorOptions = {}\r\n): Plugin {\r\n const {\r\n apiKey = process.env.OPENAI_API_KEY || '',\r\n apiUrl = process.env.OPENAI_API_URL || 'https://api.openai.com/v1',\r\n model = process.env.OPENAI_MODEL || 'gpt-4',\r\n enabled = true,\r\n autoGenerate = false,\r\n generation = {\r\n locale: 'zh-CN',\r\n count: 20,\r\n quality: 'balanced',\r\n },\r\n storage: storageOptions = {\r\n dir: 'mock-data',\r\n persist: true,\r\n cache: true,\r\n },\r\n output = {\r\n console: true,\r\n logs: false,\r\n },\r\n } = options;\r\n\r\n // 如果未启用,返回空插件\r\n if (!enabled) {\r\n return {\r\n name: 'vite-plugin-ai-mock-generator',\r\n };\r\n }\r\n\r\n // 初始化组件\r\n const storage = new MockStorage(storageOptions);\r\n const generator = new MockDataGenerator({ apiKey, apiUrl, model });\r\n const server = new MockServer(storage, options);\r\n\r\n return {\r\n name: 'vite-plugin-ai-mock-generator',\r\n enforce: 'pre',\r\n\r\n configResolved(config) {\r\n if (output.console) {\r\n console.log('\\n🤖 AI Mock Generator 已启动');\r\n console.log(`📂 存储目录: ${storageOptions.dir}`);\r\n console.log(`🌍 数据语言: ${generation.locale}`);\r\n console.log(`📊 默认数量: ${generation.count}`);\r\n console.log(`🔑 API Key: ${apiKey ? '已配置' : '未配置'}`);\r\n console.log(\r\n `📍 端点数量: ${options.endpoints?.length || 0}`\r\n );\r\n }\r\n },\r\n\r\n async buildStart() {\r\n // 如果启用自动生成\r\n if (autoGenerate && options.endpoints) {\r\n if (output.console) {\r\n console.log('\\n🔄 开始自动生成 Mock 数据...\\n');\r\n }\r\n\r\n for (const endpoint of options.endpoints) {\r\n // 检查是否已有数据\r\n const existingData = storage.get(endpoint.path, endpoint.method);\r\n if (existingData) {\r\n if (output.console) {\r\n console.log(\r\n `⏭️ 跳过 ${endpoint.method} ${endpoint.path} (已有数据)`\r\n );\r\n }\r\n continue;\r\n }\r\n\r\n try {\r\n if (output.console) {\r\n console.log(`🎲 生成 ${endpoint.method} ${endpoint.path}...`);\r\n }\r\n\r\n // 解析类型定义\r\n const typeDefinition = parseTypeDefinition(endpoint.response);\r\n\r\n // 生成数据\r\n const count = endpoint.count || generation.count || 20;\r\n let data;\r\n \r\n // 根据质量设置选择生成方式\r\n if (generation.quality === 'fast') {\r\n // 使用基础生成器(不需要 AI)\r\n data = generator.generateBasic(typeDefinition, count);\r\n } else {\r\n // 使用 AI 生成\r\n data = await generator.generate({\r\n type: typeDefinition,\r\n count,\r\n locale: generation.locale || 'zh-CN',\r\n quality: generation.quality || 'balanced',\r\n });\r\n }\r\n\r\n // 存储数据\r\n storage.set(endpoint.path, endpoint.method, data, {\r\n type: endpoint.response as string,\r\n });\r\n\r\n if (output.console) {\r\n console.log(\r\n `✅ 已生成 ${count} 条数据: ${endpoint.method} ${endpoint.path}`\r\n );\r\n }\r\n } catch (error: any) {\r\n console.error(\r\n `❌ 生成失败 ${endpoint.method} ${endpoint.path}:`,\r\n error.message\r\n );\r\n }\r\n }\r\n\r\n if (output.console) {\r\n console.log('\\n✨ Mock 数据生成完成\\n');\r\n }\r\n }\r\n },\r\n\r\n configureServer(viteServer) {\r\n // 配置 Mock 服务器中间件\r\n server.configureServer(viteServer);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 解析类型定义\r\n * 简化版本,实际应该使用 TypeScript Compiler API\r\n */\r\nfunction parseTypeDefinition(typeStr: string | TypeDefinition): TypeDefinition {\r\n if (typeof typeStr === 'object') {\r\n return typeStr;\r\n }\r\n\r\n // 简单解析(实际应该更复杂)\r\n const isArray = typeStr.endsWith('[]');\r\n const typeName = isArray ? typeStr.slice(0, -2) : typeStr;\r\n\r\n // 返回基础类型定义\r\n return {\r\n name: typeName,\r\n properties: [],\r\n isArray,\r\n };\r\n}\r\n\r\n// 导出类型\r\nexport type { MockGeneratorOptions, EndpointConfig } from './types';\r\nexport { MockStorage } from './storage';\r\nexport { MockDataGenerator } from './generator';\r\nexport { MockServer } from './server';\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/storage.ts","../src/generator.ts","../src/utils.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["/**\r\n * AI Mock Generator - 数据存储\r\n */\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type { MockDataStore, HttpMethod } from './types';\r\n\r\nexport class MockStorage {\r\n private storageDir: string;\r\n private cache: Map<string, MockDataStore>;\r\n private persist: boolean;\r\n\r\n constructor(options: { dir?: string; persist?: boolean } = {}) {\r\n this.storageDir = options.dir || 'mock-data';\r\n this.persist = options.persist !== false;\r\n this.cache = new Map();\r\n\r\n // 确保存储目录存在\r\n if (this.persist && !fs.existsSync(this.storageDir)) {\r\n fs.mkdirSync(this.storageDir, { recursive: true });\r\n }\r\n\r\n // 加载已有数据\r\n this.load();\r\n }\r\n\r\n /**\r\n * 生成存储 key\r\n */\r\n private getKey(endpoint: string, method: HttpMethod): string {\r\n return `${method}:${endpoint}`;\r\n }\r\n\r\n /**\r\n * 生成文件名\r\n */\r\n private getFileName(endpoint: string, method: HttpMethod): string {\r\n const sanitized = endpoint\r\n .replace(/^\\//, '')\r\n .replace(/\\//g, '_')\r\n .replace(/:/g, '_');\r\n return `${method}_${sanitized}.json`;\r\n }\r\n\r\n /**\r\n * 获取数据\r\n */\r\n get(endpoint: string, method: HttpMethod = 'GET'): any {\r\n const key = this.getKey(endpoint, method);\r\n const store = this.cache.get(key);\r\n return store?.data;\r\n }\r\n\r\n /**\r\n * 设置数据\r\n */\r\n set(\r\n endpoint: string,\r\n method: HttpMethod,\r\n data: any,\r\n metadata?: Partial<MockDataStore['metadata']>\r\n ): void {\r\n const key = this.getKey(endpoint, method);\r\n\r\n const store: MockDataStore = {\r\n endpoint,\r\n method,\r\n data,\r\n metadata: {\r\n count: Array.isArray(data) ? data.length : 1,\r\n generatedAt: new Date().toISOString(),\r\n version: '1.0.0',\r\n type: typeof data,\r\n ...metadata,\r\n },\r\n };\r\n\r\n this.cache.set(key, store);\r\n\r\n // 持久化\r\n if (this.persist) {\r\n this.save(endpoint, method, store);\r\n }\r\n }\r\n\r\n /**\r\n * 删除数据\r\n */\r\n delete(endpoint: string, method: HttpMethod = 'GET'): void {\r\n const key = this.getKey(endpoint, method);\r\n this.cache.delete(key);\r\n\r\n // 删除文件\r\n if (this.persist) {\r\n const fileName = this.getFileName(endpoint, method);\r\n const filePath = path.join(this.storageDir, fileName);\r\n if (fs.existsSync(filePath)) {\r\n fs.unlinkSync(filePath);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 清空所有数据\r\n */\r\n clear(): void {\r\n this.cache.clear();\r\n\r\n // 清空目录\r\n if (this.persist && fs.existsSync(this.storageDir)) {\r\n const files = fs.readdirSync(this.storageDir);\r\n for (const file of files) {\r\n fs.unlinkSync(path.join(this.storageDir, file));\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 获取所有端点\r\n */\r\n getAll(): MockDataStore[] {\r\n return Array.from(this.cache.values());\r\n }\r\n\r\n /**\r\n * 保存到文件\r\n */\r\n private save(\r\n endpoint: string,\r\n method: HttpMethod,\r\n store: MockDataStore\r\n ): void {\r\n const fileName = this.getFileName(endpoint, method);\r\n const filePath = path.join(this.storageDir, fileName);\r\n\r\n fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * 从文件加载\r\n */\r\n private load(): void {\r\n if (!this.persist || !fs.existsSync(this.storageDir)) {\r\n return;\r\n }\r\n\r\n const files = fs.readdirSync(this.storageDir);\r\n\r\n for (const file of files) {\r\n if (!file.endsWith('.json')) continue;\r\n\r\n try {\r\n const filePath = path.join(this.storageDir, file);\r\n const content = fs.readFileSync(filePath, 'utf-8');\r\n const store: MockDataStore = JSON.parse(content);\r\n\r\n const key = this.getKey(store.endpoint, store.method);\r\n this.cache.set(key, store);\r\n } catch (error) {\r\n console.warn(`Failed to load mock data from ${file}:`, error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 导出所有数据\r\n */\r\n export(outputPath: string): void {\r\n const allData = this.getAll();\r\n fs.writeFileSync(outputPath, JSON.stringify(allData, null, 2), 'utf-8');\r\n }\r\n\r\n /**\r\n * 导入数据\r\n */\r\n import(inputPath: string): void {\r\n const content = fs.readFileSync(inputPath, 'utf-8');\r\n const allData: MockDataStore[] = JSON.parse(content);\r\n\r\n for (const store of allData) {\r\n const key = this.getKey(store.endpoint, store.method);\r\n this.cache.set(key, store);\r\n\r\n if (this.persist) {\r\n this.save(store.endpoint, store.method, store);\r\n }\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - 数据生成器\r\n */\r\n\r\nimport { ChatOpenAI } from \"@langchain/openai\";\r\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\r\nimport type {\r\n TypeDefinition,\r\n GenerationContext,\r\n PropertyDefinition,\r\n} from \"./types\";\r\n\r\nexport class MockDataGenerator {\r\n private llm: ChatOpenAI;\r\n\r\n constructor(options: { apiKey: string; apiUrl: string; model: string }) {\r\n this.llm = new ChatOpenAI({\r\n openAIApiKey: options.apiKey,\r\n configuration: {\r\n baseURL: options.apiUrl,\r\n },\r\n modelName: options.model,\r\n temperature: 0.7,\r\n maxTokens: 4000,\r\n });\r\n }\r\n\r\n /**\r\n * 生成 Mock 数据\r\n */\r\n async generate(context: GenerationContext): Promise<any> {\r\n const { type, count, locale, quality } = context;\r\n\r\n // 构建 AI Prompt\r\n const prompt = this.buildPrompt(type, count, locale, quality);\r\n\r\n // 调用 AI API\r\n const response = await this.callAI(prompt);\r\n\r\n // 解析响应\r\n return this.parseResponse(response, type.isArray);\r\n }\r\n\r\n /**\r\n * 构建 AI Prompt\r\n */\r\n private buildPrompt(\r\n type: TypeDefinition,\r\n count: number,\r\n locale: string,\r\n quality: string,\r\n ): string {\r\n const properties = type.properties\r\n .map((p) => this.formatProperty(p))\r\n .join(\"\\n\");\r\n\r\n return `\r\n你是一个专业的 Mock 数据生成器。请根据以下类型定义生成真实、合理的测试数据。\r\n\r\n类型名称: ${type.name}\r\n数据语言: ${locale === \"zh-CN\" ? \"中文\" : \"英文\"}\r\n数据数量: ${count}\r\n质量要求: ${\r\n quality === \"high\"\r\n ? \"高质量(真实业务数据)\"\r\n : quality === \"fast\"\r\n ? \"快速生成\"\r\n : \"平衡质量和速度\"\r\n }\r\n\r\n类型定义:\r\n${properties}\r\n\r\n要求:\r\n1. 生成 ${count} 条数据\r\n2. 数据要符合业务逻辑和真实场景\r\n3. 字段值要合理(如价格不能为负数,年龄在合理范围)\r\n4. 日期格式使用 ISO 8601\r\n5. 返回 JSON 数组格式,不要包含任何其他文字\r\n6. 理解字段语义,生成真实数据(如 userName 生成真实姓名)\r\n\r\n示例格式:\r\n[\r\n {\r\n \"id\": 1,\r\n \"name\": \"张三\",\r\n ...\r\n }\r\n]\r\n\r\n请生成数据:\r\n`.trim();\r\n }\r\n\r\n /**\r\n * 格式化属性\r\n */\r\n private formatProperty(prop: PropertyDefinition): string {\r\n let line = `- ${prop.name}: ${prop.type}`;\r\n\r\n if (prop.comment) {\r\n line += ` // ${prop.comment}`;\r\n }\r\n\r\n if (prop.constraints) {\r\n const constraints = [];\r\n if (prop.constraints.min !== undefined) {\r\n constraints.push(`min: ${prop.constraints.min}`);\r\n }\r\n if (prop.constraints.max !== undefined) {\r\n constraints.push(`max: ${prop.constraints.max}`);\r\n }\r\n if (prop.constraints.unique) {\r\n constraints.push(\"unique\");\r\n }\r\n if (prop.constraints.enum) {\r\n constraints.push(`enum: [${prop.constraints.enum.join(\", \")}]`);\r\n }\r\n if (constraints.length > 0) {\r\n line += ` (${constraints.join(\", \")})`;\r\n }\r\n }\r\n\r\n return line;\r\n }\r\n\r\n /**\r\n * 调用 AI API\r\n */\r\n private async callAI(prompt: string): Promise<string> {\r\n try {\r\n const messages = [\r\n new SystemMessage(\r\n \"你是一个专业的 Mock 数据生成器,擅长生成真实、合理的测试数据。\",\r\n ),\r\n new HumanMessage(prompt),\r\n ];\r\n\r\n const response = await this.llm.invoke(messages);\r\n return response.content as string;\r\n } catch (error: any) {\r\n console.error(\"❌ AI API 调用失败:\", error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 解析 AI 响应\r\n */\r\n private parseResponse(response: string, isArray: boolean = true): any {\r\n try {\r\n // 移除 markdown 代码块标记\r\n let cleanedResponse = response.trim();\r\n\r\n // 移除开头的 ```json 或 ```\r\n cleanedResponse = cleanedResponse.replace(/^```json\\s*/i, \"\");\r\n cleanedResponse = cleanedResponse.replace(/^```\\s*/, \"\");\r\n\r\n // 移除结尾的 ```\r\n cleanedResponse = cleanedResponse.replace(/\\s*```$/, \"\");\r\n\r\n // 提取 JSON 部分(查找数组或对象)\r\n const jsonMatch = cleanedResponse.match(/(\\[[\\s\\S]*\\]|\\{[\\s\\S]*\\})/);\r\n if (!jsonMatch) {\r\n throw new Error(\"No JSON array or object found in response\");\r\n }\r\n\r\n const data = JSON.parse(jsonMatch[0]);\r\n\r\n return isArray ? data : data[0];\r\n } catch (error: any) {\r\n console.error(\"❌ 解析 AI 响应失败:\", error.message);\r\n console.error(\"响应内容:\", response);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * 生成基础数据(不使用 AI)\r\n */\r\n generateBasic(type: TypeDefinition, count: number): any[] {\r\n const data = [];\r\n\r\n for (let i = 0; i < count; i++) {\r\n const item: any = {};\r\n\r\n for (const prop of type.properties) {\r\n item[prop.name] = this.generateBasicValue(prop, i);\r\n }\r\n\r\n data.push(item);\r\n }\r\n\r\n return data;\r\n }\r\n\r\n /**\r\n * 生成基础值\r\n */\r\n private generateBasicValue(prop: PropertyDefinition, index: number): any {\r\n const { type, constraints } = prop;\r\n\r\n // 处理枚举\r\n if (constraints?.enum) {\r\n return constraints.enum[index % constraints.enum.length];\r\n }\r\n\r\n // 根据类型生成\r\n switch (type) {\r\n case \"number\":\r\n const min = constraints?.min ?? 0;\r\n const max = constraints?.max ?? 100;\r\n return Math.floor(Math.random() * (max - min + 1)) + min;\r\n\r\n case \"string\":\r\n return `${prop.name}_${index + 1}`;\r\n\r\n case \"boolean\":\r\n return Math.random() > 0.5;\r\n\r\n case \"Date\":\r\n return new Date().toISOString();\r\n\r\n default:\r\n return null;\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - 工具函数\r\n */\r\n\r\nimport type { HttpMethod, RequestParams } from './types';\r\n\r\n/**\r\n * 延迟函数\r\n */\r\nexport function delay(ms: number | [number, number]): Promise<void> {\r\n const delayTime = Array.isArray(ms)\r\n ? Math.random() * (ms[1] - ms[0]) + ms[0]\r\n : ms;\r\n\r\n return new Promise((resolve) => setTimeout(resolve, delayTime));\r\n}\r\n\r\n/**\r\n * 匹配路径参数\r\n * @example\r\n * matchPathParams('/api/users/:id', '/api/users/123') // { id: '123' }\r\n */\r\nexport function matchPathParams(\r\n pattern: string,\r\n path: string\r\n): Record<string, string> | null {\r\n const patternParts = pattern.split('/');\r\n const pathParts = path.split('/');\r\n\r\n if (patternParts.length !== pathParts.length) {\r\n return null;\r\n }\r\n\r\n const params: Record<string, string> = {};\r\n\r\n for (let i = 0; i < patternParts.length; i++) {\r\n const patternPart = patternParts[i];\r\n const pathPart = pathParts[i];\r\n\r\n if (patternPart.startsWith(':')) {\r\n // 路径参数\r\n const paramName = patternPart.slice(1);\r\n params[paramName] = pathPart;\r\n } else if (patternPart !== pathPart) {\r\n // 不匹配\r\n return null;\r\n }\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * 解析查询参数\r\n */\r\nexport function parseQueryParams(url: string): Record<string, any> {\r\n const queryString = url.split('?')[1];\r\n if (!queryString) return {};\r\n\r\n const params: Record<string, any> = {};\r\n const pairs = queryString.split('&');\r\n\r\n for (const pair of pairs) {\r\n const [key, value] = pair.split('=');\r\n params[decodeURIComponent(key)] = decodeURIComponent(value || '');\r\n }\r\n\r\n return params;\r\n}\r\n\r\n/**\r\n * 生成唯一 ID\r\n */\r\nexport function generateId(): string {\r\n return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * 深度克隆\r\n */\r\nexport function deepClone<T>(obj: T): T {\r\n return JSON.parse(JSON.stringify(obj));\r\n}\r\n\r\n/**\r\n * 应用过滤\r\n */\r\nexport function applyFilters(data: any[], filters: Record<string, any>): any[] {\r\n if (!filters || Object.keys(filters).length === 0) {\r\n return data;\r\n }\r\n\r\n return data.filter((item) => {\r\n for (const [key, value] of Object.entries(filters)) {\r\n if (item[key] !== value) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n });\r\n}\r\n\r\n/**\r\n * 应用排序\r\n */\r\nexport function applySorting(\r\n data: any[],\r\n sort?: string | { field: string; order: 'asc' | 'desc' }\r\n): any[] {\r\n if (!sort) return data;\r\n\r\n const sortConfig =\r\n typeof sort === 'string'\r\n ? { field: sort, order: 'asc' as const }\r\n : sort;\r\n\r\n return [...data].sort((a, b) => {\r\n const aValue = a[sortConfig.field];\r\n const bValue = b[sortConfig.field];\r\n\r\n if (aValue < bValue) return sortConfig.order === 'asc' ? -1 : 1;\r\n if (aValue > bValue) return sortConfig.order === 'asc' ? 1 : -1;\r\n return 0;\r\n });\r\n}\r\n\r\n/**\r\n * 应用分页\r\n */\r\nexport function applyPagination(\r\n data: any[],\r\n page: number = 1,\r\n pageSize: number = 20\r\n): {\r\n data: any[];\r\n pagination: {\r\n page: number;\r\n pageSize: number;\r\n total: number;\r\n totalPages: number;\r\n };\r\n} {\r\n const total = data.length;\r\n const totalPages = Math.ceil(total / pageSize);\r\n const start = (page - 1) * pageSize;\r\n const end = start + pageSize;\r\n\r\n return {\r\n data: data.slice(start, end),\r\n pagination: {\r\n page,\r\n pageSize,\r\n total,\r\n totalPages,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 格式化响应\r\n */\r\nexport function formatResponse(\r\n data: any,\r\n success: boolean = true,\r\n message?: string\r\n) {\r\n return {\r\n code: success ? 200 : 500,\r\n data,\r\n message: message || (success ? 'Success' : 'Error'),\r\n };\r\n}\r\n\r\n/**\r\n * 生成随机种子\r\n */\r\nexport function generateSeed(): number {\r\n return Math.floor(Math.random() * 1000000);\r\n}\r\n\r\n/**\r\n * 设置随机种子\r\n */\r\nexport function setSeed(seed: number): void {\r\n // 简单的伪随机数生成器\r\n let currentSeed = seed;\r\n Math.random = () => {\r\n currentSeed = (currentSeed * 9301 + 49297) % 233280;\r\n return currentSeed / 233280;\r\n };\r\n}\r\n","/**\r\n * AI Mock Generator - Mock 服务器\r\n */\r\n\r\nimport type { ViteDevServer } from 'vite';\r\nimport type {\r\n EndpointConfig,\r\n HttpMethod,\r\n MockGeneratorOptions,\r\n} from './types';\r\nimport { MockStorage } from './storage';\r\nimport {\r\n delay,\r\n matchPathParams,\r\n parseQueryParams,\r\n applyFilters,\r\n applySorting,\r\n applyPagination,\r\n formatResponse,\r\n} from './utils';\r\n\r\nexport class MockServer {\r\n private storage: MockStorage;\r\n private endpoints: EndpointConfig[];\r\n private options: MockGeneratorOptions;\r\n\r\n constructor(storage: MockStorage, options: MockGeneratorOptions) {\r\n this.storage = storage;\r\n this.endpoints = options.endpoints || [];\r\n this.options = options;\r\n }\r\n\r\n /**\r\n * 配置服务器中间件\r\n */\r\n configureServer(server: ViteDevServer): void {\r\n server.middlewares.use(async (req, res, next) => {\r\n const url = req.url || '';\r\n const method = req.method as HttpMethod;\r\n\r\n // 检查是否匹配 Mock 端点\r\n const endpoint = this.matchEndpoint(url, method);\r\n\r\n if (!endpoint) {\r\n return next();\r\n }\r\n\r\n try {\r\n // 解析请求参数\r\n const params = this.parseRequest(req, url);\r\n\r\n // 获取 Mock 数据\r\n const data = await this.getMockData(endpoint, params);\r\n\r\n // 模拟延迟\r\n if (this.options.server?.delay) {\r\n await delay(this.options.server.delay);\r\n }\r\n\r\n // 设置响应头\r\n res.setHeader('Content-Type', 'application/json');\r\n if (this.options.server?.cors) {\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.setHeader('Access-Control-Allow-Methods', '*');\r\n res.setHeader('Access-Control-Allow-Headers', '*');\r\n }\r\n\r\n // 返回响应\r\n res.statusCode = 200;\r\n res.end(JSON.stringify(data));\r\n\r\n // 日志\r\n if (this.options.output?.logs) {\r\n console.log(`[Mock] ${method} ${url} → ${data ? 'OK' : 'Empty'}`);\r\n }\r\n } catch (error: any) {\r\n console.error(`[Mock] Error handling ${method} ${url}:`, error);\r\n res.statusCode = 500;\r\n res.end(\r\n JSON.stringify({\r\n code: 500,\r\n message: error.message,\r\n })\r\n );\r\n }\r\n });\r\n\r\n console.log('\\n🎭 Mock 服务器已启动');\r\n console.log(`📍 已注册 ${this.endpoints.length} 个端点\\n`);\r\n }\r\n\r\n /**\r\n * 匹配端点\r\n */\r\n private matchEndpoint(\r\n url: string,\r\n method: HttpMethod\r\n ): EndpointConfig | null {\r\n // 移除查询参数\r\n const path = url.split('?')[0];\r\n\r\n // 移除前缀\r\n const prefix = this.options.server?.prefix || '';\r\n const cleanPath = prefix ? path.replace(new RegExp(`^${prefix}`), '') : path;\r\n\r\n for (const endpoint of this.endpoints) {\r\n // 检查是否禁用\r\n if (endpoint.enabled === false) continue;\r\n\r\n // 检查方法\r\n if (endpoint.method !== method) continue;\r\n\r\n // 精确匹配\r\n if (endpoint.path === cleanPath) {\r\n return endpoint;\r\n }\r\n\r\n // 路径参数匹配\r\n if (matchPathParams(endpoint.path, cleanPath)) {\r\n return endpoint;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * 解析请求\r\n */\r\n private parseRequest(req: any, url: string): any {\r\n const query = parseQueryParams(url);\r\n const path = url.split('?')[0];\r\n\r\n // 查找匹配的端点以提取路径参数\r\n const endpoint = this.matchEndpoint(path, req.method);\r\n const pathParams = endpoint\r\n ? matchPathParams(endpoint.path, path.split('?')[0])\r\n : null;\r\n\r\n return {\r\n query,\r\n params: pathParams || {},\r\n body: req.body,\r\n headers: req.headers,\r\n };\r\n }\r\n\r\n /**\r\n * 获取 Mock 数据\r\n */\r\n private async getMockData(\r\n endpoint: EndpointConfig,\r\n params: any\r\n ): Promise<any> {\r\n // 从存储获取数据\r\n let data = this.storage.get(endpoint.path, endpoint.method);\r\n\r\n if (!data) {\r\n console.warn(\r\n `[Mock] No data found for ${endpoint.method} ${endpoint.path}`\r\n );\r\n return formatResponse([], false, 'No mock data available');\r\n }\r\n\r\n // 如果是数组,应用过滤、排序、分页\r\n if (Array.isArray(data)) {\r\n // 过滤\r\n if (params.query.filter) {\r\n data = applyFilters(data, JSON.parse(params.query.filter));\r\n }\r\n\r\n // 排序\r\n if (params.query.sort) {\r\n data = applySorting(data, params.query.sort);\r\n }\r\n\r\n // 分页\r\n if (params.query.page || params.query.pageSize) {\r\n const page = parseInt(params.query.page) || 1;\r\n const pageSize = parseInt(params.query.pageSize) || 20;\r\n const result = applyPagination(data, page, pageSize);\r\n\r\n return formatResponse({\r\n list: result.data,\r\n pagination: result.pagination,\r\n });\r\n }\r\n }\r\n\r\n // 应用自定义处理\r\n if (endpoint.custom) {\r\n data = await endpoint.custom(data, params);\r\n }\r\n\r\n // 格式化响应\r\n return formatResponse(data);\r\n }\r\n\r\n /**\r\n * 添加端点\r\n */\r\n addEndpoint(endpoint: EndpointConfig): void {\r\n this.endpoints.push(endpoint);\r\n }\r\n\r\n /**\r\n * 移除端点\r\n */\r\n removeEndpoint(path: string, method: HttpMethod): void {\r\n this.endpoints = this.endpoints.filter(\r\n (e) => !(e.path === path && e.method === method)\r\n );\r\n }\r\n\r\n /**\r\n * 获取所有端点\r\n */\r\n getEndpoints(): EndpointConfig[] {\r\n return this.endpoints;\r\n }\r\n}\r\n","/**\r\n * AI Mock Generator - Vite 插件入口\r\n */\r\n\r\nimport type { Plugin } from \"vite\";\r\nimport type { MockGeneratorOptions, TypeDefinition } from \"./types\";\r\nimport { MockStorage } from \"./storage\";\r\nimport { MockDataGenerator } from \"./generator\";\r\nimport { MockServer } from \"./server\";\r\n\r\nexport function vitePluginAIMockGenerator(\r\n options: MockGeneratorOptions = {},\r\n): Plugin {\r\n const {\r\n apiKey = process.env.OPENAI_API_KEY || \"\",\r\n apiUrl = process.env.OPENAI_API_URL || \"https://api.openai.com/v1\",\r\n model = process.env.OPENAI_MODEL || \"gpt-4\",\r\n enabled = true,\r\n autoGenerate = false,\r\n generation = {\r\n locale: \"zh-CN\",\r\n count: 20,\r\n quality: \"balanced\",\r\n },\r\n storage: storageOptions = {\r\n dir: \"mock-data\",\r\n persist: true,\r\n cache: true,\r\n },\r\n output = {\r\n console: true,\r\n logs: false,\r\n },\r\n } = options;\r\n\r\n // 如果未启用,返回空插件\r\n if (!enabled) {\r\n return {\r\n name: \"vite-plugin-ai-mock-generator\",\r\n };\r\n }\r\n\r\n // 初始化组件\r\n const storage = new MockStorage(storageOptions);\r\n const generator = new MockDataGenerator({ apiKey, apiUrl, model });\r\n const server = new MockServer(storage, options);\r\n\r\n return {\r\n name: \"vite-plugin-ai-mock-generator\",\r\n enforce: \"pre\",\r\n\r\n configResolved(config) {\r\n if (output.console) {\r\n console.log(\"\\n🤖 AI Mock Generator 已启动\");\r\n console.log(`📂 存储目录: ${storageOptions.dir}`);\r\n console.log(`🌍 数据语言: ${generation.locale}`);\r\n console.log(`📊 默认数量: ${generation.count}`);\r\n console.log(`🔑 API Key: ${apiKey ? \"已配置\" : \"未配置\"}`);\r\n console.log(`📍 端点数量: ${options.endpoints?.length || 0}`);\r\n }\r\n },\r\n\r\n async buildStart() {\r\n // 如果启用自动生成\r\n if (autoGenerate && options.endpoints) {\r\n if (output.console) {\r\n console.log(\"\\n🔄 开始自动生成 Mock 数据...\\n\");\r\n }\r\n\r\n for (const endpoint of options.endpoints) {\r\n // 检查是否已有数据\r\n const existingData = storage.get(endpoint.path, endpoint.method);\r\n if (existingData) {\r\n if (output.console) {\r\n console.log(\r\n `⏭️ 跳过 ${endpoint.method} ${endpoint.path} (已有数据)`,\r\n );\r\n }\r\n continue;\r\n }\r\n\r\n try {\r\n if (output.console) {\r\n console.log(`🎲 生成 ${endpoint.method} ${endpoint.path}...`);\r\n }\r\n\r\n // 解析类型定义\r\n const typeDefinition = parseTypeDefinition(endpoint.response);\r\n\r\n // 生成数据\r\n const count = endpoint.count || generation.count || 20;\r\n let data;\r\n\r\n // 根据质量设置选择生成方式\r\n if (generation.quality === \"fast\") {\r\n // 使用基础生成器(不需要 AI)\r\n data = generator.generateBasic(typeDefinition, count);\r\n } else {\r\n // 使用 AI 生成\r\n data = await generator.generate({\r\n type: typeDefinition,\r\n count,\r\n locale: generation.locale || \"zh-CN\",\r\n quality: generation.quality || \"balanced\",\r\n });\r\n }\r\n\r\n // 存储数据\r\n storage.set(endpoint.path, endpoint.method, data, {\r\n type: endpoint.response as string,\r\n });\r\n\r\n if (output.console) {\r\n console.log(\r\n `✅ 已生成 ${count} 条数据: ${endpoint.method} ${endpoint.path}`,\r\n );\r\n }\r\n } catch (error: any) {\r\n console.error(\r\n `❌ 生成失败 ${endpoint.method} ${endpoint.path}:`,\r\n error.message,\r\n );\r\n }\r\n }\r\n\r\n if (output.console) {\r\n console.log(\"\\n✨ Mock 数据生成完成\\n\");\r\n }\r\n }\r\n },\r\n\r\n configureServer(viteServer) {\r\n // 配置 Mock 服务器中间件\r\n server.configureServer(viteServer);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 解析类型定义\r\n * 简化版本,实际应该使用 TypeScript Compiler API\r\n */\r\nfunction parseTypeDefinition(typeStr: string | TypeDefinition): TypeDefinition {\r\n if (typeof typeStr === \"object\") {\r\n return typeStr;\r\n }\r\n\r\n // 简单解析(实际应该更复杂)\r\n const isArray = typeStr.endsWith(\"[]\");\r\n const typeName = isArray ? typeStr.slice(0, -2) : typeStr;\r\n\r\n // 返回基础类型定义\r\n return {\r\n name: typeName,\r\n properties: [],\r\n isArray,\r\n };\r\n}\r\n\r\n// 导出类型\r\nexport type { MockGeneratorOptions, EndpointConfig } from \"./types\";\r\nexport { MockStorage } from \"./storage\";\r\nexport { MockDataGenerator } from \"./generator\";\r\nexport { MockServer } from \"./server\";\r\n\r\n// 默认导出\r\nexport default vitePluginAIMockGenerator;\r\n"],"mappings":"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","names":["path","path"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-ai-mock-generator",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "AI-powered Mock data generator for Vite - Generate realistic test data with AI or basic algorithms",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite",
|
|
@@ -44,7 +44,9 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"picocolors": "^1.1.1",
|
|
47
|
-
"
|
|
47
|
+
"@langchain/core": "^0.3.0",
|
|
48
|
+
"@langchain/openai": "^0.3.0",
|
|
49
|
+
"vite-plugin-ai-shared": "1.0.1"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
52
|
"@types/node": "^20.0.0",
|