@kubb/plugin-msw 5.0.0-beta.56 → 5.0.0-beta.73

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,9 +1,36 @@
1
- import "./chunk-C0LytTxp.js";
2
- import { s as camelCase } from "./components-Bi7cN-ws.js";
3
- import { n as handlersGenerator, t as mswGenerator } from "./generators-BnEvTy3q.js";
4
- import { definePlugin, defineResolver } from "@kubb/core";
1
+ import "./rolldown-runtime-C0LytTxp.js";
2
+ import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
5
3
  import { pluginFakerName } from "@kubb/plugin-faker";
6
- import { pluginTsName } from "@kubb/plugin-ts";
4
+ import { createFunctionParameter, createFunctionParameters, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
5
+ import { File, Function, jsxRenderer } from "@kubb/renderer-jsx";
6
+ import { jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
7
+ //#region ../../internals/utils/src/casing.ts
8
+ /**
9
+ * Shared implementation for camelCase and PascalCase conversion.
10
+ * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
11
+ * and capitalizes each word according to `pascal`.
12
+ *
13
+ * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
14
+ */
15
+ function toCamelOrPascal(text, pascal) {
16
+ 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) => {
17
+ if (word.length > 1 && word === word.toUpperCase()) return word;
18
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
19
+ }).join("").replace(/[^a-zA-Z0-9]/g, "");
20
+ }
21
+ /**
22
+ * Converts `text` to camelCase.
23
+ *
24
+ * @example Word boundaries
25
+ * `camelCase('hello-world') // 'helloWorld'`
26
+ *
27
+ * @example With a prefix
28
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
29
+ */
30
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
31
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
32
+ }
33
+ //#endregion
7
34
  //#region ../../internals/utils/src/fs.ts
