@kubb/plugin-ts 5.0.0-beta.15 → 5.0.0-beta.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-ts",
3
- "version": "5.0.0-beta.15",
3
+ "version": "5.0.0-beta.22",
4
4
  "description": "Generate TypeScript types, interfaces, and enums from your OpenAPI specification. The foundational plugin that powers type safety across the entire Kubb ecosystem.",
5
5
  "keywords": [
6
6
  "code-generation",
@@ -46,9 +46,9 @@
46
46
  "registry": "https://registry.npmjs.org/"
47
47
  },
48
48
  "dependencies": {
49
- "@kubb/core": "5.0.0-beta.19",
50
- "@kubb/parser-ts": "5.0.0-beta.19",
51
- "@kubb/renderer-jsx": "5.0.0-beta.19",
49
+ "@kubb/core": "5.0.0-beta.22",
50
+ "@kubb/parser-ts": "5.0.0-beta.22",
51
+ "@kubb/renderer-jsx": "5.0.0-beta.22",
52
52
  "remeda": "^2.34.1",
53
53
  "typescript": "^6.0.3"
54
54
  },
@@ -57,7 +57,7 @@
57
57
  "@internals/utils": "0.0.0"
58
58
  },
59
59
  "peerDependencies": {
60
- "@kubb/renderer-jsx": "5.0.0-beta.19"
60
+ "@kubb/renderer-jsx": "5.0.0-beta.22"
61
61
  },
