@ecrindigital/facetpack 0.1.10 → 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.
@@ -48,9 +48,359 @@ function setCachedResolutions(originModulePath, resolutions) {
48
48
  resolutionCache.set(originModulePath, cached);
49
49
  }
50
50
 
51
+ // src/stats.ts
52
+ var import_fs = require("fs");
53
+ var import_os = require("os");
54
+ var import_path = require("path");
55
+ var ANSI = {
56
+ green: "\x1B[32m",
57
+ yellow: "\x1B[33m",
58
+ cyan: "\x1B[36m",
59
+ white: "\x1B[37m",
60
+ gray: "\x1B[90m",
61
+ bold: "\x1B[1m",
62
+ dim: "\x1B[2m",
63
+ reset: "\x1B[0m"
64
+ };
65
+ var STATS_DIR = import_path.join(import_os.tmpdir(), "facetpack-stats");
66
+ var STATS_FILE_PREFIX = "stats-";
67
+ var LOCK_FILE = import_path.join(STATS_DIR, ".print-lock");
68
+ var PRINT_DELAY = 1000;
69
+ function getStatsFilePath() {
70
+ const workerId = process.env.METRO_WORKER_ID || process.pid.toString();
71
+ return import_path.join(STATS_DIR, `${STATS_FILE_PREFIX}${workerId}.json`);
72
+ }
73
+ function ensureStatsDir() {
74
+ if (!import_fs.existsSync(STATS_DIR)) {
75
+ import_fs.mkdirSync(STATS_DIR, { recursive: true });
76
+ }
77
+ }
78
+ function acquirePrintLock() {
79
+ try {
80
+ ensureStatsDir();
81
+ if (import_fs.existsSync(LOCK_FILE)) {
82
+ const lockTime = parseInt(import_fs.readFileSync(LOCK_FILE, "utf-8"), 10);
83
+ if (Date.now() - lockTime < 5000) {
84
+ return false;
85
+ }
86
+ }
87
+ import_fs.writeFileSync(LOCK_FILE, Date.now().toString());
88
+ return true;
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+ function releasePrintLock() {
94
+ try {
95
+ if (import_fs.existsSync(LOCK_FILE)) {
96
+ import_fs.unlinkSync(LOCK_FILE);
97
+ }
98
+ } catch {}
99
+ }
100
+
101
+ class GlobalStats {
102
+ stats = this.createEmptyStats();
103
+ exitHandlerRegistered = false;
104
+ hasPrinted = false;
105
+ printTimer = null;
106
+ createEmptyStats() {
107
+ return {
108
+ transformer: { oxc: 0, babel: 0 },
109
+ resolver: { facetpack: 0, metro: 0 },
110
+ minifier: { files: 0, originalSize: 0, minifiedSize: 0 },
111
+ treeShaking: { modulesAnalyzed: 0, modulesRemoved: 0, exportsRemoved: 0 },
112
+ startTime: Date.now()
113
+ };
114
+ }
115
+ recordTransform(engine) {
116
+ this.stats.transformer[engine]++;
117
+ this.persistStats();
118
+ this.schedulePrint();
119
+ }
120
+ adjustTransformFallback() {
121
+ this.stats.transformer.oxc--;
122
+ this.stats.transformer.babel++;
123
+ this.persistStats();
124
+ }
125
+ recordResolve(engine) {
126
+ this.stats.resolver[engine]++;
127
+ }
128
+ flush() {
129
+ this.persistStats();
130
+ }
131
+ schedulePrint() {
132
+ if (this.printTimer) {
133
+ clearTimeout(this.printTimer);
134
+ }
135
+ this.printTimer = setTimeout(() => {
136
+ if (acquirePrintLock()) {
137
+ this.print();
138
+ releasePrintLock();
139
+ }
140
+ }, PRINT_DELAY);
141
+ }
142
+ recordMinify(originalSize, minifiedSize) {
143
+ this.stats.minifier.files++;
144
+ this.stats.minifier.originalSize += originalSize;
145
+ this.stats.minifier.minifiedSize += minifiedSize;
146
+ }
147
+ recordTreeShaking(analyzed, removed, exports2) {
148
+ this.stats.treeShaking.modulesAnalyzed += analyzed;
149
+ this.stats.treeShaking.modulesRemoved += removed;
150
+ this.stats.treeShaking.exportsRemoved += exports2;
151
+ }
152
+ get() {
153
+ return JSON.parse(JSON.stringify(this.stats));
154
+ }
155
+ reset() {
156
+ this.stats = this.createEmptyStats();
157
+ this.hasPrinted = false;
158
+ this.cleanupStatsFiles();
159
+ }
160
+ persistStats() {
161
+ try {
162
+ ensureStatsDir();
163
+ import_fs.writeFileSync(getStatsFilePath(), JSON.stringify(this.stats));
164
+ } catch {}
165
+ }
166
+ cleanupStatsFiles() {
167
+ try {
168
+ if (import_fs.existsSync(STATS_DIR)) {
169
+ const { readdirSync } = require("fs");
170
+ const files = readdirSync(STATS_DIR);
171
+ for (const file of files) {
172
+ if (file.startsWith(STATS_FILE_PREFIX)) {
173
+ try {
174
+ import_fs.unlinkSync(import_path.join(STATS_DIR, file));
175
+ } catch {}
176
+ }
177
+ }
178
+ }
179
+ } catch {}
180
+ }
181
+ aggregateWorkerStats() {
182
+ const aggregated = this.createEmptyStats();
183
+ aggregated.startTime = this.stats.startTime;
184
+ try {
185
+ if (import_fs.existsSync(STATS_DIR)) {
186
+ const { readdirSync } = require("fs");
187
+ const files = readdirSync(STATS_DIR);
188
+ for (const file of files) {
189
+ if (file.startsWith(STATS_FILE_PREFIX)) {
190
+ try {
191
+ const content = import_fs.readFileSync(import_path.join(STATS_DIR, file), "utf-8");
192
+ const workerStats = JSON.parse(content);
193
+ aggregated.transformer.oxc += workerStats.transformer.oxc;
194
+ aggregated.transformer.babel += workerStats.transformer.babel;
195
+ aggregated.resolver.facetpack += workerStats.resolver.facetpack;
196
+ aggregated.resolver.metro += workerStats.resolver.metro;
197
+ if (workerStats.startTime < aggregated.startTime) {
198
+ aggregated.startTime = workerStats.startTime;
199
+ }
200
+ } catch {}
201
+ }
202
+ }
203
+ }
204
+ } catch {}
205
+ aggregated.minifier = this.stats.minifier;
206
+ aggregated.treeShaking = this.stats.treeShaking;
207
+ return aggregated;
208
+ }
209
+ formatPercent(value, total) {
210
+ if (total === 0)
211
+ return "0.0";
212
+ return (value / total * 100).toFixed(1);
213
+ }
214
+ formatSize(bytes) {
215
+ if (bytes < 1024)
216
+ return `${bytes} B`;
217
+ if (bytes < 1024 * 1024)
218
+ return `${(bytes / 1024).toFixed(1)} KB`;
219
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
220
+ }
221
+ formatDuration(ms) {
222
+ if (ms < 1000)
223
+ return `${ms}ms`;
224
+ return `${(ms / 1000).toFixed(2)}s`;
225
+ }
226
+ print() {
227
+ if (!process.env.FACETPACK_DEBUG || this.hasPrinted)
228
+ return;
229
+ const aggregated = this.aggregateWorkerStats();
230
+ const { transformer, resolver, minifier, treeShaking, startTime } = aggregated;
231
+ const duration = Date.now() - startTime;
232
+ const transformTotal = transformer.oxc + transformer.babel;
233
+ const resolveTotal = resolver.facetpack + resolver.metro;
234
+ if (transformTotal === 0 && resolveTotal === 0 && minifier.files === 0)
235
+ return;
236
+ this.hasPrinted = true;
237
+ const { cyan, green, yellow, white, gray, bold, dim, reset } = ANSI;
238
+ console.log(`
239
+ `);
240
+ console.log(`${bold}${cyan}╔════════════════════════════════════════════════════════════════════╗${reset}`);
241
+ console.log(`${bold}${cyan}║${reset} ${bold}FACETPACK BUNDLE STATS${reset} ${cyan}║${reset}`);
242
+ console.log(`${bold}${cyan}╠════════════════════════════════════════════════════════════════════╣${reset}`);
243
+ if (transformTotal > 0) {
244
+ const oxcPct = this.formatPercent(transformer.oxc, transformTotal);
245
+ const babelPct = this.formatPercent(transformer.babel, transformTotal);
246
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
247
+ console.log(`${cyan}║${reset} ${bold}TRANSFORMER${reset} ${cyan}║${reset}`);
248
+ console.log(`${cyan}║${reset} ${green}●${reset} OXC (native) ${bold}${green}${transformer.oxc.toString().padStart(6)}${reset} files ${green}${oxcPct.padStart(6)}%${reset} ${cyan}║${reset}`);
249
+ console.log(`${cyan}║${reset} ${yellow}●${reset} Babel ${bold}${yellow}${transformer.babel.toString().padStart(6)}${reset} files ${yellow}${babelPct.padStart(6)}%${reset} ${cyan}║${reset}`);
250
+ console.log(`${cyan}║${reset} ${dim}${white} Total ${transformTotal.toString().padStart(6)} files${reset} ${cyan}║${reset}`);
251
+ }
252
+ if (resolveTotal > 0) {
253
+ const fpPct = this.formatPercent(resolver.facetpack, resolveTotal);
254
+ const metroPct = this.formatPercent(resolver.metro, resolveTotal);
255
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
256
+ console.log(`${cyan}║${reset} ${bold}RESOLVER${reset} ${cyan}║${reset}`);
257
+ console.log(`${cyan}║${reset} ${green}●${reset} Facetpack ${bold}${green}${resolver.facetpack.toString().padStart(6)}${reset} hits ${green}${fpPct.padStart(6)}%${reset} ${cyan}║${reset}`);
258
+ console.log(`${cyan}║${reset} ${yellow}●${reset} Metro ${bold}${yellow}${resolver.metro.toString().padStart(6)}${reset} hits ${yellow}${metroPct.padStart(6)}%${reset} ${cyan}║${reset}`);
259
+ console.log(`${cyan}║${reset} ${dim}${white} Total ${resolveTotal.toString().padStart(6)} resolutions${reset} ${cyan}║${reset}`);
260
+ }
261
+ if (minifier.files > 0) {
262
+ const savings = minifier.originalSize - minifier.minifiedSize;
263
+ const savingsPct = this.formatPercent(savings, minifier.originalSize);
264
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
265
+ console.log(`${cyan}║${reset} ${bold}MINIFIER${reset} ${cyan}║${reset}`);
266
+ console.log(`${cyan}║${reset} ${green}●${reset} Files minified ${bold}${green}${minifier.files.toString().padStart(6)}${reset} ${cyan}║${reset}`);
267
+ console.log(`${cyan}║${reset} ${gray}●${reset} Original size ${this.formatSize(minifier.originalSize).padStart(12)} ${cyan}║${reset}`);
268
+ console.log(`${cyan}║${reset} ${green}●${reset} Minified size ${this.formatSize(minifier.minifiedSize).padStart(12)} ${green}-${savingsPct}%${reset} ${cyan}║${reset}`);
269
+ }
270
+ if (treeShaking.modulesAnalyzed > 0) {
271
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
272
+ console.log(`${cyan}║${reset} ${bold}TREE SHAKING${reset} ${cyan}║${reset}`);
273
+ console.log(`${cyan}║${reset} ${gray}●${reset} Modules analyzed ${bold}${treeShaking.modulesAnalyzed.toString().padStart(5)}${reset} ${cyan}║${reset}`);
274
+ console.log(`${cyan}║${reset} ${green}●${reset} Modules removed ${bold}${green}${treeShaking.modulesRemoved.toString().padStart(5)}${reset} ${cyan}║${reset}`);
275
+ console.log(`${cyan}║${reset} ${green}●${reset} Exports removed ${bold}${green}${treeShaking.exportsRemoved.toString().padStart(5)}${reset} ${cyan}║${reset}`);
276
+ }
277
+ console.log(`${cyan}║${reset} ${cyan}║${reset}`);
278
+ console.log(`${cyan}║${reset} ${dim}Duration: ${this.formatDuration(duration)}${reset} ${cyan}║${reset}`);
279
+ console.log(`${bold}${cyan}╚════════════════════════════════════════════════════════════════════╝${reset}`);
280
+ console.log(`
281
+ `);
282
+ this.cleanupStatsFiles();
283
+ }
284
+ registerExitHandler() {
285
+ if (this.exitHandlerRegistered)
286
+ return;
287
+ this.exitHandlerRegistered = true;
288
+ process.on("SIGINT", () => {
289
+ this.print();
290
+ process.exit(0);
291
+ });
292
+ process.on("beforeExit", () => this.print());
293
+ }
294
+ }
295
+ var globalStats = new GlobalStats;
296
+
51
297
  // src/transformer.ts
298
+ var ANSI2 = {
299
+ green: "\x1B[32m",
300
+ yellow: "\x1B[33m",
301
+ cyan: "\x1B[36m",
302
+ bold: "\x1B[1m",
303
+ reset: "\x1B[0m"
304
+ };
52
305
  var IMPORT_REGEX = /(?:import|export)\s+(?:[\s\S]*?\s+from\s+)?['"]([^'"]+)['"]/g;
53
306
  var REQUIRE_REGEX = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
307
+ var BABEL_REQUIRED_PATTERNS = [
308
+ /'worklet'/,
309
+ /"worklet"/,
310
+ /require\.context\s*\(/,
311
+ /useAnimatedStyle/,
312
+ /useAnimatedProps/,
313
+ /useAnimatedScrollHandler/,
314
+ /useAnimatedGestureHandler/,
315
+ /useAnimatedReaction/,
316
+ /useDerivedValue/,
317
+ /useAnimatedSensor/,
318
+ /useFrameCallback/,
319
+ /useScrollViewOffset/,
320
+ /runOnUI/,
321
+ /runOnJS/
322
+ ];
323
+ var DEFAULT_OPTIONS = {
324
+ jsx: true,
325
+ jsxRuntime: "automatic",
326
+ jsxImportSource: "react",
327
+ jsxPragma: "React.createElement",
328
+ jsxPragmaFrag: "React.Fragment",
329
+ typescript: true,
330
+ sourceExts: ["ts", "tsx", "js", "jsx", "mjs", "cjs"],
331
+ minifier: true,
332
+ treeShake: true,
333
+ noAst: false
334
+ };
335
+
336
+ class Logger {
337
+ startupLogged = false;
338
+ logStartup() {
339
+ if (this.startupLogged || !process.env.FACETPACK_DEBUG)
340
+ return;
341
+ this.startupLogged = true;
342
+ console.log(`${ANSI2.cyan}${ANSI2.bold}[Facetpack]${ANSI2.reset} Transformer loaded`);
343
+ }
344
+ logTransform(decision, filename) {
345
+ if (!process.env.FACETPACK_DEBUG)
346
+ return;
347
+ const color = decision === "oxc" ? ANSI2.green : ANSI2.yellow;
348
+ console.log(`${color}[Facetpack]${ANSI2.reset} ${decision.toUpperCase()}: ${filename}`);
349
+ }
350
+ logFallback(filename, error) {
351
+ if (!process.env.FACETPACK_DEBUG)
352
+ return;
353
+ const message = error instanceof Error ? error.message : String(error);
354
+ console.log(`${ANSI2.yellow}[Facetpack]${ANSI2.reset} OXC failed, falling back to Babel: ${filename}`);
355
+ console.log(`${ANSI2.yellow}[Facetpack]${ANSI2.reset} Error: ${message}`);
356
+ }
357
+ }
358
+
359
+ class OptionsManager {
360
+ globalOptions = {};
361
+ setGlobal(options) {
362
+ this.globalOptions = options;
363
+ }
364
+ get() {
365
+ return { ...DEFAULT_OPTIONS, ...this.globalOptions, ...this.getFromEnv() };
366
+ }
367
+ merge(options) {
368
+ return { ...DEFAULT_OPTIONS, ...options };
369
+ }
370
+ getFromEnv() {
371
+ try {
372
+ const json = process.env.FACETPACK_OPTIONS;
373
+ return json ? JSON.parse(json) : {};
374
+ } catch {
375
+ return {};
376
+ }
377
+ }
378
+ }
379
+
380
+ class FallbackTransformerManager {
381
+ instance = null;
382
+ get() {
383
+ if (this.instance)
384
+ return this.instance;
385
+ const envPath = process.env.FACETPACK_FALLBACK_TRANSFORMER;
386
+ if (envPath) {
387
+ try {
388
+ this.instance = require(envPath);
389
+ return this.instance;
390
+ } catch (e) {
391
+ console.warn(`[Facetpack] Failed to load fallback transformer from ${envPath}:`, e);
392
+ }
393
+ }
394
+ this.instance = {
395
+ transform: ({ src }) => ({ code: src, map: null })
396
+ };
397
+ return this.instance;
398
+ }
399
+ }
400
+ var logger = new Logger;
401
+ var options = new OptionsManager;
402
+ var fallback = new FallbackTransformerManager;
403
+ logger.logStartup();
54
404
  function extractSpecifiers(code) {
55
405
  const specifiers = new Set;
56
406
  let match;
@@ -79,211 +429,126 @@ function preResolveImports(filename, code, sourceExts) {
79
429
  const specifier = specifiers[i];
80
430
  if (specifier) {
81
431
  resolutions.set(specifier, results[i]?.path ?? null);
432
+ if (results[i]?.path) {
433
+ globalStats.recordResolve("facetpack");
434
+ }
82
435
  }
83
436
  }
84
437
  setCachedResolutions(filename, resolutions);
85
438
  }
86
- var defaultOptions = {
87
- jsx: true,
88
- jsxRuntime: "automatic",
89
- jsxImportSource: "react",
90
- jsxPragma: "React.createElement",
91
- jsxPragmaFrag: "React.Fragment",
92
- typescript: true,
93
- sourceExts: ["ts", "tsx", "js", "jsx", "mjs", "cjs"],
94
- minifier: true,
95
- treeShake: true,
96
- noAst: false
97
- };
98
- var globalOptions = {};
99
- var fallbackTransformer = null;
100
- function getFallbackTransformer() {
101
- if (fallbackTransformer) {
102
- return fallbackTransformer;
103
- }
104
- const fallbackPath = process.env.FACETPACK_FALLBACK_TRANSFORMER;
105
- if (fallbackPath) {
106
- try {
107
- fallbackTransformer = require(fallbackPath);
108
- return fallbackTransformer;
109
- } catch (e) {
110
- console.warn(`[Facetpack] Failed to load fallback transformer from ${fallbackPath}:`, e);
111
- }
112
- }
113
- fallbackTransformer = {
114
- transform: ({ src }) => ({ code: src, map: null })
115
- };
116
- return fallbackTransformer;
117
- }
118
- function setTransformerOptions(options) {
119
- globalOptions = options;
120
- }
121
- function getStoredOptions() {
122
- try {
123
- const optionsJson = process.env.FACETPACK_OPTIONS;
124
- if (optionsJson) {
125
- return JSON.parse(optionsJson);
126
- }
127
- } catch {}
128
- return {};
129
- }
130
- function getOptions() {
131
- const storedOptions = getStoredOptions();
132
- return { ...defaultOptions, ...globalOptions, ...storedOptions };
439
+ function requiresBabelTransform(src) {
440
+ return BABEL_REQUIRED_PATTERNS.some((pattern) => pattern.test(src));
133
441
  }
134
442
  function isNodeModules(filename) {
135
443
  return filename.includes("node_modules");
136
444
  }
137
- var BABEL_REQUIRED_PATTERNS = [
138
- /'worklet'/,
139
- /"worklet"/,
140
- /useAnimatedStyle/,
141
- /useAnimatedProps/,
142
- /useDerivedValue/,
143
- /useAnimatedReaction/,
144
- /useAnimatedScrollHandler/,
145
- /useAnimatedGestureHandler/,
146
- /runOnUI/,
147
- /runOnJS/
148
- ];
149
- var HERMES_COMPAT_PATTERNS = [
150
- /\basync\s+function\b/,
151
- /\basync\s*\(/,
152
- /\basync\s+\w+\s*\(/,
153
- /=\s*async\s*\(/,
154
- /=\s*async\s+function\b/
155
- ];
156
- function requiresBabelTransform(src) {
157
- return BABEL_REQUIRED_PATTERNS.some((pattern) => pattern.test(src));
445
+ function getFileExtension(filename) {
446
+ return filename.split(".").pop()?.toLowerCase();
158
447
  }
159
- function requiresHermesCompat(src) {
160
- return HERMES_COMPAT_PATTERNS.some((pattern) => pattern.test(src));
448
+ function getTransformDecision(filename, src, opts) {
449
+ if (requiresBabelTransform(src))
450
+ return "babel";
451
+ if (isNodeModules(filename))
452
+ return "babel";
453
+ const ext = getFileExtension(filename);
454
+ if (!ext || !opts.sourceExts.includes(ext))
455
+ return "babel";
456
+ return "oxc";
161
457
  }
162
- function shouldTransform(filename, src, options) {
163
- if (isNodeModules(filename)) {
164
- return false;
165
- }
166
- if (requiresBabelTransform(src)) {
167
- if (process.env.FACETPACK_DEBUG) {
168
- console.log(`[Facetpack] Babel required for worklets: ${filename}`);
458
+ function formatDiagnostics(diagnostics) {
459
+ return diagnostics.map((d) => {
460
+ if (d.formatted)
461
+ return d.formatted;
462
+ if (!d.message)
463
+ return "";
464
+ let output = `
465
+ × ${d.message}
466
+ `;
467
+ if (d.snippet) {
468
+ output += ` ╭─[${d.filename}:${d.line}:${d.column}]
469
+ `;
470
+ output += ` ${d.line} │ ${d.snippet}
471
+ `;
472
+ output += ` ╰────
473
+ `;
169
474
  }
170
- return false;
475
+ if (d.help)
476
+ output += ` help: ${d.help}
477
+ `;
478
+ return output;
479
+ }).join(`
480
+ `);
481
+ }
482
+ function transformWithOxc(filename, src, opts, isDev) {
483
+ const parseResult = import_facetpack_native.parseSync(filename, src);
484
+ if (parseResult.errors.length > 0) {
485
+ const error = parseResult.diagnostics.length > 0 ? new Error(`
486
+ ${formatDiagnostics(parseResult.diagnostics)}`) : new Error(`Parse error in ${filename}:
487
+ ${parseResult.errors.join(`
488
+ `)}`);
489
+ error.isParseError = true;
490
+ throw error;
171
491
  }
172
- if (requiresHermesCompat(src)) {
173
- if (process.env.FACETPACK_DEBUG) {
174
- console.log(`[Facetpack] Babel required for async/await (Hermes compat): ${filename}`);
175
- }
176
- return false;
492
+ const isClassic = opts.jsxRuntime === "classic";
493
+ const result = import_facetpack_native.transformSync(filename, src, {
494
+ jsx: opts.jsx,
495
+ jsxRuntime: isClassic ? import_facetpack_native.JsxRuntime.Classic : import_facetpack_native.JsxRuntime.Automatic,
496
+ ...isClassic ? { jsxPragma: opts.jsxPragma, jsxPragmaFrag: opts.jsxPragmaFrag } : { jsxImportSource: opts.jsxImportSource },
497
+ typescript: opts.typescript,
498
+ sourcemap: isDev
499
+ });
500
+ if (result.errors.length > 0) {
501
+ throw new Error(`Facetpack transform error in ${filename}:
502
+ ${result.errors.join(`
503
+ `)}`);
177
504
  }
178
- const ext = filename.split(".").pop()?.toLowerCase();
179
- if (!ext)
180
- return false;
181
- return options.sourceExts.includes(ext);
505
+ preResolveImports(filename, result.code, opts.sourceExts);
506
+ globalStats.flush();
507
+ const ast = import_parser.parse(result.code, {
508
+ sourceType: "unambiguous",
509
+ plugins: ["jsx"]
510
+ });
511
+ return {
512
+ ast,
513
+ code: result.code,
514
+ map: result.map ? JSON.parse(result.map) : null
515
+ };
516
+ }
517
+ function setTransformerOptions(opts) {
518
+ options.setGlobal(opts);
182
519
  }
183
520
  function transform(params) {
184
521
  const { filename, src, options: metroOptions } = params;
185
- const opts = getOptions();
186
- if (process.env.FACETPACK_DEBUG) {
187
- console.log(`[Facetpack] Processing: ${filename}`);
188
- }
189
- if (!shouldTransform(filename, src, opts)) {
190
- if (process.env.FACETPACK_DEBUG) {
191
- console.log(`[Facetpack] Fallback: ${filename}`);
192
- }
193
- return getFallbackTransformer().transform(params);
194
- }
195
- if (process.env.FACETPACK_DEBUG) {
196
- console.log(`[Facetpack] OXC Transform: ${filename}`);
522
+ const opts = options.get();
523
+ globalStats.registerExitHandler();
524
+ const decision = getTransformDecision(filename, src, opts);
525
+ globalStats.recordTransform(decision);
526
+ logger.logTransform(decision, filename);
527
+ if (decision === "babel") {
528
+ return fallback.get().transform(params);
197
529
  }
198
530
  try {
199
- const parseResult = import_facetpack_native.parseSync(filename, src);
200
- if (parseResult.errors.length > 0 && parseResult.diagnostics.length > 0) {
201
- const formattedErrors = parseResult.diagnostics.map((d) => {
202
- let output2 = d.formatted || "";
203
- if (!output2 && d.message) {
204
- output2 = `
205
- × ${d.message}
206
- `;
207
- if (d.snippet) {
208
- output2 += ` ╭─[${d.filename}:${d.line}:${d.column}]
209
- `;
210
- output2 += ` ${d.line} │ ${d.snippet}
211
- `;
212
- output2 += ` ╰────
213
- `;
214
- }
215
- if (d.help) {
216
- output2 += ` help: ${d.help}
217
- `;
218
- }
219
- }
220
- return output2;
221
- }).join(`
222
- `);
223
- throw new Error(`
224
- ${formattedErrors}`);
225
- }
226
- const isClassic = opts.jsxRuntime === "classic";
227
- const result = import_facetpack_native.transformSync(filename, src, {
228
- jsx: opts.jsx,
229
- jsxRuntime: isClassic ? import_facetpack_native.JsxRuntime.Classic : import_facetpack_native.JsxRuntime.Automatic,
230
- ...isClassic ? { jsxPragma: opts.jsxPragma, jsxPragmaFrag: opts.jsxPragmaFrag } : { jsxImportSource: opts.jsxImportSource },
231
- typescript: opts.typescript,
232
- sourcemap: metroOptions.dev
233
- });
234
- if (result.errors.length > 0) {
235
- const errorMessage = result.errors.join(`
236
- `);
237
- throw new Error(`Facetpack transform error in ${filename}:
238
- ${errorMessage}`);
239
- }
240
- preResolveImports(filename, result.code, opts.sourceExts);
241
- const ast = opts.noAst ? undefined : import_parser.parse(result.code, {
242
- sourceType: "unambiguous",
243
- plugins: ["jsx"]
244
- });
245
- const output = {
246
- ast,
247
- code: result.code,
248
- map: result.map ? JSON.parse(result.map) : null
249
- };
250
- if (process.env.FACETPACK_DEBUG) {
251
- console.log(`[Facetpack] Output for ${filename}:`);
252
- console.log(result.code.slice(0, 500));
253
- }
254
- return output;
531
+ return transformWithOxc(filename, src, opts, metroOptions.dev);
255
532
  } catch (error) {
256
- if (error instanceof Error) {
257
- error.message = `[Facetpack] ${error.message}`;
533
+ if (error.isParseError) {
534
+ throw error;
258
535
  }
259
- throw error;
536
+ logger.logFallback(filename, error);
537
+ globalStats.adjustTransformFallback();
538
+ return fallback.get().transform(params);
260
539
  }
261
540
  }
262
- function createTransformer(options = {}) {
263
- const opts = { ...defaultOptions, ...options };
541
+ function createTransformer(customOptions = {}) {
542
+ const opts = options.merge(customOptions);
264
543
  return {
265
544
  transform(params) {
266
545
  const { filename, src, options: metroOptions } = params;
267
- if (!shouldTransform(filename, src, opts)) {
268
- return getFallbackTransformer().transform(params);
269
- }
270
- const isClassic = opts.jsxRuntime === "classic";
271
- const result = import_facetpack_native.transformSync(filename, src, {
272
- jsx: opts.jsx,
273
- jsxRuntime: isClassic ? import_facetpack_native.JsxRuntime.Classic : import_facetpack_native.JsxRuntime.Automatic,
274
- ...isClassic ? { jsxPragma: opts.jsxPragma, jsxPragmaFrag: opts.jsxPragmaFrag } : { jsxImportSource: opts.jsxImportSource },
275
- typescript: opts.typescript,
276
- sourcemap: metroOptions.dev
277
- });
278
- if (result.errors.length > 0) {
279
- throw new Error(`Facetpack transform error in ${filename}:
280
- ${result.errors.join(`
281
- `)}`);
546
+ const decision = getTransformDecision(filename, src, opts);
547
+ globalStats.recordTransform(decision);
548
+ if (decision === "babel") {
549
+ return fallback.get().transform(params);
282
550
  }
283
- return {
284
- code: result.code,
285
- map: result.map ? JSON.parse(result.map) : null
286
- };
551
+ return transformWithOxc(filename, src, opts, metroOptions.dev);
287
552
  }
288
553
  };
289
554
  }
@@ -1,7 +1,9 @@
1
1
  import type { TransformParams, TransformResult, FacetpackOptions } from './types';
2
- export declare function setTransformerOptions(options: FacetpackOptions): void;
2
+ interface Transformer {
3
+ transform: (params: TransformParams) => TransformResult;
4
+ }
5
+ export declare function setTransformerOptions(opts: FacetpackOptions): void;
3
6
  export declare function transform(params: TransformParams): TransformResult;
4
- export declare function createTransformer(options?: FacetpackOptions): {
5
- transform(params: TransformParams): TransformResult;
6
- };
7
+ export declare function createTransformer(customOptions?: FacetpackOptions): Transformer;
8
+ export {};
7
9
  //# sourceMappingURL=transformer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../src/transformer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAuFjF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAErE;AA2ED,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CAuFlE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,gBAAqB;sBAI1C,eAAe,GAAG,eAAe;EA4BtD"}
1
+ {"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../src/transformer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAMjF,UAAU,WAAW;IACnB,SAAS,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,eAAe,CAAA;CACxD;AAiQD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAElE;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CAwBlE;AAED,wBAAgB,iBAAiB,CAAC,aAAa,GAAE,gBAAqB,GAAG,WAAW,CAiBnF"}