@kubb/plugin-ts 5.0.0-beta.22 → 5.0.0-beta.27
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 +183 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +78 -55
- package/dist/index.js +183 -40
- package/dist/index.js.map +1 -1
- package/extension.yaml +690 -247
- package/package.json +5 -5
- package/src/components/Enum.tsx +3 -3
- package/src/factory.ts +6 -6
- package/src/generators/typeGenerator.tsx +13 -4
- package/src/plugin.ts +18 -9
- package/src/printers/printerTs.ts +3 -3
- package/src/resolvers/resolverTs.ts +17 -14
- package/src/types.ts +44 -37
- package/src/utils.ts +9 -9
package/dist/index.cjs
CHANGED
|
@@ -171,6 +171,129 @@ function stringify(value) {
|
|
|
171
171
|
return JSON.stringify(trimQuotes(value.toString()));
|
|
172
172
|
}
|
|
173
173
|
//#endregion
|
|
174
|
+
//#region ../../internals/utils/src/reserved.ts
|
|
175
|
+
/**
|
|
176
|
+
* JavaScript and Java reserved words.
|
|
177
|
+
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
178
|
+
*/
|
|
179
|
+
const reservedWords = new Set([
|
|
180
|
+
"abstract",
|
|
181
|
+
"arguments",
|
|
182
|
+
"boolean",
|
|
183
|
+
"break",
|
|
184
|
+
"byte",
|
|
185
|
+
"case",
|
|
186
|
+
"catch",
|
|
187
|
+
"char",
|
|
188
|
+
"class",
|
|
189
|
+
"const",
|
|
190
|
+
"continue",
|
|
191
|
+
"debugger",
|
|
192
|
+
"default",
|
|
193
|
+
"delete",
|
|
194
|
+
"do",
|
|
195
|
+
"double",
|
|
196
|
+
"else",
|
|
197
|
+
"enum",
|
|
198
|
+
"eval",
|
|
199
|
+
"export",
|
|
200
|
+
"extends",
|
|
201
|
+
"false",
|
|
202
|
+
"final",
|
|
203
|
+
"finally",
|
|
204
|
+
"float",
|
|
205
|
+
"for",
|
|
206
|
+
"function",
|
|
207
|
+
"goto",
|
|
208
|
+
"if",
|
|
209
|
+
"implements",
|
|
210
|
+
"import",
|
|
211
|
+
"in",
|
|
212
|
+
"instanceof",
|
|
213
|
+
"int",
|
|
214
|
+
"interface",
|
|
215
|
+
"let",
|
|
216
|
+
"long",
|
|
217
|
+
"native",
|
|
218
|
+
"new",
|
|
219
|
+
"null",
|
|
220
|
+
"package",
|
|
221
|
+
"private",
|
|
222
|
+
"protected",
|
|
223
|
+
"public",
|
|
224
|
+
"return",
|
|
225
|
+
"short",
|
|
226
|
+
"static",
|
|
227
|
+
"super",
|
|
228
|
+
"switch",
|
|
229
|
+
"synchronized",
|
|
230
|
+
"this",
|
|
231
|
+
"throw",
|
|
232
|
+
"throws",
|
|
233
|
+
"transient",
|
|
234
|
+
"true",
|
|
235
|
+
"try",
|
|
236
|
+
"typeof",
|
|
237
|
+
"var",
|
|
238
|
+
"void",
|
|
239
|
+
"volatile",
|
|
240
|
+
"while",
|
|
241
|
+
"with",
|
|
242
|
+
"yield",
|
|
243
|
+
"Array",
|
|
244
|
+
"Date",
|
|
245
|
+
"hasOwnProperty",
|
|
246
|
+
"Infinity",
|
|
247
|
+
"isFinite",
|
|
248
|
+
"isNaN",
|
|
249
|
+
"isPrototypeOf",
|
|
250
|
+
"length",
|
|
251
|
+
"Math",
|
|
252
|
+
"name",
|
|
253
|
+
"NaN",
|
|
254
|
+
"Number",
|
|
255
|
+
"Object",
|
|
256
|
+
"prototype",
|
|
257
|
+
"String",
|
|
258
|
+
"toString",
|
|
259
|
+
"undefined",
|
|
260
|
+
"valueOf"
|
|
261
|
+
]);
|
|
262
|
+
/**
|
|
263
|
+
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* isValidVarName('status') // true
|
|
268
|
+
* isValidVarName('class') // false (reserved word)
|
|
269
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
function isValidVarName(name) {
|
|
273
|
+
if (!name || reservedWords.has(name)) return false;
|
|
274
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Returns `name` when it's a syntactically valid JavaScript variable name,
|
|
278
|
+
* otherwise prefixes it with `_` so the result is a valid identifier.
|
|
279
|
+
*
|
|
280
|
+
* Useful for sanitizing OpenAPI schema names or operation IDs that start with
|
|
281
|
+
* a digit (e.g. `409`, `504AccountCancel`) before using them as exported
|
|
282
|
+
* variable, type, or function names.
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* ensureValidVarName('409') // '_409'
|
|
287
|
+
* ensureValidVarName('504AccountCancel') // '_504AccountCancel'
|
|
288
|
+
* ensureValidVarName('Pet') // 'Pet'
|
|
289
|
+
* ensureValidVarName('class') // '_class'
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
function ensureValidVarName(name) {
|
|
293
|
+
if (!name || isValidVarName(name)) return name;
|
|
294
|
+
return `_${name}`;
|
|
295
|
+
}
|
|
296
|
+
//#endregion
|
|
174
297
|
//#region src/constants.ts
|
|
175
298
|
/**
|
|
176
299
|
* `optionalType` values that cause a property's type to include `| undefined`.
|
|
@@ -664,13 +787,13 @@ function Enum({ node, enumType, enumTypeSuffix, enumKeyCasing, resolver }) {
|
|
|
664
787
|
isExportable: true,
|
|
665
788
|
isIndexable: true,
|
|
666
789
|
isTypeOnly: false,
|
|
667
|
-
children:
|
|
790
|
+
children: _kubb_parser_ts.parserTs.print(nameNode)
|
|
668
791
|
}), /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
669
792
|
name: typeName,
|
|
670
793
|
isIndexable: true,
|
|
671
794
|
isExportable: ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType),
|
|
672
795
|
isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumType),
|
|
673
|
-
children:
|
|
796
|
+
children: _kubb_parser_ts.parserTs.print(typeNode)
|
|
674
797
|
})] });
|
|
675
798
|
}
|
|
676
799
|
//#endregion
|
|
@@ -733,14 +856,14 @@ function buildPropertyJSDocComments(schema) {
|
|
|
733
856
|
const meta = _kubb_core.ast.syncSchemaRef(schema);
|
|
734
857
|
const isArray = meta?.primitive === "array";
|
|
735
858
|
return [
|
|
736
|
-
meta && "description" in meta && meta.description ? `@description ${jsStringEscape(meta.description)}` :
|
|
737
|
-
meta && "deprecated" in meta && meta.deprecated ? "@deprecated" :
|
|
738
|
-
!isArray && meta && "min" in meta && meta.min !== void 0 ? `@minLength ${meta.min}` :
|
|
739
|
-
!isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` :
|
|
740
|
-
meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` :
|
|
741
|
-
meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? stringify(meta.default) : meta.default}` :
|
|
742
|
-
meta && "example" in meta && meta.example !== void 0 ? `@example ${meta.example}` :
|
|
743
|
-
meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, "optional" in schema && schema.optional ? " | undefined" :
|
|
859
|
+
meta && "description" in meta && meta.description ? `@description ${jsStringEscape(meta.description)}` : null,
|
|
860
|
+
meta && "deprecated" in meta && meta.deprecated ? "@deprecated" : null,
|
|
861
|
+
!isArray && meta && "min" in meta && meta.min !== void 0 ? `@minLength ${meta.min}` : null,
|
|
862
|
+
!isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` : null,
|
|
863
|
+
meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` : null,
|
|
864
|
+
meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? stringify(meta.default) : meta.default}` : null,
|
|
865
|
+
meta && "example" in meta && meta.example !== void 0 ? `@example ${meta.example}` : null,
|
|
866
|
+
meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, "optional" in schema && schema.optional ? " | undefined" : null].filter(Boolean).join("") : null
|
|
744
867
|
].filter(Boolean);
|
|
745
868
|
}
|
|
746
869
|
function buildParams(node, { params, resolver }) {
|
|
@@ -984,7 +1107,8 @@ const printerTs = _kubb_core.ast.definePrinter((options) => {
|
|
|
984
1107
|
const meta = _kubb_core.ast.syncSchemaRef(node);
|
|
985
1108
|
if (!name) {
|
|
986
1109
|
const withNullable = meta.nullable ? createUnionDeclaration({ nodes: [transformed, keywordTypeNodes.null] }) : transformed;
|
|
987
|
-
|
|
1110
|
+
const result = (meta.nullish || meta.optional) && addsUndefined ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
|
|
1111
|
+
return _kubb_parser_ts.parserTs.print(result);
|
|
988
1112
|
}
|
|
989
1113
|
const inner = (() => {
|
|
990
1114
|
const omitted = keysToOmit?.length ? createOmitDeclaration({
|
|
@@ -995,17 +1119,17 @@ const printerTs = _kubb_core.ast.definePrinter((options) => {
|
|
|
995
1119
|
const withNullable = meta.nullable ? createUnionDeclaration({ nodes: [omitted, keywordTypeNodes.null] }) : omitted;
|
|
996
1120
|
return meta.nullish || meta.optional ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
|
|
997
1121
|
})();
|
|
998
|
-
const
|
|
999
|
-
return (0, _kubb_parser_ts.safePrint)(createTypeDeclaration({
|
|
1122
|
+
const typeNode = createTypeDeclaration({
|
|
1000
1123
|
name,
|
|
1001
1124
|
isExportable: true,
|
|
1002
1125
|
type: inner,
|
|
1003
|
-
syntax:
|
|
1126
|
+
syntax: syntaxType === "type" || inner.kind === syntaxKind.union || !!keysToOmit?.length ? "type" : "interface",
|
|
1004
1127
|
comments: buildPropertyJSDocComments({
|
|
1005
1128
|
...meta,
|
|
1006
1129
|
description
|
|
1007
1130
|
})
|
|
1008
|
-
})
|
|
1131
|
+
});
|
|
1132
|
+
return _kubb_parser_ts.parserTs.print(typeNode);
|
|
1009
1133
|
}
|
|
1010
1134
|
};
|
|
1011
1135
|
});
|
|
@@ -1024,6 +1148,12 @@ function getPerContentTypeName(dataName, suffix) {
|
|
|
1024
1148
|
if (dataName.endsWith("Data")) return suffix.endsWith("Data") ? dataName.slice(0, -4) + suffix : `${dataName.slice(0, -4)}${suffix}Data`;
|
|
1025
1149
|
return dataName + suffix;
|
|
1026
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Built-in generator for `@kubb/plugin-ts`. Emits one TypeScript file per
|
|
1153
|
+
* schema in the spec plus per-operation request, response, and parameter
|
|
1154
|
+
* types. Drop-replace with a custom `Generator<PluginTs>` to change how
|
|
1155
|
+
* TypeScript output is produced.
|
|
1156
|
+
*/
|
|
1027
1157
|
const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
1028
1158
|
name: "typescript",
|
|
1029
1159
|
renderer: _kubb_renderer_jsx.jsxRendererSync,
|
|
@@ -1045,7 +1175,7 @@ const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1045
1175
|
}, {
|
|
1046
1176
|
root,
|
|
1047
1177
|
output,
|
|
1048
|
-
group
|
|
1178
|
+
group: group ?? void 0
|
|
1049
1179
|
}).path
|
|
1050
1180
|
}));
|
|
1051
1181
|
const isEnumSchema = !!_kubb_core.ast.narrowSchema(node, _kubb_core.ast.schemaTypes.enum);
|
|
@@ -1057,7 +1187,7 @@ const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1057
1187
|
}, {
|
|
1058
1188
|
root,
|
|
1059
1189
|
output,
|
|
1060
|
-
group
|
|
1190
|
+
group: group ?? void 0
|
|
1061
1191
|
})
|
|
1062
1192
|
};
|
|
1063
1193
|
const schemaPrinter = printerTs({
|
|
@@ -1117,7 +1247,7 @@ const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1117
1247
|
}, {
|
|
1118
1248
|
root,
|
|
1119
1249
|
output,
|
|
1120
|
-
group
|
|
1250
|
+
group: group ?? void 0
|
|
1121
1251
|
}) };
|
|
1122
1252
|
const enumSchemaNames = new Set(ctx.meta.enumNames);
|
|
1123
1253
|
function resolveImportName(schemaName) {
|
|
@@ -1134,7 +1264,7 @@ const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1134
1264
|
}, {
|
|
1135
1265
|
root,
|
|
1136
1266
|
output,
|
|
1137
|
-
group
|
|
1267
|
+
group: group ?? void 0
|
|
1138
1268
|
}).path
|
|
1139
1269
|
}));
|
|
1140
1270
|
const schemaPrinter = printerTs({
|
|
@@ -1280,20 +1410,21 @@ const typeGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1280
1410
|
//#endregion
|
|
1281
1411
|
//#region src/resolvers/resolverTs.ts
|
|
1282
1412
|
/**
|
|
1283
|
-
*
|
|
1284
|
-
*
|
|
1285
|
-
*
|
|
1413
|
+
* Default resolver used by `@kubb/plugin-ts`. Decides the names and file paths
|
|
1414
|
+
* for every generated TypeScript type. Import this in other plugins that need
|
|
1415
|
+
* to reference the exact names `plugin-ts` produces without duplicating the
|
|
1416
|
+
* casing/file-layout rules.
|
|
1286
1417
|
*
|
|
1287
|
-
* The `default` method is
|
|
1288
|
-
*
|
|
1418
|
+
* The `default` method is supplied by `defineResolver`. It uses PascalCase for
|
|
1419
|
+
* type names and PascalCase-with-isFile for files.
|
|
1289
1420
|
*
|
|
1290
|
-
* @example
|
|
1421
|
+
* @example Resolve a type and file name
|
|
1291
1422
|
* ```ts
|
|
1292
|
-
* import {
|
|
1423
|
+
* import { resolverTs } from '@kubb/plugin-ts'
|
|
1293
1424
|
*
|
|
1294
|
-
*
|
|
1295
|
-
*
|
|
1296
|
-
*
|
|
1425
|
+
* resolverTs.default('list pets', 'type') // 'ListPets'
|
|
1426
|
+
* resolverTs.resolvePathName('list pets', 'file') // 'ListPets'
|
|
1427
|
+
* resolverTs.resolveResponseStatusName(node, 200) // 'ListPetsStatus200'
|
|
1297
1428
|
* ```
|
|
1298
1429
|
*/
|
|
1299
1430
|
const resolverTs = (0, _kubb_core.defineResolver)(() => {
|
|
@@ -1301,13 +1432,15 @@ const resolverTs = (0, _kubb_core.defineResolver)(() => {
|
|
|
1301
1432
|
name: "default",
|
|
1302
1433
|
pluginName: "plugin-ts",
|
|
1303
1434
|
default(name, type) {
|
|
1304
|
-
|
|
1435
|
+
const resolved = pascalCase(name, { isFile: type === "file" });
|
|
1436
|
+
return type === "file" ? resolved : ensureValidVarName(resolved);
|
|
1305
1437
|
},
|
|
1306
1438
|
resolveTypeName(name) {
|
|
1307
|
-
return pascalCase(name);
|
|
1439
|
+
return ensureValidVarName(pascalCase(name));
|
|
1308
1440
|
},
|
|
1309
1441
|
resolvePathName(name, type) {
|
|
1310
|
-
|
|
1442
|
+
const resolved = pascalCase(name, { isFile: type === "file" });
|
|
1443
|
+
return type === "file" ? resolved : ensureValidVarName(resolved);
|
|
1311
1444
|
},
|
|
1312
1445
|
resolveParamName(node, param) {
|
|
1313
1446
|
return this.resolveTypeName(`${node.operationId} ${param.in} ${param.name}`);
|
|
@@ -1344,22 +1477,31 @@ const resolverTs = (0, _kubb_core.defineResolver)(() => {
|
|
|
1344
1477
|
//#endregion
|
|
1345
1478
|
//#region src/plugin.ts
|
|
1346
1479
|
/**
|
|
1347
|
-
* Canonical plugin name for `@kubb/plugin-ts
|
|
1480
|
+
* Canonical plugin name for `@kubb/plugin-ts`. Used for driver lookups and
|
|
1481
|
+
* cross-plugin dependency references.
|
|
1348
1482
|
*/
|
|
1349
1483
|
const pluginTsName = "plugin-ts";
|
|
1350
1484
|
/**
|
|
1351
|
-
*
|
|
1352
|
-
*
|
|
1353
|
-
*
|
|
1354
|
-
*
|
|
1355
|
-
* and writes barrel files based on `output.barrelType`.
|
|
1485
|
+
* Generates TypeScript `type` aliases and `interface` declarations from an
|
|
1486
|
+
* OpenAPI spec. The foundation that every other Kubb plugin builds on:
|
|
1487
|
+
* clients, query hooks, mocks, and validators all reference the names this
|
|
1488
|
+
* plugin produces.
|
|
1356
1489
|
*
|
|
1357
1490
|
* @example
|
|
1358
1491
|
* ```ts
|
|
1359
|
-
* import
|
|
1492
|
+
* import { defineConfig } from 'kubb'
|
|
1493
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
1360
1494
|
*
|
|
1361
1495
|
* export default defineConfig({
|
|
1362
|
-
*
|
|
1496
|
+
* input: { path: './petStore.yaml' },
|
|
1497
|
+
* output: { path: './src/gen' },
|
|
1498
|
+
* plugins: [
|
|
1499
|
+
* pluginTs({
|
|
1500
|
+
* output: { path: './types' },
|
|
1501
|
+
* enumType: 'asConst',
|
|
1502
|
+
* optionalType: 'questionTokenAndUndefined',
|
|
1503
|
+
* }),
|
|
1504
|
+
* ],
|
|
1363
1505
|
* })
|
|
1364
1506
|
* ```
|
|
1365
1507
|
*/
|
|
@@ -1374,7 +1516,7 @@ const pluginTs = (0, _kubb_core.definePlugin)((options) => {
|
|
|
1374
1516
|
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
1375
1517
|
return `${camelCase(ctx.group)}Controller`;
|
|
1376
1518
|
}
|
|
1377
|
-
} :
|
|
1519
|
+
} : null;
|
|
1378
1520
|
return {
|
|
1379
1521
|
name: pluginTsName,
|
|
1380
1522
|
options,
|