8
35
  /**
9
36
  * Builds a nested file path from a dotted name. Splits on dots that precede a letter
@@ -29,6 +56,241 @@ function toFilePath(name, caseLast = camelCase) {
29
56
  return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
30
57
  }
31
58
  //#endregion
59
+ //#region ../../internals/utils/src/reserved.ts
60
+ /**
61
+ * JavaScript and Java reserved words.
62
+ * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
63
+ */
64
+ const reservedWords = new Set([
65
+ "abstract",
66
+ "arguments",
67
+ "boolean",
68
+ "break",
69
+ "byte",
70
+ "case",
71
+ "catch",
72
+ "char",
73
+ "class",
74
+ "const",
75
+ "continue",
76
+ "debugger",
77
+ "default",
78
+ "delete",
79
+ "do",
80
+ "double",
81
+ "else",
82
+ "enum",
83
+ "eval",
84
+ "export",
85
+ "extends",
86
+ "false",
87
+ "final",
88
+ "finally",
89
+ "float",
90
+ "for",
91
+ "function",
92
+ "goto",
93
+ "if",
94
+ "implements",
95
+ "import",
96
+ "in",
97
+ "instanceof",
98
+ "int",
99
+ "interface",
100
+ "let",
101
+ "long",
102
+ "native",
103
+ "new",
104
+ "null",
105
+ "package",
106
+ "private",
107
+ "protected",
108
+ "public",
109
+ "return",
110
+ "short",
111
+ "static",
112
+ "super",
113
+ "switch",
114
+ "synchronized",
115
+ "this",
116
+ "throw",
117
+ "throws",
118
+ "transient",
119
+ "true",
120
+ "try",
121
+ "typeof",
122
+ "var",
123
+ "void",
124
+ "volatile",
125
+ "while",
126
+ "with",
127
+ "yield",
128
+ "Array",
129
+ "Date",
130
+ "hasOwnProperty",
131
+ "Infinity",
132
+ "isFinite",
133
+ "isNaN",
134
+ "isPrototypeOf",
135
+ "length",
136
+ "Math",
137
+ "name",
138
+ "NaN",
139
+ "Number",
140
+ "Object",
141
+ "prototype",
142
+ "String",
143
+ "toString",
144
+ "undefined",
145
+ "valueOf"
146
+ ]);
147
+ /**
148
+ * Returns `true` when `name` is a syntactically valid JavaScript variable name.
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * isValidVarName('status') // true
153
+ * isValidVarName('class') // false (reserved word)
154
+ * isValidVarName('42foo') // false (starts with digit)
155
+ * ```
156
+ */
157
+ function isValidVarName(name) {
158
+ if (!name || reservedWords.has(name)) return false;
159
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
160
+ }
161
+ //#endregion
162
+ //#region ../../internals/utils/src/url.ts
163
+ function transformParam(raw, casing) {
164
+ const param = isValidVarName(raw) ? raw : camelCase(raw);
165
+ return casing === "camelcase" ? camelCase(param) : param;
166
+ }
167
+ function toParamsObject(path, { replacer, casing } = {}) {
168
+ const params = {};
169
+ for (const match of path.matchAll(/\{([^}]+)\}/g)) {
170
+ const param = transformParam(match[1], casing);
171
+ const key = replacer ? replacer(param) : param;
172
+ params[key] = key;
173
+ }
174
+ return Object.keys(params).length > 0 ? params : null;
175
+ }
176
+ /**
177
+ * Helpers for OpenAPI/Swagger paths, plus a thin wrapper over the native `URL`.
178
+ */
179
+ var Url = class Url {
180
+ /**
181
+ * Reports whether `url` is a parseable absolute URL. Delegates to the native `URL.canParse`.
182
+ *
183
+ * @example
184
+ * Url.canParse('https://petstore.swagger.io/v2') // true
185
+ * Url.canParse('/pet/{petId}') // false
186
+ */
187
+ static canParse(url, base) {
188
+ return URL.canParse(url, base);
189
+ }
190
+ /**
191
+ * Converts an OpenAPI/Swagger path to Express-style colon syntax.
192
+ *
193
+ * @example
194
+ * Url.toPath('/pet/{petId}') // '/pet/:petId'
195
+ */
196
+ static toPath(path) {
197
+ return path.replace(/\{([^}]+)\}/g, ":$1");
198
+ }
199
+ /**
200
+ * Converts an OpenAPI/Swagger path to a TypeScript template literal string.
201
+ * `prefix` is prepended inside the literal, `replacer` transforms each parameter name,
202
+ * and `casing` controls parameter identifier casing.
203
+ *
204
+ * @example
205
+ * Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
206
+ *
207
+ * @example
208
+ * Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
209
+ */
210
+ static toTemplateString(path, { prefix, replacer, casing } = {}) {
211
+ const result = path.split(/\{([^}]+)\}/).map((part, i) => {
212
+ if (i % 2 === 0) return part;
213
+ const param = transformParam(part, casing);
214
+ return `\${${replacer ? replacer(param) : param}}`;
215
+ }).join("");
216
+ return `\`${prefix ?? ""}${result}\``;
217
+ }
218
+ /**
219
+ * Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
220
+ * grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
221
+ * names are camelCased to match the generated `path` type, and `prefix` is prepended inside the
222
+ * literal. Shared by the client and cypress generators that pass a grouped `path` object.
223
+ *
224
+ * @example
225
+ * Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
226
+ */
227
+ static toGroupedTemplateString(path, { prefix } = {}) {
228
+ return Url.toTemplateString(path, {
229
+ prefix,
230
+ casing: "camelcase",
231
+ replacer: (name) => `path.${name}`
232
+ });
233
+ }
234
+ /**
235
+ * Returns the path and its extracted params as a structured `URLObject`, or as a stringified
236
+ * expression when `stringify` is set.
237
+ *
238
+ * @example
239
+ * Url.toObject('/pet/{petId}')
240
+ * // { url: '/pet/:petId', params: { petId: 'petId' } }
241
+ */
242
+ static toObject(path, { type = "path", replacer, stringify, casing } = {}) {
243
+ const object = {
244
+ url: type === "path" ? Url.toPath(path) : Url.toTemplateString(path, {
245
+ replacer,
246
+ casing
247
+ }),
248
+ params: toParamsObject(path, {
249
+ replacer,
250
+ casing
251
+ })
252
+ };
253
+ if (stringify) {
254
+ if (type === "template") return JSON.stringify(object).replaceAll("'", "").replaceAll(`"`, "");
255
+ if (object.params) return `{ url: '${object.url}', params: ${JSON.stringify(object.params).replaceAll("'", "").replaceAll(`"`, "")} }`;
256
+ return `{ url: '${object.url}' }`;
257
+ }
258
+ return object;
259
+ }
260
+ };
261
+ //#endregion
262
+ //#region ../../internals/shared/src/operation.ts
263
+ function getStatusCodeNumber(statusCode) {
264
+ const code = Number(statusCode);
265
+ return Number.isNaN(code) ? null : code;
266
+ }
267
+ function isSuccessStatusCode(statusCode) {
268
+ const code = getStatusCodeNumber(statusCode);
269
+ return code !== null && code >= 200 && code < 300;
270
+ }
271
+ function getSuccessResponses(responses) {
272
+ return responses.filter((response) => isSuccessStatusCode(response.statusCode));
273
+ }
274
+ function getOperationSuccessResponses(node) {
275
+ return getSuccessResponses(node.responses);
276
+ }
277
+ function getPrimarySuccessResponse(node) {
278
+ return getOperationSuccessResponses(node)[0] ?? null;
279
+ }
280
+ function resolveResponseTypes(node, resolver) {
281
+ const types = [];
282
+ for (const response of node.responses) {
283
+ if (response.statusCode === "default") {
284
+ types.push(["default", resolver.resolveResponseName(node)]);
285
+ continue;
286
+ }
287
+ const code = getStatusCodeNumber(response.statusCode);
288
+ if (code === null) continue;
289
+ types.push([code, isSuccessStatusCode(code) ? resolver.resolveResponseName(node) : resolver.resolveResponseStatusName(node, response.statusCode)]);
290
+ }
291
+ return types;
292
+ }
293
+ //#endregion
32
294
  //#region ../../internals/shared/src/group.ts
