prisma-generator-express 1.18.0 → 1.20.0

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 (76) hide show
  1. package/README.md +399 -194
  2. package/dist/bin.d.ts +2 -0
  3. package/dist/bin.js +1 -1
  4. package/dist/bin.js.map +1 -1
  5. package/dist/client/encodeQueryParams.d.ts +1 -0
  6. package/dist/client/encodeQueryParams.js +33 -0
  7. package/dist/client/encodeQueryParams.js.map +1 -0
  8. package/dist/constants.d.ts +1 -0
  9. package/dist/copy/misc.d.ts +5 -0
  10. package/dist/copy/misc.js +52 -0
  11. package/dist/copy/misc.js.map +1 -0
  12. package/dist/generators/generateImportPrismaStatement.d.ts +3 -0
  13. package/dist/generators/generateImportPrismaStatement.js +55 -0
  14. package/dist/generators/generateImportPrismaStatement.js.map +1 -0
  15. package/dist/generators/generateQueryBuilderHelper.d.ts +2 -0
  16. package/dist/generators/generateQueryBuilderHelper.js +139 -0
  17. package/dist/generators/generateQueryBuilderHelper.js.map +1 -0
  18. package/dist/generators/generateRouter.d.ts +6 -0
  19. package/dist/generators/generateRouter.js +340 -0
  20. package/dist/generators/generateRouter.js.map +1 -0
  21. package/dist/generators/generateUnifiedDocs.d.ts +1 -0
  22. package/dist/generators/generateUnifiedDocs.js +171 -0
  23. package/dist/generators/generateUnifiedDocs.js.map +1 -0
  24. package/dist/generators/generateUnifiedHandler.d.ts +6 -0
  25. package/dist/generators/generateUnifiedHandler.js +444 -0
  26. package/dist/generators/generateUnifiedHandler.js.map +1 -0
  27. package/dist/generators/generateUnifiedScalarUI.d.ts +5 -0
  28. package/dist/generators/generateUnifiedScalarUI.js +1390 -0
  29. package/dist/generators/generateUnifiedScalarUI.js.map +1 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.js +80 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/utils/copyFiles.d.ts +6 -0
  34. package/dist/utils/copyFiles.js +123 -21
  35. package/dist/utils/copyFiles.js.map +1 -1
  36. package/dist/utils/strings.d.ts +2 -0
  37. package/dist/utils/writeFileSafely.d.ts +10 -0
  38. package/dist/utils/writeFileSafely.js +86 -14
  39. package/dist/utils/writeFileSafely.js.map +1 -1
  40. package/package.json +59 -28
  41. package/src/bin.ts +1 -1
  42. package/src/client/encodeQueryParams.ts +56 -0
  43. package/src/copy/buildModelOpenApi.ts +1569 -0
  44. package/src/copy/misc.ts +21 -0
  45. package/src/copy/operationDefinitions.ts +96 -0
  46. package/src/copy/parseQueryParams.ts +36 -21
  47. package/src/copy/routeConfig.ts +68 -28
  48. package/src/generators/generateImportPrismaStatement.ts +78 -0
  49. package/src/generators/generateQueryBuilderHelper.ts +138 -0
  50. package/src/generators/generateRouter.ts +352 -0
  51. package/src/generators/generateUnifiedDocs.ts +168 -0
  52. package/src/generators/generateUnifiedHandler.ts +469 -0
  53. package/src/generators/generateUnifiedScalarUI.ts +1409 -0
  54. package/src/index.ts +100 -0
  55. package/src/utils/copyFiles.ts +123 -16
  56. package/src/utils/writeFileSafely.ts +79 -25
  57. package/dist/generator.js +0 -47
  58. package/dist/generator.js.map +0 -1
  59. package/dist/helpers/generateImportPrismaStatement.js +0 -25
  60. package/dist/helpers/generateImportPrismaStatement.js.map +0 -1
  61. package/dist/helpers/generateOperation.js +0 -471
  62. package/dist/helpers/generateOperation.js.map +0 -1
  63. package/dist/helpers/generateRouteFile.js +0 -210
  64. package/dist/helpers/generateRouteFile.js.map +0 -1
  65. package/dist/utils/formatFile.js +0 -26
  66. package/dist/utils/formatFile.js.map +0 -1
  67. package/src/copy/encodeQueryParams.spec.ts +0 -303
  68. package/src/copy/encodeQueryParams.ts +0 -44
  69. package/src/copy/misc.spec.ts +0 -62
  70. package/src/copy/parseQueryParams.spec.ts +0 -187
  71. package/src/copy/transformZod.spec.ts +0 -763
  72. package/src/generator.ts +0 -54
  73. package/src/helpers/generateImportPrismaStatement.ts +0 -38
  74. package/src/helpers/generateOperation.ts +0 -515
  75. package/src/helpers/generateRouteFile.ts +0 -213
  76. package/src/utils/formatFile.ts +0 -22
