vxrn 2.0.0-beta.99.1 → 2.6.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.
Files changed (210) hide show
  1. package/dist/backgroundComputation.mjs +145 -0
  2. package/dist/backgroundComputation.mjs.map +1 -0
  3. package/dist/backgroundComputation.native.js +163 -0
  4. package/dist/backgroundComputation.native.js.map +1 -0
  5. package/dist/backgroundComputationNative.mjs +16 -0
  6. package/dist/backgroundComputationNative.mjs.map +1 -0
  7. package/dist/backgroundComputationNative.native.js +18 -0
  8. package/dist/backgroundComputationNative.native.js.map +1 -0
  9. package/dist/config/getBaseViteConfigOnly.mjs +6 -10
  10. package/dist/config/getBaseViteConfigOnly.mjs.map +1 -1
  11. package/dist/config/getBaseViteConfigOnly.native.js +6 -10
  12. package/dist/config/getBaseViteConfigOnly.native.js.map +1 -1
  13. package/dist/config/getOptimizeDeps.mjs +2 -1
  14. package/dist/config/getOptimizeDeps.mjs.map +1 -1
  15. package/dist/config/getOptimizeDeps.native.js +2 -1
  16. package/dist/config/getOptimizeDeps.native.js.map +1 -1
  17. package/dist/config/getViteServerConfig.mjs +13 -0
  18. package/dist/config/getViteServerConfig.mjs.map +1 -1
  19. package/dist/config/getViteServerConfig.native.js +15 -1
  20. package/dist/config/getViteServerConfig.native.js.map +1 -1
  21. package/dist/constants/defaults.mjs +4 -0
  22. package/dist/constants/defaults.mjs.map +1 -1
  23. package/dist/constants/defaults.native.js +4 -0
  24. package/dist/constants/defaults.native.js.map +1 -1
  25. package/dist/exports/build.native.js +1 -1
  26. package/dist/exports/build.native.js.map +1 -1
  27. package/dist/exports/clean.native.js +1 -1
  28. package/dist/exports/clean.native.js.map +1 -1
  29. package/dist/exports/createServer.native.js +2 -2
  30. package/dist/exports/createServer.native.js.map +1 -1
  31. package/dist/exports/dev.mjs +3 -0
  32. package/dist/exports/dev.mjs.map +1 -1
  33. package/dist/exports/dev.native.js +6 -3
  34. package/dist/exports/dev.native.js.map +1 -1
  35. package/dist/exports/loadEnv.native.js +1 -1
  36. package/dist/exports/loadEnv.native.js.map +1 -1
  37. package/dist/exports/patch.native.js +1 -1
  38. package/dist/exports/patch.native.js.map +1 -1
  39. package/dist/exports/prebuild.mjs +0 -22
  40. package/dist/exports/prebuild.mjs.map +1 -1
  41. package/dist/exports/prebuild.native.js +1 -23
  42. package/dist/exports/prebuild.native.js.map +1 -1
  43. package/dist/exports/prebuildWithoutExpo.mjs +1116 -178
  44. package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
  45. package/dist/exports/prebuildWithoutExpo.native.js +1592 -243
  46. package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
  47. package/dist/exports/runAndroid.native.js +1 -1
  48. package/dist/exports/runAndroid.native.js.map +1 -1
  49. package/dist/exports/runIos.native.js +1 -1
  50. package/dist/exports/runIos.native.js.map +1 -1
  51. package/dist/exports/serve.native.js +1 -1
  52. package/dist/exports/serve.native.js.map +1 -1
  53. package/dist/exports/serveStaticAssets.native.js +1 -1
  54. package/dist/exports/serveStaticAssets.native.js.map +1 -1
  55. package/dist/index.js +4 -1
  56. package/dist/index.mjs +4 -1
  57. package/dist/index.native.js +4 -1
  58. package/dist/native-source-contract.mjs +3 -0
  59. package/dist/native-source-contract.native.js +3 -0
  60. package/dist/patches/builtInDepPatches.mjs +0 -13
  61. package/dist/patches/builtInDepPatches.mjs.map +1 -1
  62. package/dist/patches/builtInDepPatches.native.js +0 -13
  63. package/dist/patches/builtInDepPatches.native.js.map +1 -1
  64. package/dist/plugins/autoDepOptimizePlugin.mjs +3 -2
  65. package/dist/plugins/autoDepOptimizePlugin.mjs.map +1 -1
  66. package/dist/plugins/autoDepOptimizePlugin.native.js +6 -3
  67. package/dist/plugins/autoDepOptimizePlugin.native.js.map +1 -1
  68. package/dist/plugins/backgroundComputationPlugin.mjs +27 -0
  69. package/dist/plugins/backgroundComputationPlugin.mjs.map +1 -0
  70. package/dist/plugins/backgroundComputationPlugin.native.js +32 -0
  71. package/dist/plugins/backgroundComputationPlugin.native.js.map +1 -0
  72. package/dist/plugins/reactNativeCommonJsPlugin.native.js +3 -3
  73. package/dist/plugins/reactNativeCommonJsPlugin.native.js.map +1 -1
  74. package/dist/plugins/reactNativeDevAssetPlugin.mjs +2 -1
  75. package/dist/plugins/reactNativeDevAssetPlugin.mjs.map +1 -1
  76. package/dist/plugins/reactNativeDevAssetPlugin.native.js +3 -2
  77. package/dist/plugins/reactNativeDevAssetPlugin.native.js.map +1 -1
  78. package/dist/plugins/reactNativeDevServer.mjs +87 -24
  79. package/dist/plugins/reactNativeDevServer.mjs.map +1 -1
  80. package/dist/plugins/reactNativeDevServer.native.js +162 -45
  81. package/dist/plugins/reactNativeDevServer.native.js.map +1 -1
  82. package/dist/plugins/workletImportsPlugin.mjs +9 -30
  83. package/dist/plugins/workletImportsPlugin.mjs.map +1 -1
  84. package/dist/plugins/workletImportsPlugin.native.js +10 -35
  85. package/dist/plugins/workletImportsPlugin.native.js.map +1 -1
  86. package/dist/rn-commands/bundle/buildBundle.mjs +3 -3
  87. package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
  88. package/dist/rn-commands/bundle/buildBundle.native.js +3 -3
  89. package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
  90. package/dist/runtime/hmr-client.native.js +3 -7
  91. package/dist/runtime/hmr-client.native.js.map +1 -1
  92. package/dist/runtime/hmr-runtime.native.js +32 -40
  93. package/dist/runtime/hmr-runtime.native.js.map +1 -1
  94. package/dist/serve/node.native.js +2 -2
  95. package/dist/serve/node.native.js.map +1 -1
  96. package/dist/swift-package-id.mjs +3 -0
  97. package/dist/swift-package-id.native.js +3 -0
  98. package/dist/user-interface/index.native.js +6 -6
  99. package/dist/user-interface/index.native.js.map +1 -1
  100. package/dist/utils/compileNativeDevBytecode.mjs +93 -0
  101. package/dist/utils/compileNativeDevBytecode.mjs.map +1 -0
  102. package/dist/utils/compileNativeDevBytecode.native.js +98 -0
  103. package/dist/utils/compileNativeDevBytecode.native.js.map +1 -0
  104. package/dist/utils/createNativeDevEngine.mjs +227 -20
  105. package/dist/utils/createNativeDevEngine.mjs.map +1 -1
  106. package/dist/utils/createNativeDevEngine.native.js +249 -37
  107. package/dist/utils/createNativeDevEngine.native.js.map +1 -1
  108. package/dist/utils/execSync.native.js +1 -1
  109. package/dist/utils/execSync.native.js.map +1 -1
  110. package/dist/utils/getServerEntry.native.js +2 -2
  111. package/dist/utils/getServerEntry.native.js.map +1 -1
  112. package/dist/utils/nativeRun.mjs +32 -16
  113. package/dist/utils/nativeRun.mjs.map +1 -1
  114. package/dist/utils/nativeRun.native.js +43 -18
  115. package/dist/utils/nativeRun.native.js.map +1 -1
  116. package/dist/utils/nativeSourceContract.mjs +1823 -0
  117. package/dist/utils/nativeSourceContract.mjs.map +1 -0
  118. package/dist/utils/nativeSourceContract.native.js +2425 -0
  119. package/dist/utils/nativeSourceContract.native.js.map +1 -0
  120. package/dist/utils/patches.native.js +15 -24
  121. package/dist/utils/patches.native.js.map +1 -1
  122. package/dist/utils/printServerUrls.native.js +1 -1
  123. package/dist/utils/printServerUrls.native.js.map +1 -1
  124. package/dist/utils/scanDepsToOptimize.mjs +7 -1
  125. package/dist/utils/scanDepsToOptimize.mjs.map +1 -1
  126. package/dist/utils/scanDepsToOptimize.native.js +27 -2
  127. package/dist/utils/scanDepsToOptimize.native.js.map +1 -1
  128. package/dist/utils/swiftPackageId.mjs +31 -2
  129. package/dist/utils/swiftPackageId.mjs.map +1 -1
  130. package/dist/utils/swiftPackageId.native.js +50 -2
  131. package/dist/utils/swiftPackageId.native.js.map +1 -1
  132. package/dist/vxrn-vite-plugin.native.js +1 -1
  133. package/dist/vxrn-vite-plugin.native.js.map +1 -1
  134. package/expo-plugin.cjs +792 -2
  135. package/native-project-patches.cjs +201 -10
  136. package/package.json +34 -15
  137. package/src/backgroundComputation.ts +220 -0
  138. package/src/backgroundComputationNative.ts +23 -0
  139. package/src/config/getBaseViteConfigOnly.ts +8 -9
  140. package/src/config/getOptimizeDeps.ts +3 -1
  141. package/src/config/getViteServerConfig.ts +16 -0
  142. package/src/config/glbAssets.test.ts +228 -0
  143. package/src/constants/defaults.ts +6 -0
  144. package/src/exports/dev.ts +5 -1
  145. package/src/exports/expoPlugin.test.mjs +337 -15
  146. package/src/exports/prebuild.ts +0 -31
  147. package/src/exports/prebuildWithoutExpo.test.ts +1588 -48
  148. package/src/exports/prebuildWithoutExpo.ts +1573 -213
  149. package/src/index.ts +8 -0
  150. package/src/native-source-contract.ts +16 -0
  151. package/src/patches/builtInDepPatches.ts +0 -21
  152. package/src/plugins/autoDepOptimizePlugin.ts +7 -2
  153. package/src/plugins/backgroundComputationPlugin.test.ts +77 -0
  154. package/src/plugins/backgroundComputationPlugin.ts +29 -0
  155. package/src/plugins/reactNativeDevAssetPlugin.ts +5 -1
  156. package/src/plugins/reactNativeDevServer.test.ts +74 -0
  157. package/src/plugins/reactNativeDevServer.ts +145 -28
  158. package/src/plugins/rnCodegenPlugin.test.ts +30 -0
  159. package/src/plugins/workletImportsPlugin.ts +19 -37
  160. package/src/rn-commands/bundle/buildBundle.ts +5 -3
  161. package/src/swift-package-id.ts +1 -0
  162. package/src/utils/compileNativeDevBytecode.test.ts +168 -0
  163. package/src/utils/compileNativeDevBytecode.ts +117 -0
  164. package/src/utils/createNativeDevEngine.test.ts +643 -18
  165. package/src/utils/createNativeDevEngine.ts +278 -48
  166. package/src/utils/nativeRun.test.ts +125 -23
  167. package/src/utils/nativeRun.ts +51 -23
  168. package/src/utils/nativeSourceArtifacts.test.ts +39 -0
  169. package/src/utils/nativeSourceContract.test.ts +600 -0
  170. package/src/utils/nativeSourceContract.ts +1897 -0
  171. package/src/utils/scanDepsToOptimize.test.ts +80 -0
  172. package/src/utils/scanDepsToOptimize.ts +18 -7
  173. package/src/utils/swiftPackageId.ts +25 -1
  174. package/types/backgroundComputation.d.ts +28 -0
  175. package/types/backgroundComputation.d.ts.map +1 -0
  176. package/types/backgroundComputationNative.d.ts +2 -0
  177. package/types/backgroundComputationNative.d.ts.map +1 -0
  178. package/types/config/getBaseViteConfigOnly.d.ts.map +1 -1
  179. package/types/config/getOptimizeDeps.d.ts.map +1 -1
  180. package/types/config/getViteServerConfig.d.ts.map +1 -1
  181. package/types/constants/defaults.d.ts.map +1 -1
  182. package/types/exports/dev.d.ts.map +1 -1
  183. package/types/exports/prebuild.d.ts.map +1 -1
  184. package/types/exports/prebuildWithoutExpo.d.ts +6 -0
  185. package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
  186. package/types/index.d.ts +2 -0
  187. package/types/index.d.ts.map +1 -1
  188. package/types/native-source-contract.d.ts +2 -0
  189. package/types/native-source-contract.d.ts.map +1 -0
  190. package/types/patches/builtInDepPatches.d.ts.map +1 -1
  191. package/types/plugins/autoDepOptimizePlugin.d.ts.map +1 -1
  192. package/types/plugins/backgroundComputationPlugin.d.ts +3 -0
  193. package/types/plugins/backgroundComputationPlugin.d.ts.map +1 -0
  194. package/types/plugins/reactNativeDevAssetPlugin.d.ts.map +1 -1
  195. package/types/plugins/reactNativeDevServer.d.ts.map +1 -1
  196. package/types/plugins/workletImportsPlugin.d.ts.map +1 -1
  197. package/types/rn-commands/bundle/buildBundle.d.ts.map +1 -1
  198. package/types/swift-package-id.d.ts +2 -0
  199. package/types/swift-package-id.d.ts.map +1 -0
  200. package/types/utils/compileNativeDevBytecode.d.ts +3 -0
  201. package/types/utils/compileNativeDevBytecode.d.ts.map +1 -0
  202. package/types/utils/createNativeDevEngine.d.ts +7 -22
  203. package/types/utils/createNativeDevEngine.d.ts.map +1 -1
  204. package/types/utils/nativeRun.d.ts.map +1 -1
  205. package/types/utils/nativeSourceContract.d.ts +121 -0
  206. package/types/utils/nativeSourceContract.d.ts.map +1 -0
  207. package/types/utils/scanDepsToOptimize.d.ts +1 -0
  208. package/types/utils/scanDepsToOptimize.d.ts.map +1 -1
  209. package/types/utils/swiftPackageId.d.ts +1 -0
  210. package/types/utils/swiftPackageId.d.ts.map +1 -1