33
295
  /**
34
296
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -60,6 +322,372 @@ function createGroupConfig(group) {
60
322
  };
61
323
  }
62
324
  //#endregion
325
+ //#region src/generators/handlersGenerator.ts
326
+ /**
327
+ * Aggregate generator enabled by `pluginMsw({ handlers: true })`. Emits a
328
+ * `handlers.ts` file that re-exports every generated handler grouped by HTTP
329
+ * method, ready to spread into `setupServer(...handlers)` or
330
+ * `setupWorker(...handlers)`.
331
+ */
332
+ const handlersGenerator = defineGenerator({
333
+ name: "plugin-msw",
334
+ operations(nodes, ctx) {
335
+ const { resolver, config, root } = ctx;
336
+ const { output, group } = ctx.options;
337
+ const handlersName = resolver.resolveHandlersName();
338
+ const file = resolver.resolveFile({
339
+ name: resolver.resolvePathName(handlersName, "file"),
340
+ extname: ".ts"
341
+ }, {
342
+ root,
343
+ output,
344
+ group: group ?? void 0
345
+ });
346
+ const imports = nodes.map((node) => {
347
+ const operationName = resolver.resolveHandlerName(node);
348
+ const operationFile = resolver.resolveFile({
349
+ name: resolver.resolveName(node.operationId),
350
+ extname: ".ts",
351
+ tag: node.tags[0] ?? "default",
352
+ path: node.path
353
+ }, {
354
+ root,
355
+ output,
356
+ group: group ?? void 0
357
+ });
358
+ return ast.factory.createImport({
359
+ name: [operationName],
360
+ root: file.path,
361
+ path: operationFile.path
362
+ });
363
+ });
364
+ const handlers = nodes.map((node) => `${resolver.resolveHandlerName(node)}()`);
365
+ return [ast.factory.createFile({
366
+ baseName: file.baseName,
367
+ path: file.path,
368
+ meta: file.meta,
369
+ banner: resolver.resolveBanner(ctx.meta, {
370
+ output,
371
+ config,
372
+ file: {
373
+ path: file.path,
374
+ baseName: file.baseName
375
+ }
376
+ }),
377
+ footer: resolver.resolveFooter(ctx.meta, {
378
+ output,
379
+ config,
380
+ file: {
381
+ path: file.path,
382
+ baseName: file.baseName
383
+ }
384
+ }),
385
+ imports,
386
+ sources: [ast.factory.createSource({
387
+ name: handlersName,
388
+ isIndexable: true,
389
+ isExportable: true,
390
+ nodes: [ast.factory.createText(`export const ${handlersName} = ${JSON.stringify(handlers).replaceAll("\"", "")} as const`)]
391
+ })]
392
+ })];
393
+ }
394
+ });
395
+ //#endregion
396
+ //#region src/utils.ts
397
+ /**
398
+ * Gets the content type from a response, defaulting to 'application/json' if a schema exists.
399
+ */
400
+ function getContentType(response) {
401
+ if (!hasResponseSchema(response)) return null;
402
+ return getResponseContentType(response) ?? "application/json";
403
+ }
404
+ /**
405
+ * Determines if a response has a schema that is not void or any.
406
+ */
407
+ function hasResponseSchema(response) {
408
+ const schema = response?.content?.find((entry) => entry.schema)?.schema;
409
+ return !!schema && schema.type !== "void" && schema.type !== "any";
410
+ }
411
+ /**
412
+ * Picks the content type used for the mocked response header. When a response declares multiple
413
+ * content types, JSON is preferred (the faker mock body is JSON), otherwise the first declared type.
414
+ */
415
+ function getResponseContentType(response) {
416
+ const contents = response?.content ?? [];
417
+ const value = (contents.find((entry) => {
418
+ const baseType = entry.contentType?.split(";")[0]?.trim().toLowerCase();
419
+ return baseType === "application/json" || baseType?.endsWith("+json");
420
+ }) ?? contents[0])?.contentType;
421
+ return typeof value === "string" && value.length > 0 ? value : null;
422
+ }
423
+ /**
424
+ * Converts an HTTP method to its lowercase MSW equivalent (e.g., 'POST' → 'post').
425
+ */
426
+ function getMswMethod(node) {
427
+ return ast.isHttpOperationNode(node) ? node.method.toLowerCase() : "";
428
+ }
429
+ /**
430
+ * Converts an OpenAPI-style path to an Express/MSW-style path by replacing `{param}` with `:param`.
431
+ */
432
+ function getMswUrl(node) {
433
+ return ast.isHttpOperationNode(node) ? node.path.replaceAll("{", ":").replaceAll("}", "") : "";
434
+ }
435
+ /**
436
+ * Resolves faker metadata for an MSW operation, including response name and file path.
437
+ */
438
+ function resolveFakerMeta(node, options) {
439
+ const { root, fakerResolver, fakerOutput, fakerGroup } = options;
440
+ const tag = node.tags[0] ?? "default";
441
+ return {
442
+ name: fakerResolver.resolveResponseName(node),
443
+ file: fakerResolver.resolveFile({
444
+ name: node.operationId,
445
+ extname: ".ts",
446
+ tag,
447
+ path: node.path
448
+ }, {
449
+ root,
450
+ output: fakerOutput,
451
+ group: fakerGroup ?? void 0
452
+ })
453
+ };
454
+ }
455
+ //#endregion
456
+ //#region src/components/Mock.tsx
457
+ const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
458
+ function Mock({ baseURL = "", name, typeName, requestTypeName, node }) {
459
+ const method = getMswMethod(node);
460
+ const successResponse = getPrimarySuccessResponse(node);
461
+ const statusCode = successResponse ? Number(successResponse.statusCode) : 200;
462
+ const contentType = getContentType(successResponse);
463
+ const url = Url.toPath(getMswUrl(node));
464
+ const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean);
465
+ const dataType = hasResponseSchema(successResponse) ? typeName : "string | number | boolean | null | object";
466
+ const callbackType = requestTypeName ? `HttpResponseResolver<Record<string, string>, ${requestTypeName}, any>` : `((info: Parameters<Parameters<typeof http.${method}>[1]>[0]) => Response | Promise<Response>)`;
467
+ const params = declarationPrinter$2.print(createFunctionParameters({ params: [createFunctionParameter({
468
+ name: "data",
469
+ type: `${dataType} | ${callbackType}`,
470
+ optional: true
471
+ })] }));
472
+ const httpCall = requestTypeName ? `http.${method}<Record<string, string>, ${requestTypeName}, any>` : `http.${method}`;
473
+ return /* @__PURE__ */ jsx(File.Source, {
474
+ name,
475
+ isIndexable: true,
476
+ isExportable: true,
477
+ children: /* @__PURE__ */ jsx(Function, {
478
+ name,
479
+ export: true,
480
+ params: params ?? "",
481
+ children: `return ${httpCall}(\`${baseURL}${url.replace(/([^/]):/g, "$1\\\\:")}\`, function handler(info) {
482
+ if(typeof data === 'function') return data(info)
483
+
484
+ return new Response(JSON.stringify(data), {
485
+ status: ${statusCode},
486
+ ${headers.length ? ` headers: {
487
+ ${headers.join(", \n")}
488
+ },` : ""}
489
+ })
490
+ })`
491
+ })
492
+ });
493
+ }
494
+ //#endregion
495
+ //#region src/components/MockWithFaker.tsx
496
+ const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
497
+ function MockWithFaker({ baseURL = "", name, fakerName, typeName, requestTypeName, node }) {
498
+ const method = getMswMethod(node);
499
+ const successResponse = getPrimarySuccessResponse(node);
500
+ const statusCode = successResponse ? Number(successResponse.statusCode) : 200;
501
+ const contentType = getContentType(successResponse);
502
+ const url = Url.toPath(getMswUrl(node));
503
+ const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean);
504
+ const callbackType = requestTypeName ? `HttpResponseResolver<Record<string, string>, ${requestTypeName}, any>` : `((info: Parameters<Parameters<typeof http.${method}>[1]>[0]) => Response | Promise<Response>)`;
505
+ const params = declarationPrinter$1.print(createFunctionParameters({ params: [createFunctionParameter({
506
+ name: "data",
507
+ type: `${typeName} | ${callbackType}`,
508
+ optional: true
509
+ })] }));
510
+ const httpCall = requestTypeName ? `http.${method}<Record<string, string>, ${requestTypeName}, any>` : `http.${method}`;
511
+ return /* @__PURE__ */ jsx(File.Source, {
512
+ name,
513
+ isIndexable: true,
514
+ isExportable: true,
515
+ children: /* @__PURE__ */ jsx(Function, {
516
+ name,
517
+ export: true,
518
+ params: params ?? "",
519
+ children: `return ${httpCall}('${baseURL}${url.replace(/([^/]):/g, "$1\\\\:")}', function handler(info) {
520
+ if(typeof data === 'function') return data(info)
521
+
522
+ return new Response(JSON.stringify(data || ${fakerName}(data)), {
523
+ status: ${statusCode},
524
+ ${headers.length ? ` headers: {
525
+ ${headers.join(", \n")}
526
+ },` : ""}
527
+ })
528
+ })`
529
+ })
530
+ });
531
+ }
532
+ //#endregion
533
+ //#region src/components/Response.tsx
534
+ const declarationPrinter = functionPrinter({ mode: "declaration" });
535
+ function Response({ name, typeName, response }) {
536
+ const statusCode = Number(response.statusCode);
537
+ const contentType = getContentType(response);
538
+ const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean);
539
+ const params = declarationPrinter.print(createFunctionParameters({ params: [createFunctionParameter({
540
+ name: "data",
541
+ type: typeName,
542
+ optional: !hasResponseSchema(response)
543
+ })] }));
544
+ const responseName = `${name}Response${statusCode}`;
545
+ return /* @__PURE__ */ jsx(File.Source, {
546
+ name: responseName,
547
+ isIndexable: true,
548
+ isExportable: true,
549
+ children: /* @__PURE__ */ jsx(Function, {
550
+ name: responseName,
551
+ export: true,
552
+ params: params ?? "",
553
+ children: `
554
+ return new Response(JSON.stringify(data), {
555
+ status: ${statusCode},
556
+ ${headers.length ? ` headers: {
557
+ ${headers.join(", \n")}
558
+ },` : ""}
559
+ })`
560
+ })
561
+ });
562
+ }
563
+ //#endregion
564
+ //#region src/generators/mswGenerator.tsx
565
+ /**
566
+ * Built-in operation generator for `@kubb/plugin-msw`. Emits one MSW handler
567
+ * per OpenAPI operation. With `parser: 'faker'` the handler returns a value
568
+ * from `@kubb/plugin-faker`; with `parser: 'data'` it returns a typed empty
569
+ * payload for tests to fill in.
570
+ */
571
+ const mswGenerator = defineGenerator({
572
+ name: "msw",
573
+ renderer: jsxRenderer,
574
+ operation(node, ctx) {
575
+ if (!ast.isHttpOperationNode(node)) return null;
576
+ const { driver, resolver, config, root } = ctx;
577
+ const { output, parser, baseURL, group } = ctx.options;
578
+ const fileName = resolver.resolveName(node.operationId);
579
+ const mock = {
580
+ name: resolver.resolveHandlerName(node),
581
+ file: resolver.resolveFile({
582
+ name: fileName,
583
+ extname: ".ts",
584
+ tag: node.tags[0] ?? "default",
585
+ path: node.path
586
+ }, {
587
+ root,
588
+ output,
589
+ group: group ?? void 0
590
+ })
591
+ };
592
+ const fakerPlugin = parser === "faker" ? driver.getPlugin(pluginFakerName) : null;
593
+ const faker = parser === "faker" && fakerPlugin ? resolveFakerMeta(node, {
594
+ root,
595
+ fakerResolver: driver.getResolver(pluginFakerName),
596
+ fakerOutput: fakerPlugin.options?.output ?? output,
597
+ fakerGroup: fakerPlugin.options?.group ?? null
598
+ }) : null;
599
+ const pluginTs = driver.getPlugin(pluginTsName);
600
+ if (!pluginTs) return null;
601
+ const tsResolver = driver.getResolver(pluginTsName);
602
+ const type = {
603
+ file: tsResolver.resolveFile({
604
+ name: node.operationId,
605
+ extname: ".ts",
606
+ tag: node.tags[0] ?? "default",
607
+ path: node.path
608
+ }, {
609
+ root,
610
+ output: pluginTs.options?.output ?? output,
611
+ group: pluginTs.options?.group ?? void 0
612
+ }),
613
+ responseName: tsResolver.resolveResponseName(node)
614
+ };
615
+ const types = resolveResponseTypes(node, tsResolver);
616
+ const hasSuccessSchema = getOperationSuccessResponses(node).some((response) => !!response.content?.[0]?.schema);
617
+ const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : null;
618
+ return /* @__PURE__ */ jsxs(File, {
619
+ baseName: mock.file.baseName,
620
+ path: mock.file.path,
621
+ meta: mock.file.meta,
622
+ banner: resolver.resolveBanner(ctx.meta, {
623
+ output,
624
+ config,
625
+ file: {
626
+ path: mock.file.path,
627
+ baseName: mock.file.baseName
628
+ }
629
+ }),
630
+ footer: resolver.resolveFooter(ctx.meta, {
631
+ output,
632
+ config,
633
+ file: {
634
+ path: mock.file.path,
635
+ baseName: mock.file.baseName
636
+ }
637
+ }),
638
+ children: [
639
+ /* @__PURE__ */ jsx(File.Import, {
640
+ name: ["http"],
641
+ path: "msw"
642
+ }),
643
+ /* @__PURE__ */ jsx(File.Import, {
644
+ name: ["HttpResponseResolver"],
645
+ isTypeOnly: true,
646
+ path: "msw"
647
+ }),
648
+ /* @__PURE__ */ jsx(File.Import, {
649
+ name: Array.from(new Set([
650
+ type.responseName,
651
+ ...types.map((t) => t[1]),
652
+ ...requestName ? [requestName] : []
653
+ ])),
654
+ path: type.file.path,
655
+ root: mock.file.path,
656
+ isTypeOnly: true
657
+ }),
658
+ parser === "faker" && faker && /* @__PURE__ */ jsx(File.Import, {
659
+ name: [faker.name],
660
+ root: mock.file.path,
661
+ path: faker.file.path
662
+ }),
663
+ types.filter(([code]) => code !== "default").map(([code, typeName]) => {
664
+ const response = node.responses.find((item) => item.statusCode === String(code));
665
+ if (!response) return null;
666
+ return /* @__PURE__ */ jsx(Response, {
667
+ typeName,
668
+ response,
669
+ name: mock.name
670
+ }, typeName);
671
+ }),
672
+ parser === "faker" && faker && hasSuccessSchema ? /* @__PURE__ */ jsx(MockWithFaker, {
673
+ name: mock.name,
674
+ typeName: type.responseName,
675
+ requestTypeName: requestName,
676
+ fakerName: faker.name,
677
+ node,
678
+ baseURL
679
+ }) : /* @__PURE__ */ jsx(Mock, {
680
+ name: mock.name,
681
+ typeName: type.responseName,
682
+ requestTypeName: requestName,
683
+ node,
684
+ baseURL
685
+ })
686
+ ]
687
+ });
688
+ }
689
+ });
690
+ //#endregion
63
691
  //#region src/resolvers/resolverMsw.ts
