react-native-bundle-discovery-ui 2.0.0-rc.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.
@@ -0,0 +1,267 @@
1
+ const platformColor = `transformOptions.platform = 'android' ? 'rgba(194, 239, 116, .4)' : 'rgba(119, 31, 218, .4)'`;
2
+
3
+ function getPackage(entry) {
4
+ return `
5
+ $packages: $.packages;
6
+ $totalSize: $.modules.sum(=>output.sizeInBytes);
7
+ $toModule: => {
8
+ ext: $.path.getFileExtension(),
9
+ name: $.path,
10
+ size: $.output.sizeInBytes.formatBytes(),
11
+ percent: ($.output.sizeInBytes / $totalSize).percent(3),
12
+ };
13
+
14
+ ${entry}.group(=> path.getModulesName())
15
+ .map(=> ({
16
+ $pkgName: $.key;
17
+ pkgName: $pkgName, // example: lodash
18
+ size: $.value.sum(=>output.sizeInBytes),
19
+ pkgInstances: $.value
20
+ .group(=> path.split($pkgName).pick(0) + $pkgName)
21
+ .map(=> {
22
+ $pkgNameWithPath: $.key;
23
+ pkgName: $pkgNameWithPath, // example: node_modules/lodash
24
+ version: $packages.[path = $pkgNameWithPath][0].version,
25
+ size: $.value.sum(=> output.sizeInBytes),
26
+ modules: $.value.map(=> $.$toModule()),
27
+ }),
28
+ }))`;
29
+ }
30
+
31
+ function getPackageList({
32
+ data,
33
+ itemPkgName,
34
+ showCopiesBadge,
35
+ expanded,
36
+ limit,
37
+ subLimit,
38
+ }) {
39
+ return {
40
+ view: "list",
41
+ data,
42
+ emptyText: "⚠️ No packages found",
43
+ limit,
44
+ item: {
45
+ view: "tree",
46
+ expanded,
47
+ itemConfig: {
48
+ content: [
49
+ itemPkgName,
50
+ "text: ' '",
51
+ "pill-badge:{ text: size.formatBytes(), color: 'rgba(120, 177, 9, 0.35)' }",
52
+ showCopiesBadge
53
+ ? {
54
+ view: "pill-badge",
55
+ when: "pkgInstances.size() > 1",
56
+ data: "(pkgInstances.size() - 1).pluralBadge(['copy','copies'], '+')",
57
+ color: "rgba(255, 0, 0, 0.35)",
58
+ }
59
+ : null,
60
+ {
61
+ view: "pill-badge",
62
+ data: "pkgInstances.modules.size().pluralBadge(['file','files'])",
63
+ },
64
+ ].filter(Boolean),
65
+ children: `$.pkgInstances`,
66
+ itemConfig: {
67
+ view: "tree-leaf",
68
+ limit: subLimit,
69
+ content: [
70
+ //
71
+ "text:pkgName",
72
+ "text:' '",
73
+ "pill-badge:{ text: 'v' + version, color: '#0af' }",
74
+ "pill-badge:{ text: size.formatBytes(), color: 'rgba(120, 177, 9, 0.35)' }",
75
+ {
76
+ view: "pill-badge",
77
+ data: "modules.size().pluralBadge(['file','files'])",
78
+ },
79
+ ],
80
+ children: `$.modules`,
81
+ itemConfig: {
82
+ view: "tree-leaf",
83
+ content: getTreeModule({ hasPercent: true }),
84
+ },
85
+ },
86
+ },
87
+ },
88
+ };
89
+ }
90
+
91
+ function getTreeModule({ hasTextMatch = false, hasPercent = false } = {}) {
92
+ return [
93
+ "pill-badge:{ text: ext, color: ext.getExtColor() }",
94
+ hasTextMatch
95
+ ? {
96
+ view: "link",
97
+ content: hasTextMatch ? "text-match" : "text",
98
+ data: `{
99
+ href: name.pageLink("module", {}),
100
+ text: name,
101
+ match: #.filterByPathStr
102
+ }`,
103
+ }
104
+ : {
105
+ view: "link",
106
+ data: `{ href: $.name.pageLink("module", {}), text: $.name }`,
107
+ },
108
+ "text:' '",
109
+ {
110
+ view: "badge",
111
+ when: "isEntry",
112
+ text: "Entrypoint",
113
+ color: "gold",
114
+ textColor: "black",
115
+ },
116
+ "pill-badge:{ text: size, color: 'rgba(120, 177, 9, 0.35)' }",
117
+ hasPercent
118
+ ? "pill-badge:{ text: percent, color: 'rgba(120, 177, 9, 0.35)' }"
119
+ : null,
120
+ ].filter(Boolean);
121
+ }
122
+ function getModulesTree({ data, limit }) {
123
+ if (!data) {
124
+ throw new Error("[getModulesTree]: data is required");
125
+ }
126
+ return {
127
+ view: "content-filter",
128
+ data,
129
+ name: "filterByPathStr",
130
+ content: {
131
+ view: "list",
132
+ limit,
133
+ data: ".[name ~= #.filterByPathStr]",
134
+ emptyText: "⚠️ No modules found",
135
+ item: {
136
+ view: "tree",
137
+ expanded: false,
138
+ itemConfig: {
139
+ content: getTreeModule({ hasTextMatch: true }),
140
+ children: `
141
+ [
142
+ {
143
+ title:'Imported by modules',
144
+ data: $.reasons,
145
+ type: 'reasons',
146
+ },
147
+ {
148
+ title:'Similar copies',
149
+ data: $.duplicates,
150
+ type: 'duplicates',
151
+ }
152
+ ].filter(=> $.data.size() > 0)
153
+ `,
154
+ itemConfig: {
155
+ view: "switch",
156
+ content: [
157
+ {
158
+ when: 'type="reasons"',
159
+ content: {
160
+ view: "tree-leaf",
161
+ content: [
162
+ "text:title",
163
+ "text:' '",
164
+ "badge:{ text: $.data.size() }",
165
+ ],
166
+ children: `$.data`,
167
+ itemConfig: {
168
+ view: "tree-leaf",
169
+ content: getTreeModule(),
170
+ },
171
+ },
172
+ },
173
+ {
174
+ when: 'type="duplicates"',
175
+ content: {
176
+ view: "tree-leaf",
177
+ content: [
178
+ "text:title",
179
+ "text:' '",
180
+ "badge:{ text: $.data.size() }",
181
+ ],
182
+ children: `$.data`,
183
+ itemConfig: {
184
+ view: "tree-leaf",
185
+ content: getTreeModule(),
186
+ },
187
+ },
188
+ },
189
+ ],
190
+ },
191
+ },
192
+ },
193
+ },
194
+ };
195
+ }
196
+
197
+ const metadata = {
198
+ platform: {
199
+ when: "transformOptions.platform",
200
+ view: "badge",
201
+ data: `{ prefix: 'Platform: ', text: transformOptions.platform, color: ${platformColor} }`,
202
+ },
203
+ size: {
204
+ when: "modules.filter(=> $.path has 'node_modules').size()",
205
+ view: "badge",
206
+ data: `{ prefix: 'Size: ', text: modules.sum(=>output.sizeInBytes).formatBytes(), color: ${platformColor} }`,
207
+ },
208
+ node_modules_size: {
209
+ when: "modules.filter(=> $.path has 'node_modules').size()",
210
+ view: "badge",
211
+ data: "{ prefix: 'node_modules: ', text: modules.filter(=> $.path has 'node_modules').sum(=>output.sizeInBytes).formatBytes(), color: 'rgba(255, 0, 0, 0.35)' }",
212
+ },
213
+ source_code_size: {
214
+ when: "modules.filter(=> $.path has 'node_modules').size()",
215
+ view: "badge",
216
+ data: `
217
+ // vars
218
+ $totalSize: modules.sum(=>output.sizeInBytes);
219
+ $thirdPartySize: modules.filter(=> $.path has 'node_modules').sum(=>output.sizeInBytes);
220
+ // return data
221
+ { prefix: 'Source code: ', text: ($totalSize - $thirdPartySize).formatBytes(), color: 'rgba(148, 111, 234, 0.5)' }`,
222
+ },
223
+ is_dev: {
224
+ when: "transformOptions.dev != null",
225
+ view: "badge",
226
+ data: "{ prefix: '__DEV__: ', text: transformOptions.dev }",
227
+ },
228
+ is_minified: {
229
+ when: "transformOptions.minify != null",
230
+ view: "badge",
231
+ data: "{ prefix: 'Minify: ', text: transformOptions.minify }",
232
+ },
233
+ };
234
+
235
+ 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>`;
236
+
237
+ function getCopyToClipboardButton({ textToCopy, className, text }) {
238
+ return {
239
+ view: "button",
240
+ className: `${className ?? ""} copy-to-clipboard`,
241
+ text,
242
+ data: `{ textToCopy: ${textToCopy} }`,
243
+ onClick(elm, data) {
244
+ clearTimeout(elm.__timer);
245
+ navigator.clipboard
246
+ .writeText(data.textToCopy)
247
+ .then(() => {
248
+ elm.classList.add("done");
249
+ elm.__timer = setTimeout(() => elm.classList.remove("done"), 2000);
250
+ })
251
+ .catch(() => {
252
+ elm.classList.add("err");
253
+ elm.__timer = setTimeout(() => elm.classList.remove("err"), 2000);
254
+ });
255
+ },
256
+ };
257
+ }
258
+
259
+ module.exports = {
260
+ getCopyToClipboardButton,
261
+ getPackage,
262
+ getPackageList,
263
+ externalLinkHtml,
264
+ getTreeModule,
265
+ getModulesTree,
266
+ metadata,
267
+ };
@@ -0,0 +1,211 @@
1
+ const {
2
+ metadata,
3
+ getModulesTree,
4
+ getPackage,
5
+ getPackageList,
6
+ getCopyToClipboardButton,
7
+ } = require("./_common");
8
+
9
+ const topMetaData = [
10
+ metadata.platform,
11
+ metadata.size,
12
+ metadata.source_code_size,
13
+ metadata.node_modules_size,
14
+ metadata.is_dev,
15
+ metadata.is_minified,
16
+ ];
17
+
18
+ const TABS = {
19
+ TREEMAP_FOAMTREE: "treemap-foamtree",
20
+ MODULES: "modules",
21
+ PACKAGES: "packages",
22
+ DUPLICATES: "duplicates",
23
+ };
24
+
25
+ function parseHashRef(url = window.location.href) {
26
+ return new URL(url).hash.split(":")?.[1];
27
+ }
28
+
29
+ discovery.page.define("default", [
30
+ ...topMetaData,
31
+
32
+ {
33
+ view: "tabs",
34
+ name: "mainTabs",
35
+ className: "main-tabs",
36
+ value: parseHashRef() ?? TABS.TREEMAP_FOAMTREE,
37
+ tabs: [
38
+ {
39
+ value: TABS.TREEMAP_FOAMTREE,
40
+ text: "Treemap chart",
41
+ className: `main-tabs-${TABS.TREEMAP_FOAMTREE}`,
42
+ },
43
+ {
44
+ value: TABS.PACKAGES,
45
+ className: `main-tabs-${TABS.PACKAGES}`,
46
+ content: [
47
+ "text:'Packages '",
48
+ `pill-badge: modules.filter(=> path has "node_modules").group(=> path.getModulesName(), => 0).size()`,
49
+ ],
50
+ },
51
+ {
52
+ value: TABS.MODULES,
53
+ className: `main-tabs-${TABS.MODULES}`,
54
+ content: ["text:'Modules '", "pill-badge: modules.size()"],
55
+ },
56
+ {
57
+ value: TABS.DUPLICATES,
58
+ className: `main-tabs-${TABS.DUPLICATES}`,
59
+ content: [
60
+ "text:'Duplicate modules '",
61
+ "pill-badge: modules.filter(=> duplicates).size()",
62
+ ],
63
+ },
64
+ ],
65
+ content: {
66
+ view: "switch",
67
+ context(data, context) {
68
+ // FIXME - common nobody handle navigation in such way :(
69
+ const isHashChangeEvent = new Error("").stack.includes("Promise.all");
70
+ discovery.overridePageHashStateWithAnchor({
71
+ id: "default",
72
+ ref: isHashChangeEvent ? discovery.pageRef : context.mainTabs,
73
+ });
74
+ discovery.cancelScheduledRender();
75
+
76
+ const id = discovery.pageRef ?? TABS.TREEMAP_FOAMTREE;
77
+
78
+ setTimeout(() => {
79
+ discovery.dom.root
80
+ .querySelectorAll(".main-tabs>div>.onclick")
81
+ .forEach((e) => e.classList.remove("active"));
82
+ discovery.dom.root
83
+ .querySelectorAll(`.main-tabs .main-tabs-${id}`)
84
+ .forEach((e) => e.classList.add("active"));
85
+ }, 50);
86
+
87
+ return {
88
+ ...context,
89
+ id,
90
+ };
91
+ },
92
+ content: [
93
+ {
94
+ when: `#.id="${TABS.TREEMAP_FOAMTREE}"`,
95
+ content: {
96
+ view: "content-filter",
97
+ name: "filterByPathStr",
98
+ debounce: 300,
99
+ className: "foamtree-filter",
100
+ content: {
101
+ view: "foamtree",
102
+ data: `
103
+ $root: $.rootFolder;
104
+ $applyFilter: => #.filterByPathStr ? $.modules.filter(=> $.path ~= #.filterByPathStr) : $.modules;
105
+ $dataObject: $.$applyFilter()
106
+ .map(=> {path, size: $.output.sizeInBytes})
107
+ .transformFilesList($root, "foamtree");
108
+
109
+ {
110
+ options: {
111
+ dataObject: $dataObject,
112
+ descriptionGroupSize: 0.05,
113
+ descriptionGroupMinHeight: 30,
114
+ }
115
+ }
116
+ `,
117
+ },
118
+ },
119
+ },
120
+ {
121
+ when: `#.id="${TABS.MODULES}"`,
122
+ content: getModulesTree({
123
+ limit: 200,
124
+ data: `
125
+ $entryPoint: $.entryPointPath;
126
+ $totalSize: modules.sum(=>output.sizeInBytes);
127
+ $toModule: => {
128
+ ext: $.path.getFileExtension(),
129
+ name: $.path,
130
+ size: $.output.sizeInBytes.formatBytes(),
131
+ percent: ($.output.sizeInBytes / $totalSize).percent(3),
132
+ };
133
+ modules.map(=> {
134
+ ...$.$toModule(),
135
+ isEntry: $.isEntry,
136
+ reasons: $.dependents.map(=> $.$toModule()),
137
+ duplicates: $.duplicates.map(=> $.$toModule()),
138
+ })
139
+ `,
140
+ }),
141
+ },
142
+ {
143
+ when: `#.id="${TABS.PACKAGES}"`,
144
+ content: [
145
+ getCopyToClipboardButton({
146
+ text: "Copy list",
147
+ className: "copy-before-ask-chatgpt",
148
+ textToCopy: `"- " + modules.filter(=> path has "node_modules").group(=> path.getModulesName()).map(=> $.key).join("\\n- ")`,
149
+ }),
150
+ {
151
+ view: "link",
152
+ className: "ask-chatgpt view-button",
153
+ text: "and Ask ChatGPT",
154
+ external: true,
155
+ data: `{
156
+ href: $.askChatGPTAboutPackages()
157
+ }`,
158
+ },
159
+ {
160
+ view: "content-filter",
161
+ //
162
+ data: `${getPackage(`modules.filter(=> path has "node_modules")`)}.sort(pkgInstances desc, size desc)`,
163
+ className: "packages-content",
164
+ name: "filterByPathStr",
165
+ content: getPackageList({
166
+ showCopiesBadge: true,
167
+ expanded: false,
168
+ limit: 200,
169
+ subLimit: 50,
170
+ data: ".[pkgName ~= #.filterByPathStr]",
171
+ itemPkgName: {
172
+ view: "link",
173
+ content: "text-match",
174
+ data: `{
175
+ href: pkgName.pageLink("package", {}),
176
+ text: pkgName,
177
+ match: #.filterByPathStr
178
+ }`,
179
+ },
180
+ }),
181
+ },
182
+ ],
183
+ },
184
+ {
185
+ when: `#.id="${TABS.DUPLICATES}"`,
186
+ content: getModulesTree({
187
+ data: `
188
+ // values
189
+ $duplicatesOnly: modules.filter(=> duplicates);
190
+ $totalSize: $duplicatesOnly.sum(=>output.sizeInBytes);
191
+ $toModule: => {
192
+ ext: $.path.getFileExtension(),
193
+ name: $.path,
194
+ size: $.output.sizeInBytes.formatBytes(),
195
+ percent: ($.output.sizeInBytes / $totalSize).percent(3),
196
+ };
197
+ // return
198
+ $duplicatesOnly.map(=> {
199
+ ...$.$toModule(),
200
+ reasons: $.dependents.map(=> $.$toModule()),
201
+ duplicates: $.duplicates.map(=> $.$toModule()),
202
+ })
203
+ `,
204
+ }),
205
+ },
206
+ ],
207
+ },
208
+ },
209
+
210
+ // END
211
+ ]);