react-native-bundle-discovery-ui 2.5.0 → 2.7.0-rc.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/README.md +178 -103
- package/assets/global.css +171 -0
- package/dist/bin.js +202 -0
- package/dist/client/_virtual/_rolldown/runtime.js +23 -0
- package/dist/client/pages/_common.js +282 -0
- package/dist/client/pages/default.js +184 -0
- package/dist/client/pages/module.js +260 -0
- package/dist/client/pages/package.js +187 -0
- package/dist/client/prepare.js +52 -0
- package/dist/client/queryHelpers.js +282 -0
- package/dist/client/setup.js +9 -0
- package/dist/client/views/_theme.js +16 -0
- package/dist/client/views/foamtree.js +88 -0
- package/dist/client/views/highcharts.js +23 -0
- package/dist/client/views/prettify.js +9 -0
- package/dist/discoveryrc.js +21 -0
- package/dist/rolldown-runtime-VH7oDXx4.js +28 -0
- package/dist/rsdoctor.js +75 -0
- package/dist/src-BSLX-He2.js +30 -0
- package/package.json +26 -27
- package/.discoveryrc.js +0 -22
- package/lib/bin.js +0 -94
- package/lib/build.js +0 -123
- package/lib/isRsdoctorReport.js +0 -33
- package/lib/rsdoctor.js +0 -149
- package/lib/server.js +0 -90
- package/pages/_common.js +0 -324
- package/pages/default.js +0 -211
- package/pages/module.js +0 -324
- package/pages/package.js +0 -255
- package/prepare.js +0 -102
- package/queryHelpers.js +0 -375
- package/setup.js +0 -12
- package/views/_theme.js +0 -35
- package/views/foamtree.js +0 -136
- package/views/global.css +0 -169
- package/views/highcharts.js +0 -43
- package/views/prettify.js +0 -17
- /package/{views → assets}/highcharts.css +0 -0
package/dist/bin.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.js");
|
|
3
|
+
const require_src = require("./src-BSLX-He2.js");
|
|
4
|
+
const require_discoveryrc = require("./discoveryrc.js");
|
|
5
|
+
let minimist = require("minimist");
|
|
6
|
+
minimist = require_rolldown_runtime.__toESM(minimist);
|
|
7
|
+
let node_fs = require("node:fs");
|
|
8
|
+
node_fs = require_rolldown_runtime.__toESM(node_fs);
|
|
9
|
+
let node_path = require("node:path");
|
|
10
|
+
node_path = require_rolldown_runtime.__toESM(node_path);
|
|
11
|
+
let _discoveryjs_cli = require("@discoveryjs/cli");
|
|
12
|
+
let chalk = require("chalk");
|
|
13
|
+
chalk = require_rolldown_runtime.__toESM(chalk);
|
|
14
|
+
let _discoveryjs_cli_lib_shared_utils_js = require("@discoveryjs/cli/lib/shared/utils.js");
|
|
15
|
+
//#region src/build.ts
|
|
16
|
+
function buildHtmlPage(filePath, output, clean, singleFile, verbose) {
|
|
17
|
+
if (verbose) console.info(`Building HTML page from file: ${chalk.default.green(filePath)} options: ${JSON.stringify({
|
|
18
|
+
output,
|
|
19
|
+
clean,
|
|
20
|
+
singleFile
|
|
21
|
+
}, null, 2)}`);
|
|
22
|
+
if (!filePath) {
|
|
23
|
+
console.error(`Usage: '${chalk.default.green("npx react-native-bundle-discovery build <path-to-file>")}', Please provide a path to a JSON file.`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
const jsonFilePath = node_path.default.resolve(process.cwd(), filePath);
|
|
27
|
+
if (verbose) console.info(`Loading JSON file from: ${chalk.default.green(jsonFilePath)}, base directory: ${chalk.default.green(process.cwd())}`);
|
|
28
|
+
let fullJsonPath;
|
|
29
|
+
try {
|
|
30
|
+
fullJsonPath = require.resolve(jsonFilePath);
|
|
31
|
+
} catch (err) {
|
|
32
|
+
console.error(`❌Error loading file: ${chalk.default.red(jsonFilePath)}\n\n`);
|
|
33
|
+
console.error(err.message);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const configFile = node_path.default.resolve(__dirname, "./.tmp.js");
|
|
37
|
+
if (verbose) console.info(`Creating temporary config file at: ${chalk.default.green(configFile)}, for discovery.js`);
|
|
38
|
+
const transformRcdoctor = node_path.default.join(__dirname, "rsdoctor.js");
|
|
39
|
+
node_fs.default.writeFileSync(configFile, `const {transformRSDoctorData} = require("${transformRcdoctor}");
|
|
40
|
+
module.exports = ${JSON.stringify({
|
|
41
|
+
...require_discoveryrc,
|
|
42
|
+
data: "<tmp>"
|
|
43
|
+
}, null, 1).replace(`"<tmp>"`, require_src.isRsdoctorReportPath(fullJsonPath) ? `() => transformRSDoctorData(require("${fullJsonPath}"))` : `() => require("${fullJsonPath}")`)};`);
|
|
44
|
+
if (verbose) console.info(`Building HTML page with options:`, {
|
|
45
|
+
output,
|
|
46
|
+
clean,
|
|
47
|
+
singleFile
|
|
48
|
+
});
|
|
49
|
+
const _config = {
|
|
50
|
+
name: "Bundle Discovery",
|
|
51
|
+
mode: "single",
|
|
52
|
+
colorScheme: "auto",
|
|
53
|
+
download: true,
|
|
54
|
+
upload: false,
|
|
55
|
+
embed: false,
|
|
56
|
+
encodings: false
|
|
57
|
+
};
|
|
58
|
+
const _options = {
|
|
59
|
+
singleFile,
|
|
60
|
+
clean,
|
|
61
|
+
output,
|
|
62
|
+
cache: true,
|
|
63
|
+
cachedir: node_path.default.resolve(__dirname, "./.discoveryjs-cache"),
|
|
64
|
+
checkCacheTtl: false,
|
|
65
|
+
minify: true,
|
|
66
|
+
dataCompression: true,
|
|
67
|
+
sourcemap: false,
|
|
68
|
+
embed: "by-config",
|
|
69
|
+
experimentalJsonxl: false,
|
|
70
|
+
scriptFormat: "esm",
|
|
71
|
+
scriptExternal: [],
|
|
72
|
+
data: true,
|
|
73
|
+
excludeModelOnDataFail: false,
|
|
74
|
+
prettyData: false,
|
|
75
|
+
modelDownload: false,
|
|
76
|
+
modelDataUpload: true,
|
|
77
|
+
modelResetCache: false,
|
|
78
|
+
serveOnlyAssets: true,
|
|
79
|
+
dev: true,
|
|
80
|
+
config: configFile,
|
|
81
|
+
configFile
|
|
82
|
+
};
|
|
83
|
+
return (0, _discoveryjs_cli.build)(_options, _config, configFile).then(() => {
|
|
84
|
+
console.log(`========================================`);
|
|
85
|
+
console.log(`✅ HTML page built successfully at: ${chalk.default.green(node_path.default.resolve(output, "index.html").replace(`${process.cwd()}/`, ""))}`);
|
|
86
|
+
console.log(`========================================`);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/server.ts
|
|
91
|
+
function serve(filePath, port, verbose) {
|
|
92
|
+
const PORT = process.env.PORT || port;
|
|
93
|
+
if (verbose) console.info(`start server with file: ${filePath} on port: ${port} ${process.env.PORT ? `(${chalk.default.yellow("PORT")} env)` : ""}`);
|
|
94
|
+
if (!filePath) {
|
|
95
|
+
console.error(`Usage: '${chalk.default.green("npx react-native-bundle-discovery server <path-to-file>")}', Please provide a path to a JSON file.`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
const jsonFilePath = node_path.default.resolve(process.cwd(), filePath);
|
|
99
|
+
if (verbose) console.info(`Loading JSON file from: ${chalk.default.green(jsonFilePath)}, base directory: ${chalk.default.green(process.cwd())}`);
|
|
100
|
+
let fullJsonPath;
|
|
101
|
+
try {
|
|
102
|
+
fullJsonPath = require.resolve(jsonFilePath);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.error(`❌Error loading file: ${chalk.default.red(jsonFilePath)}\n\n`);
|
|
105
|
+
console.error(err.message);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
const configFile = node_path.default.resolve(__dirname, "./.tmp.js");
|
|
109
|
+
if (verbose) console.info(`Creating temporary config file at: ${chalk.default.green(configFile)}, for discovery.js`);
|
|
110
|
+
const transformRcdoctor = node_path.default.join(__dirname, "rsdoctor.js");
|
|
111
|
+
node_fs.default.writeFileSync(configFile, `const {transformRSDoctorData} = require("${transformRcdoctor}");
|
|
112
|
+
module.exports = ${JSON.stringify({
|
|
113
|
+
...require_discoveryrc,
|
|
114
|
+
data: "<tmp>"
|
|
115
|
+
}, null, 1).replace(`"<tmp>"`, require_src.isRsdoctorReportPath(fullJsonPath) ? `() => transformRSDoctorData(require("${fullJsonPath}"))` : `() => require("${fullJsonPath}")`)};`);
|
|
116
|
+
if (verbose) console.info(`Running server with config: ${chalk.default.green(configFile)}`);
|
|
117
|
+
return (0, _discoveryjs_cli_lib_shared_utils_js.silent)(() => (0, _discoveryjs_cli.createServer)({
|
|
118
|
+
cache: false,
|
|
119
|
+
minify: true,
|
|
120
|
+
dev: false,
|
|
121
|
+
config: configFile,
|
|
122
|
+
configFile
|
|
123
|
+
}).then((server) => server.listen(PORT, () => {
|
|
124
|
+
console.log(`[react-native-bundle-discovery]: 🚀 Server listen on ${chalk.default.green.underline(chalk.default.green(`http://localhost:${PORT}`))}`);
|
|
125
|
+
})));
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/bin.ts
|
|
129
|
+
function printHelp() {
|
|
130
|
+
console.log(`react-native-bundle-discovery-ui
|
|
131
|
+
|
|
132
|
+
Usage:
|
|
133
|
+
react-native-bundle-discovery-ui <file> [port] [--verbose] # <- server can be omitted
|
|
134
|
+
react-native-bundle-discovery-ui server <file> [port] [--verbose]
|
|
135
|
+
|
|
136
|
+
react-native-bundle-discovery-ui build <file> [--output <path>] [--clean] [--single-file] [--verbose]
|
|
137
|
+
|
|
138
|
+
Commands:
|
|
139
|
+
server <file> [port] Run a web server to show a Metro bundler stat report
|
|
140
|
+
build <file> Build a HTML report from the Metro bundler stat file
|
|
141
|
+
|
|
142
|
+
Options:
|
|
143
|
+
-v, --verbose Run with verbose logging
|
|
144
|
+
-o, --output <path> Path for a build result (default: .bundle-discovery)
|
|
145
|
+
-c, --clean Clean output directory before writing build files (default: true)
|
|
146
|
+
-s, --single-file Output report build as a single HTML file (default: true)
|
|
147
|
+
-p, --port <port> Port for server command (same as [port], default: 8079)
|
|
148
|
+
-h, --help Show help
|
|
149
|
+
`);
|
|
150
|
+
}
|
|
151
|
+
function fail(message) {
|
|
152
|
+
console.error(message);
|
|
153
|
+
console.error("Use --help to see usage.");
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
function main() {
|
|
157
|
+
const argv = (0, minimist.default)(process.argv.slice(2), {
|
|
158
|
+
alias: {
|
|
159
|
+
v: "verbose",
|
|
160
|
+
h: "help",
|
|
161
|
+
o: "output",
|
|
162
|
+
c: "clean",
|
|
163
|
+
s: "single-file",
|
|
164
|
+
p: "port"
|
|
165
|
+
},
|
|
166
|
+
boolean: [
|
|
167
|
+
"verbose",
|
|
168
|
+
"help",
|
|
169
|
+
"clean",
|
|
170
|
+
"single-file"
|
|
171
|
+
],
|
|
172
|
+
string: ["output"],
|
|
173
|
+
default: {
|
|
174
|
+
clean: true,
|
|
175
|
+
"single-file": true
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
const command = argv._[0];
|
|
179
|
+
const isServerCommand = command === "server";
|
|
180
|
+
const isBuildCommand = command === "build";
|
|
181
|
+
const isImplicitServerCommand = Boolean(command) && !isServerCommand && !isBuildCommand;
|
|
182
|
+
if (argv.help || !command) {
|
|
183
|
+
printHelp();
|
|
184
|
+
process.exit(0);
|
|
185
|
+
}
|
|
186
|
+
if (isServerCommand || isImplicitServerCommand) {
|
|
187
|
+
const file = isImplicitServerCommand ? argv._[0] : argv._[1];
|
|
188
|
+
if (!file) fail("Missing required argument: <file>");
|
|
189
|
+
const rawPort = argv.port ?? (isImplicitServerCommand ? argv._[1] : argv._[2]) ?? 8079;
|
|
190
|
+
const port = Number(rawPort);
|
|
191
|
+
if (!Number.isFinite(port)) fail(`Invalid port: ${rawPort}`);
|
|
192
|
+
return serve(file, port, Boolean(argv.verbose));
|
|
193
|
+
}
|
|
194
|
+
if (isBuildCommand) {
|
|
195
|
+
const file = argv._[1];
|
|
196
|
+
if (!file) fail("Missing required argument: <file>");
|
|
197
|
+
return buildHtmlPage(file, argv.output, argv.clean, argv["single-file"], Boolean(argv.verbose));
|
|
198
|
+
}
|
|
199
|
+
fail(`Unknown command: ${command}`);
|
|
200
|
+
}
|
|
201
|
+
main();
|
|
202
|
+
//#endregion
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.__toESM = __toESM;
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/client/pages/_common.ts
|
|
3
|
+
const platformColor = `transformOptions.platform = 'android' ? 'rgba(194, 239, 116, .4)' : 'rgba(119, 31, 218, .4)'`;
|
|
4
|
+
function getPackage(entry) {
|
|
5
|
+
return `
|
|
6
|
+
$packages: $.packages;
|
|
7
|
+
$totalSize: $.modules.sum(=>output.sizeInBytes);
|
|
8
|
+
$toModule: => {
|
|
9
|
+
ext: $.path.getFileExtension(),
|
|
10
|
+
name: $.path,
|
|
11
|
+
size: $.output.sizeInBytes.formatBytes(),
|
|
12
|
+
percent: ($.output.sizeInBytes / $totalSize).percent(3),
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
${entry}.group(=> path.getModulesName())
|
|
16
|
+
.map(=> ({
|
|
17
|
+
$pkgName: $.key;
|
|
18
|
+
pkgName: $pkgName, // example: lodash
|
|
19
|
+
size: $.value.sum(=>output.sizeInBytes),
|
|
20
|
+
pkgInstances: $.value
|
|
21
|
+
.group(=> path.split('node_modules/' + $pkgName).pick(0) + 'node_modules/' + $pkgName)
|
|
22
|
+
.map(=> {
|
|
23
|
+
$pkgNameWithPath: $.key;
|
|
24
|
+
$pkgInfo: $packages.[path = $pkgNameWithPath][0];
|
|
25
|
+
pkgName: $pkgNameWithPath, // example: node_modules/lodash
|
|
26
|
+
version: $pkgInfo.version,
|
|
27
|
+
metadata: $pkgInfo.metadata,
|
|
28
|
+
size: $.value.sum(=> output.sizeInBytes),
|
|
29
|
+
modules: $.value.map(=> $.$toModule()),
|
|
30
|
+
}),
|
|
31
|
+
}))`;
|
|
32
|
+
}
|
|
33
|
+
const metadataTooltip = {
|
|
34
|
+
view: "text",
|
|
35
|
+
when: "metadata.createdAt",
|
|
36
|
+
data: "'Published ' + metadata.createdAt.formatDate() + ' (' + metadata.createdAt.timeAgo() + ')'"
|
|
37
|
+
};
|
|
38
|
+
const outdatedColor = "rgba(255, 165, 0, 0.35)";
|
|
39
|
+
function getMetadataBadges({ deprecated, outdated, latestVersion, renderLatestVersion }) {
|
|
40
|
+
return [{
|
|
41
|
+
view: "pill-badge",
|
|
42
|
+
when: deprecated,
|
|
43
|
+
data: `{ text: '⚠️ deprecated', message: ${deprecated} }`,
|
|
44
|
+
color: "#cf222e",
|
|
45
|
+
textColor: "white",
|
|
46
|
+
darkColor: "#f85149",
|
|
47
|
+
darkTextColor: "white",
|
|
48
|
+
tooltip: "text: message"
|
|
49
|
+
}, renderLatestVersion ? {
|
|
50
|
+
view: "pill-badge",
|
|
51
|
+
when: outdated,
|
|
52
|
+
data: `{ text: '↑ v' + ${latestVersion} }`,
|
|
53
|
+
color: outdatedColor,
|
|
54
|
+
tooltip: "text: 'Latest version on npm'"
|
|
55
|
+
} : null].filter(Boolean);
|
|
56
|
+
}
|
|
57
|
+
function getPackageList({ data, itemPkgName, showCopiesBadge, expanded, limit, subLimit }) {
|
|
58
|
+
return {
|
|
59
|
+
view: "list",
|
|
60
|
+
data,
|
|
61
|
+
emptyText: "⚠️ No packages found",
|
|
62
|
+
limit,
|
|
63
|
+
item: {
|
|
64
|
+
view: "tree",
|
|
65
|
+
expanded,
|
|
66
|
+
itemConfig: {
|
|
67
|
+
content: [
|
|
68
|
+
itemPkgName,
|
|
69
|
+
"text: ' '",
|
|
70
|
+
"pill-badge:{ text: size.formatBytes(), color: 'rgba(120, 177, 9, 0.35)' }",
|
|
71
|
+
...getMetadataBadges({
|
|
72
|
+
deprecated: "pkgInstances.metadata.deprecated[0]",
|
|
73
|
+
outdated: "pkgInstances.[metadata and not metadata.isLatest]",
|
|
74
|
+
latestVersion: "pkgInstances.metadata.latestVersion[0]",
|
|
75
|
+
renderLatestVersion: false
|
|
76
|
+
}),
|
|
77
|
+
showCopiesBadge ? {
|
|
78
|
+
view: "pill-badge",
|
|
79
|
+
when: "pkgInstances.size() > 1",
|
|
80
|
+
data: "(pkgInstances.size() - 1).pluralBadge(['copy','copies'], '+')",
|
|
81
|
+
color: "rgba(255, 0, 0, 0.35)"
|
|
82
|
+
} : null,
|
|
83
|
+
{
|
|
84
|
+
view: "pill-badge",
|
|
85
|
+
data: "pkgInstances.modules.size().pluralBadge(['file','files'])"
|
|
86
|
+
}
|
|
87
|
+
].filter(Boolean),
|
|
88
|
+
children: `$.pkgInstances`,
|
|
89
|
+
itemConfig: {
|
|
90
|
+
view: "tree-leaf",
|
|
91
|
+
limit: subLimit,
|
|
92
|
+
content: [
|
|
93
|
+
"text:pkgName",
|
|
94
|
+
"text:' '",
|
|
95
|
+
{
|
|
96
|
+
view: "pill-badge",
|
|
97
|
+
data: "{ text: 'v' + version, metadata }",
|
|
98
|
+
color: "#0af",
|
|
99
|
+
tooltip: metadataTooltip
|
|
100
|
+
},
|
|
101
|
+
"pill-badge:{ text: size.formatBytes(), color: 'rgba(120, 177, 9, 0.35)' }",
|
|
102
|
+
{
|
|
103
|
+
view: "pill-badge",
|
|
104
|
+
data: "modules.size().pluralBadge(['file','files'])"
|
|
105
|
+
},
|
|
106
|
+
...getMetadataBadges({
|
|
107
|
+
deprecated: "metadata.deprecated",
|
|
108
|
+
outdated: "metadata and not metadata.isLatest",
|
|
109
|
+
latestVersion: "metadata.latestVersion",
|
|
110
|
+
renderLatestVersion: true
|
|
111
|
+
})
|
|
112
|
+
],
|
|
113
|
+
children: `$.modules`,
|
|
114
|
+
itemConfig: {
|
|
115
|
+
view: "tree-leaf",
|
|
116
|
+
content: getTreeModule({ hasPercent: true })
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function getTreeModule({ hasTextMatch = false, hasPercent = false } = {}) {
|
|
124
|
+
return [
|
|
125
|
+
"pill-badge:{ text: ext, color: ext.getExtColor() }",
|
|
126
|
+
hasTextMatch ? {
|
|
127
|
+
view: "link",
|
|
128
|
+
content: hasTextMatch ? "text-match" : "text",
|
|
129
|
+
data: `{
|
|
130
|
+
href: name.pageLink("module", {}),
|
|
131
|
+
text: name,
|
|
132
|
+
match: #.filterByPathStr
|
|
133
|
+
}`
|
|
134
|
+
} : {
|
|
135
|
+
view: "link",
|
|
136
|
+
data: `{ href: $.name.pageLink("module", {}), text: $.name }`
|
|
137
|
+
},
|
|
138
|
+
"text:' '",
|
|
139
|
+
{
|
|
140
|
+
view: "badge",
|
|
141
|
+
when: "isEntry",
|
|
142
|
+
text: "Entrypoint",
|
|
143
|
+
color: "gold",
|
|
144
|
+
textColor: "black"
|
|
145
|
+
},
|
|
146
|
+
"pill-badge:{ text: size, color: 'rgba(120, 177, 9, 0.35)' }",
|
|
147
|
+
hasPercent ? "pill-badge:{ text: percent, color: 'rgba(120, 177, 9, 0.35)' }" : null
|
|
148
|
+
].filter(Boolean);
|
|
149
|
+
}
|
|
150
|
+
function getModulesTree({ data, limit }) {
|
|
151
|
+
if (!data) throw new Error("[getModulesTree]: data is required");
|
|
152
|
+
return {
|
|
153
|
+
view: "content-filter",
|
|
154
|
+
data,
|
|
155
|
+
name: "filterByPathStr",
|
|
156
|
+
content: {
|
|
157
|
+
view: "list",
|
|
158
|
+
limit,
|
|
159
|
+
data: ".[name ~= #.filterByPathStr]",
|
|
160
|
+
emptyText: "⚠️ No modules found",
|
|
161
|
+
item: {
|
|
162
|
+
view: "tree",
|
|
163
|
+
expanded: false,
|
|
164
|
+
itemConfig: {
|
|
165
|
+
content: getTreeModule({ hasTextMatch: true }),
|
|
166
|
+
children: `
|
|
167
|
+
[
|
|
168
|
+
{
|
|
169
|
+
title:'Imported by modules',
|
|
170
|
+
data: $.reasons,
|
|
171
|
+
type: 'reasons',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
title:'Similar copies',
|
|
175
|
+
data: $.duplicates,
|
|
176
|
+
type: 'duplicates',
|
|
177
|
+
}
|
|
178
|
+
].filter(=> $.data.size() > 0)
|
|
179
|
+
`,
|
|
180
|
+
itemConfig: {
|
|
181
|
+
view: "switch",
|
|
182
|
+
content: [{
|
|
183
|
+
when: "type=\"reasons\"",
|
|
184
|
+
content: {
|
|
185
|
+
view: "tree-leaf",
|
|
186
|
+
content: [
|
|
187
|
+
"text:title",
|
|
188
|
+
"text:' '",
|
|
189
|
+
"badge:{ text: $.data.size() }"
|
|
190
|
+
],
|
|
191
|
+
children: `$.data`,
|
|
192
|
+
itemConfig: {
|
|
193
|
+
view: "tree-leaf",
|
|
194
|
+
content: getTreeModule()
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}, {
|
|
198
|
+
when: "type=\"duplicates\"",
|
|
199
|
+
content: {
|
|
200
|
+
view: "tree-leaf",
|
|
201
|
+
content: [
|
|
202
|
+
"text:title",
|
|
203
|
+
"text:' '",
|
|
204
|
+
"badge:{ text: $.data.size() }"
|
|
205
|
+
],
|
|
206
|
+
children: `$.data`,
|
|
207
|
+
itemConfig: {
|
|
208
|
+
view: "tree-leaf",
|
|
209
|
+
content: getTreeModule()
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}]
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const metadata = {
|
|
220
|
+
platform: {
|
|
221
|
+
when: "transformOptions.platform",
|
|
222
|
+
view: "badge",
|
|
223
|
+
data: `{ prefix: 'Platform: ', text: transformOptions.platform, color: ${platformColor} }`
|
|
224
|
+
},
|
|
225
|
+
size: {
|
|
226
|
+
when: "modules.filter(=> $.path has 'node_modules').size()",
|
|
227
|
+
view: "badge",
|
|
228
|
+
data: `{ prefix: 'Size: ', text: modules.sum(=>output.sizeInBytes).formatBytes(), color: ${platformColor} }`
|
|
229
|
+
},
|
|
230
|
+
node_modules_size: {
|
|
231
|
+
when: "modules.filter(=> $.path has 'node_modules').size()",
|
|
232
|
+
view: "badge",
|
|
233
|
+
data: "{ prefix: 'node_modules: ', text: modules.filter(=> $.path has 'node_modules').sum(=>output.sizeInBytes).formatBytes(), color: 'rgba(255, 0, 0, 0.35)' }"
|
|
234
|
+
},
|
|
235
|
+
source_code_size: {
|
|
236
|
+
when: "modules.filter(=> $.path has 'node_modules').size()",
|
|
237
|
+
view: "badge",
|
|
238
|
+
data: `
|
|
239
|
+
// vars
|
|
240
|
+
$totalSize: modules.sum(=>output.sizeInBytes);
|
|
241
|
+
$thirdPartySize: modules.filter(=> $.path has 'node_modules').sum(=>output.sizeInBytes);
|
|
242
|
+
// return data
|
|
243
|
+
{ prefix: 'Source code: ', text: ($totalSize - $thirdPartySize).formatBytes(), color: 'rgba(148, 111, 234, 0.5)' }`
|
|
244
|
+
},
|
|
245
|
+
is_dev: {
|
|
246
|
+
when: "transformOptions.dev != null",
|
|
247
|
+
view: "badge",
|
|
248
|
+
data: "{ prefix: '__DEV__: ', text: transformOptions.dev }"
|
|
249
|
+
},
|
|
250
|
+
is_minified: {
|
|
251
|
+
when: "transformOptions.minify != null",
|
|
252
|
+
view: "badge",
|
|
253
|
+
data: "{ prefix: 'Minify: ', text: transformOptions.minify }"
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
const externalLinkHtml = `<svg class="my-icon my-icon-link" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" ><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14 21 3"></path></svg>`;
|
|
257
|
+
function getCopyToClipboardButton({ textToCopy, className, text }) {
|
|
258
|
+
return {
|
|
259
|
+
view: "button",
|
|
260
|
+
className: `${className ?? ""} copy-to-clipboard`,
|
|
261
|
+
text,
|
|
262
|
+
data: `{ textToCopy: ${textToCopy} }`,
|
|
263
|
+
onClick(elm, data) {
|
|
264
|
+
clearTimeout(elm.__timer);
|
|
265
|
+
navigator.clipboard.writeText(data.textToCopy).then(() => {
|
|
266
|
+
elm.classList.add("done");
|
|
267
|
+
elm.__timer = setTimeout(() => elm.classList.remove("done"), 2e3);
|
|
268
|
+
}).catch(() => {
|
|
269
|
+
elm.classList.add("err");
|
|
270
|
+
elm.__timer = setTimeout(() => elm.classList.remove("err"), 2e3);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
//#endregion
|
|
276
|
+
exports.externalLinkHtml = externalLinkHtml;
|
|
277
|
+
exports.getCopyToClipboardButton = getCopyToClipboardButton;
|
|
278
|
+
exports.getModulesTree = getModulesTree;
|
|
279
|
+
exports.getPackage = getPackage;
|
|
280
|
+
exports.getPackageList = getPackageList;
|
|
281
|
+
exports.getTreeModule = getTreeModule;
|
|
282
|
+
exports.metadata = metadata;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
const require_pages__common = require("./_common.js");
|
|
2
|
+
//#region src/client/pages/default.ts
|
|
3
|
+
const topMetaData = [
|
|
4
|
+
require_pages__common.metadata.platform,
|
|
5
|
+
require_pages__common.metadata.size,
|
|
6
|
+
require_pages__common.metadata.source_code_size,
|
|
7
|
+
require_pages__common.metadata.node_modules_size,
|
|
8
|
+
require_pages__common.metadata.is_dev,
|
|
9
|
+
require_pages__common.metadata.is_minified
|
|
10
|
+
];
|
|
11
|
+
const TABS = {
|
|
12
|
+
TREEMAP_FOAMTREE: "treemap-foamtree",
|
|
13
|
+
MODULES: "modules",
|
|
14
|
+
PACKAGES: "packages",
|
|
15
|
+
DUPLICATES: "duplicates"
|
|
16
|
+
};
|
|
17
|
+
function parseHashRef(url = window.location.href) {
|
|
18
|
+
return new URL(url).hash.split(":")?.[1];
|
|
19
|
+
}
|
|
20
|
+
discovery.page.define("default", [...topMetaData, {
|
|
21
|
+
view: "tabs",
|
|
22
|
+
name: "mainTabs",
|
|
23
|
+
className: "main-tabs",
|
|
24
|
+
value: parseHashRef() ?? TABS.TREEMAP_FOAMTREE,
|
|
25
|
+
tabs: [
|
|
26
|
+
{
|
|
27
|
+
value: TABS.TREEMAP_FOAMTREE,
|
|
28
|
+
text: "Treemap chart",
|
|
29
|
+
className: `main-tabs-${TABS.TREEMAP_FOAMTREE}`
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
value: TABS.PACKAGES,
|
|
33
|
+
className: `main-tabs-${TABS.PACKAGES}`,
|
|
34
|
+
content: ["text:'Packages '", `pill-badge: modules.filter(=> path has "node_modules").group(=> path.getModulesName(), => 0).size()`]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
value: TABS.MODULES,
|
|
38
|
+
className: `main-tabs-${TABS.MODULES}`,
|
|
39
|
+
content: ["text:'Modules '", "pill-badge: modules.size()"]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
value: TABS.DUPLICATES,
|
|
43
|
+
className: `main-tabs-${TABS.DUPLICATES}`,
|
|
44
|
+
content: ["text:'Duplicate modules '", "pill-badge: modules.filter(=> duplicates).size()"]
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
content: {
|
|
48
|
+
view: "switch",
|
|
49
|
+
context(_data, context) {
|
|
50
|
+
const isHashChangeEvent = (/* @__PURE__ */ new Error("")).stack.includes("Promise.all");
|
|
51
|
+
discovery.overridePageHashStateWithAnchor({
|
|
52
|
+
id: "default",
|
|
53
|
+
ref: isHashChangeEvent ? discovery.pageRef : context.mainTabs
|
|
54
|
+
});
|
|
55
|
+
discovery.cancelScheduledRender();
|
|
56
|
+
const id = discovery.pageRef ?? TABS.TREEMAP_FOAMTREE;
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
discovery.dom.root.querySelectorAll(".main-tabs>div>.onclick").forEach((e) => {
|
|
59
|
+
e.classList.remove("active");
|
|
60
|
+
});
|
|
61
|
+
discovery.dom.root.querySelectorAll(`.main-tabs .main-tabs-${id}`).forEach((e) => {
|
|
62
|
+
e.classList.add("active");
|
|
63
|
+
});
|
|
64
|
+
}, 50);
|
|
65
|
+
return {
|
|
66
|
+
...context,
|
|
67
|
+
id
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
72
|
+
when: `#.id="${TABS.TREEMAP_FOAMTREE}"`,
|
|
73
|
+
content: {
|
|
74
|
+
view: "content-filter",
|
|
75
|
+
name: "filterByPathStr",
|
|
76
|
+
debounce: 300,
|
|
77
|
+
className: "foamtree-filter",
|
|
78
|
+
content: {
|
|
79
|
+
view: "foamtree",
|
|
80
|
+
data: `
|
|
81
|
+
$root: $.rootFolder;
|
|
82
|
+
$applyFilter: => #.filterByPathStr ? $.modules.filter(=> $.path ~= #.filterByPathStr) : $.modules;
|
|
83
|
+
$dataObject: $.$applyFilter()
|
|
84
|
+
.map(=> {path, size: $.output.sizeInBytes})
|
|
85
|
+
.transformFilesList($root, "foamtree");
|
|
86
|
+
|
|
87
|
+
{
|
|
88
|
+
options: {
|
|
89
|
+
dataObject: $dataObject,
|
|
90
|
+
descriptionGroupSize: 0.05,
|
|
91
|
+
descriptionGroupMinHeight: 30,
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
`
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
when: `#.id="${TABS.MODULES}"`,
|
|
100
|
+
content: require_pages__common.getModulesTree({
|
|
101
|
+
limit: 200,
|
|
102
|
+
data: `
|
|
103
|
+
$entryPoint: $.entryPointPath;
|
|
104
|
+
$totalSize: modules.sum(=>output.sizeInBytes);
|
|
105
|
+
$toModule: => {
|
|
106
|
+
ext: $.path.getFileExtension(),
|
|
107
|
+
name: $.path,
|
|
108
|
+
size: $.output.sizeInBytes.formatBytes(),
|
|
109
|
+
percent: ($.output.sizeInBytes / $totalSize).percent(3),
|
|
110
|
+
};
|
|
111
|
+
modules.map(=> {
|
|
112
|
+
...$.$toModule(),
|
|
113
|
+
isEntry: $.isEntry,
|
|
114
|
+
reasons: $.dependents.map(=> $.$toModule()),
|
|
115
|
+
duplicates: $.duplicates.map(=> $.$toModule()),
|
|
116
|
+
})
|
|
117
|
+
`
|
|
118
|
+
})
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
when: `#.id="${TABS.PACKAGES}"`,
|
|
122
|
+
content: [
|
|
123
|
+
require_pages__common.getCopyToClipboardButton({
|
|
124
|
+
text: "Copy list",
|
|
125
|
+
className: "copy-before-ask-chatgpt",
|
|
126
|
+
textToCopy: `"- " + modules.filter(=> path has "node_modules").group(=> path.getModulesName()).map(=> $.key).join("\\n- ")`
|
|
127
|
+
}),
|
|
128
|
+
{
|
|
129
|
+
view: "link",
|
|
130
|
+
className: "ask-chatgpt view-button",
|
|
131
|
+
text: "and Ask ChatGPT",
|
|
132
|
+
external: true,
|
|
133
|
+
data: `{
|
|
134
|
+
href: $.askChatGPTAboutPackages()
|
|
135
|
+
}`
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
view: "content-filter",
|
|
139
|
+
data: `${require_pages__common.getPackage(`modules.filter(=> path has "node_modules")`)}.sort(pkgInstances desc, size desc)`,
|
|
140
|
+
className: "packages-content",
|
|
141
|
+
name: "filterByPathStr",
|
|
142
|
+
content: require_pages__common.getPackageList({
|
|
143
|
+
showCopiesBadge: true,
|
|
144
|
+
expanded: false,
|
|
145
|
+
limit: 200,
|
|
146
|
+
subLimit: 50,
|
|
147
|
+
data: ".[pkgName ~= #.filterByPathStr]",
|
|
148
|
+
itemPkgName: {
|
|
149
|
+
view: "link",
|
|
150
|
+
content: "text-match",
|
|
151
|
+
data: `{
|
|
152
|
+
href: pkgName.pageLink("package", {}),
|
|
153
|
+
text: pkgName,
|
|
154
|
+
match: #.filterByPathStr
|
|
155
|
+
}`
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
when: `#.id="${TABS.DUPLICATES}"`,
|
|
163
|
+
content: require_pages__common.getModulesTree({ data: `
|
|
164
|
+
// values
|
|
165
|
+
$duplicatesOnly: modules.filter(=> duplicates);
|
|
166
|
+
$totalSize: $duplicatesOnly.sum(=>output.sizeInBytes);
|
|
167
|
+
$toModule: => {
|
|
168
|
+
ext: $.path.getFileExtension(),
|
|
169
|
+
name: $.path,
|
|
170
|
+
size: $.output.sizeInBytes.formatBytes(),
|
|
171
|
+
percent: ($.output.sizeInBytes / $totalSize).percent(3),
|
|
172
|
+
};
|
|
173
|
+
// return
|
|
174
|
+
$duplicatesOnly.map(=> {
|
|
175
|
+
...$.$toModule(),
|
|
176
|
+
reasons: $.dependents.map(=> $.$toModule()),
|
|
177
|
+
duplicates: $.duplicates.map(=> $.$toModule()),
|
|
178
|
+
})
|
|
179
|
+
` })
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
}]);
|
|
184
|
+
//#endregion
|