64
692
  /**
65
693
  * Default resolver used by `@kubb/plugin-msw`. Decides the names and file
@@ -129,7 +757,7 @@ const pluginMsw = definePlugin((options) => {
129
757
  const { output = {
130
758
  path: "handlers",
131
759
  barrel: { type: "named" }
132
- }, group, exclude = [], include, override = [], handlers = false, parser = "data", baseURL, resolver: userResolver, transformer: userTransformer, generators: userGenerators = [] } = options;
760
+ }, group, exclude = [], include, override = [], handlers = false, parser = "data", baseURL, resolver: userResolver, macros: userMacros } = options;
133
761
  const groupConfig = createGroupConfig(group);
134
762
  return {
135
763
  name: pluginMswName,
@@ -152,10 +780,9 @@ const pluginMsw = definePlugin((options) => {
152
780
  resolver
153
781
  });
154
782
  ctx.setResolver(resolver);
155
- if (userTransformer) ctx.setTransformer(userTransformer);
783
+ if (userMacros?.length) ctx.setMacros(userMacros);
156
784
  ctx.addGenerator(mswGenerator);
157
785
  if (handlers) ctx.addGenerator(handlersGenerator);
158
- for (const gen of userGenerators) ctx.addGenerator(gen);
159
786
  } }
160
787
  };
161
788
  });