@kubb/plugin-msw 5.0.0-alpha.9 → 5.0.0-beta.100

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.js CHANGED
@@ -1,84 +1,514 @@
1
- import "./chunk--u3MIqq1.js";
2
- import { a as camelCase } from "./components-DgtTZkWX.js";
3
- import { n as handlersGenerator, t as mswGenerator } from "./generators-CvyZTxOm.js";
4
- import path from "node:path";
5
- import { createPlugin, getBarrelFiles, getMode } from "@kubb/core";
1
+ import "./rolldown-runtime-C0LytTxp.js";
2
+ import { Resolver, Url, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
6
3
  import { pluginFakerName } from "@kubb/plugin-faker";
7
- import { OperationGenerator, pluginOasName } from "@kubb/plugin-oas";
8
- import { pluginTsName } from "@kubb/plugin-ts";
4
+ import { createFunctionParameter, createFunctionParameters, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
5
+ import { File, Function, jsxRenderer } from "kubb/jsx";
6
+ import { jsx, jsxs } from "kubb/jsx/jsx-runtime";
7
+ //#region ../../internals/shared/src/operation.ts
8
+ function getStatusCodeNumber(statusCode) {
9
+ const code = Number(statusCode);
10
+ return Number.isNaN(code) ? null : code;
11
+ }
12
+ function isSuccessStatusCode(statusCode) {
13
+ const code = getStatusCodeNumber(statusCode);
14
+ return code !== null && code >= 200 && code < 300;
15
+ }
16
+ function getSuccessResponses(responses) {
17
+ return responses.filter((response) => isSuccessStatusCode(response.statusCode));
18
+ }
19
+ function getOperationSuccessResponses(node) {
20
+ return getSuccessResponses(node.responses);
21
+ }
22
+ function getPrimarySuccessResponse(node) {
23
+ return getOperationSuccessResponses(node)[0] ?? null;
24
+ }
25
+ function resolveResponseTypes(node, resolver) {
26
+ const types = [];
27
+ for (const response of node.responses) {
28
+ if (response.statusCode === "default") {
29
+ types.push(["default", resolver.response.response(node)]);
30
+ continue;
31
+ }
32
+ const code = getStatusCodeNumber(response.statusCode);
33
+ if (code === null) continue;
34
+ types.push([code, isSuccessStatusCode(code) ? resolver.response.response(node) : resolver.response.status(node, response.statusCode)]);
35
+ }
36
+ return types;
37
+ }
38
+ //#endregion
39
+ //#region ../../internals/utils/src/casing.ts
40
+ /**
41
+ * Shared implementation for camelCase and PascalCase conversion.
42
+ * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
43
+ * and capitalizes each word according to `pascal`.
44
+ *
45
+ * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
46
+ */
47
+ function toCamelOrPascal(text, pascal) {
48
+ return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
49
+ if (word.length > 1 && word === word.toUpperCase()) return word;
50
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
51
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
52
+ }
53
+ /**
54
+ * Converts `text` to camelCase.
55
+ *
56
+ * @example Word boundaries
57
+ * `camelCase('hello-world') // 'helloWorld'`
58
+ *
59
+ * @example With a prefix
60
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
61
+ */
62
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
63
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
64
+ }
65
+ //#endregion
66
+ //#region ../../internals/shared/src/group.ts
67
+ /**
68
+ * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
69
+ * shared default naming so every plugin groups output consistently:
70
+ *
71
+ * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
72
+ * - other groups use the camelCased group (`pet store` → `petStore`).
73
+ *
74
+ * A user-provided `group.name` always wins over the default namer, so callers stay in
75
+ * control of their output folders. Returns `null` when grouping is disabled, matching the
76
+ * per-plugin convention.
77
+ *
78
+ * @param group - The user-supplied group option, or `undefined` to disable grouping.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * createGroupConfig(group) // shared across every plugin
83
+ * ```
84
+ */
85
+ function createGroupConfig(group) {
86
+ if (!group) return null;
87
+ const defaultName = (ctx) => {
88
+ if (group.type === "path") return `${ctx.group.split("/")[1]}`;
89
+ return camelCase(ctx.group);
90
+ };
91
+ return {
92
+ ...group,
93
+ name: group.name ? group.name : defaultName
94
+ };
95
+ }
96
+ //#endregion
97
+ //#region src/generators/handlersGenerator.ts
98
+ /**
99
+ * Aggregate generator enabled by `pluginMsw({ handlers: true })`. Emits a
100
+ * `handlers.ts` file that re-exports every generated handler in operation
101
+ * order, ready to spread into `setupServer(...handlers)` or
102
+ * `setupWorker(...handlers)`.
103
+ */
104
+ const handlersGenerator = defineGenerator({
105
+ name: "plugin-msw",
106
+ operations(nodes, ctx) {
107
+ const { resolver, config, root } = ctx;
108
+ const { output, group } = ctx.options;
109
+ const handlersName = resolver.handler.listName();
110
+ const file = resolver.file({
111
+ name: handlersName,
112
+ extname: ".ts",
113
+ root,
114
+ output,
115
+ group: group ?? void 0
116
+ });
117
+ const imports = nodes.map((node) => {
118
+ const operationName = resolver.handler.name(node);
119
+ const operationFile = resolver.file({
120
+ name: resolver.name(node.operationId),
121
+ extname: ".ts",
122
+ tag: node.tags[0] ?? "default",
123
+ path: node.path,
124
+ root,
125
+ output,
126
+ group: group ?? void 0
127
+ });
128
+ return ast.factory.createImport({
129
+ name: [operationName],
130
+ root: file.path,
131
+ path: operationFile.path
132
+ });
133
+ });
134
+ const handlers = nodes.map((node) => `${resolver.handler.name(node)}()`);
135
+ return [ast.factory.createFile({
136
+ baseName: file.baseName,
137
+ path: file.path,
138
+ meta: file.meta,
139
+ banner: resolver.default.banner(ctx.meta, {
140
+ output,
141
+ config,
142
+ file: {
143
+ path: file.path,
144
+ baseName: file.baseName
145
+ }
146
+ }),
147
+ footer: resolver.default.footer(ctx.meta, {
148
+ output,
149
+ config,
150
+ file: {
151
+ path: file.path,
152
+ baseName: file.baseName
153
+ }
154
+ }),
155
+ imports,
156
+ sources: [ast.factory.createSource({
157
+ name: handlersName,
158
+ isIndexable: true,
159
+ isExportable: true,
160
+ nodes: [ast.factory.createText(`export const ${handlersName} = ${JSON.stringify(handlers).replaceAll("\"", "")} as const`)]
161
+ })]
162
+ })];
163
+ }
164
+ });
165
+ //#endregion
166
+ //#region src/utils.ts
167
+ /**
168
+ * Gets the content type from a response, defaulting to 'application/json' if a schema exists.
169
+ */
170
+ function getContentType(response) {
171
+ if (!hasResponseSchema(response)) return null;
172
+ return getResponseContentType(response) ?? "application/json";
173
+ }
174
+ /**
175
+ * Determines if a response has a schema that is not void or any.
176
+ */
177
+ function hasResponseSchema(response) {
178
+ const schema = response?.content?.find((entry) => entry.schema)?.schema;
179
+ return !!schema && schema.type !== "void" && schema.type !== "any";
180
+ }
181
+ /**
182
+ * Picks the content type used for the mocked response header. When a response declares multiple
183
+ * content types, JSON is preferred (the faker mock body is JSON), otherwise the first declared type.
184
+ */
185
+ function getResponseContentType(response) {
186
+ const contents = response?.content ?? [];
187
+ const value = (contents.find((entry) => {
188
+ const baseType = entry.contentType?.split(";")[0]?.trim().toLowerCase();
189
+ return baseType === "application/json" || baseType?.endsWith("+json");
190
+ }) ?? contents[0])?.contentType;
191
+ return typeof value === "string" && value.length > 0 ? value : null;
192
+ }
193
+ /**
194
+ * Converts an HTTP method to its lowercase MSW equivalent (e.g., 'POST' → 'post').
195
+ */
196
+ function getMswMethod(node) {
197
+ return ast.isHttpOperationNode(node) ? node.method.toLowerCase() : "";
198
+ }
199
+ /**
200
+ * Resolves faker metadata for an MSW operation, including response name and file path.
201
+ */
202
+ function resolveFakerMeta(node, options) {
203
+ const { root, fakerResolver, fakerOutput, fakerGroup } = options;
204
+ const tag = node.tags[0] ?? "default";
205
+ return {
206
+ name: fakerResolver.response.response(node),
207
+ file: fakerResolver.file({
208
+ name: node.operationId,
209
+ extname: ".ts",
210
+ tag,
211
+ path: node.path,
212
+ root,
213
+ output: fakerOutput,
214
+ group: fakerGroup ?? void 0
215
+ })
216
+ };
217
+ }
218
+ //#endregion
219
+ //#region src/components/Mock.tsx
220
+ const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
221
+ function Mock({ baseURL = "", name, fakerName, typeName, requestTypeName, node }) {
222
+ const method = getMswMethod(node);
223
+ const successResponse = getPrimarySuccessResponse(node);
224
+ const statusCode = successResponse ? Number(successResponse.statusCode) : 200;
225
+ const contentType = getContentType(successResponse);
226
+ const url = ast.isHttpOperationNode(node) ? Url.toPath(node.path) : "";
227
+ const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean);
228
+ const dataType = hasResponseSchema(successResponse) ? typeName : "string | number | boolean | null | object";
229
+ const paramType = fakerName ? typeName : dataType;
230
+ const callbackType = requestTypeName ? `HttpResponseResolver<Record<string, string>, ${requestTypeName}>` : `((info: Parameters<Parameters<typeof http.${method}>[1]>[0]) => Response | Promise<Response>)`;
231
+ const params = declarationPrinter$1.print(createFunctionParameters({ params: [createFunctionParameter({
232
+ name: "data",
233
+ type: `${paramType} | ${callbackType}`,
234
+ optional: true
235
+ })] }));
236
+ const httpCall = requestTypeName ? `http.${method}<Record<string, string>, ${requestTypeName}>` : `http.${method}`;
237
+ const requestUrl = `${baseURL}${url.replace(/([^/]):/g, "$1\\\\:")}`;
238
+ const urlLiteral = fakerName ? `'${requestUrl}'` : `\`${requestUrl}\``;
239
+ const responseBody = fakerName ? `JSON.stringify(data || ${fakerName}(data))` : "JSON.stringify(data)";
240
+ return /* @__PURE__ */ jsx(File.Source, {
241
+ name,
242
+ isIndexable: true,
243
+ isExportable: true,
244
+ children: /* @__PURE__ */ jsx(Function, {
245
+ name,
246
+ export: true,
247
+ params: params ?? "",
248
+ children: `return ${httpCall}(${urlLiteral}, function handler(info) {
249
+ if(typeof data === 'function') return data(info)
250
+
251
+ return new Response(${responseBody}, {
252
+ status: ${statusCode},
253
+ ${headers.length ? ` headers: {
254
+ ${headers.join(", \n")}
255
+ },` : ""}
256
+ })
257
+ })`
258
+ })
259
+ });
260
+ }
261
+ //#endregion
262
+ //#region src/components/Response.tsx
263
+ const declarationPrinter = functionPrinter({ mode: "declaration" });
264
+ function Response({ name, typeName, response }) {
265
+ const statusCode = Number(response.statusCode);
266
+ const contentType = getContentType(response);
267
+ const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean);
268
+ const params = declarationPrinter.print(createFunctionParameters({ params: [createFunctionParameter({
269
+ name: "data",
270
+ type: typeName,
271
+ optional: !hasResponseSchema(response)
272
+ })] }));
273
+ const responseName = `${name}Response${statusCode}`;
274
+ return /* @__PURE__ */ jsx(File.Source, {
275
+ name: responseName,
276
+ isIndexable: true,
277
+ isExportable: true,
278
+ children: /* @__PURE__ */ jsx(Function, {
279
+ name: responseName,
280
+ export: true,
281
+ params: params ?? "",
282
+ children: `
283
+ return new Response(JSON.stringify(data), {
284
+ status: ${statusCode},
285
+ ${headers.length ? ` headers: {
286
+ ${headers.join(", \n")}
287
+ },` : ""}
288
+ })`
289
+ })
290
+ });
291
+ }
292
+ //#endregion
293
+ //#region src/generators/mswGenerator.tsx
294
+ /**
295
+ * Built-in operation generator for `@kubb/plugin-msw`. Emits one MSW handler
296
+ * per OpenAPI operation. With `parser: 'faker'` the handler returns a value
297
+ * from `@kubb/plugin-faker`; with `parser: 'data'` it returns a typed empty
298
+ * payload for tests to fill in.
299
+ */
300
+ const mswGenerator = defineGenerator({
301
+ name: "msw",
302
+ renderer: jsxRenderer,
303
+ operation(node, ctx) {
304
+ if (!ast.isHttpOperationNode(node)) return null;
305
+ const { driver, resolver, config, root } = ctx;
306
+ const { output, parser, baseURL, group } = ctx.options;
307
+ const fileName = resolver.name(node.operationId);
308
+ const mock = {
309
+ name: resolver.handler.name(node),
310
+ file: resolver.file({
311
+ name: fileName,
312
+ extname: ".ts",
313
+ tag: node.tags[0] ?? "default",
314
+ path: node.path,
315
+ root,
316
+ output,
317
+ group: group ?? void 0
318
+ })
319
+ };
320
+ const fakerPlugin = parser === "faker" ? driver.getPlugin(pluginFakerName) : null;
321
+ const faker = parser === "faker" && fakerPlugin ? resolveFakerMeta(node, {
322
+ root,
323
+ fakerResolver: driver.getResolver(pluginFakerName),
324
+ fakerOutput: fakerPlugin.options?.output ?? output,
325
+ fakerGroup: fakerPlugin.options?.group ?? null
326
+ }) : null;
327
+ const pluginTs = driver.getPlugin(pluginTsName);
328
+ if (!pluginTs) return null;
329
+ const tsResolver = driver.getResolver(pluginTsName);
330
+ const type = {
331
+ file: tsResolver.file({
332
+ name: node.operationId,
333
+ extname: ".ts",
334
+ tag: node.tags[0] ?? "default",
335
+ path: node.path,
336
+ root,
337
+ output: pluginTs.options?.output ?? output,
338
+ group: pluginTs.options?.group ?? void 0
339
+ }),
340
+ responseName: tsResolver.response.response(node)
341
+ };
342
+ const types = resolveResponseTypes(node, tsResolver);
343
+ const hasSuccessSchema = getOperationSuccessResponses(node).some((response) => !!response.content?.[0]?.schema);
344
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.response.body(node) : null;
345
+ return /* @__PURE__ */ jsxs(File, {
346
+ baseName: mock.file.baseName,
347
+ path: mock.file.path,
348
+ meta: mock.file.meta,
349
+ banner: resolver.default.banner(ctx.meta, {
350
+ output,
351
+ config,
352
+ file: {
353
+ path: mock.file.path,
354
+ baseName: mock.file.baseName
355
+ }
356
+ }),
357
+ footer: resolver.default.footer(ctx.meta, {
358
+ output,
359
+ config,
360
+ file: {
361
+ path: mock.file.path,
362
+ baseName: mock.file.baseName
363
+ }
364
+ }),
365
+ children: [
366
+ /* @__PURE__ */ jsx(File.Import, {
367
+ name: ["http"],
368
+ path: "msw"
369
+ }),
370
+ /* @__PURE__ */ jsx(File.Import, {
371
+ name: ["HttpResponseResolver"],
372
+ isTypeOnly: true,
373
+ path: "msw"
374
+ }),
375
+ /* @__PURE__ */ jsx(File.Import, {
376
+ name: Array.from(/* @__PURE__ */ new Set([
377
+ type.responseName,
378
+ ...types.map((t) => t[1]),
379
+ ...requestName ? [requestName] : []
380
+ ])),
381
+ path: type.file.path,
382
+ root: mock.file.path,
383
+ isTypeOnly: true
384
+ }),
385
+ parser === "faker" && faker && /* @__PURE__ */ jsx(File.Import, {
386
+ name: [faker.name],
387
+ root: mock.file.path,
388
+ path: faker.file.path
389
+ }),
390
+ types.filter(([code]) => code !== "default").map(([code, typeName]) => {
391
+ const response = node.responses.find((item) => item.statusCode === String(code));
392
+ if (!response) return null;
393
+ return /* @__PURE__ */ jsx(Response, {
394
+ typeName,
395
+ response,
396
+ name: mock.name
397
+ }, typeName);
398
+ }),
399
+ parser === "faker" && faker && hasSuccessSchema ? /* @__PURE__ */ jsx(Mock, {
400
+ name: mock.name,
401
+ typeName: type.responseName,
402
+ requestTypeName: requestName,
403
+ fakerName: faker.name,
404
+ node,
405
+ baseURL
406
+ }) : /* @__PURE__ */ jsx(Mock, {
407
+ name: mock.name,
408
+ typeName: type.responseName,
409
+ requestTypeName: requestName,
410
+ node,
411
+ baseURL
412
+ })
413
+ ]
414
+ });
415
+ }
416
+ });
417
+ //#endregion
418
+ //#region src/resolvers/resolverMsw.ts
419
+ /**
420
+ * Default resolver used by `@kubb/plugin-msw`. Decides the names and file
421
+ * paths for every generated MSW handler. Function names get a `Handler`
422
+ * suffix; the aggregate export is always `handlers`.
423
+ *
424
+ * The top-level `name` applies the `handler` suffix, and `file` falls back to the built-in
425
+ * `toFilePath` casing. Operation-specific naming is grouped under the `handler` namespace.
426
+ *
427
+ * @example Resolve a handler name
428
+ * ```ts
429
+ * import { resolverMsw } from '@kubb/plugin-msw'
430
+ *
431
+ * resolverMsw.name('addPet') // 'addPetHandler'
432
+ * ```
433
+ */
434
+ const resolverMsw = createResolver({
435
+ pluginName: "plugin-msw",
436
+ name(name) {
437
+ return camelCase(name, { suffix: "handler" });
438
+ },
439
+ handler: {
440
+ name(node) {
441
+ return this.name(node.operationId);
442
+ },
443
+ listName() {
444
+ return "handlers";
445
+ }
446
+ }
447
+ });
448
+ //#endregion
9
449
  //#region src/plugin.ts
