@kubb/plugin-ts 5.0.0-alpha.34 → 5.0.0-alpha.35
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 +111 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +20 -23
- package/dist/index.js +111 -176
- package/dist/index.js.map +1 -1
- package/package.json +5 -6
- package/src/components/Enum.tsx +3 -3
- package/src/components/Type.tsx +6 -8
- package/src/factory.ts +10 -8
- package/src/generators/typeGenerator.tsx +16 -17
- package/src/generators/typeGeneratorLegacy.tsx +48 -49
- package/src/plugin.ts +47 -81
- package/src/printers/functionPrinter.ts +13 -13
- package/src/printers/printerTs.ts +7 -8
- package/src/types.ts +11 -12
- package/src/utils.ts +30 -31
- package/src/presets.ts +0 -28
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/plugin-ts",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.35",
|
|
4
4
|
"description": "TypeScript code generation plugin for Kubb, transforming OpenAPI schemas into TypeScript interfaces, types, and utility functions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -51,13 +51,12 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"remeda": "^2.33.7",
|
|
53
53
|
"typescript": "5.9.3",
|
|
54
|
-
"@kubb/
|
|
55
|
-
"@kubb/
|
|
56
|
-
"@kubb/
|
|
57
|
-
"@kubb/renderer-jsx": "5.0.0-alpha.34"
|
|
54
|
+
"@kubb/core": "5.0.0-alpha.35",
|
|
55
|
+
"@kubb/parser-ts": "5.0.0-alpha.35",
|
|
56
|
+
"@kubb/renderer-jsx": "5.0.0-alpha.35"
|
|
58
57
|
},
|
|
59
58
|
"peerDependencies": {
|
|
60
|
-
"@kubb/renderer-jsx": "5.0.0-alpha.
|
|
59
|
+
"@kubb/renderer-jsx": "5.0.0-alpha.35"
|
|
61
60
|
},
|
|
62
61
|
"engines": {
|
|
63
62
|
"node": ">=22"
|
package/src/components/Enum.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { camelCase, trimQuotes } from '@internals/utils'
|
|
2
|
-
import type {
|
|
2
|
+
import type { ast } from '@kubb/core'
|
|
3
3
|
import { safePrint } from '@kubb/parser-ts'
|
|
4
4
|
import { File } from '@kubb/renderer-jsx'
|
|
5
5
|
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
@@ -8,7 +8,7 @@ import * as factory from '../factory.ts'
|
|
|
8
8
|
import type { PluginTs, ResolverTs } from '../types.ts'
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
|
-
node: EnumSchemaNode
|
|
11
|
+
node: ast.EnumSchemaNode
|
|
12
12
|
enumType: PluginTs['resolvedOptions']['enumType']
|
|
13
13
|
enumTypeSuffix: PluginTs['resolvedOptions']['enumTypeSuffix']
|
|
14
14
|
enumKeyCasing: PluginTs['resolvedOptions']['enumKeyCasing']
|
|
@@ -28,7 +28,7 @@ export function getEnumNames({
|
|
|
28
28
|
enumTypeSuffix,
|
|
29
29
|
resolver,
|
|
30
30
|
}: {
|
|
31
|
-
node: EnumSchemaNode
|
|
31
|
+
node: ast.EnumSchemaNode
|
|
32
32
|
enumType: PluginTs['resolvedOptions']['enumType']
|
|
33
33
|
enumTypeSuffix: PluginTs['resolvedOptions']['enumTypeSuffix']
|
|
34
34
|
resolver: ResolverTs
|
package/src/components/Type.tsx
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { collect, narrowSchema, schemaTypes } from '@kubb/ast'
|
|
3
|
-
import type { EnumSchemaNode, SchemaNode } from '@kubb/ast/types'
|
|
1
|
+
import { ast } from '@kubb/core'
|
|
4
2
|
import { File } from '@kubb/renderer-jsx'
|
|
5
3
|
import type { KubbReactNode } from '@kubb/renderer-jsx/types'
|
|
6
4
|
import type { PrinterTsFactory } from '../printers/printerTs.ts'
|
|
@@ -9,12 +7,12 @@ import { Enum, getEnumNames } from './Enum.tsx'
|
|
|
9
7
|
|
|
10
8
|
type Props = {
|
|
11
9
|
name: string
|
|
12
|
-
node: SchemaNode
|
|
10
|
+
node: ast.SchemaNode
|
|
13
11
|
/**
|
|
14
12
|
* Pre-configured printer instance created by the generator.
|
|
15
13
|
* Created with `printerTs({ ..., nodes: options.printer?.nodes })`.
|
|
16
14
|
*/
|
|
17
|
-
printer: Printer<PrinterTsFactory>
|
|
15
|
+
printer: ast.Printer<PrinterTsFactory>
|
|
18
16
|
enumType: PluginTs['resolvedOptions']['enumType']
|
|
19
17
|
enumTypeSuffix: PluginTs['resolvedOptions']['enumTypeSuffix']
|
|
20
18
|
enumKeyCasing: PluginTs['resolvedOptions']['enumKeyCasing']
|
|
@@ -22,9 +20,9 @@ type Props = {
|
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
export function Type({ name, node, printer, enumType, enumTypeSuffix, enumKeyCasing, resolver }: Props): KubbReactNode {
|
|
25
|
-
const enumSchemaNodes = collect<EnumSchemaNode>(node, {
|
|
26
|
-
schema(n): EnumSchemaNode | undefined {
|
|
27
|
-
const enumNode = narrowSchema(n, schemaTypes.enum)
|
|
23
|
+
const enumSchemaNodes = ast.collect<ast.EnumSchemaNode>(node, {
|
|
24
|
+
schema(n): ast.EnumSchemaNode | undefined {
|
|
25
|
+
const enumNode = ast.narrowSchema(n, ast.schemaTypes.enum)
|
|
28
26
|
if (enumNode?.name) return enumNode
|
|
29
27
|
},
|
|
30
28
|
})
|
package/src/factory.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { camelCase, pascalCase, screamingSnakeCase, snakeCase } from '@internals/utils'
|
|
2
|
-
import {
|
|
3
|
-
import type { ArraySchemaNode, SchemaNode } from '@kubb/ast/types'
|
|
2
|
+
import { ast } from '@kubb/core'
|
|
4
3
|
import { isNumber, sortBy } from 'remeda'
|
|
5
4
|
import ts from 'typescript'
|
|
6
5
|
import { OPTIONAL_ADDS_UNDEFINED } from './constants.ts'
|
|
@@ -725,7 +724,10 @@ export function dateOrStringNode(node: { representation?: string }): ts.TypeNode
|
|
|
725
724
|
/**
|
|
726
725
|
* Maps an array of `SchemaNode`s through the printer, filtering out `null` and `undefined` results.
|
|
727
726
|
*/
|
|
728
|
-
export function buildMemberNodes(
|
|
727
|
+
export function buildMemberNodes(
|
|
728
|
+
members: Array<ast.SchemaNode> | undefined,
|
|
729
|
+
print: (node: ast.SchemaNode) => ts.TypeNode | null | undefined,
|
|
730
|
+
): Array<ts.TypeNode> {
|
|
729
731
|
return (members ?? []).map(print).filter(Boolean)
|
|
730
732
|
}
|
|
731
733
|
|
|
@@ -733,7 +735,7 @@ export function buildMemberNodes(members: Array<SchemaNode> | undefined, print:
|
|
|
733
735
|
* Builds a TypeScript tuple type node from an array schema's `items`,
|
|
734
736
|
* applying min/max slice and optional/rest element rules.
|
|
735
737
|
*/
|
|
736
|
-
export function buildTupleNode(node: ArraySchemaNode, print: (node: SchemaNode) => ts.TypeNode | null | undefined): ts.TypeNode | undefined {
|
|
738
|
+
export function buildTupleNode(node: ast.ArraySchemaNode, print: (node: ast.SchemaNode) => ts.TypeNode | null | undefined): ts.TypeNode | undefined {
|
|
737
739
|
let items = (node.items ?? []).map(print).filter(Boolean)
|
|
738
740
|
|
|
739
741
|
const restNode = node.rest ? (print(node.rest) ?? undefined) : undefined
|
|
@@ -761,12 +763,12 @@ export function buildTupleNode(node: ArraySchemaNode, print: (node: SchemaNode)
|
|
|
761
763
|
* Applies `nullable` and optional/nullish `| undefined` union modifiers to a property's resolved base type.
|
|
762
764
|
*/
|
|
763
765
|
export function buildPropertyType(
|
|
764
|
-
schema: SchemaNode,
|
|
766
|
+
schema: ast.SchemaNode,
|
|
765
767
|
baseType: ts.TypeNode,
|
|
766
768
|
optionalType: 'questionToken' | 'undefined' | 'questionTokenAndUndefined',
|
|
767
769
|
): ts.TypeNode {
|
|
768
770
|
const addsUndefined = OPTIONAL_ADDS_UNDEFINED.has(optionalType)
|
|
769
|
-
const meta = syncSchemaRef(schema)
|
|
771
|
+
const meta = ast.syncSchemaRef(schema)
|
|
770
772
|
|
|
771
773
|
let type = baseType
|
|
772
774
|
|
|
@@ -785,9 +787,9 @@ export function buildPropertyType(
|
|
|
785
787
|
* Creates TypeScript index signatures for `additionalProperties` and `patternProperties` on an object schema node.
|
|
786
788
|
*/
|
|
787
789
|
export function buildIndexSignatures(
|
|
788
|
-
node: { additionalProperties?: SchemaNode | boolean; patternProperties?: Record<string, SchemaNode> },
|
|
790
|
+
node: { additionalProperties?: ast.SchemaNode | boolean; patternProperties?: Record<string, ast.SchemaNode> },
|
|
789
791
|
propertyCount: number,
|
|
790
|
-
print: (node: SchemaNode) => ts.TypeNode | null | undefined,
|
|
792
|
+
print: (node: ast.SchemaNode) => ts.TypeNode | null | undefined,
|
|
791
793
|
): Array<ts.TypeElement> {
|
|
792
794
|
const elements: Array<ts.TypeElement> = []
|
|
793
795
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { defineGenerator } from '@kubb/core'
|
|
4
|
-
import { File } from '@kubb/renderer-jsx'
|
|
1
|
+
import { ast, defineGenerator } from '@kubb/core'
|
|
2
|
+
import { File, jsxRenderer } from '@kubb/renderer-jsx'
|
|
5
3
|
import { Type } from '../components/Type.tsx'
|
|
6
4
|
import { ENUM_TYPES_WITH_KEY_SUFFIX } from '../constants.ts'
|
|
7
5
|
import { printerTs } from '../printers/printerTs.ts'
|
|
@@ -10,17 +8,18 @@ import { buildData, buildResponses, buildResponseUnion } from '../utils.ts'
|
|
|
10
8
|
|
|
11
9
|
export const typeGenerator = defineGenerator<PluginTs>({
|
|
12
10
|
name: 'typescript',
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const {
|
|
11
|
+
renderer: jsxRenderer,
|
|
12
|
+
schema(node, ctx) {
|
|
13
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group, printer } = ctx.options
|
|
14
|
+
const { adapter, config, resolver, root } = ctx
|
|
16
15
|
|
|
17
16
|
if (!node.name) {
|
|
18
17
|
return
|
|
19
18
|
}
|
|
20
|
-
const mode =
|
|
19
|
+
const mode = ctx.getMode(output)
|
|
21
20
|
// Build a set of schema names that are enums so the ref handler and getImports
|
|
22
21
|
// callback can use the suffixed type name (e.g. `StatusKey`) for those refs.
|
|
23
|
-
const enumSchemaNames = new Set((adapter.inputNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name!))
|
|
22
|
+
const enumSchemaNames = new Set((adapter.inputNode?.schemas ?? []).filter((s) => ast.narrowSchema(s, ast.schemaTypes.enum) && s.name).map((s) => s.name!))
|
|
24
23
|
|
|
25
24
|
function resolveImportName(schemaName: string): string {
|
|
26
25
|
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) {
|
|
@@ -34,7 +33,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
|
|
|
34
33
|
path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
|
|
35
34
|
}))
|
|
36
35
|
|
|
37
|
-
const isEnumSchema = !!narrowSchema(node, schemaTypes.enum)
|
|
36
|
+
const isEnumSchema = !!ast.narrowSchema(node, ast.schemaTypes.enum)
|
|
38
37
|
|
|
39
38
|
const meta = {
|
|
40
39
|
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveTypeName(node.name),
|
|
@@ -78,13 +77,13 @@ export const typeGenerator = defineGenerator<PluginTs>({
|
|
|
78
77
|
</File>
|
|
79
78
|
)
|
|
80
79
|
},
|
|
81
|
-
operation(node,
|
|
82
|
-
const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, printer } = options
|
|
83
|
-
const { adapter, config, resolver, root } =
|
|
80
|
+
operation(node, ctx) {
|
|
81
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output, printer } = ctx.options
|
|
82
|
+
const { adapter, config, resolver, root } = ctx
|
|
84
83
|
|
|
85
|
-
const mode =
|
|
84
|
+
const mode = ctx.getMode(output)
|
|
86
85
|
|
|
87
|
-
const params = caseParams(node.parameters, paramsCasing)
|
|
86
|
+
const params = ast.caseParams(node.parameters, paramsCasing)
|
|
88
87
|
|
|
89
88
|
const meta = {
|
|
90
89
|
file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
|
|
@@ -92,7 +91,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
|
|
|
92
91
|
|
|
93
92
|
// Build a set of schema names that are enums so the ref handler and getImports
|
|
94
93
|
// callback can use the suffixed type name (e.g. `StatusKey`) for those refs.
|
|
95
|
-
const enumSchemaNames = new Set((adapter.inputNode?.schemas ?? []).filter((s) => narrowSchema(s, schemaTypes.enum) && s.name).map((s) => s.name!))
|
|
94
|
+
const enumSchemaNames = new Set((adapter.inputNode?.schemas ?? []).filter((s) => ast.narrowSchema(s, ast.schemaTypes.enum) && s.name).map((s) => s.name!))
|
|
96
95
|
|
|
97
96
|
function resolveImportName(schemaName: string): string {
|
|
98
97
|
if (ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && enumTypeSuffix && enumSchemaNames.has(schemaName)) {
|
|
@@ -101,7 +100,7 @@ export const typeGenerator = defineGenerator<PluginTs>({
|
|
|
101
100
|
return resolver.resolveTypeName(schemaName)
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
function renderSchemaType({ schema, name, keysToOmit }: { schema: SchemaNode | null; name: string; keysToOmit?: Array<string> }) {
|
|
103
|
+
function renderSchemaType({ schema, name, keysToOmit }: { schema: ast.SchemaNode | null; name: string; keysToOmit?: Array<string> }) {
|
|
105
104
|
if (!schema) return null
|
|
106
105
|
|
|
107
106
|
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { pascalCase } from '@internals/utils'
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import { defineGenerator } from '@kubb/core'
|
|
5
|
-
import { File } from '@kubb/renderer-jsx'
|
|
2
|
+
import { ast, defineGenerator } from '@kubb/core'
|
|
3
|
+
import { File, jsxRenderer } from '@kubb/renderer-jsx'
|
|
6
4
|
import { Type } from '../components/Type.tsx'
|
|
7
5
|
import { ENUM_TYPES_WITH_KEY_SUFFIX } from '../constants.ts'
|
|
8
6
|
import { printerTs } from '../printers/printerTs.ts'
|
|
@@ -10,19 +8,19 @@ import { resolverTsLegacy } from '../resolvers/resolverTsLegacy.ts'
|
|
|
10
8
|
import type { PluginTs, ResolverTs } from '../types'
|
|
11
9
|
|
|
12
10
|
type BuildGroupedParamsSchemaOptions = {
|
|
13
|
-
params: Array<ParameterNode>
|
|
11
|
+
params: Array<ast.ParameterNode>
|
|
14
12
|
parentName?: string
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
function buildGroupedParamsSchema({ params, parentName }: BuildGroupedParamsSchemaOptions): SchemaNode {
|
|
18
|
-
return createSchema({
|
|
15
|
+
function buildGroupedParamsSchema({ params, parentName }: BuildGroupedParamsSchemaOptions): ast.SchemaNode {
|
|
16
|
+
return ast.createSchema({
|
|
19
17
|
type: 'object',
|
|
20
18
|
properties: params.map((param) => {
|
|
21
19
|
let schema = param.schema
|
|
22
|
-
if (narrowSchema(schema, 'enum') && !schema.name && parentName) {
|
|
20
|
+
if (ast.narrowSchema(schema, 'enum') && !schema.name && parentName) {
|
|
23
21
|
schema = { ...schema, name: pascalCase([parentName, param.name, 'enum'].join(' ')) }
|
|
24
22
|
}
|
|
25
|
-
return createProperty({
|
|
23
|
+
return ast.createProperty({
|
|
26
24
|
name: param.name,
|
|
27
25
|
required: param.required,
|
|
28
26
|
schema,
|
|
@@ -35,7 +33,7 @@ type BuildOperationSchemaOptions = {
|
|
|
35
33
|
resolver: ResolverTs
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
function buildLegacyResponsesSchemaNode(node: OperationNode, { resolver }: BuildOperationSchemaOptions): SchemaNode | null {
|
|
36
|
+
function buildLegacyResponsesSchemaNode(node: ast.OperationNode, { resolver }: BuildOperationSchemaOptions): ast.SchemaNode | null {
|
|
39
37
|
const isGet = node.method.toLowerCase() === 'get'
|
|
40
38
|
const successResponses = node.responses.filter((res) => {
|
|
41
39
|
const code = Number(res.statusCode)
|
|
@@ -46,31 +44,31 @@ function buildLegacyResponsesSchemaNode(node: OperationNode, { resolver }: Build
|
|
|
46
44
|
const responseSchema =
|
|
47
45
|
successResponses.length > 0
|
|
48
46
|
? successResponses.length === 1
|
|
49
|
-
? createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, successResponses[0]!.statusCode) })
|
|
50
|
-
: createSchema({
|
|
47
|
+
? ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, successResponses[0]!.statusCode) })
|
|
48
|
+
: ast.createSchema({
|
|
51
49
|
type: 'union',
|
|
52
|
-
members: successResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
|
|
50
|
+
members: successResponses.map((res) => ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
|
|
53
51
|
})
|
|
54
|
-
: createSchema({ type: 'any', primitive: undefined })
|
|
52
|
+
: ast.createSchema({ type: 'any', primitive: undefined })
|
|
55
53
|
|
|
56
54
|
const errorsSchema =
|
|
57
55
|
errorResponses.length > 0
|
|
58
56
|
? errorResponses.length === 1
|
|
59
|
-
? createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, errorResponses[0]!.statusCode) })
|
|
60
|
-
: createSchema({
|
|
57
|
+
? ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, errorResponses[0]!.statusCode) })
|
|
58
|
+
: ast.createSchema({
|
|
61
59
|
type: 'union',
|
|
62
|
-
members: errorResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
|
|
60
|
+
members: errorResponses.map((res) => ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
|
|
63
61
|
})
|
|
64
|
-
: createSchema({ type: 'any', primitive: undefined })
|
|
62
|
+
: ast.createSchema({ type: 'any', primitive: undefined })
|
|
65
63
|
|
|
66
|
-
const properties = [createProperty({ name: 'Response', required: true, schema: responseSchema })]
|
|
64
|
+
const properties = [ast.createProperty({ name: 'Response', required: true, schema: responseSchema })]
|
|
67
65
|
|
|
68
66
|
if (!isGet && node.requestBody?.schema) {
|
|
69
67
|
properties.push(
|
|
70
|
-
createProperty({
|
|
68
|
+
ast.createProperty({
|
|
71
69
|
name: 'Request',
|
|
72
70
|
required: true,
|
|
73
|
-
schema: createSchema({ type: 'ref', name: resolver.resolveDataName(node) }),
|
|
71
|
+
schema: ast.createSchema({ type: 'ref', name: resolver.resolveDataName(node) }),
|
|
74
72
|
}),
|
|
75
73
|
)
|
|
76
74
|
}
|
|
@@ -78,10 +76,10 @@ function buildLegacyResponsesSchemaNode(node: OperationNode, { resolver }: Build
|
|
|
78
76
|
const queryParam = node.parameters.find((p) => p.in === 'query')
|
|
79
77
|
if (queryParam) {
|
|
80
78
|
properties.push(
|
|
81
|
-
createProperty({
|
|
79
|
+
ast.createProperty({
|
|
82
80
|
name: 'QueryParams',
|
|
83
81
|
required: true,
|
|
84
|
-
schema: createSchema({ type: 'ref', name: resolver.resolveQueryParamsName(node, queryParam) }),
|
|
82
|
+
schema: ast.createSchema({ type: 'ref', name: resolver.resolveQueryParamsName(node, queryParam) }),
|
|
85
83
|
}),
|
|
86
84
|
)
|
|
87
85
|
}
|
|
@@ -89,10 +87,10 @@ function buildLegacyResponsesSchemaNode(node: OperationNode, { resolver }: Build
|
|
|
89
87
|
const pathParam = node.parameters.find((p) => p.in === 'path')
|
|
90
88
|
if (pathParam) {
|
|
91
89
|
properties.push(
|
|
92
|
-
createProperty({
|
|
90
|
+
ast.createProperty({
|
|
93
91
|
name: 'PathParams',
|
|
94
92
|
required: true,
|
|
95
|
-
schema: createSchema({ type: 'ref', name: resolver.resolvePathParamsName(node, pathParam) }),
|
|
93
|
+
schema: ast.createSchema({ type: 'ref', name: resolver.resolvePathParamsName(node, pathParam) }),
|
|
96
94
|
}),
|
|
97
95
|
)
|
|
98
96
|
}
|
|
@@ -100,50 +98,50 @@ function buildLegacyResponsesSchemaNode(node: OperationNode, { resolver }: Build
|
|
|
100
98
|
const headerParam = node.parameters.find((p) => p.in === 'header')
|
|
101
99
|
if (headerParam) {
|
|
102
100
|
properties.push(
|
|
103
|
-
createProperty({
|
|
101
|
+
ast.createProperty({
|
|
104
102
|
name: 'HeaderParams',
|
|
105
103
|
required: true,
|
|
106
|
-
schema: createSchema({ type: 'ref', name: resolver.resolveHeaderParamsName(node, headerParam) }),
|
|
104
|
+
schema: ast.createSchema({ type: 'ref', name: resolver.resolveHeaderParamsName(node, headerParam) }),
|
|
107
105
|
}),
|
|
108
106
|
)
|
|
109
107
|
}
|
|
110
108
|
|
|
111
|
-
properties.push(createProperty({ name: 'Errors', required: true, schema: errorsSchema }))
|
|
109
|
+
properties.push(ast.createProperty({ name: 'Errors', required: true, schema: errorsSchema }))
|
|
112
110
|
|
|
113
|
-
return createSchema({ type: 'object', properties })
|
|
111
|
+
return ast.createSchema({ type: 'object', properties })
|
|
114
112
|
}
|
|
115
113
|
|
|
116
|
-
function buildLegacyResponseUnionSchemaNode(node: OperationNode, { resolver }: BuildOperationSchemaOptions): SchemaNode {
|
|
114
|
+
function buildLegacyResponseUnionSchemaNode(node: ast.OperationNode, { resolver }: BuildOperationSchemaOptions): ast.SchemaNode {
|
|
117
115
|
const successResponses = node.responses.filter((res) => {
|
|
118
116
|
const code = Number(res.statusCode)
|
|
119
117
|
return !Number.isNaN(code) && code >= 200 && code < 300
|
|
120
118
|
})
|
|
121
119
|
|
|
122
120
|
if (successResponses.length === 0) {
|
|
123
|
-
return createSchema({ type: 'any', primitive: undefined })
|
|
121
|
+
return ast.createSchema({ type: 'any', primitive: undefined })
|
|
124
122
|
}
|
|
125
123
|
|
|
126
124
|
if (successResponses.length === 1) {
|
|
127
|
-
return createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, successResponses[0]!.statusCode) })
|
|
125
|
+
return ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, successResponses[0]!.statusCode) })
|
|
128
126
|
}
|
|
129
127
|
|
|
130
|
-
return createSchema({
|
|
128
|
+
return ast.createSchema({
|
|
131
129
|
type: 'union',
|
|
132
|
-
members: successResponses.map((res) => createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
|
|
130
|
+
members: successResponses.map((res) => ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, res.statusCode) })),
|
|
133
131
|
})
|
|
134
132
|
}
|
|
135
133
|
|
|
136
|
-
function nameUnnamedEnums(node: SchemaNode, parentName: string): SchemaNode {
|
|
137
|
-
return transform(node, {
|
|
134
|
+
function nameUnnamedEnums(node: ast.SchemaNode, parentName: string): ast.SchemaNode {
|
|
135
|
+
return ast.transform(node, {
|
|
138
136
|
schema(n) {
|
|
139
|
-
const enumNode = narrowSchema(n, 'enum')
|
|
137
|
+
const enumNode = ast.narrowSchema(n, 'enum')
|
|
140
138
|
if (enumNode && !enumNode.name) {
|
|
141
139
|
return { ...enumNode, name: pascalCase([parentName, 'enum'].join(' ')) }
|
|
142
140
|
}
|
|
143
141
|
return undefined
|
|
144
142
|
},
|
|
145
143
|
property(p) {
|
|
146
|
-
const enumNode = narrowSchema(p.schema, 'enum')
|
|
144
|
+
const enumNode = ast.narrowSchema(p.schema, 'enum')
|
|
147
145
|
if (enumNode && !enumNode.name) {
|
|
148
146
|
return {
|
|
149
147
|
...p,
|
|
@@ -157,22 +155,23 @@ function nameUnnamedEnums(node: SchemaNode, parentName: string): SchemaNode {
|
|
|
157
155
|
|
|
158
156
|
export const typeGeneratorLegacy = defineGenerator<PluginTs>({
|
|
159
157
|
name: 'typescript-legacy',
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const {
|
|
158
|
+
renderer: jsxRenderer,
|
|
159
|
+
schema(node, ctx) {
|
|
160
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, syntaxType, optionalType, arrayType, output, group } = ctx.options
|
|
161
|
+
const { adapter, config, resolver, root } = ctx
|
|
163
162
|
|
|
164
163
|
if (!node.name) {
|
|
165
164
|
return
|
|
166
165
|
}
|
|
167
166
|
|
|
168
|
-
const mode =
|
|
167
|
+
const mode = ctx.getMode(output)
|
|
169
168
|
|
|
170
169
|
const imports = adapter.getImports(node, (schemaName) => ({
|
|
171
170
|
name: resolver.resolveTypeName(schemaName),
|
|
172
171
|
path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
|
|
173
172
|
}))
|
|
174
173
|
|
|
175
|
-
const isEnumSchema = !!narrowSchema(node, schemaTypes.enum)
|
|
174
|
+
const isEnumSchema = !!ast.narrowSchema(node, ast.schemaTypes.enum)
|
|
176
175
|
|
|
177
176
|
const meta = {
|
|
178
177
|
name: ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && isEnumSchema ? resolver.resolveEnumKeyName(node, enumTypeSuffix) : resolver.resolveTypeName(node.name),
|
|
@@ -214,12 +213,12 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
|
|
|
214
213
|
</File>
|
|
215
214
|
)
|
|
216
215
|
},
|
|
217
|
-
operation(node,
|
|
218
|
-
const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output } = options
|
|
219
|
-
const { adapter, config, resolver, root } =
|
|
216
|
+
operation(node, ctx) {
|
|
217
|
+
const { enumType, enumTypeSuffix, enumKeyCasing, optionalType, arrayType, syntaxType, paramsCasing, group, output } = ctx.options
|
|
218
|
+
const { adapter, config, resolver, root } = ctx
|
|
220
219
|
|
|
221
|
-
const mode =
|
|
222
|
-
const params = caseParams(node.parameters, paramsCasing)
|
|
220
|
+
const mode = ctx.getMode(output)
|
|
221
|
+
const params = ast.caseParams(node.parameters, paramsCasing)
|
|
223
222
|
|
|
224
223
|
const meta = {
|
|
225
224
|
file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
|
|
@@ -231,7 +230,7 @@ export const typeGeneratorLegacy = defineGenerator<PluginTs>({
|
|
|
231
230
|
description,
|
|
232
231
|
keysToOmit,
|
|
233
232
|
}: {
|
|
234
|
-
schema: SchemaNode | null
|
|
233
|
+
schema: ast.SchemaNode | null
|
|
235
234
|
name: string
|
|
236
235
|
description?: string
|
|
237
236
|
keysToOmit?: Array<string>
|
package/src/plugin.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { camelCase } from '@internals/utils'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { definePlugin, type Group } from '@kubb/core'
|
|
3
|
+
import { typeGenerator } from './generators/typeGenerator.tsx'
|
|
4
|
+
import { typeGeneratorLegacy } from './generators/typeGeneratorLegacy.tsx'
|
|
5
|
+
import { resolverTs } from './resolvers/resolverTs.ts'
|
|
6
|
+
import { resolverTsLegacy } from './resolvers/resolverTsLegacy.ts'
|
|
5
7
|
import type { PluginTs } from './types.ts'
|
|
6
8
|
|
|
7
9
|
/**
|
|
@@ -25,7 +27,7 @@ export const pluginTsName = 'plugin-ts' satisfies PluginTs['name']
|
|
|
25
27
|
* })
|
|
26
28
|
* ```
|
|
27
29
|
*/
|
|
28
|
-
export const pluginTs =
|
|
30
|
+
export const pluginTs = definePlugin<PluginTs>((options) => {
|
|
29
31
|
const {
|
|
30
32
|
output = { path: 'types', barrelType: 'named' },
|
|
31
33
|
group,
|
|
@@ -40,92 +42,56 @@ export const pluginTs = createPlugin<PluginTs>((options) => {
|
|
|
40
42
|
syntaxType = 'type',
|
|
41
43
|
paramsCasing,
|
|
42
44
|
printer,
|
|
43
|
-
compatibilityPreset = 'default',
|
|
44
45
|
resolver: userResolver,
|
|
45
46
|
transformer: userTransformer,
|
|
46
47
|
generators: userGenerators = [],
|
|
48
|
+
compatibilityPreset = 'default',
|
|
47
49
|
} = options
|
|
48
50
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
presets: presets,
|
|
52
|
-
resolver: userResolver,
|
|
53
|
-
transformer: userTransformer,
|
|
54
|
-
generators: userGenerators,
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
const generators = preset.generators ?? []
|
|
58
|
-
const mergedGenerator = mergeGenerators(generators)
|
|
51
|
+
const defaultResolver = compatibilityPreset === 'kubbV4' ? resolverTsLegacy : resolverTs
|
|
52
|
+
const defaultGenerator = compatibilityPreset === 'kubbV4' ? typeGeneratorLegacy : typeGenerator
|
|
59
53
|
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
const groupConfig = group
|
|
55
|
+
? ({
|
|
56
|
+
...group,
|
|
57
|
+
name: (ctx) => {
|
|
58
|
+
if (group.type === 'path') {
|
|
59
|
+
return `${ctx.group.split('/')[1]}`
|
|
60
|
+
}
|
|
61
|
+
return `${camelCase(ctx.group)}Controller`
|
|
62
|
+
},
|
|
63
|
+
} satisfies Group)
|
|
64
|
+
: undefined
|
|
62
65
|
|
|
63
66
|
return {
|
|
64
67
|
name: pluginTsName,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
enumTypeSuffix,
|
|
93
|
-
enumKeyCasing,
|
|
94
|
-
syntaxType,
|
|
95
|
-
paramsCasing,
|
|
96
|
-
printer,
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
resolvePath(baseName, pathMode, options) {
|
|
100
|
-
if (!resolvePathWarning) {
|
|
101
|
-
this.warn('Do not use resolvePath for pluginTs, use resolverTs.resolvePath instead')
|
|
102
|
-
resolvePathWarning = true
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return this.plugin.resolver.resolvePath(
|
|
106
|
-
{ baseName, pathMode, tag: options?.group?.tag, path: options?.group?.path },
|
|
107
|
-
{ root: this.root, output, group: this.plugin.options.group },
|
|
108
|
-
)
|
|
109
|
-
},
|
|
110
|
-
resolveName(name, type) {
|
|
111
|
-
if (!resolveNameWarning) {
|
|
112
|
-
this.warn('Do not use resolveName for pluginTs, use resolverTs.default instead')
|
|
113
|
-
resolveNameWarning = true
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return this.plugin.resolver.default(name, type)
|
|
117
|
-
},
|
|
118
|
-
async schema(node, options) {
|
|
119
|
-
return mergedGenerator.schema?.call(this, node, options)
|
|
120
|
-
},
|
|
121
|
-
async operation(node, options) {
|
|
122
|
-
return mergedGenerator.operation?.call(this, node, options)
|
|
123
|
-
},
|
|
124
|
-
async operations(nodes, options) {
|
|
125
|
-
return mergedGenerator.operations?.call(this, nodes, options)
|
|
126
|
-
},
|
|
127
|
-
async buildStart() {
|
|
128
|
-
await this.openInStudio({ ast: true })
|
|
68
|
+
options,
|
|
69
|
+
hooks: {
|
|
70
|
+
'kubb:plugin:setup'(ctx) {
|
|
71
|
+
ctx.setOptions({
|
|
72
|
+
output,
|
|
73
|
+
exclude,
|
|
74
|
+
include,
|
|
75
|
+
override,
|
|
76
|
+
optionalType,
|
|
77
|
+
group: groupConfig,
|
|
78
|
+
arrayType,
|
|
79
|
+
enumType,
|
|
80
|
+
enumTypeSuffix,
|
|
81
|
+
enumKeyCasing,
|
|
82
|
+
syntaxType,
|
|
83
|
+
paramsCasing,
|
|
84
|
+
printer,
|
|
85
|
+
})
|
|
86
|
+
ctx.setResolver(userResolver ? { ...defaultResolver, ...userResolver } : defaultResolver)
|
|
87
|
+
if (userTransformer) {
|
|
88
|
+
ctx.setTransformer(userTransformer)
|
|
89
|
+
}
|
|
90
|
+
ctx.addGenerator(defaultGenerator)
|
|
91
|
+
for (const gen of userGenerators) {
|
|
92
|
+
ctx.addGenerator(gen)
|
|
93
|
+
}
|
|
94
|
+
},
|
|
129
95
|
},
|
|
130
96
|
}
|
|
131
97
|
})
|