@kubb/plugin-oas 3.0.0-alpha.8 → 3.0.0-beta.1

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 (100) hide show
  1. package/README.md +14 -5
  2. package/dist/OperationGenerator-BgQeGRzk.d.cts +550 -0
  3. package/dist/OperationGenerator-BgQeGRzk.d.ts +550 -0
  4. package/dist/{Schema-B1vcPGiK.d.ts → Schema-1iM2I0dK.d.ts} +1 -12
  5. package/dist/{Schema-DoSFh7Qd.d.cts → Schema-5o-c5UOy.d.cts} +1 -12
  6. package/dist/chunk-ABOQ73FL.cjs +36 -0
  7. package/dist/chunk-ABOQ73FL.cjs.map +1 -0
  8. package/dist/chunk-BG77DP54.js +30 -0
  9. package/dist/chunk-BG77DP54.js.map +1 -0
  10. package/dist/chunk-GF26SDHQ.js +28 -0
  11. package/dist/chunk-GF26SDHQ.js.map +1 -0
  12. package/dist/chunk-PADR76WZ.cjs +4 -0
  13. package/dist/chunk-PADR76WZ.cjs.map +1 -0
  14. package/dist/chunk-QAFBZLJA.cjs +48 -0
  15. package/dist/chunk-QAFBZLJA.cjs.map +1 -0
  16. package/dist/chunk-QT6ZFRNJ.cjs +752 -0
  17. package/dist/chunk-QT6ZFRNJ.cjs.map +1 -0
  18. package/dist/chunk-QWO5NQGQ.js +88 -0
  19. package/dist/chunk-QWO5NQGQ.js.map +1 -0
  20. package/dist/chunk-R47XMJ32.js +3 -0
  21. package/dist/chunk-R47XMJ32.js.map +1 -0
  22. package/dist/chunk-SR63CBLH.cjs +92 -0
  23. package/dist/chunk-SR63CBLH.cjs.map +1 -0
  24. package/dist/chunk-V2JO6RHI.js +744 -0
  25. package/dist/chunk-V2JO6RHI.js.map +1 -0
  26. package/dist/chunk-XNCEFOE6.js +45 -0
  27. package/dist/chunk-XNCEFOE6.js.map +1 -0
  28. package/dist/chunk-ZWHQ54JM.cjs +32 -0
  29. package/dist/chunk-ZWHQ54JM.cjs.map +1 -0
  30. package/dist/components.cjs +20 -12
  31. package/dist/components.cjs.map +1 -1
  32. package/dist/components.d.cts +3 -6
  33. package/dist/components.d.ts +3 -6
  34. package/dist/components.js +3 -12
  35. package/dist/components.js.map +1 -1
  36. package/dist/generators.cjs +14 -0
  37. package/dist/generators.cjs.map +1 -0
  38. package/dist/generators.d.cts +9 -0
  39. package/dist/generators.d.ts +9 -0
  40. package/dist/generators.js +5 -0
  41. package/dist/generators.js.map +1 -0
  42. package/dist/hooks.cjs +102 -57
  43. package/dist/hooks.cjs.map +1 -1
  44. package/dist/hooks.d.cts +41 -10
  45. package/dist/hooks.d.ts +41 -10
  46. package/dist/hooks.js +91 -53
  47. package/dist/hooks.js.map +1 -1
  48. package/dist/index.cjs +137 -187
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.d.cts +2 -5
  51. package/dist/index.d.ts +2 -5
  52. package/dist/index.js +76 -153
  53. package/dist/index.js.map +1 -1
  54. package/dist/utils.cjs +32 -41
  55. package/dist/utils.cjs.map +1 -1
  56. package/dist/utils.d.cts +5 -13
  57. package/dist/utils.d.ts +5 -13
  58. package/dist/utils.js +8 -40
  59. package/dist/utils.js.map +1 -1
  60. package/package.json +20 -14
  61. package/src/OperationGenerator.ts +23 -30
  62. package/src/SchemaGenerator.ts +79 -22
  63. package/src/SchemaMapper.ts +6 -4
  64. package/src/components/Schema.tsx +1 -99
  65. package/src/{parser.tsx → generator.tsx} +30 -22
  66. package/src/generators/index.ts +1 -0
  67. package/src/generators/jsonGenerator.ts +32 -0
  68. package/src/hooks/index.ts +2 -0
  69. package/src/hooks/useOperationManager.ts +77 -30
  70. package/src/hooks/useSchemaManager.ts +77 -0
  71. package/src/index.ts +3 -3
  72. package/src/plugin.ts +69 -56
  73. package/src/types.ts +24 -18
  74. package/src/utils/getParams.ts +1 -1
  75. package/src/utils/getSchemaFactory.ts +1 -1
  76. package/src/utils/index.ts +2 -1
  77. package/src/utils/parseFromConfig.ts +7 -7
  78. package/dist/OperationGenerator-DeXrfGDC.d.ts +0 -158
  79. package/dist/OperationGenerator-DhJ0MBKc.d.cts +0 -158
  80. package/dist/SchemaMapper-sGcY1xL5.d.cts +0 -247
  81. package/dist/SchemaMapper-sGcY1xL5.d.ts +0 -247
  82. package/dist/chunk-75BIOXB7.cjs +0 -7
  83. package/dist/chunk-75BIOXB7.cjs.map +0 -1
  84. package/dist/chunk-MUI5DWM3.js +0 -3966
  85. package/dist/chunk-MUI5DWM3.js.map +0 -1
  86. package/dist/chunk-N7EEVJA6.js +0 -35
  87. package/dist/chunk-N7EEVJA6.js.map +0 -1
  88. package/dist/chunk-NU4F7G47.cjs +0 -89
  89. package/dist/chunk-NU4F7G47.cjs.map +0 -1
  90. package/dist/chunk-O76YQFZB.cjs +0 -35
  91. package/dist/chunk-O76YQFZB.cjs.map +0 -1
  92. package/dist/chunk-SQ64ESS4.js +0 -7
  93. package/dist/chunk-SQ64ESS4.js.map +0 -1
  94. package/dist/chunk-SZDO532A.js +0 -89
  95. package/dist/chunk-SZDO532A.js.map +0 -1
  96. package/dist/chunk-VSVVTCQB.cjs +0 -3966
  97. package/dist/chunk-VSVVTCQB.cjs.map +0 -1
  98. package/dist/types-CZTUCaE5.d.cts +0 -145
  99. package/dist/types-CZTUCaE5.d.ts +0 -145
  100. package/src/utils/refSorter.ts +0 -13
