Skip to content

Commit cb566bd

Browse files
atljsatya164
authored andcommitted
feat: use react-native init for generating example app (#271)
Co-authored-by: Satyajit Sahoo <satyajit.happy@gmail.com>
1 parent e46f55a commit cb566bd

File tree

65 files changed

+368
-7104
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+368
-7104
lines changed

packages/create-react-native-library/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"fs-extra": "^10.1.0",
4949
"github-username": "^6.0.0",
5050
"kleur": "^4.1.4",
51+
"ora": "^5.4.1",
5152
"prompts": "^2.4.2",
5253
"validate-npm-package-name": "^4.0.0",
5354
"yargs": "^17.5.1"

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import dedent from 'dedent';
55
import kleur from 'kleur';
66
import yargs from 'yargs';
77
import spawn from 'cross-spawn';
8+
import ora from 'ora';
89
import validateNpmPackage from 'validate-npm-package-name';
910
import githubUsername from 'github-username';
1011
import prompts, { PromptObject } from './utils/prompts';
12+
import generateRNApp from './utils/generateRNApp';
1113

1214
const FALLBACK_BOB_VERSION = '0.18.3';
1315

@@ -413,6 +415,17 @@ async function create(argv: yargs.Arguments<any>) {
413415
}
414416
};
415417

418+
await fs.mkdirp(folder);
419+
if (example === 'native') {
420+
const spinner = ora('Generating example app').start();
421+
await generateRNApp({
422+
dest: folder,
423+
projectName: options.project.name,
424+
isNewArch: options.project.turbomodule,
425+
});
426+
spinner.succeed();
427+
}
428+
416429
await copyDir(COMMON_FILES, folder);
417430

418431
if (languages === 'js') {
@@ -469,6 +482,21 @@ async function create(argv: yargs.Arguments<any>) {
469482
}
470483
}
471484

