vxrn 1.1.166 → 1.1.168

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 (43) hide show
  1. package/dist/utils/assert.js +6 -1
  2. package/dist/utils/assert.js.map +1 -1
  3. package/dist/utils/assert.mjs +4 -1
  4. package/dist/utils/assert.mjs.map +1 -1
  5. package/dist/utils/assert.native.js +10 -1
  6. package/dist/utils/assert.native.js.map +2 -2
  7. package/dist/utils/getBaseViteConfig.js +9 -0
  8. package/dist/utils/getBaseViteConfig.js.map +1 -1
  9. package/dist/utils/getBaseViteConfig.mjs +9 -0
  10. package/dist/utils/getBaseViteConfig.mjs.map +1 -1
  11. package/dist/utils/getBaseViteConfig.native.js +9 -0
  12. package/dist/utils/getBaseViteConfig.native.js.map +2 -2
  13. package/dist/utils/getReactNativeBundle.js +3 -2
  14. package/dist/utils/getReactNativeBundle.js.map +1 -1
  15. package/dist/utils/getReactNativeBundle.mjs +3 -2
  16. package/dist/utils/getReactNativeBundle.mjs.map +1 -1
  17. package/dist/utils/getReactNativeBundle.native.js +4 -3
  18. package/dist/utils/getReactNativeBundle.native.js.map +2 -2
  19. package/dist/utils/getReactNativeConfig.js +13 -0
  20. package/dist/utils/getReactNativeConfig.js.map +1 -1
  21. package/dist/utils/getReactNativeConfig.mjs +13 -1
  22. package/dist/utils/getReactNativeConfig.mjs.map +1 -1
  23. package/dist/utils/getReactNativeConfig.native.js +24 -0
  24. package/dist/utils/getReactNativeConfig.native.js.map +2 -2
  25. package/dist/utils/patches.js +95 -19
  26. package/dist/utils/patches.js.map +1 -1
  27. package/dist/utils/patches.mjs +87 -27
  28. package/dist/utils/patches.mjs.map +1 -1
  29. package/dist/utils/patches.native.js +285 -101
  30. package/dist/utils/patches.native.js.map +2 -2
  31. package/package.json +8 -7
  32. package/src/exports/dev.ts +2 -2
  33. package/src/utils/assert.ts +6 -0
  34. package/src/utils/getBaseViteConfig.ts +10 -0
  35. package/src/utils/getReactNativeBundle.ts +11 -1
  36. package/src/utils/getReactNativeConfig.ts +20 -0
  37. package/src/utils/patches.ts +168 -41
  38. package/types/utils/assert.d.ts +1 -0
  39. package/types/utils/assert.d.ts.map +1 -1
  40. package/types/utils/getBaseViteConfig.d.ts.map +1 -1
  41. package/types/utils/getReactNativeBundle.d.ts.map +1 -1
  42. package/types/utils/getReactNativeConfig.d.ts.map +1 -1
  43. package/types/utils/patches.d.ts.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vxrn",
3
- "version": "1.1.166",
3
+ "version": "1.1.168",
4
4
  "source": "src/index.ts",
5
5
  "types": "./types/index.d.ts",
6
6
  "type": "module",
@@ -40,11 +40,11 @@
40
40
  "@babel/core": "^7.21.8",
41
41
  "@hono/node-server": "^1.11.1",
42
42
  "@vitejs/plugin-react-swc": "^3.7.0",
43
- "@vxrn/react-native-prebuilt": "1.1.166",
44
- "@vxrn/safe-area": "1.1.166",
45
- "@vxrn/vendor": "1.1.166",
46
- "@vxrn/vite-flow": "1.1.166",
47
- "@vxrn/vite-native-swc": "1.1.166",
43
+ "@vxrn/react-native-prebuilt": "1.1.168",
44
+ "@vxrn/safe-area": "1.1.168",
45
+ "@vxrn/vendor": "1.1.168",
46
+ "@vxrn/vite-flow": "1.1.168",
47
+ "@vxrn/vite-native-swc": "1.1.168",
48
48
  "citty": "^0.1.6",
49
49
  "crossws": "^0.2.4",
50
50
  "es-module-lexer": "^1.3.0",
