vite-plugin-automock 1.0.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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2025 vite-plugin-automock contributors
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,350 @@
1
+ # vite-plugin-automock
2
+
3
+ Effortless API mock auto-generation for legacy projects. No manual files, just automock!
4
+
5
+ ---
6
+
7
+ ## Features
8
+
9
+ - 🚀 Automatically captures API requests and generates local mock data
10
+ - 🏆 Perfect for legacy projects, easily backfill missing mocks
11
+ - 🛠️ Supports manual mock file creation with a simple format
12
+ - ⚡ Zero-config, plug-and-play
13
+ - 🧩 Fully compatible with the Vite plugin ecosystem
14
+ - 📦 Production-ready with client-side interceptor
15
+ - 🎛️ Visual mock inspector panel
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pnpm add -D vite-plugin-automock
21
+ # or
22
+ npm install --save-dev vite-plugin-automock
23
+ # or
24
+ yarn add -D vite-plugin-automock
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Configure Vite Plugin
30
+
31
+ ```typescript
32
+ // vite.config.ts
33
+ import { automock } from 'vite-plugin-automock'
34
+
35
+ export default defineConfig({
36
+ plugins: [
37
+ automock({
38
+ mockDir: 'mock',
39
+ apiPrefix: '/api',
40
+ bundleMockData: true, // Bundle mock data for production
41
+ productionMock: true, // Enable mock in production
42
+ proxyBaseUrl: 'https://api.example.com'
43
+ })
44
+ ]
45
+ })
46
+ ```
47
+
48
+ ### 2. Create Mock Files
49
+
50
+ ```typescript
51
+ // mock/users.ts
52
+ import { MockFileConfig } from 'vite-plugin-automock'
53
+
54
+ export default {
55
+ enable: true,
56
+ data: { users: [{ id: 1, name: 'Alice' }] },
57
+ delay: 100,
58
+ status: 200
59
+ } as MockFileConfig
60
+ ```
61
+
62
+ ### 3. Initialize Client Interceptor
63
+
64
+ For PureHttp wrapper:
65
+
66
+ ```typescript
67
+ // src/main.ts or src/api/index.ts
68
+ import {
69
+ initMockInterceptorForPureHttp,
70
+ setMockEnabled,
71
+ registerHttpInstance
72
+ } from 'vite-plugin-automock/client'
73
+ import { http } from './http' // Your PureHttp instance
74
+
75
+ // Register your http instance
76
+ registerHttpInstance(http)
77
+
78
+ // Initialize mock interceptor
79
+ initMockInterceptorForPureHttp()
80
+ .then(() => {
81
+ console.log('[MockInterceptor] Initialized successfully')
82
+ })
83
+ .catch(error => {
84
+ console.error('[MockInterceptor] Failed to initialize:', error)
85
+ })
86
+
87
+ // Enable mock in development
88
+ if (import.meta.env.DEV) {
89
+ setMockEnabled(true)
90
+ }
91
+ ```
92
+
93
+ For plain Axios:
94
+
95
+ ```typescript
96
+ // src/main.ts
97
+ import { initMockInterceptor, setMockEnabled } from 'vite-plugin-automock/client'
98
+ import axios from 'axios'
99
+
100
+ // Initialize with axios instance
101
+ initMockInterceptor(axios)
102
+ .then(() => {
103
+ console.log('[MockInterceptor] Initialized successfully')
104
+ })
105
+ .catch(error => {
106
+ console.error('[MockInterceptor] Failed to initialize:', error)
107
+ })
108
+
109
+ // Enable mock in development
110
+ if (import.meta.env.DEV) {
111
+ setMockEnabled(true)
112
+ }
113
+ ```
114
+
115
+ ## Documentation
116
+
117
+ For detailed usage instructions, configuration options, and examples, see:
118
+
119
+ **[📚 Complete Usage Guide](./docs/USAGE_GUIDE.md)**
120
+
121
+ Topics covered:
122
+ - Development vs Production modes
123
+ - Client interceptor configuration
124
+ - Runtime mock toggle
125
+ - Visual inspector
126
+ - API reference
127
+ - Common scenarios
128
+
129
+ ---
130
+
131
+ ## Basic Usage (Development Mode)
132
+
133
+ Import and register the plugin in your `vite.config.ts`:
134
+
135
+ ```js
136
+ import { automock } from "vite-plugin-automock";
137
+
138
+ export default {
139
+ plugins: [
140
+ automock({
141
+ proxyBaseUrl: "http://localhost:8888", // Required: Your API server URL
142
+ mockDir: "mock", // Optional: Directory for mock files (default: 'mock')
143
+ apiPrefix: "/api", // Optional: API prefix to intercept (default: '/api')
144
+ pathRewrite: (path) => path, // Optional: Path rewrite function
145
+ inspector: true, // Optional: Enable visual inspector (default: false)
146
+ }),
147
+ ],
148
+ };
149
+ ```
150
+
151
+ ### With Custom Inspector Configuration
152
+
153
+ ```js
154
+ automock({
155
+ proxyBaseUrl: "http://localhost:8888",
156
+ inspector: {
157
+ route: "/__inspector/", // Custom route for inspector UI
158
+ enableToggle: true, // Allow toggling enable/disable
159
+ },
160
+ });
161
+ ```
162
+
163
+ ## Configuration Options
164
+
165
+ | Option | Type | Required | Default | Description |
166
+ | -------------- | ----------------- | -------- | ---------------- | --------------------------------- |
167
+ | `proxyBaseUrl` | string | ✅ | - | Base URL of your API server |
168
+ | `mockDir` | string | ❌ | `'mock'` | Directory to store mock files |
169
+ | `apiPrefix` | string | ❌ | `'/api'` | API path prefix to intercept |
170
+ | `pathRewrite` | function | ❌ | `(path) => path` | Function to rewrite request paths |
171
+ | `inspector` | boolean \| object | ❌ | `false` | Enable visual mock inspector UI |
172
+
173
+ ### Inspector Options
174
+
175
+ When `inspector` is an object, you can customize:
176
+
177
+ | Option | Type | Default | Description |
178
+ | -------------- | ------- | ------------ | ---------------------------------- |
179
+ | `route` | string | `'/__mock/'` | Route path for the inspector UI |
180
+ | `enableToggle` | boolean | `true` | Allow toggling mock enable/disable |
181
+
182
+ ## Mock Inspector 🎨
183
+
184
+ **NEW!** Visual interface to manage your mock files:
185
+
186
+ ```js
187
+ automock({
188
+ proxyBaseUrl: "http://localhost:8888",
189
+ inspector: true, // Enable inspector UI
190
+ });
191
+ ```
192
+
193
+ Then visit `http://localhost:5173/__mock/` to:
194
+
195
+ - 📋 **Browse** all mock files organized by URL
196
+ - 🎛️ **Toggle** mock enable/disable status
197
+ - ⏱️ **Adjust** response delay and status codes
198
+ - ✏️ **Edit** JSON response data directly
199
+ - 💾 **Save** changes with a single click
200
+
201
+ ![Inspector Demo](https://via.placeholder.com/800x400?text=Mock+Inspector+UI)
202
+
203
+ ## How It Works
204
+
205
+ 1. **Request Interception**: The plugin intercepts all requests matching the `apiPrefix`
206
+ 2. **Mock Check**: Checks if a corresponding mock file exists
207
+ 3. **Conditional Response**:
208
+ - If mock exists → Returns mock data
209
+ - If mock doesn't exist → Proxies to real API and saves response as mock
210
+ 4. **Auto-Generation**: Real API responses are automatically saved as mock files
211
+ 5. **Hot Reloading**: Changes to mock files are automatically detected and reloaded
212
+ 6. **Visual Inspector**: Manage and edit mocks through the web UI
213
+
214
+ ## Mock File Structure
215
+
216
+ Mock files are organized by URL path and HTTP method:
217
+
218
+ ```
219
+ mock/
220
+ ├── api/
221
+ │ ├── users/
222
+ │ │ ├── get.js # GET /api/users
223
+ │ │ └── post.js # POST /api/users
224
+ │ └── items/
225
+ │ ├── get.js # GET /api/items
226
+ │ └── post.js # POST /api/items
227
+ ```
228
+
229
+ Each mock file exports an object with this structure:
230
+
231
+ ```javascript
232
+ /**
233
+ * Mock data for /api/users (GET)
234
+ * Generated at 2025-01-11T10:30:00.000Z
235
+ */
236
+ export default {
237
+ enable: false, // Whether to use this mock (default: false)
238
+ data: {
239
+ // Response data
240
+ code: 0,
241
+ message: "success",
242
+ data: [
243
+ { id: 1, name: "User 1" },
244
+ { id: 2, name: "User 2" },
245
+ ],
246
+ },
247
+ delay: 0, // Artificial delay in milliseconds
248
+ status: 200, // HTTP status code
249
+ };
250
+ ```
251
+
252
+ ## Quick Start
253
+
254
+ 1. **Try the Example**:
255
+
256
+ ```bash
257
+ pnpm run example
258
+ ```
259
+
260
+ This starts the playground with a demo API server.
261
+
262
+ 2. **Manual Setup**:
263
+
264
+ ```bash
265
+ # Install the plugin
266
+ pnpm add -D vite-plugin-automock
267
+
268
+ # Add to your vite.config.js
269
+ import { automock } from "vite-plugin-automock";
270
+
271
+ export default {
272
+ plugins: [
273
+ automock({
274
+ proxyBaseUrl: "http://localhost:8888"
275
+ })
276
+ ]
277
+ };
278
+ ```
279
+
280
+ 3. **Start Development**:
281
+ - Start your API server
282
+ - Start Vite dev server
283
+ - Make API calls from your frontend
284
+ - Check the mock directory for generated files
285
+
286
+ ## Comparison with Traditional Mock Plugins
287
+
288
+ | Feature | Traditional Mock Plugins | vite-plugin-automock |
289
+ | ---------------------- | ------------------------ | -------------------- |
290
+ | Auto backfill | ❌ | ✅ |
291
+ | Legacy project support | ❌ | ✅ |
292
+ | Manual mock files | ✅ | ✅ |
293
+ | Config complexity | High | Very low |
294
+ | Zero setup | ❌ | ✅ |
295
+ | Real API integration | ❌ | ✅ |
296
+
297
+ ## When to Use
298
+
299
+ - **Legacy Projects**: Quickly add mock capability to existing projects
300
+ - **API Development**: Test frontend while backend is being developed
301
+ - **Offline Development**: Work without internet or when APIs are unavailable
302
+ - **Testing**: Consistent test data without external dependencies
303
+ - **Demo/Presentation**: Reliable demo data that doesn't change
304
+
305
+ ## Advanced Usage
306
+
307
+ ### Custom Path Rewriting
308
+
309
+ ```javascript
310
+ automock({
311
+ proxyBaseUrl: "http://api.example.com",
312
+ pathRewrite: (path) => {
313
+ // Remove /api prefix when proxying
314
+ return path.replace(/^\/api/, "");
315
+ },
316
+ });
317
+ ```
318
+
319
+ ### Conditional Mock Enabling
320
+
321
+ ```javascript
322
+ // In your mock file
323
+ export default {
324
+ enable: process.env.NODE_ENV === "development",
325
+ data: {
326
+ /* mock data */
327
+ },
328
+ };
329
+ ```
330
+
331
+ ### Dynamic Mock Data
332
+
333
+ ```javascript
334
+ // In your mock file
335
+ export default {
336
+ enable: true,
337
+ data: () => ({
338
+ timestamp: new Date().toISOString(),
339
+ randomId: Math.floor(Math.random() * 1000),
340
+ }),
341
+ };
342
+ ```
343
+
344
+ ## Contributing
345
+
346
+ We welcome contributions! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
347
+
348
+ ## License
349
+
350
+ ISC
@@ -0,0 +1,338 @@
1
+ // src/mockFileUtils.ts
2
+ import path from "path";
3
+ import fs from "fs-extra";
4
+ import prettier from "prettier";
5
+ var DEFAULT_CONFIG = {
6
+ enable: true,
7
+ data: null,
8
+ delay: 0,
9
+ status: 200
10
+ };
11
+ function toPosixPath(p) {
12
+ return p.replace(/\\/g, "/");
13
+ }
14
+ var isBinaryResponse = (contentType, data) => {
15
+ if (!contentType) return false;
16
+ const binaryTypes = [
17
+ "application/octet-stream",
18
+ "application/pdf",
19
+ "application/zip",
20
+ "application/x-zip-compressed",
21
+ "application/vnd.ms-excel",
22
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
23
+ "application/msword",
24
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
25
+ "application/vnd.ms-powerpoint",
26
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
27
+ "image/",
28
+ "video/",
29
+ "audio/"
30
+ ];
31
+ return binaryTypes.some((type) => contentType.toLowerCase().includes(type)) || !isBufferTextLike(data);
32
+ };
33
+ var isBufferTextLike = (buffer) => {
34
+ try {
35
+ const sample = buffer.slice(0, 100);
36
+ const text = sample.toString("utf8");
37
+ const nullBytes = [...sample].filter((b) => b === 0).length;
38
+ const controlChars = [...sample].filter(
39
+ (b) => b < 32 && b !== 9 && b !== 10 && b !== 13
40
+ ).length;
41
+ return nullBytes === 0 && controlChars < 5;
42
+ } catch {
43
+ return false;
44
+ }
45
+ };
46
+ var getFileExtension = (contentType, url) => {
47
+ const mimeMap = {
48
+ "application/json": "json",
49
+ "application/pdf": "pdf",
50
+ "application/zip": "zip",
51
+ "application/vnd.ms-excel": "xls",
52
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
53
+ "application/msword": "doc",
54
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
55
+ "application/vnd.ms-powerpoint": "ppt",
56
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
57
+ "image/jpeg": "jpg",
58
+ "image/png": "png",
59
+ "image/gif": "gif",
60
+ "text/plain": "txt",
61
+ "text/html": "html",
62
+ "text/css": "css",
63
+ "application/javascript": "js",
64
+ "text/xml": "xml"
65
+ };
66
+ if (contentType && mimeMap[contentType.toLowerCase()]) {
67
+ return mimeMap[contentType.toLowerCase()];
68
+ }
69
+ try {
70
+ const urlObj = new URL(url, "http://localhost");
71
+ const fileName = urlObj.searchParams.get("file_name");
72
+ if (fileName) {
73
+ const extensionMatch = fileName.match(/\.([a-zA-Z0-9]+)$/);
74
+ if (extensionMatch) {
75
+ return extensionMatch[1];
76
+ }
77
+ }
78
+ } catch (error) {
79
+ }
80
+ return "bin";
81
+ };
82
+ var saveMockData = async (url, method, data, rootDir, statusCode, contentType) => {
83
+ try {
84
+ const absoluteRootDir = path.isAbsolute(rootDir) ? rootDir : path.resolve(process.cwd(), rootDir);
85
+ let pathname;
86
+ let search;
87
+ try {
88
+ if (url.startsWith("http")) {
89
+ const urlObj = new URL(url);
90
+ pathname = urlObj.pathname;
91
+ search = urlObj.search;
92
+ } else {
93
+ const urlObj = new URL(url, "http://localhost");
94
+ pathname = urlObj.pathname;
95
+ search = urlObj.search;
96
+ }
97
+ } catch (error) {
98
+ const [pathPart, ...searchPart] = url.split("?");
99
+ pathname = pathPart;
100
+ search = searchPart.length > 0 ? "?" + searchPart.join("?") : "";
101
+ }
102
+ const filePath = path.join(
103
+ absoluteRootDir,
104
+ pathname.replace(/^\//, ""),
105
+ method.toLowerCase() + ".js"
106
+ );
107
+ const dir = path.dirname(filePath);
108
+ fs.ensureDirSync(dir);
109
+ const isBuffer = Buffer.isBuffer(data);
110
+ const binaryData = isBuffer ? data : Buffer.from(data || "");
111
+ const isBinary = isBinaryResponse(contentType, binaryData);
112
+ if (isBinary) {
113
+ const extension = getFileExtension(contentType, url);
114
+ const binaryFilePath = filePath.replace(/\.js$/, "." + extension);
115
+ if (fs.existsSync(binaryFilePath)) {
116
+ return null;
117
+ }
118
+ fs.writeFileSync(binaryFilePath, binaryData);
119
+ const configContent = `/**
120
+ * Mock data for ${pathname} (${method.toUpperCase()})${search || ""}
121
+ * @description ${pathname}${search || ""} - Binary file (${extension})
122
+ * Generated at ${(/* @__PURE__ */ new Date()).toISOString()}
123
+ */
124
+ export default {
125
+ enable: false,
126
+ data: {
127
+ __binaryFile: '${extension}',
128
+ __originalPath: '${pathname}',
129
+ __originalQuery: '${search}',
130
+ __originalUrl: '${pathname}${search || ""}',
131
+ __contentType: '${contentType}',
132
+ __fileSize: ${binaryData.length}
133
+ },
134
+ delay: 0,
135
+ status: ${statusCode || 200}
136
+ }`;
137
+ try {
138
+ const formattedCode = await prettier.format(configContent, {
139
+ parser: "babel"
140
+ });
141
+ fs.writeFileSync(filePath, formattedCode, "utf-8");
142
+ } catch (error) {
143
+ fs.writeFileSync(filePath, configContent, "utf-8");
144
+ }
145
+ return filePath;
146
+ } else {
147
+ if (fs.existsSync(filePath)) {
148
+ return null;
149
+ }
150
+ const dataStr = isBuffer ? data.toString("utf8") : data || "";
151
+ let jsonData;
152
+ if (!dataStr || dataStr.trim() === "") {
153
+ jsonData = {
154
+ error: true,
155
+ message: `Empty response (${statusCode || "unknown status"})`,
156
+ status: statusCode || 404,
157
+ data: null
158
+ };
159
+ } else {
160
+ try {
161
+ jsonData = JSON.parse(dataStr);
162
+ if (statusCode && statusCode >= 400) {
163
+ if (typeof jsonData === "object" && jsonData !== null) {
164
+ jsonData = {
165
+ ...jsonData,
166
+ __mockStatusCode: statusCode,
167
+ __isErrorResponse: true
168
+ };
169
+ } else {
170
+ jsonData = {
171
+ originalData: jsonData,
172
+ __mockStatusCode: statusCode,
173
+ __isErrorResponse: true
174
+ };
175
+ }
176
+ }
177
+ } catch {
178
+ jsonData = {
179
+ error: true,
180
+ message: `Non-JSON response (${statusCode || "unknown status"})`,
181
+ status: statusCode || 404,
182
+ data: dataStr,
183
+ __mockStatusCode: statusCode,
184
+ __isErrorResponse: true
185
+ };
186
+ }
187
+ }
188
+ const content = `/**
189
+ * Mock data for ${pathname} (${method.toUpperCase()})${search || ""}
190
+ * @description ${pathname}${search || ""}
191
+ * Generated at ${(/* @__PURE__ */ new Date()).toISOString()}
192
+ */
193
+ export default {
194
+ enable: false,
195
+ data: ${JSON.stringify(jsonData)},
196
+ delay: 0,
197
+ status: ${statusCode || 200}
198
+ }`;
199
+ try {
200
+ const formattedCode = await prettier.format(content, {
201
+ parser: "babel"
202
+ });
203
+ fs.writeFileSync(filePath, formattedCode, "utf-8");
204
+ return filePath;
205
+ } catch (error) {
206
+ fs.writeFileSync(filePath, content, "utf-8");
207
+ return filePath;
208
+ }
209
+ }
210
+ } catch (error) {
211
+ console.error(`Failed to save mock data for ${url}:`, error);
212
+ console.error(
213
+ `URL details: url=${url}, method=${method}, statusCode=${statusCode}, contentType=${contentType}`
214
+ );
215
+ throw error;
216
+ }
217
+ };
218
+ var recursiveReadAllFiles = (dir) => {
219
+ if (!fs.existsSync(dir)) return [];
220
+ const files = [];
221
+ try {
222
+ const list = fs.readdirSync(dir);
223
+ list.forEach((file) => {
224
+ const filePath = path.join(dir, file);
225
+ const stat = fs.statSync(filePath);
226
+ if (stat.isDirectory()) {
227
+ files.push(...recursiveReadAllFiles(filePath));
228
+ } else {
229
+ files.push(filePath);
230
+ }
231
+ });
232
+ } catch (error) {
233
+ console.error(`Error reading directory ${dir}:`, error);
234
+ }
235
+ return files;
236
+ };
237
+ var buildMockIndex = (mockDir) => {
238
+ const mockFileMap = /* @__PURE__ */ new Map();
239
+ if (!fs.existsSync(mockDir)) {
240
+ fs.ensureDirSync(mockDir);
241
+ return mockFileMap;
242
+ }
243
+ const files = recursiveReadAllFiles(mockDir);
244
+ files.forEach((filePath) => {
245
+ if (!filePath.endsWith(".js")) {
246
+ return;
247
+ }
248
+ try {
249
+ const relativePath = path.relative(mockDir, filePath);
250
+ const method = path.basename(filePath, ".js");
251
+ const dirPath = path.dirname(relativePath);
252
+ const urlPath = "/" + toPosixPath(dirPath);
253
+ const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
254
+ const key = `${urlPath}/${method}.js`.toLowerCase();
255
+ mockFileMap.set(key, absolutePath);
256
+ } catch (error) {
257
+ console.error(`\u274C [automock] \u5904\u7406\u6587\u4EF6\u5931\u8D25 ${filePath}:`, error);
258
+ }
259
+ });
260
+ return mockFileMap;
261
+ };
262
+ var parseMockModule = async (filePath) => {
263
+ const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
264
+ if (!fs.existsSync(absolutePath)) {
265
+ throw new Error(`Mock file does not exist: ${absolutePath}`);
266
+ }
267
+ const content = fs.readFileSync(absolutePath, "utf-8");
268
+ const headerCommentMatch = content.match(/^(\/\*\*[\s\S]*?\*\/)/);
269
+ const headerComment = headerCommentMatch ? headerCommentMatch[1] : void 0;
270
+ let description;
271
+ if (headerComment) {
272
+ const descMatch = headerComment.match(/@description\s+(.+?)(?:\n|\*\/)/s);
273
+ if (descMatch) {
274
+ description = descMatch[1].trim();
275
+ }
276
+ }
277
+ const { default: mockModule } = await import(`${absolutePath}?t=${Date.now()}`);
278
+ const exportedConfig = typeof mockModule === "function" ? mockModule() : mockModule;
279
+ const hasDynamicData = typeof exportedConfig?.data === "function";
280
+ const config = {
281
+ ...DEFAULT_CONFIG,
282
+ ...exportedConfig ?? {}
283
+ };
284
+ const serializable = !hasDynamicData;
285
+ const dataObj = typeof config.data === "object" && config.data !== null ? config.data : null;
286
+ const isBinary = dataObj !== null && "__binaryFile" in dataObj;
287
+ return {
288
+ config,
289
+ serializable,
290
+ hasDynamicData,
291
+ headerComment,
292
+ description,
293
+ dataText: isBinary ? `/* Binary file: ${dataObj?.__binaryFile} */` : serializable ? JSON.stringify(config.data ?? null, null, 2) : "/* data is generated dynamically and cannot be edited here */",
294
+ isBinary
295
+ };
296
+ };
297
+ var writeMockFile = async (filePath, mockInfo) => {
298
+ const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
299
+ let header = mockInfo.headerComment || "";
300
+ if (mockInfo.description !== void 0) {
301
+ if (header) {
302
+ if (/@description/.test(header)) {
303
+ header = header.replace(
304
+ /@description\s+.+?(?=\n|\*\/)/s,
305
+ `@description ${mockInfo.description}`
306
+ );
307
+ } else {
308
+ header = header.replace(
309
+ /\*\//,
310
+ ` * @description ${mockInfo.description}
311
+ */`
312
+ );
313
+ }
314
+ }
315
+ }
316
+ const content = header ? `${header}
317
+ ` : "";
318
+ const finalContent = `${content}export default ${JSON.stringify(mockInfo.config, null, 2)}
319
+ `;
320
+ try {
321
+ const formattedCode = await prettier.format(finalContent, {
322
+ parser: "babel"
323
+ });
324
+ fs.writeFileSync(absolutePath, formattedCode, "utf-8");
325
+ } catch (error) {
326
+ console.error("Error formatting code with prettier:", error);
327
+ fs.writeFileSync(absolutePath, finalContent, "utf-8");
328
+ }
329
+ };
330
+
331
+ export {
332
+ DEFAULT_CONFIG,
333
+ saveMockData,
334
+ buildMockIndex,
335
+ parseMockModule,
336
+ writeMockFile
337
+ };
338
+ //# sourceMappingURL=chunk-KZB7ARYV.mjs.map