depguard-cli 1.3.1 → 1.4.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.
package/dist/sweep.js ADDED
@@ -0,0 +1,639 @@
1
+ /**
2
+ * Dead dependency detection.
3
+ *
4
+ * Scans a project's source files for import/require statements and
5
+ * cross-references with package.json to find unused dependencies.
6
+ *
7
+ * Purely filesystem-based — zero network calls.
8
+ * Zero dependencies — only Node.js built-ins.
9
+ */
10
+ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
11
+ import { join, extname, resolve } from 'node:path';
12
+ /** File extensions to scan for imports */
13
+ const SOURCE_EXTENSIONS = new Set([
14
+ '.js', '.ts', '.mjs', '.cjs', '.jsx', '.tsx',
15
+ '.vue', '.svelte', '.astro', '.mdx',
16
+ ]);
17
+ /**
18
+ * Check if a package has install scripts (postinstall, preinstall, install).
19
+ * Packages with install scripts likely do something important at install time.
20
+ */
21
+ function hasInstallScripts(projectPath, packageName) {
22
+ try {
23
+ const pkgPath = join(projectPath, 'node_modules', ...packageName.split('/'), 'package.json');
24
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
25
+ const scripts = pkg.scripts ?? {};
26
+ return !!(scripts.postinstall || scripts.preinstall || scripts.install);
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ /** Safety note included in every sweep result */
33
+ const SWEEP_NOTE = 'These are recommendations based on static analysis. Verify before removing — some packages may be used dynamically, in CI/CD pipelines, or by tools not detected by static scanning.';
34
+ /** Stylesheet extensions to scan for @use/@import of packages */
35
+ const STYLE_EXTENSIONS = new Set(['.css', '.scss', '.sass', '.less']);
36
+ /** Directories to always exclude from scanning */
37
+ const EXCLUDE_DIRS = new Set([
38
+ 'node_modules', 'dist', 'build', '.git', '.next', '.nuxt', '.svelte-kit',
39
+ 'coverage', 'out', '.output', '.cache', '.turbo', '__pycache__',
40
+ ]);
41
+ /**
42
+ * Well-known config file patterns → the tool dependency they imply.
43
+ * Key is a filename prefix/pattern, value is the package(s) it implies.
44
+ */
45
+ const CONFIG_FILE_DEPS = {
46
+ '.eslintrc': ['eslint'],
47
+ 'eslint.config': ['eslint'],
48
+ '.prettierrc': ['prettier'],
49
+ 'prettier.config': ['prettier'],
50
+ 'jest.config': ['jest'],
51
+ 'vitest.config': ['vitest'],
52
+ 'babel.config': ['@babel/core'],
53
+ '.babelrc': ['@babel/core'],
54
+ 'tsconfig': ['typescript'],
55
+ 'tailwind.config': ['tailwindcss'],
56
+ 'postcss.config': ['postcss'],
57
+ 'webpack.config': ['webpack'],
58
+ 'rollup.config': ['rollup'],
59
+ 'vite.config': ['vite'],
60
+ 'next.config': ['next'],
61
+ 'nuxt.config': ['nuxt'],
62
+ 'svelte.config': ['svelte'],
63
+ '.swcrc': ['@swc/core'],
64
+ '.mocharc': ['mocha'],
65
+ 'cypress.config': ['cypress'],
66
+ 'playwright.config': ['playwright', '@playwright/test'],
67
+ '.storybook': ['storybook'],
68
+ 'turbo.json': ['turbo'],
69
+ 'nx.json': ['nx'],
70
+ 'lerna.json': ['lerna'],
71
+ };
72
+ /**
73
+ * Normalize a module specifier to a package name.
74
+ * `@scope/pkg/sub/path` → `@scope/pkg`
75
+ * `pkg/sub/path` → `pkg`
76
+ * `pkg` → `pkg`
77
+ */
78
+ export function normalizeToPackageName(specifier) {
79
+ if (specifier.startsWith('@')) {
80
+ // Scoped: @scope/pkg/...
81
+ const parts = specifier.split('/');
82
+ if (parts.length >= 2)
83
+ return `${parts[0]}/${parts[1]}`;
84
+ return specifier;
85
+ }
86
+ // Unscoped: pkg/...
87
+ return specifier.split('/')[0];
88
+ }
89
+ /**
90
+ * Extract package names from import/require/re-export statements in source code.
91
+ * Returns a Set of normalized package names (excludes relative imports).
92
+ */
93
+ export function extractImports(source) {
94
+ const packages = new Set();
95
+ // ES static imports: import ... from 'pkg' / import 'pkg'
96
+ const esImport = /import\s+(?:[\s\S]*?\s+from\s+)?['"]([^'"./][^'"]*)['"]/g;
97
+ // Dynamic imports: import('pkg')
98
+ const dynImport = /import\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g;
99
+ // CommonJS: require('pkg')
100
+ const cjsRequire = /require\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g;
101
+ // Re-exports: export ... from 'pkg'
102
+ const reExport = /export\s+[\s\S]*?\s+from\s+['"]([^'"./][^'"]*)['"]/g;
103
+ // require.resolve('pkg') — used to locate packages without importing
104
+ const requireResolve = /require\.resolve\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g;
105
+ // jest.mock('pkg'), jest.requireActual('pkg'), jest.unmock('pkg')
106
+ const jestMock = /jest\.(?:mock|requireActual|unmock)\s*\(\s*['"]([^'"./][^'"]*)['"]/g;
107
+ // TypeScript module augmentation: declare module 'pkg'
108
+ const declareModule = /declare\s+module\s+['"]([^'"./][^'"]*)['"]/g;
109
+ for (const pattern of [esImport, dynImport, cjsRequire, reExport, requireResolve, jestMock, declareModule]) {
110
+ let match;
111
+ while ((match = pattern.exec(source)) !== null) {
112
+ const specifier = match[1];
113
+ // Skip node: built-in modules
114
+ if (specifier.startsWith('node:'))
115
+ continue;
116
+ packages.add(normalizeToPackageName(specifier));
117
+ }
118
+ }
119
+ return packages;
120
+ }
121
+ /**
122
+ * Recursively collect source files matching the given extensions.
123
+ * Excludes directories in the exclude set.
124
+ */
125
+ export function collectSourceFiles(dir, extensions = SOURCE_EXTENSIONS, excludeDirs = EXCLUDE_DIRS) {
126
+ const files = [];
127
+ let entries;
128
+ try {
129
+ entries = readdirSync(dir);
130
+ }
131
+ catch {
132
+ return files;
133
+ }
134
+ for (const entry of entries) {
135
+ if (excludeDirs.has(entry))
136
+ continue;
137
+ const fullPath = join(dir, entry);
138
+ let stat;
139
+ try {
140
+ stat = statSync(fullPath);
141
+ }
142
+ catch {
143
+ continue;
144
+ }
145
+ if (stat.isDirectory()) {
146
+ files.push(...collectSourceFiles(fullPath, extensions, excludeDirs));
147
+ }
148
+ else if (stat.isFile() && extensions.has(extname(entry))) {
149
+ files.push(fullPath);
150
+ }
151
+ }
152
+ return files;
153
+ }
154
+ /**
155
+ * Check config files in the project root for tool-dependency references.
156
+ * Returns a map of package name → usage reason.
157
+ */
158
+ export function findConfigDependencies(projectPath) {
159
+ const configDeps = new Map();
160
+ let rootEntries;
161
+ try {
162
+ rootEntries = readdirSync(projectPath);
163
+ }
164
+ catch {
165
+ return configDeps;
166
+ }
167
+ for (const entry of rootEntries) {
168
+ for (const [pattern, deps] of Object.entries(CONFIG_FILE_DEPS)) {
169
+ if (entry.startsWith(pattern) || entry === pattern) {
170
+ for (const dep of deps) {
171
+ configDeps.set(dep, 'config-referenced');
172
+ }
173
+ }
174
+ }
175
+ // Scan config file content for plugin references
176
+ if (entry.match(/eslint\.config|\.eslintrc/)) {
177
+ scanConfigForPlugins(join(projectPath, entry), configDeps, 'eslint-plugin-', 'eslint-config-', '@typescript-eslint/');
178
+ }
179
+ if (entry.match(/babel\.config|\.babelrc/)) {
180
+ scanConfigForPlugins(join(projectPath, entry), configDeps, '@babel/plugin-', '@babel/preset-', 'babel-plugin-', 'babel-preset-');
181
+ }
182
+ if (entry.match(/jest\.config/)) {
183
+ scanConfigForPlugins(join(projectPath, entry), configDeps, 'jest-', 'ts-jest', 'babel-jest', '@jest/');
184
+ }
185
+ if (entry.match(/tailwind\.config/)) {
186
+ scanConfigForPlugins(join(projectPath, entry), configDeps, '@tailwindcss/', 'tailwindcss-');
187
+ }
188
+ if (entry.match(/postcss\.config/)) {
189
+ scanConfigForPlugins(join(projectPath, entry), configDeps, 'postcss-', 'autoprefixer', 'cssnano');
190
+ }
191
+ if (entry.match(/webpack\.config/)) {
192
+ scanConfigForPlugins(join(projectPath, entry), configDeps, '-loader', '-plugin', 'webpack-');
193
+ }
194
+ if (entry.match(/vite\.config|rollup\.config/)) {
195
+ scanConfigForPlugins(join(projectPath, entry), configDeps, '@vitejs/', 'vite-plugin-', '@rollup/', 'rollup-plugin-');
196
+ }
197
+ }
198
+ return configDeps;
199
+ }
200
+ /**
201
+ * Scan a config file for plugin name references.
202
+ */
203
+ function scanConfigForPlugins(filePath, configDeps, ...prefixes) {
204
+ try {
205
+ const content = readFileSync(filePath, 'utf-8');
206
+ // Extract all string literals from the file
207
+ const strings = content.match(/['"]([^'"]+)['"]/g) ?? [];
208
+ for (const str of strings) {
209
+ const value = str.slice(1, -1); // Remove quotes
210
+ for (const prefix of prefixes) {
211
+ // Match: starts with prefix, ends with suffix, or equals prefix without trailing dash
212
+ if (value.startsWith(prefix) || value.endsWith(prefix) || value === prefix.replace(/-$/, '')) {
213
+ configDeps.set(value, 'config-referenced');
214
+ }
215
+ }
216
+ // Also catch scoped packages referenced as strings in configs (e.g., "@scope/plugin")
217
+ if (value.startsWith('@') && value.includes('/')) {
218
+ configDeps.set(value, 'config-referenced');
219
+ }
220
+ }
221
+ }
222
+ catch {
223
+ // Config file not readable, skip
224
+ }
225
+ }
226
+ /**
227
+ * Check npm scripts in package.json for binary references.
228
+ * Returns a map of package name → usage reason.
229
+ */
230
+ export function findScriptDependencies(scripts, projectPath) {
231
+ const scriptDeps = new Map();
232
+ // Build a map of binary name → package name from node_modules/.bin
233
+ const binMap = new Map();
234
+ const nmPath = join(projectPath, 'node_modules');
235
+ if (existsSync(nmPath)) {
236
+ try {
237
+ const topLevelDeps = readdirSync(nmPath);
238
+ for (const dep of topLevelDeps) {
239
+ if (dep.startsWith('.'))
240
+ continue;
241
+ if (dep.startsWith('@')) {
242
+ // Scoped packages
243
+ try {
244
+ const scopedDeps = readdirSync(join(nmPath, dep));
245
+ for (const scopedDep of scopedDeps) {
246
+ readBinFromPackage(join(nmPath, dep, scopedDep), `${dep}/${scopedDep}`, binMap);
247
+ }
248
+ }
249
+ catch { /* skip */ }
250
+ }
251
+ else {
252
+ readBinFromPackage(join(nmPath, dep), dep, binMap);
253
+ }
254
+ }
255
+ }
256
+ catch { /* skip */ }
257
+ }
258
+ // Check each script value for binary references and --require/--loader flags
259
+ for (const scriptValue of Object.values(scripts)) {
260
+ const tokens = scriptValue.split(/[\s;&|]+/);
261
+ for (let i = 0; i < tokens.length; i++) {
262
+ const token = tokens[i];
263
+ const cleanToken = token.replace(/^(?:npx|pnpx|yarn|bunx)\s+/, '');
264
+ // Check against binary map
265
+ const cleanMatch = binMap.get(cleanToken);
266
+ if (cleanMatch) {
267
+ scriptDeps.set(cleanMatch, 'npm-script');
268
+ }
269
+ // Also check if token matches a dependency name directly
270
+ const tokenMatch = binMap.get(token);
271
+ if (tokenMatch) {
272
+ scriptDeps.set(tokenMatch, 'npm-script');
273
+ }
274
+ // Detect --require <pkg> and --loader <pkg> patterns (node flags)
275
+ if ((token === '--require' || token === '-r' || token === '--loader' || token === '--import') && i + 1 < tokens.length) {
276
+ const nextToken = tokens[i + 1];
277
+ if (nextToken && !nextToken.startsWith('-') && !nextToken.startsWith('.') && !nextToken.startsWith('/')) {
278
+ scriptDeps.set(normalizeToPackageName(nextToken), 'npm-script');
279
+ }
280
+ }
281
+ // Detect --require=pkg (equals form)
282
+ const requireMatch = token.match(/^(?:--require|-r|--loader|--import)=(.+)$/);
283
+ if (requireMatch && requireMatch[1] && !requireMatch[1].startsWith('.') && !requireMatch[1].startsWith('/')) {
284
+ scriptDeps.set(normalizeToPackageName(requireMatch[1]), 'npm-script');
285
+ }
286
+ }
287
+ }
288
+ return scriptDeps;
289
+ }
290
+ /**
291
+ * Read the `bin` field from a package's package.json and add to the bin map.
292
+ */
293
+ function readBinFromPackage(pkgDir, pkgName, binMap) {
294
+ try {
295
+ const pkgJson = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf-8'));
296
+ if (typeof pkgJson.bin === 'string') {
297
+ // Single binary, named after the package
298
+ const shortName = pkgName.includes('/') ? pkgName.split('/')[1] : pkgName;
299
+ binMap.set(shortName, pkgName);
300
+ }
301
+ else if (typeof pkgJson.bin === 'object' && pkgJson.bin !== null) {
302
+ for (const binName of Object.keys(pkgJson.bin)) {
303
+ binMap.set(binName, pkgName);
304
+ }
305
+ }
306
+ }
307
+ catch { /* skip */ }
308
+ }
309
+ /**
310
+ * Estimate the installed size of a package in KB.
311
+ * Does a shallow directory size estimation (not recursive into node_modules).
312
+ */
313
+ export function estimatePackageSize(projectPath, packageName) {
314
+ const pkgDir = join(projectPath, 'node_modules', ...packageName.split('/'));
315
+ if (!existsSync(pkgDir))
316
+ return null;
317
+ try {
318
+ let totalBytes = 0;
319
+ const entries = readdirSync(pkgDir);
320
+ for (const entry of entries) {
321
+ if (entry === 'node_modules')
322
+ continue;
323
+ try {
324
+ const stat = statSync(join(pkgDir, entry));
325
+ if (stat.isFile()) {
326
+ totalBytes += stat.size;
327
+ }
328
+ }
329
+ catch { /* skip */ }
330
+ }
331
+ return Math.round(totalBytes / 1024);
332
+ }
333
+ catch {
334
+ return null;
335
+ }
336
+ }
337
+ /**
338
+ * Extract package names from stylesheet @use/@import statements.
339
+ * Handles SCSS @use 'pkg', @import 'pkg', and Less @import 'pkg'.
340
+ */
341
+ export function extractStyleImports(source) {
342
+ const packages = new Set();
343
+ // SCSS @use 'package' / @import 'package' (non-relative only)
344
+ const atUse = /@use\s+['"]([^'"./~][^'"]*)['"]/g;
345
+ const atImport = /@import\s+['"]([^'"./~][^'"]*)['"]/g;
346
+ for (const pattern of [atUse, atImport]) {
347
+ let match;
348
+ while ((match = pattern.exec(source)) !== null) {
349
+ const specifier = match[1];
350
+ // Skip sass built-ins like 'sass:math'
351
+ if (specifier.startsWith('sass:'))
352
+ continue;
353
+ packages.add(normalizeToPackageName(specifier));
354
+ }
355
+ }
356
+ return packages;
357
+ }
358
+ /**
359
+ * Find packages that are required as peer dependencies by other installed packages.
360
+ * If package A has peerDependencies: { B: "^1.0" }, and both A and B are in
361
+ * the project's deps, then B is considered "used" via peer-dep.
362
+ */
363
+ function findPeerDependencyUsers(projectPath, depNames) {
364
+ const peerUsers = new Set();
365
+ const nmPath = join(projectPath, 'node_modules');
366
+ if (!existsSync(nmPath))
367
+ return peerUsers;
368
+ for (const depName of depNames) {
369
+ try {
370
+ const depPkgPath = join(nmPath, ...depName.split('/'), 'package.json');
371
+ const depPkg = JSON.parse(readFileSync(depPkgPath, 'utf-8'));
372
+ const peerDeps = depPkg.peerDependencies;
373
+ if (peerDeps) {
374
+ for (const peerName of Object.keys(peerDeps)) {
375
+ if (depNames.includes(peerName)) {
376
+ peerUsers.add(peerName);
377
+ }
378
+ }
379
+ }
380
+ }
381
+ catch { /* package not installed or not readable */ }
382
+ }
383
+ return peerUsers;
384
+ }
385
+ /**
386
+ * In monorepos, scan workspace package.json files for dependency references.
387
+ * This prevents marking a root dep as "unused" when a workspace uses it.
388
+ */
389
+ function scanWorkspaceImports(projectPath, workspaces) {
390
+ const wsImports = new Set();
391
+ const patterns = Array.isArray(workspaces) ? workspaces : (workspaces.packages ?? []);
392
+ for (const pattern of patterns) {
393
+ // Resolve simple glob patterns (e.g., "packages/*")
394
+ const basePath = pattern.replace(/\*.*$/, '');
395
+ const wsRoot = join(projectPath, basePath);
396
+ if (!existsSync(wsRoot))
397
+ continue;
398
+ try {
399
+ const entries = readdirSync(wsRoot);
400
+ for (const entry of entries) {
401
+ const wsPkgPath = join(wsRoot, entry, 'package.json');
402
+ if (!existsSync(wsPkgPath))
403
+ continue;
404
+ try {
405
+ const wsPkg = JSON.parse(readFileSync(wsPkgPath, 'utf-8'));
406
+ const wsDeps = {
407
+ ...(wsPkg.dependencies ?? {}),
408
+ ...(wsPkg.devDependencies ?? {}),
409
+ ...(wsPkg.peerDependencies ?? {}),
410
+ };
411
+ for (const dep of Object.keys(wsDeps)) {
412
+ wsImports.add(dep);
413
+ }
414
+ }
415
+ catch { /* skip unreadable workspace package.json */ }
416
+ }
417
+ }
418
+ catch { /* skip unreadable directory */ }
419
+ }
420
+ return wsImports;
421
+ }
422
+ /**
423
+ * Detect unused dependencies in a project.
424
+ * Purely filesystem-based — no network calls.
425
+ */
426
+ export async function sweep(projectPath, options = {}) {
427
+ const absPath = resolve(projectPath);
428
+ const warnings = [];
429
+ // Step 1: Read package.json
430
+ const pkgJsonPath = join(absPath, 'package.json');
431
+ if (!existsSync(pkgJsonPath)) {
432
+ return {
433
+ projectPath: absPath,
434
+ totalDependencies: 0,
435
+ unused: [],
436
+ maybeUnused: [],
437
+ used: 0,
438
+ estimatedSavingsKB: 0,
439
+ scannedFiles: 0,
440
+ warnings: ['No package.json found at project root'],
441
+ note: SWEEP_NOTE,
442
+ };
443
+ }
444
+ let pkgJson;
445
+ try {
446
+ pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
447
+ }
448
+ catch {
449
+ return {
450
+ projectPath: absPath,
451
+ totalDependencies: 0,
452
+ unused: [],
453
+ maybeUnused: [],
454
+ used: 0,
455
+ estimatedSavingsKB: 0,
456
+ scannedFiles: 0,
457
+ warnings: ['Could not parse package.json'],
458
+ note: SWEEP_NOTE,
459
+ };
460
+ }
461
+ // Collect dependencies to check
462
+ const deps = (pkgJson.dependencies ?? {});
463
+ const devDeps = options.includeDevDependencies
464
+ ? (pkgJson.devDependencies ?? {})
465
+ : {};
466
+ const allDeps = { ...deps, ...devDeps };
467
+ const depNames = Object.keys(allDeps);
468
+ if (depNames.length === 0) {
469
+ return {
470
+ projectPath: absPath,
471
+ totalDependencies: 0,
472
+ unused: [],
473
+ maybeUnused: [],
474
+ used: 0,
475
+ estimatedSavingsKB: 0,
476
+ scannedFiles: 0,
477
+ warnings: [],
478
+ note: SWEEP_NOTE,
479
+ };
480
+ }
481
+ // Warn about monorepos
482
+ if (pkgJson.workspaces) {
483
+ warnings.push('Monorepo detected (workspaces). Consider running sweep per workspace for accurate results.');
484
+ }
485
+ // Step 2: Scan source files for imports
486
+ const excludeDirs = new Set([...EXCLUDE_DIRS, ...(options.excludePatterns ?? [])]);
487
+ const sourceFiles = collectSourceFiles(absPath, SOURCE_EXTENSIONS, excludeDirs);
488
+ const importedPackages = new Set();
489
+ for (const file of sourceFiles) {
490
+ try {
491
+ const content = readFileSync(file, 'utf-8');
492
+ const imports = extractImports(content);
493
+ for (const pkg of imports) {
494
+ importedPackages.add(pkg);
495
+ }
496
+ }
497
+ catch {
498
+ warnings.push(`Could not read: ${file}`);
499
+ }
500
+ }
501
+ // Step 2b: Scan stylesheet files for @use/@import of packages
502
+ const styleFiles = collectSourceFiles(absPath, STYLE_EXTENSIONS, excludeDirs);
503
+ for (const file of styleFiles) {
504
+ try {
505
+ const content = readFileSync(file, 'utf-8');
506
+ const styleImports = extractStyleImports(content);
507
+ for (const pkg of styleImports) {
508
+ importedPackages.add(pkg);
509
+ }
510
+ }
511
+ catch {
512
+ warnings.push(`Could not read: ${file}`);
513
+ }
514
+ }
515
+ // Step 3: Check config files
516
+ const configDeps = findConfigDependencies(absPath);
517
+ // Step 4: Check npm scripts
518
+ const scripts = (pkgJson.scripts ?? {});
519
+ const scriptDeps = findScriptDependencies(scripts, absPath);
520
+ // Step 5: Check peer dependencies — if package A needs B as peerDep, B is "used"
521
+ const peerDepUsers = findPeerDependencyUsers(absPath, depNames);
522
+ // Step 6: Scan workspace siblings if monorepo detected (npm/yarn workspaces or pnpm)
523
+ let workspaceImports = new Set();
524
+ if (pkgJson.workspaces) {
525
+ workspaceImports = scanWorkspaceImports(absPath, pkgJson.workspaces);
526
+ }
527
+ else {
528
+ // Check for pnpm-workspace.yaml
529
+ const pnpmWsPath = join(absPath, 'pnpm-workspace.yaml');
530
+ if (existsSync(pnpmWsPath)) {
531
+ try {
532
+ const pnpmContent = readFileSync(pnpmWsPath, 'utf-8');
533
+ // Simple YAML parsing for packages list: " - 'packages/*'"
534
+ const pnpmPatterns = [];
535
+ const lines = pnpmContent.split('\n');
536
+ for (const line of lines) {
537
+ const match = line.match(/^\s*-\s+['"]?([^'"#\n]+)['"]?\s*$/);
538
+ if (match)
539
+ pnpmPatterns.push(match[1].trim());
540
+ }
541
+ if (pnpmPatterns.length > 0) {
542
+ workspaceImports = scanWorkspaceImports(absPath, pnpmPatterns);
543
+ warnings.push('Monorepo detected (pnpm workspaces). Consider running sweep per workspace for accurate results.');
544
+ }
545
+ }
546
+ catch { /* skip unreadable pnpm-workspace.yaml */ }
547
+ }
548
+ }
549
+ // Step 7: Classify each dependency
550
+ const unused = [];
551
+ const maybeUnused = [];
552
+ let usedCount = 0;
553
+ for (const name of depNames) {
554
+ const reasons = [];
555
+ const version = allDeps[name] ?? 'unknown';
556
+ // Check imports
557
+ if (importedPackages.has(name)) {
558
+ reasons.push('imported');
559
+ }
560
+ // Check config files
561
+ if (configDeps.has(name)) {
562
+ reasons.push('config-referenced');
563
+ }
564
+ // Check npm scripts
565
+ if (scriptDeps.has(name)) {
566
+ reasons.push('npm-script');
567
+ }
568
+ // Handle @types/* packages
569
+ if (name.startsWith('@types/')) {
570
+ const runtimeName = name.replace('@types/', '').replace('__', '/');
571
+ if (importedPackages.has(runtimeName) || depNames.includes(runtimeName)) {
572
+ reasons.push('types-only');
573
+ }
574
+ }
575
+ // Check peer dependencies — if another installed package needs this as peerDep
576
+ if (peerDepUsers.has(name)) {
577
+ reasons.push('peer-dep');
578
+ }
579
+ // Check workspace imports — if another workspace package imports this
580
+ if (workspaceImports.has(name)) {
581
+ reasons.push('imported');
582
+ }
583
+ // Check if this is a well-known config-only tool not caught by file patterns
584
+ // (e.g., typescript is referenced via tsconfig.json)
585
+ if (reasons.length === 0) {
586
+ for (const [, toolDeps] of Object.entries(CONFIG_FILE_DEPS)) {
587
+ if (toolDeps.includes(name) && configDeps.has(name)) {
588
+ reasons.push('config-referenced');
589
+ }
590
+ }
591
+ }
592
+ // Classify
593
+ if (reasons.length > 0) {
594
+ usedCount++;
595
+ }
596
+ else {
597
+ const sizeKB = estimatePackageSize(absPath, name);
598
+ const depResult = {
599
+ name,
600
+ version,
601
+ status: 'unused',
602
+ reasons: [],
603
+ estimatedSizeKB: sizeKB,
604
+ };
605
+ // Conservative classification — when in doubt, use maybe-unused.
606
+ // We only say "unused" when we have high confidence.
607
+ const shouldBeCautious =
608
+ // devDependency — could be used by a config/tool we don't recognize
609
+ (devDeps[name] && !deps[name]) ||
610
+ // No node_modules — can't verify peer deps or bin scripts
611
+ !existsSync(join(absPath, 'node_modules')) ||
612
+ // Scoped packages used as plugins are hard to trace
613
+ name.startsWith('@') ||
614
+ // Packages with install scripts likely do something important
615
+ hasInstallScripts(absPath, name);
616
+ if (shouldBeCautious) {
617
+ depResult.status = 'maybe-unused';
618
+ maybeUnused.push(depResult);
619
+ }
620
+ else {
621
+ unused.push(depResult);
622
+ }
623
+ }
624
+ }
625
+ // Calculate estimated savings
626
+ const estimatedSavingsKB = unused.reduce((sum, dep) => sum + (dep.estimatedSizeKB ?? 0), 0);
627
+ return {
628
+ projectPath: absPath,
629
+ totalDependencies: depNames.length,
630
+ unused,
631
+ maybeUnused,
632
+ used: usedCount,
633
+ estimatedSavingsKB,
634
+ scannedFiles: sourceFiles.length + styleFiles.length,
635
+ warnings,
636
+ note: SWEEP_NOTE,
637
+ };
638
+ }
639
+ //# sourceMappingURL=sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.js","sourceRoot":"","sources":["../src/sweep.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGlD,0CAA0C;AAC1C,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC5C,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM;CACpC,CAAC,CAAA;AAEF;;;GAGG;AACH,SAAS,iBAAiB,CAAC,WAAmB,EAAE,WAAmB;IACjE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC,CAAA;QAC5F,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;QACtD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAA;QACjC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,GAAG,sLAAsL,CAAA;AAEzM,iEAAiE;AACjE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AAErE,kDAAkD;AAClD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa;IACxE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa;CAChE,CAAC,CAAA;AAEF;;;GAGG;AACH,MAAM,gBAAgB,GAA6B;IACjD,WAAW,EAAE,CAAC,QAAQ,CAAC;IACvB,eAAe,EAAE,CAAC,QAAQ,CAAC;IAC3B,aAAa,EAAE,CAAC,UAAU,CAAC;IAC3B,iBAAiB,EAAE,CAAC,UAAU,CAAC;IAC/B,aAAa,EAAE,CAAC,MAAM,CAAC;IACvB,eAAe,EAAE,CAAC,QAAQ,CAAC;IAC3B,cAAc,EAAE,CAAC,aAAa,CAAC;IAC/B,UAAU,EAAE,CAAC,aAAa,CAAC;IAC3B,UAAU,EAAE,CAAC,YAAY,CAAC;IAC1B,iBAAiB,EAAE,CAAC,aAAa,CAAC;IAClC,gBAAgB,EAAE,CAAC,SAAS,CAAC;IAC7B,gBAAgB,EAAE,CAAC,SAAS,CAAC;IAC7B,eAAe,EAAE,CAAC,QAAQ,CAAC;IAC3B,aAAa,EAAE,CAAC,MAAM,CAAC;IACvB,aAAa,EAAE,CAAC,MAAM,CAAC;IACvB,aAAa,EAAE,CAAC,MAAM,CAAC;IACvB,eAAe,EAAE,CAAC,QAAQ,CAAC;IAC3B,QAAQ,EAAE,CAAC,WAAW,CAAC;IACvB,UAAU,EAAE,CAAC,OAAO,CAAC;IACrB,gBAAgB,EAAE,CAAC,SAAS,CAAC;IAC7B,mBAAmB,EAAE,CAAC,YAAY,EAAE,kBAAkB,CAAC;IACvD,YAAY,EAAE,CAAC,WAAW,CAAC;IAC3B,YAAY,EAAE,CAAC,OAAO,CAAC;IACvB,SAAS,EAAE,CAAC,IAAI,CAAC;IACjB,YAAY,EAAE,CAAC,OAAO,CAAC;CACxB,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,yBAAyB;QACzB,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAClC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QACvD,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,oBAAoB;IACpB,OAAO,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;IAElC,0DAA0D;IAC1D,MAAM,QAAQ,GAAG,0DAA0D,CAAA;IAC3E,iCAAiC;IACjC,MAAM,SAAS,GAAG,6CAA6C,CAAA;IAC/D,2BAA2B;IAC3B,MAAM,UAAU,GAAG,8CAA8C,CAAA;IACjE,oCAAoC;IACpC,MAAM,QAAQ,GAAG,qDAAqD,CAAA;IACtE,qEAAqE;IACrE,MAAM,cAAc,GAAG,uDAAuD,CAAA;IAC9E,kEAAkE;IAClE,MAAM,QAAQ,GAAG,qEAAqE,CAAA;IACtF,uDAAuD;IACvD,MAAM,aAAa,GAAG,6CAA6C,CAAA;IAEnE,KAAK,MAAM,OAAO,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC;QAC3G,IAAI,KAA6B,CAAA;QACjC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC/C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;YAC1B,8BAA8B;YAC9B,IAAI,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,SAAQ;YAC3C,QAAQ,CAAC,GAAG,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,CAAA;QACjD,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAW,EACX,aAA0B,iBAAiB,EAC3C,cAA2B,YAAY;IAEvC,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,IAAI,OAAiB,CAAA;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAQ;QAEpC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACjC,IAAI,IAAI,CAAA;QACR,IAAI,CAAC;YACH,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,SAAQ;QACV,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAA;QACtE,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC3D,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,MAAM,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAA;IAEpD,IAAI,WAAqB,CAAA;IACzB,IAAI,CAAC;QACH,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC/D,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;gBACnD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;oBACvB,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAA;gBAC1C,CAAC;YACH,CAAC;QACH,CAAC;QAED,iDAAiD;QACjD,IAAI,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,EAAE,CAAC;YAC7C,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,qBAAqB,CAAC,CAAA;QACvH,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,yBAAyB,CAAC,EAAE,CAAC;YAC3C,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,CAAC,CAAA;QAClI,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;YAChC,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAA;QACxG,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACpC,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,CAAC,CAAA;QAC7F,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACnC,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,CAAC,CAAA;QACnG,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACnC,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;QAC9F,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,6BAA6B,CAAC,EAAE,CAAC;YAC/C,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAA;QACtH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAC3B,QAAgB,EAChB,UAAuC,EACvC,GAAG,QAAkB;IAErB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAC/C,4CAA4C;QAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAA;QACxD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA,CAAC,gBAAgB;YAC/C,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC9B,sFAAsF;gBACtF,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;oBAC7F,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAA;gBAC5C,CAAC;YACH,CAAC;YACD,sFAAsF;YACtF,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjD,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAA;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAA+B,EAC/B,WAAmB;IAEnB,MAAM,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAA;IAEpD,mEAAmE;IACnE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;IAEhD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;YACxC,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;gBAC/B,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,SAAQ;gBACjC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxB,kBAAkB;oBAClB,IAAI,CAAC;wBACH,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;wBACjD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;4BACnC,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,GAAG,GAAG,IAAI,SAAS,EAAE,EAAE,MAAM,CAAC,CAAA;wBACjF,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;gBACpD,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IACxB,CAAC;IAED,6EAA6E;IAC7E,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;YACvB,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAA;YAClE,2BAA2B;YAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;YACzC,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;YAC1C,CAAC;YACD,yDAAyD;YACzD,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YACpC,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;YAC1C,CAAC;YACD,kEAAkE;YAClE,IAAI,CAAC,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;gBACvH,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;gBAC/B,IAAI,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxG,UAAU,CAAC,GAAG,CAAC,sBAAsB,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC,CAAA;gBACjE,CAAC;YACH,CAAC;YACD,qCAAqC;YACrC,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAA;YAC7E,IAAI,YAAY,IAAI,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5G,UAAU,CAAC,GAAG,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAA;YACvE,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,MAAc,EACd,OAAe,EACf,MAA2B;IAE3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;QAC/E,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACpC,yCAAyC;YACzC,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;YACzE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAChC,CAAC;aAAM,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;YACnE,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB,EAAE,WAAmB;IAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;IAC3E,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAA;IAEpC,IAAI,CAAC;QACH,IAAI,UAAU,GAAG,CAAC,CAAA;QAClB,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;QACnC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,KAAK,cAAc;gBAAE,SAAQ;YACtC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;gBAC1C,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;oBAClB,UAAU,IAAI,IAAI,CAAC,IAAI,CAAA;gBACzB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;IAClC,8DAA8D;IAC9D,MAAM,KAAK,GAAG,kCAAkC,CAAA;IAChD,MAAM,QAAQ,GAAG,qCAAqC,CAAA;IAEtD,KAAK,MAAM,OAAO,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;QACxC,IAAI,KAA6B,CAAA;QACjC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC/C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;YAC1B,uCAAuC;YACvC,IAAI,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,SAAQ;YAC3C,QAAQ,CAAC,GAAG,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,CAAA;QACjD,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;GAIG;AACH,SAAS,uBAAuB,CAAC,WAAmB,EAAE,QAAkB;IACtE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;IAChD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAA;IAEzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC,CAAA;YACtE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAA;YAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAsD,CAAA;YAC9E,IAAI,QAAQ,EAAE,CAAC;gBACb,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC7C,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAChC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;oBACzB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,2CAA2C,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAC3B,WAAmB,EACnB,UAA6C;IAE7C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;IACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAA;IAErF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,oDAAoD;QACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QAE1C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,SAAQ;QAEjC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;YACnC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,CAAA;gBACrD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;oBAAE,SAAQ;gBAEpC,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;oBAC1D,MAAM,MAAM,GAAG;wBACb,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;wBAC7B,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC;wBAChC,GAAG,CAAC,KAAK,CAAC,gBAAgB,IAAI,EAAE,CAAC;qBACR,CAAA;oBAE3B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;wBACtC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;oBACpB,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,+BAA+B,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,WAAmB,EACnB,UAAwB,EAAE;IAE1B,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IACpC,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,4BAA4B;IAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;IACjD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,WAAW,EAAE,OAAO;YACpB,iBAAiB,EAAE,CAAC;YACpB,MAAM,EAAE,EAAE;YACV,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,CAAC;YACP,kBAAkB,EAAE,CAAC;YACrB,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,CAAC,uCAAuC,CAAC;YACnD,IAAI,EAAE,UAAU;SACjB,CAAA;IACH,CAAC;IAED,IAAI,OAAgC,CAAA;IACpC,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,WAAW,EAAE,OAAO;YACpB,iBAAiB,EAAE,CAAC;YACpB,MAAM,EAAE,EAAE;YACV,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,CAAC;YACP,kBAAkB,EAAE,CAAC;YACrB,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,CAAC,8BAA8B,CAAC;YAC1C,IAAI,EAAE,UAAU;SACjB,CAAA;IACH,CAAC;IAED,gCAAgC;IAChC,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAA2B,CAAA;IACnE,MAAM,OAAO,GAAG,OAAO,CAAC,sBAAsB;QAC5C,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAA2B;QAC3D,CAAC,CAAC,EAAE,CAAA;IACN,MAAM,OAAO,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,EAAE,CAAA;IACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAErC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,WAAW,EAAE,OAAO;YACpB,iBAAiB,EAAE,CAAC;YACpB,MAAM,EAAE,EAAE;YACV,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,CAAC;YACP,kBAAkB,EAAE,CAAC;YACrB,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE,UAAU;SACjB,CAAA;IACH,CAAC;IAED,uBAAuB;IACvB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAA;IAC7G,CAAC;IAED,wCAAwC;IACxC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAClF,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,EAAE,WAAW,CAAC,CAAA;IAC/E,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAA;IAE1C,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC3C,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;YACvC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,WAAW,CAAC,CAAA;IAC7E,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC3C,MAAM,YAAY,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;YACjD,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;gBAC/B,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,MAAM,UAAU,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAElD,4BAA4B;IAC5B,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAA2B,CAAA;IACjE,MAAM,UAAU,GAAG,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAE3D,iFAAiF;IACjF,MAAM,YAAY,GAAG,uBAAuB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAE/D,qFAAqF;IACrF,IAAI,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAA;IACxC,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,gBAAgB,GAAG,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,UAA+C,CAAC,CAAA;IAC3G,CAAC;SAAM,CAAC;QACN,gCAAgC;QAChC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAA;QACvD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;gBACrD,4DAA4D;gBAC5D,MAAM,YAAY,GAAa,EAAE,CAAA;gBACjC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;gBACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;oBAC7D,IAAI,KAAK;wBAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;gBAC/C,CAAC;gBACD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5B,gBAAgB,GAAG,oBAAoB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;oBAC9D,QAAQ,CAAC,IAAI,CAAC,iGAAiG,CAAC,CAAA;gBAClH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAC,yCAAyC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,MAAM,MAAM,GAAqB,EAAE,CAAA;IACnC,MAAM,WAAW,GAAqB,EAAE,CAAA;IACxC,IAAI,SAAS,GAAG,CAAC,CAAA;IAEjB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAqB,EAAE,CAAA;QACpC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,SAAS,CAAA;QAE1C,gBAAgB;QAChB,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAC1B,CAAC;QAED,qBAAqB;QACrB,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;QACnC,CAAC;QAED,oBAAoB;QACpB,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QAC5B,CAAC;QAED,2BAA2B;QAC3B,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YAClE,IAAI,gBAAgB,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBACxE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YAC5B,CAAC;QACH,CAAC;QAED,+EAA+E;QAC/E,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAC1B,CAAC;QAED,sEAAsE;QACtE,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAC1B,CAAC;QAED,6EAA6E;QAC7E,qDAAqD;QACrD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,MAAM,CAAC,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAC5D,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACpD,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;gBACnC,CAAC;YACH,CAAC;QACH,CAAC;QAED,WAAW;QACX,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,SAAS,EAAE,CAAA;QACb,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACjD,MAAM,SAAS,GAAmB;gBAChC,IAAI;gBACJ,OAAO;gBACP,MAAM,EAAE,QAAQ;gBAChB,OAAO,EAAE,EAAE;gBACX,eAAe,EAAE,MAAM;aACxB,CAAA;YAED,iEAAiE;YACjE,qDAAqD;YACrD,MAAM,gBAAgB;YACpB,oEAAoE;YACpE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9B,0DAA0D;gBAC1D,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;gBAC1C,oDAAoD;gBACpD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBACpB,8DAA8D;gBAC9D,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YAElC,IAAI,gBAAgB,EAAE,CAAC;gBACrB,SAAS,CAAC,MAAM,GAAG,cAAc,CAAA;gBACjC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAC7B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAE3F,OAAO;QACL,WAAW,EAAE,OAAO;QACpB,iBAAiB,EAAE,QAAQ,CAAC,MAAM;QAClC,MAAM;QACN,WAAW;QACX,IAAI,EAAE,SAAS;QACf,kBAAkB;QAClB,YAAY,EAAE,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM;QACpD,QAAQ;QACR,IAAI,EAAE,UAAU;KACjB,CAAA;AACH,CAAC"}