codeguard-testgen 1.0.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.
@@ -0,0 +1,291 @@
1
+ "use strict";
2
+ /**
3
+ * Codebase Indexer - Caches AST analysis for faster test generation
4
+ *
5
+ * This is completely optional. Test generation works fine without it,
6
+ * but indexing provides significant speed improvements.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.CodebaseIndexer = void 0;
10
+ const fs = require("fs");
11
+ const fsPromises = require("fs/promises");
12
+ const path = require("path");
13
+ const crypto = require("crypto");
14
+ class CodebaseIndexer {
15
+ constructor() {
16
+ this.indexPath = '.codeguard-cache';
17
+ this.indexFile = '.codeguard-cache/index.json';
18
+ this.index = null;
19
+ this.version = '1.0.0';
20
+ // Ensure cache directory exists
21
+ if (!fs.existsSync(this.indexPath)) {
22
+ fs.mkdirSync(this.indexPath, { recursive: true });
23
+ }
24
+ }
25
+ /**
26
+ * Check if index exists and is valid
27
+ */
28
+ hasIndex() {
29
+ return fs.existsSync(this.indexFile);
30
+ }
31
+ /**
32
+ * Load index from disk
33
+ */
34
+ async loadIndex() {
35
+ try {
36
+ if (!this.hasIndex()) {
37
+ return false;
38
+ }
39
+ const data = await fsPromises.readFile(this.indexFile, 'utf-8');
40
+ this.index = JSON.parse(data);
41
+ // Verify version
42
+ if (this.index.version !== this.version) {
43
+ console.log('⚠️ Index version mismatch. Will rebuild.');
44
+ this.index = null;
45
+ return false;
46
+ }
47
+ return true;
48
+ }
49
+ catch (error) {
50
+ console.log('⚠️ Failed to load index. Will rebuild.');
51
+ this.index = null;
52
+ return false;
53
+ }
54
+ }
55
+ /**
56
+ * Build complete index from scratch
57
+ */
58
+ async buildIndex(rootDir, analyzeFileFn, progressCallback) {
59
+ console.log(`🔍 Scanning ${rootDir}...`);
60
+ // Get all source files
61
+ const files = await this.getAllSourceFiles(rootDir);
62
+ console.log(`📂 Found ${files.length} files to index\n`);
63
+ // Initialize index
64
+ this.index = {
65
+ version: this.version,
66
+ createdAt: Date.now(),
67
+ lastUpdated: Date.now(),
68
+ files: {},
69
+ testMapping: {}
70
+ };
71
+ // Process each file
72
+ for (let i = 0; i < files.length; i++) {
73
+ const file = files[i];
74
+ if (progressCallback) {
75
+ progressCallback(i + 1, files.length, file);
76
+ }
77
+ try {
78
+ // Get file metadata
79
+ const stats = fs.statSync(file);
80
+ const content = fs.readFileSync(file, 'utf-8');
81
+ const hash = this.calculateHash(content);
82
+ // Analyze file
83
+ const analysis = analyzeFileFn(file);
84
+ if (analysis.success) {
85
+ this.index.files[file] = {
86
+ metadata: {
87
+ path: file,
88
+ hash,
89
+ lastModified: stats.mtimeMs,
90
+ size: stats.size
91
+ },
92
+ analysis: analysis.analysis
93
+ };
94
+ // Check for corresponding test file
95
+ const testFile = this.findTestFile(file);
96
+ if (testFile) {
97
+ this.index.testMapping[file] = testFile;
98
+ }
99
+ }
100
+ }
101
+ catch (error) {
102
+ console.log(` ⚠️ Skipped ${file}: ${error.message}`);
103
+ }
104
+ }
105
+ // Save index
106
+ await this.saveIndex();
107
+ console.log(`\n✅ Index built successfully!`);
108
+ console.log(` Indexed ${Object.keys(this.index.files).length} files`);
109
+ console.log(` Cache saved to ${this.indexPath}/\n`);
110
+ }
111
+ /**
112
+ * Update index for changed files only
113
+ */
114
+ async updateIndex(changedFiles, analyzeFileFn) {
115
+ if (!this.index) {
116
+ throw new Error('Index not loaded. Call loadIndex() first.');
117
+ }
118
+ console.log(`🔄 Updating ${changedFiles.length} changed files...`);
119
+ for (const file of changedFiles) {
120
+ try {
121
+ const stats = fs.statSync(file);
122
+ const content = fs.readFileSync(file, 'utf-8');
123
+ const hash = this.calculateHash(content);
124
+ // Re-analyze file
125
+ const analysis = analyzeFileFn(file);
126
+ if (analysis.success) {
127
+ this.index.files[file] = {
128
+ metadata: {
129
+ path: file,
130
+ hash,
131
+ lastModified: stats.mtimeMs,
132
+ size: stats.size
133
+ },
134
+ analysis: analysis.analysis
135
+ };
136
+ }
137
+ }
138
+ catch (error) {
139
+ console.log(` ⚠️ Failed to update ${file}: ${error.message}`);
140
+ }
141
+ }
142
+ this.index.lastUpdated = Date.now();
143
+ await this.saveIndex();
144
+ console.log('✅ Index updated!\n');
145
+ }
146
+ /**
147
+ * Save index to disk
148
+ */
149
+ async saveIndex() {
150
+ if (!this.index) {
151
+ throw new Error('No index to save');
152
+ }
153
+ await fsPromises.writeFile(this.indexFile, JSON.stringify(this.index, null, 2), 'utf-8');
154
+ }
155
+ /**
156
+ * Get cached file analysis
157
+ */
158
+ getFileAnalysis(filePath) {
159
+ if (!this.index || !this.index.files[filePath]) {
160
+ return null;
161
+ }
162
+ return this.index.files[filePath].analysis;
163
+ }
164
+ /**
165
+ * Check if file needs re-indexing
166
+ */
167
+ isFileStale(filePath) {
168
+ if (!this.index || !this.index.files[filePath]) {
169
+ return true;
170
+ }
171
+ try {
172
+ const stats = fs.statSync(filePath);
173
+ const cached = this.index.files[filePath].metadata;
174
+ // Check if file was modified
175
+ return stats.mtimeMs > cached.lastModified;
176
+ }
177
+ catch {
178
+ return true;
179
+ }
180
+ }
181
+ /**
182
+ * Get files that need re-indexing
183
+ */
184
+ getStaleFiles() {
185
+ if (!this.index) {
186
+ return [];
187
+ }
188
+ const staleFiles = [];
189
+ for (const filePath in this.index.files) {
190
+ if (this.isFileStale(filePath)) {
191
+ staleFiles.push(filePath);
192
+ }
193
+ }
194
+ return staleFiles;
195
+ }
196
+ /**
197
+ * Get index statistics
198
+ */
199
+ getStats() {
200
+ if (!this.index) {
201
+ return null;
202
+ }
203
+ const fileCount = Object.keys(this.index.files).length;
204
+ const functionCount = Object.values(this.index.files).reduce((sum, f) => sum + f.analysis.functions.length, 0);
205
+ const testCount = Object.values(this.index.testMapping).filter(t => t !== null).length;
206
+ return {
207
+ version: this.index.version,
208
+ fileCount,
209
+ functionCount,
210
+ testCount,
211
+ createdAt: new Date(this.index.createdAt).toLocaleString(),
212
+ lastUpdated: new Date(this.index.lastUpdated).toLocaleString()
213
+ };
214
+ }
215
+ /**
216
+ * Clear index cache
217
+ */
218
+ async clearCache() {
219
+ if (fs.existsSync(this.indexFile)) {
220
+ await fsPromises.unlink(this.indexFile);
221
+ }
222
+ this.index = null;
223
+ console.log('✅ Cache cleared');
224
+ }
225
+ /**
226
+ * Get all source files recursively
227
+ */
228
+ async getAllSourceFiles(dir, fileList = []) {
229
+ const excludeDirs = ['node_modules', 'dist', 'build', '.git', 'coverage', '__tests__', 'tests'];
230
+ const extensions = ['.ts', '.tsx', '.js', '.jsx'];
231
+ const items = await fsPromises.readdir(dir);
232
+ for (const item of items) {
233
+ const fullPath = path.join(dir, item);
234
+ const stat = await fsPromises.stat(fullPath);
235
+ if (stat.isDirectory() && !excludeDirs.includes(item)) {
236
+ await this.getAllSourceFiles(fullPath, fileList);
237
+ }
238
+ else if (stat.isFile()) {
239
+ const ext = path.extname(item);
240
+ if (extensions.includes(ext) &&
241
+ !item.endsWith('.test.ts') &&
242
+ !item.endsWith('.spec.ts') &&
243
+ !item.endsWith('.test.js') &&
244
+ !item.endsWith('.spec.js')) {
245
+ fileList.push(fullPath);
246
+ }
247
+ }
248
+ }
249
+ return fileList;
250
+ }
251
+ /**
252
+ * Find corresponding test file for a source file
253
+ */
254
+ findTestFile(sourceFile) {
255
+ const testDirs = ['tests', '__tests__', 'test', '__test__'];
256
+ const baseName = path.basename(sourceFile).replace(/\.(ts|js)x?$/, '');
257
+ const sourceDir = path.dirname(sourceFile);
258
+ // Try common test file patterns
259
+ const patterns = [
260
+ `${baseName}.test.ts`,
261
+ `${baseName}.spec.ts`,
262
+ `${baseName}.test.js`,
263
+ `${baseName}.spec.js`
264
+ ];
265
+ // Check in same directory
266
+ for (const pattern of patterns) {
267
+ const testPath = path.join(sourceDir, pattern);
268
+ if (fs.existsSync(testPath)) {
269
+ return testPath;
270
+ }
271
+ }
272
+ // Check in test directories
273
+ for (const testDir of testDirs) {
274
+ for (const pattern of patterns) {
275
+ const testPath = path.join(testDir, pattern);
276
+ if (fs.existsSync(testPath)) {
277
+ return testPath;
278
+ }
279
+ }
280
+ }
281
+ return null;
282
+ }
283
+ /**
284
+ * Calculate file hash
285
+ */
286
+ calculateHash(content) {
287
+ return crypto.createHash('md5').update(content).digest('hex');
288
+ }
289
+ }
290
+ exports.CodebaseIndexer = CodebaseIndexer;
291
+ //# sourceMappingURL=codebaseIndexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codebaseIndexer.js","sourceRoot":"","sources":["../src/codebaseIndexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export interface CodeGuardConfig {
2
+ aiProvider: 'openai' | 'gemini' | 'claude';
3
+ apiKeys: {
4
+ claude?: string;
5
+ openai?: string;
6
+ gemini?: string;
7
+ };
8
+ models?: {
9
+ claude?: string;
10
+ openai?: string;
11
+ gemini?: string;
12
+ };
13
+ testDir?: string;
14
+ extensions?: string[];
15
+ excludeDirs?: string[];
16
+ }
17
+ export interface Config {
18
+ extensions: string[];
19
+ excludeDirs: string[];
20
+ testDir: string;
21
+ aiProvider: 'openai' | 'gemini' | 'claude';
22
+ apiKeys: {
23
+ claude?: string;
24
+ openai?: string;
25
+ gemini?: string;
26
+ };
27
+ models: {
28
+ claude: string;
29
+ openai: string;
30
+ gemini: string;
31
+ };
32
+ }
33
+ export declare function loadConfig(): Config;
34
+ export declare function validateConfig(config: Config): void;
35
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC3C,OAAO,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,MAAM,CAAC,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC3C,OAAO,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAQD,wBAAgB,UAAU,IAAI,MAAM,CA4EnC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAuBnD"}
package/dist/config.js ADDED
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadConfig = loadConfig;
4
+ exports.validateConfig = validateConfig;
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+ const DEFAULT_MODELS = {
8
+ claude: 'claude-sonnet-4-5-20250929',
9
+ openai: 'gpt-5-mini',
10
+ gemini: 'gemini-2.0-flash-lite'
11
+ };
12
+ function loadConfig() {
13
+ const configPath = path.join(process.cwd(), 'codeguard.json');
14
+ // Check if config file exists
15
+ if (!fs.existsSync(configPath)) {
16
+ // Fall back to environment variables for backward compatibility
17
+ console.log('⚠️ codeguard.json not found. Using environment variables (deprecated).');
18
+ console.log(' Please create a codeguard.json file in your project root.');
19
+ console.log(' See: https://github.com/yourusername/codeguard-testgen for setup.\n');
20
+ return {
21
+ aiProvider: 'claude',
22
+ testDir: 'src/tests',
23
+ extensions: ['.ts', '.tsx', '.js', '.jsx'],
24
+ excludeDirs: ['node_modules', 'dist', 'build', '.git', 'coverage', '__tests__'],
25
+ apiKeys: {
26
+ claude: process.env.ANTHROPIC_API_KEY,
27
+ openai: process.env.OPENAI_API_KEY,
28
+ gemini: process.env.GEMINI_API_KEY
29
+ },
30
+ models: DEFAULT_MODELS
31
+ };
32
+ }
33
+ // Load and parse config file
34
+ let config;
35
+ try {
36
+ const configContent = fs.readFileSync(configPath, 'utf-8');
37
+ config = JSON.parse(configContent);
38
+ }
39
+ catch (error) {
40
+ throw new Error(`Failed to parse codeguard.json: ${error.message}`);
41
+ }
42
+ // Validate required fields
43
+ if (!config.aiProvider) {
44
+ throw new Error('codeguard.json must specify "aiProvider" (claude, openai, or gemini)');
45
+ }
46
+ if (!['claude', 'openai', 'gemini'].includes(config.aiProvider)) {
47
+ throw new Error(`Invalid aiProvider "${config.aiProvider}". Must be: claude, openai, or gemini`);
48
+ }
49
+ if (!config.apiKeys || typeof config.apiKeys !== 'object') {
50
+ throw new Error('codeguard.json must include "apiKeys" object with API keys');
51
+ }
52
+ // Validate that the selected provider has an API key
53
+ const selectedProviderKey = config.apiKeys[config.aiProvider];
54
+ if (!selectedProviderKey) {
55
+ throw new Error(`API key for "${config.aiProvider}" not found in codeguard.json`);
56
+ }
57
+ // Build final config with defaults
58
+ return {
59
+ aiProvider: config.aiProvider,
60
+ testDir: config.testDir || 'src/tests',
61
+ extensions: config.extensions || ['.ts', '.tsx', '.js', '.jsx'],
62
+ excludeDirs: config.excludeDirs || [
63
+ 'node_modules',
64
+ 'dist',
65
+ 'build',
66
+ '.git',
67
+ 'coverage',
68
+ '__tests__',
69
+ 'tests',
70
+ 'test',
71
+ '.codeguard-cache',
72
+ '.testgen-cache'
73
+ ],
74
+ apiKeys: config.apiKeys,
75
+ models: {
76
+ claude: config.models?.claude || DEFAULT_MODELS.claude,
77
+ openai: config.models?.openai || DEFAULT_MODELS.openai,
78
+ gemini: config.models?.gemini || DEFAULT_MODELS.gemini
79
+ }
80
+ };
81
+ }
82
+ function validateConfig(config) {
83
+ // Validate API key for selected provider
84
+ const apiKey = config.apiKeys[config.aiProvider];
85
+ if (!apiKey) {
86
+ throw new Error(`No API key configured for ${config.aiProvider}`);
87
+ }
88
+ // Validate API key format (basic checks)
89
+ if (config.aiProvider === 'claude' && !apiKey.startsWith('sk-ant-')) {
90
+ console.warn('⚠️ Claude API key should start with "sk-ant-"');
91
+ }
92
+ else if (config.aiProvider === 'openai' && !apiKey.startsWith('sk-')) {
93
+ console.warn('⚠️ OpenAI API key should start with "sk-"');
94
+ }
95
+ // Validate test directory
96
+ if (!config.testDir || config.testDir.trim() === '') {
97
+ throw new Error('testDir cannot be empty');
98
+ }
99
+ // Validate extensions
100
+ if (!config.extensions || config.extensions.length === 0) {
101
+ throw new Error('extensions array cannot be empty');
102
+ }
103
+ }
104
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ /** //This version has lefitimate failure detection and reporting.
3
+ * AI-Powered Unit Test Generator with AST Analysis
4
+ * Supports OpenAI, Gemini, and Claude with function calling
5
+ *
6
+ * Usage: npx ts-node src/testgen.ts
7
+ *
8
+ * Required packages: npm install @babel/parser @babel/traverse ts-node
9
+ *
10
+ * Required environment variables:
11
+ * - OPENAI_API_KEY (for OpenAI)
12
+ * - GEMINI_API_KEY (for Gemini)
13
+ * - ANTHROPIC_API_KEY (for Claude)
14
+ */
15
+ import { CodebaseIndexer } from './codebaseIndexer';
16
+ interface Tool {
17
+ name: string;
18
+ description: string;
19
+ input_schema: {
20
+ type: string;
21
+ properties: Record<string, any>;
22
+ required: string[];
23
+ };
24
+ }
25
+ declare const TOOLS: Tool[];
26
+ declare function analyzeFileAST(filePath: string): any;
27
+ declare function getFunctionAST(filePath: string, functionName: string): any;
28
+ declare function getImportsAST(filePath: string): any;
29
+ declare function getTypeDefinitions(filePath: string): any;
30
+ declare function getClassMethods(filePath: string, className: string): any;
31
+ declare function replaceFunctionTests(testFilePath: string, functionName: string, newTestContent: string): Promise<any>;
32
+ declare function deleteLines(filePath: string, startLine: number, endLine: number): Promise<any>;
33
+ declare function insertLines(filePath: string, lineNumber: number, content: string): Promise<any>;
34
+ declare function replaceLines(filePath: string, startLine: number, endLine: number, newContent: string): Promise<any>;
35
+ declare function executeTool(toolName: string, args: any): Promise<any>;
36
+ declare function generateTests(sourceFile: string): Promise<string>;
37
+ declare function generateTestsForFolder(): Promise<void>;
38
+ declare function generateTestsForFunctions(sourceFile: string, functionNames: string[]): Promise<string>;
39
+ declare function generateTestsForFunction(): Promise<void>;
40
+ declare function main(): Promise<void>;
41
+ export { main, generateTests, generateTestsForFolder, generateTestsForFunction, generateTestsForFunctions, executeTool, analyzeFileAST, getFunctionAST, getImportsAST, getTypeDefinitions, getClassMethods, replaceFunctionTests, deleteLines, insertLines, replaceLines, CodebaseIndexer, TOOLS };
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAaH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA6BpD,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;CACH;AAmED,QAAA,MAAM,KAAK,EAAE,IAAI,EA8UhB,CAAC;AA2BF,iBAAS,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CA4J7C;AAqDD,iBAAS,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,GAAG,CAyCnE;AAyBD,iBAAS,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CA0D5C;AAED,iBAAS,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAuEjD;AAED,iBAAS,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,GAAG,CAoDjE;AAiLD,iBAAe,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA0DpH;AA+JD,iBAAe,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAkC7F;AAED,iBAAe,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA2B9F;AAED,iBAAe,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAkClH;AAyBD,iBAAe,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAwHpE;AA4QD,iBAAe,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsehE;AAmCD,iBAAe,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2DrD;AAGD,iBAAe,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0WrG;AAED,iBAAe,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CA8DvD;AAED,iBAAe,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAyJnC;AAQD,OAAO,EACL,IAAI,EACJ,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,EACzB,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,YAAY,EACZ,eAAe,EACf,KAAK,EACN,CAAC"}