react-native-bundle-discovery-ui 2.8.0 → 2.9.1

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 (40) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +12 -255
  3. package/assets/global.css +1606 -105
  4. package/dist/bin.js +63 -20
  5. package/dist/client/fonts.js +45 -0
  6. package/dist/client/issues.js +5 -0
  7. package/dist/client/pages/_common.js +279 -98
  8. package/dist/client/pages/_module.js +347 -0
  9. package/dist/client/pages/default.js +144 -63
  10. package/dist/client/pages/module.js +2 -309
  11. package/dist/client/pages/moduleDiff.js +76 -0
  12. package/dist/client/pages/package.js +172 -154
  13. package/dist/client/prepare.js +15 -0
  14. package/dist/client/queryHelpers.js +487 -91
  15. package/dist/client/sizeHeat.js +7 -0
  16. package/dist/client/views/{_theme.js → _colorScheme.js} +2 -9
  17. package/dist/client/views/_html.js +52 -0
  18. package/dist/client/views/codeDiff.js +66 -0
  19. package/dist/client/views/compare.js +237 -0
  20. package/dist/client/views/importGraph.js +255 -0
  21. package/dist/client/views/insights.js +81 -0
  22. package/dist/client/views/moduleOverview.js +122 -0
  23. package/dist/client/views/packageOverview.js +116 -0
  24. package/dist/client/views/persistedFilterInput.js +27 -0
  25. package/dist/client/views/reportBar.js +89 -0
  26. package/dist/client/views/treemap.js +598 -0
  27. package/dist/discoveryrc.js +27 -7
  28. package/dist/rsdoctor.js +19 -99
  29. package/dist/src-DV3VzcQY.js +1548 -0
  30. package/package.json +9 -5
  31. package/assets/highcharts.css +0 -1
  32. package/dist/client/_virtual/_rolldown/runtime.js +0 -37
  33. package/dist/client/views/foamtree.js +0 -103
  34. package/dist/client/views/highcharts.js +0 -33
  35. package/dist/src-DPAqywOJ.js +0 -201
  36. package/vendors/foamtree.js +0 -9008
  37. package/vendors/high-contrast-dark.js +0 -1
  38. package/vendors/highcharts-exporting.js +0 -13
  39. package/vendors/highcharts-networkgraph.js +0 -1
  40. package/vendors/highcharts.js +0 -10
@@ -1,4 +1,56 @@
1
+ const require_sizeHeat = require("./sizeHeat.js");
1
2
  //#region src/client/queryHelpers.ts
3
+ const HIGH_SEVERITY_SHARE = 0.01;
4
+ const TOP_LIST_SIZE = 8;
5
+ const EXT_COLORS = {
6
+ js: "#d4a72c",
7
+ jsx: "#0ea5c6",
8
+ mjs: "#84a62b",
9
+ cjs: "#a3872b",
10
+ ts: "#3178c6",
11
+ tsx: "#2b8a89",
12
+ json: "#e0503a",
13
+ svg: "#c27a0e",
14
+ css: "#7a4fc0",
15
+ png: "#c2347a",
16
+ jpg: "#a33aa8",
17
+ jpeg: "#a33aa8",
18
+ gif: "#5a63d6",
19
+ webp: "#16936b",
20
+ ttf: "#8a6a4f",
21
+ otf: "#8a6a4f",
22
+ wasm: "#654ff0",
23
+ };
24
+ const isNodeModule = (m) => m.path.includes("node_modules/");
25
+ const moduleSize = (m) => m.output.sizeInBytes;
26
+ function toListModule(m) {
27
+ return {
28
+ ext: helpers.getFileExtension(m.path),
29
+ name: m.path,
30
+ size: helpers.formatBytes(moduleSize(m)),
31
+ sizeInBytes: moduleSize(m),
32
+ isEntry: !!m.isEntry,
33
+ };
34
+ }
35
+ function stripVersion(id) {
36
+ const at = id.lastIndexOf("@");
37
+ return at > 0 ? id.slice(0, at) : id;
38
+ }
39
+ function getFindingPackageNames(packages) {
40
+ if (!packages) return [];
41
+ if (typeof packages === "string")
42
+ return [packages.split(/ x\d+:/)[0].trim()].filter(Boolean);
43
+ return Array.from(new Set(packages.map(stripVersion)));
44
+ }
45
+ const modulesByAbsolutePath = /* @__PURE__ */ new WeakMap();
46
+ function getModulesByAbsolutePath(report) {
47
+ let map = modulesByAbsolutePath.get(report);
48
+ if (!map) {
49
+ map = new Map(report.modules.map((m) => [m.absolutePath, m]));
50
+ modulesByAbsolutePath.set(report, map);
51
+ }
52
+ return map;
53
+ }
2
54
  const helpers = {
3
55
  prettifyMap: /* @__PURE__ */ new Map(),
4
56
  prettifyJS(sourceStr) {
@@ -20,16 +72,6 @@ const helpers = {
20
72
  return sourceStr;
21
73
  });
22
74
  },
