@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.cjs CHANGED
@@ -231,7 +231,7 @@ const reservedWords = /* @__PURE__ */ new Set([
231
231
  */
232
232
  function isValidVarName(name) {
233
233
  if (!name || reservedWords.has(name)) return false;
234
- return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
234
+ return isIdentifier(name);
235
235
  }
236
236
  /**
237
237
  * Returns `name` when it's a syntactically valid JavaScript variable name,
@@ -253,6 +253,22 @@ function ensureValidVarName(name) {
253
253
  if (!name || isValidVarName(name)) return name;
254
254
  return `_${name}`;
255
255
  }
256
+ /**
257
+ * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
258
+ *
259
+ * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
260
+ * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
261
+ * deciding whether an object key needs quoting.
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * isIdentifier('name') // true
266
+ * isIdentifier('x-total')// false
267
+ * ```
268
+ */
269
+ function isIdentifier(name) {
270
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
271
+ }
256
272
  //#endregion
257
273
  //#region ../../internals/utils/src/strings.ts
258
274
  /**
@@ -565,7 +581,7 @@ function createInterfaceDeclaration({ modifiers, name, typeParameters, members }
565
581
  * Intelligently selects the syntax based on the type structure and attaches JSDoc comments.
566
582
  */
567
583
  function createTypeDeclaration({ syntax, isExportable, comments, name, type }) {
568
- if (syntax === "interface" && "members" in type) return appendJSDocToNode({
584
+ if (syntax === "interface" && typescript.default.isTypeLiteralNode(type)) return appendJSDocToNode({
569
585
  node: createInterfaceDeclaration({
570
586
  members: [...type.members],
571
587
  modifiers: isExportable ? [modifiers.export] : [],
@@ -664,7 +680,7 @@ function createEnumDeclaration({ type = "enum", name, typeName, enums, enumKeyCa
664
680
  }).filter((node) => node !== void 0)))];
665
681
  if (type === "enum" || type === "constEnum") return [void 0, factory.createEnumDeclaration([factory.createToken(typescript.default.SyntaxKind.ExportKeyword), type === "constEnum" ? factory.createToken(typescript.default.SyntaxKind.ConstKeyword) : void 0].filter((modifier) => modifier !== void 0), factory.createIdentifier(typeName), enums.map(([key, value, description]) => {
666
682
  let initializer = factory.createStringLiteral(value?.toString());
667
- if (Number.parseInt(value.toString(), 10) === value && isNumber(Number.parseInt(value.toString(), 10))) if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
683
+ if (Number.parseInt(value.toString(), 10) === value && isNumber(value)) if (value < 0) initializer = factory.createPrefixUnaryExpression(typescript.default.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)));
668
684
  else initializer = factory.createNumericLiteral(value);
669
685
  if (typeof value === "boolean") initializer = value ? factory.createTrue() : factory.createFalse();
670
686
  if (isNumber(Number.parseInt(key.toString(), 10))) {
@@ -939,13 +955,13 @@ function Enum({ node, enum: enumOptions, resolver }) {
939
955
  isExportable: true,
940
956
  isIndexable: true,
941
957
  isTypeOnly: false,
942
- children: _kubb_parser_ts.parserTs.print(nameNode)
958
+ children: (0, _kubb_parser_ts.parserTs)().print(nameNode)
943
959
  }), /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
944
960
  name: typeName,
945
961
  isIndexable: !namesMerge,
946
962
  isExportable: !namesMerge && ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumOptions.type),
947
963
  isTypeOnly: ENUM_TYPES_WITH_TYPE_ONLY.has(enumOptions.type),
948
- children: _kubb_parser_ts.parserTs.print(typeNode)
964
+ children: (0, _kubb_parser_ts.parserTs)().print(typeNode)
949
965
  })] });
950
966
  }
951
967
  //#endregion
@@ -1046,6 +1062,24 @@ function getOperationParameters(node, options = {}) {
1046
1062
  };
1047
1063
  }
1048
1064
  //#endregion
1065
+ //#region ../../internals/shared/src/adapter.ts
1066
+ /**
1067
+ * Narrows the generic `Adapter` from a generator context to the OpenAPI adapter,
1068
+ * so OAS-only options (`dateType`, `nameMapping`) and the parsed `document` are typed.
1069
+ *
1070
+ * Throws when a non-OAS adapter is configured, turning a silently wrong cast into a
1071
+ * clear, actionable error at the point of use.
1072
+ *
1073
+ * @example
1074
+ * ```ts
1075
+ * const { dateType } = getOasAdapter(ctx.adapter).options
1076
+ * ```
1077
+ */
1078
+ function getOasAdapter(adapter) {
1079
+ if (adapter.name !== "oas") throw new Error(`Expected the OpenAPI adapter (adapterOas), but received "${adapter.name}". Configure \`adapter: adapterOas()\` in your Kubb config.`);
1080
+ return adapter;
1081
+ }
1082
+ //#endregion
1049
1083
  //#region ../../internals/shared/src/group.ts