@@ -56,6 +56,7 @@
56
56
  "h3-proxy": "^1.13.0",
57
57
  "hono": "^4.3.10",
58
58
  "import-meta-resolve": "^4.1.0",
59
+ "lightningcss": "^1.26.0",
59
60
  "picocolors": "^1.0.0",
60
61
  "pkg-types": "^1.0.3",
61
62
  "vite": "6.0.0-alpha.18",
@@ -65,7 +66,7 @@
65
66
  },
66
67
  "devDependencies": {
67
68
  "@biomejs/biome": "^1.8.3",
68
- "@tamagui/build": "^1.108.3",
69
+ "@tamagui/build": "^1.108.4",
69
70
  "@types/find-node-modules": "^2.1.2",
70
71
  "@types/node": "^22.1.0",
71
72
  "@types/ws": "^8.5.10",
@@ -60,8 +60,8 @@ export const dev = async (optionsIn: VXRNOptions & { clean?: boolean }) => {
60
60
  const serverConfig = await getViteServerConfig(options)
61
61
  const viteServer = await createServer(serverConfig)
62
62
 
63
- // first resolve config so we can pass into client plugin, then add client plugin:
64
- // TODO do we need this really? seems like we don't, can check if we can do this without the resolveConfig()
63
+ // we pass resolved config into client inject to get the final port etc to use
64
+ // probably can be done better
65
65
  const resolvedConfig = await resolveConfig(serverConfig, 'serve')
66
66
  const viteRNClientPlugin = clientInjectionsPlugin(resolvedConfig)
67
67
 
@@ -3,3 +3,9 @@ export function assertIsError(error: unknown): asserts error is Error {
3
3
  throw error
4
4
  }
5
5
  }
6
+
7
+ export function assertString(thing: any): asserts thing is string {
8
+ if (typeof thing !== 'string') {
9
+ throw `expected string, got ${typeof thing}`
10
+ }
11
+ }
@@ -50,6 +50,16 @@ export function getBaseViteConfig({ mode }: { mode: 'development' | 'production'
50
50
  reactSwcPlugin({}),
51
51
  ],
52
52
 
53
+ // TODO make this documented / configurable through the plugins
54
+ css: {
55
+ transformer: 'lightningcss',
56
+ lightningcss: {
57
+ targets: {
58
+ safari: (15 << 16) | (2 << 8),
59
+ },
60
+ },
61
+ },
62
+
53
63
  define: {
54
64
  __DEV__: `${mode === 'development'}`,
55
65
  'process.env.NODE_ENV': `"${mode}"`,
@@ -67,6 +67,16 @@ export async function getReactNativeBundle(options: VXRNOptionsFilled, viteRNCli
67
67
  )
68
68
  }
69
69
 
70
+ let code = outputModule.code
71
+
72
+ // A hacky way to exclude node-fetch from the bundle.
73
+ //
74
+ // Some part of Supabase SDK will import node-fetch statically (https://github.com/supabase/supabase-js/blob/v2.45.1/src/lib/fetch.ts#L2), or dynamically (https://github.com/supabase/auth-js/blob/8222ee198a0ab10570e8b4c31ffb2aeafef86392/src/lib/helpers.ts#L99), causing the node-fetch to be included in the bundle, and while imported statically it will throw a runtime error when running on React Native.
75
+ if (outputModule.facadeModuleId?.includes('@supabase/node-fetch')) {
76
+ // This should be safe since the imported '@supabase/node-fetch' will not actually be used in Supabase SDK as there's already a global `fetch` in React Native.
77
+ code = ''
78
+ }
79
+
70
80
  return `
71
81
  // id: ${id}
72
82
  // name: ${outputModule.name}
@@ -76,7 +86,7 @@ ___vxrnAbsoluteToRelative___["${outputModule.facadeModuleId}"] = "${id}"
76
86
  ___modules___["${id}"] = ((exports, module) => {
77
87
  const require = createRequire("${id}", ${JSON.stringify(importsMap, null, 2)})
78
88
 
79
- ${outputModule.code}
89
+ ${code}
80
90
  })
81
91
 
82
92
  ${
@@ -56,6 +56,26 @@ export async function getReactNativeConfig(options: VXRNOptionsFilled, viteRNCli
56
56
  mode: 'build',
57
57
  }),
58
58
 
59
+ // Avoid "failed to read input source map: failed to parse inline source map url" errors on certain packages, such as react-native-reanimated.
60
+ {
61
+ name: 'remove-inline-source-maps',
62
+ transform: {
63
+ order: 'pre',
64
+ async handler(code, id) {
65
+ if (!id.includes('react-native-reanimated')) {
66
+ return null
67
+ }
68
+
69
+ const inlineSourceMapIndex = code.lastIndexOf('//# sourceMappingURL=')
70
+ if (inlineSourceMapIndex >= 0) {
71
+ return code.slice(0, inlineSourceMapIndex).trimEnd();
72
+ }
73
+
74
+ return null;
75
+ },
76
+ },
77
+ },
78
+
59
79
  viteNativeSWC({
60
80
  tsDecorators: true,
61
81
  mode: 'build',
@@ -2,24 +2,150 @@ import findNodeModules from 'find-node-modules'
2
2
  import { join } from 'node:path'
3
3
  import FSExtra from 'fs-extra'
4
4
  import type { VXRNOptionsFilled } from './getOptionsFilled'
5
+ import { assertString } from './assert'
5
6
 
6
- const patches = [
7
+ type Patch = {
8
+ module: string
9
+ patchFiles: {
10
+ [key: string]: (contents?: string) => string | Promise<string>
11
+ }
12
+ }
13
+
14
+ class Bail extends Error {}
15
+
16
+ function bailIfExists(haystack: string, needle: string) {
17
+ if (haystack.includes(needle)) {
18
+ throw new Bail()
19
+ }
20
+ }
21
+
22
+ // TODO has no concept of version range checking, or patch versions
23
+
24
+ const patches: Patch[] = [
7
25
  {
8
26
  module: 'h3',
9
- patchFile: 'h3+1.11.1.patch',
27
+ patchFiles: {
28
+ 'dist/index.mjs': (contents) => {
29
+ assertString(contents)
30
+ bailIfExists(contents, '/** patch-version-1 **/')
31
+
32
+ const insertPoint = contents.indexOf(` return headers;`)
33
+ return (
34
+ contents.slice(0, insertPoint) +
35
+ `
36
+ /** patch-version-1 **/
37
+ // The expoManifestRequestHandlerPlugin (Vite plugin) needs the original request host so that it can compose URLs that can be accessed by physical devices. This won't be needed once we retire h3 and use the Vite Dev Server directly.
38
+ // This may not work if one installed vxrn from NPM since this patch may not apply.
39
+ const originalHost = reqHeaders.host;
40
+ if (originalHost) {
41
+ headers['X-Forwarded-Host'] = originalHost;
42
+ }
43
+
44
+ ` +
45
+ contents.slice(insertPoint)
46
+ )
47
+ },
48
+ },
10
49
  },
50
+
11
51
  {
12
52
  module: 'react',
13
- patchFile: 'react+18.3.1.patch',
53
+ patchFiles: {
54
+ 'index.web.js': () => {
55
+ return `module.exports = require('@vxrn/vendor/react-19');`
56
+ },
57
+ 'jsx-dev-runtime.web.js': () => {
58
+ return `module.exports = require('@vxrn/vendor/react-jsx-dev-19');`
59
+ },
60
+ 'jsx-runtime.web.js': () => {
61
+ return `module.exports = require('@vxrn/vendor/react-jsx-19');`
62
+ },
63
+ 'package.json': (contents) => {
64
+ assertString(contents)
65
+ bailIfExists(contents, 'index.web.js')
66
+
67
+ const pkg = JSON.parse(contents)
68
+
69
+ if (!pkg.exports['.']) {
70
+ throw new Error(`Expected a version of React that has package.json exports defined`)
71
+ }
72
+
73
+ pkg.exports['.'] = {
74
+ 'react-server': './react.shared-subset.js',
75
+ 'react-native': './index.js',
76
+ default: './index.web.js',
77
+ }
78
+
79
+ pkg.exports['./jsx-runtime'] = {
80
+ 'react-native': './jsx-runtime.js',
81
+ default: './jsx-runtime.web.js',
82
+ }
83
+
84
+ pkg.exports['./jsx-dev-runtime'] = {
85
+ 'react-native': './jsx-dev-runtime.js',
86
+ default: './jsx-dev-runtime.web.js',
87
+ }
88
+
89
+ return JSON.stringify(pkg, null, 2)
90
+ },
91
+ },
14
92
  },
93
+
15
94
  {
16
95
  module: 'react-dom',
17
- patchFile: 'react-dom+18.3.1.patch',
96
+ patchFiles: {
97
+ 'client.web.js': () => {
98
+ return `module.exports = require('@vxrn/vendor/react-dom-client-19')`
99
+ },
100
+
101
+ 'index.web.js': () => {
102
+ return `module.exports = require('@vxrn/vendor/react-dom-19')`
103
+ },
104
+
105
+ 'server.browser.web.js': () => {
106
+ return `module.exports = require('@vxrn/vendor/react-dom-server.browser-19')`
107
+ },
108
+
109
+ 'test-utils.web.js': () => {
110
+ return `module.exports = require('@vxrn/vendor/react-dom-test-utils-19')`
111
+ },
112
+
113
+ 'package.json': (contents) => {
114
+ assertString(contents)
115
+ bailIfExists(contents, 'index.web.js')
116
+
117
+ const pkg = JSON.parse(contents)
118
+
119
+ if (!pkg.exports['.']) {
120
+ throw new Error(`Expected a version of React that has package.json exports defined`)
121
+ }
122
+
123
+ pkg.exports['.'] = {
124
+ 'react-native': './index.js',
125
+ default: './index.web.js',
126
+ }
127
+
128
+ pkg.exports['./client'] = {
129
+ 'react-native': './client.js',
130
+ default: './client.web.js',
131
+ }
132
+
133
+ pkg.exports['./server.browser'] = {
134
+ 'react-native': './server.browser.js',
135
+ default: './server.browser.web.js',
136
+ }
137
+
138
+ pkg.exports['./test-utils'] = {
139
+ 'react-native': './test-utils.js',
140
+ default: './test-utils.web.js',
141
+ }
142
+
143
+ return JSON.stringify(pkg, null, 2)
144
+ },
145
+ },
18
146
  },
19
147
  ]
20
148
 
21
- type Patch = (typeof patches)[0]
22
-
23
149
  export async function checkPatches(options: VXRNOptionsFilled) {
24
150
  if (options.state.applyPatches === false) {
25
151
  return
@@ -29,47 +155,48 @@ export async function checkPatches(options: VXRNOptionsFilled) {
29
155
  cwd: options.root,
30
156
  }).map((relativePath) => join(options.root, relativePath))
31
157
 
32
- const patchesToCopy: { patch: Patch; dir: string }[] = []
33
-
34
158
  await Promise.all(
35
159
  patches.flatMap((patch) => {
36
160
  return nodeModulesDirs.flatMap(async (dir) => {
37
- if (await FSExtra.pathExists(join(dir, patch.module))) {
38
- patchesToCopy.push({ patch, dir })
39
- }
40
- })
41
- })
42
- )
161
+ const nodeModuleDir = join(dir, patch.module)
43
162
 
44
- let didCopy = false
163
+ if (await FSExtra.pathExists(nodeModuleDir)) {
164
+ for (const file in patch.patchFiles) {
165
+ const log = () => {
166
+ console.info(` Applying patch to ${patch.module}`)
167
+ }
45
168
 
46
- for (const { patch, dir } of patchesToCopy) {
47
- const patchesDir = join(dir, '..', 'patches')
169
+ try {
170
+ const fullPath = join(nodeModuleDir, file)
171
+ const patchFn = patch.patchFiles[file]
48
172
 
49
- if (!(await FSExtra.pathExists(patchesDir))) {
50
- await FSExtra.mkdir(patchesDir)
51
- }
173
+ // create
174
+ if (!(await FSExtra.pathExists(fullPath))) {
175
+ log()
176
+ await FSExtra.writeFile(fullPath, await patchFn())
177
+ return
178
+ }
52
179
 
53
- const src = join(options.internalPatchesDir, patch.patchFile)
54
- const dest = join(patchesDir, patch.patchFile)
55
- const patchContents = await FSExtra.readFile(src, 'utf-8')
180
+ // if its a create function (takes no arg), bail if it exists already
181
+ if (patchFn.length === 0) {
182
+ return
183
+ }
56
184
 
57
- if (
58
- !(await FSExtra.pathExists(dest)) ||
59
- (await FSExtra.readFile(dest, 'utf-8')) !== patchContents
60
- ) {
61
- didCopy = true
62
- console.info(` 🩹 Adding patch ${patch.module}`)
63
- await FSExtra.copy(src, dest)
64
- }
65
- }
66
-
67
- if (didCopy) {
68
- console.info(
69
- `\nWe've added patches to support running React 19 and 18 in parallel. Please run "npx patch-package" and re-run.
70
-
71
- You'll want to add "patch-package" to your devDependencies and scripts.postinstall in your package.json.\n`
72
- )
73
- process.exit(0)
74
- }
185
+ log()
186
+ // update
187
+ await FSExtra.writeFile(
188
+ fullPath,
189
+ await patchFn(await FSExtra.readFile(fullPath, 'utf-8'))
190
+ )
191
+ } catch (err) {
192
+ if (err instanceof Bail) {
193
+ return
194
+ }
195
+ throw err
196
+ }
197
+ }
198
+ }
199
+ })
200
+ })
201
+ )
75
202
  }