@@ -14,7 +14,6 @@ export function getOptimizeDeps(mode: 'build' | 'serve') {
14
14
  'secure-json-parse',
15
15
 
16
16
  '@react-native/normalize-colors',
17
- '@vxrn/safe-area',
18
17
  '@vxrn/vendor/react-19-prod',
19
18
  '@vxrn/vendor/react-19',
20
19
  '@vxrn/vendor/react-19-compiler-runtime',
@@ -82,6 +81,9 @@ export function getOptimizeDeps(mode: 'build' | 'serve') {
82
81
  '@react-navigation/bottom-tabs',
83
82
  '@react-navigation/native-stack',
84
83
  'one',
84
+ 'one/drawer',
85
+ // one's own copy, by alias: prebundled with one so both share one context
86
+ 'react-native-safe-area-context',
85
87
  'styleq',
86
88
  'fbjs',
87
89
  '@vxrn/universal-color-scheme',
@@ -75,5 +75,21 @@ export async function getViteServerConfig(
75
75
  console.debug('merged config:', JSON.stringify(serverConfig, null, 2), `\n----\n`)
76
76
  }
77
77
 
78
+ // mergeConfig adds enumerable transport aliases to hmr. passing those aliases
79
+ // back to vite makes its next merge write deprecated fields even though we use ws.
80
+ if (typeof serverConfig.server?.hmr === 'object') {
81
+ for (const key of [
82
+ 'protocol',
83
+ 'host',
84
+ 'port',
85
+ 'path',
86
+ 'clientPort',
87
+ 'timeout',
88
+ 'server',
89
+ ] as const) {
90
+ delete serverConfig.server.hmr[key]
91
+ }
92
+ }
93
+
78
94
  return serverConfig
79
95
  }
@@ -0,0 +1,228 @@
1
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
2
+ import { join, relative } from 'node:path'
3
+ import { runInNewContext } from 'node:vm'
4
+ import { tmpdir } from 'node:os'
5
+ import { build, createServer } from 'vite'
6
+ import { expect, it } from 'vitest'
7
+ import { getBaseViteConfig } from './getBaseViteConfigOnly'
8
+ import { DEFAULT_ASSET_EXTS } from '../constants/defaults'
9
+ import { reactNativeDevAssetPlugin } from '../plugins/reactNativeDevAssetPlugin'
10
+ import { getNativeAssetContentType } from '../plugins/reactNativeDevServer'
11
+ import {
12
+ buildNativeBundle,
13
+ createNativeDevAssetRegistry,
14
+ createNativeDevEngine,
15
+ getNativeAssetData,
16
+ } from '../utils/createNativeDevEngine'
17
+
18
+ // a valid gltf 2 binary with a json chunk and binary payload.
19
+ function glbFixture() {
20
+ const json = Buffer.from(
21
+ JSON.stringify({ asset: { version: '2.0' }, buffers: [{ byteLength: 4 }] }).padEnd(
22
+ 80,
23
+ ' '
24
+ )
25
+ )
26
+ const header = Buffer.alloc(20)
27
+ header.write('glTF')
28
+ header.writeUInt32LE(2, 4)
29
+ header.writeUInt32LE(20 + json.length + 12, 8)
30
+ header.writeUInt32LE(json.length, 12)
31
+ header.writeUInt32LE(0x4e4f534a, 16)
32
+ const bin = Buffer.from([4, 0, 0, 0, 0x42, 0x49, 0x4e, 0, 0xff, 0, 0x80, 1])
33
+ return Buffer.concat([header, json, bin])
34
+ }
35
+
36
+ it('imports GLB as a web URL and preserves emitted binary bytes', async () => {
37
+ const root = await mkdtemp(join(import.meta.dirname, '.glb-web-'))
38
+ const bytes = glbFixture()
39
+ await writeFile(join(root, 'sofa.glb'), bytes)
40
+ await writeFile(
41
+ join(root, 'entry.js'),
42
+ "import model from './sofa.glb'; globalThis.model = model"
43
+ )
44
+ const config = await getBaseViteConfig({ root, mode: 'development' })
45
+ const server = await createServer({
46
+ ...config,
47
+ root,
48
+ configFile: false,
49
+ server: { port: 0, host: '127.0.0.1' },
50
+ })
51
+ try {
52
+ await server.listen()
53
+ const address = server.httpServer!.address() as { port: number }
54
+ const origin = `http://127.0.0.1:${address.port}`
55
+ const imported = await fetch(`${origin}/sofa.glb?import`)
56
+ expect(imported.status).toBe(200)
57
+ expect(await imported.text()).toContain('export default "/sofa.glb"')
58
+ const asset = await fetch(`${origin}/sofa.glb`)
59
+ expect(asset.headers.get('content-type')).toBe('model/gltf-binary')
60
+ expect(Buffer.from(await asset.arrayBuffer())).toEqual(bytes)
61
+ const result: any = await build({
62
+ ...config,
63
+ root,
64
+ configFile: false,
65
+ logLevel: 'silent',
66
+ build: {
67
+ write: false,
68
+ assetsInlineLimit: 0,
69
+ rolldownOptions: { input: join(root, 'entry.js') },
70
+ },
71
+ })
72
+ const emitted = result.output.find(
73
+ (output: any) => output.type === 'asset' && output.fileName.endsWith('.glb')
74
+ )
75
+ expect(Buffer.from(emitted.source)).toEqual(bytes)
76
+ expect(result.output.find((output: any) => output.type === 'chunk').code).toContain(
77
+ emitted.fileName
78
+ )
79
+ } finally {
80
+ await server.close()
81
+ await rm(root, { recursive: true, force: true })
82
+ }
83
+ })
84
+
85
+ it.each(['ios', 'android'] as const)(
86
+ 'registers GLB and copies release bytes on %s',
87
+ async (platform) => {
88
+ const root = await mkdtemp(join(tmpdir(), 'vxrn-glb-native-'))
89
+ const bytes = glbFixture()
90
+ await mkdir(join(root, 'models'))
91
+ await mkdir(join(root, 'node_modules/react-native/src'), { recursive: true })
92
+ await writeFile(
93
+ join(root, 'node_modules/react-native/package.json'),
94
+ JSON.stringify({
95
+ name: 'react-native',
96
+ exports: { './asset-registry': './src/asset-registry.js' },
97
+ })
98
+ )
99
+ await writeFile(
100
+ join(root, 'node_modules/react-native/src/asset-registry.js'),
101
+ 'const assets = []; export function registerAsset(asset) { return assets.push(asset) }; export function getAssetByID(id) { return assets[id - 1] }'
102
+ )
103
+ const file = join(root, 'models/sofa.glb')
104
+ await writeFile(file, bytes)
105
+ await writeFile(
106
+ join(root, 'entry.js'),
107
+ "import model from './models/sofa.glb'; import { getAssetByID } from 'react-native/asset-registry'; globalThis.model = getAssetByID(model)"
108
+ )
109
+ try {
110
+ const result = await buildNativeBundle({
111
+ root,
112
+ entryFile: 'entry.js',
113
+ platform,
114
+ assetsDest: join(root, 'output'),
115
+ })
116
+ const context: any = { console }
117
+ runInNewContext(result.code, context)
118
+ const registered = context.model
119
+ expect(registered).toMatchObject({ name: 'sofa', type: 'glb', scales: [1] })
120
+ expect(registered.width).toBeUndefined()
121
+ expect(registered.height).toBeUndefined()
122
+ const data = await getNativeAssetData(file, root, platform)
123
+ expect(registered.hash).toBe(data.hash)
124
+ const registry = createNativeDevAssetRegistry()
125
+ registry.register(registered)
126
+ const devAsset = registry.resolve(
127
+ `${registered.httpServerLocation}/sofa.glb`,
128
+ registered.hash
129
+ )!
130
+ expect(await readFile(devAsset.filePath)).toEqual(bytes)
131
+ expect(
132
+ registry.resolve(`${registered.httpServerLocation}/sofa.glb`, 'stale')
133
+ ).toBeUndefined()
134
+ expect(getNativeAssetContentType(devAsset.type)).toBe('model/gltf-binary')
135
+ const native = await createNativeDevEngine({
136
+ root,
137
+ port: 0,
138
+ platform,
139
+ plugins: [
140
+ {
141
+ name: 'glb-fixture-entry',
142
+ transform(_code, id) {
143
+ if (id.endsWith('/__virtual-native-entry.tsx')) return "import './entry.js'"
144
+ },
145
+ },
146
+ ],
147
+ })
148
+ try {
149
+ await native.getBundle()
150
+ const served = native.getAsset(
151
+ `${registered.httpServerLocation}/sofa.glb`,
152
+ registered.hash
153
+ )!
154
+ expect(await readFile(served.filePath)).toEqual(bytes)
155
+ expect(served.hash).toBe(registered.hash)
156
+ expect(served.type).toBe('glb')
157
+ } finally {
158
+ await native.close()
159
+ }
160
+ const copied = platform === 'ios' ? 'assets/models/sofa.glb' : 'raw/models_sofa.glb'
161
+ expect(await readFile(join(root, 'output', copied))).toEqual(bytes)
162
+
163
+ const plugin = reactNativeDevAssetPlugin({
164
+ assetExts: DEFAULT_ASSET_EXTS,
165
+ mode: 'prod',
166
+ assetsDest: join(root, 'legacy-output'),
167
+ })
168
+ ;(plugin.configResolved as Function)({ root })
169
+ const code = await (plugin.load as Function).call(
170
+ { environment: { name: platform } },
171
+ file
172
+ )
173
+ expect(code).toContain('AssetRegistry.registerAsset')
174
+ expect(await readFile(join(root, 'legacy-output/assets/models/sofa.glb'))).toEqual(
175
+ bytes
176
+ )
177
+ } finally {
178
+ await rm(root, { recursive: true, force: true })
179
+ }
180
+ }
181
+ )
182
+
183
+ it('serves legacy native dev GLB bytes with their content type', async () => {
184
+ const root = await mkdtemp(join(import.meta.dirname, '.glb-dev-'))
185
+ const file = join(root, 'sofa.glb')
186
+ const bytes = glbFixture()
187
+ await writeFile(file, bytes)
188
+ const plugin = reactNativeDevAssetPlugin({ assetExts: DEFAULT_ASSET_EXTS, mode: 'dev' })
189
+ let middleware: Function
190
+ ;(plugin.configResolved as Function)({ root: process.cwd() })
191
+ ;(plugin.configureServer as Function)({
192
+ config: {
193
+ logger: {
194
+ error: (error: string) => {
195
+ throw new Error(error)
196
+ },
197
+ },
198
+ },
199
+ middlewares: {
200
+ use: (handler: Function) => {
201
+ middleware = handler
202
+ },
203
+ },
204
+ })
205
+ const headers: Record<string, string> = {}
206
+ let served: Buffer | undefined
207
+ try {
208
+ await middleware!(
209
+ { url: `/__vxrn_dev_native_assets/${relative(process.cwd(), file)}` },
210
+ {
211
+ setHeader: (name: string, value: string) => {
212
+ headers[name] = value
213
+ },
214
+ write: (value: Buffer) => {
215
+ served = value
216
+ },
217
+ end() {},
218
+ },
219
+ () => {
220
+ throw new Error('asset request not handled')
221
+ }
222
+ )
223
+ expect(served).toEqual(bytes)
224
+ expect(headers['content-type']).toBe('model/gltf-binary')
225
+ } finally {
226
+ await rm(root, { recursive: true, force: true })
227
+ }
228
+ })
@@ -9,6 +9,10 @@ export const DEFAULT_ASSET_EXTS = [
9
9
  'psd',
10
10
  'svg',
11
11
  'webp',
12
+ // dotLottie animation archives
13
+ 'lottie',
14
+ // binary gltf models
15
+ 'glb',
12
16
  // Video formats
13
17
  'm4v',
14
18
  'mov',
@@ -32,6 +36,8 @@ export const DEFAULT_ASSET_EXTS = [
32
36
  // Font formats
33
37
  'otf',
34
38
  'ttf',
39
+ 'woff',
40
+ 'woff2',
35
41
  // Archives (virtual files)
36
42
  'zip',
37
43
  ]
@@ -2,7 +2,7 @@ import { execFileSync } from 'node:child_process'
2
2
  import FSExtra from 'fs-extra'
3
3
  import colors from 'picocolors'
4
4
  import { debounce } from 'perfect-debounce'
5
- import { normalizePath, type ViteDevServer } from 'vite'
5
+ import { normalizePath, type PluginOption, type ViteDevServer } from 'vite'
6
6
  import type { VXRNOptions } from '../types'
7
7
 
8
8
  const { ensureDir } = FSExtra
@@ -133,6 +133,7 @@ export default defineConfig({
133
133
  process.exit(0)
134
134
  }
135
135
 
136
+ let extraPlugins: PluginOption[] = []
136
137
  if (optionsIn.extraConfig) {
137
138
  const { resolve } = await import('node:path')
138
139
  const extraConfigPath = resolve(optionsIn.extraConfig)
@@ -142,6 +143,7 @@ export default defineConfig({
142
143
  )
143
144
  if (extraResult?.config) {
144
145
  const { mergeConfig } = await import('vite')
146
+ extraPlugins = extraResult.config.plugins || []
145
147
  config = mergeConfig(config, extraResult.config)
146
148
  console.info(colors.cyan(`Merged extra config from ${extraConfigPath}`))
147
149
  } else {
@@ -195,6 +197,8 @@ export default defineConfig({
195
197
  await ensureDir(`${cacheDir}/compiler-cache`)
196
198
 
197
199
  const serverConfig = await getViteServerConfig(options, config)
200
+ // the base config reloads through vite; extra config plugins must travel inline.
201
+ serverConfig.plugins = [...(serverConfig.plugins || []), ...extraPlugins]
198
202
 
199
203
  let viteServer: ViteDevServer | null = null
200
204
  // Track if server is closing to prevent work during shutdown