@@ -3,7 +3,8 @@ import path from 'path';
3
3
import https from 'https' ;
4
4
import { spawn } from '../utils/spawn' ;
5
5
import sortObjectKeys from '../utils/sortObjectKeys' ;
6
- import type { ExampleApp } from '../input' ;
6
+ import dedent from 'dedent' ;
7
+ import type { TemplateConfiguration } from '../template' ;
7
8
8
9
const FILES_TO_DELETE = [
9
10
'__tests__' ,
@@ -35,40 +36,34 @@ const PACKAGES_TO_REMOVE = [
35
36
'typescript' ,
36
37
] ;
37
38
38
- const PACKAGES_TO_ADD_WEB = {
39
+ const PACKAGES_TO_ADD_EXPO_WEB = {
39
40
'@expo/metro-runtime' : '~3.2.1' ,
40
41
'react-dom' : '18.2.0' ,
41
42
'react-native-web' : '~0.18.10' ,
42
43
} ;
43
44
45
+ const PACKAGES_TO_ADD_DEV_EXPO_NATIVE = {
46
+ 'expo-dev-client' : '~5.0.3' ,
47
+ } ;
48
+
44
49
export default async function generateExampleApp ( {
45
- type,
46
- dest,
47
- arch,
48
- project,
49
- bobVersion,
50
+ config,
51
+ destination,
50
52
reactNativeVersion = 'latest' ,
51
53
} : {
52
- type : ExampleApp ;
53
- dest : string ;
54
- arch : 'new' | 'legacy' ;
55
- project : {
56
- slug : string ;
57
- name : string ;
58
- package : string ;
59
- } ;
60
- bobVersion : string ;
61
- reactNativeVersion ?: string ;
54
+ config : TemplateConfiguration ;
55
+ destination : string ;
56
+ reactNativeVersion : string | undefined ;
62
57
} ) {
63
- const directory = path . join ( dest , 'example' ) ;
58
+ const directory = path . join ( destination , 'example' ) ;
64
59
65
60
// `npx --package react-native-test-app@latest init --name ${projectName}Example --destination example --version ${reactNativeVersion}`
66
61
const testAppArgs = [
67
62
'--package' ,
68
63
`react-native-test-app@latest` ,
69
64
'init' ,
70
65
'--name' ,
71
- `${ project . name } Example` ,
66
+ `${ config . project . name } Example` ,
72
67
`--destination` ,
73
68
directory ,
74
69
...( reactNativeVersion !== 'latest'
@@ -84,9 +79,9 @@ export default async function generateExampleApp({
84
79
const vanillaArgs = [
85
80
`@react-native-community/cli` ,
86
81
'init' ,
87
- `${ project . name } Example` ,
82
+ `${ config . project . name } Example` ,
88
83
'--package-name' ,
89
- `${ project . package } .example` ,
84
+ `${ config . project . package } .example` ,
90
85
'--directory' ,
91
86
directory ,
92
87
'--version' ,
@@ -107,7 +102,7 @@ export default async function generateExampleApp({
107
102
108
103
let args : string [ ] = [ ] ;
109
104
110
- switch ( type ) {
105
+ switch ( config . example ) {
111
106
case 'vanilla' :
112
107
args = vanillaArgs ;
113
108
break ;
@@ -131,7 +126,7 @@ export default async function generateExampleApp({
131
126
// Patch the example app's package.json
132
127
const pkg = await fs . readJSON ( path . join ( directory , 'package.json' ) ) ;
133
128
134
- pkg . name = `${ project . slug } -example` ;
129
+ pkg . name = `${ config . project . slug } -example` ;
135
130
136
131
// Remove Jest config for now
137
132
delete pkg . jest ;
@@ -144,12 +139,12 @@ export default async function generateExampleApp({
144
139
const SCRIPTS_TO_ADD = {
145
140
'build:android' :
146
141
'react-native build-android --extra-params "--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a"' ,
147
- 'build:ios' : `react-native build-ios --scheme ${ project . name } Example --mode Debug --extra-params "-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO"` ,
142
+ 'build:ios' : `react-native build-ios --scheme ${ config . project . name } Example --mode Debug --extra-params "-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO"` ,
148
143
} ;
149
144
150
- if ( type === 'vanilla' ) {
145
+ if ( config . example === 'vanilla' ) {
151
146
Object . assign ( scripts , SCRIPTS_TO_ADD ) ;
152
- } else if ( type === 'test-app' ) {
147
+ } else if ( config . example === 'test-app' ) {
153
148
// `react-native-test-app` doesn't bundle application by default in 'Release' mode and also `bundle` command doesn't create a directory.
154
149
// `mkdist` script should be removed after stable React Native major contains this fix: https://github.com/facebook/react-native/pull/45182.
155
150
@@ -173,9 +168,9 @@ export default async function generateExampleApp({
173
168
const app = await fs . readJSON ( path . join ( directory , 'app.json' ) ) ;
174
169
175
170
app . android = app . android || { } ;
176
- app . android . package = `${ project . package } .example` ;
171
+ app . android . package = `${ config . project . package } .example` ;
177
172
app . ios = app . ios || { } ;
178
- app . ios . bundleIdentifier = `${ project . package } .example` ;
173
+ app . ios . bundleIdentifier = `${ config . project . package } .example` ;
179
174
180
175
await fs . writeJSON ( path . join ( directory , 'app.json' ) , app , {
181
176
spaces : 2 ,
@@ -188,12 +183,12 @@ export default async function generateExampleApp({
188
183
} ) ;
189
184
190
185
const PACKAGES_TO_ADD_DEV = {
191
- 'react-native-builder-bob' : `^${ bobVersion } ` ,
186
+ 'react-native-builder-bob' : `^${ config . bob . version } ` ,
192
187
} ;
193
188
194
189
Object . assign ( devDependencies , PACKAGES_TO_ADD_DEV ) ;
195
190
196
- if ( type === 'expo' ) {
191
+ if ( config . example === 'expo' ) {
197
192
const sdkVersion = dependencies . expo . split ( '.' ) [ 0 ] . replace ( / [ ^ \d ] / , '' ) ;
198
193
199
194
let bundledNativeModules : Record < string , string > ;
@@ -222,18 +217,43 @@ export default async function generateExampleApp({
222
217
bundledNativeModules = { } ;
223
218
}
224
219
225
- Object . entries ( PACKAGES_TO_ADD_WEB ) . forEach ( ( [ name , version ] ) => {
226
- dependencies [ name ] = bundledNativeModules [ name ] || version ;
227
- } ) ;
220
+ if ( config . project . native ) {
221
+ Object . entries ( PACKAGES_TO_ADD_DEV_EXPO_NATIVE ) . forEach (
222
+ ( [ name , version ] ) => {
223
+ devDependencies [ name ] = bundledNativeModules [ name ] || version ;
224
+ }
225
+ ) ;
226
+
227
+ scripts . start = 'expo start --dev-client' ;
228
+ scripts . android = 'expo run:android' ;
229
+ scripts . ios = 'expo run:ios' ;
228
230
229
- scripts . web = 'expo start --web' ;
231
+ delete scripts . web ;
232
+
233
+ await fs . writeFile (
234
+ path . join ( directory , '.gitignore' ) ,
235
+ dedent `
236
+ # These folders are generated with prebuild (CNG)
237
+ android/
238
+ ios/
239
+ `
240
+ ) ;
241
+ } else {
242
+ Object . entries ( PACKAGES_TO_ADD_EXPO_WEB ) . forEach ( ( [ name , version ] ) => {
243
+ dependencies [ name ] = bundledNativeModules [ name ] || version ;
244
+ } ) ;
245
+
246
+ scripts . web = 'expo start --web' ;
247
+ }
230
248
231
249
const app = await fs . readJSON ( path . join ( directory , 'app.json' ) ) ;
232
250
251
+ app . expo . name = `${ config . project . name } Example` ;
252
+ app . expo . slug = `${ config . project . slug } -example` ;
233
253
app . expo . android = app . expo . android || { } ;
234
- app . expo . android . package = `${ project . package } .example` ;
254
+ app . expo . android . package = `${ config . project . package } .example` ;
235
255
app . expo . ios = app . expo . ios || { } ;
236
- app . expo . ios . bundleIdentifier = `${ project . package } .example` ;
256
+ app . expo . ios . bundleIdentifier = `${ config . project . package } .example` ;
237
257
238
258
await fs . writeJSON ( path . join ( directory , 'app.json' ) , app , {
239
259
spaces : 2 ,
@@ -250,7 +270,7 @@ export default async function generateExampleApp({
250
270
spaces : 2 ,
251
271
} ) ;
252
272
253
- if ( type !== 'expo' ) {
273
+ if ( config . example !== 'expo' ) {
254
274
let gradleProperties = await fs . readFile (
255
275
path . join ( directory , 'android' , 'gradle.properties' ) ,
256
276
'utf8'
@@ -264,7 +284,7 @@ export default async function generateExampleApp({
264
284
) ;
265
285
266
286
// If the library is on new architecture, enable new arch for iOS and Android
267
- if ( arch === 'new' ) {
287
+ if ( config . project . arch === 'new' ) {
268
288
// iOS
269
289
// Add ENV['RCT_NEW_ARCH_ENABLED'] = 1 on top of example/ios/Podfile
270
290
const podfile = await fs . readFile (
0 commit comments