@kubb/plugin-ts 5.0.0-alpha.11 → 5.0.0-alpha.13

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.
Files changed (57) hide show
  1. package/dist/Type-C8EHVKjc.js +663 -0
  2. package/dist/Type-C8EHVKjc.js.map +1 -0
  3. package/dist/Type-DrOq6-nh.cjs +680 -0
  4. package/dist/Type-DrOq6-nh.cjs.map +1 -0
  5. package/dist/casing-Cp-jbC_k.js +84 -0
  6. package/dist/casing-Cp-jbC_k.js.map +1 -0
  7. package/dist/casing-D2uQKLWS.cjs +144 -0
  8. package/dist/casing-D2uQKLWS.cjs.map +1 -0
  9. package/dist/components.cjs +3 -2
  10. package/dist/components.d.ts +41 -9
  11. package/dist/components.js +2 -2
  12. package/dist/generators-CX3cSSdF.cjs +551 -0
  13. package/dist/generators-CX3cSSdF.cjs.map +1 -0
  14. package/dist/generators-dCqW0ECC.js +547 -0
  15. package/dist/generators-dCqW0ECC.js.map +1 -0
  16. package/dist/generators.cjs +2 -3
  17. package/dist/generators.d.ts +3 -503
  18. package/dist/generators.js +2 -2
  19. package/dist/index.cjs +135 -4
  20. package/dist/index.cjs.map +1 -0
  21. package/dist/index.d.ts +2 -41
  22. package/dist/index.js +134 -2
  23. package/dist/index.js.map +1 -0
  24. package/dist/resolvers-CH7hINyz.js +181 -0
  25. package/dist/resolvers-CH7hINyz.js.map +1 -0
  26. package/dist/resolvers-ebHaaCyw.cjs +191 -0
  27. package/dist/resolvers-ebHaaCyw.cjs.map +1 -0
  28. package/dist/resolvers.cjs +4 -0
  29. package/dist/resolvers.d.ts +51 -0
  30. package/dist/resolvers.js +2 -0
  31. package/dist/{types-mSXmB8WU.d.ts → types-BSRhtbGl.d.ts} +80 -57
  32. package/package.json +12 -5
  33. package/src/components/{v2/Enum.tsx → Enum.tsx} +27 -11
  34. package/src/components/Type.tsx +24 -141
  35. package/src/components/index.ts +1 -0
  36. package/src/generators/index.ts +0 -1
  37. package/src/generators/typeGenerator.tsx +204 -413
  38. package/src/generators/utils.ts +300 -0
  39. package/src/index.ts +0 -1
  40. package/src/plugin.ts +81 -126
  41. package/src/printer.ts +20 -6
  42. package/src/resolvers/index.ts +2 -0
  43. package/src/{resolverTs.ts → resolvers/resolverTs.ts} +26 -2
  44. package/src/resolvers/resolverTsLegacy.ts +85 -0
  45. package/src/types.ts +75 -52
  46. package/dist/components-CRu8IKY3.js +0 -729
  47. package/dist/components-CRu8IKY3.js.map +0 -1
  48. package/dist/components-DeNDKlzf.cjs +0 -982
  49. package/dist/components-DeNDKlzf.cjs.map +0 -1
  50. package/dist/plugin-CJ29AwE2.cjs +0 -1320
  51. package/dist/plugin-CJ29AwE2.cjs.map +0 -1
  52. package/dist/plugin-D60XNJSD.js +0 -1267
  53. package/dist/plugin-D60XNJSD.js.map +0 -1
  54. package/src/components/v2/Type.tsx +0 -59
  55. package/src/generators/v2/typeGenerator.tsx +0 -167
  56. package/src/generators/v2/utils.ts +0 -140
  57. package/src/parser.ts +0 -389
