@kubb/plugin-faker 5.0.0-beta.3 → 5.0.0-beta.31

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 (37) hide show
  1. package/README.md +26 -5
  2. package/dist/{Faker-CdyPfOPg.d.ts → Faker-BaLJxPyl.d.ts} +2 -2
  3. package/dist/{Faker-fcQEB9i5.js → Faker-DwIc_lta.js} +38 -100
  4. package/dist/Faker-DwIc_lta.js.map +1 -0
  5. package/dist/{Faker-BgleOzVN.cjs → Faker-XuyEQflW.cjs} +37 -123
  6. package/dist/Faker-XuyEQflW.cjs.map +1 -0
  7. package/dist/components.cjs +1 -1
  8. package/dist/components.d.ts +1 -1
  9. package/dist/components.js +1 -1
  10. package/dist/{fakerGenerator-VJEVzLjc.cjs → fakerGenerator-BBr2WsG8.cjs} +236 -60
  11. package/dist/fakerGenerator-BBr2WsG8.cjs.map +1 -0
  12. package/dist/{fakerGenerator-D7daHCh6.js → fakerGenerator-BDNxA7KY.js} +235 -59
  13. package/dist/fakerGenerator-BDNxA7KY.js.map +1 -0
  14. package/dist/fakerGenerator-DSvAJTq3.d.ts +15 -0
  15. package/dist/generators.cjs +1 -1
  16. package/dist/generators.d.ts +1 -1
  17. package/dist/generators.js +1 -1
  18. package/dist/index.cjs +213 -42
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.ts +33 -12
  21. package/dist/index.js +214 -43
  22. package/dist/index.js.map +1 -1
  23. package/dist/{printerFaker-CJiwzoto.d.ts → printerFaker-Bhwq62d1.d.ts} +63 -26
  24. package/extension.yaml +817 -0
  25. package/package.json +9 -13
  26. package/src/components/Faker.tsx +50 -64
  27. package/src/generators/fakerGenerator.tsx +107 -67
  28. package/src/plugin.ts +25 -21
  29. package/src/printers/printerFaker.ts +80 -16
  30. package/src/resolvers/resolverFaker.ts +29 -37
  31. package/src/types.ts +36 -23
  32. package/src/utils.ts +6 -105
  33. package/dist/Faker-BgleOzVN.cjs.map +0 -1
  34. package/dist/Faker-fcQEB9i5.js.map +0 -1
  35. package/dist/fakerGenerator-C3Ho3BaI.d.ts +0 -9
  36. package/dist/fakerGenerator-D7daHCh6.js.map +0 -1
  37. package/dist/fakerGenerator-VJEVzLjc.cjs.map +0 -1
@@ -3,12 +3,30 @@ import { ast } from '@kubb/core'
3
3
  import type { PluginFaker, ResolverFaker } from '../types.ts'
4
4
 
5
5
  /**
6
- * Partial printer nodes for Faker generation, mapping schema types to output strings.
6
+ * Partial map of node-type overrides for the Faker printer. Each key is a
7
+ * `SchemaType` (`'string'`, `'date'`, ...) and each handler returns the
8
+ * Faker expression for that schema as a string. Use `this.transform` to
9
+ * recurse into nested schema nodes and `this.options` to read printer options.
10
+ *
11
+ * @example Override the integer handler
12
+ * ```ts
13
+ * pluginFaker({
14
+ * printer: {
15
+ * nodes: {
16
+ * integer() {
17
+ * return 'faker.number.float()'
18
+ * },
19
+ * },
20
+ * },
21
+ * })
22
+ * ```
7
23
  */
8
24
  export type PrinterFakerNodes = ast.PrinterPartial<string, PrinterFakerOptions>
9
25
 
10
26
  /**
11
- * Configuration options for the Faker printer, including resolvers, mappers, and cyclic schema tracking.
27
+ * Options passed to the Faker printer at instantiation: the parser library
28
+ * for date strings, the regex generator, the user-supplied schema-name
29
+ * mapper, and the resolver used to compute identifiers.
12
30
  */
