Skip to content

Commit dd9775f

Browse files
committed
feat: add support for expo example in native libraries
1 parent 09e8647 commit dd9775f

File tree

11 files changed

+64
-25
lines changed

11 files changed

+64
-25
lines changed

packages/create-react-native-library/src/exampleApp/generateExampleApp.ts

+36-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import https from 'https';
44
import { spawn } from '../utils/spawn';
55
import sortObjectKeys from '../utils/sortObjectKeys';
66
import type { TemplateConfiguration } from '../template';
7+
import dedent from 'dedent';
78

89
const FILES_TO_DELETE = [
910
'__tests__',
@@ -35,20 +36,24 @@ const PACKAGES_TO_REMOVE = [
3536
'typescript',
3637
];
3738

38-
const PACKAGES_TO_ADD_WEB = {
39+
const PACKAGES_TO_ADD_EXPO_WEB = {
3940
'@expo/metro-runtime': '~3.2.1',
4041
'react-dom': '18.2.0',
4142
'react-native-web': '~0.18.10',
4243
};
4344

45+
const PACKAGES_TO_ADD_DEV_EXPO_NATIVE = {
46+
'expo-dev-client': '~5.0.3',
47+
};
48+
4449
export default async function generateExampleApp({
4550
config,
4651
destination,
4752
reactNativeVersion = 'latest',
4853
}: {
4954
config: TemplateConfiguration;
5055
destination: string;
51-
reactNativeVersion?: string;
56+
reactNativeVersion: string | undefined;
5257
}) {
5358
const directory = path.join(destination, 'example');
5459

@@ -219,14 +224,39 @@ export default async function generateExampleApp({
219224
bundledNativeModules = {};
220225
}
221226

222-
Object.entries(PACKAGES_TO_ADD_WEB).forEach(([name, version]) => {
223-
dependencies[name] = bundledNativeModules[name] || version;
224-
});
227+
if (config.project.native) {
228+
Object.entries(PACKAGES_TO_ADD_DEV_EXPO_NATIVE).forEach(
229+
([name, version]) => {
230+
devDependencies[name] = bundledNativeModules[name] || version;
231+
}
232+
);
233+
234+
scripts.start = 'expo start --dev-client';
235+
scripts.android = 'expo run:android';
236+
scripts.ios = 'expo run:ios';
237+
238+
delete scripts.web;
225239

226-
scripts.web = 'expo start --web';
240+
await fs.writeFile(
241+
path.join(directory, '.gitignore'),
242+
dedent`
243+
# These folders are generated with prebuild (CNG)
244+
android/
245+
ios/
246+
`
247+
);
248+
} else {
249+
Object.entries(PACKAGES_TO_ADD_EXPO_WEB).forEach(([name, version]) => {
250+
dependencies[name] = bundledNativeModules[name] || version;
251+
});
252+
253+
scripts.web = 'expo start --web';
254+
}
227255

228256
const app = await fs.readJSON(path.join(directory, 'app.json'));
229257

258+
app.expo.name = `${config.project.name} Example`;
259+
app.expo.slug = `${config.project.slug}-example`;
230260
app.expo.android = app.expo.android || {};
231261
app.expo.android.package = `${config.project.package}.example`;
232262
app.expo.ios = app.expo.ios || {};

packages/create-react-native-library/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ async function create(_argv: yargs.Arguments<Args>) {
103103
spinner.text = 'Generating example app';
104104

105105
await generateExampleApp({
106+
config,
106107
destination: folder,
107108
reactNativeVersion: answers.reactNativeVersion,
108-
config,
109109
});
110110
}
111111

packages/create-react-native-library/src/input.ts

+15-10
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ const LANGUAGE_CHOICES: {
5757

5858
const EXAMPLE_CHOICES = (
5959
[
60+
{
61+
title: 'App with Expo CLI',
62+
value: 'expo',
63+
description: 'managed expo app for easier upgrades',
64+
disabled: false,
65+
},
6066
{
6167
title: 'App with Community CLI',
6268
value: 'vanilla',
@@ -71,12 +77,6 @@ const EXAMPLE_CHOICES = (
7177
// Codegen spec shipping is implemented
7278
disabled: !process.env.CRNL_ENABLE_TEST_APP,
7379
},
74-
{
75-
title: 'App with Expo CLI',
76-
value: 'expo',
77-
description: 'managed expo app with web support',
78-
disabled: false,
79-
},
8080
] as const
8181
).filter((choice) => !choice.disabled);
8282

@@ -304,10 +304,15 @@ export async function createQuestions({
304304
}
305305

306306
return EXAMPLE_CHOICES.filter((choice) => {
307-
if (values.type) {
308-
return values.type === 'library'
309-
? choice.value === 'expo'
310-
: choice.value !== 'expo';
307+
if (values.type === 'library') {
308+
return choice.value === 'expo';
309+
}
310+
311+
if (
312+
values.type === 'legacy-module' ||
313+
values.type === 'legacy-view'
314+
) {
315+
return choice.value !== 'expo';
311316
}
312317

313318
return true;

packages/create-react-native-library/src/template.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ const EXAMPLE_MODULE_NEW_FILES = path.resolve(
7171
'../templates/example-module-new'
7272
);
7373
const EXAMPLE_VIEW_FILES = path.resolve(__dirname, '../templates/example-view');
74+
const EXAMPLE_EXPO_FILES = path.resolve(__dirname, '../templates/example-expo');
7475

7576
const JS_FILES = path.resolve(__dirname, '../templates/js-library');
76-
const EXPO_FILES = path.resolve(__dirname, '../templates/expo-library');
7777
const CPP_FILES = path.resolve(__dirname, '../templates/cpp-library');
7878
const NATIVE_COMMON_FILES = path.resolve(
7979
__dirname,
@@ -228,14 +228,18 @@ export async function applyTemplates(
228228

229229
if (answers.languages === 'js') {
230230
await applyTemplate(config, JS_FILES, folder);
231-
await applyTemplate(config, EXPO_FILES, folder);
231+
await applyTemplate(config, EXAMPLE_EXPO_FILES, folder);
232232
} else {
233233
await applyTemplate(config, NATIVE_COMMON_FILES, folder);
234234

235235
if (config.example !== 'none') {
236236
await applyTemplate(config, NATIVE_COMMON_EXAMPLE_FILES, folder);
237237
}
238238

239+
if (config.example === 'expo') {
240+
await applyTemplate(config, EXAMPLE_EXPO_FILES, folder);
241+
}
242+
239243
if (config.project.moduleConfig === 'nitro-modules') {
240244
await applyTemplate(config, NATIVE_FILES['module_nitro'], folder);
241245
return;

packages/create-react-native-library/templates/native-common-example/example/react-native.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ module.exports = {
1515
automaticPodsInstallation: true,
1616
},
1717
}),
18-
<% } else { -%>
18+
<% } else if (example === 'vanila') { -%>
1919
project: {
2020
ios: {
2121
automaticPodsInstallation: true,

packages/create-react-native-library/templates/objc-library/ios/{%- project.name %}.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<% } -%>
66

77
<% if (project.arch === 'new') { -%>
8-
#import "generated/RN<%- project.name -%>Spec/RN<%- project.name -%>Spec.h"
8+
#import "RN<%- project.name -%>Spec/RN<%- project.name -%>Spec.h"
99

1010
@interface <%- project.name -%> : NSObject <Native<%- project.name -%>Spec>
1111
<% } else { -%>

packages/create-react-native-library/templates/objc-view-new/ios/{%- project.name %}View.mm

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#import "<%- project.name -%>View.h"
22

3-
#import "generated/RN<%- project.name -%>ViewSpec/ComponentDescriptors.h"
4-
#import "generated/RN<%- project.name -%>ViewSpec/EventEmitters.h"
5-
#import "generated/RN<%- project.name -%>ViewSpec/Props.h"
6-
#import "generated/RN<%- project.name -%>ViewSpec/RCTComponentViewHelpers.h"
3+
#import "RN<%- project.name -%>ViewSpec/ComponentDescriptors.h"
4+
#import "RN<%- project.name -%>ViewSpec/EventEmitters.h"
5+
#import "RN<%- project.name -%>ViewSpec/Props.h"
6+
#import "RN<%- project.name -%>ViewSpec/RCTComponentViewHelpers.h"
77

88
#import "RCTFabricComponentsPlugins.h"
99

0 commit comments

Comments
 (0)