@@ -0,0 +1,51 @@
1
+ import { t as __name } from "./chunk--u3MIqq1.js";
2
+ import { r as ResolverTs } from "./types-BSRhtbGl.js";
3
+
4
+ //#region src/resolvers/resolverTs.d.ts
5
+ /**
6
+ * Resolver for `@kubb/plugin-ts` that provides the default naming and path-resolution
7
+ * helpers used by the plugin. Import this in other plugins to resolve the exact names and
8
+ * paths that `plugin-ts` generates without hardcoding the conventions.
9
+ *
10
+ * The `default` method is automatically injected by `defineResolver` — it uses `camelCase`
11
+ * for identifiers/files and `pascalCase` for type names.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { resolver } from '@kubb/plugin-ts'
16
+ *
17
+ * resolver.default('list pets', 'type') // → 'ListPets'
18
+ * resolver.resolveName('list pets status 200') // → 'listPetsStatus200'
19
+ * resolver.resolveTypedName('list pets status 200') // → 'ListPetsStatus200'
20
+ * resolver.resolvePathName('list pets', 'file') // → 'listPets'
21
+ * ```
22
+ */
23
+ declare const resolverTs: ResolverTs;
24
+ //#endregion
25
+ //#region src/resolvers/resolverTsLegacy.d.ts
26
+ /**
27
+ * Legacy resolver for `@kubb/plugin-ts` that reproduces the naming conventions
28
+ * used before the v2 resolver refactor. Enable via `legacy: true` in plugin options.
29
+ *
30
+ * Key differences from the default resolver:
31
+ * - Response status types: `<OperationId><StatusCode>` (e.g. `CreatePets201`) instead of `<OperationId>Status201`
32
+ * - Default/error responses: `<OperationId>Error` instead of `<OperationId>StatusDefault`
33
+ * - Request body: `<OperationId>MutationRequest` (non-GET) / `<OperationId>QueryRequest` (GET)
34
+ * - Combined responses type: `<OperationId>Mutation` / `<OperationId>Query`
35
+ * - Response union: `<OperationId>MutationResponse` / `<OperationId>QueryResponse`
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import { resolverTsLegacy } from '@kubb/plugin-ts'
40
+ *
41
+ * resolverTsLegacy.resolveResponseStatusTypedName(node, 201) // → 'CreatePets201'
42
+ * resolverTsLegacy.resolveResponseStatusTypedName(node, 'default') // → 'CreatePetsError'
43
+ * resolverTsLegacy.resolveDataTypedName(node) // → 'CreatePetsMutationRequest' (POST)
44
+ * resolverTsLegacy.resolveResponsesTypedName(node) // → 'CreatePetsMutation' (POST)
45
+ * resolverTsLegacy.resolveResponseTypedName(node) // → 'CreatePetsMutationResponse' (POST)
46
+ * ```
47
+ */
48
+ declare const resolverTsLegacy: ResolverTs;
49
+ //#endregion
50
+ export { resolverTs, resolverTsLegacy };
51
+ //# sourceMappingURL=resolvers.d.ts.map
@@ -0,0 +1,2 @@
1
+ import { n as resolverTs, t as resolverTsLegacy } from "./resolvers-CH7hINyz.js";
2
+ export { resolverTs, resolverTsLegacy };
@@ -1,9 +1,9 @@
1
1
  import { t as __name } from "./chunk--u3MIqq1.js";
2
2
  import { Group, Output, PluginFactoryOptions, ResolveNameParams, Resolver } from "@kubb/core";
3
- import { Exclude, Include, Override, ResolvePathOptions } from "@kubb/plugin-oas";
4
- import { Generator as Generator$1 } from "@kubb/plugin-oas/generators";
5
- import { Oas, contentType } from "@kubb/oas";
6
3
  import { OperationNode, ParameterNode, SchemaNode, StatusCode } from "@kubb/ast/types";
4
+ import { Oas, contentType } from "@kubb/oas";
5
+ import { Exclude, Include, Override, ResolvePathOptions } from "@kubb/plugin-oas";
6
+ import { Generator } from "@kubb/plugin-oas/generators";
7
7
 
8
8
  //#region src/types.d.ts
9
9
  /**
@@ -135,6 +135,60 @@ type ResolverTs = Resolver & {
135
135
  * resolver.resolveEnumKeyTypedName(node) // → 'PetStatusKey'
136
136
  */
137
137
  resolveEnumKeyTypedName(node: SchemaNode): string;