package/src/index.ts ADDED
@@ -0,0 +1,100 @@
1
+ import {
2
+ generatorHandler,
3
+ GeneratorOptions,
4
+ DMMF,
5
+ } from '@prisma/generator-helper'
6
+ import { generateUnifiedHandler } from './generators/generateUnifiedHandler'
7
+ import { generateRouterFunction } from './generators/generateRouter'
8
+ import { generateScalarUIHandler } from './generators/generateUnifiedScalarUI'
9
+ import { generateUnifiedDocs } from './generators/generateUnifiedDocs'
10
+ import { generateQueryBuilderHelper } from './generators/generateQueryBuilderHelper'
11
+ import {
12
+ generateImportPrismaStatement,
13
+ getRelativeClientPath,
14
+ } from './generators/generateImportPrismaStatement'
15
+ import { writeFileSafely } from './utils/writeFileSafely'
16
+ import { copyFiles } from './utils/copyFiles'
17
+ import { GENERATOR_NAME } from './constants'
18
+
19
+ generatorHandler({
20
+ onManifest() {
21
+ return {
22
+ version: require('../package.json').version,
23
+ defaultOutput: '../generated',
24
+ prettyName: GENERATOR_NAME,
25
+ }
26
+ },
27
+
28
+ async onGenerate(options: GeneratorOptions) {
29
+ const prismaImportStatement = generateImportPrismaStatement(options)
30
+
31
+ console.log('\n═══ Prisma Generator Express ═══')
32
+
33
+ await copyFiles(options)
34
+
35
+ const modelNames: string[] = []
36
+
37
+ for (const model of options.dmmf.datamodel.models) {
38
+ if (
39
+ model.documentation &&
40
+ model.documentation.includes('generator off')
41
+ ) {
42
+ console.log(` Skipping: ${model.name} (generator off)`)
43
+ continue
44
+ }
45
+
46
+ modelNames.push(model.name)
47
+
48
+ const relativeClientPath = getRelativeClientPath(options, model.name)
49
+
50
+ await writeFileSafely({
51
+ content: generateUnifiedHandler({
52
+ model: model as DMMF.Model,
53
+ prismaImportStatement,
54
+ }),
55
+ options,
56
+ model: model as DMMF.Model,
57
+ operation: 'Handlers',
58
+ })
59
+
60
+ await writeFileSafely({
61
+ content: generateRouterFunction({
62
+ model: model as DMMF.Model,
63
+ enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
64
+ relativeClientPath,
65
+ }),
66
+ options,
67
+ model: model as DMMF.Model,
68
+ operation: 'Router',
69
+ })
70
+
71
+ await writeFileSafely({
72
+ content: generateScalarUIHandler({
73
+ model: model as DMMF.Model,
74
+ enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
75
+ }),
76
+ options,
77
+ model: model as DMMF.Model,
78
+ operation: 'Docs',
79
+ })
80
+ }
81
+
82
+ await writeFileSafely({
83
+ content: generateUnifiedDocs(modelNames),
84
+ options,
85
+ operation: 'combinedDocs',
86
+ })
87
+
88
+ await writeFileSafely({
89
+ content: generateQueryBuilderHelper(options),
90
+ options,
91
+ operation: 'queryBuilder',
92
+ })
93
+
94
+ console.log('\n═══ Generation Complete ═══')
95
+ console.log(`✓ ${modelNames.length} models`)
96
+ console.log(`✓ OpenAPI documentation generated`)
97
+ console.log(`✓ Query builder helper generated`)
98
+ console.log('')
99
+ },
100
+ })
@@ -1,27 +1,134 @@
1
1
  import { GeneratorOptions } from '@prisma/generator-helper'
