vite-plugin-ai-mock-generator 1.0.2 → 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 +1 -3
- package/dist/index.d.ts +1 -3
- package/dist/index.js +116 -92
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +62 -65
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,23 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Object.defineProperty
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
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);
|
|
9
29
|
|
|
10
|
-
|
|
11
|
-
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);
|
|
12
40
|
|
|
13
41
|
// src/storage.ts
|
|
42
|
+
var import_fs = __toESM(require("fs"));
|
|
43
|
+
var import_path = __toESM(require("path"));
|
|
14
44
|
var MockStorage = class {
|
|
15
45
|
constructor(options = {}) {
|
|
16
46
|
this.storageDir = options.dir || "mock-data";
|
|
17
47
|
this.persist = options.persist !== false;
|
|
18
48
|
this.cache = /* @__PURE__ */ new Map();
|
|
19
|
-
if (this.persist && !
|
|
20
|
-
|
|
49
|
+
if (this.persist && !import_fs.default.existsSync(this.storageDir)) {
|
|
50
|
+
import_fs.default.mkdirSync(this.storageDir, { recursive: true });
|
|
21
51
|
}
|
|
22
52
|
this.load();
|
|
23
53
|
}
|
|
@@ -72,9 +102,9 @@ var MockStorage = class {
|
|
|
72
102
|
this.cache.delete(key);
|
|
73
103
|
if (this.persist) {
|
|
74
104
|
const fileName = this.getFileName(endpoint, method);
|
|
75
|
-
const filePath =
|
|
76
|
-
if (
|
|
77
|
-
|
|
105
|
+
const filePath = import_path.default.join(this.storageDir, fileName);
|
|
106
|
+
if (import_fs.default.existsSync(filePath)) {
|
|
107
|
+
import_fs.default.unlinkSync(filePath);
|
|
78
108
|
}
|
|
79
109
|
}
|
|
80
110
|
}
|
|
@@ -83,10 +113,10 @@ var MockStorage = class {
|
|
|
83
113
|
*/
|
|
84
114
|
clear() {
|
|
85
115
|
this.cache.clear();
|
|
86
|
-
if (this.persist &&
|
|
87
|
-
const files =
|
|
116
|
+
if (this.persist && import_fs.default.existsSync(this.storageDir)) {
|
|
117
|
+
const files = import_fs.default.readdirSync(this.storageDir);
|
|
88
118
|
for (const file of files) {
|
|
89
|
-
|
|
119
|
+
import_fs.default.unlinkSync(import_path.default.join(this.storageDir, file));
|
|
90
120
|
}
|
|
91
121
|
}
|
|
92
122
|
}
|
|
@@ -101,22 +131,22 @@ var MockStorage = class {
|
|
|
101
131
|
*/
|
|
102
132
|
save(endpoint, method, store) {
|
|
103
133
|
const fileName = this.getFileName(endpoint, method);
|
|
104
|
-
const filePath =
|
|
105
|
-
|
|
134
|
+
const filePath = import_path.default.join(this.storageDir, fileName);
|
|
135
|
+
import_fs.default.writeFileSync(filePath, JSON.stringify(store, null, 2), "utf-8");
|
|
106
136
|
}
|
|
107
137
|
/**
|
|
108
138
|
* 从文件加载
|
|
109
139
|
*/
|
|
110
140
|
load() {
|
|
111
|
-
if (!this.persist || !
|
|
141
|
+
if (!this.persist || !import_fs.default.existsSync(this.storageDir)) {
|
|
112
142
|
return;
|
|
113
143
|
}
|
|
114
|
-
const files =
|
|
144
|
+
const files = import_fs.default.readdirSync(this.storageDir);
|
|
115
145
|
for (const file of files) {
|
|
116
146
|
if (!file.endsWith(".json")) continue;
|
|
117
147
|
try {
|
|
118
|
-
const filePath =
|
|
119
|
-
const content =
|
|
148
|
+
const filePath = import_path.default.join(this.storageDir, file);
|
|
149
|
+
const content = import_fs.default.readFileSync(filePath, "utf-8");
|
|
120
150
|
const store = JSON.parse(content);
|
|
121
151
|
const key = this.getKey(store.endpoint, store.method);
|
|
122
152
|
this.cache.set(key, store);
|
|
@@ -130,13 +160,13 @@ var MockStorage = class {
|
|
|
130
160
|
*/
|
|
131
161
|
export(outputPath) {
|
|
132
162
|
const allData = this.getAll();
|
|
133
|
-
|
|
163
|
+
import_fs.default.writeFileSync(outputPath, JSON.stringify(allData, null, 2), "utf-8");
|
|
134
164
|
}
|
|
135
165
|
/**
|
|
136
166
|
* 导入数据
|
|
137
167
|
*/
|
|
138
168
|
import(inputPath) {
|
|
139
|
-
const content =
|
|
169
|
+
const content = import_fs.default.readFileSync(inputPath, "utf-8");
|
|
140
170
|
const allData = JSON.parse(content);
|
|
141
171
|
for (const store of allData) {
|
|
142
172
|
const key = this.getKey(store.endpoint, store.method);
|
|
@@ -149,11 +179,19 @@ var MockStorage = class {
|
|
|
149
179
|
};
|
|
150
180
|
|
|
151
181
|
// src/generator.ts
|
|
182
|
+
var import_openai = require("@langchain/openai");
|
|
183
|
+
var import_messages = require("@langchain/core/messages");
|
|
152
184
|
var MockDataGenerator = class {
|
|
153
185
|
constructor(options) {
|
|
154
|
-
this.
|
|
155
|
-
|
|
156
|
-
|
|
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
|
+
});
|
|
157
195
|
}
|
|
158
196
|
/**
|
|
159
197
|
* 生成 Mock 数据
|
|
@@ -170,34 +208,34 @@ var MockDataGenerator = class {
|
|
|
170
208
|
buildPrompt(type, count, locale, quality) {
|
|
171
209
|
const properties = type.properties.map((p) => this.formatProperty(p)).join("\n");
|
|
172
210
|
return `
|
|
173
|
-
|
|
211
|
+
你是一个专业的 Mock 数据生成器。请根据以下类型定义生成真实、合理的测试数据。
|
|
174
212
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
213
|
+
类型名称: ${type.name}
|
|
214
|
+
数据语言: ${locale === "zh-CN" ? "中文" : "英文"}
|
|
215
|
+
数据数量: ${count}
|
|
216
|
+
质量要求: ${quality === "high" ? "高质量(真实业务数据)" : quality === "fast" ? "快速生成" : "平衡质量和速度"}
|
|
179
217
|
|
|
180
|
-
|
|
218
|
+
类型定义:
|
|
181
219
|
${properties}
|
|
182
220
|
|
|
183
|
-
|
|
184
|
-
1.
|
|
185
|
-
2.
|
|
186
|
-
3.
|
|
187
|
-
4.
|
|
188
|
-
5.
|
|
189
|
-
6.
|
|
221
|
+
要求:
|
|
222
|
+
1. 生成 ${count} 条数据
|
|
223
|
+
2. 数据要符合业务逻辑和真实场景
|
|
224
|
+
3. 字段值要合理(如价格不能为负数,年龄在合理范围)
|
|
225
|
+
4. 日期格式使用 ISO 8601
|
|
226
|
+
5. 返回 JSON 数组格式,不要包含任何其他文字
|
|
227
|
+
6. 理解字段语义,生成真实数据(如 userName 生成真实姓名)
|
|
190
228
|
|
|
191
|
-
|
|
229
|
+
示例格式:
|
|
192
230
|
[
|
|
193
231
|
{
|
|
194
232
|
"id": 1,
|
|
195
|
-
"name": "
|
|
233
|
+
"name": "张三",
|
|
196
234
|
...
|
|
197
235
|
}
|
|
198
236
|
]
|
|
199
237
|
|
|
200
|
-
|
|
238
|
+
请生成数据:
|
|
201
239
|
`.trim();
|
|
202
240
|
}
|
|
203
241
|
/**
|
|
@@ -233,30 +271,16 @@ ${properties}
|
|
|
233
271
|
*/
|
|
234
272
|
async callAI(prompt) {
|
|
235
273
|
try {
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
messages: [
|
|
245
|
-
{
|
|
246
|
-
role: "user",
|
|
247
|
-
content: prompt
|
|
248
|
-
}
|
|
249
|
-
],
|
|
250
|
-
temperature: 0.7
|
|
251
|
-
})
|
|
252
|
-
});
|
|
253
|
-
if (!response.ok) {
|
|
254
|
-
throw new Error(`AI API error: ${response.statusText}`);
|
|
255
|
-
}
|
|
256
|
-
const data = await response.json();
|
|
257
|
-
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;
|
|
258
282
|
} catch (error) {
|
|
259
|
-
console.error("
|
|
283
|
+
console.error("❌ AI API 调用失败:", error.message);
|
|
260
284
|
throw error;
|
|
261
285
|
}
|
|
262
286
|
}
|
|
@@ -276,8 +300,8 @@ ${properties}
|
|
|
276
300
|
const data = JSON.parse(jsonMatch[0]);
|
|
277
301
|
return isArray ? data : data[0];
|
|
278
302
|
} catch (error) {
|
|
279
|
-
console.error("
|
|
280
|
-
console.error("
|
|
303
|
+
console.error("❌ 解析 AI 响应失败:", error.message);
|
|
304
|
+
console.error("响应内容:", response);
|
|
281
305
|
throw error;
|
|
282
306
|
}
|
|
283
307
|
}
|
|
@@ -435,7 +459,7 @@ var MockServer = class {
|
|
|
435
459
|
res.statusCode = 200;
|
|
436
460
|
res.end(JSON.stringify(data));
|
|
437
461
|
if (this.options.output?.logs) {
|
|
438
|
-
console.log(`[Mock] ${method} ${url}
|
|
462
|
+
console.log(`[Mock] ${method} ${url} → ${data ? "OK" : "Empty"}`);
|
|
439
463
|
}
|
|
440
464
|
} catch (error) {
|
|
441
465
|
console.error(`[Mock] Error handling ${method} ${url}:`, error);
|
|
@@ -448,8 +472,8 @@ var MockServer = class {
|
|
|
448
472
|
);
|
|
449
473
|
}
|
|
450
474
|
});
|
|
451
|
-
console.log("\n
|
|
452
|
-
console.log(
|
|
475
|
+
console.log("\n🎭 Mock 服务器已启动");
|
|
476
|
+
console.log(`📍 已注册 ${this.endpoints.length} 个端点
|
|
453
477
|
`);
|
|
454
478
|
}
|
|
455
479
|
/**
|
|
@@ -577,32 +601,32 @@ function vitePluginAIMockGenerator(options = {}) {
|
|
|
577
601
|
enforce: "pre",
|
|
578
602
|
configResolved(config) {
|
|
579
603
|
if (output.console) {
|
|
580
|
-
console.log("\n
|
|
581
|
-
console.log(
|
|
582
|
-
console.log(
|
|
583
|
-
console.log(
|
|
584
|
-
console.log(
|
|
585
|
-
console.log(
|
|
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
|
},
|
|
@@ -655,11 +679,11 @@ function parseTypeDefinition(typeStr) {
|
|
|
655
679
|
};
|
|
656
680
|
}
|
|
657
681
|
var index_default = vitePluginAIMockGenerator;
|
|
658
|
-
|
|
659
|
-
exports
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
682
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
683
|
+
0 && (module.exports = {
|
|
684
|
+
MockDataGenerator,
|
|
685
|
+
MockServer,
|
|
686
|
+
MockStorage,
|
|
687
|
+
vitePluginAIMockGenerator
|
|
688
|
+
});
|
|
665
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(`📍 端点数量: ${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"]}
|
|
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":"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","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,32 +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(
|
|
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}`);
|
|
577
570
|
}
|
|
578
571
|
},
|
|
579
572
|
async buildStart() {
|
|
580
573
|
if (autoGenerate && options.endpoints) {
|
|
581
574
|
if (output.console) {
|
|
582
|
-
console.log("\n
|
|
575
|
+
console.log("\n🔄 开始自动生成 Mock 数据...\n");
|
|
583
576
|
}
|
|
584
577
|
for (const endpoint of options.endpoints) {
|
|
585
578
|
const existingData = storage.get(endpoint.path, endpoint.method);
|
|
586
579
|
if (existingData) {
|
|
587
580
|
if (output.console) {
|
|
588
581
|
console.log(
|
|
589
|
-
|
|
582
|
+
`⏭️ 跳过 ${endpoint.method} ${endpoint.path} (已有数据)`
|
|
590
583
|
);
|
|
591
584
|
}
|
|
592
585
|
continue;
|
|
593
586
|
}
|
|
594
587
|
try {
|
|
595
588
|
if (output.console) {
|
|
596
|
-
console.log(
|
|
589
|
+
console.log(`🎲 生成 ${endpoint.method} ${endpoint.path}...`);
|
|
597
590
|
}
|
|
598
591
|
const typeDefinition = parseTypeDefinition(endpoint.response);
|
|
599
592
|
const count = endpoint.count || generation.count || 20;
|
|
@@ -613,18 +606,18 @@ function vitePluginAIMockGenerator(options = {}) {
|
|
|
613
606
|
});
|
|
614
607
|
if (output.console) {
|
|
615
608
|
console.log(
|
|
616
|
-
|
|
609
|
+
`✅ 已生成 ${count} 条数据: ${endpoint.method} ${endpoint.path}`
|
|
617
610
|
);
|
|
618
611
|
}
|
|
619
612
|
} catch (error) {
|
|
620
613
|
console.error(
|
|
621
|
-
|
|
614
|
+
`❌ 生成失败 ${endpoint.method} ${endpoint.path}:`,
|
|
622
615
|
error.message
|
|
623
616
|
);
|
|
624
617
|
}
|
|
625
618
|
}
|
|
626
619
|
if (output.console) {
|
|
627
|
-
console.log("\n
|
|
620
|
+
console.log("\n✨ Mock 数据生成完成\n");
|
|
628
621
|
}
|
|
629
622
|
}
|
|
630
623
|
},
|
|
@@ -646,7 +639,11 @@ function parseTypeDefinition(typeStr) {
|
|
|
646
639
|
};
|
|
647
640
|
}
|
|
648
641
|
var index_default = vitePluginAIMockGenerator;
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
642
|
+
export {
|
|
643
|
+
MockDataGenerator,
|
|
644
|
+
MockServer,
|
|
645
|
+
MockStorage,
|
|
646
|
+
index_default as default,
|
|
647
|
+
vitePluginAIMockGenerator
|
|
648
|
+
};
|
|
652
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(`📍 端点数量: ${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"]}
|
|
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",
|