vite-plugin-mock-data 6.0.2 → 8.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/README.md CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  [![npm package](https://nodei.co/npm/vite-plugin-mock-data.png?downloads=true&downloadRank=true&stars=true)](https://www.npmjs.com/package/vite-plugin-mock-data)
4
4
 
5
- > Provides a simple way to mock data. Vite >= 3.1
5
+ > Provides a simple way to mock data.
6
6
 
7
7
  [![NPM version](https://img.shields.io/npm/v/vite-plugin-mock-data.svg?style=flat)](https://npmjs.org/package/vite-plugin-mock-data)
8
8
  [![NPM Downloads](https://img.shields.io/npm/dm/vite-plugin-mock-data.svg?style=flat)](https://npmjs.org/package/vite-plugin-mock-data)
9
+ [![Node version](https://img.shields.io/node/v/vite-plugin-mock-data.svg?style=flat)](https://npmjs.org/package/vite-plugin-mock-data)
9
10
 
10
11
  ## Installation
11
12
 
@@ -30,4 +31,4 @@ We welcome contributions from the community! If you find a bug or want to sugges
30
31
 
31
32
  ## License
32
33
 
33
- This project is licensed under the [MIT License](../../LICENSE).
34
+ This project is licensed under the [MIT License](LICENSE).
@@ -1,7 +1,7 @@
1
1
  import { OutgoingHttpHeaders } from 'node:http';
2
2
  import { Config as SirvConfig, HTTPVersion } from 'find-my-way';
3
- import { type Options as SirvOptions } from 'sirv';
3
+ import { Options as SirvOptions } from 'sirv';
4
4
  import { ViteDevServer } from 'vite';
5
- import { RouteConfig } from './typings';
5
+ import { RouteConfig } from './types';
6
6
  export declare function sirvOptions(headers?: OutgoingHttpHeaders): SirvOptions;
7
7
  export declare function configureServer(server: ViteDevServer, routerOpts: SirvConfig<HTTPVersion.V1> | SirvConfig<HTTPVersion.V2> | undefined, routes: RouteConfig[], cwd: string): void;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from 'vite';
2
- import { Options } from './typings';
3
- export * from './typings';
2
+ import { Options } from './types';
3
+ export * from './types';
4
4
  /**
5
5
  * Provides a simple way to mock data.
6
6
  *
package/dist/index.js CHANGED
@@ -1,160 +1,286 @@
1
- "use strict";
2
- const isWhatType = require("is-what-type");
3
- const vpRuntimeHelper = require("vp-runtime-helper");
4
- const node_path = require("node:path");
5
- const getRouter = require("find-my-way");
6
- const sirv = require("sirv");
7
- const vite = require("vite");
8
- const node_fs = require("node:fs");
9
- const promises = require("node:fs/promises");
10
- const node_module = require("node:module");
11
- const tinyglobby = require("tinyglobby");
12
- const baseLogFactory = require("base-log-factory");
13
- const blfColorfulAppender = require("blf-colorful-appender");
14
- var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
15
- const name = "vite-plugin-mock-data";
16
- const pkg = {
17
- name
1
+ //#region \0rolldown/runtime.js
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 __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
18
17
  };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ let is_what_type = require("is-what-type");
24
+ let vp_runtime_helper = require("vp-runtime-helper");
25
+ let node_path = require("node:path");
26
+ let find_my_way = require("find-my-way");
27
+ find_my_way = __toESM(find_my_way);
28
+ let sirv = require("sirv");
29
+ sirv = __toESM(sirv);
30
+ let vite = require("vite");
31
+ let node_fs = require("node:fs");
32
+ let node_fs_promises = require("node:fs/promises");
33
+ let node_module = require("node:module");
34
+ let tinyglobby = require("tinyglobby");
35
+ //#region package.json
36
+ var name = "vite-plugin-mock-data";
37
+ var package_default = {
38
+ name,
39
+ version: "8.0.0",
40
+ description: "Provides a simple way to mock data.",
41
+ main: "./dist/index.js",
42
+ module: "./dist/index.mjs",
43
+ types: "./dist/index.d.ts",
44
+ exports: { ".": {
45
+ "types": "./dist/index.d.ts",
46
+ "import": "./dist/index.mjs",
47
+ "require": "./dist/index.js"
48
+ } },
49
+ engines: {
50
+ "node": "^20.19.0 || >=22.12.0",
51
+ "vite": ">=8.0.0"
52
+ },
53
+ scripts: {
54
+ "build": "vite build",
55
+ "watch": "vite build --watch",
56
+ "prepublishOnly": "npm run build",
57
+ "release": "pnpm publish --no-git-checks",
58
+ "test": "vitest run",
59
+ "test:watch": "vitest"
60
+ },
61
+ repository: {
62
+ "type": "git",
63
+ "url": "git+https://github.com/fengxinming/vite-plugins.git",
64
+ "directory": "plugins/vite-plugin-mock-data"
65
+ },
66
+ keywords: ["vite-plugin", "vite-plugin-mock-data"],
67
+ author: "Jesse Feng <fxm0016@126.com>",
68
+ license: "MIT",
69
+ bugs: { "url": "https://github.com/fengxinming/vite-plugins/issues" },
70
+ homepage: "https://fengxinming.github.io/vite-plugins/plugins/vite-plugin-mock-data/quick-start",
71
+ dependencies: {
72
+ "find-my-way": "^9.2.0",
73
+ "is-what-type": "^1.1.4",
74
+ "sirv": "^3.0.1",
75
+ "tinyglobby": "^0.2.12",
76
+ "vp-runtime-helper": "workspace:^"
77
+ },
78
+ devDependencies: {
79
+ "vite": "^8.0.0",
80
+ "vite-plugin-dts": "^5.0.3",
81
+ "vite-plugin-external": "workspace:^"
82
+ },
83
+ files: ["dist"]
84
+ };
85
+ //#endregion
86
+ //#region src/configureServer.ts
87
+ /**
88
+ * Simple request body parser for JSON / urlencoded payloads.
89
+ * Populates `req.body` so that route handlers can read it directly,
90
+ * matching the documented handler signature `(req) => req.body`.
91
+ */
92
+ function readJsonBody(req) {
93
+ return new Promise((resolve, reject) => {
94
+ const chunks = [];
95
+ req.on("data", (c) => chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c)));
96
+ req.on("end", () => {
97
+ const raw = Buffer.concat(chunks).toString("utf8");
98
+ if (!raw) {
99
+ resolve(void 0);
100
+ return;
101
+ }
102
+ const type = (req.headers["content-type"] || "").toLowerCase();
103
+ try {
104
+ if (type.includes("application/json")) resolve(JSON.parse(raw));
105
+ else if (type.includes("application/x-www-form-urlencoded")) {
106
+ const out = {};
107
+ for (const [k, v] of new URLSearchParams(raw)) out[k] = v;
108
+ resolve(out);
109
+ } else resolve(raw);
110
+ } catch (e) {
111
+ reject(e);
112
+ }
113
+ });
114
+ req.on("error", reject);
115
+ });
116
+ }
117
+ function sendResult(req, res, ret, defaultHeaders) {
118
+ if (res.headersSent || ret === void 0) return;
119
+ (0, vite.send)(req, res, typeof ret !== "string" ? JSON.stringify(ret) : ret, (0, is_what_type.isObject)(ret) ? "json" : "html", { headers: defaultHeaders });
120
+ }
19
121
  function sirvOptions(headers) {
20
- return {
21
- dev: true,
22
- etag: true,
23
- extensions: [],
24
- setHeaders(res, pathname) {
25
- res.setHeader("Access-Control-Allow-Origin", "*");
26
- if (/\.[tj]sx?$/.test(pathname)) {
27
- res.setHeader("Content-Type", "application/javascript");
28
- }
29
- if (headers) {
30
- Object.entries(headers).forEach(([key, val]) => {
31
- if (val) {
32
- res.setHeader(key, val);
33
- }
34
- });
35
- }
36
- }
37
- };
122
+ return {
123
+ dev: true,
124
+ etag: true,
125
+ extensions: [],
126
+ setHeaders(res, pathname) {
127
+ res.setHeader("Access-Control-Allow-Origin", "*");
128
+ if (/\.[tj]sx?$/.test(pathname)) res.setHeader("Content-Type", "application/javascript");
129
+ if (headers) Object.entries(headers).forEach(([key, val]) => {
130
+ if (val) res.setHeader(key, val);
131
+ });
132
+ }
133
+ };
38
134
  }
39
135
  function configureServer(server, routerOpts, routes, cwd) {
40
- const router = getRouter(routerOpts);
41
- if (Array.isArray(routes)) {
42
- routes.forEach((route) => {
43
- Object.keys(route).forEach((xpath) => {
44
- let [methods, pathname] = xpath.split(" ");
45
- if (!pathname) {
46
- pathname = methods;
47
- methods = "GET";
48
- }
49
- methods = methods.toUpperCase();
50
- let routeConfig = route[xpath];
51
- if (!isWhatType.isObject(routeConfig)) {
52
- routeConfig = { handler: routeConfig };
53
- }
54
- let handler;
55
- if (typeof routeConfig.file === "string") {
56
- handler = (req, res) => {
57
- const parsedPath = node_path.parse(vpRuntimeHelper.toAbsolutePath(routeConfig.file, cwd));
58
- const serve = sirv(parsedPath.dir, sirvOptions(server.config.server.headers));
59
- req.url = `/${parsedPath.base}`;
60
- serve(req, res);
61
- };
62
- } else if (typeof routeConfig.handler !== "function") {
63
- const ret = routeConfig.handler;
64
- const retType = typeof ret;
65
- handler = (req, res) => {
66
- vite.send(req, res, retType !== "string" ? JSON.stringify(ret) : ret, isWhatType.isObject(ret) ? "json" : "html", {
67
- headers: server.config.server.headers
68
- });
69
- };
70
- } else {
71
- handler = routeConfig.handler;
72
- }
73
- if (handler) {
74
- router.on(methods.split("/"), pathname, {}, handler, routeConfig.store);
75
- }
76
- });
77
- });
78
- }
79
- server.middlewares.use((req, res, next) => {
80
- router.defaultRoute = () => next();
81
- router.lookup(req, res);
82
- });
136
+ const router = (0, find_my_way.default)(routerOpts);
137
+ if (Array.isArray(routes)) routes.forEach((route) => {
138
+ Object.keys(route).forEach((xpath) => {
139
+ let [methods, pathname] = xpath.split(" ");
140
+ if (!pathname) {
141
+ pathname = methods;
142
+ methods = "GET";
143
+ }
144
+ methods = methods.toUpperCase();
145
+ let routeConfig = route[xpath];
146
+ if (!(0, is_what_type.isObject)(routeConfig)) routeConfig = { handler: routeConfig };
147
+ let handler;
148
+ if (typeof routeConfig.file === "string") handler = (req, res) => {
149
+ const parsedPath = (0, node_path.parse)((0, vp_runtime_helper.toAbsolutePath)(routeConfig.file, cwd));
150
+ const serve = (0, sirv.default)(parsedPath.dir, sirvOptions(server.config.server.headers));
151
+ req.url = `/${parsedPath.base}`;
152
+ serve(req, res);
153
+ };
154
+ else if (typeof routeConfig.handler !== "function") {
155
+ const ret = routeConfig.handler;
156
+ const retType = typeof ret;
157
+ handler = (req, res) => {
158
+ (0, vite.send)(req, res, retType !== "string" ? JSON.stringify(ret) : ret, (0, is_what_type.isObject)(ret) ? "json" : "html", { headers: server.config.server.headers });
159
+ };
160
+ } else {
161
+ const userHandler = routeConfig.handler;
162
+ const needsBody = methods.toUpperCase().split("/").some((m) => [
163
+ "POST",
164
+ "PUT",
165
+ "PATCH",
166
+ "DELETE"
167
+ ].includes(m));
168
+ handler = async (req, res, params) => {
169
+ req.params = params ?? {};
170
+ try {
171
+ if (needsBody) req.body = await readJsonBody(req);
172
+ } catch (e) {
173
+ res.statusCode = 400;
174
+ res.setHeader("Content-Type", "application/json");
175
+ res.end(JSON.stringify({
176
+ error: "Invalid request body",
177
+ detail: String(e)
178
+ }));
179
+ return;
180
+ }
181
+ try {
182
+ sendResult(req, res, await userHandler(req, res), server.config.server.headers);
183
+ } catch (e) {
184
+ server.config.logger.error(`[mock-data] handler error on ${methods} ${pathname}: ${e}`);
185
+ if (!res.headersSent) {
186
+ res.statusCode = 500;
187
+ res.setHeader("Content-Type", "application/json");
188
+ res.end(JSON.stringify({
189
+ error: "Mock handler error",
190
+ detail: String(e)
191
+ }));
192
+ }
193
+ }
194
+ };
195
+ }
196
+ if (handler) router.on(methods.split("/"), pathname, {}, handler, routeConfig.store);
197
+ });
198
+ });
199
+ server.middlewares.use((req, res, next) => {
200
+ router.defaultRoute = () => next();
201
+ router.lookup(req, res);
202
+ });
83
203
  }
84
- const PLUGIN_NAME = pkg.name;
85
- const logger = new baseLogFactory.Logger(PLUGIN_NAME, {
86
- level: baseLogFactory.Level.WARN,
87
- appenders: [
88
- new blfColorfulAppender.ColorfulAppender()
89
- ]
90
- });
204
+ //#endregion
205
+ //#region src/logger.ts
206
+ var PLUGIN_NAME = name;
207
+ var logger = vp_runtime_helper.logFactory.getLogger(PLUGIN_NAME);
208
+ //#endregion
209
+ //#region src/loadRoutes.ts
210
+ var _require = typeof require === "function" ? require : (0, node_module.createRequire)({}.url);
91
211
  async function getRoute(filename) {
92
- logger.debug("Load mock file:", filename);
93
- let { ext, dir, name: name2 } = node_path.parse(filename);
94
- const isTs = ext === ".ts" || ext === ".mts";
95
- if (isTs) {
96
- const { code } = await vite.transformWithEsbuild(node_fs.readFileSync(filename, "utf-8"), filename, {
97
- loader: "ts",
98
- target: "esnext"
99
- });
100
- filename = node_path.join(dir, `${name2}-${PLUGIN_NAME}.mjs`);
101
- ext = ".mjs";
102
- await promises.writeFile(filename, code);
103
- }
104
- let config;
105
- switch (ext) {
106
- case ".js":
107
- config = node_module.createRequire(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.js", document.baseURI).href)(filename);
108
- break;
109
- case ".mjs":
110
- config = (await import(filename)).default;
111
- if (isTs) {
112
- await promises.unlink(filename);
113
- }
114
- break;
115
- case ".json":
116
- config = JSON.parse(node_fs.readFileSync(filename, "utf-8"));
117
- break;
118
- }
119
- return config;
212
+ logger.debug("Load mock file:", filename);
213
+ let { ext, dir, name } = (0, node_path.parse)(filename);
214
+ const isTs = ext === ".ts" || ext === ".mts";
215
+ if (isTs) {
216
+ const { code } = await (0, vite.transformWithOxc)((0, node_fs.readFileSync)(filename, "utf-8"), filename);
217
+ filename = (0, node_path.join)(dir, `${name}-${PLUGIN_NAME}.mjs`);
218
+ ext = ".mjs";
219
+ await (0, node_fs_promises.writeFile)(filename, code);
220
+ }
221
+ let config;
222
+ switch (ext) {
223
+ case ".js":
224
+ config = _require(filename);
225
+ break;
226
+ case ".mjs":
227
+ config = (await import(filename)).default;
228
+ if (isTs) await (0, node_fs_promises.unlink)(filename);
229
+ break;
230
+ case ".json": config = JSON.parse((0, node_fs.readFileSync)(filename, "utf-8"));
231
+ }
232
+ return config;
120
233
  }
121
234
  async function loadRoutes(dir, routes) {
122
- const paths = await tinyglobby.glob(`${dir}/**/*.{js,mjs,json,ts,mts}`, { absolute: true });
123
- const configs = await Promise.all(paths.map(getRoute));
124
- for (const config of configs) {
125
- if (config) {
126
- routes.push(config);
127
- }
128
- }
235
+ const paths = await (0, tinyglobby.glob)(`${dir}/**/*.{js,mjs,json,ts,mts}`, { absolute: true });
236
+ const configs = await Promise.all(paths.map(getRoute));
237
+ for (const config of configs) if (config) routes.push(config);
129
238
  }
239
+ //#endregion
240
+ //#region src/index.ts
241
+ /**
242
+ * Provides a simple way to mock data.
243
+ *
244
+ * @example
245
+ * ```js
246
+ * import { defineConfig } from 'vite';
247
+ * import pluginMockDate from 'vite-plugin-mock-data';
248
+ *
249
+ * export default defineConfig({
250
+ * plugins: [
251
+ * pluginMockDate({
252
+ * routes: './mock'
253
+ * })
254
+ * ]
255
+ * });
256
+ * ```
257
+ *
258
+ * @param opts Options
259
+ * @returns a vite plugin
260
+ */
130
261
  function pluginMockDate(opts) {
131
- vpRuntimeHelper.banner(pkg.name);
132
- const { isAfter, routerOptions, routes, logLevel, cwd = process.cwd() } = opts;
133
- if (logLevel) {
134
- logger.level = logLevel;
135
- }
136
- const allRoutes = [];
137
- return {
138
- name: PLUGIN_NAME,
139
- async configureServer(server) {
140
- if (typeof routes === "string") {
141
- logger.debug("Load routes from", routes);
142
- await loadRoutes(vpRuntimeHelper.toAbsolutePath(routes, cwd), allRoutes);
143
- } else if (Array.isArray(routes)) {
144
- for (const route of routes) {
145
- logger.debug("Load routes from", route);
146
- if (typeof route === "string") {
147
- await loadRoutes(vpRuntimeHelper.toAbsolutePath(route, cwd), allRoutes);
148
- } else {
149
- allRoutes.push(route);
150
- }
151
- }
152
- } else if (isWhatType.isObject(routes)) {
153
- logger.debug("Load routes from", routes);
154
- allRoutes.push(routes);
155
- }
156
- return isAfter ? () => configureServer(server, routerOptions, allRoutes, cwd) : configureServer(server, routerOptions, allRoutes, cwd);
157
- }
158
- };
262
+ if (opts.enableBanner) (0, vp_runtime_helper.banner)(package_default.name);
263
+ const { isAfter, routerOptions, routes, logLevel, cwd = process.cwd() } = opts;
264
+ if (logLevel) logger.level = logLevel;
265
+ const allRoutes = [];
266
+ return {
267
+ name: PLUGIN_NAME,
268
+ async configureServer(server) {
269
+ if (typeof routes === "string") {
270
+ logger.debug("Load routes from", routes);
271
+ await loadRoutes((0, vp_runtime_helper.toAbsolutePath)(routes, cwd), allRoutes);
272
+ } else if (Array.isArray(routes)) for (const route of routes) {
273
+ logger.debug("Load routes from", route);
274
+ if (typeof route === "string") await loadRoutes((0, vp_runtime_helper.toAbsolutePath)(route, cwd), allRoutes);
275
+ else allRoutes.push(route);
276
+ }
277
+ else if ((0, is_what_type.isObject)(routes)) {
278
+ logger.debug("Load routes from", routes);
279
+ allRoutes.push(routes);
280
+ }
281
+ return isAfter ? () => configureServer(server, routerOptions, allRoutes, cwd) : configureServer(server, routerOptions, allRoutes, cwd);
282
+ }
283
+ };
159
284
  }
285
+ //#endregion
160
286
  module.exports = pluginMockDate;
package/dist/index.mjs CHANGED
@@ -1,160 +1,268 @@
1
1
  import { isObject } from "is-what-type";
2
- import { toAbsolutePath, banner } from "vp-runtime-helper";
3
- import { parse, join } from "node:path";
2
+ import { banner, logFactory, toAbsolutePath } from "vp-runtime-helper";
3
+ import { join, parse } from "node:path";
4
4
  import getRouter from "find-my-way";
5
5
  import sirv from "sirv";
6
- import { send, transformWithEsbuild } from "vite";
6
+ import { send, transformWithOxc } from "vite";
7
7
  import { readFileSync } from "node:fs";
8
- import { writeFile, unlink } from "node:fs/promises";
8
+ import { unlink, writeFile } from "node:fs/promises";
9
9
  import { createRequire } from "node:module";
10
10
  import { glob } from "tinyglobby";
11
- import { Logger, Level } from "base-log-factory";
12
- import { ColorfulAppender } from "blf-colorful-appender";
13
- const name = "vite-plugin-mock-data";
14
- const pkg = {
15
- name
11
+ //#region \0rolldown/runtime.js
12
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
13
+ if (typeof require !== "undefined") return require.apply(this, arguments);
14
+ throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
15
+ });
16
+ //#endregion
17
+ //#region package.json
18
+ var name = "vite-plugin-mock-data";
19
+ var package_default = {
20
+ name,
21
+ version: "8.0.0",
22
+ description: "Provides a simple way to mock data.",
23
+ main: "./dist/index.js",
24
+ module: "./dist/index.mjs",
25
+ types: "./dist/index.d.ts",
26
+ exports: { ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.mjs",
29
+ "require": "./dist/index.js"
30
+ } },
31
+ engines: {
32
+ "node": "^20.19.0 || >=22.12.0",
33
+ "vite": ">=8.0.0"
34
+ },
35
+ scripts: {
36
+ "build": "vite build",
37
+ "watch": "vite build --watch",
38
+ "prepublishOnly": "npm run build",
39
+ "release": "pnpm publish --no-git-checks",
40
+ "test": "vitest run",
41
+ "test:watch": "vitest"
42
+ },
43
+ repository: {
44
+ "type": "git",
45
+ "url": "git+https://github.com/fengxinming/vite-plugins.git",
46
+ "directory": "plugins/vite-plugin-mock-data"
47
+ },
48
+ keywords: ["vite-plugin", "vite-plugin-mock-data"],
49
+ author: "Jesse Feng <fxm0016@126.com>",
50
+ license: "MIT",
51
+ bugs: { "url": "https://github.com/fengxinming/vite-plugins/issues" },
52
+ homepage: "https://fengxinming.github.io/vite-plugins/plugins/vite-plugin-mock-data/quick-start",
53
+ dependencies: {
54
+ "find-my-way": "^9.2.0",
55
+ "is-what-type": "^1.1.4",
56
+ "sirv": "^3.0.1",
57
+ "tinyglobby": "^0.2.12",
58
+ "vp-runtime-helper": "workspace:^"
59
+ },
60
+ devDependencies: {
61
+ "vite": "^8.0.0",
62
+ "vite-plugin-dts": "^5.0.3",
63
+ "vite-plugin-external": "workspace:^"
64
+ },
65
+ files: ["dist"]
16
66
  };
67
+ //#endregion
68
+ //#region src/configureServer.ts
69
+ /**
70
+ * Simple request body parser for JSON / urlencoded payloads.
71
+ * Populates `req.body` so that route handlers can read it directly,
72
+ * matching the documented handler signature `(req) => req.body`.
73
+ */
74
+ function readJsonBody(req) {
75
+ return new Promise((resolve, reject) => {
76
+ const chunks = [];
77
+ req.on("data", (c) => chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c)));
78
+ req.on("end", () => {
79
+ const raw = Buffer.concat(chunks).toString("utf8");
80
+ if (!raw) {
81
+ resolve(void 0);
82
+ return;
83
+ }
84
+ const type = (req.headers["content-type"] || "").toLowerCase();
85
+ try {
86
+ if (type.includes("application/json")) resolve(JSON.parse(raw));
87
+ else if (type.includes("application/x-www-form-urlencoded")) {
88
+ const out = {};
89
+ for (const [k, v] of new URLSearchParams(raw)) out[k] = v;
90
+ resolve(out);
91
+ } else resolve(raw);
92
+ } catch (e) {
93
+ reject(e);
94
+ }
95
+ });
96
+ req.on("error", reject);
97
+ });
98
+ }
99
+ function sendResult(req, res, ret, defaultHeaders) {
100
+ if (res.headersSent || ret === void 0) return;
101
+ send(req, res, typeof ret !== "string" ? JSON.stringify(ret) : ret, isObject(ret) ? "json" : "html", { headers: defaultHeaders });
102
+ }
17
103
  function sirvOptions(headers) {
18
- return {
19
- dev: true,
20
- etag: true,
21
- extensions: [],
22
- setHeaders(res, pathname) {
23
- res.setHeader("Access-Control-Allow-Origin", "*");
24
- if (/\.[tj]sx?$/.test(pathname)) {
25
- res.setHeader("Content-Type", "application/javascript");
26
- }
27
- if (headers) {
28
- Object.entries(headers).forEach(([key, val]) => {
29
- if (val) {
30
- res.setHeader(key, val);
31
- }
32
- });
33
- }
34
- }
35
- };
104
+ return {
105
+ dev: true,
106
+ etag: true,
107
+ extensions: [],
108
+ setHeaders(res, pathname) {
109
+ res.setHeader("Access-Control-Allow-Origin", "*");
110
+ if (/\.[tj]sx?$/.test(pathname)) res.setHeader("Content-Type", "application/javascript");
111
+ if (headers) Object.entries(headers).forEach(([key, val]) => {
112
+ if (val) res.setHeader(key, val);
113
+ });
114
+ }
115
+ };
36
116
  }
37
117
  function configureServer(server, routerOpts, routes, cwd) {
38
- const router = getRouter(routerOpts);
39
- if (Array.isArray(routes)) {
40
- routes.forEach((route) => {
41
- Object.keys(route).forEach((xpath) => {
42
- let [methods, pathname] = xpath.split(" ");
43
- if (!pathname) {
44
- pathname = methods;
45
- methods = "GET";
46
- }
47
- methods = methods.toUpperCase();
48
- let routeConfig = route[xpath];
49
- if (!isObject(routeConfig)) {
50
- routeConfig = { handler: routeConfig };
51
- }
52
- let handler;
53
- if (typeof routeConfig.file === "string") {
54
- handler = (req, res) => {
55
- const parsedPath = parse(toAbsolutePath(routeConfig.file, cwd));
56
- const serve = sirv(parsedPath.dir, sirvOptions(server.config.server.headers));
57
- req.url = `/${parsedPath.base}`;
58
- serve(req, res);
59
- };
60
- } else if (typeof routeConfig.handler !== "function") {
61
- const ret = routeConfig.handler;
62
- const retType = typeof ret;
63
- handler = (req, res) => {
64
- send(req, res, retType !== "string" ? JSON.stringify(ret) : ret, isObject(ret) ? "json" : "html", {
65
- headers: server.config.server.headers
66
- });
67
- };
68
- } else {
69
- handler = routeConfig.handler;
70
- }
71
- if (handler) {
72
- router.on(methods.split("/"), pathname, {}, handler, routeConfig.store);
73
- }
74
- });
75
- });
76
- }
77
- server.middlewares.use((req, res, next) => {
78
- router.defaultRoute = () => next();
79
- router.lookup(req, res);
80
- });
118
+ const router = getRouter(routerOpts);
119
+ if (Array.isArray(routes)) routes.forEach((route) => {
120
+ Object.keys(route).forEach((xpath) => {
121
+ let [methods, pathname] = xpath.split(" ");
122
+ if (!pathname) {
123
+ pathname = methods;
124
+ methods = "GET";
125
+ }
126
+ methods = methods.toUpperCase();
127
+ let routeConfig = route[xpath];
128
+ if (!isObject(routeConfig)) routeConfig = { handler: routeConfig };
129
+ let handler;
130
+ if (typeof routeConfig.file === "string") handler = (req, res) => {
131
+ const parsedPath = parse(toAbsolutePath(routeConfig.file, cwd));
132
+ const serve = sirv(parsedPath.dir, sirvOptions(server.config.server.headers));
133
+ req.url = `/${parsedPath.base}`;
134
+ serve(req, res);
135
+ };
136
+ else if (typeof routeConfig.handler !== "function") {
137
+ const ret = routeConfig.handler;
138
+ const retType = typeof ret;
139
+ handler = (req, res) => {
140
+ send(req, res, retType !== "string" ? JSON.stringify(ret) : ret, isObject(ret) ? "json" : "html", { headers: server.config.server.headers });
141
+ };
142
+ } else {
143
+ const userHandler = routeConfig.handler;
144
+ const needsBody = methods.toUpperCase().split("/").some((m) => [
145
+ "POST",
146
+ "PUT",
147
+ "PATCH",
148
+ "DELETE"
149
+ ].includes(m));
150
+ handler = async (req, res, params) => {
151
+ req.params = params ?? {};
152
+ try {
153
+ if (needsBody) req.body = await readJsonBody(req);
154
+ } catch (e) {
155
+ res.statusCode = 400;
156
+ res.setHeader("Content-Type", "application/json");
157
+ res.end(JSON.stringify({
158
+ error: "Invalid request body",
159
+ detail: String(e)
160
+ }));
161
+ return;
162
+ }
163
+ try {
164
+ sendResult(req, res, await userHandler(req, res), server.config.server.headers);
165
+ } catch (e) {
166
+ server.config.logger.error(`[mock-data] handler error on ${methods} ${pathname}: ${e}`);
167
+ if (!res.headersSent) {
168
+ res.statusCode = 500;
169
+ res.setHeader("Content-Type", "application/json");
170
+ res.end(JSON.stringify({
171
+ error: "Mock handler error",
172
+ detail: String(e)
173
+ }));
174
+ }
175
+ }
176
+ };
177
+ }
178
+ if (handler) router.on(methods.split("/"), pathname, {}, handler, routeConfig.store);
179
+ });
180
+ });
181
+ server.middlewares.use((req, res, next) => {
182
+ router.defaultRoute = () => next();
183
+ router.lookup(req, res);
184
+ });
81
185
  }
82
- const PLUGIN_NAME = pkg.name;
83
- const logger = new Logger(PLUGIN_NAME, {
84
- level: Level.WARN,
85
- appenders: [
86
- new ColorfulAppender()
87
- ]
88
- });
186
+ //#endregion
187
+ //#region src/logger.ts
188
+ var PLUGIN_NAME = name;
189
+ var logger = logFactory.getLogger(PLUGIN_NAME);
190
+ //#endregion
191
+ //#region src/loadRoutes.ts
192
+ var _require = typeof __require === "function" ? __require : createRequire(import.meta.url);
89
193
  async function getRoute(filename) {
90
- logger.debug("Load mock file:", filename);
91
- let { ext, dir, name: name2 } = parse(filename);
92
- const isTs = ext === ".ts" || ext === ".mts";
93
- if (isTs) {
94
- const { code } = await transformWithEsbuild(readFileSync(filename, "utf-8"), filename, {
95
- loader: "ts",
96
- target: "esnext"
97
- });
98
- filename = join(dir, `${name2}-${PLUGIN_NAME}.mjs`);
99
- ext = ".mjs";
100
- await writeFile(filename, code);
101
- }
102
- let config;
103
- switch (ext) {
104
- case ".js":
105
- config = createRequire(import.meta.url)(filename);
106
- break;
107
- case ".mjs":
108
- config = (await import(filename)).default;
109
- if (isTs) {
110
- await unlink(filename);
111
- }
112
- break;
113
- case ".json":
114
- config = JSON.parse(readFileSync(filename, "utf-8"));
115
- break;
116
- }
117
- return config;
194
+ logger.debug("Load mock file:", filename);
195
+ let { ext, dir, name } = parse(filename);
196
+ const isTs = ext === ".ts" || ext === ".mts";
197
+ if (isTs) {
198
+ const { code } = await transformWithOxc(readFileSync(filename, "utf-8"), filename);
199
+ filename = join(dir, `${name}-${PLUGIN_NAME}.mjs`);
200
+ ext = ".mjs";
201
+ await writeFile(filename, code);
202
+ }
203
+ let config;
204
+ switch (ext) {
205
+ case ".js":
206
+ config = _require(filename);
207
+ break;
208
+ case ".mjs":
209
+ config = (await import(filename)).default;
210
+ if (isTs) await unlink(filename);
211
+ break;
212
+ case ".json": config = JSON.parse(readFileSync(filename, "utf-8"));
213
+ }
214
+ return config;
118
215
  }
119
216
  async function loadRoutes(dir, routes) {
120
- const paths = await glob(`${dir}/**/*.{js,mjs,json,ts,mts}`, { absolute: true });
121
- const configs = await Promise.all(paths.map(getRoute));
122
- for (const config of configs) {
123
- if (config) {
124
- routes.push(config);
125
- }
126
- }
217
+ const paths = await glob(`${dir}/**/*.{js,mjs,json,ts,mts}`, { absolute: true });
218
+ const configs = await Promise.all(paths.map(getRoute));
219
+ for (const config of configs) if (config) routes.push(config);
127
220
  }
221
+ //#endregion
222
+ //#region src/index.ts
223
+ /**
224
+ * Provides a simple way to mock data.
225
+ *
226
+ * @example
227
+ * ```js
228
+ * import { defineConfig } from 'vite';
229
+ * import pluginMockDate from 'vite-plugin-mock-data';
230
+ *
231
+ * export default defineConfig({
232
+ * plugins: [
233
+ * pluginMockDate({
234
+ * routes: './mock'
235
+ * })
236
+ * ]
237
+ * });
238
+ * ```
239
+ *
240
+ * @param opts Options
241
+ * @returns a vite plugin
242
+ */
128
243
  function pluginMockDate(opts) {
129
- banner(pkg.name);
130
- const { isAfter, routerOptions, routes, logLevel, cwd = process.cwd() } = opts;
131
- if (logLevel) {
132
- logger.level = logLevel;
133
- }
134
- const allRoutes = [];
135
- return {
136
- name: PLUGIN_NAME,
137
- async configureServer(server) {
138
- if (typeof routes === "string") {
139
- logger.debug("Load routes from", routes);
140
- await loadRoutes(toAbsolutePath(routes, cwd), allRoutes);
141
- } else if (Array.isArray(routes)) {
142
- for (const route of routes) {
143
- logger.debug("Load routes from", route);
144
- if (typeof route === "string") {
145
- await loadRoutes(toAbsolutePath(route, cwd), allRoutes);
146
- } else {
147
- allRoutes.push(route);
148
- }
149
- }
150
- } else if (isObject(routes)) {
151
- logger.debug("Load routes from", routes);
152
- allRoutes.push(routes);
153
- }
154
- return isAfter ? () => configureServer(server, routerOptions, allRoutes, cwd) : configureServer(server, routerOptions, allRoutes, cwd);
155
- }
156
- };
244
+ if (opts.enableBanner) banner(package_default.name);
245
+ const { isAfter, routerOptions, routes, logLevel, cwd = process.cwd() } = opts;
246
+ if (logLevel) logger.level = logLevel;
247
+ const allRoutes = [];
248
+ return {
249
+ name: PLUGIN_NAME,
250
+ async configureServer(server) {
251
+ if (typeof routes === "string") {
252
+ logger.debug("Load routes from", routes);
253
+ await loadRoutes(toAbsolutePath(routes, cwd), allRoutes);
254
+ } else if (Array.isArray(routes)) for (const route of routes) {
255
+ logger.debug("Load routes from", route);
256
+ if (typeof route === "string") await loadRoutes(toAbsolutePath(route, cwd), allRoutes);
257
+ else allRoutes.push(route);
258
+ }
259
+ else if (isObject(routes)) {
260
+ logger.debug("Load routes from", routes);
261
+ allRoutes.push(routes);
262
+ }
263
+ return isAfter ? () => configureServer(server, routerOptions, allRoutes, cwd) : configureServer(server, routerOptions, allRoutes, cwd);
264
+ }
265
+ };
157
266
  }
158
- export {
159
- pluginMockDate as default
160
- };
267
+ //#endregion
268
+ export { pluginMockDate as default };
@@ -1,2 +1,2 @@
1
- import { RouteConfig } from './typings';
1
+ import { RouteConfig } from './types';
2
2
  export default function loadRoutes(dir: string, routes: RouteConfig[]): Promise<void>;
package/dist/logger.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { Logger } from 'base-log-factory';
1
+ import { Logger } from 'vp-runtime-helper';
2
2
  export declare const PLUGIN_NAME: string;
3
3
  export declare const logger: Logger;
@@ -1,5 +1,5 @@
1
- import { LogLevel } from 'base-log-factory';
2
1
  import { Config as SirvConfig, Handler, HTTPVersion, RouteOptions } from 'find-my-way';
2
+ import { LogLevel } from 'vp-runtime-helper';
3
3
  export interface HandleRoute {
4
4
  file?: string;
5
5
  handler?: any | Handler<HTTPVersion.V1>;
@@ -43,4 +43,10 @@ export interface Options {
43
43
  * or specify the directory to define mock routes that should be added to the dev server.
44
44
  */
45
45
  routes?: RouteConfig | Array<RouteConfig | string> | string;
46
+ /**
47
+ * Whether to output the banner
48
+ *
49
+ * 是否输出 banner
50
+ */
51
+ enableBanner?: boolean;
46
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-mock-data",
3
- "version": "6.0.2",
3
+ "version": "8.0.0",
4
4
  "description": "Provides a simple way to mock data.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -13,13 +13,13 @@
13
13
  }
14
14
  },
15
15
  "engines": {
16
- "node": ">=14.18.0",
17
- "vite": ">=3.1.0"
16
+ "node": "^20.19.0 || >=22.12.0",
17
+ "vite": ">=8.0.0"
18
18
  },
19
19
  "repository": {
20
20
  "type": "git",
21
21
  "url": "git+https://github.com/fengxinming/vite-plugins.git",
22
- "directory": "packages/vite-plugin-mock-data"
22
+ "directory": "plugins/vite-plugin-mock-data"
23
23
  },
24
24
  "keywords": [
25
25
  "vite-plugin",
@@ -32,25 +32,25 @@
32
32
  },
33
33
  "homepage": "https://fengxinming.github.io/vite-plugins/plugins/vite-plugin-mock-data/quick-start",
34
34
  "dependencies": {
35
- "base-log-factory": "^2.0.9",
36
- "blf-colorful-appender": "^1.0.2",
37
35
  "find-my-way": "^9.2.0",
38
- "is-what-type": "^1.0.0",
36
+ "is-what-type": "^1.1.4",
39
37
  "sirv": "^3.0.1",
40
38
  "tinyglobby": "^0.2.12",
41
- "vp-runtime-helper": "^1.0.3"
39
+ "vp-runtime-helper": "^8.0.0"
42
40
  },
43
41
  "devDependencies": {
44
- "@rollup/plugin-typescript": "^12.1.2",
45
- "@types/fs-extra": "^11.0.4",
46
- "vite": "^6.1.0"
42
+ "vite": "^8.0.0",
43
+ "vite-plugin-dts": "^5.0.3",
44
+ "vite-plugin-external": "^8.0.0"
47
45
  },
48
46
  "files": [
49
47
  "dist"
50
48
  ],
51
49
  "scripts": {
52
- "build:lib": "vite build",
50
+ "build": "vite build",
53
51
  "watch": "vite build --watch",
54
- "release": "pnpm publish --no-git-checks"
52
+ "release": "pnpm publish --no-git-checks",
53
+ "test": "vitest run",
54
+ "test:watch": "vitest"
55
55
  }
56
56
  }