62
62
  "size-limit": [
63
63
  {
package/src/factory.ts CHANGED
@@ -372,13 +372,8 @@ export function createImportDeclaration({
372
372
  isNameSpace?: boolean
373
373
  }) {
374
374
  if (!Array.isArray(name)) {
375
- let importPropertyName: ts.Identifier | undefined = factory.createIdentifier(name)
376
- let importName: ts.NamedImportBindings | undefined
377
-
378
- if (isNameSpace) {
379
- importPropertyName = undefined
380
- importName = factory.createNamespaceImport(factory.createIdentifier(name))
381
- }
375
+ const importPropertyName = isNameSpace ? undefined : factory.createIdentifier(name)
376
+ const importName = isNameSpace ? factory.createNamespaceImport(factory.createIdentifier(name)) : undefined
382
377
 
383
378
  return factory.createImportDeclaration(
384
379
  undefined,
@@ -29,7 +29,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
29
29
  renderer: jsxRendererSync,
30
30
  schema(node, ctx) {
31
31
  const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, printer } = ctx.options
32
- const { adapter, config, resolver, root, inputNode } = ctx
32
+ const { adapter, config, resolver, root } = ctx
33
33
 
34
34
  if (!node.name) {
35
35
  return
@@ -37,7 +37,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
37
37
  const mode = ctx.getMode(output)
38
38
  // Build a set of schema names that are enums so the ref handler and getImports
39
39
  // callback can use the suffixed type name (e.g. `StatusKey`) for those refs.
40
- const enumSchemaNames = new Set(inputNode.schemas.filter((s) => ast.narrowSchema(s, ast.schemaTypes.enum) && s.name).map((s) => s.name!))
40
+ const enumSchemaNames = new Set<string>(ctx.meta.enumNames)
41
41
 
42
42
  function resolveImportName(schemaName: string): string {
43
43
  if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) {
@@ -76,8 +76,8 @@ export const typeGenerator = defineGenerator<PluginTs>({
76
76
  baseName={meta.file.baseName}
77
77
  path={meta.file.path}
78
78
  meta={meta.file.meta}
79
- banner={resolver.resolveBanner(inputNode, { output, config })}
80
- footer={resolver.resolveFooter(inputNode, { output, config })}
79
+ banner={resolver.resolveBanner(ctx.meta, { output, config })}
80
+ footer={resolver.resolveFooter(ctx.meta, { output, config })}
81
81
  >
82
82
  {mode === 'split' &&
83
83
  imports.map((imp) => (
@@ -97,7 +97,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
97
97
  },
98
98
  operation(node, ctx) {
99
99
  const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, printer } = ctx.options
100
- const { adapter, config, resolver, root, inputNode } = ctx
100
+ const { adapter, config, resolver, root } = ctx
101
101
 
102
102
  const mode = ctx.getMode(output)
103
103
 
@@ -109,7 +109,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
109
109
 
110
110
  // Build a set of schema names that are enums so the ref handler and getImports
111
111
  // callback can use the suffixed type name (e.g. `StatusKey`) for those refs.
112
- const enumSchemaNames = new Set(inputNode.schemas.filter((s) => ast.narrowSchema(s, ast.schemaTypes.enum) && s.name).map((s) => s.name!))
112
+ const enumSchemaNames = new Set<string>(ctx.meta.enumNames)
113
113
 
114
114
  function resolveImportName(schemaName: string): string {
115
115
  if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) {
@@ -118,7 +118,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
118
118
  return resolver.resolveTypeName(schemaName)
119
119
  }
120
120
 
121
- function renderSchemaType({ schema, name, keysToOmit }: { schema: ast.SchemaNode | null; name: string; keysToOmit?: Array<string> }) {
121
+ function renderSchemaType({ schema, name, keysToOmit }: { schema: ast.SchemaNode | null; name: string; keysToOmit?: Array<string> | null }) {
122
122
  if (!schema) return null
123
123
 
124
124
  const imports = adapter.getImports(schema, (schemaName) => ({
@@ -281,8 +281,8 @@ export const typeGenerator = defineGenerator<PluginTs>({
281
281
  baseName={meta.file.baseName}
282
282
  path={meta.file.path}
283
283
  meta={meta.file.meta}
284
- banner={resolver.resolveBanner(inputNode, { output, config })}
285
- footer={resolver.resolveFooter(inputNode, { output, config })}
284
+ banner={resolver.resolveBanner(ctx.meta, { output, config })}
285
+ footer={resolver.resolveFooter(ctx.meta, { output, config })}
286
286
  >
287
287
  {paramTypes}
288
288
  {responseTypes}
@@ -89,7 +89,7 @@ export type PrinterTsOptions = {
89
89
  * Properties to exclude using `Omit<Type, Keys>`.
90
90
  * Forces type alias syntax regardless of `syntaxType` setting.
91
91
  */
92
- keysToOmit?: Array<string>
92
+ keysToOmit?: Array<string> | null
93
93
  /**
94
94
  * Transforms raw schema names into valid TypeScript identifiers.
95
95
  */
@@ -167,7 +167,7 @@ export const printerTs = ast.definePrinter<PrinterTs>((options) => {
167
167
  time: factory.dateOrStringNode,
168
168
  ref(node) {
169
169
  if (!node.name) {
170
- return undefined
170
+ return null
171
171
  }
172
172
  // Parser-generated refs (with $ref) carry raw schema names that need resolving.
173
173
  // Use the canonical name from the $ref path — node.name may have been overridden
@@ -236,15 +236,15 @@ export const printerTs = ast.definePrinter<PrinterTs>((options) => {
236
236
  return factory.createUnionDeclaration({ withParentheses: true, nodes: factory.buildMemberNodes(members, this.transform) }) ?? undefined
237
237
  },
238
238
  intersection(node) {
239
- return factory.createIntersectionDeclaration({ withParentheses: true, nodes: factory.buildMemberNodes(node.members, this.transform) }) ?? undefined
239
+ return factory.createIntersectionDeclaration({ withParentheses: true, nodes: factory.buildMemberNodes(node.members, this.transform) }) ?? null
240
240
  },
241
241
  array(node) {
242
242
  const itemNodes = (node.items ?? []).map((item) => this.transform(item)).filter(isNonNullable)
243
243
 
244
- return factory.createArrayDeclaration({ nodes: itemNodes, arrayType: this.options.arrayType }) ?? undefined
244
+ return factory.createArrayDeclaration({ nodes: itemNodes, arrayType: this.options.arrayType }) ?? null
245
245
  },
246
246
  tuple(node) {
247
- return factory.buildTupleNode(node, this.transform)
247
+ return factory.buildTupleNode(node, this.transform) ?? null
248
248
  },
249
249
  object(node) {
250
250
  const { transform, options } = this
@@ -279,36 +279,33 @@ export const printerTs = ast.definePrinter<PrinterTs>((options) => {
279
279
  print(node) {
280
280
  const { name, syntaxType = 'type', description, keysToOmit } = this.options
281
281
 
282
- let base = this.transform(node)
283
- if (!base) return null
282
+ const transformed = this.transform(node)
283
+ if (!transformed) return null
284
284
 
285
285
  // For ref nodes, structural metadata lives on node.schema rather than the ref node itself.
286
286
  const meta = ast.syncSchemaRef(node)
287
287
 
288
288
  // Without name, apply modifiers inline and return.
289
289
  if (!name) {
290
- if (meta.nullable) {
291
- base = factory.createUnionDeclaration({ nodes: [base, factory.keywordTypeNodes.null] })
292
- }
293
- if ((meta.nullish || meta.optional) && addsUndefined) {
294
- base = factory.createUnionDeclaration({ nodes: [base, factory.keywordTypeNodes.undefined] })
295
- }
296
- return safePrint(base)
290
+ const withNullable = meta.nullable ? factory.createUnionDeclaration({ nodes: [transformed, factory.keywordTypeNodes.null] }) : transformed
291
+ const result =
292
+ (meta.nullish || meta.optional) && addsUndefined
293
+ ? factory.createUnionDeclaration({ nodes: [withNullable, factory.keywordTypeNodes.undefined] })
294
+ : withNullable
295
+ return safePrint(result)
297
296
  }
298
297
 
299
298
  // When keysToOmit is present, wrap with Omit first, then apply nullable/optional
300
299
  // modifiers so they are not swallowed by NonNullable inside createOmitDeclaration.
301
- let inner: ts.TypeNode = keysToOmit?.length ? factory.createOmitDeclaration({ keys: keysToOmit, type: base, nonNullable: true }) : base
302
-
303
- if (meta.nullable) {
304
- inner = factory.createUnionDeclaration({ nodes: [inner, factory.keywordTypeNodes.null] })
305
- }
306
-
307
- // For named type declarations (type aliases), optional/nullish always produces | undefined
308
- // regardless of optionalType the questionToken ? modifier only applies to object properties.
309
- if (meta.nullish || meta.optional) {
310
- inner = factory.createUnionDeclaration({ nodes: [inner, factory.keywordTypeNodes.undefined] })
311
- }
300
+ const inner = (() => {
301
+ const omitted: ts.TypeNode = keysToOmit?.length
302
+ ? factory.createOmitDeclaration({ keys: keysToOmit, type: transformed, nonNullable: true })
303
+ : transformed
304
+ const withNullable = meta.nullable ? factory.createUnionDeclaration({ nodes: [omitted, factory.keywordTypeNodes.null] }) : omitted
305
+ // For named type declarations (type aliases), optional/nullish always produces | undefined
306
+ // regardless of optionalType the questionToken ? modifier only applies to object properties.
307
+ return meta.nullish || meta.optional ? factory.createUnionDeclaration({ nodes: [withNullable, factory.keywordTypeNodes.undefined] }) : withNullable
308
+ })()
312
309
 
313
310
  const useTypeGeneration = syntaxType === 'type' || inner.kind === factory.syntaxKind.union || !!keysToOmit?.length
314
311