1050
1084
  /**
1051
1085
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -1113,7 +1147,7 @@ function buildPropertyJSDocComments(schema, optional) {
1113
1147
  !isArray && meta && "min" in meta && meta.min !== void 0 ? `@minLength ${meta.min}` : null,
1114
1148
  !isArray && meta && "max" in meta && meta.max !== void 0 ? `@maxLength ${meta.max}` : null,
1115
1149
  meta && "pattern" in meta && meta.pattern ? `@pattern ${meta.pattern}` : null,
1116
- meta && "default" in meta && meta.default !== void 0 ? `@default ${"primitive" in meta && meta.primitive === "string" ? stringify(meta.default) : meta.default}` : null,
1150
+ 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,
1117
1151
  ...exampleValues.map((example) => `@example ${example}`),
1118
1152
  meta && "primitive" in meta && meta.primitive ? [`@type ${meta.primitive}`, optional ?? isSchemaOptional(schema) ? " | undefined" : null].filter(Boolean).join("") : null
1119
1153
  ].filter(Boolean);
@@ -1424,7 +1458,7 @@ const printerTs = kubb_kit.ast.createPrinter((options) => {
1424
1458
  if (!name) {
1425
1459
  const withNullable = meta.nullable ? createUnionDeclaration({ nodes: [transformed, keywordTypeNodes.null] }) : transformed;
1426
1460
  const result = (meta.nullish || meta.optional) && addsUndefined ? createUnionDeclaration({ nodes: [withNullable, keywordTypeNodes.undefined] }) : withNullable;
1427
- return _kubb_parser_ts.parserTs.print(result);
1461
+ return (0, _kubb_parser_ts.parserTs)().print(result);
1428
1462
  }
1429
1463
  const inner = (() => {
1430
1464
  const omitted = keysToOmit?.length ? createOmitDeclaration({
@@ -1445,13 +1479,22 @@ const printerTs = kubb_kit.ast.createPrinter((options) => {
1445
1479
  description
1446
1480
  })
1447
1481
  });
1448
- return _kubb_parser_ts.parserTs.print(typeNode);
1482
+ return (0, _kubb_parser_ts.parserTs)().print(typeNode);
1449
1483
  }
1450
1484
  };
1451
1485
  });
1452
1486
  //#endregion
1453
1487
  //#region src/generators/typeGenerator.tsx
1454
1488
  /**
1489
+ * Resolves the imported type name for a referenced schema. An enum schema emitted
1490
+ * as a `const` object imports its suffixed key alias (e.g. `StatusKey`); every other
1491
+ * schema imports its plain resolved name.
1492
+ */
1493
+ function resolveImportName({ schemaName, enumOptions, enumSchemaNames, resolver }) {
1494
+ if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.enum.keyName({ name: schemaName }, enumOptions.typeSuffix);
1495
+ return resolver.name(schemaName);
1496
+ }
1497
+ /**
1455
1498
  * Built-in generator for `@kubb/plugin-ts`. Emits one TypeScript file per
1456
1499
  * schema in the spec plus per-operation request, response, and parameter
1457
1500
  * types. Drop-replace with a custom `Generator<PluginTs>` to change how
@@ -1465,12 +1508,13 @@ const typeGenerator = (0, kubb_kit.defineGenerator)({
1465
1508
  const { adapter, config, resolver, root } = ctx;
1466
1509
  if (!node.name) return;
1467
1510
  const enumSchemaNames = new Set(ctx.meta.enumNames);
1468
- function resolveImportName(schemaName) {
1469
- if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.enum.keyName({ name: schemaName }, enumOptions.typeSuffix);
1470
- return resolver.name(schemaName);
1471
- }
1472
1511
  const imports = adapter.getImports(node, (schemaName) => ({
1473
- name: resolveImportName(schemaName),
1512
+ name: resolveImportName({
1513
+ schemaName,
1514
+ enumOptions,
1515
+ enumSchemaNames,
1516
+ resolver
1517
+ }),
1474
1518
  path: resolver.file({
1475
1519
  name: schemaName,
1476
1520
  extname: ".ts",
@@ -1500,7 +1544,7 @@ const typeGenerator = (0, kubb_kit.defineGenerator)({
1500
1544
  description: node.description,
1501
1545
  resolver,
1502
1546
  enumSchemaNames,
1503
- nameMapping: adapter.options.nameMapping,
1547
+ nameMapping: getOasAdapter(adapter).options.nameMapping,
1504
1548
  nodes: printer?.nodes
1505
1549
  });
1506
1550
  return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
@@ -1555,14 +1599,15 @@ const typeGenerator = (0, kubb_kit.defineGenerator)({
1555
1599
  group: group ?? void 0
1556
1600
  }) };
1557
1601
  const enumSchemaNames = new Set(ctx.meta.enumNames);
1558
- function resolveImportName(schemaName) {
1559
- if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumOptions.type) && enumOptions.typeSuffix && enumSchemaNames.has(schemaName)) return resolver.enum.keyName({ name: schemaName }, enumOptions.typeSuffix);
1560
- return resolver.name(schemaName);
1561
- }
1562
1602
  function renderSchemaType({ schema, name, keysToOmit }) {
1563
1603
  if (!schema) return null;
1564
1604
  const imports = adapter.getImports(schema, (schemaName) => ({
1565
- name: resolveImportName(schemaName),
1605
+ name: resolveImportName({
1606
+ schemaName,
1607
+ enumOptions,
1608
+ enumSchemaNames,
1609
+ resolver
1610
+ }),
1566
1611
  path: resolver.file({
1567
1612
  name: schemaName,
1568
1613
  extname: ".ts",
@@ -1581,7 +1626,7 @@ const typeGenerator = (0, kubb_kit.defineGenerator)({
1581
1626
  keysToOmit,
1582
1627
  resolver,
1583
1628
  enumSchemaNames,
1584
- nameMapping: adapter.options.nameMapping,
1629
+ nameMapping: getOasAdapter(adapter).options.nameMapping,
1585
1630
  nodes: printer?.nodes
1586
1631
  });
1587
1632
  return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [imports.map((imp) => /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
@@ -1691,7 +1736,12 @@ const typeGenerator = (0, kubb_kit.defineGenerator)({
1691
1736
  const responseName = resolver.response.response(node);
1692
1737
  const responsesWithSchema = node.responses.filter(hasSchema);
1693
1738
  if (new Set(responsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
1694
- name: resolveImportName(schemaName),
1739
+ name: resolveImportName({
1740
+ schemaName,
1741
+ enumOptions,
1742
+ enumSchemaNames,
1743
+ resolver
1744
+ }),
1695
1745
  path: ""
1696
1746
  })).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseName)) return null;
1697
1747
  return renderSchemaType({
@@ -1817,7 +1867,7 @@ const pluginTsName = "plugin-ts";
1817
1867
  * import { pluginTs } from '@kubb/plugin-ts'
1818
1868
  *
1819
1869
  * export default defineConfig({
1820
- * input: { path: './petStore.yaml' },
1870
+ * input: './petStore.yaml',
1821
1871
  * output: { path: './src/gen' },
1822
1872
  * plugins: [
1823
1873
  * pluginTs({
@@ -2054,14 +2104,14 @@ function renderGroupType(type, sorted, transformType) {
2054
2104
  }
2055
2105
  function printParameter(node, options) {
2056
2106
  const { mode, transformName, transformType } = options;
2057
- const isGroup = typeof node.name !== "string";
2107
+ const bindingName = node.name;
2058
2108
  if (mode === "call") {
2059
- if (isGroup) return `{ ${sortedGroupMembers(node.name, node.type).map((member) => renderBindingMember(member)).join(", ")} }`;
2060
- const name = transformName ? transformName(node.name) : node.name;
2109
+ if (typeof bindingName !== "string") return `{ ${sortedGroupMembers(bindingName, node.type).map((member) => renderBindingMember(member)).join(", ")} }`;
2110
+ const name = transformName ? transformName(bindingName) : bindingName;
2061
2111
  return node.rest ? `...${name}` : name;
2062
2112
  }
2063
- if (isGroup) {
2064
- const sorted = sortedGroupMembers(node.name, node.type);
2113
+ if (typeof bindingName !== "string") {
2114
+ const sorted = sortedGroupMembers(bindingName, node.type);
2065
2115
  const binding = `{ ${sorted.map((member) => renderBindingMember(member, transformName)).join(", ")} }`;
2066
2116
  const allOptional = sorted.every((member) => member.optional);
2067
2117
  const type = renderGroupType(node.type, sorted, transformType);
@@ -2071,7 +2121,7 @@ function printParameter(node, options) {
2071
2121
  }
2072
2122
  return node.default ? `${binding} = ${node.default}` : binding;
2073
2123
  }
2074
- const name = transformName ? transformName(node.name) : node.name;
2124
+ const name = transformName ? transformName(bindingName) : bindingName;
2075
2125
  const type = node.type ? renderType(node.type, transformType) : void 0;
2076
2126
  if (node.rest) return type ? `...${name}: ${type}` : `...${name}`;
2077
2127
  if (type) {