23
- askChatGPTAboutPackages() {
24
- return `https://chat.openai.com/?prompt=${encodeURIComponent(`I have a list of JavaScript packages from my React Native bundle (see below). I want to optimize bundle size by identifying similar or redundant packages — such as multiple versions of similar libraries (e.g., lodash, lodash-es, underscore, etc.), duplicate utilities, or overlapping functionality (e.g., date libraries like moment, dayjs, date-fns).
25
-
26
- Please do the following:
27
-
28
- 1. Group similar or overlapping packages together.
29
- 2. For each group, suggest which one to keep and which ones to consider removing.
30
- 3. For each group, provide a regex string that can be used to filter those packages from the list (e.g., in grep, find, or search tools).
31
- 4. Keep the output concise and copy-paste friendly.`)}`;
32
- },
33
75
  plural(count, [singular, plural]) {
34
76
  return count === 1 ? singular : plural;
35
77
  },
@@ -79,6 +121,7 @@ Please do the following:
79
121
  const result = [];
80
122
  let entryPointPath = null;
81
123
  const data = [];
124
+ const nodes = [];
82
125
  while (queue.length > 0) {
83
126
  const { module: currentModule, parentId, level } = queue.shift();
84
127
  if (level >= Number(maxParentDepth)) break;
@@ -87,6 +130,15 @@ Please do the following:
87
130
  if (visited.has(id)) continue;
88
131
  visited.add(id);
89
132
  }
133
+ nodes.push({
134
+ id,
135
+ size: currentModule.output.sizeInBytes,
136
+ level,
137
+ isCurrent: level === 0,
138
+ isRoot:
139
+ !!currentModule.isEntry || currentModule.dependents.length === 0,
140
+ isNodeModule: id.includes("node_modules/"),
141
+ });
90
142
  if (parentId) {
91
143
  const isEntryPoint = currentModule.dependents.length === 0;
92
144
  result.push({
@@ -112,22 +164,40 @@ Please do the following:
112
164
  break;
113
165
  }
114
166
  }
167
+ const links = data.map(([parentId, id]) => ({
168
+ source: id,
169
+ target: parentId,
170
+ }));
115
171
  return {
116
172
  entryPointPath,
117
173
  data,
174
+ nodes,
175
+ links,
118
176
  };
119
177
  },
120
178
  getExtColor(extName) {
121
- const colors = {
122
- js: "#f1e05a50",
123
- ts: "#2b748950",
124
- tsx: "#2b748950",
125
- json: "#e34c2650",
126
- svg: "#e69f0d50",
127
- css: "#563d7c50",
128
- png: "#e44b2350",
129
- };
130
- return colors[extName] ?? colors.js;
179
+ const known = EXT_COLORS[extName];
180
+ if (known) return known;
181
+ let hash = 0;
182
+ for (const char of String(extName))
183
+ hash = (hash * 31 + char.charCodeAt(0)) % 360;
184
+ return `hsl(${hash} 55% 45%)`;
185
+ },
186
+ withSizeHeat(items, field) {
187
+ const top = items
188
+ .map((item) => item[field])
189
+ .filter((size) => size > require_sizeHeat.SIZE_HEAT_MIN)
190
+ .sort((a, b) => b - a)
191
+ .slice(0, 3);
192
+ return items.map((item) => {
193
+ const rank = top.indexOf(item[field]);
194
+ return rank === -1
195
+ ? item
196
+ : {
197
+ ...item,
198
+ sizeHeat: 3 - rank,
199
+ };
200
+ });
131
201
  },
