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.
- package/dist/backgroundComputation.mjs +145 -0
- package/dist/backgroundComputation.mjs.map +1 -0
- package/dist/backgroundComputation.native.js +163 -0
- package/dist/backgroundComputation.native.js.map +1 -0
- package/dist/backgroundComputationNative.mjs +16 -0
- package/dist/backgroundComputationNative.mjs.map +1 -0
- package/dist/backgroundComputationNative.native.js +18 -0
- package/dist/backgroundComputationNative.native.js.map +1 -0
- package/dist/config/getBaseViteConfigOnly.mjs +6 -10
- package/dist/config/getBaseViteConfigOnly.mjs.map +1 -1
- package/dist/config/getBaseViteConfigOnly.native.js +6 -10
- package/dist/config/getBaseViteConfigOnly.native.js.map +1 -1
- package/dist/config/getOptimizeDeps.mjs +2 -1
- package/dist/config/getOptimizeDeps.mjs.map +1 -1
- package/dist/config/getOptimizeDeps.native.js +2 -1
- package/dist/config/getOptimizeDeps.native.js.map +1 -1
- package/dist/config/getViteServerConfig.mjs +13 -0
- package/dist/config/getViteServerConfig.mjs.map +1 -1
- package/dist/config/getViteServerConfig.native.js +15 -1
- package/dist/config/getViteServerConfig.native.js.map +1 -1
- package/dist/constants/defaults.mjs +4 -0
- package/dist/constants/defaults.mjs.map +1 -1
- package/dist/constants/defaults.native.js +4 -0
- package/dist/constants/defaults.native.js.map +1 -1
- package/dist/exports/build.native.js +1 -1
- package/dist/exports/build.native.js.map +1 -1
- package/dist/exports/clean.native.js +1 -1
- package/dist/exports/clean.native.js.map +1 -1
- package/dist/exports/createServer.native.js +2 -2
- package/dist/exports/createServer.native.js.map +1 -1
- package/dist/exports/dev.mjs +3 -0
- package/dist/exports/dev.mjs.map +1 -1
- package/dist/exports/dev.native.js +6 -3
- package/dist/exports/dev.native.js.map +1 -1
- package/dist/exports/loadEnv.native.js +1 -1
- package/dist/exports/loadEnv.native.js.map +1 -1
- package/dist/exports/patch.native.js +1 -1
- package/dist/exports/patch.native.js.map +1 -1
- package/dist/exports/prebuild.mjs +0 -22
- package/dist/exports/prebuild.mjs.map +1 -1
- package/dist/exports/prebuild.native.js +1 -23
- package/dist/exports/prebuild.native.js.map +1 -1
- package/dist/exports/prebuildWithoutExpo.mjs +1116 -178
- package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
- package/dist/exports/prebuildWithoutExpo.native.js +1592 -243
- package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
- package/dist/exports/runAndroid.native.js +1 -1
- package/dist/exports/runAndroid.native.js.map +1 -1
- package/dist/exports/runIos.native.js +1 -1
- package/dist/exports/runIos.native.js.map +1 -1
- package/dist/exports/serve.native.js +1 -1
- package/dist/exports/serve.native.js.map +1 -1
- package/dist/exports/serveStaticAssets.native.js +1 -1
- package/dist/exports/serveStaticAssets.native.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.mjs +4 -1
- package/dist/index.native.js +4 -1
- package/dist/native-source-contract.mjs +3 -0
- package/dist/native-source-contract.native.js +3 -0
- package/dist/patches/builtInDepPatches.mjs +0 -13
- package/dist/patches/builtInDepPatches.mjs.map +1 -1
- package/dist/patches/builtInDepPatches.native.js +0 -13
- package/dist/patches/builtInDepPatches.native.js.map +1 -1
- package/dist/plugins/autoDepOptimizePlugin.mjs +3 -2
- package/dist/plugins/autoDepOptimizePlugin.mjs.map +1 -1
- package/dist/plugins/autoDepOptimizePlugin.native.js +6 -3
- package/dist/plugins/autoDepOptimizePlugin.native.js.map +1 -1
- package/dist/plugins/backgroundComputationPlugin.mjs +27 -0
- package/dist/plugins/backgroundComputationPlugin.mjs.map +1 -0
- package/dist/plugins/backgroundComputationPlugin.native.js +32 -0
- package/dist/plugins/backgroundComputationPlugin.native.js.map +1 -0
- package/dist/plugins/reactNativeCommonJsPlugin.native.js +3 -3
- package/dist/plugins/reactNativeCommonJsPlugin.native.js.map +1 -1
- package/dist/plugins/reactNativeDevAssetPlugin.mjs +2 -1
- package/dist/plugins/reactNativeDevAssetPlugin.mjs.map +1 -1
- package/dist/plugins/reactNativeDevAssetPlugin.native.js +3 -2
- package/dist/plugins/reactNativeDevAssetPlugin.native.js.map +1 -1
- package/dist/plugins/reactNativeDevServer.mjs +87 -24
- package/dist/plugins/reactNativeDevServer.mjs.map +1 -1
- package/dist/plugins/reactNativeDevServer.native.js +162 -45
- package/dist/plugins/reactNativeDevServer.native.js.map +1 -1
- package/dist/plugins/workletImportsPlugin.mjs +9 -30
- package/dist/plugins/workletImportsPlugin.mjs.map +1 -1
- package/dist/plugins/workletImportsPlugin.native.js +10 -35
- package/dist/plugins/workletImportsPlugin.native.js.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.mjs +3 -3
- package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
- package/dist/rn-commands/bundle/buildBundle.native.js +3 -3
- package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
- package/dist/runtime/hmr-client.native.js +3 -7
- package/dist/runtime/hmr-client.native.js.map +1 -1
- package/dist/runtime/hmr-runtime.native.js +32 -40
- package/dist/runtime/hmr-runtime.native.js.map +1 -1
- package/dist/serve/node.native.js +2 -2
- package/dist/serve/node.native.js.map +1 -1
- package/dist/swift-package-id.mjs +3 -0
- package/dist/swift-package-id.native.js +3 -0
- package/dist/user-interface/index.native.js +6 -6
- package/dist/user-interface/index.native.js.map +1 -1
- package/dist/utils/compileNativeDevBytecode.mjs +93 -0
- package/dist/utils/compileNativeDevBytecode.mjs.map +1 -0
- package/dist/utils/compileNativeDevBytecode.native.js +98 -0
- package/dist/utils/compileNativeDevBytecode.native.js.map +1 -0
- package/dist/utils/createNativeDevEngine.mjs +227 -20
- package/dist/utils/createNativeDevEngine.mjs.map +1 -1
- package/dist/utils/createNativeDevEngine.native.js +249 -37
- package/dist/utils/createNativeDevEngine.native.js.map +1 -1
- package/dist/utils/execSync.native.js +1 -1
- package/dist/utils/execSync.native.js.map +1 -1
- package/dist/utils/getServerEntry.native.js +2 -2
- package/dist/utils/getServerEntry.native.js.map +1 -1
- package/dist/utils/nativeRun.mjs +32 -16
- package/dist/utils/nativeRun.mjs.map +1 -1
- package/dist/utils/nativeRun.native.js +43 -18
- package/dist/utils/nativeRun.native.js.map +1 -1
- package/dist/utils/nativeSourceContract.mjs +1823 -0
- package/dist/utils/nativeSourceContract.mjs.map +1 -0
- package/dist/utils/nativeSourceContract.native.js +2425 -0
- package/dist/utils/nativeSourceContract.native.js.map +1 -0
- package/dist/utils/patches.native.js +15 -24
- package/dist/utils/patches.native.js.map +1 -1
- package/dist/utils/printServerUrls.native.js +1 -1
- package/dist/utils/printServerUrls.native.js.map +1 -1
- package/dist/utils/scanDepsToOptimize.mjs +7 -1
- package/dist/utils/scanDepsToOptimize.mjs.map +1 -1
- package/dist/utils/scanDepsToOptimize.native.js +27 -2
- package/dist/utils/scanDepsToOptimize.native.js.map +1 -1
- package/dist/utils/swiftPackageId.mjs +31 -2
- package/dist/utils/swiftPackageId.mjs.map +1 -1
- package/dist/utils/swiftPackageId.native.js +50 -2
- package/dist/utils/swiftPackageId.native.js.map +1 -1
- package/dist/vxrn-vite-plugin.native.js +1 -1
- package/dist/vxrn-vite-plugin.native.js.map +1 -1
- package/expo-plugin.cjs +792 -2
- package/native-project-patches.cjs +201 -10
- package/package.json +34 -15
- package/src/backgroundComputation.ts +220 -0
- package/src/backgroundComputationNative.ts +23 -0
- package/src/config/getBaseViteConfigOnly.ts +8 -9
- package/src/config/getOptimizeDeps.ts +3 -1
- package/src/config/getViteServerConfig.ts +16 -0
- package/src/config/glbAssets.test.ts +228 -0
- package/src/constants/defaults.ts +6 -0
- package/src/exports/dev.ts +5 -1
- package/src/exports/expoPlugin.test.mjs +337 -15
- package/src/exports/prebuild.ts +0 -31
- package/src/exports/prebuildWithoutExpo.test.ts +1588 -48
- package/src/exports/prebuildWithoutExpo.ts +1573 -213
- package/src/index.ts +8 -0
- package/src/native-source-contract.ts +16 -0
- package/src/patches/builtInDepPatches.ts +0 -21
- package/src/plugins/autoDepOptimizePlugin.ts +7 -2
- package/src/plugins/backgroundComputationPlugin.test.ts +77 -0
- package/src/plugins/backgroundComputationPlugin.ts +29 -0
- package/src/plugins/reactNativeDevAssetPlugin.ts +5 -1
- package/src/plugins/reactNativeDevServer.test.ts +74 -0
- package/src/plugins/reactNativeDevServer.ts +145 -28
- package/src/plugins/rnCodegenPlugin.test.ts +30 -0
- package/src/plugins/workletImportsPlugin.ts +19 -37
- package/src/rn-commands/bundle/buildBundle.ts +5 -3
- package/src/swift-package-id.ts +1 -0
- package/src/utils/compileNativeDevBytecode.test.ts +168 -0
- package/src/utils/compileNativeDevBytecode.ts +117 -0
- package/src/utils/createNativeDevEngine.test.ts +643 -18
- package/src/utils/createNativeDevEngine.ts +278 -48
- package/src/utils/nativeRun.test.ts +125 -23
- package/src/utils/nativeRun.ts +51 -23
- package/src/utils/nativeSourceArtifacts.test.ts +39 -0
- package/src/utils/nativeSourceContract.test.ts +600 -0
- package/src/utils/nativeSourceContract.ts +1897 -0
- package/src/utils/scanDepsToOptimize.test.ts +80 -0
- package/src/utils/scanDepsToOptimize.ts +18 -7
- package/src/utils/swiftPackageId.ts +25 -1
- package/types/backgroundComputation.d.ts +28 -0
- package/types/backgroundComputation.d.ts.map +1 -0
- package/types/backgroundComputationNative.d.ts +2 -0
- package/types/backgroundComputationNative.d.ts.map +1 -0
- package/types/config/getBaseViteConfigOnly.d.ts.map +1 -1
- package/types/config/getOptimizeDeps.d.ts.map +1 -1
- package/types/config/getViteServerConfig.d.ts.map +1 -1
- package/types/constants/defaults.d.ts.map +1 -1
- package/types/exports/dev.d.ts.map +1 -1
- package/types/exports/prebuild.d.ts.map +1 -1
- package/types/exports/prebuildWithoutExpo.d.ts +6 -0
- package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/native-source-contract.d.ts +2 -0
- package/types/native-source-contract.d.ts.map +1 -0
- package/types/patches/builtInDepPatches.d.ts.map +1 -1
- package/types/plugins/autoDepOptimizePlugin.d.ts.map +1 -1
- package/types/plugins/backgroundComputationPlugin.d.ts +3 -0
- package/types/plugins/backgroundComputationPlugin.d.ts.map +1 -0
- package/types/plugins/reactNativeDevAssetPlugin.d.ts.map +1 -1
- package/types/plugins/reactNativeDevServer.d.ts.map +1 -1
- package/types/plugins/workletImportsPlugin.d.ts.map +1 -1
- package/types/rn-commands/bundle/buildBundle.d.ts.map +1 -1
- package/types/swift-package-id.d.ts +2 -0
- package/types/swift-package-id.d.ts.map +1 -0
- package/types/utils/compileNativeDevBytecode.d.ts +3 -0
- package/types/utils/compileNativeDevBytecode.d.ts.map +1 -0
- package/types/utils/createNativeDevEngine.d.ts +7 -22
- package/types/utils/createNativeDevEngine.d.ts.map +1 -1
- package/types/utils/nativeRun.d.ts.map +1 -1
- package/types/utils/nativeSourceContract.d.ts +121 -0
- package/types/utils/nativeSourceContract.d.ts.map +1 -0
- package/types/utils/scanDepsToOptimize.d.ts +1 -0
- package/types/utils/scanDepsToOptimize.d.ts.map +1 -1
- package/types/utils/swiftPackageId.d.ts +1 -0
- package/types/utils/swiftPackageId.d.ts.map +1 -1
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import { createHash } from 'node:crypto'
|
|
3
|
+
import {
|
|
4
|
+
existsSync,
|
|
5
|
+
mkdtempSync,
|
|
6
|
+
mkdirSync,
|
|
7
|
+
readFileSync,
|
|
8
|
+
rmSync,
|
|
9
|
+
symlinkSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
} from 'node:fs'
|
|
2
12
|
import { createRequire } from 'node:module'
|
|
3
13
|
import { tmpdir } from 'node:os'
|
|
4
14
|
import { join } from 'node:path'
|
|
@@ -35,6 +45,34 @@ end
|
|
|
35
45
|
`
|
|
36
46
|
|
|
37
47
|
describe('vxrn Expo project patches', () => {
|
|
48
|
+
it('keeps WebGPU header resolution inside its own CocoaPods target', () => {
|
|
49
|
+
const generated = patches.injectWebGPUHeaderPathsIntoPodfile(podfile)
|
|
50
|
+
expect(patches.injectWebGPUHeaderPathsIntoPodfile(generated)).toBe(generated)
|
|
51
|
+
const result = JSON.parse(execFileSync('ruby', ['-rjson', '-e', `
|
|
52
|
+
Config = Struct.new(:build_settings)
|
|
53
|
+
Target = Struct.new(:name, :build_configurations)
|
|
54
|
+
Project = Struct.new(:targets)
|
|
55
|
+
Installer = Struct.new(:pods_project)
|
|
56
|
+
gpu = Config.new({'USE_HEADERMAP' => 'NO', 'HEADER_SEARCH_PATHS' => ['$(inherited)', '/dawn/include']})
|
|
57
|
+
unrelated = Config.new({'HEADER_SEARCH_PATHS' => '/other/include'})
|
|
58
|
+
$installer = Installer.new(Project.new([Target.new('react-native-webgpu', [gpu]), Target.new('other', [unrelated])]))
|
|
59
|
+
def target(name); yield; end
|
|
60
|
+
def use_native_modules!; {}; end
|
|
61
|
+
def post_install; yield $installer; end
|
|
62
|
+
def react_native_post_install(installer); end
|
|
63
|
+
eval(STDIN.read)
|
|
64
|
+
puts JSON.generate([gpu.build_settings, unrelated.build_settings])
|
|
65
|
+
`], { input: generated, encoding: 'utf8' }))
|
|
66
|
+
expect(result[0].USE_HEADERMAP).toBe('NO')
|
|
67
|
+
expect(result[0].HEADER_SEARCH_PATHS).toEqual([
|
|
68
|
+
'$(inherited)', '/dawn/include',
|
|
69
|
+
'$(PODS_TARGET_SRCROOT)/cpp/rnwgpu',
|
|
70
|
+
'$(PODS_TARGET_SRCROOT)/cpp/rnwgpu/api',
|
|
71
|
+
'$(PODS_TARGET_SRCROOT)/cpp/rnwgpu/api/descriptors',
|
|
72
|
+
'$(PODS_TARGET_SRCROOT)/cpp/jsi',
|
|
73
|
+
])
|
|
74
|
+
expect(result[1]).toEqual({ HEADER_SEARCH_PATHS: '/other/include' })
|
|
75
|
+
})
|
|
38
76
|
it('replaces Expo bundle defaults with One bundle configuration', () => {
|
|
39
77
|
let result =
|
|
40
78
|
patches.removeExpoDefaultsFromBundleReactNativeShellScript(expoBundlePhase)
|
|
@@ -56,10 +94,13 @@ describe('vxrn Expo project patches', () => {
|
|
|
56
94
|
let result = patches.replaceAppBuildGradleReactBlock(input)
|
|
57
95
|
result = patches.addDepsPatchToAppBuildGradle(result)
|
|
58
96
|
|
|
59
|
-
expect(result).toContain('cliFile =
|
|
97
|
+
expect(result).toContain('cliFile = file(providers.exec {')
|
|
60
98
|
expect(result).toContain('autolinkLibrariesWithApp()')
|
|
61
99
|
expect(result).not.toContain('entryFile = file("../index.js")')
|
|
62
100
|
expect(result).toContain('[vxrn/one] ensure patches are applied')
|
|
101
|
+
expect(patches.addDepsPatchToAppBuildGradle(
|
|
102
|
+
patches.replaceAppBuildGradleReactBlock(result)
|
|
103
|
+
)).toBe(result)
|
|
63
104
|
})
|
|
64
105
|
|
|
65
106
|
it('applies the shared Podfile patches idempotently', () => {
|
|
@@ -92,24 +133,117 @@ class MainActivity : ReactActivity() {
|
|
|
92
133
|
})
|
|
93
134
|
})
|
|
94
135
|
|
|
136
|
+
function expoProject() {
|
|
137
|
+
const projectRoot = mkdtempSync(join(tmpdir(), 'vxrn-expo-plugin-'))
|
|
138
|
+
temporaryDirectories.push(projectRoot)
|
|
139
|
+
writeFileSync(join(projectRoot, 'package.json'), '{"private":true}')
|
|
140
|
+
const configPluginsRoot = createRequire(import.meta.url).resolve(
|
|
141
|
+
'@expo/config-plugins/package.json'
|
|
142
|
+
)
|
|
143
|
+
const scopedDirectory = join(projectRoot, 'node_modules', '@expo')
|
|
144
|
+
mkdirSync(scopedDirectory, { recursive: true })
|
|
145
|
+
symlinkSync(
|
|
146
|
+
configPluginsRoot.slice(0, -'/package.json'.length),
|
|
147
|
+
join(scopedDirectory, 'config-plugins'),
|
|
148
|
+
'dir'
|
|
149
|
+
)
|
|
150
|
+
return projectRoot
|
|
151
|
+
}
|
|
152
|
+
|
|
95
153
|
describe('vxrn/expo-plugin', () => {
|
|
154
|
+
it('combines background location and audio modes', async () => {
|
|
155
|
+
const projectRoot = expoProject()
|
|
156
|
+
const config = withVxrn(
|
|
157
|
+
{ name: 'TestApp', slug: 'test-app', _internal: { projectRoot } },
|
|
158
|
+
{ location: { whenInUse: 'Track a hike.', background: true }, audio: { background: true } }
|
|
159
|
+
)
|
|
160
|
+
const result = await config.mods.ios.infoPlist({
|
|
161
|
+
...config,
|
|
162
|
+
modRequest: { projectRoot, platform: 'ios', modName: 'infoPlist', projectName: 'TestApp', introspect: false },
|
|
163
|
+
modResults: {},
|
|
164
|
+
})
|
|
165
|
+
expect(result.modResults.NSLocationWhenInUseUsageDescription).toBe('Track a hike.')
|
|
166
|
+
expect(result.modResults.UIBackgroundModes).toEqual(['audio', 'location'])
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it('stamps separate Photos save and read usage descriptions', async () => {
|
|
170
|
+
const projectRoot = expoProject()
|
|
171
|
+
const config = withVxrn(
|
|
172
|
+
{ name: 'TestApp', slug: 'test-app', _internal: { projectRoot } },
|
|
173
|
+
{ photoLibrary: { addOnly: 'Save a photo.', readWrite: 'Browse photos.' } }
|
|
174
|
+
)
|
|
175
|
+
const result = await config.mods.ios.infoPlist({
|
|
176
|
+
...config,
|
|
177
|
+
modRequest: { projectRoot, platform: 'ios', modName: 'infoPlist', projectName: 'TestApp', introspect: false },
|
|
178
|
+
modResults: {},
|
|
179
|
+
})
|
|
180
|
+
expect(result.modResults.NSPhotoLibraryAddUsageDescription).toBe('Save a photo.')
|
|
181
|
+
expect(result.modResults.NSPhotoLibraryUsageDescription).toBe('Browse photos.')
|
|
182
|
+
expect(result.modResults.PHPhotoLibraryPreventAutomaticLimitedAccessAlert).toBe(true)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('stamps the same notification entries as one prebuild', async () => {
|
|
186
|
+
const projectRoot = expoProject()
|
|
187
|
+
const config = withVxrn(
|
|
188
|
+
{
|
|
189
|
+
name: 'TestApp',
|
|
190
|
+
slug: 'test-app',
|
|
191
|
+
_internal: { projectRoot },
|
|
192
|
+
},
|
|
193
|
+
{ notifications: { push: true } }
|
|
194
|
+
)
|
|
195
|
+
const modRequest = { projectRoot, introspect: false, projectName: 'TestApp' }
|
|
196
|
+
const run = (platform, mod, modResults) =>
|
|
197
|
+
config.mods[platform][mod]({
|
|
198
|
+
...config,
|
|
199
|
+
modRequest: { ...modRequest, platform, modName: mod },
|
|
200
|
+
modResults,
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
const infoPlist = (await run('ios', 'infoPlist', {})).modResults
|
|
204
|
+
expect(infoPlist[patches.ONE_NOTIFICATIONS.enabledInfoPlistKey]).toBe(true)
|
|
205
|
+
expect(infoPlist[patches.ONE_NOTIFICATIONS.pushInfoPlistKey]).toBe(true)
|
|
206
|
+
const entitlements = (await run('ios', 'entitlements', {})).modResults
|
|
207
|
+
expect(entitlements['aps-environment']).toBe('development')
|
|
208
|
+
|
|
209
|
+
const manifest = {
|
|
210
|
+
manifest: {
|
|
211
|
+
$: {},
|
|
212
|
+
'uses-permission': [{ $: { 'android:name': 'android.permission.INTERNET' } }],
|
|
213
|
+
application: [{ $: { 'android:name': '.MainApplication' }, activity: [] }],
|
|
214
|
+
},
|
|
215
|
+
}
|
|
216
|
+
const once = (await run('android', 'manifest', manifest)).modResults
|
|
217
|
+
const twice = (await run('android', 'manifest', once)).modResults
|
|
218
|
+
const application = twice.manifest.application[0]
|
|
219
|
+
expect(twice.manifest['uses-permission'].map((p) => p.$['android:name'])).toEqual([
|
|
220
|
+
'android.permission.INTERNET',
|
|
221
|
+
...patches.ONE_NOTIFICATIONS.androidPermissions,
|
|
222
|
+
])
|
|
223
|
+
expect(application.receiver.map((r) => r.$['android:name'])).toEqual([
|
|
224
|
+
patches.ONE_NOTIFICATIONS.receiver,
|
|
225
|
+
])
|
|
226
|
+
expect(application.service.map((r) => r.$['android:name'])).toEqual([
|
|
227
|
+
patches.ONE_NOTIFICATIONS.pushService,
|
|
228
|
+
])
|
|
229
|
+
|
|
230
|
+
const properties = (
|
|
231
|
+
await run('android', 'gradleProperties', [
|
|
232
|
+
{ type: 'property', key: 'hermesEnabled', value: 'true' },
|
|
233
|
+
])
|
|
234
|
+
).modResults
|
|
235
|
+
expect(properties).toContainEqual({
|
|
236
|
+
type: 'property',
|
|
237
|
+
key: patches.ONE_NOTIFICATIONS.pushGradleProperty,
|
|
238
|
+
value: 'true',
|
|
239
|
+
})
|
|
240
|
+
})
|
|
241
|
+
|
|
96
242
|
it('resolves Expo config plugins from the app and binds the dangerous mod', async () => {
|
|
97
|
-
const projectRoot =
|
|
98
|
-
temporaryDirectories.push(projectRoot)
|
|
243
|
+
const projectRoot = expoProject()
|
|
99
244
|
const iosRoot = join(projectRoot, 'ios')
|
|
100
245
|
mkdirSync(iosRoot, { recursive: true })
|
|
101
246
|
writeFileSync(join(iosRoot, 'Podfile'), podfile)
|
|
102
|
-
writeFileSync(join(projectRoot, 'package.json'), '{"private":true}')
|
|
103
|
-
const workspaceRequire = createRequire(import.meta.url)
|
|
104
|
-
const configPluginsRoot = workspaceRequire.resolve(
|
|
105
|
-
'@expo/config-plugins/package.json'
|
|
106
|
-
)
|
|
107
|
-
const scopedDirectory = join(projectRoot, 'node_modules', '@expo')
|
|
108
|
-
mkdirSync(scopedDirectory, { recursive: true })
|
|
109
|
-
const packageDirectory = configPluginsRoot.slice(0, -'/package.json'.length)
|
|
110
|
-
await import('node:fs/promises').then(({ symlink }) =>
|
|
111
|
-
symlink(packageDirectory, join(scopedDirectory, 'config-plugins'), 'dir')
|
|
112
|
-
)
|
|
113
247
|
|
|
114
248
|
const config = withVxrn({
|
|
115
249
|
name: 'TestApp',
|
|
@@ -137,3 +271,191 @@ describe('vxrn/expo-plugin', () => {
|
|
|
137
271
|
expect(result).toContain("ENV['RNS_GAMMA_ENABLED'] ||= '1'")
|
|
138
272
|
})
|
|
139
273
|
})
|
|
274
|
+
|
|
275
|
+
function nativeSourceProject() {
|
|
276
|
+
const projectRoot = expoProject()
|
|
277
|
+
const packageDir = join(projectRoot, 'native', 'Showcase')
|
|
278
|
+
mkdirSync(packageDir, { recursive: true })
|
|
279
|
+
writeFileSync(
|
|
280
|
+
join(packageDir, 'Package.swift'),
|
|
281
|
+
'// swift-tools-version: 6.2\nimport PackageDescription\n\nlet package = Package(\n name: "Showcase",\n platforms: [.iOS(.v17)],\n targets: [.executableTarget(name: "Showcase", path: ".", swiftSettings: [.swiftLanguageMode(.v6)])],\n)\n'
|
|
282
|
+
)
|
|
283
|
+
writeFileSync(
|
|
284
|
+
join(packageDir, 'Device.swift'),
|
|
285
|
+
'@MainActor final class Device: PeachModule {\n init() {}\n\n func info() -> [String: String] {\n ["model": "expo"]\n }\n}\n'
|
|
286
|
+
)
|
|
287
|
+
writeFileSync(
|
|
288
|
+
join(projectRoot, 'Device.kt'),
|
|
289
|
+
'object Device : OneModule {\n fun info(): Map<String, String> = mapOf("model" to "expo")\n}\n'
|
|
290
|
+
)
|
|
291
|
+
const iosRoot = join(projectRoot, 'ios')
|
|
292
|
+
const androidRoot = join(projectRoot, 'android')
|
|
293
|
+
mkdirSync(iosRoot, { recursive: true })
|
|
294
|
+
mkdirSync(join(androidRoot, 'app'), { recursive: true })
|
|
295
|
+
writeFileSync(join(iosRoot, 'Podfile'), podfile)
|
|
296
|
+
return { projectRoot, iosRoot, androidRoot, packageDir }
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function dangerousRequest(platformProjectRoot, projectRoot, platform) {
|
|
300
|
+
return {
|
|
301
|
+
platformProjectRoot,
|
|
302
|
+
projectRoot,
|
|
303
|
+
platform,
|
|
304
|
+
modName: 'dangerous',
|
|
305
|
+
projectName: 'TestApp',
|
|
306
|
+
introspect: false,
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
describe('vxrn/expo-plugin nativeSource', () => {
|
|
311
|
+
it('rejects a non-boolean nativeSource option', () => {
|
|
312
|
+
const projectRoot = expoProject()
|
|
313
|
+
expect(() =>
|
|
314
|
+
withVxrn(
|
|
315
|
+
{ name: 'TestApp', slug: 'test-app', _internal: { projectRoot } },
|
|
316
|
+
{ nativeSource: 'yes' }
|
|
317
|
+
)
|
|
318
|
+
).toThrow('nativeSource must be a boolean')
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
it('leaves the project alone when nativeSource is off', async () => {
|
|
322
|
+
const { projectRoot, iosRoot, androidRoot } = nativeSourceProject()
|
|
323
|
+
const config = withVxrn({
|
|
324
|
+
name: 'TestApp',
|
|
325
|
+
slug: 'test-app',
|
|
326
|
+
_internal: { projectRoot },
|
|
327
|
+
})
|
|
328
|
+
await config.mods.ios.dangerous({
|
|
329
|
+
...config,
|
|
330
|
+
modRequest: dangerousRequest(iosRoot, projectRoot, 'ios'),
|
|
331
|
+
modResults: {},
|
|
332
|
+
})
|
|
333
|
+
expect(existsSync(join(iosRoot, 'OneSwiftPackages'))).toBe(false)
|
|
334
|
+
expect(existsSync(join(androidRoot, 'app/src/main/java/one/source'))).toBe(false)
|
|
335
|
+
expect(readFileSync(join(iosRoot, 'Podfile'), 'utf8')).not.toContain('OneSwiftPackages')
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
it('generates swift pods and kotlin sources into the expo project', async () => {
|
|
339
|
+
const { projectRoot, iosRoot, androidRoot } = nativeSourceProject()
|
|
340
|
+
const config = withVxrn(
|
|
341
|
+
{ name: 'TestApp', slug: 'test-app', _internal: { projectRoot } },
|
|
342
|
+
{ nativeSource: true }
|
|
343
|
+
)
|
|
344
|
+
const iosMod = (modResults) =>
|
|
345
|
+
config.mods.ios.dangerous({
|
|
346
|
+
...config,
|
|
347
|
+
modRequest: dangerousRequest(iosRoot, projectRoot, 'ios'),
|
|
348
|
+
modResults,
|
|
349
|
+
})
|
|
350
|
+
await iosMod({})
|
|
351
|
+
await config.mods.android.dangerous({
|
|
352
|
+
...config,
|
|
353
|
+
modRequest: dangerousRequest(androidRoot, projectRoot, 'android'),
|
|
354
|
+
modResults: {},
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
// the pod exists and carries the module
|
|
358
|
+
const podDir = join(iosRoot, 'OneSwiftPackages', 'Showcase')
|
|
359
|
+
const podspec = readFileSync(join(podDir, 'Showcase.podspec'), 'utf8')
|
|
360
|
+
expect(podspec).toContain("s.dependency 'One'")
|
|
361
|
+
expect(podspec).toContain("s.swift_version = '6.0'")
|
|
362
|
+
// the sources compile as one pod with the generated glue
|
|
363
|
+
expect(readFileSync(join(podDir, 'Sources', 'Device.swift'), 'utf8')).toContain(
|
|
364
|
+
'PeachModule'
|
|
365
|
+
)
|
|
366
|
+
const glue = readFileSync(join(podDir, 'Sources', 'OneNativeSource.generated.swift'), 'utf8')
|
|
367
|
+
expect(glue).toContain('Showcase.Device')
|
|
368
|
+
expect(glue).toContain('case "info"')
|
|
369
|
+
// the pod is linked into the app target, idempotently
|
|
370
|
+
const once = readFileSync(join(iosRoot, 'Podfile'), 'utf8')
|
|
371
|
+
expect(once).toContain('OneSwiftPackages')
|
|
372
|
+
await iosMod({})
|
|
373
|
+
expect(readFileSync(join(iosRoot, 'Podfile'), 'utf8')).toBe(once)
|
|
374
|
+
|
|
375
|
+
// the kotlin sources land with their glue
|
|
376
|
+
const kotlinId = `K_${createHash('sha256').update('Device.kt').digest('hex').slice(0, 16)}`
|
|
377
|
+
const kotlinDir = join(androidRoot, 'app/src/main/java/one/source', kotlinId)
|
|
378
|
+
expect(readFileSync(join(kotlinDir, 'Device.kt'), 'utf8')).toContain('OneModule')
|
|
379
|
+
const kotlinGlue = readFileSync(join(kotlinDir, `OneNativeSource_${kotlinId}.kt`), 'utf8')
|
|
380
|
+
expect(kotlinGlue).toContain(`${kotlinId}.Device`)
|
|
381
|
+
expect(kotlinGlue).toContain('"info"')
|
|
382
|
+
// declarations sit beside the sources for typescript
|
|
383
|
+
expect(readFileSync(join(projectRoot, 'Device.d.kt.ts'), 'utf8')).toContain('Device')
|
|
384
|
+
expect(readFileSync(join(projectRoot, 'native/Showcase/Device.d.swift.ts'), 'utf8')).toContain(
|
|
385
|
+
'Device'
|
|
386
|
+
)
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
it('wires compose dependencies for kotlin views and fails fast without anchors', async () => {
|
|
390
|
+
const projectRoot = expoProject()
|
|
391
|
+
writeFileSync(
|
|
392
|
+
join(projectRoot, 'Greeting.kt'),
|
|
393
|
+
'import androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\n\n@Composable\nfun Greeting(name: String) {\n Text(name)\n}\n'
|
|
394
|
+
)
|
|
395
|
+
const androidRoot = join(projectRoot, 'android')
|
|
396
|
+
mkdirSync(join(androidRoot, 'app'), { recursive: true })
|
|
397
|
+
writeFileSync(
|
|
398
|
+
join(androidRoot, 'build.gradle'),
|
|
399
|
+
'buildscript {\n dependencies {\n classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")\n }\n}\n'
|
|
400
|
+
)
|
|
401
|
+
const appGradle = join(androidRoot, 'app/build.gradle')
|
|
402
|
+
writeFileSync(
|
|
403
|
+
appGradle,
|
|
404
|
+
'apply plugin: "com.android.application"\napply plugin: "org.jetbrains.kotlin.android"\nandroid {\n}\ndependencies {\n implementation("com.facebook.react:react-android")\n}\n'
|
|
405
|
+
)
|
|
406
|
+
const config = withVxrn(
|
|
407
|
+
{ name: 'TestApp', slug: 'test-app', _internal: { projectRoot } },
|
|
408
|
+
{ nativeSource: true }
|
|
409
|
+
)
|
|
410
|
+
const run = () =>
|
|
411
|
+
config.mods.android.dangerous({
|
|
412
|
+
...config,
|
|
413
|
+
modRequest: dangerousRequest(androidRoot, projectRoot, 'android'),
|
|
414
|
+
modResults: {},
|
|
415
|
+
})
|
|
416
|
+
await run()
|
|
417
|
+
const once = readFileSync(appGradle, 'utf8')
|
|
418
|
+
expect(once).toContain('org.jetbrains.kotlin.plugin.compose')
|
|
419
|
+
expect(once).toContain('compose true')
|
|
420
|
+
expect(once).toContain('androidx.compose.ui:ui')
|
|
421
|
+
await run()
|
|
422
|
+
expect(readFileSync(appGradle, 'utf8')).toBe(once)
|
|
423
|
+
|
|
424
|
+
writeFileSync(appGradle, 'android {\n}\n')
|
|
425
|
+
await expect(run()).rejects.toThrow('no kotlin android plugin anchor')
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
it('adds material-icons-core only when a kotlin source imports material icons', async () => {
|
|
429
|
+
const projectRoot = expoProject()
|
|
430
|
+
writeFileSync(
|
|
431
|
+
join(projectRoot, 'Greeting.kt'),
|
|
432
|
+
'import androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.filled.Add\nimport androidx.compose.runtime.Composable\n\n@Composable\nfun Greeting(name: String) {\n}\n'
|
|
433
|
+
)
|
|
434
|
+
const androidRoot = join(projectRoot, 'android')
|
|
435
|
+
mkdirSync(join(androidRoot, 'app'), { recursive: true })
|
|
436
|
+
writeFileSync(
|
|
437
|
+
join(androidRoot, 'build.gradle'),
|
|
438
|
+
'buildscript {\n dependencies {\n classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")\n }\n}\n'
|
|
439
|
+
)
|
|
440
|
+
const appGradle = join(androidRoot, 'app/build.gradle')
|
|
441
|
+
writeFileSync(
|
|
442
|
+
appGradle,
|
|
443
|
+
'apply plugin: "com.android.application"\napply plugin: "org.jetbrains.kotlin.android"\nandroid {\n}\ndependencies {\n implementation("com.facebook.react:react-android")\n}\n'
|
|
444
|
+
)
|
|
445
|
+
const config = withVxrn(
|
|
446
|
+
{ name: 'TestApp', slug: 'test-app', _internal: { projectRoot } },
|
|
447
|
+
{ nativeSource: true }
|
|
448
|
+
)
|
|
449
|
+
const run = () =>
|
|
450
|
+
config.mods.android.dangerous({
|
|
451
|
+
...config,
|
|
452
|
+
modRequest: dangerousRequest(androidRoot, projectRoot, 'android'),
|
|
453
|
+
modResults: {},
|
|
454
|
+
})
|
|
455
|
+
await run()
|
|
456
|
+
const once = readFileSync(appGradle, 'utf8')
|
|
457
|
+
expect(once).toContain('androidx.compose.material:material-icons-core:$materialIconsVersion')
|
|
458
|
+
await run()
|
|
459
|
+
expect(readFileSync(appGradle, 'utf8')).toBe(once)
|
|
460
|
+
})
|
|
461
|
+
})
|
package/src/exports/prebuild.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { resolvePath } from '@vxrn/resolve'
|
|
2
1
|
import { detectPackageManager, type PackageManagerName } from '@vxrn/utils'
|
|
3
2
|
import FSExtra from 'fs-extra'
|
|
4
3
|
import path from 'node:path'
|
|
5
|
-
import colors from 'picocolors'
|
|
6
4
|
import { fillOptions } from '../config/getOptionsFilled'
|
|
7
5
|
import { applyBuiltInPatches } from '../utils/patches'
|
|
8
6
|
import {
|
|
@@ -115,35 +113,6 @@ Android:
|
|
|
115
113
|
`
|
|
116
114
|
)
|
|
117
115
|
}
|
|
118
|
-
|
|
119
|
-
// See: https://github.com/facebook/react-native/pull/45464
|
|
120
|
-
try {
|
|
121
|
-
resolvePath('@react-native-community/cli', root)
|
|
122
|
-
} catch (e) {
|
|
123
|
-
if (isMissingCliDependency(e)) {
|
|
124
|
-
warnMissingCliDependency()
|
|
125
|
-
} else {
|
|
126
|
-
throw e
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function isMissingCliDependency(error) {
|
|
132
|
-
return (
|
|
133
|
-
error.code === 'MODULE_NOT_FOUND' &&
|
|
134
|
-
/@react-native-community\/cli/.test(error.message)
|
|
135
|
-
)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function warnMissingCliDependency() {
|
|
139
|
-
console.warn(`
|
|
140
|
-
${colors.red('⚠')}️ To build the app, ${colors.dim('react-native')} depends on ${colors.dim('@react-native-community/cli')} for cli commands. Please update your ${colors.dim('package.json')} to include:
|
|
141
|
-
${colors.white(
|
|
142
|
-
colors.bold(`
|
|
143
|
-
"devDependencies": {
|
|
144
|
-
"@react-native-community/cli": "latest",
|
|
145
|
-
}`)
|
|
146
|
-
)}`)
|
|
147
116
|
}
|
|
148
117
|
|
|
149
118
|
export async function replaceInUTF8File(
|