@vxrn/vite-plugin-metro 1.26.0 → 2.0.0-beta.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/cjs/babel-plugins/import-meta-env-plugin.cjs +14 -25
  2. package/dist/cjs/babel-plugins/import-meta-env-plugin.native.js +14 -25
  3. package/dist/cjs/babel-plugins/import-meta-env-plugin.native.js.map +1 -1
  4. package/dist/cjs/metro-config/getMetroConfigFromViteConfig.cjs +3 -4
  5. package/dist/cjs/metro-config/getMetroConfigFromViteConfig.native.js +3 -4
  6. package/dist/cjs/metro-config/getMetroConfigFromViteConfig.native.js.map +1 -1
  7. package/dist/cjs/transformer/metroNativeWorker.native.js.map +1 -1
  8. package/dist/cjs/transformer/metroNativeWorker.test.cjs +11 -0
  9. package/dist/cjs/transformer/metroNativeWorker.test.native.js +15 -0
  10. package/dist/cjs/transformer/metroNativeWorker.test.native.js.map +1 -1
  11. package/dist/esm/babel-plugins/import-meta-env-plugin.mjs +1 -1
  12. package/dist/esm/babel-plugins/import-meta-env-plugin.mjs.map +1 -1
  13. package/dist/esm/babel-plugins/import-meta-env-plugin.native.js +1 -1
  14. package/dist/esm/babel-plugins/import-meta-env-plugin.native.js.map +1 -1
  15. package/dist/esm/metro-config/getMetroConfigFromViteConfig.mjs +3 -4
  16. package/dist/esm/metro-config/getMetroConfigFromViteConfig.mjs.map +1 -1
  17. package/dist/esm/metro-config/getMetroConfigFromViteConfig.native.js +3 -4
  18. package/dist/esm/metro-config/getMetroConfigFromViteConfig.native.js.map +1 -1
  19. package/dist/esm/transformer/metroNativeWorker.mjs.map +1 -1
  20. package/dist/esm/transformer/metroNativeWorker.native.js.map +1 -1
  21. package/dist/esm/transformer/metroNativeWorker.test.mjs +11 -0
  22. package/dist/esm/transformer/metroNativeWorker.test.mjs.map +1 -1
  23. package/dist/esm/transformer/metroNativeWorker.test.native.js +15 -0
  24. package/dist/esm/transformer/metroNativeWorker.test.native.js.map +1 -1
  25. package/package.json +4 -5
  26. package/src/babel-plugins/import-meta-env-plugin.ts +1 -2
  27. package/src/metro-config/getMetroConfigFromViteConfig.ts +11 -18
  28. package/src/transformer/metroNativeWorker.test.ts +173 -87
  29. package/src/transformer/metroNativeWorker.ts +241 -62
  30. package/types/babel-plugins/import-meta-env-plugin.d.ts +1 -1
  31. package/types/babel-plugins/import-meta-env-plugin.d.ts.map +1 -1
  32. package/types/metro-config/getMetroConfigFromViteConfig.d.ts.map +1 -1
  33. package/types/transformer/metroNativeWorker.d.ts.map +1 -1
@@ -80,28 +80,45 @@ function assertZeroBabelCalls() {
80
80
  }
81
81
 
