@kubb/plugin-msw 5.0.0-beta.99 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +64 -222
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +65 -223
- package/dist/index.js.map +1 -1
- package/package.json +7 -10
package/dist/index.cjs
CHANGED
|
@@ -8,220 +8,46 @@ let _kubb_plugin_faker = require("@kubb/plugin-faker");
|
|
|
8
8
|
let _kubb_plugin_ts = require("@kubb/plugin-ts");
|
|
9
9
|
let kubb_jsx = require("kubb/jsx");
|
|
10
10
|
let kubb_jsx_jsx_runtime = require("kubb/jsx/jsx-runtime");
|
|
11
|
-
//#region ../../internals/
|
|
12
|
-
/**
|
|
13
|
-
* Shared implementation for camelCase and PascalCase conversion.
|
|
14
|
-
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
15
|
-
* and capitalizes each word according to `pascal`.
|
|
16
|
-
*
|
|
17
|
-
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
18
|
-
*/
|
|
19
|
-
function toCamelOrPascal(text, pascal) {
|
|
20
|
-
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) => {
|
|
21
|
-
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
22
|
-
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
23
|
-
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Converts `text` to camelCase.
|
|
27
|
-
*
|
|
28
|
-
* @example Word boundaries
|
|
29
|
-
* `camelCase('hello-world') // 'helloWorld'`
|
|
30
|
-
*
|
|
31
|
-
* @example With a prefix
|
|
32
|
-
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
33
|
-
*/
|
|
34
|
-
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
35
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region ../../internals/utils/src/reserved.ts
|
|
39
|
-
/**
|
|
40
|
-
* JavaScript and Java reserved words.
|
|
41
|
-
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
42
|
-
*/
|
|
43
|
-
const reservedWords = /* @__PURE__ */ new Set([
|
|
44
|
-
"abstract",
|
|
45
|
-
"arguments",
|
|
46
|
-
"boolean",
|
|
47
|
-
"break",
|
|
48
|
-
"byte",
|
|
49
|
-
"case",
|
|
50
|
-
"catch",
|
|
51
|
-
"char",
|
|
52
|
-
"class",
|
|
53
|
-
"const",
|
|
54
|
-
"continue",
|
|
55
|
-
"debugger",
|
|
56
|
-
"default",
|
|
57
|
-
"delete",
|
|
58
|
-
"do",
|
|
59
|
-
"double",
|
|
60
|
-
"else",
|
|
61
|
-
"enum",
|
|
62
|
-
"eval",
|
|
63
|
-
"export",
|
|
64
|
-
"extends",
|
|
65
|
-
"false",
|
|
66
|
-
"final",
|
|
67
|
-
"finally",
|
|
68
|
-
"float",
|
|
69
|
-
"for",
|
|
70
|
-
"function",
|
|
71
|
-
"goto",
|
|
72
|
-
"if",
|
|
73
|
-
"implements",
|
|
74
|
-
"import",
|
|
75
|
-
"in",
|
|
76
|
-
"instanceof",
|
|
77
|
-
"int",
|
|
78
|
-
"interface",
|
|
79
|
-
"let",
|
|
80
|
-
"long",
|
|
81
|
-
"native",
|
|
82
|
-
"new",
|
|
83
|
-
"null",
|
|
84
|
-
"package",
|
|
85
|
-
"private",
|
|
86
|
-
"protected",
|
|
87
|
-
"public",
|
|
88
|
-
"return",
|
|
89
|
-
"short",
|
|
90
|
-
"static",
|
|
91
|
-
"super",
|
|
92
|
-
"switch",
|
|
93
|
-
"synchronized",
|
|
94
|
-
"this",
|
|
95
|
-
"throw",
|
|
96
|
-
"throws",
|
|
97
|
-
"transient",
|
|
98
|
-
"true",
|
|
99
|
-
"try",
|
|
100
|
-
"typeof",
|
|
101
|
-
"var",
|
|
102
|
-
"void",
|
|
103
|
-
"volatile",
|
|
104
|
-
"while",
|
|
105
|
-
"with",
|
|
106
|
-
"yield",
|
|
107
|
-
"Array",
|
|
108
|
-
"Date",
|
|
109
|
-
"hasOwnProperty",
|
|
110
|
-
"Infinity",
|
|
111
|
-
"isFinite",
|
|
112
|
-
"isNaN",
|
|
113
|
-
"isPrototypeOf",
|
|
114
|
-
"length",
|
|
115
|
-
"Math",
|
|
116
|
-
"name",
|
|
117
|
-
"NaN",
|
|
118
|
-
"Number",
|
|
119
|
-
"Object",
|
|
120
|
-
"prototype",
|
|
121
|
-
"String",
|
|
122
|
-
"toString",
|
|
123
|
-
"undefined",
|
|
124
|
-
"valueOf"
|
|
125
|
-
]);
|
|
11
|
+
//#region ../../internals/shared/src/operation.ts
|
|
126
12
|
/**
|
|
127
|
-
*
|
|
13
|
+
* Builds the `ResolverFileParams` every operation generator passes to
|
|
14
|
+
* `resolver.file`: a file named `name`, tagged by the operation's first
|
|
15
|
+
* tag (or `'default'`), at the operation's path. Centralizes the entry object
|
|
16
|
+
* that was repeated at dozens of call sites across the client and query plugins.
|
|
128
17
|
*
|
|
129
18
|
* @example
|
|
130
19
|
* ```ts
|
|
131
|
-
*
|
|
132
|
-
* isValidVarName('class') // false (reserved word)
|
|
133
|
-
* isValidVarName('42foo') // false (starts with digit)
|
|
20
|
+
* resolver.file(operationFileEntry(node, node.operationId), { root, output, group })
|
|
134
21
|
* ```
|
|
135
22
|
*/
|
|
136
|
-
function
|
|
137
|
-
|
|
138
|
-
|
|
23
|
+
function operationFileEntry(node, name, extname = ".ts") {
|
|
24
|
+
return {
|
|
25
|
+
name,
|
|
26
|
+
extname,
|
|
27
|
+
tag: node.tags[0] ?? "default",
|
|
28
|
+
path: node.path
|
|
29
|
+
};
|
|
139
30
|
}
|
|
140
31
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* deciding whether an object key needs quoting.
|
|
32
|
+
* Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the
|
|
33
|
+
* current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the
|
|
34
|
+
* same dependency for the same operation in one pass (a query plugin's several hook generators, the
|
|
35
|
+
* MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.
|
|
146
36
|
*
|
|
147
|
-
* @example
|
|
37
|
+
* @example Cache `plugin-ts`'s file for the current operation
|
|
148
38
|
* ```ts
|
|
149
|
-
*
|
|
150
|
-
* isIdentifier('x-total')// false
|
|
39
|
+
* const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })
|
|
151
40
|
* ```
|
|
152
41
|
*/
|
|
153
|
-
function
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
*/
|
|
162
|
-
function transformParam(raw) {
|
|
163
|
-
return isValidVarName(raw) ? raw : camelCase(raw);
|
|
42
|
+
function resolveDependencyOperationFile(options) {
|
|
43
|
+
const { cache, node, resolver, root, output, group } = options;
|
|
44
|
+
return cache.ensureItem(`${resolver.pluginName}:operationFile`, () => resolver.file({
|
|
45
|
+
...operationFileEntry(node, node.operationId),
|
|
46
|
+
root,
|
|
47
|
+
output,
|
|
48
|
+
group: group ?? void 0
|
|
49
|
+
}));
|
|
164
50
|
}
|
|
165
|
-
/**
|
|
166
|
-
* Helpers for OpenAPI/Swagger paths.
|
|
167
|
-
*/
|
|
168
|
-
var Url = class Url {
|
|
169
|
-
/**
|
|
170
|
-
* Converts an OpenAPI/Swagger path to Express-style colon syntax.
|
|
171
|
-
*
|
|
172
|
-
* @example
|
|
173
|
-
* Url.toPath('/pet/{petId}') // '/pet/:petId'
|
|
174
|
-
*/
|
|
175
|
-
static toPath(path) {
|
|
176
|
-
return path.replace(/\{([^}]+)\}/g, ":$1");
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Rewrites OpenAPI placeholder names while keeping the `{...}` braces, so the generated `url`
|
|
180
|
-
* literal aligns with the grouped `path` request option that the runtime client interpolates by
|
|
181
|
-
* key.
|
|
182
|
-
*
|
|
183
|
-
* @example
|
|
184
|
-
* Url.toSafeTemplate('/user/{monetary-account-id}') // '/user/{monetaryAccountId}'
|
|
185
|
-
*/
|
|
186
|
-
static toSafeTemplate(path) {
|
|
187
|
-
return path.replace(/\{([^}]+)\}/g, (_, name) => `{${transformParam(name)}}`);
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Converts an OpenAPI/Swagger path to a TypeScript template literal string.
|
|
191
|
-
* `prefix` is prepended inside the literal, and `replacer` transforms each parameter name.
|
|
192
|
-
*
|
|
193
|
-
* @example
|
|
194
|
-
* Url.toTemplateString('/pet/{petId}') // '`/pet/${petId}`'
|
|
195
|
-
*
|
|
196
|
-
* @example
|
|
197
|
-
* Url.toTemplateString('/pet/{petId}', { prefix: 'https://api' }) // '`https://api/pet/${petId}`'
|
|
198
|
-
*/
|
|
199
|
-
static toTemplateString(path, { prefix, replacer } = {}) {
|
|
200
|
-
const result = path.split(/\{([^}]+)\}/).map((part, i) => {
|
|
201
|
-
if (i % 2 === 0) return part;
|
|
202
|
-
const param = transformParam(part);
|
|
203
|
-
return `\${${replacer ? replacer(param) : param}}`;
|
|
204
|
-
}).join("");
|
|
205
|
-
return `\`${prefix ?? ""}${result}\``;
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Converts an OpenAPI/Swagger path to a template literal that reads each parameter off the
|
|
209
|
-
* grouped `path` request option, e.g. `/pet/{petId}` becomes `` `/pet/${path.petId}` ``. Parameter
|
|
210
|
-
* names match the generated `path` type, and `prefix` is prepended inside the literal. Shared by
|
|
211
|
-
* the client and cypress generators that pass a grouped `path` object.
|
|
212
|
-
*
|
|
213
|
-
* @example
|
|
214
|
-
* Url.toGroupedTemplateString('/pet/{petId}') // '`/pet/${path.petId}`'
|
|
215
|
-
*/
|
|
216
|
-
static toGroupedTemplateString(path, { prefix } = {}) {
|
|
217
|
-
return Url.toTemplateString(path, {
|
|
218
|
-
prefix,
|
|
219
|
-
replacer: (name) => `path.${name}`
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
//#endregion
|
|
224
|
-
//#region ../../internals/shared/src/operation.ts
|
|
225
51
|
function getStatusCodeNumber(statusCode) {
|
|
226
52
|
const code = Number(statusCode);
|
|
227
53
|
return Number.isNaN(code) ? null : code;
|
|
@@ -253,6 +79,33 @@ function resolveResponseTypes(node, resolver) {
|
|
|
253
79
|
return types;
|
|
254
80
|
}
|
|
255
81
|
//#endregion
|
|
82
|
+
//#region ../../internals/utils/src/casing.ts
|
|
83
|
+
/**
|
|
84
|
+
* Shared implementation for camelCase and PascalCase conversion.
|
|
85
|
+
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
86
|
+
* and capitalizes each word according to `pascal`.
|
|
87
|
+
*
|
|
88
|
+
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
89
|
+
*/
|
|
90
|
+
function toCamelOrPascal(text, pascal) {
|
|
91
|
+
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) => {
|
|
92
|
+
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
93
|
+
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
94
|
+
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Converts `text` to camelCase.
|
|
98
|
+
*
|
|
99
|
+
* @example Word boundaries
|
|
100
|
+
* `camelCase('hello-world') // 'helloWorld'`
|
|
101
|
+
*
|
|
102
|
+
* @example With a prefix
|
|
103
|
+
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
104
|
+
*/
|
|
105
|
+
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
106
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
256
109
|
//#region ../../internals/shared/src/group.ts
|
|
257
110
|
/**
|
|
258
111
|
* Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
|
|
@@ -387,12 +240,6 @@ function getMswMethod(node) {
|
|
|
387
240
|
return kubb_kit.ast.isHttpOperationNode(node) ? node.method.toLowerCase() : "";
|
|
388
241
|
}
|
|
389
242
|
/**
|
|
390
|
-
* Converts an OpenAPI-style path to an Express/MSW-style path by replacing `{param}` with `:param`.
|
|
391
|
-
*/
|
|
392
|
-
function getMswUrl(node) {
|
|
393
|
-
return kubb_kit.ast.isHttpOperationNode(node) ? node.path.replaceAll("{", ":").replaceAll("}", "") : "";
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
243
|
* Resolves faker metadata for an MSW operation, including response name and file path.
|
|
397
244
|
*/
|
|
398
245
|
function resolveFakerMeta(node, options) {
|
|
@@ -419,7 +266,7 @@ function Mock({ baseURL = "", name, fakerName, typeName, requestTypeName, node }
|
|
|
419
266
|
const successResponse = getPrimarySuccessResponse(node);
|
|
420
267
|
const statusCode = successResponse ? Number(successResponse.statusCode) : 200;
|
|
421
268
|
const contentType = getContentType(successResponse);
|
|
422
|
-
const url = Url.toPath(
|
|
269
|
+
const url = kubb_kit.ast.isHttpOperationNode(node) ? kubb_kit.Url.toPath(node.path) : "";
|
|
423
270
|
const headers = [contentType ? `'Content-Type': '${contentType}'` : null].filter(Boolean);
|
|
424
271
|
const dataType = hasResponseSchema(successResponse) ? typeName : "string | number | boolean | null | object";
|
|
425
272
|
const paramType = fakerName ? typeName : dataType;
|
|
@@ -433,6 +280,7 @@ function Mock({ baseURL = "", name, fakerName, typeName, requestTypeName, node }
|
|
|
433
280
|
const requestUrl = `${baseURL}${url.replace(/([^/]):/g, "$1\\\\:")}`;
|
|
434
281
|
const urlLiteral = fakerName ? `'${requestUrl}'` : `\`${requestUrl}\``;
|
|
435
282
|
const responseBody = fakerName ? `JSON.stringify(data || ${fakerName}(data))` : "JSON.stringify(data)";
|
|
283
|
+
const headersBlock = headers.length ? `\n headers: {\n ${headers.join(", \n")}\n },` : "";
|
|
436
284
|
return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
|
|
437
285
|
name,
|
|
438
286
|
isIndexable: true,
|
|
@@ -445,10 +293,7 @@ function Mock({ baseURL = "", name, fakerName, typeName, requestTypeName, node }
|
|
|
445
293
|
if(typeof data === 'function') return data(info)
|
|
446
294
|
|
|
447
295
|
return new Response(${responseBody}, {
|
|
448
|
-
status: ${statusCode}
|
|
449
|
-
${headers.length ? ` headers: {
|
|
450
|
-
${headers.join(", \n")}
|
|
451
|
-
},` : ""}
|
|
296
|
+
status: ${statusCode},${headersBlock}
|
|
452
297
|
})
|
|
453
298
|
})`
|
|
454
299
|
})
|
|
@@ -467,6 +312,7 @@ function Response({ name, typeName, response }) {
|
|
|
467
312
|
optional: !hasResponseSchema(response)
|
|
468
313
|
})] }));
|
|
469
314
|
const responseName = `${name}Response${statusCode}`;
|
|
315
|
+
const headersBlock = headers.length ? `\n headers: {\n ${headers.join(", \n")}\n },` : "";
|
|
470
316
|
return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
|
|
471
317
|
name: responseName,
|
|
472
318
|
isIndexable: true,
|
|
@@ -477,10 +323,7 @@ function Response({ name, typeName, response }) {
|
|
|
477
323
|
params: params ?? "",
|
|
478
324
|
children: `
|
|
479
325
|
return new Response(JSON.stringify(data), {
|
|
480
|
-
status: ${statusCode}
|
|
481
|
-
${headers.length ? ` headers: {
|
|
482
|
-
${headers.join(", \n")}
|
|
483
|
-
},` : ""}
|
|
326
|
+
status: ${statusCode},${headersBlock}
|
|
484
327
|
})`
|
|
485
328
|
})
|
|
486
329
|
});
|
|
@@ -524,14 +367,13 @@ const mswGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
524
367
|
if (!pluginTs) return null;
|
|
525
368
|
const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
|
|
526
369
|
const type = {
|
|
527
|
-
file:
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
path: node.path,
|
|
370
|
+
file: resolveDependencyOperationFile({
|
|
371
|
+
cache: ctx.cache,
|
|
372
|
+
node,
|
|
373
|
+
resolver: tsResolver,
|
|
532
374
|
root,
|
|
533
375
|
output: pluginTs.options?.output ?? output,
|
|
534
|
-
group: pluginTs.options?.group
|
|
376
|
+
group: pluginTs.options?.group
|
|
535
377
|
}),
|
|
536
378
|
responseName: tsResolver.response.response(node)
|
|
537
379
|
};
|