@kubb/plugin-oas 4.33.0 → 4.33.2
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/{SchemaMapper-CEvL7_hg.cjs → SchemaMapper-CeavHZlp.cjs} +1 -1
- package/dist/{SchemaMapper-CEvL7_hg.cjs.map → SchemaMapper-CeavHZlp.cjs.map} +1 -1
- package/dist/{SchemaMapper-ClUmzpCc.js → SchemaMapper-CqMkO2T1.js} +1 -1
- package/dist/{SchemaMapper-ClUmzpCc.js.map → SchemaMapper-CqMkO2T1.js.map} +1 -1
- package/dist/{createGenerator-BPVBbTHR.d.ts → createGenerator-Z5-TQKKC.d.ts} +44 -8
- package/dist/{generators-BvfaSMp3.cjs → generators-CBlzDhTh.cjs} +4 -5
- package/dist/generators-CBlzDhTh.cjs.map +1 -0
- package/dist/{generators-BrYP9z4D.js → generators-DRPPf38p.js} +2 -3
- package/dist/{generators-BrYP9z4D.js.map → generators-DRPPf38p.js.map} +1 -1
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +1 -1
- package/dist/generators.js +1 -1
- package/dist/getFooter-BBzsC616.cjs +136 -0
- package/dist/getFooter-BBzsC616.cjs.map +1 -0
- package/dist/getFooter-Pw3tLCiV.js +112 -0
- package/dist/getFooter-Pw3tLCiV.js.map +1 -0
- package/dist/hooks.cjs +2 -2
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +2 -2
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +60 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +47 -57
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +1 -1
- package/dist/mocks.js +1 -1
- package/dist/{resolveServerUrl-sGGjx0hA.js → requestBody-C0-TOJVO.js} +111 -49
- package/dist/requestBody-C0-TOJVO.js.map +1 -0
- package/dist/{resolveServerUrl-CxAWmztf.cjs → requestBody-DTUm-tGf.cjs} +111 -56
- package/dist/requestBody-DTUm-tGf.cjs.map +1 -0
- package/dist/utils.cjs +139 -25
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.ts +3 -21
- package/dist/utils.js +130 -14
- package/dist/utils.js.map +1 -1
- package/package.json +5 -4
- package/src/OperationGenerator.ts +56 -79
- package/src/SchemaGenerator.ts +50 -29
- package/src/generators/jsonGenerator.ts +1 -1
- package/src/hooks/useOperationManager.ts +2 -2
- package/src/plugin.ts +4 -13
- package/src/types.ts +1 -1
- package/src/utils/getComments.ts +3 -6
- package/src/utils/getImports.ts +5 -3
- package/src/utils/getParams.ts +2 -2
- package/src/utils/index.ts +0 -1
- package/src/utils/paramsCasing.ts +5 -5
- package/src/utils/requestBody.ts +7 -1
- package/dist/generators-BvfaSMp3.cjs.map +0 -1
- package/dist/getFooter-DGVGGyRc.js +0 -57
- package/dist/getFooter-DGVGGyRc.js.map +0 -1
- package/dist/getFooter-WAZDOcmk.cjs +0 -69
- package/dist/getFooter-WAZDOcmk.cjs.map +0 -1
- package/dist/resolveServerUrl-CxAWmztf.cjs.map +0 -1
- package/dist/resolveServerUrl-sGGjx0hA.js.map +0 -1
- package/src/utils/resolveServerUrl.ts +0 -37
package/src/SchemaGenerator.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import transformers, { pascalCase } from '@kubb/core/transformers'
|
|
4
|
-
import { type AsyncEventEmitter, getUniqueName } from '@kubb/core/utils'
|
|
1
|
+
import { type AsyncEventEmitter, getUniqueName, pascalCase, stringify } from '@internals/utils'
|
|
2
|
+
import type { FileMetaBase, KubbEvents, Plugin, PluginFactoryOptions, PluginManager, ResolveNameParams } from '@kubb/core'
|
|
5
3
|
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
6
4
|
import type { contentType, Oas, OasTypes, OpenAPIV3, SchemaObject } from '@kubb/oas'
|
|
7
|
-
import { isDiscriminator, isNullable, isReference } from '@kubb/oas'
|
|
5
|
+
import { isDiscriminator, isNullable, isReference, KUBB_INLINE_REF_PREFIX } from '@kubb/oas'
|
|
8
6
|
import type { Fabric } from '@kubb/react-fabric'
|
|
9
7
|
import pLimit from 'p-limit'
|
|
10
8
|
import { isDeepEqual, isNumber, uniqueWith } from 'remeda'
|
|
@@ -18,6 +16,11 @@ export type GetSchemaGeneratorOptions<T extends SchemaGenerator<any, any, any>>
|
|
|
18
16
|
|
|
19
17
|
export type SchemaMethodResult<TFileMeta extends FileMetaBase> = Promise<KubbFile.File<TFileMeta> | Array<KubbFile.File<TFileMeta>> | null>
|
|
20
18
|
|
|
19
|
+
/** Max concurrent generator tasks (across generators). */
|
|
20
|
+
const GENERATOR_CONCURRENCY = 3
|
|
21
|
+
/** Max concurrent schema parsing tasks (per generator). */
|
|
22
|
+
const SCHEMA_CONCURRENCY = 30
|
|
23
|
+
|
|
21
24
|
type Context<TOptions, TPluginOptions extends PluginFactoryOptions> = {
|
|
22
25
|
fabric: Fabric
|
|
23
26
|
oas: Oas
|
|
@@ -55,8 +58,8 @@ export type SchemaGeneratorOptions = {
|
|
|
55
58
|
*/
|
|
56
59
|
name?: (name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
|
|
57
60
|
/**
|
|
58
|
-
* Receive schema and name(propertyName) and return
|
|
59
|
-
*
|
|
61
|
+
* Receive schema and name(propertyName) and return Schema array.
|
|
62
|
+
* Return `undefined` to fall through to default schema generation.
|
|
60
63
|
* @beta
|
|
61
64
|
*/
|
|
62
65
|
schema?: (schemaProps: SchemaProps, defaultSchemas: Schema[]) => Array<Schema> | undefined
|
|
@@ -76,7 +79,26 @@ export class SchemaGenerator<
|
|
|
76
79
|
TOptions extends SchemaGeneratorOptions = SchemaGeneratorOptions,
|
|
77
80
|
TPluginOptions extends PluginFactoryOptions = PluginFactoryOptions,
|
|
78
81
|
TFileMeta extends FileMetaBase = FileMetaBase,
|
|
79
|
-
>
|
|
82
|
+
> {
|
|
83
|
+
#options: TOptions
|
|
84
|
+
#context: Context<TOptions, TPluginOptions>
|
|
85
|
+
|
|
86
|
+
constructor(options: TOptions, context: Context<TOptions, TPluginOptions>) {
|
|
87
|
+
this.#options = options
|
|
88
|
+
this.#context = context
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get options(): TOptions {
|
|
92
|
+
return this.#options
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
set options(options: TOptions) {
|
|
96
|
+
this.#options = { ...this.#options, ...options }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get context(): Context<TOptions, TPluginOptions> {
|
|
100
|
+
return this.#context
|
|
101
|
+
}
|
|
80
102
|
// Collect the types of all referenced schemas, so we can export them later
|
|
81
103
|
refs: Refs = {}
|
|
82
104
|
|
|
@@ -559,8 +581,8 @@ export class SchemaGenerator<
|
|
|
559
581
|
let arg: Schema | undefined
|
|
560
582
|
|
|
561
583
|
// Check if this is a synthetic ref for inline schemas (e.g., #kubb-inline-0)
|
|
562
|
-
if (value.startsWith(
|
|
563
|
-
const index = Number.parseInt(value.replace(
|
|
584
|
+
if (value.startsWith(KUBB_INLINE_REF_PREFIX)) {
|
|
585
|
+
const index = Number.parseInt(value.replace(KUBB_INLINE_REF_PREFIX, ''), 10)
|
|
564
586
|
// Validate index is within bounds
|
|
565
587
|
if (!Number.isNaN(index) && index >= 0 && index < schema.args.length) {
|
|
566
588
|
arg = schema.args[index]
|
|
@@ -667,7 +689,7 @@ export class SchemaGenerator<
|
|
|
667
689
|
{
|
|
668
690
|
keyword: schemaKeywords.schema,
|
|
669
691
|
args: {
|
|
670
|
-
type: schemaObject.type as
|
|
692
|
+
type: schemaObject.type as SchemaKeywordMapper['schema']['args']['type'],
|
|
671
693
|
format: schemaObject.format,
|
|
672
694
|
},
|
|
673
695
|
},
|
|
@@ -685,7 +707,7 @@ export class SchemaGenerator<
|
|
|
685
707
|
if (typeof schemaObject.default === 'string') {
|
|
686
708
|
baseItems.push({
|
|
687
709
|
keyword: schemaKeywords.default,
|
|
688
|
-
args:
|
|
710
|
+
args: stringify(schemaObject.default),
|
|
689
711
|
})
|
|
690
712
|
} else if (typeof schemaObject.default === 'boolean') {
|
|
691
713
|
baseItems.push({
|
|
@@ -759,7 +781,7 @@ export class SchemaGenerator<
|
|
|
759
781
|
rootName,
|
|
760
782
|
})[0],
|
|
761
783
|
)
|
|
762
|
-
.filter(Boolean)
|
|
784
|
+
.filter((x): x is Schema => Boolean(x))
|
|
763
785
|
.map((item) => (isKeyword(item, schemaKeywords.object) ? { ...item, args: { ...item.args, strict: true } } : item)),
|
|
764
786
|
},
|
|
765
787
|
]
|
|
@@ -779,6 +801,7 @@ export class SchemaGenerator<
|
|
|
779
801
|
if (isReference(schemaObject)) {
|
|
780
802
|
return [
|
|
781
803
|
...this.#getRefAlias(schemaObject, name),
|
|
804
|
+
...baseItems.filter((item) => item.keyword === schemaKeywords.default),
|
|
782
805
|
schemaObject.description && {
|
|
783
806
|
keyword: schemaKeywords.describe,
|
|
784
807
|
args: schemaObject.description,
|
|
@@ -794,11 +817,11 @@ export class SchemaGenerator<
|
|
|
794
817
|
{
|
|
795
818
|
keyword: schemaKeywords.schema,
|
|
796
819
|
args: {
|
|
797
|
-
type: schemaObject.type as
|
|
820
|
+
type: schemaObject.type as SchemaKeywordMapper['schema']['args']['type'],
|
|
798
821
|
format: schemaObject.format,
|
|
799
822
|
},
|
|
800
823
|
},
|
|
801
|
-
].filter(Boolean)
|
|
824
|
+
].filter((x): x is Schema => Boolean(x))
|
|
802
825
|
}
|
|
803
826
|
|
|
804
827
|
if (schemaObject.oneOf || schemaObject.anyOf) {
|
|
@@ -813,7 +836,7 @@ export class SchemaGenerator<
|
|
|
813
836
|
// first item, this is ref
|
|
814
837
|
return item && this.parse({ schema: item as SchemaObject, name, parentName, rootName })[0]
|
|
815
838
|
})
|
|
816
|
-
.filter(Boolean),
|
|
839
|
+
.filter((x): x is Schema => Boolean(x)),
|
|
817
840
|
}
|
|
818
841
|
|
|
819
842
|
if (discriminator) {
|
|
@@ -967,7 +990,7 @@ export class SchemaGenerator<
|
|
|
967
990
|
typeName,
|
|
968
991
|
asConst: false,
|
|
969
992
|
items: [...new Set(schemaObject[extensionKey as keyof typeof schemaObject] as string[])].map((name: string | number, index) => ({
|
|
970
|
-
name:
|
|
993
|
+
name: stringify(name),
|
|
971
994
|
value: schemaObject.enum?.[index] as string | number,
|
|
972
995
|
format: isNumber(schemaObject.enum?.[index]) ? 'number' : 'string',
|
|
973
996
|
})),
|
|
@@ -1049,7 +1072,7 @@ export class SchemaGenerator<
|
|
|
1049
1072
|
typeName,
|
|
1050
1073
|
asConst: false,
|
|
1051
1074
|
items: [...new Set(filteredValues)].map((value: string) => ({
|
|
1052
|
-
name:
|
|
1075
|
+
name: stringify(value),
|
|
1053
1076
|
value,
|
|
1054
1077
|
format: isNumber(value) ? 'number' : 'string',
|
|
1055
1078
|
})),
|
|
@@ -1075,7 +1098,7 @@ export class SchemaGenerator<
|
|
|
1075
1098
|
.map((item) => {
|
|
1076
1099
|
return this.parse({ schema: item, name, parentName, rootName })[0]
|
|
1077
1100
|
})
|
|
1078
|
-
.filter(Boolean),
|
|
1101
|
+
.filter((x): x is Schema => Boolean(x)),
|
|
1079
1102
|
rest: this.parse({
|
|
1080
1103
|
schema: items,
|
|
1081
1104
|
name,
|
|
@@ -1126,7 +1149,7 @@ export class SchemaGenerator<
|
|
|
1126
1149
|
* see also https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.7
|
|
1127
1150
|
*/
|
|
1128
1151
|
// Handle OpenAPI 3.1 contentMediaType for binary data
|
|
1129
|
-
if (schemaObject.type === 'string' && (schemaObject as
|
|
1152
|
+
if (schemaObject.type === 'string' && (schemaObject as SchemaObject & { contentMediaType?: string }).contentMediaType === 'application/octet-stream') {
|
|
1130
1153
|
baseItems.unshift({ keyword: schemaKeywords.blob })
|
|
1131
1154
|
return baseItems
|
|
1132
1155
|
}
|
|
@@ -1257,22 +1280,23 @@ export class SchemaGenerator<
|
|
|
1257
1280
|
if (schemaObject.properties || schemaObject.additionalProperties || 'patternProperties' in schemaObject) {
|
|
1258
1281
|
if (isDiscriminator(schemaObject)) {
|
|
1259
1282
|
// override schema to set type to be based on discriminator mapping, use of enum to convert type string to type 'mapping1' | 'mapping2'
|
|
1260
|
-
const schemaObjectOverridden = Object.keys(schemaObject.properties || {}).reduce((acc, propertyName) => {
|
|
1283
|
+
const schemaObjectOverridden = Object.keys(schemaObject.properties || {}).reduce<SchemaObject>((acc, propertyName) => {
|
|
1261
1284
|
if (acc.properties?.[propertyName] && propertyName === schemaObject.discriminator.propertyName) {
|
|
1285
|
+
const existingProperty = acc.properties[propertyName] as SchemaObject
|
|
1262
1286
|
return {
|
|
1263
1287
|
...acc,
|
|
1264
1288
|
properties: {
|
|
1265
1289
|
...acc.properties,
|
|
1266
1290
|
[propertyName]: {
|
|
1267
|
-
...
|
|
1291
|
+
...existingProperty,
|
|
1268
1292
|
enum: schemaObject.discriminator.mapping ? Object.keys(schemaObject.discriminator.mapping) : undefined,
|
|
1269
1293
|
},
|
|
1270
1294
|
},
|
|
1271
|
-
}
|
|
1295
|
+
} as SchemaObject
|
|
1272
1296
|
}
|
|
1273
1297
|
|
|
1274
1298
|
return acc
|
|
1275
|
-
}, schemaObject
|
|
1299
|
+
}, schemaObject as SchemaObject)
|
|
1276
1300
|
|
|
1277
1301
|
return [...this.#parseProperties(name, schemaObjectOverridden, rootName), ...baseItems]
|
|
1278
1302
|
}
|
|
@@ -1337,11 +1361,8 @@ export class SchemaGenerator<
|
|
|
1337
1361
|
async #doBuild(schemas: Record<string, OasTypes.SchemaObject>, generators: Array<Generator<TPluginOptions>>): Promise<Array<KubbFile.File<TFileMeta>>> {
|
|
1338
1362
|
const schemaEntries = Object.entries(schemas)
|
|
1339
1363
|
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
// - schemaLimit increased from 10 to 30 to process more schemas concurrently
|
|
1343
|
-
const generatorLimit = pLimit(3)
|
|
1344
|
-
const schemaLimit = pLimit(30)
|
|
1364
|
+
const generatorLimit = pLimit(GENERATOR_CONCURRENCY)
|
|
1365
|
+
const schemaLimit = pLimit(SCHEMA_CONCURRENCY)
|
|
1345
1366
|
|
|
1346
1367
|
const writeTasks = generators.map((generator) =>
|
|
1347
1368
|
generatorLimit(async () => {
|
|
@@ -85,7 +85,7 @@ export function useOperationManager<TPluginOptions extends PluginFactoryOptions
|
|
|
85
85
|
|
|
86
86
|
const getSchemas: UseOperationManagerResult['getSchemas'] = (operation, params) => {
|
|
87
87
|
if (!generator) {
|
|
88
|
-
throw new Error(`'generator' is not
|
|
88
|
+
throw new Error(`useOperationManager: 'generator' parameter is required but was not provided`)
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
return generator.getSchemas(operation, {
|
|
@@ -122,7 +122,7 @@ export function useOperationManager<TPluginOptions extends PluginFactoryOptions
|
|
|
122
122
|
|
|
123
123
|
const groupSchemasByName: UseOperationManagerResult['groupSchemasByName'] = (operation, { pluginKey = plugin.key, type }) => {
|
|
124
124
|
if (!generator) {
|
|
125
|
-
throw new Error(`'generator' is not
|
|
125
|
+
throw new Error(`useOperationManager: 'generator' parameter is required but was not provided`)
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
const schemas = generator.getSchemas(operation)
|
package/src/plugin.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
+
import type { AsyncEventEmitter } from '@internals/utils'
|
|
3
|
+
import { camelCase } from '@internals/utils'
|
|
2
4
|
import { type Config, definePlugin, type Group, getMode, type KubbEvents } from '@kubb/core'
|
|
3
|
-
import { camelCase } from '@kubb/core/transformers'
|
|
4
|
-
import type { AsyncEventEmitter } from '@kubb/core/utils'
|
|
5
5
|
import type { Oas } from '@kubb/oas'
|
|
6
|
-
import { parseFromConfig } from '@kubb/oas'
|
|
6
|
+
import { parseFromConfig, resolveServerUrl } from '@kubb/oas'
|
|
7
7
|
import { jsonGenerator } from './generators'
|
|
8
8
|
import { OperationGenerator } from './OperationGenerator.ts'
|
|
9
9
|
import { SchemaGenerator } from './SchemaGenerator.ts'
|
|
10
10
|
import type { PluginOas } from './types.ts'
|
|
11
|
-
import { resolveServerUrl } from './utils/resolveServerUrl.ts'
|
|
12
11
|
|
|
13
12
|
export const pluginOasName = 'plugin-oas' satisfies PluginOas['name']
|
|
14
13
|
|
|
@@ -140,15 +139,7 @@ export const pluginOas = definePlugin<PluginOas>((options) => {
|
|
|
140
139
|
return
|
|
141
140
|
}
|
|
142
141
|
|
|
143
|
-
await oas.dereference()
|
|
144
|
-
// Some specs have invalid internal $ref pointers (e.g. `#/definitions/...` in OpenAPI 3.x docs)
|
|
145
|
-
// that cause dereference to fail. Log the issue and continue — the SchemaGenerator resolves
|
|
146
|
-
// refs on-the-fly via dereferenceWithRef(), so schema generation still works.
|
|
147
|
-
this.events.emit('debug', {
|
|
148
|
-
date: new Date(),
|
|
149
|
-
logs: [`Unable to fully dereference schema: ${(err as Error).message}`],
|
|
150
|
-
})
|
|
151
|
-
})
|
|
142
|
+
await oas.dereference()
|
|
152
143
|
|
|
153
144
|
const schemaGenerator = new SchemaGenerator(
|
|
154
145
|
{
|
package/src/types.ts
CHANGED
|
@@ -30,7 +30,7 @@ export type ResolvePathOptions = {
|
|
|
30
30
|
|
|
31
31
|
export type Options = {
|
|
32
32
|
/**
|
|
33
|
-
* Validate your input(see kubb.config) based on '@
|
|
33
|
+
* Validate your input(see kubb.config) based on '@apidevtools/swagger-parser'.
|
|
34
34
|
* @default true
|
|
35
35
|
*/
|
|
36
36
|
validate?: boolean
|
package/src/utils/getComments.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { URLPath } from '@
|
|
2
|
-
|
|
1
|
+
import { URLPath } from '@internals/utils'
|
|
3
2
|
import type { Operation } from '@kubb/oas'
|
|
4
3
|
|
|
5
4
|
export function getComments(operation: Operation): string[] {
|
|
@@ -9,11 +8,9 @@ export function getComments(operation: Operation): string[] {
|
|
|
9
8
|
operation.path && `{@link ${new URLPath(operation.path).URL}}`,
|
|
10
9
|
operation.isDeprecated() && '@deprecated',
|
|
11
10
|
]
|
|
12
|
-
.filter(Boolean)
|
|
11
|
+
.filter((x): x is string => Boolean(x))
|
|
13
12
|
.flatMap((text) => {
|
|
14
|
-
// Split by newlines to preserve line breaks in JSDoc
|
|
15
|
-
// Trim each line individually to remove leading/trailing whitespace
|
|
16
13
|
return text.split(/\r?\n/).map((line) => line.trim())
|
|
17
14
|
})
|
|
18
|
-
.filter(Boolean)
|
|
15
|
+
.filter((x): x is string => Boolean(x))
|
|
19
16
|
}
|
package/src/utils/getImports.ts
CHANGED
|
@@ -9,8 +9,10 @@ import { schemaKeywords } from '../SchemaMapper'
|
|
|
9
9
|
export function getImports(tree: Array<Schema>): Array<KubbFile.Import> {
|
|
10
10
|
const refs = SchemaGenerator.deepSearch(tree, schemaKeywords.ref)
|
|
11
11
|
|
|
12
|
+
if (!refs) return []
|
|
13
|
+
|
|
12
14
|
return refs
|
|
13
|
-
|
|
15
|
+
.map((item) => {
|
|
14
16
|
if (!item.args.path || !item.args.isImportable) {
|
|
15
17
|
return undefined
|
|
16
18
|
}
|
|
@@ -18,7 +20,7 @@ export function getImports(tree: Array<Schema>): Array<KubbFile.Import> {
|
|
|
18
20
|
return {
|
|
19
21
|
name: [item.args.name],
|
|
20
22
|
path: item.args.path,
|
|
21
|
-
}
|
|
23
|
+
} satisfies KubbFile.Import
|
|
22
24
|
})
|
|
23
|
-
.filter(
|
|
25
|
+
.filter((x): x is NonNullable<typeof x> => x !== undefined)
|
|
24
26
|
}
|
package/src/utils/getParams.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { camelCase, isValidVarName } from '@
|
|
2
|
-
import type { FunctionParamsAST } from '@kubb/core
|
|
1
|
+
import { camelCase, isValidVarName } from '@internals/utils'
|
|
2
|
+
import type { FunctionParamsAST } from '@kubb/core'
|
|
3
3
|
import type { OasTypes } from '@kubb/oas'
|
|
4
4
|
import type { Params } from '@kubb/react-fabric/types'
|
|
5
5
|
import type { OperationSchema } from '../types.ts'
|
package/src/utils/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { camelCase, isValidVarName } from '@internals/utils'
|
|
2
2
|
import type { SchemaObject } from '@kubb/oas'
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -18,10 +18,10 @@ export function applyParamsCasing(schema: SchemaObject, casing: 'camelcase' | un
|
|
|
18
18
|
let transformedName = originalName
|
|
19
19
|
|
|
20
20
|
if (casing === 'camelcase') {
|
|
21
|
-
transformedName =
|
|
21
|
+
transformedName = camelCase(originalName)
|
|
22
22
|
} else if (!isValidVarName(originalName)) {
|
|
23
23
|
// If not valid variable name, make it valid
|
|
24
|
-
transformedName =
|
|
24
|
+
transformedName = camelCase(originalName)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
transformedProperties[transformedName] = propertySchema
|
|
@@ -33,9 +33,9 @@ export function applyParamsCasing(schema: SchemaObject, casing: 'camelcase' | un
|
|
|
33
33
|
let transformedName = originalName
|
|
34
34
|
|
|
35
35
|
if (casing === 'camelcase') {
|
|
36
|
-
transformedName =
|
|
36
|
+
transformedName = camelCase(originalName)
|
|
37
37
|
} else if (!isValidVarName(originalName)) {
|
|
38
|
-
transformedName =
|
|
38
|
+
transformedName = camelCase(originalName)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
transformedRequired.push(transformedName)
|
package/src/utils/requestBody.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { OasTypes } from '@kubb/oas'
|
|
2
2
|
import type { OperationSchema } from '../types.ts'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Sentinel value injected into `schema.required` to signal that the request body is required.
|
|
6
|
+
* Downstream generators check for this marker to emit the correct required constraint.
|
|
7
|
+
*/
|
|
8
|
+
export const KUBB_REQUIRED_REQUEST_BODY_MARKER = '__kubb_required_request_body__'
|
|
9
|
+
|
|
4
10
|
function getRequestBody(operationSchema: OperationSchema | undefined): OasTypes.RequestBodyObject | undefined {
|
|
5
11
|
const requestBody = operationSchema?.operation?.schema?.requestBody
|
|
6
12
|
|
|
@@ -30,7 +36,7 @@ export function withRequiredRequestBodySchema(operationSchema: OperationSchema |
|
|
|
30
36
|
...operationSchema,
|
|
31
37
|
schema: {
|
|
32
38
|
...operationSchema.schema,
|
|
33
|
-
required: [
|
|
39
|
+
required: [KUBB_REQUIRED_REQUEST_BODY_MARKER],
|
|
34
40
|
},
|
|
35
41
|
}
|
|
36
42
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generators-BvfaSMp3.cjs","names":["getBanner","getFooter"],"sources":["../src/generators/createGenerator.ts","../src/generators/createReactGenerator.ts","../src/generators/jsonGenerator.ts"],"sourcesContent":["import type { PluginFactoryOptions } from '@kubb/core'\nimport type { KubbFile } from '@kubb/fabric-core/types'\nimport type { OperationProps, OperationsProps, SchemaProps } from './types.ts'\n\ntype UserGenerator<TOptions extends PluginFactoryOptions> = {\n name: string\n operations?: (props: OperationsProps<TOptions>) => Promise<KubbFile.File[]>\n operation?: (props: OperationProps<TOptions>) => Promise<KubbFile.File[]>\n schema?: (props: SchemaProps<TOptions>) => Promise<KubbFile.File[]>\n}\n\nexport type CoreGenerator<TOptions extends PluginFactoryOptions> = {\n name: string\n type: 'core'\n operations: (props: OperationsProps<TOptions>) => Promise<KubbFile.File[]>\n operation: (props: OperationProps<TOptions>) => Promise<KubbFile.File[]>\n schema: (props: SchemaProps<TOptions>) => Promise<KubbFile.File[]>\n}\n\nexport function createGenerator<TOptions extends PluginFactoryOptions>(generator: UserGenerator<TOptions>): CoreGenerator<TOptions> {\n return {\n type: 'core',\n async operations() {\n return []\n },\n async operation() {\n return []\n },\n async schema() {\n return []\n },\n ...generator,\n }\n}\n","import type { PluginFactoryOptions } from '@kubb/core'\nimport type { FabricReactNode } from '@kubb/react-fabric/types'\nimport type { OperationProps, OperationsProps, SchemaProps } from './types.ts'\n\ntype UserGenerator<TOptions extends PluginFactoryOptions> = {\n name: string\n Operations?: (props: OperationsProps<TOptions>) => FabricReactNode\n Operation?: (props: OperationProps<TOptions>) => FabricReactNode\n Schema?: (props: SchemaProps<TOptions>) => FabricReactNode\n}\n\nexport type ReactGenerator<TOptions extends PluginFactoryOptions> = {\n name: string\n type: 'react'\n Operations: (props: OperationsProps<TOptions>) => FabricReactNode\n Operation: (props: OperationProps<TOptions>) => FabricReactNode\n Schema: (props: SchemaProps<TOptions>) => FabricReactNode\n}\n\n/****\n * Creates a generator that uses React component functions to generate files for OpenAPI operations and schemas.\n *\n * The returned generator exposes async methods for generating files from operations, a single operation, or a schema, using the corresponding React components if provided. If a component is not defined, the method returns an empty array.\n *\n * @returns A generator object with async methods for operations, operation, and schema file generation.\n */\nexport function createReactGenerator<TOptions extends PluginFactoryOptions>(generator: UserGenerator<TOptions>): ReactGenerator<TOptions> {\n return {\n type: 'react',\n Operations() {\n return null\n },\n Operation() {\n return null\n },\n Schema() {\n return null\n },\n ...generator,\n }\n}\n","import { camelCase } from '@kubb/core/transformers'\nimport type { PluginOas } from '../types.ts'\nimport { getBanner } from '../utils/getBanner.ts'\nimport { getFooter } from '../utils/getFooter.ts'\nimport { createGenerator } from './createGenerator.ts'\n\nexport const jsonGenerator = createGenerator<PluginOas>({\n name: 'plugin-oas',\n async schema({ schema, generator }) {\n const { pluginManager, plugin } = generator.context\n const file = pluginManager.getFile({\n name: camelCase(schema.name),\n extname: '.json',\n mode: 'split',\n pluginKey: plugin.key,\n })\n\n return [\n {\n ...file,\n sources: [\n {\n name: camelCase(schema.name),\n isExportable: false,\n isIndexable: false,\n value: JSON.stringify(schema.value),\n },\n ],\n banner: getBanner({\n oas: generator.context.oas,\n output: plugin.options.output,\n config: pluginManager.config,\n }),\n format: getFooter({ oas: generator.context.oas, output: plugin.options.output }),\n },\n ]\n },\n})\n"],"mappings":";;;;AAmBA,SAAgB,gBAAuD,WAA6D;AAClI,QAAO;EACL,MAAM;EACN,MAAM,aAAa;AACjB,UAAO,EAAE;;EAEX,MAAM,YAAY;AAChB,UAAO,EAAE;;EAEX,MAAM,SAAS;AACb,UAAO,EAAE;;EAEX,GAAG;EACJ;;;;;;;;;;;ACNH,SAAgB,qBAA4D,WAA8D;AACxI,QAAO;EACL,MAAM;EACN,aAAa;AACX,UAAO;;EAET,YAAY;AACV,UAAO;;EAET,SAAS;AACP,UAAO;;EAET,GAAG;EACJ;;;;ACjCH,MAAa,gBAAgB,gBAA2B;CACtD,MAAM;CACN,MAAM,OAAO,EAAE,QAAQ,aAAa;EAClC,MAAM,EAAE,eAAe,WAAW,UAAU;AAQ5C,SAAO,CACL;GACE,GATS,cAAc,QAAQ;IACjC,OAAA,GAAA,wBAAA,WAAgB,OAAO,KAAK;IAC5B,SAAS;IACT,MAAM;IACN,WAAW,OAAO;IACnB,CAAC;GAKE,SAAS,CACP;IACE,OAAA,GAAA,wBAAA,WAAgB,OAAO,KAAK;IAC5B,cAAc;IACd,aAAa;IACb,OAAO,KAAK,UAAU,OAAO,MAAM;IACpC,CACF;GACD,QAAQA,kBAAAA,UAAU;IAChB,KAAK,UAAU,QAAQ;IACvB,QAAQ,OAAO,QAAQ;IACvB,QAAQ,cAAc;IACvB,CAAC;GACF,QAAQC,kBAAAA,UAAU;IAAE,KAAK,UAAU,QAAQ;IAAK,QAAQ,OAAO,QAAQ;IAAQ,CAAC;GACjF,CACF;;CAEJ,CAAC"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import "./chunk--u3MIqq1.js";
|
|
2
|
-
import { isFunction } from "remeda";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
//#region src/utils/getBanner.ts
|
|
5
|
-
/**
|
|
6
|
-
* Generate a default banner for files created by Kubb
|
|
7
|
-
* @returns A string with the default banner
|
|
8
|
-
*/
|
|
9
|
-
function getDefaultBanner({ title, description, version, config }) {
|
|
10
|
-
try {
|
|
11
|
-
let source = "";
|
|
12
|
-
if ("path" in config.input) source = path.basename(config.input.path);
|
|
13
|
-
else if ("data" in config.input) source = "text content";
|
|
14
|
-
let banner = "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n";
|
|
15
|
-
if (config.output.defaultBanner === "simple") {
|
|
16
|
-
banner += "*/\n";
|
|
17
|
-
return banner;
|
|
18
|
-
}
|
|
19
|
-
if (source) banner += `* Source: ${source}\n`;
|
|
20
|
-
if (title) banner += `* Title: ${title}\n`;
|
|
21
|
-
if (description) {
|
|
22
|
-
const formattedDescription = description.replace(/\n/gm, "\n* ");
|
|
23
|
-
banner += `* Description: ${formattedDescription}\n`;
|
|
24
|
-
}
|
|
25
|
-
if (version) banner += `* OpenAPI spec version: ${version}\n`;
|
|
26
|
-
banner += "*/\n";
|
|
27
|
-
return banner;
|
|
28
|
-
} catch (_error) {
|
|
29
|
-
return "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/";
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function getBanner({ output, oas, config }) {
|
|
33
|
-
let banner = "";
|
|
34
|
-
if (config?.output?.defaultBanner !== false && config) {
|
|
35
|
-
const { title, description, version } = oas.api?.info || {};
|
|
36
|
-
banner = getDefaultBanner({
|
|
37
|
-
title,
|
|
38
|
-
description,
|
|
39
|
-
version,
|
|
40
|
-
config
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
if (!output.banner) return banner;
|
|
44
|
-
if (isFunction(output.banner)) return `${output.banner(oas)}\n${banner}`;
|
|
45
|
-
return `${output.banner}\n${banner}`;
|
|
46
|
-
}
|
|
47
|
-
//#endregion
|
|
48
|
-
//#region src/utils/getFooter.ts
|
|
49
|
-
function getFooter({ output, oas }) {
|
|
50
|
-
if (!output.footer) return;
|
|
51
|
-
if (isFunction(output.footer)) return output.footer(oas);
|
|
52
|
-
return output.footer;
|
|
53
|
-
}
|
|
54
|
-
//#endregion
|
|
55
|
-
export { getBanner as n, getFooter as t };
|
|
56
|
-
|
|
57
|
-
//# sourceMappingURL=getFooter-DGVGGyRc.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getFooter-DGVGGyRc.js","names":[],"sources":["../src/utils/getBanner.ts","../src/utils/getFooter.ts"],"sourcesContent":["import path from 'node:path'\nimport type { Config, Output } from '@kubb/core'\nimport type { Oas } from '@kubb/oas'\nimport { isFunction } from 'remeda'\n\ntype Props<TOas extends Oas> = {\n oas: TOas\n output: Output<any>\n config?: Config\n}\n\n/**\n * Generate a default banner for files created by Kubb\n * @returns A string with the default banner\n */\nfunction getDefaultBanner({ title, description, version, config }: { title?: string; description?: string; version?: string; config: Config }): string {\n try {\n let source = ''\n if ('path' in config.input) {\n source = path.basename(config.input.path)\n } else if ('data' in config.input) {\n source = 'text content'\n }\n\n let banner = '/**\\n* Generated by Kubb (https://kubb.dev/).\\n* Do not edit manually.\\n'\n\n if (config.output.defaultBanner === 'simple') {\n banner += '*/\\n'\n return banner\n }\n\n if (source) {\n banner += `* Source: ${source}\\n`\n }\n\n if (title) {\n banner += `* Title: ${title}\\n`\n }\n\n if (description) {\n const formattedDescription = description.replace(/\\n/gm, '\\n* ')\n banner += `* Description: ${formattedDescription}\\n`\n }\n\n if (version) {\n banner += `* OpenAPI spec version: ${version}\\n`\n }\n\n banner += '*/\\n'\n return banner\n } catch (_error) {\n // If there's any error in parsing the Oas data, return a simpler banner\n return '/**\\n* Generated by Kubb (https://kubb.dev/).\\n* Do not edit manually.\\n*/'\n }\n}\n\nexport function getBanner<TOas extends Oas>({ output, oas, config }: Props<TOas>): string {\n let banner = ''\n if (config?.output?.defaultBanner !== false && config) {\n const { title, description, version } = oas.api?.info || {}\n\n banner = getDefaultBanner({ title, description, version, config })\n }\n\n if (!output.banner) {\n return banner\n }\n\n if (isFunction(output.banner)) {\n return `${output.banner(oas)}\\n${banner}`\n }\n\n return `${output.banner}\\n${banner}`\n}\n","import type { Output } from '@kubb/core'\nimport type { Oas } from '@kubb/oas'\nimport { isFunction } from 'remeda'\n\ntype Props<TOas extends Oas> = {\n oas: TOas\n output: Output<any>\n}\n\nexport function getFooter<TOas extends Oas>({ output, oas }: Props<TOas>) {\n if (!output.footer) {\n return undefined\n }\n\n if (isFunction(output.footer)) {\n return output.footer(oas)\n }\n\n return output.footer\n}\n"],"mappings":";;;;;;;;AAeA,SAAS,iBAAiB,EAAE,OAAO,aAAa,SAAS,UAA8F;AACrJ,KAAI;EACF,IAAI,SAAS;AACb,MAAI,UAAU,OAAO,MACnB,UAAS,KAAK,SAAS,OAAO,MAAM,KAAK;WAChC,UAAU,OAAO,MAC1B,UAAS;EAGX,IAAI,SAAS;AAEb,MAAI,OAAO,OAAO,kBAAkB,UAAU;AAC5C,aAAU;AACV,UAAO;;AAGT,MAAI,OACF,WAAU,aAAa,OAAO;AAGhC,MAAI,MACF,WAAU,YAAY,MAAM;AAG9B,MAAI,aAAa;GACf,MAAM,uBAAuB,YAAY,QAAQ,QAAQ,OAAO;AAChE,aAAU,kBAAkB,qBAAqB;;AAGnD,MAAI,QACF,WAAU,2BAA2B,QAAQ;AAG/C,YAAU;AACV,SAAO;UACA,QAAQ;AAEf,SAAO;;;AAIX,SAAgB,UAA4B,EAAE,QAAQ,KAAK,UAA+B;CACxF,IAAI,SAAS;AACb,KAAI,QAAQ,QAAQ,kBAAkB,SAAS,QAAQ;EACrD,MAAM,EAAE,OAAO,aAAa,YAAY,IAAI,KAAK,QAAQ,EAAE;AAE3D,WAAS,iBAAiB;GAAE;GAAO;GAAa;GAAS;GAAQ,CAAC;;AAGpE,KAAI,CAAC,OAAO,OACV,QAAO;AAGT,KAAI,WAAW,OAAO,OAAO,CAC3B,QAAO,GAAG,OAAO,OAAO,IAAI,CAAC,IAAI;AAGnC,QAAO,GAAG,OAAO,OAAO,IAAI;;;;AC/D9B,SAAgB,UAA4B,EAAE,QAAQ,OAAoB;AACxE,KAAI,CAAC,OAAO,OACV;AAGF,KAAI,WAAW,OAAO,OAAO,CAC3B,QAAO,OAAO,OAAO,IAAI;AAG3B,QAAO,OAAO"}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
const require_chunk = require("./chunk-ByKO4r7w.cjs");
|
|
2
|
-
let remeda = require("remeda");
|
|
3
|
-
let node_path = require("node:path");
|
|
4
|
-
node_path = require_chunk.__toESM(node_path);
|
|
5
|
-
//#region src/utils/getBanner.ts
|
|
6
|
-
/**
|
|
7
|
-
* Generate a default banner for files created by Kubb
|
|
8
|
-
* @returns A string with the default banner
|
|
9
|
-
*/
|
|
10
|
-
function getDefaultBanner({ title, description, version, config }) {
|
|
11
|
-
try {
|
|
12
|
-
let source = "";
|
|
13
|
-
if ("path" in config.input) source = node_path.default.basename(config.input.path);
|
|
14
|
-
else if ("data" in config.input) source = "text content";
|
|
15
|
-
let banner = "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n";
|
|
16
|
-
if (config.output.defaultBanner === "simple") {
|
|
17
|
-
banner += "*/\n";
|
|
18
|
-
return banner;
|
|
19
|
-
}
|
|
20
|
-
if (source) banner += `* Source: ${source}\n`;
|
|
21
|
-
if (title) banner += `* Title: ${title}\n`;
|
|
22
|
-
if (description) {
|
|
23
|
-
const formattedDescription = description.replace(/\n/gm, "\n* ");
|
|
24
|
-
banner += `* Description: ${formattedDescription}\n`;
|
|
25
|
-
}
|
|
26
|
-
if (version) banner += `* OpenAPI spec version: ${version}\n`;
|
|
27
|
-
banner += "*/\n";
|
|
28
|
-
return banner;
|
|
29
|
-
} catch (_error) {
|
|
30
|
-
return "/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/";
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function getBanner({ output, oas, config }) {
|
|
34
|
-
let banner = "";
|
|
35
|
-
if (config?.output?.defaultBanner !== false && config) {
|
|
36
|
-
const { title, description, version } = oas.api?.info || {};
|
|
37
|
-
banner = getDefaultBanner({
|
|
38
|
-
title,
|
|
39
|
-
description,
|
|
40
|
-
version,
|
|
41
|
-
config
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
if (!output.banner) return banner;
|
|
45
|
-
if ((0, remeda.isFunction)(output.banner)) return `${output.banner(oas)}\n${banner}`;
|
|
46
|
-
return `${output.banner}\n${banner}`;
|
|
47
|
-
}
|
|
48
|
-
//#endregion
|
|
49
|
-
//#region src/utils/getFooter.ts
|
|
50
|
-
function getFooter({ output, oas }) {
|
|
51
|
-
if (!output.footer) return;
|
|
52
|
-
if ((0, remeda.isFunction)(output.footer)) return output.footer(oas);
|
|
53
|
-
return output.footer;
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
56
|
-
Object.defineProperty(exports, "getBanner", {
|
|
57
|
-
enumerable: true,
|
|
58
|
-
get: function() {
|
|
59
|
-
return getBanner;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
Object.defineProperty(exports, "getFooter", {
|
|
63
|
-
enumerable: true,
|
|
64
|
-
get: function() {
|
|
65
|
-
return getFooter;
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
//# sourceMappingURL=getFooter-WAZDOcmk.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getFooter-WAZDOcmk.cjs","names":["path"],"sources":["../src/utils/getBanner.ts","../src/utils/getFooter.ts"],"sourcesContent":["import path from 'node:path'\nimport type { Config, Output } from '@kubb/core'\nimport type { Oas } from '@kubb/oas'\nimport { isFunction } from 'remeda'\n\ntype Props<TOas extends Oas> = {\n oas: TOas\n output: Output<any>\n config?: Config\n}\n\n/**\n * Generate a default banner for files created by Kubb\n * @returns A string with the default banner\n */\nfunction getDefaultBanner({ title, description, version, config }: { title?: string; description?: string; version?: string; config: Config }): string {\n try {\n let source = ''\n if ('path' in config.input) {\n source = path.basename(config.input.path)\n } else if ('data' in config.input) {\n source = 'text content'\n }\n\n let banner = '/**\\n* Generated by Kubb (https://kubb.dev/).\\n* Do not edit manually.\\n'\n\n if (config.output.defaultBanner === 'simple') {\n banner += '*/\\n'\n return banner\n }\n\n if (source) {\n banner += `* Source: ${source}\\n`\n }\n\n if (title) {\n banner += `* Title: ${title}\\n`\n }\n\n if (description) {\n const formattedDescription = description.replace(/\\n/gm, '\\n* ')\n banner += `* Description: ${formattedDescription}\\n`\n }\n\n if (version) {\n banner += `* OpenAPI spec version: ${version}\\n`\n }\n\n banner += '*/\\n'\n return banner\n } catch (_error) {\n // If there's any error in parsing the Oas data, return a simpler banner\n return '/**\\n* Generated by Kubb (https://kubb.dev/).\\n* Do not edit manually.\\n*/'\n }\n}\n\nexport function getBanner<TOas extends Oas>({ output, oas, config }: Props<TOas>): string {\n let banner = ''\n if (config?.output?.defaultBanner !== false && config) {\n const { title, description, version } = oas.api?.info || {}\n\n banner = getDefaultBanner({ title, description, version, config })\n }\n\n if (!output.banner) {\n return banner\n }\n\n if (isFunction(output.banner)) {\n return `${output.banner(oas)}\\n${banner}`\n }\n\n return `${output.banner}\\n${banner}`\n}\n","import type { Output } from '@kubb/core'\nimport type { Oas } from '@kubb/oas'\nimport { isFunction } from 'remeda'\n\ntype Props<TOas extends Oas> = {\n oas: TOas\n output: Output<any>\n}\n\nexport function getFooter<TOas extends Oas>({ output, oas }: Props<TOas>) {\n if (!output.footer) {\n return undefined\n }\n\n if (isFunction(output.footer)) {\n return output.footer(oas)\n }\n\n return output.footer\n}\n"],"mappings":";;;;;;;;;AAeA,SAAS,iBAAiB,EAAE,OAAO,aAAa,SAAS,UAA8F;AACrJ,KAAI;EACF,IAAI,SAAS;AACb,MAAI,UAAU,OAAO,MACnB,UAASA,UAAAA,QAAK,SAAS,OAAO,MAAM,KAAK;WAChC,UAAU,OAAO,MAC1B,UAAS;EAGX,IAAI,SAAS;AAEb,MAAI,OAAO,OAAO,kBAAkB,UAAU;AAC5C,aAAU;AACV,UAAO;;AAGT,MAAI,OACF,WAAU,aAAa,OAAO;AAGhC,MAAI,MACF,WAAU,YAAY,MAAM;AAG9B,MAAI,aAAa;GACf,MAAM,uBAAuB,YAAY,QAAQ,QAAQ,OAAO;AAChE,aAAU,kBAAkB,qBAAqB;;AAGnD,MAAI,QACF,WAAU,2BAA2B,QAAQ;AAG/C,YAAU;AACV,SAAO;UACA,QAAQ;AAEf,SAAO;;;AAIX,SAAgB,UAA4B,EAAE,QAAQ,KAAK,UAA+B;CACxF,IAAI,SAAS;AACb,KAAI,QAAQ,QAAQ,kBAAkB,SAAS,QAAQ;EACrD,MAAM,EAAE,OAAO,aAAa,YAAY,IAAI,KAAK,QAAQ,EAAE;AAE3D,WAAS,iBAAiB;GAAE;GAAO;GAAa;GAAS;GAAQ,CAAC;;AAGpE,KAAI,CAAC,OAAO,OACV,QAAO;AAGT,MAAA,GAAA,OAAA,YAAe,OAAO,OAAO,CAC3B,QAAO,GAAG,OAAO,OAAO,IAAI,CAAC,IAAI;AAGnC,QAAO,GAAG,OAAO,OAAO,IAAI;;;;AC/D9B,SAAgB,UAA4B,EAAE,QAAQ,OAAoB;AACxE,KAAI,CAAC,OAAO,OACV;AAGF,MAAA,GAAA,OAAA,YAAe,OAAO,OAAO,CAC3B,QAAO,OAAO,OAAO,IAAI;AAG3B,QAAO,OAAO"}
|