138
+ /**
139
+ * Resolves the variable/function name for an operation's grouped path parameters type.
140
+ * Only available in legacy mode (`legacy: true`).
141
+ *
142
+ * @deprecated Legacy only — will be removed in v6. Use `resolveParamName` per individual parameter instead.
143
+ * @example
144
+ * resolver.resolvePathParamsName(node) // → 'GetPetByIdPathParams'
145
+ */
146
+ resolvePathParamsName?(node: OperationNode): string;
147
+ /**
148
+ * Resolves the TypeScript type alias name for an operation's grouped path parameters type.
149
+ * Only available in legacy mode (`legacy: true`).
150
+ *
151
+ * @deprecated Legacy only — will be removed in v6. Use `resolveParamTypedName` per individual parameter instead.
152
+ * @example
153
+ * resolver.resolvePathParamsTypedName(node) // → 'GetPetByIdPathParams'
154
+ */
155
+ resolvePathParamsTypedName?(node: OperationNode): string;
156
+ /**
157
+ * Resolves the variable/function name for an operation's grouped query parameters type.
158
+ * Only available in legacy mode (`legacy: true`).
159
+ *
160
+ * @deprecated Legacy only — will be removed in v6. Use `resolveParamName` per individual parameter instead.
161
+ * @example
162
+ * resolver.resolveQueryParamsName(node) // → 'FindPetsByStatusQueryParams'
163
+ */
164
+ resolveQueryParamsName?(node: OperationNode): string;
165
+ /**
166
+ * Resolves the TypeScript type alias name for an operation's grouped query parameters type.
167
+ * Only available in legacy mode (`legacy: true`).
168
+ *
169
+ * @deprecated Legacy only — will be removed in v6. Use `resolveParamTypedName` per individual parameter instead.
170
+ * @example
171
+ * resolver.resolveQueryParamsTypedName(node) // → 'FindPetsByStatusQueryParams'
172
+ */
173
+ resolveQueryParamsTypedName?(node: OperationNode): string;
174
+ /**
175
+ * Resolves the variable/function name for an operation's grouped header parameters type.
176
+ * Only available in legacy mode (`legacy: true`).
177
+ *
178
+ * @deprecated Legacy only — will be removed in v6. Use `resolveParamName` per individual parameter instead.
179
+ * @example
180
+ * resolver.resolveHeaderParamsName(node) // → 'DeletePetHeaderParams'
181
+ */
182
+ resolveHeaderParamsName?(node: OperationNode): string;
183
+ /**
184
+ * Resolves the TypeScript type alias name for an operation's grouped header parameters type.
185
+ * Only available in legacy mode (`legacy: true`).
186
+ *
187
+ * @deprecated Legacy only — will be removed in v6. Use `resolveParamTypedName` per individual parameter instead.
188
+ * @example
189
+ * resolver.resolveHeaderParamsTypedName(node) // → 'DeletePetHeaderParams'
190
+ */
191
+ resolveHeaderParamsTypedName?(node: OperationNode): string;
138
192
  };
