@ecrindigital/facetpack 0.1.9 → 0.2.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/minifier.cjs CHANGED
@@ -35,6 +35,254 @@ __export(exports_minifier, {
35
35
  });
36
36
  module.exports = __toCommonJS(exports_minifier);
37
37
  var import_facetpack_native = require("@ecrindigital/facetpack-native");
38
+
39
+ // src/stats.ts
40
+ var import_fs = require("fs");
41
+ var import_os = require("os");
42
+ var import_path = require("path");
43
+ var ANSI = {
44
+ green: "\x1B[32m",
45
+ yellow: "\x1B[33m",
46
+ cyan: "\x1B[36m",
47
+ white: "\x1B[37m",
48
+ gray: "\x1B[90m",
49
+ bold: "\x1B[1m",
50
+ dim: "\x1B[2m",
51
+ reset: "\x1B[0m"
52
+ };
53
+ var STATS_DIR = import_path.join(import_os.tmpdir(), "facetpack-stats");
54
+ var STATS_FILE_PREFIX = "stats-";
55
+ var LOCK_FILE = import_path.join(STATS_DIR, ".print-lock");
56
+ var PRINT_DELAY = 1000;
57
+ function getStatsFilePath() {
58
+ const workerId = process.env.METRO_WORKER_ID || process.pid.toString();
59
+ return import_path.join(STATS_DIR, `${STATS_FILE_PREFIX}${workerId}.json`);
60
+ }
61
+ function ensureStatsDir() {
62
+ if (!import_fs.existsSync(STATS_DIR)) {
63
+ import_fs.mkdirSync(STATS_DIR, { recursive: true });
64
+ }
65
+ }
66
+ function acquirePrintLock() {
67
+ try {
68
+ ensureStatsDir();
69
+ if (import_fs.existsSync(LOCK_FILE)) {
70
+ const lockTime = parseInt(import_fs.readFileSync(LOCK_FILE, "utf-8"), 10);
71
+ if (Date.now() - lockTime < 5000) {
72
+ return false;
73
+ }
74
+ }
75
+ import_fs.writeFileSync(LOCK_FILE, Date.now().toString());
76
+ return true;
77
+ } catch {
78
+ return false;
79
+ }
80
+ }
81
+ function releasePrintLock() {
82
+ try {
83
+ if (import_fs.existsSync(LOCK_FILE)) {
84
+ import_fs.unlinkSync(LOCK_FILE);
85
+ }
86
+ } catch {}
87
+ }
88
+
89
+ class GlobalStats {
90
+ stats = this.createEmptyStats();
91
+ exitHandlerRegistered = false;
92
+ hasPrinted = false;
93
+ printTimer = null;
94
+ createEmptyStats() {
95
+ return {
96
+ transformer: { oxc: 0, babel: 0 },
97
+ resolver: { facetpack: 0, metro: 0 },
98
+ minifier: { files: 0, originalSize: 0, minifiedSize: 0 },
99
+ treeShaking: { modulesAnalyzed: 0, modulesRemoved: 0, exportsRemoved: 0 },
100
+ startTime: Date.now()
101
+ };
102
+ }
103
+ recordTransform(engine) {
104
+ this.stats.transformer[engine]++;
105
+ this.persistStats();
106
+ this.schedulePrint();
107
+ }
108
+ adjustTransformFallback() {
109
+ this.stats.transformer.oxc--;
110
+ this.stats.transformer.babel++;
111
+ this.persistStats();
112
+ }
113
+ recordResolve(engine) {
114
+ this.stats.resolver[engine]++;
115
+ }
116
+ flush() {
117
+ this.persistStats();
118
+ }
119
+ schedulePrint() {
120
+ if (this.printTimer) {
121
+ clearTimeout(this.printTimer);
122
+ }
123
+ this.printTimer = setTimeout(() => {
124
+ if (acquirePrintLock()) {
125
+ this.print();
126
+ releasePrintLock();
127
+ }
128
+ }, PRINT_DELAY);
129
+ }
130
+ recordMinify(originalSize, minifiedSize) {
131
+ this.stats.minifier.files++;
132
+ this.stats.minifier.originalSize += originalSize;
133
+ this.stats.minifier.minifiedSize += minifiedSize;
134
+ }
135
+ recordTreeShaking(analyzed, removed, exports2) {
136
+ this.stats.treeShaking.modulesAnalyzed += analyzed;
137
+ this.stats.treeShaking.modulesRemoved += removed;
138
+ this.stats.treeShaking.exportsRemoved += exports2;
139
+ }
140
+ get() {
141
+ return JSON.parse(JSON.stringify(this.stats));
142
+ }
143
+ reset() {
144
+ this.stats = this.createEmptyStats();
145
+ this.hasPrinted = false;
146
+ this.cleanupStatsFiles();
147
+ }
148
+ persistStats() {
149
+ try {
150
+ ensureStatsDir();
151
+ import_fs.writeFileSync(getStatsFilePath(), JSON.stringify(this.stats));
152
+ } catch {}
153
+ }
154
+ cleanupStatsFiles() {
155
+ try {
156
+ if (import_fs.existsSync(STATS_DIR)) {
157
+ const { readdirSync } = require("fs");
158
+ const files = readdirSync(STATS_DIR);
159
+ for (const file of files) {
160
+ if (file.startsWith(STATS_FILE_PREFIX)) {
161
+ try {
162
+ import_fs.unlinkSync(import_path.join(STATS_DIR, file));
163
+ } catch {}
164
+ }
165
+ }
166
+ }
167
+ } catch {}
168
+ }
169
+ aggregateWorkerStats() {
170
+ const aggregated = this.createEmptyStats();
171
+ aggregated.startTime = this.stats.startTime;
172
+ try {
173
+ if (import_fs.existsSync(STATS_DIR)) {
174
+ const { readdirSync } = require("fs");
175
+ const files = readdirSync(STATS_DIR);
176
+ for (const file of files) {
177
+ if (file.startsWith(STATS_FILE_PREFIX)) {
178
+ try {
179
+ const content = import_fs.readFileSync(import_path.join(STATS_DIR, file), "utf-8");
180
+ const workerStats = JSON.parse(content);
181
+ aggregated.transformer.oxc += workerStats.transformer.oxc;
182
+ aggregated.transformer.babel += workerStats.transformer.babel;
183
+ aggregated.resolver.facetpack += workerStats.resolver.facetpack;
184
+ aggregated.resolver.metro += workerStats.resolver.metro;
185
+ if (workerStats.startTime < aggregated.startTime) {
186
+ aggregated.startTime = workerStats.startTime;
187
+ }
188
+ } catch {}
189
+ }
190
+ }
191
+ }
192
+ } catch {}
193
+ aggregated.minifier = this.stats.minifier;
194
+ aggregated.treeShaking = this.stats.treeShaking;
195
+ return aggregated;
196
+ }
197
+ formatPercent(value, total) {
198
+ if (total === 0)
199
+ return "0.0";
200
+ return (value / total * 100).toFixed(1);
201
+ }
202
+ formatSize(bytes) {
203
+ if (bytes < 1024)
204
+ return `${bytes} B`;
205
+ if (bytes < 1024 * 1024)
206
+ return `${(bytes / 1024).toFixed(1)} KB`;
207
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
208
+ }
209
+ formatDuration(ms) {
210
+ if (ms < 1000)
211
+ return `${ms}ms`;
212
+ return `${(ms / 1000).toFixed(2)}s`;
213
+ }
214
+ print() {
215
+ if (!process.env.FACETPACK_DEBUG || this.hasPrinted)
216
+ return;
217
+ const aggregated = this.aggregateWorkerStats();
218
+ const { transformer, resolver, minifier, treeShaking, startTime } = aggregated;
219
+ const duration = Date.now() - startTime;
220
+ const transformTotal = transformer.oxc + transformer.babel;
221
+ const resolveTotal = resolver.facetpack + resolver.metro;
222
+ if (transformTotal === 0 && resolveTotal === 0 && minifier.files === 0)
223
+ return;
224
+ this.hasPrinted = true;
225
+ const { cyan, green, yellow, white, gray, bold, dim, reset } = ANSI;
226
+ console.log(`
227
+ `);
228
+ console.log(`${bold}${cyan}╔════════════════════════════════════════════════════════════════════╗${reset}`);
229
+ console.log(`${bold}${cyan}║${reset} ${bold}FACETPACK BUNDLE STATS${reset} ${cyan}║${reset}`);
230
+ console.log(`${bold}${cyan}╠════════════════════════════════════════════════════════════════════╣${reset}`);
231
+ if (transformTotal > 0) {
232
+ const oxcPct = this.formatPercent(transformer.oxc, transformTotal);
233
+ const babelPct = this.formatPercent(transformer.babel, transformTotal);
234
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
235
+ console.log(`${cyan}║${reset} ${bold}TRANSFORMER${reset} ${cyan}║${reset}`);
236
+ console.log(`${cyan}║${reset} ${green}●${reset} OXC (native) ${bold}${green}${transformer.oxc.toString().padStart(6)}${reset} files ${green}${oxcPct.padStart(6)}%${reset} ${cyan}║${reset}`);
237
+ console.log(`${cyan}║${reset} ${yellow}●${reset} Babel ${bold}${yellow}${transformer.babel.toString().padStart(6)}${reset} files ${yellow}${babelPct.padStart(6)}%${reset} ${cyan}║${reset}`);
238
+ console.log(`${cyan}║${reset} ${dim}${white} Total ${transformTotal.toString().padStart(6)} files${reset} ${cyan}║${reset}`);
239
+ }
240
+ if (resolveTotal > 0) {
241
+ const fpPct = this.formatPercent(resolver.facetpack, resolveTotal);
242
+ const metroPct = this.formatPercent(resolver.metro, resolveTotal);
243
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
244
+ console.log(`${cyan}║${reset} ${bold}RESOLVER${reset} ${cyan}║${reset}`);
245
+ console.log(`${cyan}║${reset} ${green}●${reset} Facetpack ${bold}${green}${resolver.facetpack.toString().padStart(6)}${reset} hits ${green}${fpPct.padStart(6)}%${reset} ${cyan}║${reset}`);
246
+ console.log(`${cyan}║${reset} ${yellow}●${reset} Metro ${bold}${yellow}${resolver.metro.toString().padStart(6)}${reset} hits ${yellow}${metroPct.padStart(6)}%${reset} ${cyan}║${reset}`);
247
+ console.log(`${cyan}║${reset} ${dim}${white} Total ${resolveTotal.toString().padStart(6)} resolutions${reset} ${cyan}║${reset}`);
248
+ }
249
+ if (minifier.files > 0) {
250
+ const savings = minifier.originalSize - minifier.minifiedSize;
251
+ const savingsPct = this.formatPercent(savings, minifier.originalSize);
252
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
253
+ console.log(`${cyan}║${reset} ${bold}MINIFIER${reset} ${cyan}║${reset}`);
254
+ console.log(`${cyan}║${reset} ${green}●${reset} Files minified ${bold}${green}${minifier.files.toString().padStart(6)}${reset} ${cyan}║${reset}`);
255
+ console.log(`${cyan}║${reset} ${gray}●${reset} Original size ${this.formatSize(minifier.originalSize).padStart(12)} ${cyan}║${reset}`);
256
+ console.log(`${cyan}║${reset} ${green}●${reset} Minified size ${this.formatSize(minifier.minifiedSize).padStart(12)} ${green}-${savingsPct}%${reset} ${cyan}║${reset}`);
257
+ }
258
+ if (treeShaking.modulesAnalyzed > 0) {
259
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
260
+ console.log(`${cyan}║${reset} ${bold}TREE SHAKING${reset} ${cyan}║${reset}`);
261
+ console.log(`${cyan}║${reset} ${gray}●${reset} Modules analyzed ${bold}${treeShaking.modulesAnalyzed.toString().padStart(5)}${reset} ${cyan}║${reset}`);
262
+ console.log(`${cyan}║${reset} ${green}●${reset} Modules removed ${bold}${green}${treeShaking.modulesRemoved.toString().padStart(5)}${reset} ${cyan}║${reset}`);
263
+ console.log(`${cyan}║${reset} ${green}●${reset} Exports removed ${bold}${green}${treeShaking.exportsRemoved.toString().padStart(5)}${reset} ${cyan}║${reset}`);
264
+ }
265
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
266
+ console.log(`${cyan}║${reset} ${dim}Duration: ${this.formatDuration(duration)}${reset} ${cyan}║${reset}`);
267
+ console.log(`${bold}${cyan}╚════════════════════════════════════════════════════════════════════╝${reset}`);
268
+ console.log(`
269
+ `);
270
+ this.cleanupStatsFiles();
271
+ }
272
+ registerExitHandler() {
273
+ if (this.exitHandlerRegistered)
274
+ return;
275
+ this.exitHandlerRegistered = true;
276
+ process.on("SIGINT", () => {
277
+ this.print();
278
+ process.exit(0);
279
+ });
280
+ process.on("beforeExit", () => this.print());
281
+ }
282
+ }
283
+ var globalStats = new GlobalStats;
284
+
285
+ // src/minifier.ts
38
286
  function minify(input) {
39
287
  const options = {
40
288
  compress: input.config.compress ?? true,
@@ -44,7 +292,10 @@ function minify(input) {
44
292
  dropDebugger: input.config.drop_debugger ?? true,
45
293
  sourcemap: input.map !== undefined
46
294
  };
295
+ const originalSize = Buffer.byteLength(input.code, "utf8");
47
296
  const result = import_facetpack_native.minifySync(input.code, input.filename, options);
297
+ const minifiedSize = Buffer.byteLength(result.code, "utf8");
298
+ globalStats.recordMinify(originalSize, minifiedSize);
48
299
  return {
49
300
  code: result.code,
50
301
  map: result.map ?? undefined
@@ -59,7 +310,10 @@ function minifyCode(code, filename, options) {
59
310
  dropDebugger: options?.drop_debugger ?? true,
60
311
  sourcemap: false
61
312
  };
313
+ const originalSize = Buffer.byteLength(code, "utf8");
62
314
  const result = import_facetpack_native.minifySync(code, filename, nativeOptions);
315
+ const minifiedSize = Buffer.byteLength(result.code, "utf8");
316
+ globalStats.recordMinify(originalSize, minifiedSize);
63
317
  return {
64
318
  code: result.code,
65
319
  map: result.map ?? undefined
@@ -1 +1 @@
1
- {"version":3,"file":"minifier.d.ts","sourceRoot":"","sources":["../src/minifier.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAgBjE;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,iBAAiB,CAgBnB;AAED,eAAe,MAAM,CAAA"}
1
+ {"version":3,"file":"minifier.d.ts","sourceRoot":"","sources":["../src/minifier.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAoBjE;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,iBAAiB,CAoBnB;AAED,eAAe,MAAM,CAAA"}
package/dist/minifier.js CHANGED
@@ -3,6 +3,263 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
3
 
4
4
  // src/minifier.ts
5
5
  import { minifySync } from "@ecrindigital/facetpack-native";
6
+
7
+ // src/stats.ts
8
+ import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync } from "fs";
9
+ import { tmpdir } from "os";
10
+ import { join } from "path";
11
+ var ANSI = {
12
+ green: "\x1B[32m",
13
+ yellow: "\x1B[33m",
14
+ cyan: "\x1B[36m",
15
+ white: "\x1B[37m",
16
+ gray: "\x1B[90m",
17
+ bold: "\x1B[1m",
18
+ dim: "\x1B[2m",
19
+ reset: "\x1B[0m"
20
+ };
21
+ var STATS_DIR = join(tmpdir(), "facetpack-stats");
22
+ var STATS_FILE_PREFIX = "stats-";
23
+ var LOCK_FILE = join(STATS_DIR, ".print-lock");
24
+ var PRINT_DELAY = 1000;
25
+ function getStatsFilePath() {
26
+ const workerId = process.env.METRO_WORKER_ID || process.pid.toString();
27
+ return join(STATS_DIR, `${STATS_FILE_PREFIX}${workerId}.json`);
28
+ }
29
+ function ensureStatsDir() {
30
+ if (!existsSync(STATS_DIR)) {
31
+ mkdirSync(STATS_DIR, { recursive: true });
32
+ }
33
+ }
34
+ function acquirePrintLock() {
35
+ try {
36
+ ensureStatsDir();
37
+ if (existsSync(LOCK_FILE)) {
38
+ const lockTime = parseInt(readFileSync(LOCK_FILE, "utf-8"), 10);
39
+ if (Date.now() - lockTime < 5000) {
40
+ return false;
41
+ }
42
+ }
43
+ writeFileSync(LOCK_FILE, Date.now().toString());
44
+ return true;
45
+ } catch {
46
+ return false;
47
+ }
48
+ }
49
+ function releasePrintLock() {
50
+ try {
51
+ if (existsSync(LOCK_FILE)) {
52
+ unlinkSync(LOCK_FILE);
53
+ }
54
+ } catch {}
55
+ }
56
+
57
+ class GlobalStats {
58
+ stats = this.createEmptyStats();
59
+ exitHandlerRegistered = false;
60
+ hasPrinted = false;
61
+ printTimer = null;
62
+ createEmptyStats() {
63
+ return {
64
+ transformer: { oxc: 0, babel: 0 },
65
+ resolver: { facetpack: 0, metro: 0 },
66
+ minifier: { files: 0, originalSize: 0, minifiedSize: 0 },
67
+ treeShaking: { modulesAnalyzed: 0, modulesRemoved: 0, exportsRemoved: 0 },
68
+ startTime: Date.now()
69
+ };
70
+ }
71
+ recordTransform(engine) {
72
+ this.stats.transformer[engine]++;
73
+ this.persistStats();
74
+ this.schedulePrint();
75
+ }
76
+ adjustTransformFallback() {
77
+ this.stats.transformer.oxc--;
78
+ this.stats.transformer.babel++;
79
+ this.persistStats();
80
+ }
81
+ recordResolve(engine) {
82
+ this.stats.resolver[engine]++;
83
+ }
84
+ flush() {
85
+ this.persistStats();
86
+ }
87
+ schedulePrint() {
88
+ if (this.printTimer) {
89
+ clearTimeout(this.printTimer);
90
+ }
91
+ this.printTimer = setTimeout(() => {
92
+ if (acquirePrintLock()) {
93
+ this.print();
94
+ releasePrintLock();
95
+ }
96
+ }, PRINT_DELAY);
97
+ }
98
+ recordMinify(originalSize, minifiedSize) {
99
+ this.stats.minifier.files++;
100
+ this.stats.minifier.originalSize += originalSize;
101
+ this.stats.minifier.minifiedSize += minifiedSize;
102
+ }
103
+ recordTreeShaking(analyzed, removed, exports) {
104
+ this.stats.treeShaking.modulesAnalyzed += analyzed;
105
+ this.stats.treeShaking.modulesRemoved += removed;
106
+ this.stats.treeShaking.exportsRemoved += exports;
107
+ }
108
+ get() {
109
+ return JSON.parse(JSON.stringify(this.stats));
110
+ }
111
+ reset() {
112
+ this.stats = this.createEmptyStats();
113
+ this.hasPrinted = false;
114
+ this.cleanupStatsFiles();
115
+ }
116
+ persistStats() {
117
+ try {
118
+ ensureStatsDir();
119
+ writeFileSync(getStatsFilePath(), JSON.stringify(this.stats));
120
+ } catch {}
121
+ }
122
+ cleanupStatsFiles() {
123
+ try {
124
+ if (existsSync(STATS_DIR)) {
125
+ const { readdirSync } = __require("fs");
126
+ const files = readdirSync(STATS_DIR);
127
+ for (const file of files) {
128
+ if (file.startsWith(STATS_FILE_PREFIX)) {
129
+ try {
130
+ unlinkSync(join(STATS_DIR, file));
131
+ } catch {}
132
+ }
133
+ }
134
+ }
135
+ } catch {}
136
+ }
137
+ aggregateWorkerStats() {
138
+ const aggregated = this.createEmptyStats();
139
+ aggregated.startTime = this.stats.startTime;
140
+ try {
141
+ if (existsSync(STATS_DIR)) {
142
+ const { readdirSync } = __require("fs");
143
+ const files = readdirSync(STATS_DIR);
144
+ for (const file of files) {
145
+ if (file.startsWith(STATS_FILE_PREFIX)) {
146
+ try {
147
+ const content = readFileSync(join(STATS_DIR, file), "utf-8");
148
+ const workerStats = JSON.parse(content);
149
+ aggregated.transformer.oxc += workerStats.transformer.oxc;
150
+ aggregated.transformer.babel += workerStats.transformer.babel;
151
+ aggregated.resolver.facetpack += workerStats.resolver.facetpack;
152
+ aggregated.resolver.metro += workerStats.resolver.metro;
153
+ if (workerStats.startTime < aggregated.startTime) {
154
+ aggregated.startTime = workerStats.startTime;
155
+ }
156
+ } catch {}
157
+ }
158
+ }
159
+ }
160
+ } catch {}
161
+ aggregated.minifier = this.stats.minifier;
162
+ aggregated.treeShaking = this.stats.treeShaking;
163
+ return aggregated;
164
+ }
165
+ formatPercent(value, total) {
166
+ if (total === 0)
167
+ return "0.0";
168
+ return (value / total * 100).toFixed(1);
169
+ }
170
+ formatSize(bytes) {
171
+ if (bytes < 1024)
172
+ return `${bytes} B`;
173
+ if (bytes < 1024 * 1024)
174
+ return `${(bytes / 1024).toFixed(1)} KB`;
175
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
176
+ }
177
+ formatDuration(ms) {
178
+ if (ms < 1000)
179
+ return `${ms}ms`;
180
+ return `${(ms / 1000).toFixed(2)}s`;
181
+ }
182
+ print() {
183
+ if (!process.env.FACETPACK_DEBUG || this.hasPrinted)
184
+ return;
185
+ const aggregated = this.aggregateWorkerStats();
186
+ const { transformer, resolver, minifier, treeShaking, startTime } = aggregated;
187
+ const duration = Date.now() - startTime;
188
+ const transformTotal = transformer.oxc + transformer.babel;
189
+ const resolveTotal = resolver.facetpack + resolver.metro;
190
+ if (transformTotal === 0 && resolveTotal === 0 && minifier.files === 0)
191
+ return;
192
+ this.hasPrinted = true;
193
+ const { cyan, green, yellow, white, gray, bold, dim, reset } = ANSI;
194
+ console.log(`
195
+ `);
196
+ console.log(`${bold}${cyan}╔════════════════════════════════════════════════════════════════════╗${reset}`);
197
+ console.log(`${bold}${cyan}║${reset} ${bold}FACETPACK BUNDLE STATS${reset} ${cyan}║${reset}`);
198
+ console.log(`${bold}${cyan}╠════════════════════════════════════════════════════════════════════╣${reset}`);
199
+ if (transformTotal > 0) {
200
+ const oxcPct = this.formatPercent(transformer.oxc, transformTotal);
201
+ const babelPct = this.formatPercent(transformer.babel, transformTotal);
202
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
203
+ console.log(`${cyan}║${reset} ${bold}TRANSFORMER${reset} ${cyan}║${reset}`);
204
+ console.log(`${cyan}║${reset} ${green}●${reset} OXC (native) ${bold}${green}${transformer.oxc.toString().padStart(6)}${reset} files ${green}${oxcPct.padStart(6)}%${reset} ${cyan}║${reset}`);
205
+ console.log(`${cyan}║${reset} ${yellow}●${reset} Babel ${bold}${yellow}${transformer.babel.toString().padStart(6)}${reset} files ${yellow}${babelPct.padStart(6)}%${reset} ${cyan}║${reset}`);
206
+ console.log(`${cyan}║${reset} ${dim}${white} Total ${transformTotal.toString().padStart(6)} files${reset} ${cyan}║${reset}`);
207
+ }
208
+ if (resolveTotal > 0) {
209
+ const fpPct = this.formatPercent(resolver.facetpack, resolveTotal);
210
+ const metroPct = this.formatPercent(resolver.metro, resolveTotal);
211
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
212
+ console.log(`${cyan}║${reset} ${bold}RESOLVER${reset} ${cyan}║${reset}`);
213
+ console.log(`${cyan}║${reset} ${green}●${reset} Facetpack ${bold}${green}${resolver.facetpack.toString().padStart(6)}${reset} hits ${green}${fpPct.padStart(6)}%${reset} ${cyan}║${reset}`);
214
+ console.log(`${cyan}║${reset} ${yellow}●${reset} Metro ${bold}${yellow}${resolver.metro.toString().padStart(6)}${reset} hits ${yellow}${metroPct.padStart(6)}%${reset} ${cyan}║${reset}`);
215
+ console.log(`${cyan}║${reset} ${dim}${white} Total ${resolveTotal.toString().padStart(6)} resolutions${reset} ${cyan}║${reset}`);
216
+ }
217
+ if (minifier.files > 0) {
218
+ const savings = minifier.originalSize - minifier.minifiedSize;
219
+ const savingsPct = this.formatPercent(savings, minifier.originalSize);
220
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
221
+ console.log(`${cyan}║${reset} ${bold}MINIFIER${reset} ${cyan}║${reset}`);
222
+ console.log(`${cyan}║${reset} ${green}●${reset} Files minified ${bold}${green}${minifier.files.toString().padStart(6)}${reset} ${cyan}║${reset}`);
223
+ console.log(`${cyan}║${reset} ${gray}●${reset} Original size ${this.formatSize(minifier.originalSize).padStart(12)} ${cyan}║${reset}`);
224
+ console.log(`${cyan}║${reset} ${green}●${reset} Minified size ${this.formatSize(minifier.minifiedSize).padStart(12)} ${green}-${savingsPct}%${reset} ${cyan}║${reset}`);
225
+ }
226
+ if (treeShaking.modulesAnalyzed > 0) {
227
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
228
+ console.log(`${cyan}║${reset} ${bold}TREE SHAKING${reset} ${cyan}║${reset}`);
229
+ console.log(`${cyan}║${reset} ${gray}●${reset} Modules analyzed ${bold}${treeShaking.modulesAnalyzed.toString().padStart(5)}${reset} ${cyan}║${reset}`);
230
+ console.log(`${cyan}║${reset} ${green}●${reset} Modules removed ${bold}${green}${treeShaking.modulesRemoved.toString().padStart(5)}${reset} ${cyan}║${reset}`);
231
+ console.log(`${cyan}║${reset} ${green}●${reset} Exports removed ${bold}${green}${treeShaking.exportsRemoved.toString().padStart(5)}${reset} ${cyan}║${reset}`);
232
+ }
233
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
234
+ console.log(`${cyan}║${reset} ${dim}Duration: ${this.formatDuration(duration)}${reset} ${cyan}║${reset}`);
235
+ console.log(`${bold}${cyan}╚════════════════════════════════════════════════════════════════════╝${reset}`);
236
+ console.log(`
237
+ `);
238
+ this.cleanupStatsFiles();
239
+ }
240
+ registerExitHandler() {
241
+ if (this.exitHandlerRegistered)
242
+ return;
243
+ this.exitHandlerRegistered = true;
244
+ process.on("SIGINT", () => {
245
+ this.print();
246
+ process.exit(0);
247
+ });
248
+ process.on("beforeExit", () => this.print());
249
+ }
250
+ }
251
+ var globalStats = new GlobalStats;
252
+ function printStats() {
253
+ globalStats.print();
254
+ }
255
+ function resetStats() {
256
+ globalStats.reset();
257
+ }
258
+ function getStats() {
259
+ return globalStats.get();
260
+ }
261
+
262
+ // src/minifier.ts
6
263
  function minify(input) {
7
264
  const options = {
8
265
  compress: input.config.compress ?? true,
@@ -12,7 +269,10 @@ function minify(input) {
12
269
  dropDebugger: input.config.drop_debugger ?? true,
13
270
  sourcemap: input.map !== undefined
14
271
  };
272
+ const originalSize = Buffer.byteLength(input.code, "utf8");
15
273
  const result = minifySync(input.code, input.filename, options);
274
+ const minifiedSize = Buffer.byteLength(result.code, "utf8");
275
+ globalStats.recordMinify(originalSize, minifiedSize);
16
276
  return {
17
277
  code: result.code,
18
278
  map: result.map ?? undefined
@@ -27,7 +287,10 @@ function minifyCode(code, filename, options) {
27
287
  dropDebugger: options?.drop_debugger ?? true,
28
288
  sourcemap: false
29
289
  };
290
+ const originalSize = Buffer.byteLength(code, "utf8");
30
291
  const result = minifySync(code, filename, nativeOptions);
292
+ const minifiedSize = Buffer.byteLength(result.code, "utf8");
293
+ globalStats.recordMinify(originalSize, minifiedSize);
31
294
  return {
32
295
  code: result.code,
33
296
  map: result.map ?? undefined
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAElF,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,CAAA;AAE5C,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe;8BAE1B,MAAM,cAAc,MAAM,GAAG,MAAM,GAAG,IAAI;EAMvE"}
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAGlF,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,CAAA;AAE5C,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe;8BAE1B,MAAM,cAAc,MAAM,GAAG,MAAM,GAAG,IAAI;EAavE"}