132
202
  getFileExtension(filename) {
133
203
  const idx = filename.lastIndexOf(".");
@@ -163,6 +233,387 @@ Please do the following:
163
233
  i = Math.floor(Math.log(bytes) / Math.log(k));
164
234
  return `${parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
165
235
  },
236
+ moduleOverview(report, id) {
237
+ const module = report.modules.find((m) => m.path === id);
238
+ if (!module) return null;
239
+ const size = (m) => m.output.sizeInBytes;
240
+ const totalSize = report.modules.reduce((acc, m) => acc + size(m), 0);
241
+ const largest = report.modules.reduce(
242
+ (acc, m) => Math.max(acc, size(m)),
243
+ 0,
244
+ );
245
+ const rank =
246
+ report.modules.filter((m) => size(m) > size(module)).length + 1;
247
+ const byAbsolutePath = new Map(
248
+ report.modules.map((m) => [m.absolutePath, m]),
249
+ );
250
+ const slash = module.path.lastIndexOf("/");
251
+ const toModule = (m) => ({
252
+ ext: helpers.getFileExtension(m.path),
253
+ name: m.path,
254
+ size: helpers.formatBytes(size(m)),
255
+ sizeInBytes: size(m),
256
+ isEntry: m.isEntry,
257
+ });
258
+ let pkg = null;
259
+ if (module.path.includes("node_modules/")) {
260
+ const name = helpers.getModulesName(module.path);
261
+ const marker = `node_modules/${name}/`;
262
+ const path = module.path.slice(
263
+ 0,
264
+ module.path.lastIndexOf(marker) + marker.length - 1,
265
+ );
266
+ const info = report.packages.find((p) => p.path === path);
267
+ const files = report.modules.filter((m) => m.path.startsWith(`${path}/`));
268
+ const pkgSize = files.reduce((acc, m) => acc + size(m), 0);
269
+ pkg = {
270
+ name,
271
+ path,
272
+ version: info?.version,
273
+ metadata: info?.metadata,
274
+ size: pkgSize,
275
+ files: files.length,
276
+ share: pkgSize ? size(module) / pkgSize : 0,
277
+ };
278
+ }
279
+ const imports = module.dependencies
280
+ .map((d) => {
281
+ const m = byAbsolutePath.get(d.absolutePath);
282
+ return m
283
+ ? {
284
+ specifier: d.name,
285
+ ...toModule(m),
286
+ missing: false,
287
+ }
288
+ : {
289
+ specifier: d.name,
290
+ ext: helpers.getFileExtension(d.path),
291
+ name: d.path,
292
+ size: "",
293
+ sizeInBytes: -1,
294
+ isEntry: false,
295
+ missing: true,
296
+ };
297
+ })
298
+ .sort((a, b) => b.sizeInBytes - a.sizeInBytes);
299
+ const importerPackages = new Set(
300
+ module.dependents.map((m) =>
301
+ m.path.includes("node_modules/") ? helpers.getModulesName(m.path) : "",
302
+ ),
303
+ );
304
+ return {
305
+ path: module.path,
306
+ dir: module.path.slice(0, slash + 1),
307
+ file: module.path.slice(slash + 1),
308
+ ext: helpers.getFileExtension(module.path),
309
+ isEntry: !!module.isEntry,
310
+ injectedBy:
311
+ module.path === "__runtime__"
312
+ ? "Webpack/Rspack"
313
+ : module.path === "__prelude__" ||
314
+ module.path.includes("@react-native/js-polyfills") ||
315
+ module.path.includes("metro-runtime")
316
+ ? "Metro"
317
+ : null,
318
+ outputSize: size(module),
319
+ sourceSize: module.source.sizeInBytes,
320
+ outputLines: module.output.lineCount,
321
+ sourceLines: module.source.lineCount,
322
+ totalSize,
323
+ bundleShare: totalSize ? size(module) / totalSize : 0,
324
+ largestShare: largest ? size(module) / largest : 0,
325
+ rank,
326
+ modulesCount: report.modules.length,
327
+ pkg,
328
+ imports,
329
+ missingImports: imports.filter((i) => i.missing).length,
330
+ importedBy: module.dependents.length,
331
+ importerPackages: importerPackages.size,
332
+ importedByOwnCode: importerPackages.has(""),
333
+ duplicates: module.duplicates.length,
334
+ duplicatesSize: module.duplicates.reduce((acc, m) => acc + size(m), 0),
335
+ };
336
+ },
337
+ reportSummary(report) {
338
+ let totalSize = 0;
339
+ let nodeModulesSize = 0;
340
+ for (const m of report.modules) {
341
+ totalSize += moduleSize(m);
342
+ if (isNodeModule(m)) nodeModulesSize += moduleSize(m);
343
+ }
344
+ const options = report.transformOptions;
345
+ return {
346
+ platform: options?.platform ?? null,
347
+ dev: typeof options?.dev === "boolean" ? options.dev : null,
348
+ minify: typeof options?.minify === "boolean" ? options.minify : null,
349
+ totalSize,
350
+ sourceSize: totalSize - nodeModulesSize,
351
+ nodeModulesSize,
352
+ date: report.date ?? null,
353
+ };
354
+ },
355
+ bundleInsights(report) {
356
+ const totalSize = report.modules.reduce((acc, m) => acc + moduleSize(m), 0);
357
+ const share = (bytes) => (totalSize ? bytes / totalSize : 0);
358
+ const modulesByPath = new Map(report.modules.map((m) => [m.path, m]));
359
+ const packages = /* @__PURE__ */ new Map();
360
+ let nodeModulesSize = 0;
361
+ const ownModules = [];
362
+ for (const m of report.modules) {
363
+ if (!isNodeModule(m)) {
364
+ ownModules.push(m);
365
+ continue;
366
+ }
367
+ nodeModulesSize += moduleSize(m);
368
+ const name = helpers.getModulesName(m.path);
369
+ const marker = `node_modules/${name}/`;
370
+ const pkg = packages.get(name) ?? {
371
+ size: 0,
372
+ copies: /* @__PURE__ */ new Set(),
373
+ };
374
+ pkg.size += moduleSize(m);
375
+ pkg.copies.add(m.path.slice(0, m.path.lastIndexOf(marker)));
376
+ packages.set(name, pkg);
377
+ }
378
+ const sourceSize = totalSize - nodeModulesSize;
379
+ const largestPackage = Math.max(
380
+ 0,
381
+ ...[...packages.values()].map((p) => p.size),
382
+ );
383
+ const largestOwnModule = Math.max(0, ...ownModules.map(moduleSize));
384
+ const countedModules = /* @__PURE__ */ new Set();
385
+ let potentialSavings = 0;
386
+ const findings = (report.recommendations ?? [])
387
+ .map((finding) => {
388
+ const savings = finding.sizeInBytes ?? 0;
389
+ const affected = (finding.modules ?? [])
390
+ .map((path) => modulesByPath.get(path))
391
+ .filter((m) => !!m)
392
+ .sort((a, b) => moduleSize(b) - moduleSize(a));
393
+ const severity =
394
+ savings && share(savings) >= HIGH_SEVERITY_SHARE
395
+ ? "high"
396
+ : savings
397
+ ? "medium"
398
+ : "low";
399
+ return {
400
+ ...finding,
401
+ severity,
402
+ savings,
403
+ savingsShare: share(savings),
404
+ packageNames: getFindingPackageNames(finding.packages),
405
+ packagesText:
406
+ typeof finding.packages === "string" ? finding.packages : null,
407
+ docsUrls: [finding.docsUrl ?? []].flat(),
408
+ affected: affected.map(toListModule),
409
+ affectedSize: affected.reduce((acc, m) => acc + moduleSize(m), 0),
410
+ };
411
+ })
412
+ .sort((a, b) => b.savings - a.savings);
413
+ for (const finding of findings) {
414
+ if (!finding.savings) continue;
415
+ const overlap = finding.affected
416
+ .filter((m) => countedModules.has(m.name))
417
+ .reduce((acc, m) => acc + m.sizeInBytes, 0);
418
+ potentialSavings += Math.max(finding.savings - overlap, 0);
419
+ for (const m of finding.affected) countedModules.add(m.name);
420
+ }
421
+ const duplicatePackages = [...packages.values()].filter(
422
+ (p) => p.copies.size > 1,
423
+ ).length;
424
+ return {
425
+ platform: report.transformOptions?.platform,
426
+ isDev: report.transformOptions?.dev !== false,
427
+ hasRecommendations: report.recommendations !== null,
428
+ totalSize,
429
+ modulesCount: report.modules.length,
430
+ sourceSize,
431
+ sourceShare: share(sourceSize),
432
+ ownModulesCount: ownModules.length,
433
+ nodeModulesSize,
434
+ nodeModulesShare: share(nodeModulesSize),
435
+ packagesCount: packages.size,
436
+ duplicatePackages,
437
+ duplicateModules: report.modules.filter((m) => m.duplicates.length)
438
+ .length,
439
+ potentialSavings,
440
+ potentialSavingsShare: share(potentialSavings),
441
+ findings,
442
+ findingsWithSavings: findings.filter((f) => f.savings).length,
443
+ topPackages: [...packages.entries()]
444
+ .sort((a, b) => b[1].size - a[1].size)
445
+ .slice(0, TOP_LIST_SIZE)
446
+ .map(([name, pkg]) => ({
447
+ name,
448
+ size: pkg.size,
449
+ share: share(pkg.size),
450
+ bar: largestPackage ? pkg.size / largestPackage : 0,
451
+ copies: pkg.copies.size,
452
+ })),
453
+ topPackagesShare: share(
454
+ [...packages.values()]
455
+ .map((p) => p.size)
456
+ .sort((a, b) => b - a)
457
+ .slice(0, 5)
458
+ .reduce((acc, size) => acc + size, 0),
459
+ ),
460
+ topOwnModules: [...ownModules]
461
+ .sort((a, b) => moduleSize(b) - moduleSize(a))
462
+ .slice(0, TOP_LIST_SIZE)
463
+ .map((m) => ({
464
+ name: m.path,
465
+ size: moduleSize(m),
466
+ share: share(moduleSize(m)),
467
+ bar: largestOwnModule ? moduleSize(m) / largestOwnModule : 0,
468
+ })),
469
+ };
470
+ },
471
+ packageOverview(report, name) {
472
+ const isOwn = (m) =>
473
+ isNodeModule(m) && helpers.getModulesName(m.path) === name;
474
+ const files = report.modules.filter(isOwn);
475
+ if (files.length === 0) return null;
476
+ const marker = `node_modules/${name}/`;
477
+ const instancePath = (m) =>
478
+ m.path.slice(0, m.path.lastIndexOf(marker) + marker.length - 1);
479
+ const instances = /* @__PURE__ */ new Map();
480
+ for (const m of files) {
481
+ const path = instancePath(m);
482
+ instances.set(path, [...(instances.get(path) ?? []), m]);
483
+ }
484
+ const totalSize = report.modules.reduce((acc, m) => acc + moduleSize(m), 0);
485
+ const size = files.reduce((acc, m) => acc + moduleSize(m), 0);
486
+ const packageSizes = /* @__PURE__ */ new Map();
487
+ for (const m of report.modules) {
488
+ if (!isNodeModule(m)) continue;
489
+ const pkgName = helpers.getModulesName(m.path);
490
+ packageSizes.set(
491
+ pkgName,
492
+ (packageSizes.get(pkgName) ?? 0) + moduleSize(m),
493
+ );
494
+ }
495
+ const largestPackage = Math.max(...packageSizes.values());
496
+ const rank = [...packageSizes.values()].filter((s) => s > size).length + 1;
497
+ const copies = [...instances.entries()]
498
+ .map(([path, modules]) => {
499
+ const info = report.packages.find((p) => p.path === path);
500
+ return {
501
+ path,
502
+ version: info?.version,
503
+ metadata: info?.metadata ?? null,
504
+ size: modules.reduce((acc, m) => acc + moduleSize(m), 0),
505
+ files: modules.length,
506
+ };
507
+ })
508
+ .sort((a, b) => b.size - a.size);
509
+ const fileSet = new Set(files);
510
+ const importers = /* @__PURE__ */ new Map();
511
+ for (const m of files)
512
+ for (const dependent of m.dependents) {
513
+ if (fileSet.has(dependent)) continue;
514
+ importers.set(
515
+ dependent,
516
+ (importers.get(dependent) ?? /* @__PURE__ */ new Set()).add(m),
517
+ );
518
+ }
519
+ const importerPackages = new Set(
520
+ [...importers.keys()].map((m) =>
521
+ isNodeModule(m) ? helpers.getModulesName(m.path) : "",
522
+ ),
523
+ );
524
+ const largestFile = files.reduce((a, b) =>
525
+ moduleSize(b) > moduleSize(a) ? b : a,
526
+ );
527
+ const withMetadata = copies.find((c) => c.metadata)?.metadata ?? null;
528
+ const findings = (report.recommendations ?? []).filter((f) =>
529
+ getFindingPackageNames(f.packages).includes(name),
530
+ );
531
+ return {
532
+ name,
533
+ paths: copies.map((c) => c.path),
534
+ versions: Array.from(
535
+ new Set(copies.map((c) => c.version).filter(Boolean)),
536
+ ),
537
+ size,
538
+ bundleShare: totalSize ? size / totalSize : 0,
539
+ largestShare: largestPackage ? size / largestPackage : 0,
540
+ rank,
541
+ packagesCount: packageSizes.size,
542
+ filesCount: files.length,
543
+ largestFile: largestFile.path,
544
+ largestFileSize: moduleSize(largestFile),
545
+ copies,
546
+ copiesSavings: size - copies[0].size,
547
+ deprecated: copies.filter((c) => c.metadata?.deprecated),
548
+ latestVersion: withMetadata?.latestVersion ?? null,
549
+ isOutdated: copies.some((c) => c.metadata && !c.metadata.isLatest),
550
+ publishedAt: withMetadata?.createdAt ?? null,
551
+ importedBy: importers.size,
552
+ importerPackages:
553
+ importerPackages.size - (importerPackages.has("") ? 1 : 0),
554
+ importedByOwnCode: importerPackages.has(""),
555
+ importers: [...importers.entries()]
556
+ .map(([m, imported]) => ({
557
+ ...toListModule(m),
558
+ imports: [...imported].map(toListModule),
559
+ }))
560
+ .sort((a, b) => b.sizeInBytes - a.sizeInBytes),
561
+ findings: findings.map((f) => ({
562
+ id: f.id,
563
+ title: f.title,
564
+ })),
565
+ };
566
+ },
567
+ importChain(report, pkgName) {
568
+ const isTarget = (m) =>
569
+ isNodeModule(m) && helpers.getModulesName(m.path) === pkgName;
570
+ const byAbsolutePath = getModulesByAbsolutePath(report);
571
+ const search = (starts) => {
572
+ const prev = /* @__PURE__ */ new Map();
573
+ const queue = [...starts];
574
+ for (const start of starts) prev.set(start, null);
575
+ while (queue.length) {
576
+ const current = queue.shift();
577
+ if (isTarget(current)) {
578
+ const chain = [];
579
+ for (let m = current; m; m = prev.get(m) ?? null) chain.unshift(m);
580
+ return chain;
581
+ }
582
+ for (const dependency of current.dependencies) {
583
+ const next = byAbsolutePath.get(dependency.absolutePath);
584
+ if (next && !prev.has(next)) {
585
+ prev.set(next, current);
586
+ queue.push(next);
587
+ }
588
+ }
589
+ }
590
+ return null;
591
+ };
592
+ let chain = search(report.modules.filter((m) => m.isEntry));
593
+ let fromEntry = true;
594
+ if (!chain) {
595
+ chain = search(report.modules.filter((m) => m.dependents.length === 0));
596
+ fromEntry = false;
597
+ }
598
+ if (!chain) return null;
599
+ return {
600
+ fromEntry,
601
+ steps: chain.map((m, index) => {
602
+ const pkg = isNodeModule(m) ? helpers.getModulesName(m.path) : null;
603
+ const prevModule = chain[index - 1];
604
+ const prevPkg =
605
+ prevModule && isNodeModule(prevModule)
606
+ ? helpers.getModulesName(prevModule.path)
607
+ : null;
608
+ return {
609
+ ...toListModule(m),
610
+ pkg,
611
+ entersPackage: index > 0 && pkg !== prevPkg ? pkg : null,
612
+ isTarget: index === chain.length - 1,
613
+ };
614
+ }),
615
+ };
616
+ },
166
617
  isPackageImport(moduleName) {
167
618
  return moduleName?.[0] !== ".";
168
619
  },
@@ -175,7 +626,7 @@ Please do the following:
175
626
  children: {},
176
627
  size: 0,
177
628
  };
178
- files.forEach(({ path, size }) => {
629
+ files.forEach(({ path, size, issues }) => {
179
630
  if (path === "__prelude__") path = "node_modules/__prelude__";
180
631
  if (path === "__runtime__") path = "node_modules/__runtime__";
181
632
  const shortPath = path.replace(`${rootFolder}/`, "");
@@ -192,79 +643,26 @@ Please do the following:
192
643
  current[part].size = size;
193
644
  current[part].path = shortPath;
194
645
  current[part].fullPath = path;
646
+ current[part].issues = issues;
195
647
  }
196
648
  current = current[part].children;
197
649
  });
198
650
  });
199
- if (type === "foamtree") {
651
+ if (type === "treemap") {
200
652
  sumSizes(nodeModulesMap);
201
653
  sumSizes(sourceCodeMap);
202
- const sourceCodeGroup = toGroups(sourceCodeMap, "Source Code");
203
- const nodeModulesGroup = nodeModulesMap?.children?.node_modules
204
- ? toGroups(nodeModulesMap.children.node_modules, "node_modules")
205
- : {};
206
- if (!sourceCodeGroup.groups) return nodeModulesGroup;
207
- if (!nodeModulesGroup.groups) return sourceCodeGroup;
208
- const topLevelNode = { groups: [sourceCodeGroup, nodeModulesGroup] };
209
- topLevelNode.weight = topLevelNode.groups.reduce(
210
- (acc, group) => acc + group.weight,
211
- 0,
212
- );
213
- return topLevelNode;
214
- }
215
- if (type === "highcharts-treemap") {
216
- const ROOT_ID_1 = "~";
217
- const ROOT_ID_2 = ".";
218
- return [
219
- {
220
- id: ROOT_ID_1,
221
- name: "node_modules",
222
- },
223
- {
224
- id: ROOT_ID_2,
225
- name: "Source Code",
226
- },
227
- ]
228
- .concat(flattenTree(nodeModulesMap.children.node_modules, ROOT_ID_1))
229
- .concat(flattenTree(sourceCodeMap, ROOT_ID_2));
654
+ const roots = [];
655
+ if (Object.keys(sourceCodeMap.children).length > 0)
656
+ roots.push(toTreemapNode(sourceCodeMap, "Source Code"));
657
+ if (nodeModulesMap.children.node_modules)
658
+ roots.push(
659
+ toTreemapNode(nodeModulesMap.children.node_modules, "node_modules"),
660
+ );
661
+ return roots;
230
662
  }
231
663
  throw new Error(`Unsupported type: ${type}`);
232
664
  },
233
665
  };
234
- function flattenTree(
235
- node,
236
- parentId,
237
- prevWasSkipped = false,
238
- lvl = 0,
239
- result = [],
240
- overrideParentId,
241
- ) {
242
- const nodeChildrenCount = Object.keys(node.children);
243
- for (const key of nodeChildrenCount) {
244
- const childNode = node.children[key];
245
- const childId = `${parentId}/${key}`;
246
- const childrenCount = Object.keys(childNode.children).length;
247
- const hasChildren = childrenCount > 0;
248
- const item = {
249
- id: childId,
250
- name: prevWasSkipped ? parentId : key,
251
- parent: overrideParentId ?? parentId,
252
- };
253
- if (!hasChildren) item.value = childNode.size;
254
- if (lvl === 0) item.color = Highcharts.getOptions().colors[randomInt(0, 9)];
255
- const skipThisNode = nodeChildrenCount.length === 1 && childrenCount === 1;
256
- if (!skipThisNode) result.push(item);
257
- flattenTree(
258
- childNode,
259
- childId,
260
- skipThisNode,
261
- lvl + 1,
262
- result,
263
- skipThisNode ? (overrideParentId ?? parentId) : void 0,
264
- );
265
- }
266
- return result;
267
- }
268
666
  function sumSizes(node) {
269
667
  const isFile = Object.keys(node.children).length === 0;
270
668
  let totalFiles = isFile ? 1 : 0;
@@ -282,24 +680,22 @@ function sumSizes(node) {
282
680
  totalFiles,
283
681
  };
284
682
  }
285
- function toGroups(node, label) {
683
+ function toTreemapNode(node, name) {
286
684
  const keys = Object.keys(node.children);
287
685
  const common = {
288
- label,
289
- weight: node.size,
686
+ name,
687
+ value: node.size,
290
688
  fullPath: node.fullPath,
291
689
  files: node.files,
292
690
  type: node.type,
293
691
  size: helpers.formatBytes(node.size),
692
+ issues: node.issues,
294
693
  };
295
694
  if (keys.length === 0) return common;
296
695
  return Object.assign(common, {
297
- groups: keys.map((key) => toGroups(node.children[key], key)),
696
+ children: keys.map((key) => toTreemapNode(node.children[key], key)),
298
697
  });
299
698
  }
300
- function randomInt(min, max) {
301
- return Math.floor(Math.random() * (max - min + 1)) + min;
302
- }
303
699
  const nm = "node_modules/";
304
700
  function shortenPath(path, nodeModulesMap) {
305
701
  if (path.startsWith(`${nm}.pnpm/`)) path = path.replaceAll(`${nm}.pnpm/`, "");
@@ -0,0 +1,7 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/client/sizeHeat.ts
3
+ const SIZE_HEAT_MIN = 716800;
4
+ const SIZE_HEAT_TOP = 3;
5
+ //#endregion
6
+ exports.SIZE_HEAT_MIN = SIZE_HEAT_MIN;
7
+ exports.SIZE_HEAT_TOP = SIZE_HEAT_TOP;
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region src/client/views/_theme.ts
2
+ //#region src/client/views/_colorScheme.ts
3
3
  function isDark() {
4
4
  const isSystemDarkMode = window?.matchMedia?.(
5
5
  "(prefers-color-scheme: dark)",
@@ -7,12 +7,5 @@ function isDark() {
7
7
  const userMode = localStorage.getItem("discoveryjs:color-scheme");
8
8
  return userMode === "auto" ? isSystemDarkMode : userMode === "dark";
9
9
  }
10
- function doTheming(el) {
11
- const dark = isDark();
12
- el.classList.add("highcharts-light");
13
- el.classList[!dark ? "add" : "remove"]("my-light");
14
- el.classList[dark ? "add" : "remove"]("highcharts-dark");
15
- }
16
- if (isDark()) require("../../../vendors/high-contrast-dark.js");
17
10
  //#endregion
18
- exports.doTheming = doTheming;
11
+ exports.isDark = isDark;