82
82
  describe('metroNativeWorker', () => {
83
- it.each([['data.json', true], ['data.json', false], ['data.js', false]] as const)('minifies %s with source maps enabled=%s without stale mappings', async (filename, sourceMap) => {
84
- const result = await transform(
85
- {
86
- minifierPath: createRequire(import.meta.url).resolve('metro-minify-terser'),
87
- minifierConfig: { sourceMap },
88
- },
89
- '/project',
90
- filename,
91
- Buffer.from(filename.endsWith('.json') ? '{"answer":42}' : 'module.exports = { answer: 42 }'),
92
- { dev: false, minify: true, platform: 'ios', type: 'module' }
93
- )
94
- const module = { exports: {} as any }
95
- const { code, map } = result.output[0].data
96
- vm.runInNewContext(code, {
97
- __d(factory: any) {
98
- factory({}, () => {}, () => {}, () => {}, module, module.exports, [])
99
- },
100
- })
101
- expect(module.exports.answer).toBe(42)
102
- expect(map.every((entry) => entry.length === 2)).toBe(true)
103
- assertZeroBabelCalls()
104
- })
83
+ it.each([
84
+ ['data.json', true],
85
+ ['data.json', false],
86
+ ['data.js', false],
87
+ ] as const)(
88
+ 'minifies %s with source maps enabled=%s without stale mappings',
89
+ async (filename, sourceMap) => {
90
+ const result = await transform(
91
+ {
92
+ minifierPath: createRequire(import.meta.url).resolve('metro-minify-terser'),
93
+ minifierConfig: { sourceMap },
94
+ },
95
+ '/project',
96
+ filename,
97
+ Buffer.from(
98
+ filename.endsWith('.json') ? '{"answer":42}' : 'module.exports = { answer: 42 }'
99
+ ),
100
+ { dev: false, minify: true, platform: 'ios', type: 'module' }
101
+ )
102
+ const module = { exports: {} as any }
103
+ const { code, map } = result.output[0].data
104
+ vm.runInNewContext(code, {
105
+ __d(factory: any) {
106
+ factory(
107
+ {},
108
+ () => {},
109
+ () => {},
110
+ () => {},
111
+ module,
112
+ module.exports,
113
+ []
114
+ )
115
+ },
116
+ })
117
+ expect(module.exports.answer).toBe(42)
118
+ expect(map.every((entry) => entry.length === 2)).toBe(true)
119
+ assertZeroBabelCalls()
120
+ }
121
+ )
105
122
 
106
123
  it('minifies production modules with executable output and original source locations', async () => {
107
124
  const source = 'exports.answer = function answer(value) {\n return value + 42\n}\n'
@@ -119,7 +136,15 @@ describe('metroNativeWorker', () => {
119
136
  const module = { exports: {} as any }
120
137
  vm.runInNewContext(code, {
121
138
  __d(factory: any) {
122
- factory({}, () => {}, () => {}, () => {}, module, module.exports, [])
139
+ factory(
140
+ {},
141
+ () => {},
142
+ () => {},
143
+ () => {},
144
+ module,
145
+ module.exports,
146
+ []
147
+ )
123
148
  },
124
149
  })
125
150
  expect(module.exports.answer(8)).toBe(50)
@@ -207,10 +232,14 @@ describe('metroNativeWorker', () => {
207
232
  `
208
233
 
209
234
  const off = extractDependencies(code, 'setup.js')
210
- expect(off.find((d) => d.name === 'react-native-worklets-core')!.data.isOptional).toBeUndefined()
235
+ expect(
236
+ off.find((d) => d.name === 'react-native-worklets-core')!.data.isOptional
237
+ ).toBeUndefined()
211
238
 
212
239
  const on = extractDependencies(code, 'setup.js', { allowOptionalDependencies: true })
213
- expect(on.find((d) => d.name === 'react-native-worklets-core')!.data.isOptional).toBe(true)
240
+ expect(on.find((d) => d.name === 'react-native-worklets-core')!.data.isOptional).toBe(
241
+ true
242
+ )
214
243
  expect(on.find((d) => d.name === './always-there')!.data.isOptional).toBeUndefined()
215
244
 
216
245
  const excluded = extractDependencies(code, 'setup.js', {
@@ -361,7 +390,9 @@ describe('metroNativeWorker', () => {
361
390
  expect(result.dependencies).toEqual([])
362
391
  expect(result.output).toHaveLength(1)
363
392
  expect(result.output[0].type).toBe('js/module')
364
- expect(result.output[0].data.code).toContain('module.exports = {"name":"my-package","version":"1.0.0"}')
393
+ expect(result.output[0].data.code).toContain(
394
+ 'module.exports = {"name":"my-package","version":"1.0.0"}'
395
+ )
365
396
  expect(result.output[0].data.code).toContain('__d(function (global, require')
366
397
  })
367
398
 
@@ -409,8 +440,14 @@ describe('metroNativeWorker', () => {
409
440
  })
410
441
 
411
442
  it('generates a deterministic cache key without Babel', () => {
412
- const key1 = getCacheKey({ globalPrefix: '__one_', minifierPath: 'terser' }, { projectRoot: '/app' })
413
- const key2 = getCacheKey({ globalPrefix: '__one_', minifierPath: 'terser' }, { projectRoot: '/app' })
443
+ const key1 = getCacheKey(
444
+ { globalPrefix: '__one_', minifierPath: 'terser' },
445
+ { projectRoot: '/app' }
446
+ )
447
+ const key2 = getCacheKey(
448
+ { globalPrefix: '__one_', minifierPath: 'terser' },
449
+ { projectRoot: '/app' }
450
+ )
414
451
  const key3 = getCacheKey({ globalPrefix: '__other_' }, { projectRoot: '/app' })
415
452
 
416
453
  assertZeroBabelCalls()
@@ -455,12 +492,36 @@ describe('metroNativeWorker', () => {
455
492
  delete process.env.ONE_METRO_NATIVE_TRANSFORMS
456
493
  })
457
494
 
495
+ it('excludes volatile compiler caches from Metro without hiding package output', async () => {
496
+ const config = await buildMetroConfigInputFromViteConfig(
497
+ { root: process.cwd() } as any,
498
+ { watchman: false }
499
+ )
500
+ const blockList = config.defaultConfig.resolver.blockList as RegExp[]
501
+ const isBlocked = (file: string) => blockList.some((pattern) => pattern.test(file))
502
+
503
+ expect(
504
+ isBlocked(
505
+ '/home/runner/work/one/one/tests/test-app-cases/node_modules/.vxrn/compiler-cache'
506
+ )
507
+ ).toBe(true)
508
+ expect(
509
+ isBlocked(
510
+ 'C:\\workspace\\tests\\test-app-cases\\node_modules\\.vxrn\\compiler-cache'
511
+ )
512
+ ).toBe(true)
513
+ expect(isBlocked('/home/runner/work/one/one/packages/one/dist/esm/index.mjs')).toBe(
514
+ false
515
+ )
516
+ })
517
+
458
518
  it('transforms and executes a real 2-module Metro bundle through metro-runtime require polyfill', async () => {
459
519
  // Probe 1 verification:
460
520
  // Module 2 (dep.js): exports a value
461
521
  // Module 1 (a.js): requires dep.js using Metro dependency ABI and exports computed result
462
522
  const depSource = 'exports.value = 42;'
463
- const aSource = 'const dep = require("./dep"); module.exports = { doubled: dep.value * 2 };'
523
+ const aSource =
524
+ 'const dep = require("./dep"); module.exports = { doubled: dep.value * 2 };'
464
525
 
465
526
  // Transform dep.js (Module 2)
466
527
  const depRes = await transform(
@@ -478,19 +539,13 @@ describe('metroNativeWorker', () => {
478
539
  )
479
540
 
480
541
  // Transform a.js (Module 1) which depends on dep.js (dependency slot 0 -> moduleId 2)
481
- const aRes = await transform(
482
- {},
483
- '/project',
484
- 'a.js',
485
- Buffer.from(aSource, 'utf8'),
486
- {
487
- dev: false,
488
- platform: 'ios',
489
- type: 'module',
490
- moduleId: 1,
491
- dependencyIds: [2],
492
- } as any
493
- )
542
+ const aRes = await transform({}, '/project', 'a.js', Buffer.from(aSource, 'utf8'), {
543
+ dev: false,
544
+ platform: 'ios',
545
+ type: 'module',
546
+ moduleId: 1,
547
+ dependencyIds: [2],
548
+ } as any)
494
549
 
495
550
  assertZeroBabelCalls()
496
551
 
@@ -526,7 +581,8 @@ describe('metroNativeWorker', () => {
526
581
 
527
582
  it('transforms and executes a 2-module Metro bundle with ESM imports in dev mode', async () => {
528
583
  const depSource = 'export const greeting = "Hello Metro Native";'
529
- const aSource = 'import { greeting } from "./dep"; export const message = greeting.toUpperCase();'
584
+ const aSource =
585
+ 'import { greeting } from "./dep"; export const message = greeting.toUpperCase();'
530
586
 
531
587
  // Transform dep.js (Module 2)
532
588
  const depRes = await transform(
@@ -544,19 +600,13 @@ describe('metroNativeWorker', () => {
544
600
  )
545
601
 
546
602
  // Transform a.js (Module 1) depending on dep.js (dependency slot 0 -> moduleId 2)
547
- const aRes = await transform(
548
- {},
549
- '/project',
550
- 'a.js',
551
- Buffer.from(aSource, 'utf8'),
552
- {
553
- dev: true,
554
- platform: 'ios',
555
- type: 'module',
556
- moduleId: 1,
557
- dependencyIds: [2],
558
- } as any
559
- )
603
+ const aRes = await transform({}, '/project', 'a.js', Buffer.from(aSource, 'utf8'), {
604
+ dev: true,
605
+ platform: 'ios',
606
+ type: 'module',
607
+ moduleId: 1,
608
+ dependencyIds: [2],
609
+ } as any)
560
610
 
561
611
  assertZeroBabelCalls()
562
612
 
@@ -583,7 +633,8 @@ describe('metroNativeWorker', () => {
583
633
  // Exact probe from Astra:
584
634
  // function f(require){return require("./local")}; module.exports=f(x=>x);
585
635
  // require is shadowed by parameter: must NOT extract ./local, and must NOT rewrite require
586
- const input = 'function f(require){return require("./local")}; module.exports=f(x=>x);'
636
+ const input =
637
+ 'function f(require){return require("./local")}; module.exports=f(x=>x);'
587
638
 
588
639
  const res = await transform(
589
640
  {},
@@ -635,13 +686,11 @@ describe('metroNativeWorker', () => {
635
686
  const c = await import('./dep');
636
687
  }
637
688
  `
638
- const res = await transform(
639
- {},
640
- '/project',
641
- 'index.js',
642
- Buffer.from(code, 'utf8'),
643
- { dev: false, platform: 'ios', type: 'module' }
644
- )
689
+ const res = await transform({}, '/project', 'index.js', Buffer.from(code, 'utf8'), {
690
+ dev: false,
691
+ platform: 'ios',
692
+ type: 'module',
693
+ })
645
694
 
646
695
  assertZeroBabelCalls()
647
696
 
@@ -649,8 +698,12 @@ describe('metroNativeWorker', () => {
649
698
  const depNames = res.dependencies.map((d) => d.name)
650
699
  expect(depNames).toContain('./dep')
651
700
 
652
- const syncDep = res.dependencies.find((d) => d.name === './dep' && d.data.asyncType === null)!
653
- const asyncDep = res.dependencies.find((d) => d.name === './dep' && d.data.asyncType === 'async')!
701
+ const syncDep = res.dependencies.find(
702
+ (d) => d.name === './dep' && d.data.asyncType === null
703
+ )!
704
+ const asyncDep = res.dependencies.find(
705
+ (d) => d.name === './dep' && d.data.asyncType === 'async'
706
+ )!
654
707
  expect(syncDep).toBeDefined()
655
708
  expect(asyncDep).toBeDefined()
656
709
  expect(syncDep.data.index).not.toEqual(asyncDep.data.index)
@@ -721,7 +774,8 @@ describe('metroNativeWorker', () => {
721
774
  // Exact probe from Astra:
722
775
  // function f(){const x=require("./local"); function require(x){return x}; return x} module.exports=f();
723
776
  // function require is hoisted to f's function scope, so require("./local") is a local call and needs no module.
724
- const input = 'function f(){const x=require("./local"); function require(x){return x}; return x} module.exports=f();'
777
+ const input =
778
+ 'function f(){const x=require("./local"); function require(x){return x}; return x} module.exports=f();'
725
779
 
726
780
  const res = await transform(
727
781
  {},
@@ -823,7 +877,10 @@ describe('metroNativeWorker', () => {
823
877
  const polyfillCode = fs.readFileSync(polyfillPath, 'utf8')
824
878
  const asyncRequirePath = require.resolve('metro-runtime/src/modules/asyncRequire.js')
825
879
  const asyncRequireSource = fs.readFileSync(asyncRequirePath, 'utf8')
826
- const wrappedAsyncRequire = wrapModule(asyncRequireSource, { moduleId: 1, dependencyIds: [] })
880
+ const wrappedAsyncRequire = wrapModule(asyncRequireSource, {
881
+ moduleId: 1,
882
+ dependencyIds: [],
883
+ })
827
884
 
828
885
  for (const isDev of [true, false]) {
829
886
  const contextObj = {
@@ -844,7 +901,9 @@ describe('metroNativeWorker', () => {
844
901
  expect(typeof mainFn).toBe('function')
845
902
 
846
903
  const promise = mainFn()
847
- expect(promise instanceof Promise || (promise && typeof promise.then === 'function')).toBe(true)
904
+ expect(
905
+ promise instanceof Promise || (promise && typeof promise.then === 'function')
906
+ ).toBe(true)
848
907
 
849
908
  const resolved = await promise
850
909
  expect(resolved.message).toBe('hello dynamic')
@@ -945,11 +1004,17 @@ describe('metroNativeWorker', () => {
945
1004
  export const ctx = require.context(routeRoot, true, /\\.tsx$/)
946
1005
  `
947
1006
 
948
- const result = await transform({}, '/project', 'entry.js', Buffer.from(sourceCode, 'utf8'), {
949
- dev: true,
950
- platform: 'ios',
951
- type: 'module',
952
- })
1007
+ const result = await transform(
1008
+ {},
1009
+ '/project',
1010
+ 'entry.js',
1011
+ Buffer.from(sourceCode, 'utf8'),
1012
+ {
1013
+ dev: true,
1014
+ platform: 'ios',
1015
+ type: 'module',
1016
+ }
1017
+ )
953
1018
 
954
1019
  const contextDep = result.dependencies.find((d) => d.data.contextParams != null)
955
1020
  expect(contextDep?.name).toBe('./app')
@@ -967,7 +1032,15 @@ describe('metroNativeWorker', () => {
967
1032
  req.context = () => {
968
1033
  throw new Error('fallbackRequireContext reached')
969
1034
  }
970
- factory({}, req, () => ({}), () => ({}), module, module.exports, ['./app'])
1035
+ factory(
1036
+ {},
1037
+ req,
1038
+ () => ({}),
1039
+ () => ({}),
1040
+ module,
1041
+ module.exports,
1042
+ ['./app']
1043
+ )
971
1044
  ctx = module.exports.ctx
972
1045
  },
973
1046
  }
@@ -989,11 +1062,17 @@ describe('metroNativeWorker', () => {
989
1062
  }
990
1063
  `
991
1064
 
992
- const result = await transform({}, '/project', 'loops.ts', Buffer.from(sourceCode, 'utf8'), {
993
- dev: true,
994
- platform: 'ios',
995
- type: 'module',
996
- })
1065
+ const result = await transform(
1066
+ {},
1067
+ '/project',
1068
+ 'loops.ts',
1069
+ Buffer.from(sourceCode, 'utf8'),
1070
+ {
1071
+ dev: true,
1072
+ platform: 'ios',
1073
+ type: 'module',
1074
+ }
1075
+ )
997
1076
 
998
1077
  const code = result.output[0].data.code
999
1078
 
@@ -1002,16 +1081,21 @@ describe('metroNativeWorker', () => {
1002
1081
  // Rewriting the heads that way reproduces Hermes on a runtime that is
1003
1082
  // otherwise spec-correct, which is what makes this assertion meaningful:
1004
1083
  // the untransformed source returns 2,2,b,b,y,y under it.
1005
- const asHermesWouldSeeIt = code.replace(
1006
- /\bfor\s*\(\s*(let|const)\b/g,
1007
- 'for (var'
1008
- )
1084
+ const asHermesWouldSeeIt = code.replace(/\bfor\s*\(\s*(let|const)\b/g, 'for (var')
1009
1085
 
1010
1086
  let collect: any
1011
1087
  const sandbox: any = {
1012
1088
  __d: (factory: any) => {
1013
1089
  const module = { exports: {} as any }
1014
- factory({}, () => ({}), () => ({}), () => ({}), module, module.exports, [])
1090
+ factory(
1091
+ {},
1092
+ () => ({}),
1093
+ () => ({}),
1094
+ () => ({}),
1095
+ module,
1096
+ module.exports,
1097
+ []
1098
+ )
1015
1099
  collect = module.exports.collect
1016
1100
  },
1017
1101
  }
@@ -1095,7 +1179,9 @@ export const all = { ...import.meta.env };`,
1095
1179
 
1096
1180
  it('folds a ternary and keeps a branch it cannot resolve', () => {
1097
1181
  expect(
1098
- applyInlineEnvVars('const a = import.meta.env.DEV ? x : y;', 'a.ts', true, { DEV: false })
1182
+ applyInlineEnvVars('const a = import.meta.env.DEV ? x : y;', 'a.ts', true, {
1183
+ DEV: false,
1184
+ })
1099
1185
  ).toContain('const a = y;')
1100
1186
  const dynamic = 'const a = flag ? x : y;'
1101
1187
  expect(applyInlineEnvVars(dynamic, 'a.ts', true, { DEV: false })).toBe(dynamic)
@@ -1181,7 +1267,7 @@ export const all = { ...import.meta.env };`,
1181
1267
  expect(parsed.program.body.map((n: any) => n.type)).toContain('ThrowStatement')
1182
1268
  })
1183
1269
 
1184
- it('reads the router root off one\'s remove-server-code plugin entry', () => {
1270
+ it("reads the router root off one's remove-server-code plugin entry", () => {
1185
1271
  const options: any = {
1186
1272
  customTransformOptions: {
1187
1273
  vite: {