@@ -1,4 +1,4 @@
1
- import { type FileMetaBase, Generator } from '@kubb/core'
1
+ import { BaseGenerator, type FileMetaBase } from '@kubb/core'
2
2
  import transformers from '@kubb/core/transformers'
3
3
 
4
4
  import type { PluginFactoryOptions, PluginManager } from '@kubb/core'
@@ -6,10 +6,13 @@ import type * as KubbFile from '@kubb/fs/types'
6
6
 
7
7
  import type { Plugin } from '@kubb/core'
8
8
  import type { HttpMethod, Oas, OasTypes, Operation, contentType } from '@kubb/oas'
9
+ import type { Generator } from './generator.tsx'
9
10
  import type { Exclude, Include, OperationSchemas, OperationsByMethod, Override } from './types.ts'
10
- import type { Parser } from './parser.tsx'
11
11
 
12
- export type GetOperationGeneratorOptions<T extends OperationGenerator<any, any, any>> = T extends OperationGenerator<infer Options, any, any> ? Options : never
12
+ /**
13
+ * @deprecated
14
+ */
15
+ export type GetOperationGeneratorOptions<T = any> = any
13
16
 
14
17
  export type OperationMethodResult<TFileMeta extends FileMetaBase> = Promise<KubbFile.File<TFileMeta> | Array<KubbFile.File<TFileMeta>> | null>
15
18
 
@@ -28,10 +31,9 @@ type Context<TOptions, TPluginOptions extends PluginFactoryOptions> = {
28
31
  }
29
32
 
30
33
  export class OperationGenerator<
31
- TOptions = unknown,
32
34
  TPluginOptions extends PluginFactoryOptions = PluginFactoryOptions,
33
35
  TFileMeta extends FileMetaBase = FileMetaBase,
34
- > extends Generator<TOptions, Context<TOptions, TPluginOptions>> {
36
+ > extends BaseGenerator<TPluginOptions['resolvedOptions'], Context<TPluginOptions['resolvedOptions'], TPluginOptions>> {
35
37
  #operationsByMethod: OperationsByMethod = {}
36
38
  get operationsByMethod(): OperationsByMethod {
37
39
  return this.#operationsByMethod
@@ -41,7 +43,7 @@ export class OperationGenerator<
41
43
  this.#operationsByMethod = paths
42
44
  }
43
45
 
44
- #getOptions(operation: Operation, method: HttpMethod): Partial<TOptions> {
46
+ #getOptions(operation: Operation, method: HttpMethod): Partial<TPluginOptions['resolvedOptions']> {
45
47
  const { override = [] } = this.context
46
48
 
47
49
  return (
@@ -67,10 +69,6 @@ export class OperationGenerator<
67
69
  )
68
70
  }
69
71
 
70
- /**
71
- *
72
- * @deprecated
73
- */
74
72
  #isExcluded(operation: Operation, method: HttpMethod): boolean {
75
73
  const { exclude = [] } = this.context
76
74
  let matched = false
@@ -96,10 +94,6 @@ export class OperationGenerator<
96
94
  return matched
97
95
  }