450
+ /**
451
+ * Canonical plugin name for `@kubb/plugin-msw`. Used for driver lookups and
452
+ * cross-plugin dependency references.
453
+ */
10
454
  const pluginMswName = "plugin-msw";
11
- const pluginMsw = createPlugin((options) => {
455
+ /**
456
+ * Generates MSW request handlers from an OpenAPI spec. Drop them into your
457
+ * test setup or service worker to mock the API end-to-end. Request path,
458
+ * method, status, and response body all stay in sync with the spec. Combine
459
+ * with `@kubb/plugin-faker` (via `parser: 'faker'`) to seed handlers with
460
+ * realistic data.
461
+ *
462
+ * @example
463
+ * ```ts
464
+ * import { defineConfig } from 'kubb/config'
465
+ * import { pluginTs } from '@kubb/plugin-ts'
466
+ * import { pluginMsw } from '@kubb/plugin-msw'
467
+ *
468
+ * export default defineConfig({
469
+ * input: './petStore.yaml',
470
+ * output: { path: './src/gen' },
471
+ * plugins: [
472
+ * pluginTs(),
473
+ * pluginMsw({
474
+ * output: { path: './handlers' },
475
+ * handlers: true,
476
+ * }),
477
+ * ],
478
+ * })
479
+ * ```
480
+ */
481
+ const pluginMsw = definePlugin((options) => {
12
482
  const { output = {
13
483
  path: "handlers",
14
- barrelType: "named"
15
- }, group, exclude = [], include, override = [], transformers = {}, handlers = false, parser = "data", generators = [mswGenerator, handlers ? handlersGenerator : void 0].filter(Boolean), contentType, baseURL } = options;
484
+ barrel: { type: "named" }
485
+ }, group, exclude = [], include, override = [], handlers = false, parser = "data", baseURL, resolver: userResolver, macros: userMacros } = options;
486
+ const groupConfig = createGroupConfig(group);
16
487
  return {
17
488
  name: pluginMswName,
18
- options: {
19
- output,
20
- parser,
21
- group,
22
- baseURL
23
- },
24
- pre: [
25
- pluginOasName,
26
- pluginTsName,
27
- parser === "faker" ? pluginFakerName : void 0
28
- ].filter(Boolean),
29
- resolvePath(baseName, pathMode, options) {
30
- const root = path.resolve(this.config.root, this.config.output.path);
31
- if ((pathMode ?? getMode(path.resolve(root, output.path))) === "single")
32
- /**
33
- * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
34
- * Other plugins then need to call addOrAppend instead of just add from the fileManager class
35
- */
36
- return path.resolve(root, output.path);
37
- if (group && (options?.group?.path || options?.group?.tag)) {
38
- const groupName = group?.name ? group.name : (ctx) => {
39
- if (group?.type === "path") return `${ctx.group.split("/")[1]}`;
40
- return `${camelCase(ctx.group)}Controller`;
41
- };
42
- return path.resolve(root, output.path, groupName({ group: group.type === "path" ? options.group.path : options.group.tag }), baseName);
43
- }
44
- return path.resolve(root, output.path, baseName);
45
- },
46
- resolveName(name, type) {
47
- const resolvedName = camelCase(name, {
48
- suffix: type ? "handler" : void 0,
49
- isFile: type === "file"
50
- });
51
- if (type) return transformers?.name?.(resolvedName, type) || resolvedName;
52
- return resolvedName;
53
- },
54
- async install() {
55
- const root = path.resolve(this.config.root, this.config.output.path);
56
- const mode = getMode(path.resolve(root, output.path));
57
- const oas = await this.getOas();
58
- const files = await new OperationGenerator(this.plugin.options, {
59
- fabric: this.fabric,
60
- oas,
61
- driver: this.driver,
62
- events: this.events,
63
- plugin: this.plugin,
64
- contentType,
489
+ options,
490
+ dependencies: [pluginTsName, parser === "faker" ? pluginFakerName : null].filter((dependency) => Boolean(dependency)),
491
+ hooks: { "kubb:plugin:setup"(ctx) {
492
+ const resolver = userResolver ? Resolver.merge(resolverMsw, userResolver) : resolverMsw;
493
+ ctx.setOptions({
494
+ output,
495
+ parser,
496
+ baseURL,
497
+ group: groupConfig,
65
498
  exclude,
66
499
  include,
67
500
  override,
68
- mode
69
- }).build(...generators);
70
- await this.upsertFile(...files);
71
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
72
- type: output.barrelType ?? "named",
73
- root,
74
- output,
75
- meta: { pluginName: this.plugin.name }
501
+ handlers,
502
+ resolver
76
503
  });
77
- await this.upsertFile(...barrelFiles);
78
- }
504
+ ctx.setResolver(resolver);
505
+ if (userMacros?.length) ctx.setMacros(userMacros);
506
+ ctx.addGenerator(mswGenerator);
507
+ if (handlers) ctx.addGenerator(handlersGenerator);
508
+ } }
79
509
  };
80
510
  });
81
511
  //#endregion
82
- export { pluginMsw, pluginMswName };
512
+ export { pluginMsw as default, pluginMsw, pluginMswName, resolverMsw };
83
513
 
84
514
  //# sourceMappingURL=index.js.map