139
193
  type Options = {
140
194
  /**
@@ -192,52 +246,6 @@ type Options = {
192
246
  * @default 'type'
193
247
  */
194
248
  syntaxType?: 'type' | 'interface';
195
- /**
196
- * Set a suffix for the generated enums.
197
- * @default 'enum'
198
- * @deprecated Set `enumSuffix` on the adapter (`adapterOas({ enumSuffix })`) instead.
199
- * In v5, the adapter owns this decision at parse time; the plugin option is ignored.
200
- */
201
- enumSuffix?: string;
202
- /**
203
- * Choose to use date or datetime as JavaScript Date instead of string.
204
- * - 'string' represents dates as string values.
205
- * - 'date' represents dates as JavaScript Date objects.
206
- * @default 'string'
207
- * @deprecated Set `dateType` on the adapter (`adapterOas({ dateType })`) instead.
208
- * In v5, the adapter owns this decision at parse time; the plugin option is ignored.
209
- */
210
- dateType?: 'string' | 'date';
211
- /**
212
- * Choose to use `number` or `bigint` for integer fields with `int64` format.
213
- * - 'number' uses the TypeScript `number` type (matches JSON.parse() runtime behavior).
214
- * - 'bigint' uses the TypeScript `bigint` type (accurate for values exceeding Number.MAX_SAFE_INTEGER).
215
- * @note in v5 of Kubb 'bigint' will become the default to better align with OpenAPI's int64 specification.
216
- * @default 'number'
217
- * @deprecated Set `integerType` on the adapter (`adapterOas({ integerType })`) instead.
218
- * In v5, the adapter owns this decision at parse time; the plugin option is ignored.
219
- */
220
- integerType?: 'number' | 'bigint';
221
- /**
222
- * Which type to use when the Swagger/OpenAPI file is not providing more information.
223
- * - 'any' allows any value.
224
- * - 'unknown' requires type narrowing before use.
225
- * - 'void' represents no value.
226
- * @default 'any'
227
- * @deprecated Set `unknownType` on the adapter (`adapterOas({ unknownType })`) instead.
228
- * In v5, the adapter owns this decision at parse time; the plugin option is ignored.
229
- */
230
- unknownType?: 'any' | 'unknown' | 'void';
231
- /**
232
- * Which type to use for empty schema values.
233
- * - 'any' allows any value.
234
- * - 'unknown' requires type narrowing before use.
235
- * - 'void' represents no value.
236
- * @default `unknownType`
237
- * @deprecated Set `emptySchemaType` on the adapter (`adapterOas({ emptySchemaType })`) instead.
238
- * In v5, the adapter owns this decision at parse time; the plugin option is ignored.
239
- */
240
- emptySchemaType?: 'any' | 'unknown' | 'void';
241
249
  /**
242
250
  * Choose what to use as mode for an optional value.
243
251
  * - 'questionToken' marks the property as optional with ? (e.g., type?: string).
@@ -269,11 +277,22 @@ type Options = {
269
277
  /**
270
278
  * Define some generators next to the ts generators
271
279
  */
272
- generators?: Array<Generator$1<PluginTs>>;
280
+ generators?: Array<Generator<PluginTs>>;
273
281
  /**
274
282
  * Unstable naming for v5
275
283
  */
276
284
  UNSTABLE_NAMING?: true;
285
+ /**
286
+ * Enable legacy naming conventions for backwards compatibility.
287
+ * When enabled, operation-level types use the old naming scheme:
288
+ * - GET responses → `<OperationId>QueryResponse`, `<OperationId>Query`
289
+ * - Non-GET responses → `<OperationId>MutationResponse`, `<OperationId>Mutation`
290
+ * - Request body → `<OperationId>QueryRequest` / `<OperationId>MutationRequest`
291
+ * - Response status codes → `<OperationId><StatusCode>` (e.g. `CreatePets201`)
292
+ * - Default/error response → `<OperationId>Error`
293
+ * @default false
294
+ */
295
+ legacy?: boolean;
277
296
  };
278
297
  type ResolvedOptions = {
279
298
  output: Output<Oas>;
@@ -281,18 +300,22 @@ type ResolvedOptions = {
281
300
  override: NonNullable<Options['override']>;
282
301
  enumType: NonNullable<Options['enumType']>;
283
302
  enumKeyCasing: NonNullable<Options['enumKeyCasing']>;
284
- enumSuffix: NonNullable<Options['enumSuffix']>;
285
- dateType: NonNullable<Options['dateType']>;
286
- integerType: NonNullable<Options['integerType']>;
287
- unknownType: NonNullable<Options['unknownType']>;
288
- emptySchemaType: NonNullable<Options['emptySchemaType']>;
289
303
  optionalType: NonNullable<Options['optionalType']>;
290
304
  arrayType: NonNullable<Options['arrayType']>;
291
305
  transformers: NonNullable<Options['transformers']>;
292
306
  syntaxType: NonNullable<Options['syntaxType']>;
293
307
  paramsCasing: Options['paramsCasing'];
308
+ legacy: NonNullable<Options['legacy']>;
309
+ resolver: ResolverTs;
310
+ /**
311
+ * The base resolver without any `transformers.name` wrapping.
312
+ * Used internally to derive enum prefix names so that user-defined
313
+ * name transformations (e.g. appending `Type`) are not embedded in
314
+ * the middle of inline-enum identifiers.
315
+ */
316
+ baseResolver?: ResolverTs;
294
317
  };
295
318
  type PluginTs = PluginFactoryOptions<'plugin-ts', Options, ResolvedOptions, never, ResolvePathOptions, ResolverTs>;
296
319
  //#endregion
297
- export { PluginTs as n, Options as t };
298
- //# sourceMappingURL=types-mSXmB8WU.d.ts.map
320
+ export { PluginTs as n, ResolverTs as r, Options as t };
321
+ //# sourceMappingURL=types-BSRhtbGl.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-ts",
3
- "version": "5.0.0-alpha.11",
3
+ "version": "5.0.0-alpha.13",
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",
@@ -39,6 +39,10 @@
39
39
  "import": "./dist/generators.js",
40
40
  "require": "./dist/generators.cjs"
41
41
  },
