@kubb/plugin-ts 5.0.0-beta.85 → 5.0.0-beta.87

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.d.ts CHANGED
@@ -2,7 +2,6 @@ import { n as __name } from "./rolldown-runtime-CNktS9qV.js";
2
2
  import { KubbReactNode } from "kubb/jsx";
3
3
  import { Exclude, Group, Include, Output, OutputOptions, Override, PluginFactoryOptions, Resolver, ResolverPatch, ast } from "kubb/kit";
4
4
  import ts from "typescript";
5
-
6
5
  //#region src/printers/printerTs.d.ts
7
6
  /**
8
7
  * Partial map of node-type overrides for the TypeScript printer.
@@ -525,7 +524,7 @@ declare const pluginTsName = "plugin-ts";
525
524
  * import { pluginTs } from '@kubb/plugin-ts'
526
525
  *
527
526
  * export default defineConfig({
528
- * input: { path: './petStore.yaml' },
527
+ * input: './petStore.yaml',
529
528
  * output: { path: './src/gen' },
530
529
  * plugins: [
531
530
  * pluginTs({
package/dist/index.js CHANGED
@@ -192,7 +192,7 @@ const reservedWords = /* @__PURE__ */ new Set([
192
192
  */
193
193
  function isValidVarName(name) {
194
194
  if (!name || reservedWords.has(name)) return false;
195
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
195
+ return isIdentifier(name);
196
196
  }
197
197
  /**
198
198
  * Returns `name` when it's a syntactically valid JavaScript variable name,
@@ -214,6 +214,22 @@ function ensureValidVarName(name) {
214
214
  if (!name || isValidVarName(name)) return name;
215
215
  return `_${name}`;
216
216
  }
217
+ /**
218
+ * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
219
+ *
220
+ * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
221
+ * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
222
+ * deciding whether an object key needs quoting.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * isIdentifier('name') // true
227
+ * isIdentifier('x-total')// false
228
+ * ```
229
+ */
230
+ function isIdentifier(name) {
231
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
232
+ }
217
233
  //#endregion
218
234
  //#region ../../internals/utils/src/strings.ts
219
235
  /**
@@ -526,7 +542,7 @@ function createInterfaceDeclaration({ modifiers, name, typeParameters, members }
526
542
  * Intelligently selects the syntax based on the type structure and attaches JSDoc comments.
527
543
  */
528
544
  function createTypeDeclaration({ syntax, isExportable, comments, name, type }) {
529
- if (syntax === "interface" && "members" in type) return appendJSDocToNode({
545
+ if (syntax === "interface" && ts.isTypeLiteralNode(type)) return appendJSDocToNode({
530
546
  node: createInterfaceDeclaration({
531
547
  members: [...type.members],
532
548
  modifiers: isExportable ? [modifiers.export] : [],
@@ -625,7 +641,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
625
641
  }).filter((node) => node !== void 0)))];
626
642
  if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(ts.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(ts.SyntaxKind.ConstKeyword) : void 0].filter((modifier) => modifier !== void 0), factory.createIdentifier(typeName), enums.map(([key, value, description]) => {
627
643
  let initializer = factory.createStringLiteral(value?.toString());
628
- if (Number.parseInt(value.toString(), 10) === value && isNumber(Number.parseInt(value.toString(), 10))) if (value < 0) initializer = factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
644
+ if (Number.parseInt(value.toString(), 10) === value && isNumber(value)) if (value < 0) initializer = factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
629
645
  else initializer = factory.createNumericLiteral(value);
630
646
  if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
631
647
  if (isNumber(Number.parseInt(key.toString(), 10))) {
@@ -900,13 +916,13 @@ function Enum({ node, enum: enumOptions, resolver }) {
900
916
  isExportable: true,
901
917
  isIndexable: true,
902
918
  isTypeOnly: false,
903
- children: parserTs.print(nameNode)
919
+ children: parserTs().print(nameNode)
904
920
  }), /* @__PURE__ */ jsx(File.Source, {
905
921
  name: typeName,
906
922
  isIndexable: !namesMerge,
907
923
  isExportable: !namesMerge && ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumOptions.type),
908
924
  isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumOptions.type),
909
- children: parserTs.print(typeNode)
925
+ children: parserTs().print(typeNode)
910
926
  })] });
911
927
  }
912
928
  //#endregion
@@ -1007,6 +1023,24 @@ function getOperationParameters(node, options = {}) {
1007
1023
  };
1008
1024
  }
1009
1025
  //#endregion