485+
if (example === 'native') {
486+
// Set `react` and `react-native` versions of root `package.json` from example `package.json`
487+
const examplePackageJson = fs.readJSONSync(
488+
path.join(folder, 'example', 'package.json')
489+
);
490+
const rootPackageJson = fs.readJSONSync(path.join(folder, 'package.json'));
491+
rootPackageJson.devDependencies.react =
492+
examplePackageJson.dependencies.react;
493+
rootPackageJson.devDependencies['react-native'] =
494+
examplePackageJson.dependencies['react-native'];
495+
fs.writeJSONSync(path.join(folder, 'package.json'), rootPackageJson, {
496+
spaces: 2,
497+
});
498+
}
499+
472500
try {
473501
spawn.sync('git', ['init'], { cwd: folder });
474502
spawn.sync('git', ['add', '.'], { cwd: folder });
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import fs from 'fs';
2+
import spawn from 'cross-spawn';
3+
import path from 'path';
4+
5+
const FILES_TO_DELETE = [
6+
'.eslintrc.js',
7+
'.gitignore',
8+
'.prettierrc.js',
9+
'App.js',
10+
'index.js',
11+
'.flowconfig',
12+
'.buckconfig',
13+
];
14+
15+
const FOLDERS_TO_DELETE = ['__tests__'];
16+
17+
const PACKAGES_TO_REMOVE = [
18+
'@react-native-community/eslint-config',
19+
'babel-jest',
20+
'eslint',
21+
'jest',
22+
'react-test-renderer',
23+
];
24+
25+
const PACKAGES_TO_ADD = {
26+
'babel-plugin-module-resolver': '^4.1.0',
27+
'metro-react-native-babel-preset': '^0.72.1',
28+
'patch-package': '^6.4.7',
29+
'postinstall-postinstall': '^2.1.0',
30+
};
31+
32+
export default async function generateRNApp({
33+
dest,
34+
projectName,
35+
isNewArch,
36+
}: {
37+
dest: string;
38+
projectName: string;
39+
isNewArch: boolean;
40+
}) {
41+
// Generate the example app's base using `npx react-native init <projectName>Example --directory example --skip-install`
42+
const createRNAppProcess = spawn(
43+
'npx',
44+
[
45+
'react-native',
46+
'init',
47+
`${projectName}Example`,
48+
'--directory',
49+
path.join(dest, 'example'),
50+
'--skip-install',
51+
],
52+
{
53+
cwd: dest,
54+
}
55+
);
56+
await new Promise((resolve, reject) => {
57+
createRNAppProcess.once('error', reject);
58+
createRNAppProcess.once('close', resolve);
59+
});
60+
61+
// Remove unnecessary files
62+
FILES_TO_DELETE.forEach((file) => {
63+
try {
64+
fs.unlinkSync(path.join(dest, 'example', file));
65+
} catch (e) {
66+
//ignore
67+
}
68+
});
69+
70+
// Remove unnecessary folders
71+
FOLDERS_TO_DELETE.forEach((folder) => {
72+
try {
73+
fs.rmSync(path.join(dest, 'example', folder), {
74+
recursive: true,
75+
});
76+
} catch (e) {
77+
// ignore
78+
}
79+
});
80+
81+
// Patch the example app's package.json
82+
const examplePackageJson = JSON.parse(
83+
fs.readFileSync(path.join(dest, 'example', 'package.json'), 'utf8')
84+
);
85+
examplePackageJson.scripts = {
86+
...examplePackageJson.scripts,
87+
test: undefined,
88+
lint: undefined,
89+
90+
pods: 'pod-install --quiet',
91+
postinstall: 'patch-package',
92+
};
93+
PACKAGES_TO_REMOVE.forEach((pkg) => {
94+
examplePackageJson.devDependencies[pkg] = undefined;
95+
});
96+
examplePackageJson.devDependencies = {
97+
...examplePackageJson.devDependencies,
98+
...PACKAGES_TO_ADD,
99+
};
100+
examplePackageJson.jest = undefined;
101+
fs.writeFileSync(
102+
path.join(dest, 'example', 'package.json'),
103+
JSON.stringify(examplePackageJson, null, 2)
104+
);
105+
106+
// If the library is on new architecture, enable new arch for IOS and Android
107+
if (isNewArch) {
108+
// Android
109+
// Change newArchEnabled=false to newArchEnabled=true in example/android/gradle.properties
110+
const gradleProperties = fs
111+
.readFileSync(
112+
path.join(dest, 'example', 'android', 'gradle.properties'),
113+
'utf8'
114+
)
115+
.replace('newArchEnabled=false', 'newArchEnabled=true');
116+
fs.writeFileSync(
117+
path.join(dest, 'example', 'android', 'gradle.properties'),
118+
gradleProperties
119+
);
120+
121+
// IOS
122+
// Add ENV['RCT_NEW_ARCH_ENABLED'] = 1 on top of example/ios/Podfile
123+
const podfile = fs.readFileSync(
124+
path.join(dest, 'example', 'ios', 'Podfile'),
125+
'utf8'
126+
);
127+
fs.writeFileSync(
128+
path.join(dest, 'example', 'ios', 'Podfile'),
129+
"ENV['RCT_NEW_ARCH_ENABLED'] = '1'\n" + podfile
130+
);
131+
}
132+
}

packages/create-react-native-library/templates/example-turbo/example/patches/react-native+0.68.2.patch

Lines changed: 0 additions & 49 deletions
This file was deleted.
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
diff --git a/node_modules/react-native/scripts/codegen/generate-artifacts-executor.js b/node_modules/react-native/scripts/codegen/generate-artifacts-executor.js
2+
index 458495b..6fc398a 100644
3+
--- a/node_modules/react-native/scripts/codegen/generate-artifacts-executor.js
4+
+++ b/node_modules/react-native/scripts/codegen/generate-artifacts-executor.js
5+
@@ -204,6 +204,55 @@ function handleThirdPartyLibraries(
6+
});
7+
}
8+
9+
+function handleLibrariesFromReactNativeConfig(
10+
+ libraries,
11+
+ codegenConfigKey,
12+
+ codegenConfigFilename,
13+
+ appRootDir,
14+
+) {
15+
+ const rnConfigFileName = 'react-native.config.js';
16+
+
17+
+ console.log(
18+
+ `\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in ${rnConfigFileName}`,
19+
+ );
20+
+
21+
+ const rnConfigFilePath = path.join(appRootDir, rnConfigFileName);
22+
+
23+
+ if (fs.existsSync(rnConfigFilePath)) {
24+
+ const rnConfig = require(rnConfigFilePath);
25+
+
26+
+ if (rnConfig.dependencies != null) {
27+
+ Object.keys(rnConfig.dependencies).forEach(name => {
28+
+ const dependencyConfig = rnConfig.dependencies[name];
29+
+
30+
+ if (dependencyConfig.root) {
31+
+ const codegenConfigFileDir = path.resolve(
32+
+ appRootDir,
33+
+ dependencyConfig.root,
34+
+ );
35+
+ const configFilePath = path.join(
36+
+ codegenConfigFileDir,
37+
+ codegenConfigFilename,
38+
+ );
39+
+ const pkgJsonPath = path.join(codegenConfigFileDir, 'package.json');
40+
+
41+
+ if (fs.existsSync(configFilePath)) {
42+
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath));
43+
+ const configFile = JSON.parse(fs.readFileSync(configFilePath));
44+
+ extractLibrariesFromJSON(
45+
+ configFile,
46+
+ libraries,
47+
+ codegenConfigKey,
48+
+ pkgJson.name,
49+
+ codegenConfigFileDir,
50+
+ );
51+
+ }
52+
+ }
53+
+ });
54+
+ }
55+
+ }
56+
+}
57+
+
58+
function handleInAppLibraries(
59+
libraries,
60+
pkgJson,
61+
@@ -362,6 +411,39 @@ function createComponentProvider(
62+
}
63+
}
64+
65+
+function findCodegenEnabledLibraries(
66+
+ appRootDir,
67+
+ baseCodegenConfigFileDir,
68+
+ codegenConfigFilename,
69+
+ codegenConfigKey,
70+
+) {
71+
+ const pkgJson = readPackageJSON(appRootDir);
72+
+ const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies};
73+
+ const libraries = [];
74+
+
75+
+ handleReactNativeCodeLibraries(
76+
+ libraries,
77+
+ codegenConfigFilename,
78+
+ codegenConfigKey,
79+
+ );
80+
+ handleThirdPartyLibraries(
81+
+ libraries,
82+
+ baseCodegenConfigFileDir,
83+
+ dependencies,
84+
+ codegenConfigFilename,
85+
+ codegenConfigKey,
86+
+ );
87+
+ handleLibrariesFromReactNativeConfig(
88+
+ libraries,
89+
+ codegenConfigKey,
90+
+ codegenConfigFilename,
91+
+ appRootDir,
92+
+ );
93+
+ handleInAppLibraries(libraries, pkgJson, codegenConfigKey, appRootDir);
94+
+
95+
+ return libraries;
96+
+}
97+
+
98+
// It removes all the empty files and empty folders
99+
// it finds, starting from `filepath`, recursively.
100+
//
101+
@@ -429,23 +511,12 @@ function execute(
102+
}
103+
104+
try {
105+
- const pkgJson = readPackageJSON(appRootDir);
106+
- const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies};
107+
- const libraries = [];
108+
-
109+
- handleReactNativeCodeLibraries(
110+
- libraries,
111+
- codegenConfigFilename,
112+
- codegenConfigKey,
113+
- );
114+
- handleThirdPartyLibraries(
115+
- libraries,
116+
+ const libraries = findCodegenEnabledLibraries(
117+
+ appRootDir,
118+
baseCodegenConfigFileDir,
119+
- dependencies,
120+
codegenConfigFilename,
121+
codegenConfigKey,
122+
);
123+
- handleInAppLibraries(libraries, pkgJson, codegenConfigKey, appRootDir);
124+
125+
if (libraries.length === 0) {
126+
console.log('[Codegen] No codegen-enabled libraries found.');
127+
@@ -482,6 +553,7 @@ module.exports = {
128+
execute: execute,
129+
// exported for testing purposes only:
130+
_extractLibrariesFromJSON: extractLibrariesFromJSON,
131+
+ _findCodegenEnabledLibraries: findCodegenEnabledLibraries,
132+
_executeNodeScript: executeNodeScript,
133+
_generateCode: generateCode,
134+
_cleanupEmptyFilesAndFolders: cleanupEmptyFilesAndFolders,

packages/create-react-native-library/templates/example/example/$.bundle/config

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/create-react-native-library/templates/example/example/$.ruby-version

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)