@flagshark/core 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.
Files changed (105) hide show
  1. package/dist/detection/config-adapter.d.ts +16 -0
  2. package/dist/detection/config-adapter.d.ts.map +1 -0
  3. package/dist/detection/config-adapter.js +60 -0
  4. package/dist/detection/config-adapter.js.map +1 -0
  5. package/dist/detection/detectors/cpp.d.ts +17 -0
  6. package/dist/detection/detectors/cpp.d.ts.map +1 -0
  7. package/dist/detection/detectors/cpp.js +113 -0
  8. package/dist/detection/detectors/cpp.js.map +1 -0
  9. package/dist/detection/detectors/csharp.d.ts +17 -0
  10. package/dist/detection/detectors/csharp.d.ts.map +1 -0
  11. package/dist/detection/detectors/csharp.js +258 -0
  12. package/dist/detection/detectors/csharp.js.map +1 -0
  13. package/dist/detection/detectors/go.d.ts +17 -0
  14. package/dist/detection/detectors/go.d.ts.map +1 -0
  15. package/dist/detection/detectors/go.js +319 -0
  16. package/dist/detection/detectors/go.js.map +1 -0
  17. package/dist/detection/detectors/index.d.ts +14 -0
  18. package/dist/detection/detectors/index.d.ts.map +1 -0
  19. package/dist/detection/detectors/index.js +14 -0
  20. package/dist/detection/detectors/index.js.map +1 -0
  21. package/dist/detection/detectors/java.d.ts +17 -0
  22. package/dist/detection/detectors/java.d.ts.map +1 -0
  23. package/dist/detection/detectors/java.js +264 -0
  24. package/dist/detection/detectors/java.js.map +1 -0
  25. package/dist/detection/detectors/javascript.d.ts +18 -0
  26. package/dist/detection/detectors/javascript.d.ts.map +1 -0
  27. package/dist/detection/detectors/javascript.js +32 -0
  28. package/dist/detection/detectors/javascript.js.map +1 -0
  29. package/dist/detection/detectors/kotlin.d.ts +17 -0
  30. package/dist/detection/detectors/kotlin.d.ts.map +1 -0
  31. package/dist/detection/detectors/kotlin.js +210 -0
  32. package/dist/detection/detectors/kotlin.js.map +1 -0
  33. package/dist/detection/detectors/objectivec.d.ts +17 -0
  34. package/dist/detection/detectors/objectivec.d.ts.map +1 -0
  35. package/dist/detection/detectors/objectivec.js +244 -0
  36. package/dist/detection/detectors/objectivec.js.map +1 -0
  37. package/dist/detection/detectors/php.d.ts +17 -0
  38. package/dist/detection/detectors/php.d.ts.map +1 -0
  39. package/dist/detection/detectors/php.js +210 -0
  40. package/dist/detection/detectors/php.js.map +1 -0
  41. package/dist/detection/detectors/python.d.ts +17 -0
  42. package/dist/detection/detectors/python.d.ts.map +1 -0
  43. package/dist/detection/detectors/python.js +284 -0
  44. package/dist/detection/detectors/python.js.map +1 -0
  45. package/dist/detection/detectors/ruby.d.ts +17 -0
  46. package/dist/detection/detectors/ruby.d.ts.map +1 -0
  47. package/dist/detection/detectors/ruby.js +259 -0
  48. package/dist/detection/detectors/ruby.js.map +1 -0
  49. package/dist/detection/detectors/rust.d.ts +17 -0
  50. package/dist/detection/detectors/rust.d.ts.map +1 -0
  51. package/dist/detection/detectors/rust.js +159 -0
  52. package/dist/detection/detectors/rust.js.map +1 -0
  53. package/dist/detection/detectors/swift.d.ts +17 -0
  54. package/dist/detection/detectors/swift.d.ts.map +1 -0
  55. package/dist/detection/detectors/swift.js +229 -0
  56. package/dist/detection/detectors/swift.js.map +1 -0
  57. package/dist/detection/detectors/typescript.d.ts +17 -0
  58. package/dist/detection/detectors/typescript.d.ts.map +1 -0
  59. package/dist/detection/detectors/typescript.js +350 -0
  60. package/dist/detection/detectors/typescript.js.map +1 -0
  61. package/dist/detection/feature-flag.d.ts +16 -0
  62. package/dist/detection/feature-flag.d.ts.map +1 -0
  63. package/dist/detection/feature-flag.js +2 -0
  64. package/dist/detection/feature-flag.js.map +1 -0
  65. package/dist/detection/helpers.d.ts +51 -0
  66. package/dist/detection/helpers.d.ts.map +1 -0
  67. package/dist/detection/helpers.js +266 -0
  68. package/dist/detection/helpers.js.map +1 -0
  69. package/dist/detection/index.d.ts +19 -0
  70. package/dist/detection/index.d.ts.map +1 -0
  71. package/dist/detection/index.js +53 -0
  72. package/dist/detection/index.js.map +1 -0
  73. package/dist/detection/interface.d.ts +76 -0
  74. package/dist/detection/interface.d.ts.map +1 -0
  75. package/dist/detection/interface.js +25 -0
  76. package/dist/detection/interface.js.map +1 -0
  77. package/dist/detection/polyglot-analyzer.d.ts +83 -0
  78. package/dist/detection/polyglot-analyzer.d.ts.map +1 -0
  79. package/dist/detection/polyglot-analyzer.js +245 -0
  80. package/dist/detection/polyglot-analyzer.js.map +1 -0
  81. package/dist/detection/registry.d.ts +31 -0
  82. package/dist/detection/registry.d.ts.map +1 -0
  83. package/dist/detection/registry.js +68 -0
  84. package/dist/detection/registry.js.map +1 -0
  85. package/dist/detection/yaml-config.d.ts +333 -0
  86. package/dist/detection/yaml-config.d.ts.map +1 -0
  87. package/dist/detection/yaml-config.js +215 -0
  88. package/dist/detection/yaml-config.js.map +1 -0
  89. package/dist/index.d.ts +8 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +9 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/scan-repo.d.ts +67 -0
  94. package/dist/scan-repo.d.ts.map +1 -0
  95. package/dist/scan-repo.js +55 -0
  96. package/dist/scan-repo.js.map +1 -0
  97. package/dist/scanner.d.ts +18 -0
  98. package/dist/scanner.d.ts.map +1 -0
  99. package/dist/scanner.js +108 -0
  100. package/dist/scanner.js.map +1 -0
  101. package/dist/staleness.d.ts +30 -0
  102. package/dist/staleness.d.ts.map +1 -0
  103. package/dist/staleness.js +217 -0
  104. package/dist/staleness.js.map +1 -0
  105. package/package.json +37 -0
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Polyglot Analyzer -- multi-language feature flag detection coordinator.
3
+ * Ported from Go: internal/processor/polyglot_analyzer.go
4
+ *
5
+ * This module coordinates analysis across multiple programming languages,
6
+ * delegating to language-specific detectors registered in a language registry.
7
+ */
8
+ import pLimit from 'p-limit';
9
+ const DEFAULT_WORKER_POOL_SIZE = 10;
10
+ // -- Max file size for analysis (5 MB) --
11
+ const MAX_FILE_SIZE = 5 * 1024 * 1024;
12
+ // -- Analyzer --
13
+ export class PolyglotAnalyzer {
14
+ registry;
15
+ logger;
16
+ constructor(registry, logger) {
17
+ this.registry = registry;
18
+ this.logger = logger;
19
+ }
20
+ /** Analyzes multiple files using appropriate language detectors. */
21
+ async analyzeFiles(files, signal) {
22
+ return this.analyzeFilesWithProgress(files, undefined, signal);
23
+ }
24
+ /** Analyzes multiple files with progress reporting. */
25
+ async analyzeFilesWithProgress(files, progressCallback, signal) {
26
+ const result = {
27
+ files: new Map(),
28
+ totalFlags: new Map(),
29
+ languages: new Map(),
30
+ skippedFiles: [],
31
+ partialFiles: [],
32
+ };
33
+ const workerPoolSize = Number(process.env.ANALYZER_WORKER_POOL_SIZE) || DEFAULT_WORKER_POOL_SIZE;
34
+ const limit = pLimit(workerPoolSize);
35
+ this.logger.debug('Using analyzer worker pool size', {
36
+ workerPoolSize,
37
+ filesToAnalyze: files.size,
38
+ });
39
+ let filesAnalyzed = 0;
40
+ let filesWithFlags = 0;
41
+ let totalFlagsFound = 0;
42
+ let errorCount = 0;
43
+ let lastEmittedPercent = 0;
44
+ const totalFiles = files.size;
45
+ const tasks = [];
46
+ for (const [filePath, content] of files) {
47
+ if (signal?.aborted) {
48
+ break;
49
+ }
50
+ tasks.push(limit(async () => {
51
+ if (signal?.aborted) {
52
+ return;
53
+ }
54
+ const fileResult = await this.analyzeFile(filePath, content);
55
+ filesAnalyzed++;
56
+ result.files.set(filePath, fileResult);
57
+ let flagsInFile = 0;
58
+ for (const flag of fileResult.flags) {
59
+ flag.language = fileResult.language;
60
+ const existing = result.totalFlags.get(flag.name) ?? [];
61
+ existing.push(flag);
62
+ result.totalFlags.set(flag.name, existing);
63
+ flagsInFile++;
64
+ totalFlagsFound++;
65
+ }
66
+ if (flagsInFile > 0) {
67
+ filesWithFlags++;
68
+ }
69
+ if (fileResult.parseErrors.length > 0) {
70
+ errorCount++;
71
+ }
72
+ if (fileResult.status === 'skipped') {
73
+ result.skippedFiles.push(filePath);
74
+ }
75
+ else if (fileResult.status === 'partial') {
76
+ result.partialFiles.push(filePath);
77
+ }
78
+ if (fileResult.language) {
79
+ const count = result.languages.get(fileResult.language) ?? 0;
80
+ result.languages.set(fileResult.language, count + 1);
81
+ }
82
+ // Report progress every 5%
83
+ if (progressCallback && totalFiles > 0) {
84
+ const currentPercent = Math.floor((filesAnalyzed * 100) / totalFiles);
85
+ const roundedPercent = Math.floor(currentPercent / 5) * 5;
86
+ if (roundedPercent > lastEmittedPercent || filesAnalyzed === totalFiles) {
87
+ lastEmittedPercent = roundedPercent;
88
+ progressCallback(filesAnalyzed, totalFiles);
89
+ }
90
+ }
91
+ }));
92
+ }
93
+ await Promise.allSettled(tasks);
94
+ if (totalFlagsFound > 0 || errorCount > 0) {
95
+ this.logger.info('Polyglot analysis completed', {
96
+ totalFiles: filesAnalyzed,
97
+ filesWithFlags,
98
+ totalFlagsFound,
99
+ uniqueFlags: result.totalFlags.size,
100
+ filesWithErrors: errorCount,
101
+ languages: Object.fromEntries(result.languages),
102
+ });
103
+ }
104
+ return result;
105
+ }
106
+ /** Analyzes a single file using the appropriate language detector. */
107
+ async analyzeSingleFile(filePath, content) {
108
+ return this.analyzeFile(filePath, content);
109
+ }
110
+ /** Determines if a file should be analyzed based on language support. */
111
+ shouldAnalyzeFile(filePath, status) {
112
+ if (status === 'removed') {
113
+ return false;
114
+ }
115
+ if (filePath.includes('/vendor/') || filePath.startsWith('vendor/')) {
116
+ return false;
117
+ }
118
+ if (filePath.includes('/node_modules/') || filePath.startsWith('node_modules/')) {
119
+ return false;
120
+ }
121
+ return !!this.registry.getDetectorForFile(filePath);
122
+ }
123
+ /** Returns all supported file extensions. */
124
+ getSupportedExtensions() {
125
+ return this.registry.getSupportedExtensions();
126
+ }
127
+ async analyzeFile(filePath, content) {
128
+ const result = {
129
+ filePath,
130
+ language: '',
131
+ flags: [],
132
+ parseErrors: [],
133
+ status: 'ok',
134
+ };
135
+ if (!filePath) {
136
+ result.parseErrors.push(new Error('empty file path'));
137
+ result.status = 'skipped';
138
+ result.skippedReason = 'empty file path';
139
+ return result;
140
+ }
141
+ if (content.length === 0) {
142
+ return result;
143
+ }
144
+ if (content.length > MAX_FILE_SIZE) {
145
+ result.parseErrors.push(new Error(`file too large: ${content.length} bytes`));
146
+ result.status = 'skipped';
147
+ result.skippedReason = `file too large (${Math.floor(content.length / (1024 * 1024))} MB)`;
148
+ return result;
149
+ }
150
+ const detector = this.registry.getDetectorForFile(filePath);
151
+ if (!detector) {
152
+ result.status = 'unsupported';
153
+ return result;
154
+ }
155
+ result.language = detector.language();
156
+ try {
157
+ const flags = await Promise.resolve(detector.detectFlags(filePath, content));
158
+ result.flags = flags;
159
+ }
160
+ catch (err) {
161
+ const error = err instanceof Error ? err : new Error(String(err));
162
+ result.parseErrors.push(error);
163
+ if (error.message.includes('operation limit')) {
164
+ result.status = 'skipped';
165
+ result.skippedReason = 'file too complex for parsing';
166
+ }
167
+ else {
168
+ result.status = 'partial';
169
+ }
170
+ }
171
+ return result;
172
+ }
173
+ }
174
+ /** Compares two analysis results to find flag changes. */
175
+ export function compareResults(before, after) {
176
+ const comparison = {
177
+ added: new Map(),
178
+ removed: new Map(),
179
+ occurrenceChanges: new Map(),
180
+ };
181
+ const allFlags = new Set();
182
+ for (const name of before.totalFlags.keys()) {
183
+ allFlags.add(name);
184
+ }
185
+ for (const name of after.totalFlags.keys()) {
186
+ allFlags.add(name);
187
+ }
188
+ for (const flagName of allFlags) {
189
+ const beforeOccurrences = before.totalFlags.get(flagName) ?? [];
190
+ const afterOccurrences = after.totalFlags.get(flagName) ?? [];
191
+ if (beforeOccurrences.length === 0 && afterOccurrences.length > 0) {
192
+ comparison.added.set(flagName, toOccurrences(afterOccurrences));
193
+ }
194
+ else if (beforeOccurrences.length > 0 && afterOccurrences.length === 0) {
195
+ comparison.removed.set(flagName, toOccurrences(beforeOccurrences));
196
+ }
197
+ else if (beforeOccurrences.length !== afterOccurrences.length) {
198
+ comparison.occurrenceChanges.set(flagName, {
199
+ flagName,
200
+ beforeCount: beforeOccurrences.length,
201
+ afterCount: afterOccurrences.length,
202
+ addedIn: findNewOccurrences(beforeOccurrences, afterOccurrences),
203
+ removedFrom: findRemovedOccurrences(beforeOccurrences, afterOccurrences),
204
+ });
205
+ }
206
+ }
207
+ return comparison;
208
+ }
209
+ function toOccurrences(flags) {
210
+ return flags.map((f) => ({
211
+ name: f.name,
212
+ filePath: f.filePath,
213
+ lineNumber: f.lineNumber,
214
+ language: f.language,
215
+ provider: f.provider,
216
+ }));
217
+ }
218
+ function flagKey(f) {
219
+ return `${f.filePath}:${f.lineNumber}:${f.name}`;
220
+ }
221
+ function findNewOccurrences(before, after) {
222
+ const existing = new Set(before.map(flagKey));
223
+ return after
224
+ .filter((f) => !existing.has(flagKey(f)))
225
+ .map((f) => ({
226
+ name: f.name,
227
+ filePath: f.filePath,
228
+ lineNumber: f.lineNumber,
229
+ language: f.language,
230
+ provider: f.provider,
231
+ }));
232
+ }
233
+ function findRemovedOccurrences(before, after) {
234
+ const remaining = new Set(after.map(flagKey));
235
+ return before
236
+ .filter((f) => !remaining.has(flagKey(f)))
237
+ .map((f) => ({
238
+ name: f.name,
239
+ filePath: f.filePath,
240
+ lineNumber: f.lineNumber,
241
+ language: f.language,
242
+ provider: f.provider,
243
+ }));
244
+ }
245
+ //# sourceMappingURL=polyglot-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polyglot-analyzer.js","sourceRoot":"","sources":["../../src/detection/polyglot-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Language detector registry.
3
+ * Ported from Go: internal/languages/registry.go
4
+ *
5
+ * Maps file extensions and language identifiers to their respective detectors.
6
+ */
7
+ import type { FeatureFlag } from './feature-flag.js';
8
+ import type { Language, LanguageDetector } from './interface.js';
9
+ export declare class LanguageRegistry {
10
+ private detectors;
11
+ /** Registers a language detector. Throws if a detector for the language is already registered. */
12
+ register(detector: LanguageDetector): void;
13
+ /** Returns the detector for a specific language, or undefined if not registered. */
14
+ getDetector(lang: Language): LanguageDetector | undefined;
15
+ /** Returns the appropriate detector for a file based on its extension. */
16
+ getDetectorForFile(filename: string): LanguageDetector | undefined;
17
+ /** Detects feature flags in a file using the appropriate language detector. */
18
+ detectInFile(filename: string, content: string): FeatureFlag[] | null;
19
+ /** Returns all registered languages. */
20
+ getSupportedLanguages(): Language[];
21
+ /** Returns all supported file extensions (deduplicated). */
22
+ getSupportedExtensions(): string[];
23
+ }
24
+ /** Returns the global default registry singleton. */
25
+ export declare function getDefaultRegistry(): LanguageRegistry;
26
+ /**
27
+ * Resets the default registry (primarily for testing).
28
+ * @internal
29
+ */
30
+ export declare function resetDefaultRegistry(): void;
31
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/detection/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEhE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAwC;IAEzD,kGAAkG;IAClG,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAQ1C,oFAAoF;IACpF,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,gBAAgB,GAAG,SAAS;IAIzD,0EAA0E;IAC1E,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IASlE,+EAA+E;IAC/E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,IAAI;IAQrE,wCAAwC;IACxC,qBAAqB,IAAI,QAAQ,EAAE;IAInC,4DAA4D;IAC5D,sBAAsB,IAAI,MAAM,EAAE;CASnC;AAID,qDAAqD;AACrD,wBAAgB,kBAAkB,IAAI,gBAAgB,CAKrD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Language detector registry.
3
+ * Ported from Go: internal/languages/registry.go
4
+ *
5
+ * Maps file extensions and language identifiers to their respective detectors.
6
+ */
7
+ export class LanguageRegistry {
8
+ detectors = new Map();
9
+ /** Registers a language detector. Throws if a detector for the language is already registered. */
10
+ register(detector) {
11
+ const lang = detector.language();
12
+ if (this.detectors.has(lang)) {
13
+ throw new Error(`detector for language ${lang} already registered`);
14
+ }
15
+ this.detectors.set(lang, detector);
16
+ }
17
+ /** Returns the detector for a specific language, or undefined if not registered. */
18
+ getDetector(lang) {
19
+ return this.detectors.get(lang);
20
+ }
21
+ /** Returns the appropriate detector for a file based on its extension. */
22
+ getDetectorForFile(filename) {
23
+ for (const detector of this.detectors.values()) {
24
+ if (detector.supportsFile(filename)) {
25
+ return detector;
26
+ }
27
+ }
28
+ return undefined;
29
+ }
30
+ /** Detects feature flags in a file using the appropriate language detector. */
31
+ detectInFile(filename, content) {
32
+ const detector = this.getDetectorForFile(filename);
33
+ if (!detector) {
34
+ return null;
35
+ }
36
+ return detector.detectFlags(filename, content);
37
+ }
38
+ /** Returns all registered languages. */
39
+ getSupportedLanguages() {
40
+ return Array.from(this.detectors.keys());
41
+ }
42
+ /** Returns all supported file extensions (deduplicated). */
43
+ getSupportedExtensions() {
44
+ const extensionSet = new Set();
45
+ for (const detector of this.detectors.values()) {
46
+ for (const ext of detector.fileExtensions()) {
47
+ extensionSet.add(ext);
48
+ }
49
+ }
50
+ return Array.from(extensionSet);
51
+ }
52
+ }
53
+ let defaultRegistry = null;
54
+ /** Returns the global default registry singleton. */
55
+ export function getDefaultRegistry() {
56
+ if (!defaultRegistry) {
57
+ defaultRegistry = new LanguageRegistry();
58
+ }
59
+ return defaultRegistry;
60
+ }
61
+ /**
62
+ * Resets the default registry (primarily for testing).
63
+ * @internal
64
+ */
65
+ export function resetDefaultRegistry() {
66
+ defaultRegistry = null;
67
+ }
68
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/detection/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,OAAO,gBAAgB;IACnB,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAA;IAEzD,kGAAkG;IAClG,QAAQ,CAAC,QAA0B;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAA;QAChC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,qBAAqB,CAAC,CAAA;QACrE,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACpC,CAAC;IAED,oFAAoF;IACpF,WAAW,CAAC,IAAc;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;IAED,0EAA0E;IAC1E,kBAAkB,CAAC,QAAgB;QACjC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,IAAI,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpC,OAAO,QAAQ,CAAA;YACjB,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,+EAA+E;IAC/E,YAAY,CAAC,QAAgB,EAAE,OAAe;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAA;QAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAChD,CAAC;IAED,wCAAwC;IACxC,qBAAqB;QACnB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAA;IAC1C,CAAC;IAED,4DAA4D;IAC5D,sBAAsB;QACpB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;QACtC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC5C,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACvB,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IACjC,CAAC;CACF;AAED,IAAI,eAAe,GAA4B,IAAI,CAAA;AAEnD,qDAAqD;AACrD,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,IAAI,gBAAgB,EAAE,CAAA;IAC1C,CAAC;IACD,OAAO,eAAe,CAAA;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,eAAe,GAAG,IAAI,CAAA;AACxB,CAAC"}