@kubb/plugin-msw 5.0.0-beta.84 → 5.0.0-beta.86
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.cjs +67 -120
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +13 -16
- package/dist/index.js +68 -121
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./rolldown-runtime-C0LytTxp.js";
|
|
2
|
-
import { ast, defineGenerator, definePlugin
|
|
2
|
+
import { Resolver, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
|
|
3
3
|
import { pluginFakerName } from "@kubb/plugin-faker";
|
|
4
4
|
import { createFunctionParameter, createFunctionParameters, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
|
|
5
5
|
import { File, Function, jsxRenderer } from "kubb/jsx";
|
|
@@ -31,31 +31,6 @@ function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
|
31
31
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
32
32
|
}
|
|
33
33
|
//#endregion
|
|
34
|
-
//#region ../../internals/utils/src/fs.ts
|
|
35
|
-
/**
|
|
36
|
-
* Builds a nested file path from a dotted name. Splits on dots that precede a letter
|
|
37
|
-
* (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
|
|
38
|
-
* every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
|
|
39
|
-
*
|
|
40
|
-
* Empty segments are dropped before joining. They arise when the name starts with a dot
|
|
41
|
-
* followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
|
|
42
|
-
* an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
|
|
43
|
-
* absolute path, letting generated files escape the configured output directory.
|
|
44
|
-
*
|
|
45
|
-
* @example Nested path from a dotted name
|
|
46
|
-
* `toFilePath('pet.petId') // 'pet/petId'`
|
|
47
|
-
*
|
|
48
|
-
* @example PascalCase the final segment
|
|
49
|
-
* `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
|
|
50
|
-
*
|
|
51
|
-
* @example Suffix applied to the final segment only
|
|
52
|
-
* `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
|
|
53
|
-
*/
|
|
54
|
-
function toFilePath(name, caseLast = camelCase) {
|
|
55
|
-
const parts = name.split(/\.(?=[a-zA-Z])/);
|
|
56
|
-
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
|
|
57
|
-
}
|
|
58
|
-
//#endregion
|
|
59
34
|
//#region ../../internals/utils/src/reserved.ts
|
|
60
35
|
/**
|
|
61
36
|
* JavaScript and Java reserved words.
|
|
@@ -156,6 +131,22 @@ const reservedWords = /* @__PURE__ */ new Set([
|
|
|
156
131
|
*/
|
|
157
132
|
function isValidVarName(name) {
|
|
158
133
|
if (!name || reservedWords.has(name)) return false;
|
|
134
|
+
return isIdentifier(name);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
|
|
138
|
+
*
|
|
139
|
+
* Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
|
|
140
|
+
* even though they are not valid variable names, so use this (not {@link isValidVarName}) when
|
|
141
|
+
* deciding whether an object key needs quoting.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* isIdentifier('name') // true
|
|
146
|
+
* isIdentifier('x-total')// false
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
function isIdentifier(name) {
|
|
159
150
|
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
160
151
|
}
|
|
161
152
|
//#endregion
|
|
@@ -292,12 +283,12 @@ function resolveResponseTypes(node, resolver) {
|
|
|
292
283
|
const types = [];
|
|
293
284
|
for (const response of node.responses) {
|
|
294
285
|
if (response.statusCode === "default") {
|
|
295
|
-
types.push(["default", resolver.
|
|
286
|
+
types.push(["default", resolver.response.response(node)]);
|
|
296
287
|
continue;
|
|
297
288
|
}
|
|
298
289
|
const code = getStatusCodeNumber(response.statusCode);
|
|
299
290
|
if (code === null) continue;
|
|
300
|
-
types.push([code, isSuccessStatusCode(code) ? resolver.
|
|
291
|
+
types.push([code, isSuccessStatusCode(code) ? resolver.response.response(node) : resolver.response.status(node, response.statusCode)]);
|
|
301
292
|
}
|
|
302
293
|
return types;
|
|
303
294
|
}
|
|
@@ -345,23 +336,21 @@ const handlersGenerator = defineGenerator({
|
|
|
345
336
|
operations(nodes, ctx) {
|
|
346
337
|
const { resolver, config, root } = ctx;
|
|
347
338
|
const { output, group } = ctx.options;
|
|
348
|
-
const handlersName = resolver.
|
|
349
|
-
const file = resolver.
|
|
350
|
-
name:
|
|
351
|
-
extname: ".ts"
|
|
352
|
-
}, {
|
|
339
|
+
const handlersName = resolver.handler.listName();
|
|
340
|
+
const file = resolver.file({
|
|
341
|
+
name: handlersName,
|
|
342
|
+
extname: ".ts",
|
|
353
343
|
root,
|
|
354
344
|
output,
|
|
355
345
|
group: group ?? void 0
|
|
356
346
|
});
|
|
357
347
|
const imports = nodes.map((node) => {
|
|
358
|
-
const operationName = resolver.
|
|
359
|
-
const operationFile = resolver.
|
|
360
|
-
name: resolver.
|
|
348
|
+
const operationName = resolver.handler.name(node);
|
|
349
|
+
const operationFile = resolver.file({
|
|
350
|
+
name: resolver.name(node.operationId),
|
|
361
351
|
extname: ".ts",
|
|
362
352
|
tag: node.tags[0] ?? "default",
|
|
363
|
-
path: node.path
|
|
364
|
-
}, {
|
|
353
|
+
path: node.path,
|
|
365
354
|
root,
|
|
366
355
|
output,
|
|
367
356
|
group: group ?? void 0
|
|
@@ -372,12 +361,12 @@ const handlersGenerator = defineGenerator({
|
|
|
372
361
|
path: operationFile.path
|
|
373
362
|
});
|
|
374
363
|
});
|
|
375
|
-
const handlers = nodes.map((node) => `${resolver.
|
|
364
|
+
const handlers = nodes.map((node) => `${resolver.handler.name(node)}()`);
|
|
376
365
|
return [ast.factory.createFile({
|
|
377
366
|
baseName: file.baseName,
|
|
378
367
|
path: file.path,
|
|
379
368
|
meta: file.meta,
|
|
380
|
-
banner: resolver.
|
|
369
|
+
banner: resolver.default.banner(ctx.meta, {
|
|
381
370
|
output,
|
|
382
371
|
config,
|
|
383
372
|
file: {
|
|
@@ -385,7 +374,7 @@ const handlersGenerator = defineGenerator({
|
|
|
385
374
|
baseName: file.baseName
|
|
386
375
|
}
|
|
387
376
|
}),
|
|
388
|
-
footer: resolver.
|
|
377
|
+
footer: resolver.default.footer(ctx.meta, {
|
|
389
378
|
output,
|
|
390
379
|
config,
|
|
391
380
|
file: {
|
|
@@ -450,13 +439,12 @@ function resolveFakerMeta(node, options) {
|
|
|
450
439
|
const { root, fakerResolver, fakerOutput, fakerGroup } = options;
|
|
451
440
|
const tag = node.tags[0] ?? "default";
|
|
452
441
|
return {
|
|
453
|
-
name: fakerResolver.
|
|
454
|
-
file: fakerResolver.
|
|
442
|
+
name: fakerResolver.response.response(node),
|
|
443
|
+
file: fakerResolver.file({
|
|
455
444
|
name: node.operationId,
|
|
456
445
|
extname: ".ts",
|
|
457
446
|
tag,
|
|
458
|
-
path: node.path
|
|
459
|
-
}, {
|
|
447
|
+
path: node.path,
|
|
460
448
|
root,
|
|
461
449
|
output: fakerOutput,
|
|
462
450
|
group: fakerGroup ?? void 0
|
|
@@ -465,60 +453,26 @@ function resolveFakerMeta(node, options) {
|
|
|
465
453
|
}
|
|
466
454
|
//#endregion
|
|
467
455
|
//#region src/components/Mock.tsx
|
|
468
|
-
const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
|
|
469
|
-
function Mock({ baseURL = "", name, typeName, requestTypeName, node }) {
|
|
470
|
-
const method = getMswMethod(node);
|
|
471
|
-
const successResponse = getPrimarySuccessResponse(node);
|
|
472
|
-
const statusCode = successResponse ? Number(successResponse.statusCode) : 200;
|
|
473
|
-
const contentType = getContentType(successResponse);
|
|
474
|
-
const url = Url.toPath(getMswUrl(node));
|
|
475
|
-
const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean);
|
|
476
|
-
const dataType = hasResponseSchema(successResponse) ? typeName : "string | number | boolean | null | object";
|
|
477
|
-
const callbackType = requestTypeName ? `HttpResponseResolver<Record<string, string>, ${requestTypeName}>` : `((info: Parameters<Parameters<typeof http.${method}>[1]>[0]) => Response | Promise<Response>)`;
|
|
478
|
-
const params = declarationPrinter$2.print(createFunctionParameters({ params: [createFunctionParameter({
|
|
479
|
-
name: "data",
|
|
480
|
-
type: `${dataType} | ${callbackType}`,
|
|
481
|
-
optional: true
|
|
482
|
-
})] }));
|
|
483
|
-
const httpCall = requestTypeName ? `http.${method}<Record<string, string>, ${requestTypeName}>` : `http.${method}`;
|
|
484
|
-
return /* @__PURE__ */ jsx(File.Source, {
|
|
485
|
-
name,
|
|
486
|
-
isIndexable: true,
|
|
487
|
-
isExportable: true,
|
|
488
|
-
children: /* @__PURE__ */ jsx(Function, {
|
|
489
|
-
name,
|
|
490
|
-
export: true,
|
|
491
|
-
params: params ?? "",
|
|
492
|
-
children: `return ${httpCall}(\`${baseURL}${url.replace(/([^/]):/g, "$1\\\\:")}\`, function handler(info) {
|
|
493
|
-
if(typeof data === 'function') return data(info)
|
|
494
|
-
|
|
495
|
-
return new Response(JSON.stringify(data), {
|
|
496
|
-
status: ${statusCode},
|
|
497
|
-
${headers.length ? ` headers: {
|
|
498
|
-
${headers.join(", \n")}
|
|
499
|
-
},` : ""}
|
|
500
|
-
})
|
|
501
|
-
})`
|
|
502
|
-
})
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
//#endregion
|
|
506
|
-
//#region src/components/MockWithFaker.tsx
|
|
507
456
|
const declarationPrinter$1 = functionPrinter({ mode: "declaration" });
|
|
508
|
-
function
|
|
457
|
+
function Mock({ baseURL = "", name, fakerName, typeName, requestTypeName, node }) {
|
|
509
458
|
const method = getMswMethod(node);
|
|
510
459
|
const successResponse = getPrimarySuccessResponse(node);
|
|
511
460
|
const statusCode = successResponse ? Number(successResponse.statusCode) : 200;
|
|
512
461
|
const contentType = getContentType(successResponse);
|
|
513
462
|
const url = Url.toPath(getMswUrl(node));
|
|
514
463
|
const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean);
|
|
464
|
+
const dataType = hasResponseSchema(successResponse) ? typeName : "string | number | boolean | null | object";
|
|
465
|
+
const paramType = fakerName ? typeName : dataType;
|
|
515
466
|
const callbackType = requestTypeName ? `HttpResponseResolver<Record<string, string>, ${requestTypeName}>` : `((info: Parameters<Parameters<typeof http.${method}>[1]>[0]) => Response | Promise<Response>)`;
|
|
516
467
|
const params = declarationPrinter$1.print(createFunctionParameters({ params: [createFunctionParameter({
|
|
517
468
|
name: "data",
|
|
518
|
-
type: `${
|
|
469
|
+
type: `${paramType} | ${callbackType}`,
|
|
519
470
|
optional: true
|
|
520
471
|
})] }));
|
|
521
472
|
const httpCall = requestTypeName ? `http.${method}<Record<string, string>, ${requestTypeName}>` : `http.${method}`;
|
|
473
|
+
const requestUrl = `${baseURL}${url.replace(/([^/]):/g, "$1\\\\:")}`;
|
|
474
|
+
const urlLiteral = fakerName ? `'${requestUrl}'` : `\`${requestUrl}\``;
|
|
475
|
+
const responseBody = fakerName ? `JSON.stringify(data || ${fakerName}(data))` : "JSON.stringify(data)";
|
|
522
476
|
return /* @__PURE__ */ jsx(File.Source, {
|
|
523
477
|
name,
|
|
524
478
|
isIndexable: true,
|
|
@@ -527,10 +481,10 @@ function MockWithFaker({ baseURL = "", name, fakerName, typeName, requestTypeNam
|
|
|
527
481
|
name,
|
|
528
482
|
export: true,
|
|
529
483
|
params: params ?? "",
|
|
530
|
-
children: `return ${httpCall}(
|
|
484
|
+
children: `return ${httpCall}(${urlLiteral}, function handler(info) {
|
|
531
485
|
if(typeof data === 'function') return data(info)
|
|
532
486
|
|
|
533
|
-
return new Response(
|
|
487
|
+
return new Response(${responseBody}, {
|
|
534
488
|
status: ${statusCode},
|
|
535
489
|
${headers.length ? ` headers: {
|
|
536
490
|
${headers.join(", \n")}
|
|
@@ -586,15 +540,14 @@ const mswGenerator = defineGenerator({
|
|
|
586
540
|
if (!ast.isHttpOperationNode(node)) return null;
|
|
587
541
|
const { driver, resolver, config, root } = ctx;
|
|
588
542
|
const { output, parser, baseURL, group } = ctx.options;
|
|
589
|
-
const fileName = resolver.
|
|
543
|
+
const fileName = resolver.name(node.operationId);
|
|
590
544
|
const mock = {
|
|
591
|
-
name: resolver.
|
|
592
|
-
file: resolver.
|
|
545
|
+
name: resolver.handler.name(node),
|
|
546
|
+
file: resolver.file({
|
|
593
547
|
name: fileName,
|
|
594
548
|
extname: ".ts",
|
|
595
549
|
tag: node.tags[0] ?? "default",
|
|
596
|
-
path: node.path
|
|
597
|
-
}, {
|
|
550
|
+
path: node.path,
|
|
598
551
|
root,
|
|
599
552
|
output,
|
|
600
553
|
group: group ?? void 0
|
|
@@ -611,26 +564,25 @@ const mswGenerator = defineGenerator({
|
|
|
611
564
|
if (!pluginTs) return null;
|
|
612
565
|
const tsResolver = driver.getResolver(pluginTsName);
|
|
613
566
|
const type = {
|
|
614
|
-
file: tsResolver.
|
|
567
|
+
file: tsResolver.file({
|
|
615
568
|
name: node.operationId,
|
|
616
569
|
extname: ".ts",
|
|
617
570
|
tag: node.tags[0] ?? "default",
|
|
618
|
-
path: node.path
|
|
619
|
-
}, {
|
|
571
|
+
path: node.path,
|
|
620
572
|
root,
|
|
621
573
|
output: pluginTs.options?.output ?? output,
|
|
622
574
|
group: pluginTs.options?.group ?? void 0
|
|
623
575
|
}),
|
|
624
|
-
responseName: tsResolver.
|
|
576
|
+
responseName: tsResolver.response.response(node)
|
|
625
577
|
};
|
|
626
578
|
const types = resolveResponseTypes(node, tsResolver);
|
|
627
579
|
const hasSuccessSchema = getOperationSuccessResponses(node).some((response) => !!response.content?.[0]?.schema);
|
|
628
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.
|
|
580
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? tsResolver.response.body(node) : null;
|
|
629
581
|
return /* @__PURE__ */ jsxs(File, {
|
|
630
582
|
baseName: mock.file.baseName,
|
|
631
583
|
path: mock.file.path,
|
|
632
584
|
meta: mock.file.meta,
|
|
633
|
-
banner: resolver.
|
|
585
|
+
banner: resolver.default.banner(ctx.meta, {
|
|
634
586
|
output,
|
|
635
587
|
config,
|
|
636
588
|
file: {
|
|
@@ -638,7 +590,7 @@ const mswGenerator = defineGenerator({
|
|
|
638
590
|
baseName: mock.file.baseName
|
|
639
591
|
}
|
|
640
592
|
}),
|
|
641
|
-
footer: resolver.
|
|
593
|
+
footer: resolver.default.footer(ctx.meta, {
|
|
642
594
|
output,
|
|
643
595
|
config,
|
|
644
596
|
file: {
|
|
@@ -680,7 +632,7 @@ const mswGenerator = defineGenerator({
|
|
|
680
632
|
name: mock.name
|
|
681
633
|
}, typeName);
|
|
682
634
|
}),
|
|
683
|
-
parser === "faker" && faker && hasSuccessSchema ? /* @__PURE__ */ jsx(
|
|
635
|
+
parser === "faker" && faker && hasSuccessSchema ? /* @__PURE__ */ jsx(Mock, {
|
|
684
636
|
name: mock.name,
|
|
685
637
|
typeName: type.responseName,
|
|
686
638
|
requestTypeName: requestName,
|
|
@@ -705,32 +657,30 @@ const mswGenerator = defineGenerator({
|
|
|
705
657
|
* paths for every generated MSW handler. Function names get a `Handler`
|
|
706
658
|
* suffix; the aggregate export is always `handlers`.
|
|
707
659
|
*
|
|
660
|
+
* The top-level `name` applies the `handler` suffix, and `file` falls back to the built-in
|
|
661
|
+
* `toFilePath` casing. Operation-specific naming is grouped under the `handler` namespace.
|
|
662
|
+
*
|
|
708
663
|
* @example Resolve a handler name
|
|
709
664
|
* ```ts
|
|
710
665
|
* import { resolverMsw } from '@kubb/plugin-msw'
|
|
711
666
|
*
|
|
712
|
-
* resolverMsw.
|
|
667
|
+
* resolverMsw.name('addPet') // 'addPetHandler'
|
|
713
668
|
* ```
|
|
714
669
|
*/
|
|
715
|
-
const resolverMsw =
|
|
716
|
-
name: "default",
|
|
670
|
+
const resolverMsw = createResolver({
|
|
717
671
|
pluginName: "plugin-msw",
|
|
718
|
-
|
|
719
|
-
return type === "file" ? toFilePath(name) : camelCase(name);
|
|
720
|
-
},
|
|
721
|
-
resolveName(name) {
|
|
672
|
+
name(name) {
|
|
722
673
|
return camelCase(name, { suffix: "handler" });
|
|
723
674
|
},
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
return "handlers";
|
|
675
|
+
handler: {
|
|
676
|
+
name(node) {
|
|
677
|
+
return this.name(node.operationId);
|
|
678
|
+
},
|
|
679
|
+
listName() {
|
|
680
|
+
return "handlers";
|
|
681
|
+
}
|
|
732
682
|
}
|
|
733
|
-
})
|
|
683
|
+
});
|
|
734
684
|
//#endregion
|
|
735
685
|
//#region src/plugin.ts
|
|
736
686
|
/**
|
|
@@ -775,10 +725,7 @@ const pluginMsw = definePlugin((options) => {
|
|
|
775
725
|
options,
|
|
776
726
|
dependencies: [pluginTsName, parser === "faker" ? pluginFakerName : null].filter((dependency) => Boolean(dependency)),
|
|
777
727
|
hooks: { "kubb:plugin:setup"(ctx) {
|
|
778
|
-
const resolver = userResolver ?
|
|
779
|
-
...resolverMsw,
|
|
780
|
-
...userResolver
|
|
781
|
-
} : resolverMsw;
|
|
728
|
+
const resolver = userResolver ? Resolver.merge(resolverMsw, userResolver) : resolverMsw;
|
|
782
729
|
ctx.setOptions({
|
|
783
730
|
output,
|
|
784
731
|
parser,
|