42
+ "./resolvers": {
43
+ "import": "./dist/resolvers.js",
44
+ "require": "./dist/resolvers.cjs"
45
+ },
42
46
  "./package.json": "./package.json"
43
47
  },
44
48
  "types": "./dist/index.d.ts",
@@ -49,6 +53,9 @@
49
53
  ],
50
54
  "generators": [
51
55
  "./dist/generators.d.ts"
56
+ ],
57
+ "resolvers": [
58
+ "./dist/resolvers.d.ts"
52
59
  ]
53
60
  }
54
61
  },
@@ -71,10 +78,10 @@
71
78
  "@kubb/react-fabric": "0.14.0",
72
79
  "remeda": "^2.33.6",
73
80
  "typescript": "5.9.3",
74
- "@kubb/ast": "5.0.0-alpha.11",
75
- "@kubb/core": "5.0.0-alpha.11",
76
- "@kubb/oas": "5.0.0-alpha.11",
77
- "@kubb/plugin-oas": "5.0.0-alpha.11"
81
+ "@kubb/ast": "5.0.0-alpha.13",
82
+ "@kubb/core": "5.0.0-alpha.13",
83
+ "@kubb/oas": "5.0.0-alpha.13",
84
+ "@kubb/plugin-oas": "5.0.0-alpha.13"
78
85
  },
