rspack-plugin-mock 1.3.0 → 2.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.
@@ -0,0 +1,487 @@
1
+ import { c as processRawData, d as normalizePath, f as vfs, h as createMatcher, m as getPackageDeps, p as getPackageDepList, s as processMockData, t as createLogger } from "./logger-CzeuHKAL.js";
2
+ import { createRequire } from "node:module";
3
+ import path from "node:path";
4
+ import process from "node:process";
5
+ import { attemptAsync, isBoolean, isPlainObject, toArray, uniq } from "@pengzhanbo/utils";
6
+ import * as rspackCore from "@rspack/core";
7
+ import fs, { promises } from "node:fs";
8
+ import fsp from "node:fs/promises";
9
+ import ansis from "ansis";
10
+ import { glob } from "tinyglobby";
11
+ import isCore from "is-core-module";
12
+ import { loadPackageJSONSync } from "local-pkg";
13
+ import { pathToFileURL } from "node:url";
14
+ import { createHash } from "node:crypto";
15
+ import EventEmitter from "node:events";
16
+ import chokidar from "chokidar";
17
+ //#region src/compiler/createRspackCompiler.ts
18
+ const require = createRequire(import.meta.url);
19
+ function createCompiler(options, callback) {
20
+ const rspackOptions = resolveRspackOptions(options);
21
+ const isWatch = rspackOptions.watch === true;
22
+ async function handler(err, stats) {
23
+ const name = "[rspack:mock]";
24
+ const logError = (...args) => {
25
+ if (stats) stats.compilation.getLogger(name).error(...args);
26
+ else console.error(ansis.red(name), ...args);
27
+ };
28
+ if (err) {
29
+ logError(err.stack || err);
30
+ if ("details" in err) logError(err.details);
31
+ return;
32
+ }
33
+ if (stats?.hasErrors()) logError(stats.toJson().errors);
34
+ const code = vfs.readFileSync("/output.js", "utf-8");
35
+ const externals = [];
36
+ if (!isWatch) {
37
+ const modules = stats?.toJson().modules || [];
38
+ const aliasList = Object.keys(options.alias || {}).map((key) => key.replace(/\$$/g, ""));
39
+ for (const { name } of modules) if (name?.startsWith("external")) {
40
+ const packageName = normalizePackageName(name);
41
+ if (!isCore(packageName) && !aliasList.includes(packageName)) externals.push(normalizePackageName(name));
42
+ }
43
+ }
44
+ await callback({
45
+ code,
46
+ externals
47
+ });
48
+ }
49
+ const compiler = rspackCore.rspack(rspackOptions);
50
+ compiler.outputFileSystem = vfs;
51
+ if (!isWatch) compiler.run(async (...args) => {
52
+ await handler(...args);
53
+ compiler.close(() => {});
54
+ });
55
+ else compiler.watch({}, handler);
56
+ return compiler;
57
+ }
58
+ function transformWithRspack(options) {
59
+ return new Promise((resolve) => {
60
+ createCompiler({
61
+ ...options,
62
+ watch: false
63
+ }, (result) => {
64
+ resolve(result);
65
+ });
66
+ });
67
+ }
68
+ function normalizePackageName(name) {
69
+ const filepath = name.replace("external ", "").slice(1, -1);
70
+ const [scope, packageName] = filepath.split("/");
71
+ if (filepath[0] === "@") return `${scope}/${packageName}`;
72
+ return scope;
73
+ }
74
+ function resolveRspackOptions({ cwd, isEsm = true, entryFile, plugins, alias, watch = false }) {
75
+ const targets = ["node >= 20.0.0"];
76
+ if (alias && "@swc/helpers" in alias) delete alias["@swc/helpers"];
77
+ const externals = getPackageDepList(cwd);
78
+ const externalPattern = new RegExp(`^(${externals.join("|")})($|/)`, "i");
79
+ return {
80
+ mode: "production",
81
+ context: cwd,
82
+ entry: entryFile,
83
+ watch,
84
+ target: `node${(process.versions.node || "").replace(/\.\d+$/, "")}`,
85
+ externalsType: isEsm ? "module" : "commonjs2",
86
+ externals: [externalPattern],
87
+ resolve: {
88
+ alias,
89
+ extensions: [
90
+ ".js",
91
+ ".ts",
92
+ ".cjs",
93
+ ".mjs",
94
+ ".json5",
95
+ ".json"
96
+ ]
97
+ },
98
+ plugins,
99
+ output: {
100
+ library: { type: !isEsm ? "commonjs2" : "module" },
101
+ filename: "output.js",
102
+ module: isEsm,
103
+ path: "/"
104
+ },
105
+ optimization: { minimize: !watch },
106
+ node: {
107
+ __dirname: false,
108
+ __filename: false
109
+ },
110
+ module: { rules: [
111
+ {
112
+ test: /\.json5?$/,
113
+ loader: require.resolve("#json5-loader"),
114
+ type: "javascript/auto"
115
+ },
116
+ {
117
+ test: /\.[cm]?js$/,
118
+ use: [{
119
+ loader: "builtin:swc-loader",
120
+ options: {
121
+ jsc: { parser: { syntax: "ecmascript" } },
122
+ env: { targets }
123
+ }
124
+ }]
125
+ },
126
+ {
127
+ test: /\.[cm]?ts$/,
128
+ use: [{
129
+ loader: "builtin:swc-loader",
130
+ options: {
131
+ jsc: { parser: { syntax: "typescript" } },
132
+ env: { targets }
133
+ }
134
+ }]
135
+ }
136
+ ] }
137
+ };
138
+ }
139
+ //#endregion
140
+ //#region src/compiler/loadFromCode.ts
141
+ async function loadFromCode({ filepath, code, isESM, cwd }) {
142
+ filepath = path.resolve(cwd, filepath);
143
+ const ext = isESM ? ".mjs" : ".cjs";
144
+ const filepathTmp = `${filepath}.${getHash(code)}${ext}`;
145
+ await promises.writeFile(filepathTmp, code, "utf8");
146
+ const [, mod] = await attemptAsync(importDefault, String(pathToFileURL(filepathTmp)));
147
+ await attemptAsync(promises.unlink, filepathTmp);
148
+ return mod;
149
+ }
150
+ async function importDefault(filepath) {
151
+ const mod = await import(filepath);
152
+ return mod.default || mod;
153
+ }
154
+ function getHash(str) {
155
+ return createHash("md5").update(str).digest("hex");
156
+ }
157
+ //#endregion
158
+ //#region src/compiler/mockCompiler.ts
159
+ function createMockCompiler(options) {
160
+ return new MockCompiler(options);
161
+ }
162
+ var MockCompiler = class extends EventEmitter {
163
+ cwd;
164
+ mockWatcher;
165
+ entryFile;
166
+ deps = [];
167
+ isESM = false;
168
+ _mockData = {};
169
+ watchInfo;
170
+ compiler;
171
+ constructor(options) {
172
+ super();
173
+ this.options = options;
174
+ this.cwd = options.cwd || process.cwd();
175
+ try {
176
+ const pkg = loadPackageJSONSync(this.cwd);
177
+ this.isESM = pkg?.type === "module";
178
+ } catch {}
179
+ this.entryFile = path.resolve(process.cwd(), "node_modules/.cache/mock-server/mock-server.ts");
180
+ }
181
+ get mockData() {
182
+ return this._mockData;
183
+ }
184
+ async run() {
185
+ const { include, exclude } = this.options;
186
+ const { pattern, ignore, isMatch } = createMatcher(include, exclude);
187
+ const files = await glob(pattern, {
188
+ ignore,
189
+ cwd: path.join(this.cwd, this.options.dir)
190
+ });
191
+ this.deps = files.map((file) => normalizePath(file));
192
+ this.updateMockEntry();
193
+ this.watchMockFiles(isMatch);
194
+ const { plugins, alias } = this.options;
195
+ const options = {
196
+ isEsm: this.isESM,
197
+ cwd: this.cwd,
198
+ plugins,
199
+ entryFile: this.entryFile,
200
+ alias,
201
+ watch: true
202
+ };
203
+ this.compiler = createCompiler(options, async ({ code }) => {
204
+ try {
205
+ const result = await loadFromCode({
206
+ filepath: "mock.bundle.js",
207
+ code,
208
+ isESM: this.isESM,
209
+ cwd: this.cwd
210
+ });
211
+ this._mockData = processMockData(processRawData(result));
212
+ this.emit("update", this.watchInfo || {});
213
+ } catch (e) {
214
+ this.options.logger.error(e.stack || e.message);
215
+ }
216
+ });
217
+ }
218
+ close() {
219
+ this.mockWatcher.close();
220
+ this.compiler?.close(() => {});
221
+ this.emit("close");
222
+ }
223
+ updateAlias(alias) {
224
+ this.options.alias = {
225
+ ...this.options.alias,
226
+ ...alias
227
+ };
228
+ }
229
+ async updateMockEntry() {
230
+ await writeMockEntryFile(this.entryFile, this.deps, this.cwd, this.options.dir);
231
+ }
232
+ watchMockFiles(isMatch) {
233
+ const watcher = this.mockWatcher = chokidar.watch(this.options.dir, {
234
+ ignoreInitial: true,
235
+ cwd: this.cwd,
236
+ ignored: (filepath, stats) => {
237
+ if (filepath.includes("node_modules")) return true;
238
+ return !!stats?.isFile() && !isMatch(filepath);
239
+ }
240
+ });
241
+ watcher.on("add", (filepath) => {
242
+ filepath = normalizePath(filepath);
243
+ if (isMatch(filepath)) {
244
+ this.watchInfo = {
245
+ filepath,
246
+ type: "add"
247
+ };
248
+ this.deps = uniq([...this.deps, filepath]);
249
+ this.updateMockEntry();
250
+ }
251
+ });
252
+ watcher.on("change", (filepath) => {
253
+ filepath = normalizePath(filepath);
254
+ if (isMatch(filepath)) this.watchInfo = {
255
+ filepath,
256
+ type: "change"
257
+ };
258
+ });
259
+ watcher.on("unlink", async (filepath) => {
260
+ filepath = normalizePath(filepath);
261
+ if (isMatch(filepath)) {
262
+ this.watchInfo = {
263
+ filepath,
264
+ type: "unlink"
265
+ };
266
+ this.deps = this.deps.filter((dep) => dep !== filepath);
267
+ this.updateMockEntry();
268
+ }
269
+ });
270
+ }
271
+ };
272
+ //#endregion
273
+ //#region package.json
274
+ var name = "rspack-plugin-mock";
275
+ var version = "2.1.0";
276
+ //#endregion
277
+ //#region src/build/packageJson.ts
278
+ function generatePackageJson(options, externals) {
279
+ const deps = getPackageDeps(options.context);
280
+ const exclude = [
281
+ name,
282
+ "connect",
283
+ "cors"
284
+ ];
285
+ const mockPkg = {
286
+ name: "mock-server",
287
+ type: "module",
288
+ scripts: { start: "node index.js" },
289
+ dependencies: {
290
+ connect: "^3.7.0",
291
+ [name]: `^${version}`,
292
+ cors: "^2.8.5"
293
+ }
294
+ };
295
+ externals.filter((dep) => !exclude.includes(dep)).forEach((dep) => {
296
+ mockPkg.dependencies[dep] = deps[dep] || "latest";
297
+ });
298
+ return JSON.stringify(mockPkg, null, 2);
299
+ }
300
+ //#endregion
301
+ //#region src/build/serverEntryCode.ts
302
+ function generatorServerEntryCode({ proxies, wsPrefix, cookiesOptions, bodyParserOptions, priority, build }) {
303
+ const { serverPort, log } = build;
304
+ return `import { createServer } from 'node:http';
305
+ import connect from 'connect';
306
+ import corsMiddleware from 'cors';
307
+ import {
308
+ baseMiddleware,
309
+ createLogger,
310
+ mockWebSocket,
311
+ processMockData,
312
+ processRawData
313
+ } from 'rspack-plugin-mock/server';
314
+ import rawData from './mock-data.js';
315
+
316
+ const app = connect();
317
+ const server = createServer(app);
318
+ const logger = createLogger('mock-server', '${log}');
319
+ const proxies = ${JSON.stringify(proxies)};
320
+ const wsProxies = ${JSON.stringify(toArray(wsPrefix))};
321
+ const cookiesOptions = ${JSON.stringify(cookiesOptions)};
322
+ const bodyParserOptions = ${JSON.stringify(bodyParserOptions)};
323
+ const priority = ${JSON.stringify(priority)};
324
+ const mockConfig = {
325
+ mockData: processMockData(processRawData(rawData)),
326
+ on: () => {},
327
+ };
328
+
329
+ mockWebSocket(mockConfig, server, { wsProxies, cookiesOptions, logger });
330
+
331
+ app.use(corsMiddleware());
332
+ app.use(baseMiddleware(mockConfig, {
333
+ formidableOptions: { multiples: true },
334
+ proxies,
335
+ priority,
336
+ cookiesOptions,
337
+ bodyParserOptions,
338
+ logger,
339
+ }));
340
+
341
+ server.listen(${serverPort});
342
+
343
+ console.log('listen: http://localhost:${serverPort}');
344
+ `;
345
+ }
346
+ //#endregion
347
+ //#region src/build/writeEntryFile.ts
348
+ async function writeMockEntryFile(entryFile, files, cwd, dir) {
349
+ const importers = [];
350
+ const exporters = [];
351
+ for (const [index, filepath] of files.entries()) {
352
+ const relative = normalizePath(path.join(dir, filepath));
353
+ const file = normalizePath(path.join(cwd, relative));
354
+ importers.push(`import * as m${index} from '${file}'`);
355
+ exporters.push(`[m${index}, '${relative}']`);
356
+ }
357
+ const code = `${importers.join("\n")}\n\nexport default [\n ${exporters.join(",\n ")}\n]`;
358
+ const dirname = path.dirname(entryFile);
359
+ if (!fs.existsSync(dirname)) await fsp.mkdir(dirname, { recursive: true });
360
+ await fsp.writeFile(entryFile, code, "utf8");
361
+ }
362
+ //#endregion
363
+ //#region src/build/generate.ts
364
+ async function buildMockServer(options, outputDir) {
365
+ const buildOptions = options.build;
366
+ const entryFile = path.resolve(process.cwd(), "node_modules/.cache/mock-server/mock-server.ts");
367
+ const { pattern, ignore } = createMatcher(options.include, options.exclude);
368
+ await writeMockEntryFile(entryFile, await glob(pattern, {
369
+ ignore,
370
+ cwd: path.join(options.cwd, options.dir)
371
+ }), options.cwd, options.dir);
372
+ const { code, externals } = await transformWithRspack({
373
+ entryFile,
374
+ cwd: options.cwd,
375
+ plugins: options.plugins,
376
+ alias: options.alias
377
+ });
378
+ await fsp.unlink(entryFile);
379
+ const outputList = [
380
+ {
381
+ filename: "mock-data.js",
382
+ source: code
383
+ },
384
+ {
385
+ filename: "index.js",
386
+ source: generatorServerEntryCode(options)
387
+ },
388
+ {
389
+ filename: "package.json",
390
+ source: generatePackageJson(options, externals)
391
+ }
392
+ ];
393
+ if (options.record.enabled && buildOptions.includeRecord) {
394
+ const files = await glob(path.join(options.record.dir, "**/*.json"), {
395
+ cwd: options.cwd,
396
+ dot: true
397
+ });
398
+ for (const file of files) outputList.push({
399
+ filename: path.join(outputDir, file),
400
+ source: await fsp.readFile(path.join(options.cwd, file), "utf-8")
401
+ });
402
+ }
403
+ const dist = path.resolve(outputDir, options.build.dist);
404
+ options.logger.info(`${ansis.green("✓")} generate mock server in ${ansis.cyan(path.relative(process.cwd(), dist))}`);
405
+ if (!fs.existsSync(dist)) await fsp.mkdir(dist, { recursive: true });
406
+ for (const { filename, source } of outputList) {
407
+ await fsp.writeFile(path.join(dist, filename), source, "utf8");
408
+ const sourceSize = (source.length / 1024).toFixed(2);
409
+ const space = filename.length < 24 ? " ".repeat(24 - filename.length) : "";
410
+ options.logger.info(` ${ansis.green(filename)}${space}${ansis.bold.dim(`${sourceSize} kB`)}`);
411
+ }
412
+ }
413
+ //#endregion
414
+ //#region src/core/options.ts
415
+ function resolvePluginOptions({ prefix = [], wsPrefix = [], cwd, dir = "mock", include = ["**/*.mock.{js,ts,cjs,mjs,json,json5}"], exclude = [], reload = false, log = "info", cors = true, formidableOptions = {}, build = false, cookiesOptions = {}, bodyParserOptions = {}, priority = {}, activeScene = [], record = false, replay }, { alias, context, plugins, proxies: rawProxies }) {
416
+ const logger = createLogger("rspack:mock", isBoolean(log) ? log ? "info" : "error" : log);
417
+ const proxies = [...toArray(prefix), ...rawProxies];
418
+ const wsProxies = toArray(wsPrefix);
419
+ if (!proxies.length && !wsProxies.length) logger.warn(`No proxy was configured, mock server will not work. See ${ansis.cyan("https://vite-plugin-mock-dev-server.netlify.app/guide/usage")}`);
420
+ const enabled = !!cors;
421
+ let corsOptions = {};
422
+ if (enabled && isPlainObject(cors)) corsOptions = {
423
+ ...corsOptions,
424
+ ...cors
425
+ };
426
+ cwd = cwd || context || process.cwd();
427
+ const resolvedRecord = resolveRecordOptions(cwd, dir, record);
428
+ return {
429
+ enabled: true,
430
+ prefix,
431
+ wsPrefix,
432
+ cwd,
433
+ dir,
434
+ include,
435
+ exclude,
436
+ reload,
437
+ cors: enabled ? corsOptions : false,
438
+ cookiesOptions,
439
+ log,
440
+ formidableOptions: {
441
+ multiples: true,
442
+ ...formidableOptions
443
+ },
444
+ bodyParserOptions,
445
+ priority,
446
+ build: build ? {
447
+ serverPort: 8080,
448
+ dist: "mockServer",
449
+ log: "error",
450
+ ...typeof build === "object" ? build : {}
451
+ } : false,
452
+ alias,
453
+ plugins,
454
+ proxies,
455
+ wsProxies,
456
+ logger,
457
+ activeScene: toArray(activeScene),
458
+ record: resolvedRecord,
459
+ replay: replay ?? resolvedRecord.enabled ?? false
460
+ };
461
+ }
462
+ /**
463
+ * Resolve record options
464
+ *
465
+ * 解析录制配置
466
+ *
467
+ * @param cwd - Current working directory / 当前工作目录
468
+ * @param dir - Mock context directory / 模拟上下文目录
469
+ * @param record - Record options / 录制配置
470
+ * @returns Resolved record options / 解析后的录制配置
471
+ */
472
+ function resolveRecordOptions(cwd, dir, record) {
473
+ const recordOptions = typeof record === "boolean" ? { enabled: record } : record;
474
+ const expires = recordOptions?.expires ?? 0;
475
+ return {
476
+ enabled: recordOptions?.enabled ?? false,
477
+ cwd,
478
+ dir: path.join(dir, recordOptions?.dir || ".recordings"),
479
+ overwrite: recordOptions?.overwrite ?? true,
480
+ status: toArray(recordOptions?.status).map(Number),
481
+ expires: expires === 0 ? Number.MAX_SAFE_INTEGER : expires * 1e3,
482
+ gitignore: recordOptions?.gitignore ?? true,
483
+ filter: recordOptions?.filter || (() => true)
484
+ };
485
+ }
486
+ //#endregion
487
+ export { buildMockServer as n, createMockCompiler as r, resolvePluginOptions as t };
@@ -0,0 +1,8 @@
1
+ import { A as ResponseBody, C as HandleFunction, D as MockResponse, E as MockRequest, M as CookiesOption, N as GetCookieOption, O as NextFunction, P as SetCookieOption, S as ExtraRequest, T as Method, _ as RecordedMeta, a as MockWebsocketItem, b as RecordedRes, c as MockHttpItem, d as LogType, f as MockMatchPriority, g as RecordOptions, h as ServerBuildOption, i as MockOptions, j as SimpleHandleFunction, k as NextHandleFunction, l as BodyParserOptions, m as MockServerPluginOptions, n as HttpProxyPlugin, o as WebSocketSetupContext, p as MockMatchSpecialPriority, r as PathFilter, s as MockErrorConfig, t as FormidableFile, u as LogLevel, v as RecordedReq, w as Headers, x as ResolvedRecordOptions, y as RecordedRequest } from "./index-BMMGM-eD.js";
2
+ import { DefineMockDataOptions, HeaderStream, MockData, SSEMessage, createDefineMock, createSSEStream, defineMock, defineMockData } from "./helper.js";
3
+ import { RsbuildPlugin } from "@rsbuild/core";
4
+
5
+ //#region src/core/rsbuild.d.ts
6
+ declare function pluginMockServer(options?: MockServerPluginOptions): RsbuildPlugin;
7
+ //#endregion
8
+ export { BodyParserOptions, CookiesOption, DefineMockDataOptions, ExtraRequest, type FormidableFile, GetCookieOption, HandleFunction, HeaderStream, Headers, HttpProxyPlugin, LogLevel, LogType, Method, MockData, MockErrorConfig, type MockHttpItem, MockMatchPriority, MockMatchSpecialPriority, type MockOptions, type MockRequest, MockResponse, type MockServerPluginOptions, type MockWebsocketItem, NextFunction, NextHandleFunction, PathFilter, RecordOptions, RecordedMeta, RecordedReq, RecordedRequest, RecordedRes, ResolvedRecordOptions, ResponseBody, SSEMessage, ServerBuildOption, SetCookieOption, SimpleHandleFunction, WebSocketSetupContext, createDefineMock, createSSEStream, defineMock, defineMockData, pluginMockServer };
@@ -0,0 +1,80 @@
1
+ import { a as rewriteRequest, i as createMockMiddleware, o as Recorder, r as mockWebSocket } from "./logger-CzeuHKAL.js";
2
+ import { n as buildMockServer, r as createMockCompiler, t as resolvePluginOptions } from "./options-CI0LRpJZ.js";
3
+ import { createDefineMock, createSSEStream, defineMock, defineMockData } from "./helper.js";
4
+ import path from "node:path";
5
+ import process from "node:process";
6
+ import { isArray, objectEntries, toArray } from "@pengzhanbo/utils";
7
+ import rspack from "@rspack/core";
8
+ //#region src/core/rsbuild.ts
9
+ function pluginMockServer(options = {}) {
10
+ return {
11
+ name: "plugin-mock-server",
12
+ setup(api) {
13
+ if (options.enabled === false) return;
14
+ const rsbuildConfig = api.getRsbuildConfig();
15
+ const resolvedOptions = resolvePluginOptions(options, {
16
+ proxies: resolveConfigProxies(rsbuildConfig),
17
+ alias: {},
18
+ context: api.context.rootPath,
19
+ plugins: [new rspack.DefinePlugin(rsbuildConfig.source?.define || {})]
20
+ });
21
+ if (api.context.action === "build") {
22
+ if (resolvedOptions.build) api.onAfterBuild(async () => {
23
+ const config = api.getNormalizedConfig();
24
+ await buildMockServer(resolvedOptions, path.resolve(process.cwd(), config.output.distPath.root || "dist"));
25
+ });
26
+ return;
27
+ }
28
+ const mockCompiler = createMockCompiler(resolvedOptions);
29
+ api.onAfterCreateCompiler(({ compiler }) => {
30
+ if ("compilers" in compiler) compiler.compilers.forEach((compiler) => {
31
+ mockCompiler.updateAlias(compiler.options.resolve?.alias || {});
32
+ });
33
+ else mockCompiler.updateAlias(compiler.options.resolve?.alias || {});
34
+ });
35
+ let recorder = null;
36
+ if (resolvedOptions.record.enabled) recorder = new Recorder(resolvedOptions.record);
37
+ function wrapProxyOptions(options) {
38
+ const plugins = options.plugins ??= [];
39
+ plugins.push((proxyServer) => proxyServer.on("proxyReq", rewriteRequest));
40
+ if (resolvedOptions.record.enabled && recorder) plugins.push(recorder.getPlugin());
41
+ return options;
42
+ }
43
+ api.modifyRsbuildConfig((config) => {
44
+ if (!config.server?.proxy) return;
45
+ if (isArray(config.server.proxy)) config.server.proxy = config.server.proxy.map((item) => item.ws ? item : wrapProxyOptions(item));
46
+ else if (config.server.proxy) {
47
+ const proxy = config.server.proxy;
48
+ Object.keys(proxy).forEach((key) => {
49
+ const target = proxy[key];
50
+ const options = typeof target === "string" ? { target } : target;
51
+ if (options.ws) return;
52
+ proxy[key] = wrapProxyOptions(options);
53
+ });
54
+ }
55
+ });
56
+ function initMockServer(server) {
57
+ server.middlewares.use(createMockMiddleware(mockCompiler, resolvedOptions));
58
+ if (resolvedOptions.reload && api.context.action === "dev") mockCompiler.on("update", () => server.sockWrite("static-changed"));
59
+ if (toArray(resolvedOptions.wsPrefix).length > 0) mockWebSocket(mockCompiler, server.httpServer, resolvedOptions);
60
+ mockCompiler.run();
61
+ }
62
+ api.onBeforeStartDevServer(({ server }) => initMockServer(server));
63
+ api.onBeforeStartPreviewServer(({ server }) => initMockServer(server));
64
+ api.onExit(() => mockCompiler.close());
65
+ }
66
+ };
67
+ }
68
+ function resolveConfigProxies(config) {
69
+ config.server ??= {};
70
+ const proxy = config.server.proxy ??= {};
71
+ const proxies = [];
72
+ if (isArray(proxy)) {
73
+ for (const item of proxy) if (item.pathFilter && !item.ws) proxies.push(...toArray(item.pathFilter));
74
+ } else objectEntries(proxy).forEach(([pathFilter, opt]) => {
75
+ if (typeof opt === "string" || !opt.ws) proxies.push(pathFilter);
76
+ });
77
+ return proxies;
78
+ }
79
+ //#endregion
80
+ export { createDefineMock, createSSEStream, defineMock, defineMockData, pluginMockServer };
@@ -0,0 +1,113 @@
1
+ import { a as MockWebsocketItem, c as MockHttpItem, h as ServerBuildOption, i as MockOptions, k as NextHandleFunction, m as MockServerPluginOptions, r as PathFilter, u as LogLevel, x as ResolvedRecordOptions } from "./index-BMMGM-eD.js";
2
+ import { Arrayable } from "@pengzhanbo/utils";
3
+ import { Compiler, RspackPluginInstance } from "@rspack/core";
4
+ import { Matcher } from "picomatch";
5
+ import EventEmitter from "node:events";
6
+ import { FSWatcher } from "chokidar";
7
+ import { CorsOptions } from "cors";
8
+ import { Server } from "node:http";
9
+ import { Http2SecureServer } from "node:http2";
10
+
11
+ //#region src/core/logger.d.ts
12
+ interface Logger {
13
+ debug: (msg: string, level?: boolean | LogLevel) => void;
14
+ info: (msg: string, level?: boolean | LogLevel) => void;
15
+ warn: (msg: string, level?: boolean | LogLevel) => void;
16
+ error: (msg: string, level?: boolean | LogLevel) => void;
17
+ }
18
+ declare const logLevels: Record<LogLevel, number>;
19
+ declare function createLogger(prefix: string, defaultLevel?: LogLevel): Logger;
20
+ //#endregion
21
+ //#region src/core/options.d.ts
22
+ interface ResolvedCompilerOptions {
23
+ alias: Record<string, Arrayable<false | string>>;
24
+ proxies: PathFilter[];
25
+ wsProxies: PathFilter[];
26
+ plugins: RspackPluginInstance[];
27
+ context?: string;
28
+ }
29
+ type ResolvePluginOptions = Required<Omit<MockServerPluginOptions, "build">> & ResolvedCompilerOptions & {
30
+ logger: Logger;
31
+ build: false | ServerBuildOption;
32
+ cors: false | CorsOptions;
33
+ record: ResolvedRecordOptions;
34
+ activeScene: string[];
35
+ };
36
+ //#endregion
37
+ //#region src/compiler/mockCompiler.d.ts
38
+ declare class MockCompiler extends EventEmitter {
39
+ options: ResolvePluginOptions;
40
+ cwd: string;
41
+ mockWatcher!: FSWatcher;
42
+ entryFile!: string;
43
+ deps: string[];
44
+ isESM: boolean;
45
+ private _mockData;
46
+ private watchInfo?;
47
+ compiler?: Compiler | null;
48
+ constructor(options: ResolvePluginOptions);
49
+ get mockData(): Record<string, MockOptions>;
50
+ run(): Promise<void>;
51
+ close(): void;
52
+ updateAlias(alias: Record<string, false | string | (string | false)[]>): void;
53
+ updateMockEntry(): Promise<void>;
54
+ watchMockFiles(isMatch: Matcher): void;
55
+ }
56
+ //#endregion
57
+ //#region src/compiler/processData.d.ts
58
+ declare function processRawData(rawData: (readonly [any, string])[]): (MockHttpItem | MockWebsocketItem | MockOptions)[];
59
+ declare function processMockData(mockList: (MockHttpItem | MockWebsocketItem | MockOptions)[]): Record<string, MockOptions>;
60
+ declare function sortByValidator(mocks: MockOptions): (MockHttpItem | MockWebsocketItem)[];
61
+ //#endregion
62
+ //#region src/mockHttp/middleware.d.ts
63
+ interface CreateMockMiddlewareOptions extends Pick<ResolvePluginOptions, "formidableOptions" | "cookiesOptions" | "bodyParserOptions" | "priority" | "record" | "replay" | "activeScene"> {
64
+ proxies: PathFilter[];
65
+ logger: Logger;
66
+ cors: false | CorsOptions;
67
+ }
68
+ /**
69
+ * Create mock middleware
70
+ *
71
+ * 创建 Mock 中间件
72
+ *
73
+ * @param compiler - Compiler instance / 编译器实例
74
+ * @param options - Middleware options / 中间件配置项
75
+ * @param options.formidableOptions - Formidable options / Formidable 配置项
76
+ * @param options.bodyParserOptions - Body parser options / 请求体解析配置项
77
+ * @param options.proxies - Proxy paths / 代理路径
78
+ * @param options.cookiesOptions - Cookies options / Cookies 配置项
79
+ * @param options.logger - Logger instance / 日志实例
80
+ * @param options.priority - Path matching priority / 路径匹配优先级
81
+ * @param options.cors - CORS options / CORS 配置项
82
+ * @param options.record - Record options / 录制配置项
83
+ * @param options.replay - Replay options / 回放配置项
84
+ * @param options.activeScene - Active scene / 活动场景
85
+ *
86
+ * @returns Connect middleware function / Connect 中间件函数
87
+ */
88
+ declare function createMockMiddleware(compiler: MockCompiler, {
89
+ formidableOptions,
90
+ bodyParserOptions,
91
+ proxies,
92
+ cookiesOptions,
93
+ logger,
94
+ priority,
95
+ cors: corsOptions,
96
+ record,
97
+ replay,
98
+ activeScene
99
+ }: CreateMockMiddlewareOptions): NextHandleFunction;
100
+ //#endregion
101
+ //#region src/mockWebsocket/server.d.ts
102
+ interface MockSocketOptions {
103
+ wsProxies: PathFilter[];
104
+ cookiesOptions: MockServerPluginOptions["cookiesOptions"];
105
+ logger: Logger;
106
+ }
107
+ declare function mockWebSocket(compiler: MockCompiler, httpServer: Server | Http2SecureServer | null, {
108
+ wsProxies: proxies,
109
+ cookiesOptions,
110
+ logger
111
+ }: MockSocketOptions): void;
112
+ //#endregion
113
+ export { processMockData as a, MockCompiler as c, createLogger as d, logLevels as f, createMockMiddleware as i, ResolvePluginOptions as l, mockWebSocket as n, processRawData as o, CreateMockMiddlewareOptions as r, sortByValidator as s, MockSocketOptions as t, Logger as u };
@@ -0,0 +1,2 @@
1
+ import { a as processMockData, d as createLogger, f as logLevels, i as createMockMiddleware, n as mockWebSocket, o as processRawData, r as CreateMockMiddlewareOptions, s as sortByValidator, t as MockSocketOptions, u as Logger } from "./server-pC78IYdH.js";
2
+ export { CreateMockMiddlewareOptions, Logger, MockSocketOptions, createLogger, createMockMiddleware, logLevels, mockWebSocket, processMockData, processRawData, sortByValidator };
package/dist/server.js ADDED
@@ -0,0 +1,2 @@
1
+ import { c as processRawData, i as createMockMiddleware, l as sortByValidator, n as logLevels, r as mockWebSocket, s as processMockData, t as createLogger } from "./logger-CzeuHKAL.js";
2
+ export { createLogger, createMockMiddleware, logLevels, mockWebSocket, processMockData, processRawData, sortByValidator };