13
31
  export type PrinterFakerOptions = {
14
32
  dateParser?: PluginFaker['resolvedOptions']['dateParser']
@@ -18,6 +36,12 @@ export type PrinterFakerOptions = {
18
36
  typeName?: string
19
37
  schemaName?: string
20
38
  nestedInObject?: boolean
39
+ /**
40
+ * Set while printing the members of a union (`oneOf`). Object properties then index their
41
+ * type as `(NonNullable<T> & Record<K, unknown>)[K]` instead of `NonNullable<T>[K]`, so a key
42
+ * carried by only some branches stays valid (a plain index would be a TS2339).
43
+ */
44
+ nestedInUnion?: boolean
21
45
  nodes?: PrinterFakerNodes
22
46
  /**
23
47
  * Names of schemas that participate in a circular dependency chain.
@@ -85,7 +109,7 @@ const fakerKeywordMapper = {
85
109
  },
86
110
  boolean: () => 'faker.datatype.boolean()',
87
111
  null: () => 'null',
88
- array: (items: string[] = [], min?: number, max?: number) => {
112
+ array: (items: Array<string> = [], min?: number, max?: number) => {
89
113
  if (items.length > 1) {
90
114
  return `faker.helpers.arrayElements([${items.join(', ')}])`
91
115
  }
@@ -106,9 +130,9 @@ const fakerKeywordMapper = {
106
130
 
107
131
  return `faker.helpers.multiple(() => (${item}))`
108
132
  },
109
- tuple: (items: string[] = []) => `[${items.join(', ')}]`,
133
+ tuple: (items: Array<string> = []) => `[${items.join(', ')}]`,
110
134
  enum: (items: Array<string | number | boolean | undefined> = [], type = 'any') => `faker.helpers.arrayElement<${type}>([${items.join(', ')}])`,
111
- union: (items: string[] = []) => `faker.helpers.arrayElement<any>([${items.join(', ')}])`,
135
+ union: (items: Array<string> = []) => `faker.helpers.arrayElement<any>([${items.join(', ')}])`,
112
136
  datetime: () => 'faker.date.anytime().toISOString()',
113
137
  date: (representation: 'date' | 'string' = 'string', parser: PluginFaker['resolvedOptions']['dateParser'] = 'faker') => {
114
138
  if (representation === 'string') {
@@ -142,7 +166,7 @@ const fakerKeywordMapper = {
142
166
  },
143
167
  uuid: () => 'faker.string.uuid()',
144
168
  url: () => 'faker.internet.url()',
145
- and: (items: string[] = []) => {
169
+ and: (items: Array<string> = []) => {
146
170
  if (items.length === 0) {
147
171
  return '{}'
148
172
  }
@@ -180,6 +204,32 @@ function parseEnumValue(value: string | number | boolean | undefined) {
180
204
  return value
181
205
  }
182
206
 
207
+ /** Reads the discriminator literal off a variant, or `undefined` when it can't be determined. */
208
+ function getDiscriminatorValue(member: ast.SchemaNode, discriminatorPropertyName: string) {
209
+ const prop = ast.narrowSchema(member, 'object')?.properties?.find((p) => p.name === discriminatorPropertyName)
210
+ const enumNode = prop ? ast.narrowSchema(prop.schema, 'enum') : null
211
+
212
+ return enumNode ? getEnumValues(enumNode)[0] : undefined
213
+ }
214
+
215
+ /**
216
+ * Type expression for an object property's value, indexed off the parent `typeName`.
217
+ *
218
+ * In a union (`oneOf`), a key that only some branches declare turns a plain `NonNullable<T>[K]`
219
+ * into a TS2339 error, so union members guard the access. The breakdown is below.
220
+ */
221
+ function indexedTypeName(typeName: string, propertyName: string, nestedInUnion?: boolean): string {
222
+ const key = JSON.stringify(propertyName)
223
+
224
+ // `(NonNullable<T> & Record<K, unknown>)[K]`, read inside-out:
225
+ // NonNullable<T> strips null and undefined from the parent type T.
226
+ // & Record<K, unknown> forces every branch to have key K. A branch that already declares K
227
+ // keeps it (`T[K] & unknown` is `T[K]`); a branch missing K gains it as `unknown`.
228
+ // [K] reads the key, which is now always present, so it never hits TS2339.
229
+ // For a single object T the intersection does nothing, leaving `T[K]`.
230
+ return nestedInUnion ? `(NonNullable<${typeName}> & Record<${key}, unknown>)[${key}]` : `NonNullable<${typeName}>[${key}]`
231
+ }
232
+
183
233
  /**
184
234
  * Creates a Faker printer that generates mock data generation code from schema nodes.
185
235
  * Handles circular references gracefully by emitting memoizing getters for cyclic properties.
@@ -258,18 +308,32 @@ export const printerFaker: (options: PrinterFakerOptions) => ast.Printer<Printer
258
308
  return fakerKeywordMapper.enum(getEnumValues(node).map(parseEnumValue), this.options.typeName)
259
309
  },
260
310
  union(node): string {
261
- const items: string[] = (node.members ?? [])
262
- .map((member) =>
263
- printNested(member, {
264
- nestedInObject: true,
265
- }),
266
- )
311
+ const { discriminatorPropertyName } = node
312
+ const baseTypeName = this.options.typeName
313
+
314
+ const items: Array<string> = (node.members ?? [])
315
+ .map((member) => {
316
+ // For a discriminated union, narrow each variant to its own branch so nested
317
+ // `NonNullable<T>[K]` indexes resolve against that branch instead of the whole union.
318
+ const value = discriminatorPropertyName ? getDiscriminatorValue(member, discriminatorPropertyName) : undefined
319
+
320
+ if (baseTypeName && value !== undefined) {
321
+ const typeName = `Extract<NonNullable<${baseTypeName}>, { ${JSON.stringify(discriminatorPropertyName)}: ${parseEnumValue(value)} }>`
322
+
323
+ return printNested(member, { typeName, nestedInObject: true })
324
+ }
325
+
326
+ // Without a discriminator, keep the union type but guard each indexed access (see
327
+ // `indexedTypeName`) so a key carried by only some branches resolves to `unknown`
328
+ // rather than erroring with TS2339.
329
+ return printNested(member, { typeName: baseTypeName, nestedInObject: true, nestedInUnion: true })
330
+ })
267
331
  .filter((item): item is string => Boolean(item))
268
332
 
269
333
  return fakerKeywordMapper.union(items)
270
334
  },
271
335
  intersection(node): string {
272
- const items: string[] = (node.members ?? [])
336
+ const items: Array<string> = (node.members ?? [])
273
337
  .map((member) =>
274
338
  printNested(member, {
275
339
  nestedInObject: true,
@@ -280,7 +344,7 @@ export const printerFaker: (options: PrinterFakerOptions) => ast.Printer<Printer
280
344
  return fakerKeywordMapper.and(items)
281
345
  },
282
346
  array(node): string {
283
- const items: string[] = (node.items ?? [])
347
+ const items: Array<string> = (node.items ?? [])
284
348
  .map((member) =>
285
349
  printNested(member, {
286
350
  typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[number]` : undefined,
@@ -292,7 +356,7 @@ export const printerFaker: (options: PrinterFakerOptions) => ast.Printer<Printer
292
356
  return fakerKeywordMapper.array(items, node.min, node.max)
293
357
  },
294
358
  tuple(node): string {
295
- const items: string[] = (node.items ?? [])
359
+ const items: Array<string> = (node.items ?? [])
296
360
  .map((member, index) =>
297
361
  printNested(member, {
298
362
  typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[${index}]` : undefined,
@@ -313,7 +377,7 @@ export const printerFaker: (options: PrinterFakerOptions) => ast.Printer<Printer
313
377
 
314
378
  const value: string =
315
379
  printNested(property.schema, {
316
- typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[${JSON.stringify(property.name)}]` : undefined,
380
+ typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : undefined,
317
381
  nestedInObject: true,
318
382
  }) ?? 'undefined'
319
383
 
@@ -1,50 +1,39 @@
1
1
  import { createHash } from 'node:crypto'
2
2
  import path from 'node:path'
3
- import { camelCase } from '@internals/utils'
4
- import { defineResolver, PluginDriver } from '@kubb/core'
3
+ import { camelCase, ensureValidVarName } from '@internals/utils'
4
+ import { defineResolver, KubbDriver } from '@kubb/core'
5
5
  import type { PluginFaker } from '../types.ts'
6
6
 
7
- function isValidStrictIdentifier(name: string): boolean {
8
- try {
9
- new Function(`"use strict"; const ${name} = 1;`)
10
- } catch {
11
- return false
12
- }
13
-
14
- return true
15
- }
16
-
17
7
  /**
18
- * Naming convention resolver for Faker plugin.
8
+ * Default resolver used by `@kubb/plugin-faker`. Decides the names and file
9
+ * paths for every generated mock factory. Functions and files are prefixed
10
+ * with `create` so `Pet` becomes `createPet`.
19
11
  *
20
- * Provides default naming helpers using camelCase. Prefixes invalid identifiers with `_`.
12
+ * @example Resolve a factory name
13
+ * ```ts
14
+ * import { resolverFaker } from '@kubb/plugin-faker'
21
15
  *
22
- * @example
23
- * `resolverFaker.default('list pets', 'function') // → 'listPets'`
16
+ * resolverFaker.default('list pets', 'function') // 'createListPets'
17
+ * ```
24
18
  */
25
- export const resolverFaker = defineResolver<PluginFaker>((ctx) => {
19
+ export const resolverFaker = defineResolver<PluginFaker>(() => {
26
20
  return {
27
21
  name: 'default',
28
22
  pluginName: 'plugin-faker',
29
23
  default(name, type) {
30
- const resolvedName = camelCase(name, { isFile: type === 'file' })
31
-
32
- if (type === 'file' || isValidStrictIdentifier(resolvedName)) {
33
- return resolvedName
34
- }
35
-
36
- return `_${resolvedName}`
24
+ const resolvedName = camelCase(name, { isFile: type === 'file', prefix: 'create' })
25
+ return type === 'file' ? resolvedName : ensureValidVarName(resolvedName)
37
26
  },
38
27
  resolveName(name, type) {
39
- return ctx.default(name, type)
28
+ return this.default(name, type)
40
29
  },
41
30
  resolvePathName(name, type) {
42
- return ctx.default(name, type)
31
+ return this.default(name, type)
43
32
  },
44
33
  resolveFile({ name, extname, tag, path: groupPath }, context) {
45
- const pathMode = PluginDriver.getMode(path.resolve(context.root, context.output.path))
46
- const baseName = `${pathMode === 'single' ? '' : ctx.resolveName(name, 'file')}${extname}` as `${string}.${string}`
47
- const filePath = ctx.resolvePath(
34
+ const pathMode = KubbDriver.getMode(path.resolve(context.root, context.output.path))
35
+ const baseName = `${pathMode === 'single' ? '' : this.resolveName(name, 'file')}${extname}` as `${string}.${string}`
36
+ const filePath = this.resolvePath(
48
37
  {
49
38
  baseName,
50
39
  pathMode,
@@ -61,32 +50,35 @@ export const resolverFaker = defineResolver<PluginFaker>((ctx) => {
61
50
  path: filePath,
62
51
  baseName,
63
52
  extname,
64
- meta: { pluginName: ctx.pluginName },
53
+ meta: { pluginName: this.pluginName },
65
54
  sources: [],
66
55
  imports: [],
67
56
  exports: [],
68
57
  }
69
58
  },
70
59
  resolveParamName(node, param) {
71
- return ctx.resolveName(`${node.operationId} ${param.in} ${param.name}`)
60
+ return this.resolveName(`${node.operationId} ${param.in} ${param.name}`)
72
61
  },
73
62
  resolveDataName(node) {
74
- return ctx.resolveName(`${node.operationId} Data`)
63
+ return this.resolveName(`${node.operationId} Data`)
75
64
  },
76
65
  resolveResponseStatusName(node, statusCode) {
77
- return ctx.resolveName(`${node.operationId} Status ${statusCode}`)
66
+ return this.resolveName(`${node.operationId} Status ${statusCode}`)
78
67
  },
79
68
  resolveResponseName(node) {
80
- return ctx.resolveName(`${node.operationId} Response`)
69
+ return this.resolveName(`${node.operationId} Response`)
70
+ },
71
+ resolveResponsesName(node) {
72
+ return this.resolveName(`${node.operationId} Responses`)
81
73
  },
82
74
  resolvePathParamsName(node, param) {
83
- return ctx.resolveParamName(node, param)
75
+ return this.resolveParamName(node, param)
84
76
  },
85
77
  resolveQueryParamsName(node, param) {
86
- return ctx.resolveParamName(node, param)
78
+ return this.resolveParamName(node, param)
87
79
  },
88
80
  resolveHeaderParamsName(node, param) {
89
- return ctx.resolveParamName(node, param)
81
+ return this.resolveParamName(node, param)
90
82
  },
91
83
  }
92
84
  })
package/src/types.ts CHANGED
@@ -41,6 +41,13 @@ export type ResolverFaker = Resolver &
41
41
  * `resolver.resolveResponseName(node) // -> 'listPetsResponse'`
42
42
  */
43
43
  resolveResponseName(this: ResolverFaker, node: ast.OperationNode): string
44
+ /**
45
+ * Resolves the faker function name for the response collection.
46
+ *
47
+ * @example Responses collection names
48
+ * `resolver.resolveResponsesName(node) // -> 'listPetsResponses'`
49
+ */
50
+ resolveResponsesName(this: ResolverFaker, node: ast.OperationNode): string
44
51
  /**
45
52
  * Resolves the faker function name for path parameters.
46
53
  *
@@ -66,80 +73,86 @@ export type ResolverFaker = Resolver &
66
73
 
67
74
  export type Options = {
68
75
  /**
69
- * Specify the export location for the files and define the behavior of the output.
70
- * @default { path: 'mocks', barrelType: 'named' }
76
+ * Where the generated mock factories are written and how they are exported.
77
+ *
78
+ * @default { path: 'mocks', barrel: { type: 'named' } }
71
79
  */
72
80
  output?: Output
73
81
  /**
74
- * Group the Faker mocks based on the provided name.
82
+ * Split generated files into subfolders based on the operation's tag.
75
83
  */
76
84
  group?: Group
77
85
  /**
78
- * Tags, operations, or paths to exclude from generation.
86
+ * Skip operations matching at least one entry in the list.
79
87
  */
80
88
  exclude?: Array<Exclude>
81
89
  /**
82
- * Tags, operations, or paths to include in generation.
90
+ * Restrict generation to operations matching at least one entry in the list.
83
91
  */
84
92
  include?: Array<Include>
85
93
  /**
86
- * Override options for specific tags, operations, or paths.
94
+ * Apply a different options object to operations matching a pattern.
87
95
  */
88
96
  override?: Array<Override<ResolvedOptions>>
89
97
  /**
90
- * Parser to use when formatting date/time values as strings.
98
+ * Library used to format string-represented date, time, and datetime fields.
99
+ * Any library exporting a default function works; Kubb adds the import for you.
91
100
  *
92
101
  * @default 'faker'
93
102
  */
94
103
  dateParser?: 'faker' | 'dayjs' | 'moment' | (string & {})
95
104
  /**
96
- * Generator to use for RegExp patterns.
105
+ * Library used to generate strings that satisfy a regex `pattern` keyword.
106
+ * - `'faker'` uses `faker.helpers.fromRegExp`. No extra dependency.
107
+ * - `'randexp'` uses the `randexp` package. Supports a wider regex grammar.
97
108
  *
98
109
  * @default 'faker'
99
110
  */
100
111
  regexGenerator?: 'faker' | 'randexp'
101
112
  /**
102
- * Provide per-property faker expressions keyed by property name.
113
+ * Map a schema name to a custom Faker expression. Use this when the schema name
114
+ * does not give Faker enough context (`'email'`, `'avatarUrl'`, `'phoneNumber'`).
103
115
  */
104
116
  mapper?: Record<string, string>
105
117
  /**
106
- * Locale for generating mock data.
107
- * Imports the matching localized `@faker-js/faker` instance so names, addresses,
108
- * and phone numbers reflect the target region.
118
+ * Faker locale code. Switches the named import to `fakerXX` from `@faker-js/faker`
119
+ * so names, addresses, and phone numbers reflect the target region.
109
120
  *
110
121
  * @default 'en'
111
- *
112
122
  * @example German
113
123
  * `locale: 'de'`
114
- *
115
124
  * @example Austrian German
116
125
  * `locale: 'de_AT'`
117
- *
118
126
  * @see https://fakerjs.dev/api/localization.html
119
127
  */
120
128
  locale?: string
121
129
  /**
122
- * Seed faker for deterministic output.
130
+ * Value passed to `faker.seed(...)`. Set this for deterministic mock output,
131
+ * which is useful for snapshot tests.
123
132
  */
124
- seed?: number | number[]
133
+ seed?: number | Array<number>
125
134
  /**
126
- * Apply casing to parameter names to match your configuration.
135
+ * Rename properties inside path/query/header mocks. Body mocks are unaffected.
136
+ *
137
+ * @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
127
138
  */
128
139
  paramsCasing?: 'camelcase'
129
140
  /**
130
- * Additional generators alongside the default generators.
141
+ * Custom generators that run alongside the built-in Faker generators.
131
142
  */
132
143
  generators?: Array<Generator<PluginFaker>>
133
144
  /**
134
- * Override naming conventions for function names and types.
145
+ * Override the naming of generated factory helpers. Common use: append `Mock` or
146
+ * `Factory` so helpers do not clash with imported types.
135
147
  */
136
148
  resolver?: Partial<ResolverFaker> & ThisType<ResolverFaker>
137
149
  /**
138
- * AST visitor to transform generated nodes.
150
+ * AST visitor applied to schema and operation nodes before printing.
139
151
  */
140
152
  transformer?: ast.Visitor
141
153
  /**
142
- * Override individual faker printer node handlers.
154
+ * Replace the Faker handler for a specific schema type (`'integer'`, `'date'`, ...).
155
+ * Each handler returns the Faker expression as a string.
143
156
  */
144
157
  printer?: {
145
158
  nodes?: PrinterFakerNodes
@@ -148,7 +161,7 @@ export type Options = {
148
161
 
149
162
  type ResolvedOptions = {
150
163
  output: Output
151
- group: Group | undefined
164
+ group: Group | null
152
165
  exclude: NonNullable<Options['exclude']>
153
166
  include: Options['include']
154
167
  override: NonNullable<Options['override']>
package/src/utils.ts CHANGED
@@ -54,18 +54,6 @@ export function canOverrideSchema(node: ast.SchemaNode): boolean {
54
54
  ]).has(node.type)
55
55
  }
56
56
 
57
- /**
58
- * Resolves a schema reference by looking up the referenced schema in the provided array.
59
- * Returns the original node if it's not a reference.
60
- */
61
- export function resolveSchemaRef(node: ast.SchemaNode, schemas: Array<ast.SchemaNode>): ast.SchemaNode {
62
- if (node.type !== 'ref') {
63
- return node
64
- }
65
-
66
- return schemas.find((schema) => schema.name === node.name && schema.type !== 'ref') ?? node
67
- }
68
-
69
57
  /**
70
58
  * Resolves a parameter name based on its location (path, query, header, etc.) using the provided resolver.
71
59
  */
@@ -116,15 +104,16 @@ function shouldInlineSingleResponseSchema(schema: ast.SchemaNode): boolean {
116
104
  * Returns null if no responses are provided, or embeds single simple responses inline.
117
105
  */
118
106
  export function buildResponseUnionSchema(node: ast.OperationNode, resolver: ResolverFaker): ast.SchemaNode | null {
119
- const responses = node.responses.filter((response) => response.schema)
107
+ const responses = node.responses.filter((response) => response.content?.[0]?.schema)
120
108
 
121
109
  if (!responses.length) {
122
110
  return null
123
111
  }
124
112
 
125
113
  if (responses.length === 1) {
126
- if (shouldInlineSingleResponseSchema(responses[0]!.schema)) {
127
- return responses[0]!.schema
114
+ const schema = responses[0]!.content?.[0]?.schema
115
+ if (schema && shouldInlineSingleResponseSchema(schema)) {
116
+ return schema
128
117
  }
129
118
 
130
119
  return ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, responses[0]!.statusCode) })
@@ -136,19 +125,6 @@ export function buildResponseUnionSchema(node: ast.OperationNode, resolver: Reso
136
125
  })
137
126
  }
138
127
 
139
- /**
140
- * Import name that can be a string or a renamed import object.
141
- */
142
- export type ImportName = string | { propertyName: string; name?: string }
143
-
144
- /**
145
- * Import entry containing module path and imported names.
146
- */
147
- export type ImportEntry = {
148
- name: string | Array<ImportName>
149
- path: string
150
- }
151
-
152
128
  const SCALAR_TYPES = new Set<ast.SchemaNode['type']>([
153
129
  'string',
154
130
  'email',
@@ -171,81 +147,6 @@ function toRelativeImportPath(from: string, to: string): string {
171
147
  return relativePath.startsWith('../') ? relativePath : `./${relativePath}`
172
148
  }
173
149
 
174
- function escapeRegExp(value: string): string {
175
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
176
- }
177
-
178
- /**
179
- * Filters imports to only those that are actually used in the generated code.
180
- * Checks for function calls matching the imported names.
181
- */
182
- export function filterUsedImports(imports: Array<ImportEntry>, text: string, skipImportNames: Array<string> = []): Array<ImportEntry> {
183
- return imports.filter((entry) => {
184
- const names = (Array.isArray(entry.name) ? entry.name : [entry.name])
185
- .map((name) => {
186
- if (typeof name === 'string') {
187
- return name
188
- }
189
-
190
- return name?.name ?? name?.propertyName
191
- })
192
- .filter((name): name is string => Boolean(name))
193
-
194
- return names.some((name) => {
195
- if (skipImportNames.includes(name)) {
196
- return false
197
- }
198
-
199
- return new RegExp(`\\b${escapeRegExp(name)}\\b(?=\\s*\\()`).test(text)
200
- })
201
- })
202
- }
203
-
204
- /**
205
- * Detects and resolves import name conflicts by adding aliases to conflicting names.
206
- * Returns updated imports with a mapping of original names to their aliases.
207
- */
208
- export function aliasConflictingImports(
209
- imports: Array<ImportEntry>,
210
- reservedNames: Iterable<string>,
211
- ): { imports: Array<ImportEntry>; aliases: Map<string, string> } {
212
- const reservedNameSet = new Set(reservedNames)
213
- const aliases = new Map<string, string>()
214
-
215
- const aliasedImports = imports.map((entry) => {
216
- const names = Array.isArray(entry.name) ? entry.name : [entry.name]
217
- const aliasedNames = names.map((item): ImportName => {
218
- if (typeof item !== 'string' || !reservedNameSet.has(item)) {
219
- return item
220
- }
221
-
222
- const alias = `${item}Schema`
223
- aliases.set(item, alias)
224
-
225
- return { propertyName: item, name: alias }
226
- })
227
-
228
- return aliasedNames.some((item) => typeof item === 'object' && item.name)
229
- ? {
230
- ...entry,
231
- name: aliasedNames,
232
- }
233
- : entry
234
- })
235
-
236
- return {
237
- imports: aliasedImports,
238
- aliases,
239
- }
240
- }
241
-
242
- /**
243
- * Replaces all occurrences of original names with their aliased versions in the given text.
244
- */
245
- export function rewriteAliasedImports(text: string, aliases: ReadonlyMap<string, string>): string {
246
- return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, 'g'), alias), text)
247
- }
248
-
249
150
  /**
250
151
  * Resolves a type reference, determining if it needs an import statement or inline type reference.
251
152
  * Takes into account whether the type can be overridden and the file paths.
@@ -325,7 +226,7 @@ export function resolveFakerTypeUsage(
325
226
  canOverride: boolean,
326
227
  ): {
327
228
  dataType: string
328
- returnType: string | undefined
229
+ returnType: string | null
329
230
  usesTypeName: boolean
330
231
  } {
331
232
  const isArray = ARRAY_TYPES.has(node.type)
@@ -342,7 +243,7 @@ export function resolveFakerTypeUsage(
342
243
  dataType = getScalarType(node, typeName)
343
244
  }
344
245
 
345
- let returnType = canOverride ? typeName : undefined
246
+ let returnType = canOverride ? typeName : null
346
247
 
347
248
  if (isScalar) {
348
249
  returnType = getScalarType(node, typeName)
@@ -1 +0,0 @@
1
- {"version":3,"file":"Faker-BgleOzVN.cjs","names":["ast","SCALAR_TYPES","ARRAY_TYPES","posix","ast","File","Function"],"sources":["../../../internals/utils/src/string.ts","../src/utils.ts","../src/components/Faker.tsx"],"sourcesContent":["/**\n * Strips a single matching pair of `\"...\"`, `'...'`, or `` `...` `` from both ends of `text`.\n * Returns the string unchanged when no balanced quote pair is found.\n *\n * @example\n * trimQuotes('\"hello\"') // 'hello'\n * trimQuotes('hello') // 'hello'\n */\nexport function trimQuotes(text: string): string {\n if (text.length >= 2) {\n const first = text[0]\n const last = text[text.length - 1]\n if ((first === '\"' && last === '\"') || (first === \"'\" && last === \"'\") || (first === '`' && last === '`')) {\n return text.slice(1, -1)\n }\n }\n return text\n}\n\n/**\n * Escapes characters that are not allowed inside JS string literals.\n * Handles quotes, backslashes, and Unicode line terminators (U+2028 / U+2029).\n *\n * @see http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4\n *\n * @example\n * ```ts\n * jsStringEscape('say \"hi\"\\nbye') // 'say \\\\\"hi\\\\\"\\\\nbye'\n * ```\n */\nexport function jsStringEscape(input: unknown): string {\n return `${input}`.replace(/[\"'\\\\\\n\\r\\u2028\\u2029]/g, (character) => {\n switch (character) {\n case '\"':\n case \"'\":\n case '\\\\':\n return `\\\\${character}`\n case '\\n':\n return '\\\\n'\n case '\\r':\n return '\\\\r'\n case '\\u2028':\n return '\\\\u2028'\n case '\\u2029':\n return '\\\\u2029'\n default:\n return ''\n }\n })\n}\n\n/**\n * Strips the file extension from a path or file name.\n * Only removes the last `.ext` segment when the dot is not part of a directory name.\n *\n * @example\n * trimExtName('petStore.ts') // 'petStore'\n * trimExtName('/src/models/pet.ts') // '/src/models/pet'\n * trimExtName('/project.v2/gen/pet.ts') // '/project.v2/gen/pet'\n * trimExtName('noExtension') // 'noExtension'\n */\nexport function trimExtName(text: string): string {\n const dotIndex = text.lastIndexOf('.')\n if (dotIndex > 0 && !text.includes('/', dotIndex)) {\n return text.slice(0, dotIndex)\n }\n return text\n}\n","import { posix } from 'node:path'\nimport { ast } from '@kubb/core'\nimport type { ResolverFaker } from './types.ts'\n\n/**\n * Returns the `@faker-js/faker` named export for a locale code.\n *\n * Without a locale, returns `'faker'` for the default English instance.\n * With a locale, the language code is converted to upper case and joined with any region suffix.\n *\n * @example Default\n * `localeToFakerImport() // 'faker'`\n *\n * @example Simple locale\n * `localeToFakerImport('de') // 'fakerDE'`\n *\n * @example Compound locale\n * `localeToFakerImport('de_AT') // 'fakerDE_AT'`\n */\nexport function localeToFakerImport(locale?: string): string {\n if (!locale) {\n return 'faker'\n }\n\n const parts = locale.split('_')\n parts[0] = parts[0]!.toUpperCase()\n return `faker${parts.join('_')}`\n}\n\n/**\n * Determines if a schema node can be overridden during faker generation.\n */\nexport function canOverrideSchema(node: ast.SchemaNode): boolean {\n return new Set<ast.SchemaNode['type']>([\n 'array',\n 'tuple',\n 'object',\n 'intersection',\n 'union',\n 'enum',\n 'ref',\n 'string',\n 'email',\n 'url',\n 'uuid',\n 'number',\n 'integer',\n 'bigint',\n 'boolean',\n 'date',\n 'time',\n 'datetime',\n 'blob',\n ]).has(node.type)\n}\n\n/**\n * Resolves a schema reference by looking up the referenced schema in the provided array.\n * Returns the original node if it's not a reference.\n */\nexport function resolveSchemaRef(node: ast.SchemaNode, schemas: Array<ast.SchemaNode>): ast.SchemaNode {\n if (node.type !== 'ref') {\n return node\n }\n\n return schemas.find((schema) => schema.name === node.name && schema.type !== 'ref') ?? node\n}\n\n/**\n * Resolves a parameter name based on its location (path, query, header, etc.) using the provided resolver.\n */\nexport function resolveParamNameByLocation(\n resolver: Pick<ResolverFaker, 'resolvePathParamsName' | 'resolveQueryParamsName' | 'resolveHeaderParamsName' | 'resolveParamName'>,\n node: ast.OperationNode,\n param: ast.ParameterNode,\n): string {\n switch (param.in) {\n case 'path':\n return resolver.resolvePathParamsName(node, param)\n case 'query':\n return resolver.resolveQueryParamsName(node, param)\n case 'header':\n return resolver.resolveHeaderParamsName(node, param)\n default:\n return resolver.resolveParamName(node, param)\n }\n}\n\nfunction shouldInlineSingleResponseSchema(schema: ast.SchemaNode): boolean {\n return new Set<ast.SchemaNode['type']>([\n 'any',\n 'unknown',\n 'void',\n 'null',\n 'array',\n 'tuple',\n 'string',\n 'email',\n 'url',\n 'uuid',\n 'number',\n 'integer',\n 'bigint',\n 'boolean',\n 'date',\n 'time',\n 'datetime',\n 'blob',\n 'enum',\n 'union',\n ]).has(schema.type)\n}\n\n/**\n * Builds a response schema as a union of all response statuses.\n * Returns null if no responses are provided, or embeds single simple responses inline.\n */\nexport function buildResponseUnionSchema(node: ast.OperationNode, resolver: ResolverFaker): ast.SchemaNode | null {\n const responses = node.responses.filter((response) => response.schema)\n\n if (!responses.length) {\n return null\n }\n\n if (responses.length === 1) {\n if (shouldInlineSingleResponseSchema(responses[0]!.schema)) {\n return responses[0]!.schema\n }\n\n return ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, responses[0]!.statusCode) })\n }\n\n return ast.createSchema({\n type: 'union',\n members: responses.map((response) => ast.createSchema({ type: 'ref', name: resolver.resolveResponseStatusName(node, response.statusCode) })),\n })\n}\n\n/**\n * Import name that can be a string or a renamed import object.\n */\nexport type ImportName = string | { propertyName: string; name?: string }\n\n/**\n * Import entry containing module path and imported names.\n */\nexport type ImportEntry = {\n name: string | Array<ImportName>\n path: string\n}\n\nconst SCALAR_TYPES = new Set<ast.SchemaNode['type']>([\n 'string',\n 'email',\n 'url',\n 'uuid',\n 'number',\n 'integer',\n 'bigint',\n 'boolean',\n 'date',\n 'time',\n 'datetime',\n 'blob',\n 'enum',\n])\nconst ARRAY_TYPES = new Set<ast.SchemaNode['type']>(['array'])\n\nfunction toRelativeImportPath(from: string, to: string): string {\n const relativePath = posix.relative(posix.dirname(from), to)\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Filters imports to only those that are actually used in the generated code.\n * Checks for function calls matching the imported names.\n */\nexport function filterUsedImports(imports: Array<ImportEntry>, text: string, skipImportNames: Array<string> = []): Array<ImportEntry> {\n return imports.filter((entry) => {\n const names = (Array.isArray(entry.name) ? entry.name : [entry.name])\n .map((name) => {\n if (typeof name === 'string') {\n return name\n }\n\n return name?.name ?? name?.propertyName\n })\n .filter((name): name is string => Boolean(name))\n\n return names.some((name) => {\n if (skipImportNames.includes(name)) {\n return false\n }\n\n return new RegExp(`\\\\b${escapeRegExp(name)}\\\\b(?=\\\\s*\\\\()`).test(text)\n })\n })\n}\n\n/**\n * Detects and resolves import name conflicts by adding aliases to conflicting names.\n * Returns updated imports with a mapping of original names to their aliases.\n */\nexport function aliasConflictingImports(\n imports: Array<ImportEntry>,\n reservedNames: Iterable<string>,\n): { imports: Array<ImportEntry>; aliases: Map<string, string> } {\n const reservedNameSet = new Set(reservedNames)\n const aliases = new Map<string, string>()\n\n const aliasedImports = imports.map((entry) => {\n const names = Array.isArray(entry.name) ? entry.name : [entry.name]\n const aliasedNames = names.map((item): ImportName => {\n if (typeof item !== 'string' || !reservedNameSet.has(item)) {\n return item\n }\n\n const alias = `${item}Schema`\n aliases.set(item, alias)\n\n return { propertyName: item, name: alias }\n })\n\n return aliasedNames.some((item) => typeof item === 'object' && item.name)\n ? {\n ...entry,\n name: aliasedNames,\n }\n : entry\n })\n\n return {\n imports: aliasedImports,\n aliases,\n }\n}\n\n/**\n * Replaces all occurrences of original names with their aliased versions in the given text.\n */\nexport function rewriteAliasedImports(text: string, aliases: ReadonlyMap<string, string>): string {\n return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\\\b${escapeRegExp(name)}\\\\b`, 'g'), alias), text)\n}\n\n/**\n * Resolves a type reference, determining if it needs an import statement or inline type reference.\n * Takes into account whether the type can be overridden and the file paths.\n */\nexport function resolveTypeReference({\n node,\n canOverride,\n name,\n typeName,\n filePath,\n typeFilePath,\n}: {\n node: ast.SchemaNode\n canOverride: boolean\n name: string\n typeName: string\n filePath: string\n typeFilePath: string\n}): { importPath?: string; typeName: string } {\n const { usesTypeName } = resolveFakerTypeUsage(node, typeName, canOverride)\n\n if (!usesTypeName) {\n return { typeName }\n }\n\n if (name === typeName) {\n return {\n typeName: `import('${toRelativeImportPath(filePath, typeFilePath)}').${typeName}`,\n }\n }\n\n return {\n importPath: typeFilePath,\n typeName,\n }\n}\n\n/**\n * Maps a schema node type to its corresponding scalar type representation.\n * Returns the type name for enums or the base type (string, number, etc.) for primitives.\n */\nexport function getScalarType(node: ast.SchemaNode, typeName: string): string {\n switch (node.type) {\n case 'string':\n case 'email':\n case 'url':\n case 'uuid':\n return 'string'\n case 'number':\n case 'integer':\n return 'number'\n case 'bigint':\n return 'bigint'\n case 'boolean':\n return 'boolean'\n case 'date':\n case 'time':\n return node.representation === 'date' ? 'Date' : 'string'\n case 'datetime':\n return 'string'\n case 'blob':\n return 'Blob'\n case 'enum':\n return typeName\n default:\n return typeName\n }\n}\n\n/**\n * Resolves faker type usage information for a schema.\n * Determines the data type, return type, and whether it uses the type name.\n */\nexport function resolveFakerTypeUsage(\n node: ast.SchemaNode,\n typeName: string,\n canOverride: boolean,\n): {\n dataType: string\n returnType: string | undefined\n usesTypeName: boolean\n} {\n const isArray = ARRAY_TYPES.has(node.type)\n const isTuple = node.type === 'tuple'\n const isScalar = SCALAR_TYPES.has(node.type)\n\n let dataType = `Partial<${typeName}>`\n\n if (isArray || isTuple || node.type === 'union' || node.type === 'enum') {\n dataType = typeName\n }\n\n if (isScalar) {\n dataType = getScalarType(node, typeName)\n }\n\n let returnType = canOverride ? typeName : undefined\n\n if (isScalar) {\n returnType = getScalarType(node, typeName)\n }\n\n return {\n dataType,\n returnType,\n usesTypeName: dataType.includes(typeName) || Boolean(returnType?.includes(typeName)),\n }\n}\n","import { jsStringEscape } from '@internals/utils'\nimport { ast } from '@kubb/core'\nimport { functionPrinter } from '@kubb/plugin-ts'\nimport { File, Function } from '@kubb/renderer-jsx'\nimport type { KubbReactNode } from '@kubb/renderer-jsx/types'\nimport type { PrinterFakerFactory } from '../printers/printerFaker.ts'\nimport type { PluginFaker } from '../types.ts'\nimport { resolveFakerTypeUsage } from '../utils.ts'\n\ntype Props = {\n name: string\n typeName: string\n node: ast.SchemaNode\n printer: ast.Printer<PrinterFakerFactory>\n seed?: PluginFaker['options']['seed']\n description?: string\n canOverride: boolean\n}\n\nconst OBJECT_TYPES = new Set<ast.SchemaNode['type']>(['object', 'intersection'])\nconst ARRAY_TYPES = new Set<ast.SchemaNode['type']>(['array'])\nconst SCALAR_TYPES = new Set<ast.SchemaNode['type']>([\n 'string',\n 'email',\n 'url',\n 'uuid',\n 'number',\n 'integer',\n 'bigint',\n 'boolean',\n 'date',\n 'time',\n 'datetime',\n 'blob',\n 'enum',\n])\nconst declarationPrinter = functionPrinter({ mode: 'declaration' })\n\nexport function Faker({ node, description, name, typeName, printer, seed, canOverride }: Props): KubbReactNode {\n const fakerText = printer.print(node) ?? 'undefined'\n\n const isArray = ARRAY_TYPES.has(node.type)\n const isObject = OBJECT_TYPES.has(node.type)\n const isTuple = node.type === 'tuple'\n const isScalar = SCALAR_TYPES.has(node.type)\n\n let fakerTextWithOverride = fakerText\n let useGenericOverride = false\n\n if (canOverride && isObject) {\n useGenericOverride = true\n }\n\n if (canOverride && isTuple) {\n fakerTextWithOverride = `data || ${fakerText}`\n }\n\n if (canOverride && isArray) {\n fakerTextWithOverride = `[\n ...${fakerText},\n ...(data || [])\n]`\n }\n\n if (canOverride && isScalar) {\n fakerTextWithOverride = `data ?? ${fakerText}`\n }\n\n const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride)\n\n let functionSignature = ''\n let functionBody = ''\n\n if (useGenericOverride) {\n // Generate function with defaultFakeData structure\n const jsdoc = description ? `/**\\n * @description ${jsStringEscape(description)}\\n */\\n ` : ''\n functionSignature = `${jsdoc}export function ${name}(data?: Partial<${typeName}>): Required<${typeName}>`\n\n const seedCode = seed ? `faker.seed(${JSON.stringify(seed)})\\n ` : ''\n\n // When the object node has properties that transitively reference a cyclic schema,\n // the printer emits memoizing getters for those properties. Spreading the object\n // literal would immediately invoke those getters, triggering recursive faker calls\n // and causing a stack overflow. Detect this upfront via ast helpers so we can\n // use Object.defineProperty-based merging instead of spread.\n const { cyclicSchemas, schemaName } = printer.options\n const hasGetters =\n node.type === 'object' &&\n !!cyclicSchemas &&\n (node.properties ?? []).some((p) => ast.containsCircularRef(p.schema, { circularSchemas: cyclicSchemas, excludeName: schemaName }))\n\n if (hasGetters) {\n functionBody = `{\n ${seedCode}const defaultFakeData = ${fakerText}\n if (data) {\n for (const [key, value] of Object.entries(data)) {\n Object.defineProperty(defaultFakeData, key, { value, configurable: true, writable: true, enumerable: true })\n }\n }\n return defaultFakeData as Required<${typeName}>\n}`\n } else {\n functionBody = `{\n ${seedCode}const defaultFakeData = ${fakerText}\n return {\n ...defaultFakeData,\n ...(data || {}),\n } as Required<${typeName}>\n}`\n }\n } else {\n const usesData = /\\bdata\\b/.test(fakerTextWithOverride)\n const dataParamName = usesData ? 'data' : '_data'\n const params = ast.createFunctionParameters({\n params: [\n ast.createFunctionParameter({\n name: dataParamName,\n type: ast.createParamsType({ variant: 'reference', name: dataType }),\n optional: true,\n }),\n ],\n })\n const paramsSignature = declarationPrinter.print(params) ?? ''\n const returnType = resolvedReturnType\n\n return (\n <File.Source name={name} isExportable isIndexable>\n <Function\n export\n name={name}\n JSDoc={{ comments: description ? [`@description ${jsStringEscape(description)}`] : [] }}\n params={canOverride ? paramsSignature : undefined}\n returnType={returnType}\n >\n {seed ? (\n <>\n {`faker.seed(${JSON.stringify(seed)})`}\n <br />\n </>\n ) : undefined}\n {`return ${fakerTextWithOverride}`}\n </Function>\n </File.Source>\n )\n }\n\n return (\n <File.Source name={name} isExportable isIndexable>\n {functionSignature}\n {functionBody}\n </File.Source>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,SAAgB,WAAW,MAAsB;AAC/C,KAAI,KAAK,UAAU,GAAG;EACpB,MAAM,QAAQ,KAAK;EACnB,MAAM,OAAO,KAAK,KAAK,SAAS;AAChC,MAAK,UAAU,QAAO,SAAS,QAAS,UAAU,OAAO,SAAS,OAAS,UAAU,OAAO,SAAS,IACnG,QAAO,KAAK,MAAM,GAAG,GAAG;;AAG5B,QAAO;;;;;;;;;;;;;AAcT,SAAgB,eAAe,OAAwB;AACrD,QAAO,GAAG,QAAQ,QAAQ,4BAA4B,cAAc;AAClE,UAAQ,WAAR;GACE,KAAK;GACL,KAAK;GACL,KAAK,KACH,QAAO,KAAK;GACd,KAAK,KACH,QAAO;GACT,KAAK,KACH,QAAO;GACT,KAAK,SACH,QAAO;GACT,KAAK,SACH,QAAO;GACT,QACE,QAAO;;GAEX;;;;;;;;;;;;;;;;;;;AC7BJ,SAAgB,oBAAoB,QAAyB;AAC3D,KAAI,CAAC,OACH,QAAO;CAGT,MAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,OAAM,KAAK,MAAM,GAAI,aAAa;AAClC,QAAO,QAAQ,MAAM,KAAK,IAAI;;;;;AAMhC,SAAgB,kBAAkB,MAA+B;AAC/D,QAAO,IAAI,IAA4B;EACrC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CAAC,IAAI,KAAK,KAAK;;;;;;AAOnB,SAAgB,iBAAiB,MAAsB,SAAgD;AACrG,KAAI,KAAK,SAAS,MAChB,QAAO;AAGT,QAAO,QAAQ,MAAM,WAAW,OAAO,SAAS,KAAK,QAAQ,OAAO,SAAS,MAAM,IAAI;;;;;AAMzF,SAAgB,2BACd,UACA,MACA,OACQ;AACR,SAAQ,MAAM,IAAd;EACE,KAAK,OACH,QAAO,SAAS,sBAAsB,MAAM,MAAM;EACpD,KAAK,QACH,QAAO,SAAS,uBAAuB,MAAM,MAAM;EACrD,KAAK,SACH,QAAO,SAAS,wBAAwB,MAAM,MAAM;EACtD,QACE,QAAO,SAAS,iBAAiB,MAAM,MAAM;;;AAInD,SAAS,iCAAiC,QAAiC;AACzE,QAAO,IAAI,IAA4B;EACrC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CAAC,IAAI,OAAO,KAAK;;;;;;AAOrB,SAAgB,yBAAyB,MAAyB,UAAgD;CAChH,MAAM,YAAY,KAAK,UAAU,QAAQ,aAAa,SAAS,OAAO;AAEtE,KAAI,CAAC,UAAU,OACb,QAAO;AAGT,KAAI,UAAU,WAAW,GAAG;AAC1B,MAAI,iCAAiC,UAAU,GAAI,OAAO,CACxD,QAAO,UAAU,GAAI;AAGvB,SAAOA,WAAAA,IAAI,aAAa;GAAE,MAAM;GAAO,MAAM,SAAS,0BAA0B,MAAM,UAAU,GAAI,WAAW;GAAE,CAAC;;AAGpH,QAAOA,WAAAA,IAAI,aAAa;EACtB,MAAM;EACN,SAAS,UAAU,KAAK,aAAaA,WAAAA,IAAI,aAAa;GAAE,MAAM;GAAO,MAAM,SAAS,0BAA0B,MAAM,SAAS,WAAW;GAAE,CAAC,CAAC;EAC7I,CAAC;;AAgBJ,MAAMC,iBAAe,IAAI,IAA4B;CACnD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AACF,MAAMC,gBAAc,IAAI,IAA4B,CAAC,QAAQ,CAAC;AAE9D,SAAS,qBAAqB,MAAc,IAAoB;CAC9D,MAAM,eAAeC,UAAAA,MAAM,SAASA,UAAAA,MAAM,QAAQ,KAAK,EAAE,GAAG;AAC5D,QAAO,aAAa,WAAW,MAAM,GAAG,eAAe,KAAK;;AAG9D,SAAS,aAAa,OAAuB;AAC3C,QAAO,MAAM,QAAQ,uBAAuB,OAAO;;;;;;AAOrD,SAAgB,kBAAkB,SAA6B,MAAc,kBAAiC,EAAE,EAAsB;AACpI,QAAO,QAAQ,QAAQ,UAAU;AAW/B,UAVe,MAAM,QAAQ,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,KAAK,EACjE,KAAK,SAAS;AACb,OAAI,OAAO,SAAS,SAClB,QAAO;AAGT,UAAO,MAAM,QAAQ,MAAM;IAC3B,CACD,QAAQ,SAAyB,QAAQ,KAAK,CAErC,CAAC,MAAM,SAAS;AAC1B,OAAI,gBAAgB,SAAS,KAAK,CAChC,QAAO;AAGT,UAAO,IAAI,OAAO,MAAM,aAAa,KAAK,CAAC,gBAAgB,CAAC,KAAK,KAAK;IACtE;GACF;;;;;;AAOJ,SAAgB,wBACd,SACA,eAC+D;CAC/D,MAAM,kBAAkB,IAAI,IAAI,cAAc;CAC9C,MAAM,0BAAU,IAAI,KAAqB;AAuBzC,QAAO;EACL,SAtBqB,QAAQ,KAAK,UAAU;GAE5C,MAAM,gBADQ,MAAM,QAAQ,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,KAAK,EACxC,KAAK,SAAqB;AACnD,QAAI,OAAO,SAAS,YAAY,CAAC,gBAAgB,IAAI,KAAK,CACxD,QAAO;IAGT,MAAM,QAAQ,GAAG,KAAK;AACtB,YAAQ,IAAI,MAAM,MAAM;AAExB,WAAO;KAAE,cAAc;KAAM,MAAM;KAAO;KAC1C;AAEF,UAAO,aAAa,MAAM,SAAS,OAAO,SAAS,YAAY,KAAK,KAAK,GACrE;IACE,GAAG;IACH,MAAM;IACP,GACD;IAImB;EACvB;EACD;;;;;AAMH,SAAgB,sBAAsB,MAAc,SAA8C;AAChG,QAAO,MAAM,KAAK,QAAQ,CAAC,QAAQ,KAAK,CAAC,MAAM,WAAW,IAAI,QAAQ,IAAI,OAAO,MAAM,aAAa,KAAK,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,KAAK;;;;;;AAOrI,SAAgB,qBAAqB,EACnC,MACA,aACA,MACA,UACA,UACA,gBAQ4C;CAC5C,MAAM,EAAE,iBAAiB,sBAAsB,MAAM,UAAU,YAAY;AAE3E,KAAI,CAAC,aACH,QAAO,EAAE,UAAU;AAGrB,KAAI,SAAS,SACX,QAAO,EACL,UAAU,WAAW,qBAAqB,UAAU,aAAa,CAAC,KAAK,YACxE;AAGH,QAAO;EACL,YAAY;EACZ;EACD;;;;;;AAOH,SAAgB,cAAc,MAAsB,UAA0B;AAC5E,SAAQ,KAAK,MAAb;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,OACH,QAAO;EACT,KAAK;EACL,KAAK,UACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK;EACL,KAAK,OACH,QAAO,KAAK,mBAAmB,SAAS,SAAS;EACnD,KAAK,WACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,QACE,QAAO;;;;;;;AAQb,SAAgB,sBACd,MACA,UACA,aAKA;CACA,MAAM,UAAUD,cAAY,IAAI,KAAK,KAAK;CAC1C,MAAM,UAAU,KAAK,SAAS;CAC9B,MAAM,WAAWD,eAAa,IAAI,KAAK,KAAK;CAE5C,IAAI,WAAW,WAAW,SAAS;AAEnC,KAAI,WAAW,WAAW,KAAK,SAAS,WAAW,KAAK,SAAS,OAC/D,YAAW;AAGb,KAAI,SACF,YAAW,cAAc,MAAM,SAAS;CAG1C,IAAI,aAAa,cAAc,WAAW,KAAA;AAE1C,KAAI,SACF,cAAa,cAAc,MAAM,SAAS;AAG5C,QAAO;EACL;EACA;EACA,cAAc,SAAS,SAAS,SAAS,IAAI,QAAQ,YAAY,SAAS,SAAS,CAAC;EACrF;;;;AC/UH,MAAM,eAAe,IAAI,IAA4B,CAAC,UAAU,eAAe,CAAC;AAChF,MAAM,cAAc,IAAI,IAA4B,CAAC,QAAQ,CAAC;AAC9D,MAAM,eAAe,IAAI,IAA4B;CACnD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AACF,MAAM,sBAAA,GAAA,gBAAA,iBAAqC,EAAE,MAAM,eAAe,CAAC;AAEnE,SAAgB,MAAM,EAAE,MAAM,aAAa,MAAM,UAAU,SAAS,MAAM,eAAqC;CAC7G,MAAM,YAAY,QAAQ,MAAM,KAAK,IAAI;CAEzC,MAAM,UAAU,YAAY,IAAI,KAAK,KAAK;CAC1C,MAAM,WAAW,aAAa,IAAI,KAAK,KAAK;CAC5C,MAAM,UAAU,KAAK,SAAS;CAC9B,MAAM,WAAW,aAAa,IAAI,KAAK,KAAK;CAE5C,IAAI,wBAAwB;CAC5B,IAAI,qBAAqB;AAEzB,KAAI,eAAe,SACjB,sBAAqB;AAGvB,KAAI,eAAe,QACjB,yBAAwB,WAAW;AAGrC,KAAI,eAAe,QACjB,yBAAwB;OACrB,UAAU;;;AAKf,KAAI,eAAe,SACjB,yBAAwB,WAAW;CAGrC,MAAM,EAAE,UAAU,YAAY,uBAAuB,sBAAsB,MAAM,UAAU,YAAY;CAEvG,IAAI,oBAAoB;CACxB,IAAI,eAAe;AAEnB,KAAI,oBAAoB;AAGtB,sBAAoB,GADN,cAAc,0BAA0B,eAAe,YAAY,CAAC,eAAe,GACpE,kBAAkB,KAAK,kBAAkB,SAAS,eAAe,SAAS;EAEvG,MAAM,WAAW,OAAO,cAAc,KAAK,UAAU,KAAK,CAAC,SAAS;EAOpE,MAAM,EAAE,eAAe,eAAe,QAAQ;AAM9C,MAJE,KAAK,SAAS,YACd,CAAC,CAAC,kBACD,KAAK,cAAc,EAAE,EAAE,MAAM,MAAMG,WAAAA,IAAI,oBAAoB,EAAE,QAAQ;GAAE,iBAAiB;GAAe,aAAa;GAAY,CAAC,CAAC,CAGnI,gBAAe;IACjB,SAAS,0BAA0B,UAAU;;;;;;uCAMV,SAAS;;MAG1C,gBAAe;IACjB,SAAS,0BAA0B,UAAU;;;;kBAI/B,SAAS;;QAGlB;EAEL,MAAM,gBADW,WAAW,KAAK,sBACH,GAAG,SAAS;EAC1C,MAAM,SAASA,WAAAA,IAAI,yBAAyB,EAC1C,QAAQ,CACNA,WAAAA,IAAI,wBAAwB;GAC1B,MAAM;GACN,MAAMA,WAAAA,IAAI,iBAAiB;IAAE,SAAS;IAAa,MAAM;IAAU,CAAC;GACpE,UAAU;GACX,CAAC,CACH,EACF,CAAC;EACF,MAAM,kBAAkB,mBAAmB,MAAM,OAAO,IAAI;EAC5D,MAAM,aAAa;AAEnB,SACE,iBAAA,GAAA,+BAAA,KAACC,mBAAAA,KAAK,QAAN;GAAmB;GAAM,cAAA;GAAa,aAAA;aACpC,iBAAA,GAAA,+BAAA,MAACC,mBAAAA,UAAD;IACE,QAAA;IACM;IACN,OAAO,EAAE,UAAU,cAAc,CAAC,gBAAgB,eAAe,YAAY,GAAG,GAAG,EAAE,EAAE;IACvF,QAAQ,cAAc,kBAAkB,KAAA;IAC5B;cALd,CAOG,OACC,iBAAA,GAAA,+BAAA,MAAA,+BAAA,UAAA,EAAA,UAAA,CACG,cAAc,KAAK,UAAU,KAAK,CAAC,IACpC,iBAAA,GAAA,+BAAA,KAAC,MAAD,EAAM,CAAA,CACL,EAAA,CAAA,GACD,KAAA,GACH,UAAU,wBACF;;GACC,CAAA;;AAIlB,QACE,iBAAA,GAAA,+BAAA,MAACD,mBAAAA,KAAK,QAAN;EAAmB;EAAM,cAAA;EAAa,aAAA;YAAtC,CACG,mBACA,aACW"}