2
- import fs from 'fs/promises'
3
- import path from 'path'
2
+ import * as fs from 'fs'
3
+ import * as path from 'path'
4
4
 
5
- export const copyFiles = async (
5
+ export interface CopyFilesConfig {
6
+ includeCacheUtils?: boolean
7
+ includeValidatorUtils?: boolean
8
+ }
9
+
10
+ export async function copyFiles(
6
11
  options: GeneratorOptions,
7
- destPath?: string,
8
- ) => {
9
- const sourceDir = path.join(__dirname.replace('dist', 'src'), '..', 'copy')
10
- const destinationDir = destPath || options.generator.output?.value!
12
+ config?: CopyFilesConfig,
13
+ ): Promise<void> {
14
+ const copyConfig = config || {}
15
+ const outputPath = options.generator.output?.value
16
+ if (!outputPath) return
17
+
18
+ const srcDir = path.join(__dirname, '..', '..', 'src', 'copy')
19
+
20
+ const baseFiles = [
21
+ 'routeConfig.ts',
22
+ 'parseQueryParams.ts',
23
+ 'buildModelOpenApi.ts',
24
+ 'operationDefinitions.ts',
25
+ 'misc.ts',
26
+ ]
11
27
 
12
- const files = await fs.readdir(sourceDir)
28
+ let allCopied = true
13
29
 
14
- for (const file of files) {
15
- if (file.endsWith('.spec.ts')) {
16
- continue
30
+ console.log(`Copying utility files to: ${outputPath}`)
31
+
32
+ for (const file of baseFiles) {
33
+ const ok = await copyFile(srcDir, outputPath, file, { required: true })
34
+ if (!ok) allCopied = false
35
+ }
36
+
37
+ if (copyConfig.includeCacheUtils) {
38
+ const ok = await copyFile(srcDir, outputPath, 'cacheManager.ts', {
39
+ required: true,
40
+ })
41
+ if (!ok) allCopied = false
42
+ }
43
+
44
+ if (copyConfig.includeValidatorUtils) {
45
+ const ok = await copyFile(srcDir, outputPath, 'inputValidator.ts', {
46
+ required: true,
47
+ })
48
+ if (!ok) allCopied = false
49
+ }
50
+
51
+ const clientDir = path.join(outputPath, 'client')
52
+ if (!fs.existsSync(clientDir)) {
53
+ fs.mkdirSync(clientDir, { recursive: true })
54
+ }
55
+
56
+ const clientSrcDir = path.join(__dirname, '..', '..', 'src', 'client')
57
+ const clientOk = await copyFile(
58
+ clientSrcDir,
59
+ clientDir,
60
+ 'encodeQueryParams.ts',
61
+ {
62
+ required: true,
63
+ importRewrites: [{ from: '../copy/misc', to: '../misc' }],
64
+ },
65
+ )
66
+ if (!clientOk) allCopied = false
67
+
68
+ if (allCopied) {
69
+ console.log(`✓ Utility files copied successfully`)
70
+ } else {
71
+ throw new Error(
72
+ 'One or more required utility files could not be copied. Generation aborted.',
73
+ )
74
+ }
75
+ }
76
+
77
+ interface CopyFileOptions {
78
+ required?: boolean
79
+ importRewrites?: Array<{ from: string; to: string }>
80
+ }
81
+
82
+ async function copyFile(
83
+ srcDir: string,
84
+ destDir: string,
85
+ filename: string,
86
+ options?: CopyFileOptions,
87
+ ): Promise<boolean> {
88
+ const srcPath = path.join(srcDir, filename)
89
+ const destPath = path.join(destDir, filename)
90
+
91
+ if (!fs.existsSync(srcPath)) {
92
+ if (options?.required) {
93
+ console.error(`✗ Required source file not found: ${srcPath}`)
94
+ return false
95
+ }
96
+ console.warn(`⚠️ Source file not found: ${srcPath}`)
97
+ return true
98
+ }
99
+
100
+ const destDirPath = path.dirname(destPath)
101
+ if (!fs.existsSync(destDirPath)) {
102
+ fs.mkdirSync(destDirPath, { recursive: true })
103
+ }
104
+
105
+ let content = fs.readFileSync(srcPath, 'utf-8')
106
+
107
+ if (options?.importRewrites) {
108
+ for (const rewrite of options.importRewrites) {
109
+ content = content.replace(
110
+ new RegExp(`from ['"]${escapeRegex(rewrite.from)}['"]`, 'g'),
111
+ `from '${rewrite.to}'`,
112
+ )
17
113
  }
114
+ }
115
+
116
+ const header = `/**
117
+ * Auto-generated by prisma-generator-express
118
+ * DO NOT EDIT MANUALLY
119
+ */
18
120
 
19
- const sourceFile = path.join(sourceDir, file)
20
- const destinationFile = path.join(destinationDir, file)
121
+ `
21
122
 
22
- await fs.mkdir(path.dirname(destinationFile), { recursive: true })
23
- await fs.copyFile(sourceFile, destinationFile)
123
+ if (!content.startsWith('/**')) {
124
+ content = header + content
24
125
  }
25
126
 
26
- console.log(`Files copied from ${sourceDir} to ${destinationDir}`)
127
+ fs.writeFileSync(destPath, content)
128
+ console.log(` ✓ Copied: ${filename}`)
129
+ return true
27
130
  }
131
+
132
+ function escapeRegex(str: string): string {
133
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
134
+ }
@@ -1,29 +1,83 @@
1
- import fs from 'fs/promises'
2
- import path from 'path'
3
- import { formatFile } from './formatFile'
4
- import { DMMF, GeneratorOptions } from '@prisma/generator-helper'
1
+ import { GeneratorOptions } from '@prisma/generator-helper'
2
+ import { DMMF } from '@prisma/generator-helper'
3
+ import * as fs from 'fs'
4
+ import * as path from 'path'
5
+ import prettier from 'prettier'
5
6
 
6
- export const writeFileSafely = async ({
7
- model,
8
- operation,
9
- options,
10
- content,
11
- }: {
7
+ interface WriteFileOptions {
8
+ content: string
9
+ options: GeneratorOptions
12
10
  model?: DMMF.Model
13
11
  operation: string
14
- options: GeneratorOptions
15
- content: string
16
- }) => {
17
- const fileName =
18
- operation === 'index' ? 'index' : `${model?.name || ''}${operation}`
19
- const filePath = path.join(
20
- options.generator.output?.value!,
21
- model ? `${model?.name}/${fileName}.ts` : `/${fileName}.ts`,
22
- )
23
- console.log('filePath :>> ', filePath)
24
- await fs.mkdir(path.dirname(filePath), {
25
- recursive: true,
26
- })
27
-
28
- await fs.writeFile(filePath, await formatFile(content))
12
+ }
13
+
14
+ let _prettierOptions: prettier.Options | null | undefined
15
+
16
+ async function getPrettierOptions(): Promise<prettier.Options | null> {
17
+ if (_prettierOptions !== undefined) return _prettierOptions
18
+ _prettierOptions = await prettier.resolveConfig(process.cwd())
19
+ return _prettierOptions
20
+ }
21
+
22
+ export async function writeFileSafely({
23
+ content,
24
+ options,
25
+ model,
26
+ operation,
27
+ }: WriteFileOptions): Promise<void> {
28
+ const outputPath = options.generator.output?.value
29
+ if (!outputPath) {
30
+ throw new Error('Output path not defined')
31
+ }
32
+
33
+ let filePath: string
34
+
35
+ switch (operation) {
36
+ case 'cacheConfig':
37
+ filePath = path.join(outputPath, 'cacheConfig.ts')
38
+ break
39
+
40
+ case 'types/inputs':
41
+ filePath = path.join(outputPath, 'types', 'inputs.ts')
42
+ break
43
+
44
+ case 'combinedDocs':
45
+ filePath = path.join(outputPath, 'combinedDocs.ts')
46
+ break
47
+
48
+ case 'queryBuilder':
49
+ filePath = path.join(outputPath, 'queryBuilder.ts')
50
+ break
51
+
52
+ default:
53
+ if (!model) {
54
+ throw new Error(`Model required for operation: ${operation}`)
55
+ }
56
+ filePath = path.join(
57
+ outputPath,
58
+ model.name,
59
+ `${model.name}${operation}.ts`,
60
+ )
61
+ }
62
+
63
+ const dirPath = path.dirname(filePath)
64
+ if (!fs.existsSync(dirPath)) {
65
+ fs.mkdirSync(dirPath, { recursive: true })
66
+ }
67
+
68
+ let formattedContent: string
69
+ try {
70
+ const resolvedOptions = await getPrettierOptions()
71
+ formattedContent = await prettier.format(content, {
72
+ ...resolvedOptions,
73
+ parser: 'typescript',
74
+ })
75
+ } catch (error) {
76
+ console.warn(
77
+ `⚠️ Prettier formatting failed for ${path.basename(filePath)}, writing unformatted`,
78
+ )
79
+ formattedContent = content
80
+ }
81
+
82
+ fs.writeFileSync(filePath, formattedContent)
29
83
  }
package/dist/generator.js DELETED
@@ -1,47 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const generator_helper_1 = require("@prisma/generator-helper");
4
- const sdk_1 = require("@prisma/sdk");
5
- const constants_1 = require("./constants");
6
- const writeFileSafely_1 = require("./utils/writeFileSafely");
7
- const generateImportPrismaStatement_1 = require("./helpers/generateImportPrismaStatement");
8
- const generateRouteFile_1 = require("./helpers/generateRouteFile");
9
- const generateOperation_1 = require("./helpers/generateOperation");
10
- const copyFiles_1 = require("./utils/copyFiles");
11
- const { version } = require('../package.json');
12
- (0, generator_helper_1.generatorHandler)({
13
- onManifest() {
14
- sdk_1.logger.info(`${constants_1.GENERATOR_NAME}:Registered`);
15
- return {
16
- version,
17
- defaultOutput: '../generated',
18
- prettyName: constants_1.GENERATOR_NAME,
19
- };
20
- },
21
- onGenerate: async (options) => {
22
- const prismaImportStatement = (0, generateImportPrismaStatement_1.generateImportPrismaStatement)(options);
23
- for await (const model of options.dmmf.datamodel.models) {
24
- if (model.documentation &&
25
- model.documentation.includes('generator off')) {
26
- sdk_1.logger.info(`Skipping generation for model ${model.name} as it is marked with 'generator off'.`);
27
- continue;
28
- }
29
- for (const cfg of generateOperation_1.OPERATION_CONFIGS) {
30
- await (0, writeFileSafely_1.writeFileSafely)({
31
- content: (0, generateOperation_1.generateOperationFunction)(cfg, model, prismaImportStatement),
32
- options,
33
- model,
34
- operation: cfg.operation,
35
- });
36
- }
37
- await (0, writeFileSafely_1.writeFileSafely)({
38
- content: (0, generateRouteFile_1.generateRouterFunction)({ model }),
39
- options,
40
- model,
41
- operation: 'index',
42
- });
43
- }
44
- await (0, copyFiles_1.copyFiles)(options);
45
- },
46
- });
47
- //# sourceMappingURL=generator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":";;AAAA,+DAA6E;AAC7E,qCAAoC;AACpC,2CAA4C;AAC5C,6DAAyD;AACzD,2FAAuF;AACvF,mEAAoE;AACpE,mEAA0F;AAC1F,iDAA6C;AAE7C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;AAE9C,IAAA,mCAAgB,EAAC;IACf,UAAU;QACR,YAAM,CAAC,IAAI,CAAC,GAAG,0BAAc,aAAa,CAAC,CAAA;QAC3C,OAAO;YACL,OAAO;YACP,aAAa,EAAE,cAAc;YAC7B,UAAU,EAAE,0BAAc;SAC3B,CAAA;IACH,CAAC;IACD,UAAU,EAAE,KAAK,EAAE,OAAyB,EAAE,EAAE;QAC9C,MAAM,qBAAqB,GAAG,IAAA,6DAA6B,EAAC,OAAO,CAAC,CAAA;QAEpE,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YACxD,IACE,KAAK,CAAC,aAAa;gBACnB,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,eAAe,CAAC,EAC7C,CAAC;gBACD,YAAM,CAAC,IAAI,CACT,iCAAiC,KAAK,CAAC,IAAI,wCAAwC,CACpF,CAAA;gBACD,SAAQ;YACV,CAAC;YAED,KAAK,MAAM,GAAG,IAAI,qCAAiB,EAAE,CAAC;gBACpC,MAAM,IAAA,iCAAe,EAAC;oBACpB,OAAO,EAAE,IAAA,6CAAyB,EAAC,GAAG,EAAE,KAAK,EAAE,qBAAqB,CAAC;oBACrE,OAAO;oBACP,KAAK;oBACL,SAAS,EAAE,GAAG,CAAC,SAAS;iBACzB,CAAC,CAAA;YACJ,CAAC;YAED,MAAM,IAAA,iCAAe,EAAC;gBACpB,OAAO,EAAE,IAAA,0CAAsB,EAAC,EAAE,KAAK,EAAE,CAAC;gBAC1C,OAAO;gBACP,KAAK;gBACL,SAAS,EAAE,OAAO;aACnB,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,IAAA,qBAAS,EAAC,OAAO,CAAC,CAAA;IAC1B,CAAC;CACF,CAAC,CAAA"}
@@ -1,25 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateImportPrismaStatement = generateImportPrismaStatement;
7
- const path_1 = __importDefault(require("path"));
8
- function getImportGeneratorOptions(options) {
9
- var _a, _b;
10
- const clientGenerator = options.otherGenerators.find((gen) => gen.name === 'client');
11
- if (!clientGenerator || !((_a = clientGenerator.output) === null || _a === void 0 ? void 0 : _a.value)) {
12
- throw new Error('Prisma client generator not found.');
13
- }
14
- const modelDirPath = path_1.default.join((_b = options.generator.output) === null || _b === void 0 ? void 0 : _b.value, 'modelFolder');
15
- const clientOutputPath = clientGenerator.output.value;
16
- const relativeImportPath = path_1.default.relative(modelDirPath, clientOutputPath);
17
- return {
18
- outputPath: relativeImportPath.split(path_1.default.sep).join(path_1.default.posix.sep),
19
- };
20
- }
21
- function generateImportPrismaStatement(generatorOptions) {
22
- const options = getImportGeneratorOptions(generatorOptions);
23
- return `import type { Prisma } from '${options.outputPath}';\nimport type { PrismaClient } from '${options.outputPath}';\n`;
24
- }
25
- //# sourceMappingURL=generateImportPrismaStatement.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generateImportPrismaStatement.js","sourceRoot":"","sources":["../../src/helpers/generateImportPrismaStatement.ts"],"names":[],"mappings":";;;;;AA+BA,sEAMC;AApCD,gDAAuB;AAMvB,SAAS,yBAAyB,CAChC,OAAyB;;IAEzB,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,IAAI,CAClD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,CAC/B,CAAA;IAED,IAAI,CAAC,eAAe,IAAI,CAAC,CAAA,MAAA,eAAe,CAAC,MAAM,0CAAE,KAAK,CAAA,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IAED,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAC5B,MAAA,OAAO,CAAC,SAAS,CAAC,MAAM,0CAAE,KAAM,EAChC,aAAa,CACd,CAAA;IACD,MAAM,gBAAgB,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,CAAA;IAErD,MAAM,kBAAkB,GAAG,cAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAA;IAExE,OAAO;QACL,UAAU,EAAE,kBAAkB,CAAC,KAAK,CAAC,cAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAI,CAAC,KAAK,CAAC,GAAG,CAAC;KACpE,CAAA;AACH,CAAC;AAED,SAAgB,6BAA6B,CAC3C,gBAAkC;IAElC,MAAM,OAAO,GAAG,yBAAyB,CAAC,gBAAgB,CAAC,CAAA;IAE3D,OAAO,gCAAgC,OAAO,CAAC,UAAU,0CAA0C,OAAO,CAAC,UAAU,MAAM,CAAA;AAC7H,CAAC"}