1026
+ //#region ../../internals/shared/src/adapter.ts
1027
+ /**
1028
+ * Narrows the generic `Adapter` from a generator context to the OpenAPI adapter,
1029
+ * so OAS-only options (`dateType`, `nameMapping`) and the parsed `document` are typed.
1030
+ *
1031
+ * Throws when a non-OAS adapter is configured, turning a silently wrong cast into a
1032
+ * clear, actionable error at the point of use.
1033
+ *
1034
+ * @example
1035
+ * ```ts
1036
+ * const { dateType } = getOasAdapter(ctx.adapter).options
1037
+ * ```
1038
+ */
1039
+ function getOasAdapter(adapter) {
1040
+ if (adapter.name !== "oas") throw new Error(`Expected the OpenAPI adapter (adapterOas), but received "${adapter.name}". Configure \`adapter: adapterOas()\` in your Kubb config.`);
1041
+ return adapter;
1042
+ }
1043
+ //#endregion
1010
1044
  //#region ../../internals/shared/src/group.ts
1011
1045
  /**
1012
1046
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -1074,7 +1108,7 @@ function buildPropertyJSDocComments(schema, optional) {
1074
1108
  !isArray && meta && "min" in meta && meta.min !== void 0 ? `@minLength ${meta.min}` : null,
1075
1109
  !isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` : null,
1076
1110
  meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` : null,
1077
- meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? stringify(meta.default) : meta.default}` : null,
1111
+ meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" && typeof meta.default === "string" ? stringify(meta.default) : meta.default}` : null,
1078
1112
  ...exampleValues.map((example) => `@example ${example}`),
1079
1113
  meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, optional ?? isSchemaOptional(schema) ? " | undefined" : null].filter(Boolean).join("") : null
1080
1114
  ].filter(Boolean);
@@ -1385,7 +1419,7 @@ const printerTs = ast.createPrinter((options) => {
1385
1419
  if (!name) {
1386
1420
  const withNullable = meta.nullable ? createUnionDeclaration({ nodes: [transformed, keywordTypeNodes.null] }) : transformed;
1387
1421
  const result = (meta.nullish || meta.optional) && addsUndefined ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
1388
- return parserTs.print(result);
1422
+ return parserTs().print(result);
1389
1423
  }
1390
1424
  const inner = (() => {
1391
1425
  const omitted = keysToOmit?.length ? createOmitDeclaration({
@@ -1406,13 +1440,22 @@ const printerTs = ast.createPrinter((options) => {
1406
1440
  description
1407
1441
  })
1408
1442
  });
1409
- return parserTs.print(typeNode);
1443
+ return parserTs().print(typeNode);
1410
1444
  }
1411
1445
  };
1412
1446
  });
1413
1447
  //#endregion
1414
1448
  //#region src/generators/typeGenerator.tsx
1415
1449
  /**
1450
+ * Resolves the imported type name for a referenced schema. An enum schema emitted
1451
+ * as a `const` object imports its suffixed key alias (e.g. `StatusKey`); every other
1452
+ * schema imports its plain resolved name.
1453
+ */
1454
+ function resolveImportName({ schemaName, enumOptions, enumSchemaNames, resolver }) {
1455
+ if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.enum.keyName({ name: schemaName }, enumOptions.typeSuffix);
1456
+ return resolver.name(schemaName);
1457
+ }
1458
+ /**
1416
1459
  * Built-in generator for `@kubb/plugin-ts`. Emits one TypeScript file per
1417
1460
  * schema in the spec plus per-operation request, response, and parameter
1418
1461
  * types. Drop-replace with a custom `Generator<PluginTs>` to change how
@@ -1426,12 +1469,13 @@ const typeGenerator = defineGenerator({
1426
1469
  const { adapter, config, resolver, root } = ctx;
1427
1470
  if (!node.name) return;
1428
1471
  const enumSchemaNames = new Set(ctx.meta.enumNames);
1429
- function resolveImportName(schemaName) {
1430
- if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.enum.keyName({ name: schemaName }, enumOptions.typeSuffix);
1431
- return resolver.name(schemaName);
1432
- }
1433
1472
  const imports = adapter.getImports(node, (schemaName) => ({
1434
- name: resolveImportName(schemaName),
1473
+ name: resolveImportName({
1474
+ schemaName,
1475
+ enumOptions,
1476
+ enumSchemaNames,
1477
+ resolver
1478
+ }),
1435
1479
  path: resolver.file({
1436
1480
  name: schemaName,
1437
1481
  extname: ".ts",
@@ -1461,7 +1505,7 @@ const typeGenerator = defineGenerator({
1461
1505
  description: node.description,
1462
1506
  resolver,
1463
1507
  enumSchemaNames,
1464
- nameMapping: adapter.options.nameMapping,
1508
+ nameMapping: getOasAdapter(adapter).options.nameMapping,
1465
1509
  nodes: printer?.nodes
1466
1510
  });
1467
1511
  return /* @__PURE__ */ jsxs(File, {
@@ -1516,14 +1560,15 @@ const typeGenerator = defineGenerator({
1516
1560
  group: group ?? void 0
1517
1561
  }) };
1518
1562
  const enumSchemaNames = new Set(ctx.meta.enumNames);
1519
- function resolveImportName(schemaName) {
1520
- if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.enum.keyName({ name: schemaName }, enumOptions.typeSuffix);
1521
- return resolver.name(schemaName);
1522
- }
1523
1563
  function renderSchemaType({ schema, name, keysToOmit }) {
1524
1564
  if (!schema) return null;
1525
1565
  const imports = adapter.getImports(schema, (schemaName) => ({
1526
- name: resolveImportName(schemaName),
1566
+ name: resolveImportName({
1567
+ schemaName,
1568
+ enumOptions,
1569
+ enumSchemaNames,
1570
+ resolver
1571
+ }),
1527
1572
  path: resolver.file({
1528
1573
  name: schemaName,
1529
1574
  extname: ".ts",
@@ -1542,7 +1587,7 @@ const typeGenerator = defineGenerator({
1542
1587
  keysToOmit,
1543
1588
  resolver,
1544
1589
  enumSchemaNames,
1545
- nameMapping: adapter.options.nameMapping,
1590
+ nameMapping: getOasAdapter(adapter).options.nameMapping,
1546
1591
  nodes: printer?.nodes
1547
1592
  });
1548
1593
  return /* @__PURE__ */ jsxs(Fragment, { children: [imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
@@ -1652,7 +1697,12 @@ const typeGenerator = defineGenerator({
1652
1697
  const responseName = resolver.response.response(node);
1653
1698
  const responsesWithSchema = node.responses.filter(hasSchema);
1654
1699
  if (new Set(responsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1655
- name: resolveImportName(schemaName),
1700
+ name: resolveImportName({
1701
+ schemaName,
1702
+ enumOptions,
1703
+ enumSchemaNames,
1704
+ resolver
1705
+ }),
1656
1706
  path: ""
1657
1707
  })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseName)) return null;
1658
1708
  return renderSchemaType({
@@ -1778,7 +1828,7 @@ const pluginTsName = "plugin-ts";
1778
1828
  * import { pluginTs } from '@kubb/plugin-ts'
1779
1829
  *
1780
1830
  * export default defineConfig({
1781
- * input: { path: './petStore.yaml' },
1831
+ * input: './petStore.yaml',
1782
1832
  * output: { path: './src/gen' },
1783
1833
  * plugins: [
1784
1834
  * pluginTs({
@@ -2015,14 +2065,14 @@ function renderGroupType(type, sorted, transformType) {
2015
2065
  }
2016
2066
  function printParameter(node, options) {
2017
2067
  const { mode, transformName, transformType } = options;
2018
- const isGroup = typeof node.name !== "string";
2068
+ const bindingName = node.name;
2019
2069
  if (mode === "call") {
2020
- if (isGroup) return `{ ${sortedGroupMembers(node.name, node.type).map((member) => renderBindingMember(member)).join(", ")} }`;
2021
- const name = transformName ? transformName(node.name) : node.name;
2070
+ if (typeof bindingName !== "string") return `{ ${sortedGroupMembers(bindingName, node.type).map((member) => renderBindingMember(member)).join(", ")} }`;
2071
+ const name = transformName ? transformName(bindingName) : bindingName;
2022
2072
  return node.rest ? `...${name}` : name;
2023
2073
  }
2024
- if (isGroup) {
2025
- const sorted = sortedGroupMembers(node.name, node.type);
2074
+ if (typeof bindingName !== "string") {
2075
+ const sorted = sortedGroupMembers(bindingName, node.type);
2026
2076
  const binding = `{ ${sorted.map((member) => renderBindingMember(member, transformName)).join(", ")} }`;
2027
2077
  const allOptional = sorted.every((member) => member.optional);
2028
2078
  const type = renderGroupType(node.type, sorted, transformType);
@@ -2032,7 +2082,7 @@ function printParameter(node, options) {
2032
2082
  }
2033
2083
  return node.default ? `${binding} = ${node.default}` : binding;
2034
2084
  }
2035
- const name = transformName ? transformName(node.name) : node.name;
2085
+ const name = transformName ? transformName(bindingName) : bindingName;
2036
2086
  const type = node.type ? renderType(node.type, transformType) : void 0;
2037
2087
  if (node.rest) return type ? `...${name}: ${type}` : `...${name}`;
2038
2088
  if (type) {