@@ -1,2 +1,3 @@
1
1
  export declare function assertIsError(error: unknown): asserts error is Error;
2
+ export declare function assertString(thing: any): asserts thing is string;
2
3
  //# sourceMappingURL=assert.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../src/utils/assert.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAIpE"}
1
+ {"version":3,"file":"assert.d.ts","sourceRoot":"","sources":["../../src/utils/assert.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAIpE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAIhE"}
@@ -1 +1 @@
1
- {"version":3,"file":"getBaseViteConfig.d.ts","sourceRoot":"","sources":["../../src/utils/getBaseViteConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAKxC,eAAO,MAAM,MAAM,UAWlB,CAAA;AAED,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,aAAa,GAAG,YAAY,CAAA;CAAE,GAAG,YAAY,CAsDhG"}
1
+ {"version":3,"file":"getBaseViteConfig.d.ts","sourceRoot":"","sources":["../../src/utils/getBaseViteConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAKxC,eAAO,MAAM,MAAM,UAWlB,CAAA;AAED,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,aAAa,GAAG,YAAY,CAAA;CAAE,GAAG,YAAY,CAgEhG"}
@@ -1 +1 @@
1
- {"version":3,"file":"getReactNativeBundle.d.ts","sourceRoot":"","sources":["../../src/utils/getReactNativeBundle.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAS3D,eAAO,IAAI,SAAS,QAAK,CAAA;AAEzB,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,GAAG,mBAuG7F"}
1
+ {"version":3,"file":"getReactNativeBundle.d.ts","sourceRoot":"","sources":["../../src/utils/getReactNativeBundle.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAS3D,eAAO,IAAI,SAAS,QAAK,CAAA;AAEzB,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,GAAG,mBAiH7F"}
@@ -1 +1 @@
1
- {"version":3,"file":"getReactNativeConfig.d.ts","sourceRoot":"","sources":["../../src/utils/getReactNativeConfig.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAG3D,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2H7F"}
1
+ {"version":3,"file":"getReactNativeConfig.d.ts","sourceRoot":"","sources":["../../src/utils/getReactNativeConfig.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAG3D,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+I7F"}
@@ -1 +1 @@
1
- {"version":3,"file":"patches.d.ts","sourceRoot":"","sources":["../../src/utils/patches.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAmB3D,wBAAsB,YAAY,CAAC,OAAO,EAAE,iBAAiB,iBAoD5D"}
1
+ {"version":3,"file":"patches.d.ts","sourceRoot":"","sources":["../../src/utils/patches.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAiJ3D,wBAAsB,YAAY,CAAC,OAAO,EAAE,iBAAiB,iBAqD5D"}