79
86
  "peerDependencies": {
80
87
  "@kubb/react-fabric": "0.14.0"
@@ -1,31 +1,40 @@
1
- import { camelCase, pascalCase, trimQuotes } from '@internals/utils'
1
+ import { camelCase, trimQuotes } from '@internals/utils'
2
2
  import type { EnumSchemaNode } from '@kubb/ast/types'
3
3
  import { safePrint } from '@kubb/fabric-core/parsers/typescript'
4
4
  import { File } from '@kubb/react-fabric'
5
5
  import type { FabricReactNode } from '@kubb/react-fabric/types'
6
- import { ENUM_TYPES_WITH_KEY_SUFFIX, ENUM_TYPES_WITH_RUNTIME_VALUE, ENUM_TYPES_WITH_TYPE_ONLY } from '../../constants.ts'
7
- import * as factory from '../../factory.ts'
8
- import type { PluginTs } from '../../types.ts'
6
+ import { ENUM_TYPES_WITH_KEY_SUFFIX, ENUM_TYPES_WITH_RUNTIME_VALUE, ENUM_TYPES_WITH_TYPE_ONLY } from '../constants.ts'
7
+ import * as factory from '../factory.ts'
8
+ import type { PluginTs, ResolverTs } from '../types.ts'
9
9
 
10
10
  type Props = {
11
11
  node: EnumSchemaNode
12
12
  enumType: PluginTs['resolvedOptions']['enumType']
13
13
  enumKeyCasing: PluginTs['resolvedOptions']['enumKeyCasing']
14
+ resolver: ResolverTs
14
15
  }
15
16
 
16
17
  /**
17
18
  * Resolves the runtime identifier name and the TypeScript type name for an enum schema node.
18
19
  *
19
20
  * The raw `node.name` may be a YAML key such as `"enumNames.Type"` which is not a
20
- * valid TypeScript identifier. `pascalCase` normalizes it unconditionally; for inline enum
21
- * properties the adapter already emits a PascalCase+suffix name so `pascalCase` is a no-op.
21
+ * valid TypeScript identifier. The resolver normalizes it; for inline enum
22
+ * properties the adapter already emits a PascalCase+suffix name so resolution is typically a no-op.
22
23
  */
23
- export function getEnumNames(node: EnumSchemaNode, enumType: PluginTs['resolvedOptions']['enumType']): { enumName: string; typeName: string } {
24
- const resolved = pascalCase(node.name!)
24
+ export function getEnumNames({ node, enumType, resolver }: { node: EnumSchemaNode; enumType: PluginTs['resolvedOptions']['enumType']; resolver: ResolverTs }): {
25
+ enumName: string
26
+ typeName: string
27
+ /**
28
+ * The PascalCase name that `$ref` importers will use to reference this enum type.
29
+ * For `asConst`/`asPascalConst` this differs from `typeName` (which has a `Key` suffix).
30
+ */
31
+ refName: string
32
+ } {
33
+ const resolved = resolver.default(node.name!, 'type')
25
34
  const enumName = enumType === 'asPascalConst' ? resolved : camelCase(node.name!)
26
35
  const typeName = ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) ? `${resolved}Key` : resolved
27
36
 
28
- return { enumName, typeName }
37
+ return { enumName, typeName, refName: resolved }
29
38
  }
30
39
 
31
40
  /**
@@ -39,8 +48,8 @@ export function getEnumNames(node: EnumSchemaNode, enumType: PluginTs['resolvedO
39
48
  * The emitted `File.Source` nodes carry the resolved names so that the barrel
40
49
  * index picks up the correct export identifiers.
41
50
  */
42
- export function Enum({ node, enumType, enumKeyCasing }: Props): FabricReactNode {
43
- const { enumName, typeName } = getEnumNames(node, enumType)
51
+ export function Enum({ node, enumType, enumKeyCasing, resolver }: Props): FabricReactNode {
52
+ const { enumName, typeName, refName } = getEnumNames({ node, enumType, resolver })
44
53
 
45
54
  const [nameNode, typeNode] = factory.createEnumDeclaration({
46
55
  name: enumName,
@@ -52,6 +61,8 @@ export function Enum({ node, enumType, enumKeyCasing }: Props): FabricReactNode
52
61
  enumKeyCasing,
53
62
  })
54
63
 
64
+ const needsRefAlias = ENUM_TYPES_WITH_KEY_SUFFIX.has(enumType) && refName !== typeName
65
+
55
66
  return (
56
67
  <>
57
68
  {nameNode && (
@@ -62,6 +73,11 @@ export function Enum({ node, enumType, enumKeyCasing }: Props): FabricReactNode
62
73
  <File.Source name={typeName} isIndexable isExportable={ENUM_TYPES_WITH_RUNTIME_VALUE.has(enumType)} isTypeOnly={ENUM_TYPES_WITH_TYPE_ONLY.has(enumType)}>
63
74
  {safePrint(typeNode)}
64
75
  </File.Source>
76
+ {needsRefAlias && (
77
+ <File.Source name={refName} isExportable isIndexable isTypeOnly>
78
+ {`export type ${refName} = ${typeName}`}
79
+ </File.Source>
80
+ )}
65
81
  </>
66
82
  )
67
83
  }
@@ -1,24 +1,23 @@
1
- import { camelCase, jsStringEscape, pascalCase, trimQuotes } from '@internals/utils'
1
+ import { collect } from '@kubb/ast'
2
+ import type { EnumSchemaNode, SchemaNode } from '@kubb/ast/types'
2
3
  import { safePrint } from '@kubb/fabric-core/parsers/typescript'
3
- import type { SchemaObject } from '@kubb/oas'
4
- import { isKeyword, type Schema, SchemaGenerator, schemaKeywords } from '@kubb/plugin-oas'
5
4
  import { File } from '@kubb/react-fabric'
6
5
  import type { FabricReactNode } from '@kubb/react-fabric/types'
7
- import type ts from 'typescript'
8
- import * as factory from '../factory.ts'
9
- import { parse, typeKeywordMapper } from '../parser.ts'
6
+ import { printerTs } from '../printer.ts'
10
7
  import type { PluginTs } from '../types.ts'
8
+ import { Enum, getEnumNames } from './Enum.tsx'
11
9
 
12
10
  type Props = {
13
11
  name: string
14
12
  typedName: string
15
- schema: SchemaObject
16
- tree: Array<Schema>
13
+ node: SchemaNode
17
14
  optionalType: PluginTs['resolvedOptions']['optionalType']
18
15
  arrayType: PluginTs['resolvedOptions']['arrayType']
19
16
  enumType: PluginTs['resolvedOptions']['enumType']
20
17
  enumKeyCasing: PluginTs['resolvedOptions']['enumKeyCasing']
21
18
  syntaxType: PluginTs['resolvedOptions']['syntaxType']
19
+ resolver: PluginTs['resolvedOptions']['resolver']
20
+ legacy?: boolean
22
21
  description?: string
23
22
  keysToOmit?: string[]
24
23
  }
@@ -26,131 +25,34 @@ type Props = {
26
25
  export function Type({
27
26
  name,
28
27
  typedName,
29
- tree,
28
+ node,
30
29
  keysToOmit,
31
- schema,
32
30
  optionalType,
33
31
  arrayType,
34
32
  syntaxType,
35
33
  enumType,
36
34
  enumKeyCasing,
37
35
  description,
36
+ resolver,
38
37
  }: Props): FabricReactNode {
39
- const typeNodes: ts.Node[] = []
40
-
41
- if (!tree.length) {
42
- return ''
43
- }
44
-
45
- const schemaFromTree = tree.find((item) => item.keyword === schemaKeywords.schema)
46
- const enumSchemas = SchemaGenerator.deepSearch(tree, schemaKeywords.enum)
47
-
48
- let type =
49
- (tree
50
- .map((current, _index, siblings) =>
51
- parse(
52
- { name, schema, parent: undefined, current, siblings },
53
- {
54
- optionalType,
55
- arrayType,
56
- enumType,
57
- },
58
- ),
59
- )
60
- .filter(Boolean)
61
- .at(0) as ts.TypeNode) || typeKeywordMapper.undefined()
62
-
63
- // Add a "Key" suffix to avoid collisions where necessary
64
- if (['asConst', 'asPascalConst'].includes(enumType) && enumSchemas.length > 0) {
65
- const isDirectEnum = schema.type === 'array' && schema.items !== undefined
66
- const isEnumOnly = 'enum' in schema && schema.enum
67
-
68
- if (isDirectEnum || isEnumOnly) {
69
- const enumSchema = enumSchemas[0]!
70
- const typeNameWithKey = `${enumSchema.args.typeName}Key`
71
-
72
- type = factory.createTypeReferenceNode(typeNameWithKey)
73
-
74
- if (schema.type === 'array') {
75
- if (arrayType === 'generic') {
76
- type = factory.createTypeReferenceNode(factory.createIdentifier('Array'), [type])
77
- } else {
78
- type = factory.createArrayTypeNode(type)
79
- }
80
- }
81
- }
82
- }
83
-
84
- if (schemaFromTree && isKeyword(schemaFromTree, schemaKeywords.schema)) {
85
- const isNullish = tree.some((item) => item.keyword === schemaKeywords.nullish)
86
- const isNullable = tree.some((item) => item.keyword === schemaKeywords.nullable)
87
- const isOptional = tree.some((item) => item.keyword === schemaKeywords.optional)
38
+ const resolvedDescription = description || node?.description
39
+ const enumSchemaNodes = collect<EnumSchemaNode>(node, {
40
+ schema(n): EnumSchemaNode | undefined {
41
+ if (n.type === 'enum' && n.name) return n as EnumSchemaNode
42
+ },
43
+ })
88
44
 
89
- if (isNullable) {
90
- type = factory.createUnionDeclaration({
91
- nodes: [type, factory.keywordTypeNodes.null],
92
- }) as ts.TypeNode
93
- }
45
+ const printer = printerTs({ optionalType, arrayType, enumType, typeName: name, syntaxType, description: resolvedDescription, keysToOmit, resolver })
46
+ const typeNode = printer.print(node)
94
47
 
95
- if (isNullish && ['undefined', 'questionTokenAndUndefined'].includes(optionalType as string)) {
96
- type = factory.createUnionDeclaration({
97
- nodes: [type, factory.keywordTypeNodes.undefined],
98
- }) as ts.TypeNode
99
- }
100
-
101
- if (isOptional && ['undefined', 'questionTokenAndUndefined'].includes(optionalType as string)) {
102
- type = factory.createUnionDeclaration({
103
- nodes: [type, factory.keywordTypeNodes.undefined],
104
- }) as ts.TypeNode
105
- }
48
+ if (!typeNode) {
49
+ return
106
50
  }
107
51
 
108
- const useTypeGeneration = syntaxType === 'type' || [factory.syntaxKind.union].includes(type.kind as typeof factory.syntaxKind.union) || !!keysToOmit?.length
109
-
110
- typeNodes.push(
111
- factory.createTypeDeclaration({
112
- name,
113
- isExportable: true,
114
- type: keysToOmit?.length
115
- ? factory.createOmitDeclaration({
116
- keys: keysToOmit,
117
- type,
118
- nonNullable: true,
119
- })
120
- : type,
121
- syntax: useTypeGeneration ? 'type' : 'interface',
122
- comments: [
123
- schema.title ? `${jsStringEscape(schema.title)}` : undefined,
124
- description ? `@description ${jsStringEscape(description)}` : undefined,
125
- schema.deprecated ? '@deprecated' : undefined,
126
- schema.minLength ? `@minLength ${schema.minLength}` : undefined,
127
- schema.maxLength ? `@maxLength ${schema.maxLength}` : undefined,
128
- schema.pattern ? `@pattern ${schema.pattern}` : undefined,
129
- schema.default ? `@default ${schema.default}` : undefined,
130
- schema.example ? `@example ${schema.example}` : undefined,
131
- ],
132
- }),
133
- )
134
-
135
- const enums = [...new Set(enumSchemas)].map((enumSchema) => {
136
- const name = enumType === 'asPascalConst' ? pascalCase(enumSchema.args.name) : camelCase(enumSchema.args.name)
137
- const typeName = ['asConst', 'asPascalConst'].includes(enumType) ? `${enumSchema.args.typeName}Key` : enumSchema.args.typeName
138
-
139
- const [nameNode, typeNode] = factory.createEnumDeclaration({
140
- name,
141
- typeName,
142
- enums: enumSchema.args.items
143
- .map((item) => (item.value === undefined ? undefined : [trimQuotes(item.name?.toString()), item.value]))
144
- .filter(Boolean) as unknown as Array<[string, string]>,
145
- type: enumType,
146
- enumKeyCasing,
147
- })
148
-
52
+ const enums = [...new Map(enumSchemaNodes.map((n) => [n.name, n])).values()].map((node) => {
149
53
  return {
150
- nameNode,
151
- typeNode,
152
- name,
153
- typeName,
54
+ node,
55
+ ...getEnumNames({ node, enumType, resolver }),
154
56
  }
155
57
  })
156
58
 
@@ -160,29 +62,10 @@ export function Type({
160
62
 
161
63
  return (
162
64
  <>
163
- {shouldExportEnums &&
164
- enums.map(({ name, nameNode, typeName, typeNode }) => (
165
- <>
166
- {nameNode && (
167
- <File.Source name={name} isExportable isIndexable isTypeOnly={false}>
168
- {safePrint(nameNode)}
169
- </File.Source>
170
- )}
171
- {
172
- <File.Source
173
- name={typeName}
174
- isIndexable
175
- isExportable={['enum', 'asConst', 'asPascalConst', 'constEnum', 'literal', undefined].includes(enumType)}
176
- isTypeOnly={['asConst', 'asPascalConst', 'literal', undefined].includes(enumType)}
177
- >
178
- {safePrint(typeNode)}
179
- </File.Source>
180
- }
181
- </>
182
- ))}
65
+ {shouldExportEnums && enums.map(({ node }) => <Enum node={node} enumType={enumType} enumKeyCasing={enumKeyCasing} resolver={resolver} />)}
183
66
  {shouldExportType && (
184
67
  <File.Source name={typedName} isTypeOnly isExportable isIndexable>
185
- {safePrint(...typeNodes)}
68
+ {safePrint(typeNode)}
186
69
  </File.Source>
187
70
  )}
188
71
  </>
@@ -1 +1,2 @@
1
+ export { Enum } from './Enum.tsx'
1
2
  export { Type } from './Type.tsx'
@@ -1,2 +1 @@
1
1
  export { typeGenerator } from './typeGenerator.tsx'
2
- export { typeGenerator as typeGeneratorV2 } from './v2/typeGenerator.tsx'