98
96
 
99
- /**
100
- *
101
- * @deprecated
102
- */
103
97
  #isIncluded(operation: Operation, method: HttpMethod): boolean {
104
98
  const { include = [] } = this.context
105
99
  let matched = false
@@ -128,10 +122,8 @@ export class OperationGenerator<
128
122
  getSchemas(
129
123
  operation: Operation,
130
124
  {
131
- forStatusCode,
132
125
  resolveName = (name) => name,
133
126
  }: {
134
- forStatusCode?: string | number
135
127
  resolveName?: (name: string) => string
136
128
  } = {},
137
129
  ): OperationSchemas {
@@ -139,8 +131,7 @@ export class OperationGenerator<
139
131
  const queryParamsSchema = this.context.oas.getParametersSchema(operation, 'query')
140
132
  const headerParamsSchema = this.context.oas.getParametersSchema(operation, 'header')
141
133
  const requestSchema = this.context.oas.getRequestSchema(operation)
142
- const responseStatusCode =
143
- forStatusCode || (operation.schema.responses && Object.keys(operation.schema.responses).find((key) => key.startsWith('2'))) || 200
134
+ const responseStatusCode = (operation.schema.responses && Object.keys(operation.schema.responses).find((key) => key.startsWith('2'))) || 200
144
135
  const responseSchema = this.context.oas.getResponseSchema(operation, responseStatusCode)
145
136
  const statusCodes = operation.getResponseStatusCodes().map((statusCode) => {
146
137
  let name = statusCode
@@ -226,7 +217,9 @@ export class OperationGenerator<
226
217
  }
227
218
  }
228
219
 
229
- async build(...parsers: Array<Parser<Extract<TOptions, PluginFactoryOptions>>>): Promise<Array<KubbFile.File<TFileMeta>>> {
220
+ #methods = ['get', 'post', 'patch', 'put', 'delete']
221
+
222
+ async build(...generators: Array<Generator<TPluginOptions>>): Promise<Array<KubbFile.File<TFileMeta>>> {
230
223
  const { oas } = this.context
231
224
 
232
225
  const paths = oas.getPaths()
@@ -235,7 +228,7 @@ export class OperationGenerator<
235
228
 
236
229
  methods.forEach((method) => {
237
230
  const operation = oas.operation(path, method)
238
- if (operation) {
231
+ if (operation && [this.#methods].some((methods) => method === operation.method)) {
239
232
  const isExcluded = this.#isExcluded(operation, method)
240
233
  const isIncluded = this.context.include ? this.#isIncluded(operation, method) : true
241
234
 
@@ -286,8 +279,8 @@ export class OperationGenerator<
286
279
  acc.push(promiseOperation)
287
280
  }
288
281
 
289
- parsers?.forEach((parser) => {
290
- const promise = parser.operation?.({
282
+ generators?.forEach((generator) => {
283
+ const promise = generator.operation?.({
291
284
  instance: this,
292
285
  operation,
293
286
  options: {
@@ -309,8 +302,8 @@ export class OperationGenerator<
309
302
 
310
303
  promises.push(this.all(operations.flat().filter(Boolean), this.operationsByMethod))
311
304
 
312
- parsers?.forEach((parser) => {
313
- const promise = parser.operations?.({
305
+ generators?.forEach((generator) => {
306
+ const promise = generator.operations?.({
314
307
  instance: this,
315
308
  operations: operations.flat().filter(Boolean),
316
309
  operationsByMethod: this.operationsByMethod,
@@ -331,41 +324,41 @@ export class OperationGenerator<
331
324
  /**
332
325
  * Operation
333
326
  */
334
- async operation(operation: Operation, options: TOptions): OperationMethodResult<TFileMeta> {
327
+ async operation(operation: Operation, options: TPluginOptions['resolvedOptions']): OperationMethodResult<TFileMeta> {
335
328
  return []
336
329
  }
337
330
 
338
331
  /**
339
332
  * GET
340
333
  */
341
- async get(operation: Operation, options: TOptions): OperationMethodResult<TFileMeta> {
334
+ async get(operation: Operation, options: TPluginOptions['resolvedOptions']): OperationMethodResult<TFileMeta> {
342
335
  return []
343
336
  }
344
337
 
345
338
  /**
346
339
  * POST
347
340
  */
348
- async post(operation: Operation, options: TOptions): OperationMethodResult<TFileMeta> {
341
+ async post(operation: Operation, options: TPluginOptions['resolvedOptions']): OperationMethodResult<TFileMeta> {
349
342
  return []
350
343
  }
351
344
  /**
352
345
  * PATCH
353
346
  */
354
- async patch(operation: Operation, options: TOptions): OperationMethodResult<TFileMeta> {
347
+ async patch(operation: Operation, options: TPluginOptions['resolvedOptions']): OperationMethodResult<TFileMeta> {
355
348
  return []
356
349
  }
357
350
 
358
351
  /**
359
352
  * PUT
360
353
  */
361
- async put(operation: Operation, options: TOptions): OperationMethodResult<TFileMeta> {
354
+ async put(operation: Operation, options: TPluginOptions['resolvedOptions']): OperationMethodResult<TFileMeta> {
362
355
  return []
363
356
  }
364
357
 
365
358
  /**
366
359
  * DELETE
367
360
  */
368
- async delete(operation: Operation, options: TOptions): OperationMethodResult<TFileMeta> {
361
+ async delete(operation: Operation, options: TPluginOptions['resolvedOptions']): OperationMethodResult<TFileMeta> {
369
362
  return []
370
363
  }
371
364
 
@@ -1,4 +1,4 @@
1
- import { type FileMetaBase, Generator } from '@kubb/core'
1
+ import { BaseGenerator, type FileMetaBase } from '@kubb/core'
2
2
  import transformers, { pascalCase } from '@kubb/core/transformers'
3
3
  import { getUniqueName } from '@kubb/core/utils'
4
4
 
@@ -13,7 +13,7 @@ import type * as KubbFile from '@kubb/fs/types'
13
13
 
14
14
  import type { Oas, OpenAPIV3, SchemaObject, contentType } from '@kubb/oas'
15
15
  import type { Schema, SchemaKeywordMapper } from './SchemaMapper.ts'
16
- import type { Parser } from './parser.tsx'
16
+ import type { Generator } from './generator.tsx'
17
17
  import type { OperationSchema, Override, Refs } from './types.ts'
18
18
 
19
19
  export type GetSchemaGeneratorOptions<T extends SchemaGenerator<any, any, any>> = T extends SchemaGenerator<infer Options, any, any> ? Options : never
@@ -68,7 +68,7 @@ export class SchemaGenerator<
68
68
  TOptions extends SchemaGeneratorOptions = SchemaGeneratorOptions,
69
69
  TPluginOptions extends PluginFactoryOptions = PluginFactoryOptions,
70
70
  TFileMeta extends FileMetaBase = FileMetaBase,
71
- > extends Generator<TOptions, Context<TOptions, TPluginOptions>> {
71
+ > extends BaseGenerator<TOptions, Context<TOptions, TPluginOptions>> {
72
72
  // Collect the types of all referenced schemas, so we can export them later
73
73
  refs: Refs = {}
74
74
 
@@ -302,7 +302,7 @@ export class SchemaGenerator<
302
302
 
303
303
  if (additionalProperties) {
304
304
  additionalPropertiesSchemas =
305
- additionalProperties === true
305
+ additionalProperties === true || !Object.keys(additionalProperties).length
306
306
  ? [{ keyword: this.#getUnknownReturn({ schema, name }) }]
307
307
  : this.parse({ schema: additionalProperties as SchemaObject, parentName: name })
308
308
  }
@@ -349,7 +349,7 @@ export class SchemaGenerator<
349
349
  const file = this.context.pluginManager.getFile({
350
350
  name: fileName,
351
351
  pluginKey: this.context.plugin.key,
352
- extName: '.ts',
352
+ extname: '.ts',
353
353
  })
354
354
 
355
355
  ref = this.refs[$ref] = {
@@ -379,12 +379,6 @@ export class SchemaGenerator<
379
379
  const options = this.#getOptions({ schema: _schema, name })
380
380
  const unknownReturn = this.#getUnknownReturn({ schema: _schema, name })
381
381
  const { schema, version } = this.#getParsedSchemaObject(_schema)
382
- const resolvedName = this.context.pluginManager.resolveName({
383
- name: `${parentName || ''} ${name}`,
384
- pluginKey: this.context.plugin.key,
385
- type: 'type',
386
- })
387
-
388
382
  if (!schema) {
389
383
  return [{ keyword: unknownReturn }]
390
384
  }
@@ -408,12 +402,16 @@ export class SchemaGenerator<
408
402
  keyword: schemaKeywords.default,
409
403
  args: transformers.stringify(schema.default),
410
404
  })
411
- }
412
- if (typeof schema.default === 'boolean') {
405
+ } else if (typeof schema.default === 'boolean') {
413
406
  baseItems.push({
414
407
  keyword: schemaKeywords.default,
415
408
  args: schema.default ?? false,
416
409
  })
410
+ } else {
411
+ baseItems.push({
412
+ keyword: schemaKeywords.default,
413
+ args: schema.default,
414
+ })
417
415
  }
418
416
  }
419
417
 
@@ -455,10 +453,16 @@ export class SchemaGenerator<
455
453
  baseItems.push({ keyword: schemaKeywords.readOnly })
456
454
  }
457
455
 
456
+ if (schema.writeOnly) {
457
+ baseItems.push({ keyword: schemaKeywords.writeOnly })
458
+ }
459
+
458
460
  if (isReference(schema)) {
459
461
  return [
460
462
  ...this.#getRefAlias(schema),
461
463
  nullable && { keyword: schemaKeywords.nullable },
464
+ schema.readOnly && { keyword: schemaKeywords.readOnly },
465
+ schema.writeOnly && { keyword: schemaKeywords.writeOnly },
462
466
  {
463
467
  keyword: schemaKeywords.schema,
464
468
  args: {
@@ -485,7 +489,20 @@ export class SchemaGenerator<
485
489
  }),
486
490
  }
487
491
  if (schemaWithoutOneOf.properties) {
488
- return [...this.parse({ schema: schemaWithoutOneOf, name, parentName }), union, ...baseItems]
492
+ const propertySchemas = this.parse({ schema: schemaWithoutOneOf, name, parentName })
493
+
494
+ return [
495
+ {
496
+ ...union,
497
+ args: union.args.map((arg) => {
498
+ return {
499
+ keyword: schemaKeywords.and,
500
+ args: [arg, ...propertySchemas],
501
+ }
502
+ }),
503
+ },
504
+ ...baseItems,
505
+ ]
489
506
  }
490
507
 
491
508
  return [union, ...baseItems]
@@ -620,6 +637,35 @@ export class SchemaGenerator<
620
637
  ]
621
638
  }
622
639
 
640
+ if (schema.type === 'boolean') {
641
+ // we cannot use z.enum when enum type is boolean
642
+ const enumNames = extensionEnums[0]?.find((item) => isKeyword(item, schemaKeywords.enum)) as unknown as SchemaKeywordMapper['enum']
643
+ return [
644
+ {
645
+ keyword: schemaKeywords.enum,
646
+ args: {
647
+ name: enumName,
648
+ typeName,
649
+ asConst: true,
650
+ items: enumNames?.args?.items
651
+ ? [...new Set(enumNames.args.items)].map(({ name, value }) => ({
652
+ name,
653
+ value,
654
+ format: 'boolean',
655
+ }))
656
+ : [...new Set(filteredValues)].map((value: string) => {
657
+ return {
658
+ name: value,
659
+ value,
660
+ format: 'boolean',
661
+ }
662
+ }),
663
+ },
664
+ },
665
+ ...baseItems.filter((item) => item.keyword !== schemaKeywords.matches),
666
+ ]
667
+ }
668
+
623
669
  if (extensionEnums.length > 0 && extensionEnums[0]) {
624
670
  return extensionEnums[0]
625
671
  }
@@ -810,7 +856,7 @@ export class SchemaGenerator<
810
856
  ].filter(Boolean)
811
857
  }
812
858
 
813
- if (!['boolean', 'object', 'number', 'string', 'integer'].includes(schema.type)) {
859
+ if (!['boolean', 'object', 'number', 'string', 'integer', 'null'].includes(schema.type)) {
814
860
  this.context.pluginManager.logger.emit('warning', `Schema type '${schema.type}' is not valid for schema ${parentName}.${name}`)
815
861
  }
816
862
 
@@ -821,14 +867,20 @@ export class SchemaGenerator<
821
867
  return [{ keyword: unknownReturn }]
822
868
  }
823
869
 
824
- async build(...parsers: Array<Parser<Extract<TOptions, PluginFactoryOptions>>>): Promise<Array<KubbFile.File<TFileMeta>>> {
870
+ async build(...generators: Array<Generator<TPluginOptions>>): Promise<Array<KubbFile.File<TFileMeta>>> {
825
871
  const { oas, contentType, include } = this.context
826
872
 
873
+ oas.resolveDiscriminators()
874
+
827
875
  const schemas = getSchemas({ oas, contentType, includes: include })
828
876
 
829
- const promises = Object.entries(schemas).reduce((acc, [name, schema]) => {
877
+ const promises = Object.entries(schemas).reduce((acc, [name, value]) => {
878
+ if (!value) {
879
+ return acc
880
+ }
881
+
830
882
  const options = this.#getOptions({ name })
831
- const promiseOperation = this.schema.call(this, name, schema, {
883
+ const promiseOperation = this.schema.call(this, name, value, {
832
884
  ...this.options,
833
885
  ...options,
834
886
  })
@@ -837,11 +889,16 @@ export class SchemaGenerator<
837
889
  acc.push(promiseOperation)
838
890
  }
839
891
 
840
- parsers?.forEach((parser) => {
841
- const promise = parser.schema?.({
892
+ generators?.forEach((generator) => {
893
+ const tree = this.parse({ schema: value, name: name })
894
+
895
+ const promise = generator.schema?.({
842
896
  instance: this,
843
- name,
844
- schema,
897
+ schema: {
898
+ name,
899
+ value,
900
+ tree,
901
+ },
845
902
  options: {
846
903
  ...this.options,
847
904
  ...options,
@@ -12,6 +12,7 @@ export type SchemaKeywordMapper = {
12
12
  strict: { keyword: 'strict' }
13
13
  url: { keyword: 'url' }
14
14
  readOnly: { keyword: 'readOnly' }
15
+ writeOnly: { keyword: 'writeOnly' }
15
16
  uuid: { keyword: 'uuid' }
16
17
  email: { keyword: 'email' }
17
18
  firstName: { keyword: 'firstName' }
@@ -34,8 +35,8 @@ export type SchemaKeywordMapper = {
34
35
  asConst: boolean
35
36
  items: Array<{
36
37
  name: string | number
37
- format: 'string' | 'number'
38
- value?: string | number
38
+ format: 'string' | 'number' | 'boolean'
39
+ value?: string | number | boolean
39
40
  }>
40
41
  }
41
42
  }
@@ -44,8 +45,8 @@ export type SchemaKeywordMapper = {
44
45
  keyword: 'const'
45
46
  args: {
46
47
  name: string | number
47
- format: 'string' | 'number'
48
- value?: string | number
48
+ format: 'string' | 'number' | 'boolean'
49
+ value?: string | number | boolean
49
50
  }
50
51
  }
51
52
  union: { keyword: 'union'; args: Schema[] }
@@ -107,6 +108,7 @@ export const schemaKeywords = {
107
108
  max: 'max',
108
109
  optional: 'optional',
109
110
  readOnly: 'readOnly',
111
+ writeOnly: 'writeOnly',
110
112
 
111
113
  // custom ones
112
114
  object: 'object',
@@ -1,15 +1,8 @@
1
- import { File, createContext, useApp, useFile } from '@kubb/react'
1
+ import { createContext } from '@kubb/react'
2
2
 
3
- import { schemaKeywords } from '../SchemaMapper.ts'
4
- import { useSchema } from '../hooks/useSchema.ts'
5
-
6
- import type * as KubbFile from '@kubb/fs/types'
7
3
  import type { SchemaObject } from '@kubb/oas'
8
4
  import type { KubbNode } from '@kubb/react/types'
9
- import type { ReactNode } from 'react'
10
- import { SchemaGenerator } from '../SchemaGenerator.ts'
11
5
  import type { Schema as SchemaType } from '../SchemaMapper.ts'
12
- import type { PluginOas } from '../types.ts'
13
6
 
14
7
  export type SchemaContextProps = {
15
8
  name: string
@@ -33,95 +26,4 @@ export function Schema({ name, value, tree = [], children }: Props): KubbNode {
33
26
  return <SchemaContext.Provider value={{ name, schema: value, tree }}>{children}</SchemaContext.Provider>
34
27
  }
35
28
 
36
- type FileProps = {
37
- isTypeOnly?: boolean
38
- output: string | undefined
39
- children?: KubbNode
40
- }
41
-
42
- Schema.File = function ({ output, isTypeOnly, children }: FileProps): ReactNode {
43
- const { plugin, pluginManager, mode } = useApp<PluginOas>()
44
- const { name } = useSchema()
45
-
46
- if (mode === 'single') {
47
- const baseName = `${pluginManager.resolveName({
48
- name,
49
- pluginKey: plugin.key,
50
- type: 'file',
51
- })}.ts` as const
52
-
53
- const resolvedPath = pluginManager.resolvePath({
54
- baseName: '',
55
- pluginKey: plugin.key,
56
- })
57
-
58
- if (!resolvedPath) {
59
- return null
60
- }
61
-
62
- return (
63
- <File
64
- baseName={baseName}
65
- path={resolvedPath}
66
- meta={{
67
- pluginKey: plugin.key,
68
- }}
69
- >
70
- {children}
71
- </File>
72
- )
73
- }
74
-
75
- const baseName = `${pluginManager.resolveName({
76
- name,
77
- pluginKey: plugin.key,
78
- type: 'file',
79
- })}.ts` as const
80
- const resolvedPath = pluginManager.resolvePath({
81
- baseName,
82
- pluginKey: plugin.key,
83
- })
84
-
85
- if (!resolvedPath) {
86
- return null
87
- }
88
-
89
- return (
90
- <File
91
- baseName={baseName}
92
- path={resolvedPath}
93
- meta={{
94
- pluginKey: plugin.key,
95
- }}
96
- >
97
- <Schema.Imports isTypeOnly={isTypeOnly} />
98
- {children}
99
- </File>
100
- )
101
- }
102
-
103
- type SchemaImportsProps = {
104
- isTypeOnly?: boolean
105
- }
106
-
107
- Schema.Imports = ({ isTypeOnly }: SchemaImportsProps): ReactNode => {
108
- const { tree } = useSchema()
109
- const { path: root } = useFile()
110
-
111
- const refs = SchemaGenerator.deepSearch(tree, schemaKeywords.ref)
112
-
113
- return (
114
- <>
115
- {refs
116
- ?.map((item, i) => {
117
- if (!item.args.path) {
118
- return undefined
119
- }
120
-
121
- return <File.Import key={i} root={root} name={[item.args.name]} path={item.args.path} isTypeOnly={isTypeOnly} />
122
- })
123
- .filter(Boolean)}
124
- </>
125
- )
126
- }
127
29
  Schema.Context = SchemaContext
@@ -1,12 +1,13 @@
1
1
  import type { PluginFactoryOptions } from '@kubb/core'
2
+ import type * as KubbFile from '@kubb/fs/types'
2
3
  import type { Operation, SchemaObject } from '@kubb/oas'
4
+ import { Oas } from '@kubb/plugin-oas/components'
3
5
  import { App, createRoot } from '@kubb/react'
4
6
  import type { KubbNode } from '@kubb/react/types'
5
- import type * as KubbFile from '@kubb/fs/types'
6
- import type { OperationsByMethod } from './types.ts'
7
- import { Oas } from '@kubb/plugin-oas/components'
8
7
  import type { OperationGenerator } from './OperationGenerator.ts'
9
8
  import type { SchemaGenerator, SchemaGeneratorOptions } from './SchemaGenerator.ts'
9
+ import type { Schema } from './SchemaMapper.ts'
10
+ import type { OperationsByMethod } from './types.ts'
10
11
 
11
12
  type OperationsProps<TOptions extends PluginFactoryOptions> = {
12
13
  instance: Omit<OperationGenerator<TOptions>, 'build'>
@@ -23,32 +24,35 @@ type OperationProps<TOptions extends PluginFactoryOptions> = {
23
24
 
24
25
  type SchemaProps<TOptions extends PluginFactoryOptions> = {
25
26
  instance: Omit<SchemaGenerator<SchemaGeneratorOptions, TOptions>, 'build'>
26
- name: string
27
- schema: SchemaObject
27
+ schema: {
28
+ name: string
29
+ tree: Array<Schema>
30
+ value: SchemaObject
31
+ }
28
32
  options: TOptions['resolvedOptions']
29
33
  }
30
34
 
31
- export type ParserOptions<TOptions extends PluginFactoryOptions> = {
35
+ export type GeneratorOptions<TOptions extends PluginFactoryOptions> = {
32
36
  name: string
33
- operations?: (props: OperationsProps<TOptions>) => Promise<KubbFile.File[]>
34
- operation?: (props: OperationProps<TOptions>) => Promise<KubbFile.File[]>
35
- schema?: (props: SchemaProps<TOptions>) => Promise<KubbFile.File[]>
37
+ operations?: (this: GeneratorOptions<TOptions>, props: OperationsProps<TOptions>) => Promise<KubbFile.File[]>
38
+ operation?: (this: GeneratorOptions<TOptions>, props: OperationProps<TOptions>) => Promise<KubbFile.File[]>
39
+ schema?: (this: GeneratorOptions<TOptions>, props: SchemaProps<TOptions>) => Promise<KubbFile.File[]>
36
40
  }
37
41
 
38
- export type Parser<TOptions extends PluginFactoryOptions> = ParserOptions<TOptions>
42
+ export type Generator<TOptions extends PluginFactoryOptions> = GeneratorOptions<TOptions>
39
43
 
40
- export function createParser<TOptions extends PluginFactoryOptions>(parseOptions: ParserOptions<TOptions>): Parser<TOptions> {
44
+ export function createGenerator<TOptions extends PluginFactoryOptions>(parseOptions: GeneratorOptions<TOptions>): Generator<TOptions> {
41
45
  return parseOptions
42
46
  }
43
47
 
44
- export type ParserReactOptions<TOptions extends PluginFactoryOptions> = {
48
+ export type ReactGeneratorOptions<TOptions extends PluginFactoryOptions> = {
45
49
  name: string
46
- Operations?: (props: OperationsProps<TOptions>) => KubbNode
47
- Operation?: (props: OperationProps<TOptions>) => KubbNode
48
- Schema?: (props: SchemaProps<TOptions>) => KubbNode
50
+ Operations?: (this: ReactGeneratorOptions<TOptions>, props: OperationsProps<TOptions>) => KubbNode
51
+ Operation?: (this: ReactGeneratorOptions<TOptions>, props: OperationProps<TOptions>) => KubbNode
52
+ Schema?: (this: ReactGeneratorOptions<TOptions>, props: SchemaProps<TOptions>) => KubbNode
49
53
  }
50
54
 
51
- export function createReactParser<TOptions extends PluginFactoryOptions>(parseOptions: ParserReactOptions<TOptions>): Parser<TOptions> {
55
+ export function createReactGenerator<TOptions extends PluginFactoryOptions>(parseOptions: ReactGeneratorOptions<TOptions>): Generator<TOptions> {
52
56
  return {
53
57
  ...parseOptions,
54
58
  async operations({ instance, options, operations, operationsByMethod }) {
@@ -61,10 +65,12 @@ export function createReactParser<TOptions extends PluginFactoryOptions>(parseOp
61
65
  logger: pluginManager.logger,
62
66
  })
63
67
 
68
+ const Component = parseOptions.Operations.bind(this)
69
+
64
70
  root.render(
65
71
  <App pluginManager={pluginManager} plugin={plugin} mode={mode}>
66
72
  <Oas oas={oas} operations={operations} generator={instance}>
67
- <parseOptions.Operations operations={operations} instance={instance} operationsByMethod={operationsByMethod} options={options} />
73
+ <Component operations={operations} instance={instance} operationsByMethod={operationsByMethod} options={options} />
68
74
  </Oas>
69
75
  </App>,
70
76
  )
@@ -81,11 +87,13 @@ export function createReactParser<TOptions extends PluginFactoryOptions>(parseOp
81
87
  logger: pluginManager.logger,
82
88
  })
83
89
 
90
+ const Component = parseOptions.Operation.bind(this)
91
+
84
92
  root.render(
85
93
  <App pluginManager={pluginManager} plugin={{ ...plugin, options }} mode={mode}>
86
94
  <Oas oas={oas} operations={[operation]} generator={instance}>
87
95
  <Oas.Operation operation={operation}>
88
- <parseOptions.Operation operation={operation} options={options} instance={instance} />
96
+ <Component operation={operation} options={options} instance={instance} />
89
97
  </Oas.Operation>
90
98
  </Oas>
91
99
  </App>,
@@ -93,7 +101,7 @@ export function createReactParser<TOptions extends PluginFactoryOptions>(parseOp
93
101
 
94
102
  return root.files
95
103
  },
96
- async schema({ instance, schema, name, options }) {
104
+ async schema({ instance, schema, options }) {
97
105
  if (!parseOptions.Schema) {
98
106
  return []
99
107
  }
@@ -103,13 +111,13 @@ export function createReactParser<TOptions extends PluginFactoryOptions>(parseOp
103
111
  logger: pluginManager.logger,
104
112
  })
105
113
 
106
- const tree = instance.parse({ schema, name })
114
+ const Component = parseOptions.Schema.bind(this)
107
115
 
108
116
  root.render(
109
117
  <App pluginManager={pluginManager} plugin={{ ...plugin, options }} mode={mode}>
110
118
  <Oas oas={oas}>
111
- <Oas.Schema name={name} value={schema} tree={tree}>
112
- <parseOptions.Schema schema={schema} options={options} instance={instance} name={name} />
119
+ <Oas.Schema name={schema.name} value={schema.value} tree={schema.tree}>
120
+ <Component schema={schema} options={options} instance={instance} />
113
121
  </Oas.Schema>
114
122
  </Oas>
115
123
  </App>,
@@ -0,0 +1 @@
1
+ export { jsonGenerator } from './jsonGenerator.ts'
@@ -0,0 +1,32 @@
1
+ import { camelCase } from '@kubb/core/transformers'
2
+ import { createGenerator } from '../generator.tsx'
3
+ import type { PluginOas } from '../types.ts'
4
+
5
+ export const jsonGenerator = createGenerator<PluginOas>({
6
+ name: 'plugin-oas',
7
+ async schema({ schema, instance }) {
8
+ const { pluginManager, plugin } = instance.context
9
+ const file = pluginManager.getFile({
10
+ name: camelCase(schema.name),
11
+ extname: '.json',
12
+ mode: 'split',
13
+ pluginKey: plugin.key,
14
+ })
15
+
16
+ return [
17
+ {
18
+ ...file,
19
+ sources: [
20
+ {
21
+ name: camelCase(schema.name),
22
+ isExportable: false,
23
+ isIndexable: false,
24
+ value: JSON.stringify(schema.value),
25
+ },
26
+ ],
27
+ banner: plugin.options.output?.banner,
28
+ format: plugin.options.output?.footer,
29
+ },
30
+ ]
31
+ },
32
+ })
@@ -1,5 +1,7 @@
1
1
  export { useOas } from './useOas.ts'
2
2
  export { useOperation } from './useOperation.ts'
3
3
  export { useOperationManager } from './useOperationManager.ts'
4
+ export type { SchemaNames } from './useOperationManager.ts'
4
5
  export { useOperations } from './useOperations.ts'
5
6
  export { useSchema } from './useSchema.ts'
7
+ export { useSchemaManager } from './useSchemaManager.ts'