Skip to content

Commit

Permalink
feat: use react-native-init-func to generate example app (#421)
Browse files Browse the repository at this point in the history
* chore: add react-native-init-func to package dependencies
* refactor(prep): resolve *absolute* paths before generating example
* test: replace absolute process cwd in output paths before taking snapshots
* feat: use react-native-init-func to generate example app
* refactor: make reactNativeInit overridable (for testing purposes)
* test: update tests to use injected / mocked reactNativeInit function
* test: remove test for react-native CLI tool no longer needed
* test: remove test of missing react-native CLI (no longer relevant)
* test: update test of missing Yarn CLI
* refactor: update help text for --example-react-native-version
* refactor: update help text for --generate-example
* test: update test snapshots
* doc: update option text in README.md
* doc: update some more documentation in README.md

BREAKING CHANGE: this may change how the React Native template version
is used to generate the example app.
  • Loading branch information
Chris Brody authored Mar 11, 2021
1 parent 51f8666 commit 56e7dbf
Show file tree
Hide file tree
Showing 31 changed files with 2,744 additions and 380 deletions.
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ __Outdated alternatives:__ see [acknowledgements](#acknowledgements) below

## Installation

Packages required to be installed globally if the recommended example app is generated:
Package required to be installed globally if the recommended example app is generated:

- [`react-native-cli`](https://www.npmjs.com/package/react-native-cli)
- [`yarn`](https://www.npmjs.com/package/yarn)

```
$ npm install -g react-native-cli yarn
$ npm install -g yarn
```

To install this package:
Expand Down Expand Up @@ -105,10 +104,10 @@ Options:
--author-email <authorEmail> The author's email (Default: `[email protected]`)
--license <license> The license type (Default: `MIT`)
--use-apple-networking [iOS] EXPERIMENTAL FEATURE NOT SUPPORTED: Use `AFNetworking` dependency as a sample in the podspec & use it from the iOS code - see issue #426
--generate-example Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires both react-native-cli and yarn to be installed globally
--generate-example Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires Yarn to be installed globally
--example-file-linkage DEPRECATED: do `yarn add file:../` instead of `yarn add link:../` in a generated example project, and add a postinstall workaround script, with no overwrite of example metro.config.js
--example-name <exampleName> Name for the example project (default: `example`)
--example-react-native-version <version> React Native version for the generated example project (default: `react-native@latest`)
--example-react-native-version <version> React Native template version for the generated example project, for example: react-native-tvos or [email protected] (requires --tvos-enabled option); [email protected] (default: `react-native@latest`)
--write-example-podfile [iOS] EXPERIMENTAL FEATURE NOT SUPPORTED: write (or overwrite) example ios/Podfile
-h, --help output usage information
```
Expand Down Expand Up @@ -143,10 +142,10 @@ createLibraryModule({
authorEmail: String, /* The author's email (Default: `[email protected]`) */
license: String, /* The license type of this library (Default: `MIT`) */
useAppleNetworking: Boolean, /* [iOS] EXPERIMENTAL FEATURE NOT SUPPORTED: Use `AFNetworking` dependency as a sample in the podspec & use it from the iOS code - see issue #426 (Default: false) */
generateExample: Boolean, /* Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires both react-native-cli and yarn to be installed globally (Default: false) */
generateExample: Boolean, /* Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires Yarn to be installed globally (Default: false) */
exampleFileLinkage: Boolean, /* DEPRECATED: do `yarn add file:../` instead of `yarn add link:../` in a generated example project, and add a postinstall workaround script, with no overwrite of example metro.config.js (Default: false) */
exampleName: String, /* Name for the example project (Default: `example`) */
exampleReactNativeVersion: String, /* React Native version for the generated example project (Default: `react-native@latest`) */
exampleReactNativeVersion: String, /* React Native template version for the generated example project, for example: react-native-tvos or [email protected] (requires --tvos-enabled option); [email protected] (Default: `react-native@latest`) */
writeExamplePodfile: Boolean, /* [iOS] EXPERIMENTAL FEATURE NOT SUPPORTED: write (or overwrite) example ios/Podfile (Default: false) */
}
```
Expand Down Expand Up @@ -188,13 +187,15 @@ Otherwise, React Native will open its own window to run the Metro Bundler.
To run on Android, do the following command (within `react-native-alice-helper/example`):

```
react-native run-android
npx react-native run-android
```

(or `yarn android` on React Native starting with 0.61)

This assumes that the `ANDROID_HOME` environmental variable is set properly. Here is a sample command that does not make such an assumption on a mac:

```
ANDROID_HOME=~/Library/Android/sdk react-native run-android
ANDROID_HOME=~/Library/Android/sdk npx react-native run-android
```

For iOS:
Expand All @@ -208,9 +209,11 @@ cd ios && pod install && cd ..
Then to run on iOS:

```
react-native run-ios
npx react-native run-ios
```

(or `yarn ios` on React Native starting with 0.61)

or do the following command to open the iOS project in Xcode:

```
Expand Down Expand Up @@ -254,12 +257,12 @@ It is *recommended* to start the Metro Bundler manually as described above (with
yarn start
```

To run on Android: do `react-native run-android` as described for the other example above.
To run on Android: do `npx react-native run-android` as described for the other example above.

To run on iOS (as described above):

- _in case of clean checkout **only**_: do `pod install` in `ios` subdirectory
- do `react-native run-ios` or `open ios/example.xcodeproj`
- do `npx react-native run-ios` or `open ios/example.xcodeproj`

__Expected result:__

Expand Down
4 changes: 2 additions & 2 deletions lib/cli-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ ${postCreateInstructions(createOptions)}`);
description: '[iOS] Use `AFNetworking` dependency as a sample in the podspec & use it from the iOS code',
}, {
command: '--generate-example',
description: 'Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires both react-native-cli and yarn to be installed globally',
description: 'Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires Yarn to be installed globally',
}, {
command: '--example-file-linkage',
description: "DEPRECATED: do `yarn add file:../` instead of `yarn add link:../` in a generated example project, and add a postinstall workaround script, with no overwrite of example metro.config.js",
Expand All @@ -142,7 +142,7 @@ ${postCreateInstructions(createOptions)}`);
default: 'example',
}, {
command: '--example-react-native-version [exampleReactNativeVersion]',
description: 'React Native version for the generated example project',
description: 'React Native template version for the generated example project, for example: react-native-tvos or [email protected] (requires --tvos-enabled option); [email protected]',
default: 'react-native@latest',
}, {
command: '--write-example-podfile',
Expand Down
49 changes: 20 additions & 29 deletions lib/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const fsExtra = require('fs-extra');

const jsonfile = require('jsonfile');

// default reactNativeInit function
const reactNativeInitDefault = require('react-native-init-func');

// Internal imports:

const normalizedOptions = require('./normalized-options');
Expand Down Expand Up @@ -88,6 +91,7 @@ const generateWithNormalizedOptions = ({
}, {
fs = fsExtra, // (this can be mocked out for testing purposes)
execa = execaDefault, // (this can be mocked out for testing purposes)
reactNativeInit = reactNativeInitDefault // (can be overridden or mocked out for testing purposes)
}) => {
if (packageIdentifier === DEFAULT_PACKAGE_IDENTIFIER) {
warn(`While \`{DEFAULT_PACKAGE_IDENTIFIER}\` is the default package
Expand Down Expand Up @@ -130,28 +134,16 @@ exampleReactNativeVersion: ${exampleReactNativeVersion}
const commandSync = execa.commandSync;

if (generateExample) {
const reactNativeVersionCommand = 'react-native --version';
const yarnVersionCommand = 'yarn --version';

const checkCliOptions = { stdio: 'inherit' };
const errorRemedyMessage = 'both react-native-cli and yarn CLI tools are needed to generate example project';

try {
info('CREATE: Check for valid react-native-cli tool version, as needed to generate the example project');
commandSync(reactNativeVersionCommand, checkCliOptions);
info(`${reactNativeVersionCommand} ok`);
} catch (e) {
throw new Error(
`${reactNativeVersionCommand} failed; ${errorRemedyMessage}`);
}
const errorRemedyMessage = 'yarn CLI is needed to generate example project';

try {
info('CREATE: Check for valid Yarn CLI tool version, as needed to generate the example project');
commandSync(yarnVersionCommand, checkCliOptions);
info(`${yarnVersionCommand} ok`);
} catch (e) {
throw new Error(
`${yarnVersionCommand} failed; ${errorRemedyMessage}`);
throw new Error(`${yarnVersionCommand} failed ... ${errorRemedyMessage}`);
}

// NOTE: While the pod tool is also required for example on iOS,
Expand Down Expand Up @@ -195,22 +187,24 @@ exampleReactNativeVersion: ${exampleReactNativeVersion}
// multiple test or sample apps in the future.
const generateExampleApp =
() => {
const exampleReactNativeInitCommand =
`react-native init ${exampleName} --version ${exampleReactNativeVersion}`;

info(
`CREATE example app with the following command: ${exampleReactNativeInitCommand}`);
// TODO: rename --example-react-native-version to --example-react-native-template
info(`CREATE example app with the following template: ${exampleReactNativeVersion}`);

const execOptions = { cwd: `./${moduleName}`, stdio: 'inherit' };
// resolve **absolute** module & example paths before
// react-native-init-func function call
// which may affect the process cwd state
// (absolute paths seem to be needed for the steps below function properly)
const modulePath = path.resolve('.', moduleName);
const pathExampleApp = path.join(modulePath, exampleName);
const exampleAppSubdirectory = path.join('.', moduleName, exampleName);

// (with the work done in a promise chain)
return Promise.resolve()
.then(() => {
// We use synchronous execSync / commandSync call here
// which is able to output its stdout to stdout in this process.
// Note that any exception would be properly handled since this
// call is executed within a Promise.resolve().then() callback.
commandSync(exampleReactNativeInitCommand, execOptions);
return reactNativeInit([exampleName], {
template: exampleReactNativeVersion,
directory: exampleAppSubdirectory
});
})
.then(() => {
// Render the example template
Expand All @@ -226,16 +220,13 @@ exampleReactNativeVersion: ${exampleReactNativeVersion}

return Promise.all(
exampleTemplates.map((template) => {
return renderTemplateIfValid(fs, moduleName, template, templateArgs);
return renderTemplateIfValid(fs, modulePath, template, templateArgs);
})
);
})
.then(() => {
// Adds and link the new library
return new Promise((resolve) => {
// determine this path before the next steps:
const pathExampleApp = `./${moduleName}/${exampleName}`;

// postinstall workaround script *only* needed in case
// the DEPRECATED --example-file-linkage option
// (exampleFileLinkage: true) is used
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"param-case": "^3.0.4",
"pascal-case": "^3.1.2",
"please-upgrade-node": "^3.2.0",
"react-native-init-func": "^0.0.3",
"update-notifier": "^5.1.0"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Options:
--author-email [authorEmail] The author's email (default: \\"[email protected]\\")
--license [license] The license type (default: \\"MIT\\")
--use-apple-networking [iOS] Use \`AFNetworking\` dependency as a sample in the podspec & use it from the iOS code
--generate-example Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires both react-native-cli and yarn to be installed globally
--generate-example Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires Yarn to be installed globally
--example-file-linkage DEPRECATED: do \`yarn add file:../\` instead of \`yarn add link:../\` in a generated example project, and add a postinstall workaround script, with no overwrite of example metro.config.js
--example-name [exampleName] Name for the example project (default: \\"example\\")
--example-react-native-version [exampleReactNativeVersion] React Native version for the generated example project (default: \\"react-native@latest\\")
--example-react-native-version [exampleReactNativeVersion] React Native template version for the generated example project, for example: react-native-tvos or [email protected] (requires --tvos-enabled option); [email protected] (default: \\"react-native@latest\\")
--write-example-podfile [iOS] EXPERIMENTAL FEATURE NOT SUPPORTED: write (or overwrite) example ios/Podfile
-h, --help display help for command"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Options:
--author-email [authorEmail] The author's email (default: \\"[email protected]\\")
--license [license] The license type (default: \\"MIT\\")
--use-apple-networking [iOS] Use \`AFNetworking\` dependency as a sample in the podspec & use it from the iOS code
--generate-example Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires both react-native-cli and yarn to be installed globally
--generate-example Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires Yarn to be installed globally
--example-file-linkage DEPRECATED: do \`yarn add file:../\` instead of \`yarn add link:../\` in a generated example project, and add a postinstall workaround script, with no overwrite of example metro.config.js
--example-name [exampleName] Name for the example project (default: \\"example\\")
--example-react-native-version [exampleReactNativeVersion] React Native version for the generated example project (default: \\"react-native@latest\\")
--example-react-native-version [exampleReactNativeVersion] React Native template version for the generated example project, for example: react-native-tvos or [email protected] (requires --tvos-enabled option); [email protected] (default: \\"react-native@latest\\")
--write-example-podfile [iOS] EXPERIMENTAL FEATURE NOT SUPPORTED: write (or overwrite) example ios/Podfile
-h, --help display help for command"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Object {
},
Object {
"command": "--generate-example",
"description": "Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires both react-native-cli and yarn to be installed globally",
"description": "Generate an example project and add the library module to it with symlink by defult, with overwrite of example metro.config.js to add workaround for Metro symlink issue - requires Yarn to be installed globally",
},
Object {
"command": "--example-file-linkage",
Expand All @@ -82,7 +82,7 @@ Object {
Object {
"command": "--example-react-native-version [exampleReactNativeVersion]",
"default": "react-native@latest",
"description": "React Native version for the generated example project",
"description": "React Native template version for the generated example project, for example: react-native-tvos or [email protected] (requires --tvos-enabled option); [email protected]",
},
Object {
"command": "--write-example-podfile",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

exports[`create alice-bobbi view module with example, with defaults 1`] = `
Array [
"* execa.commandSync command: react-native --version options: {\\"stdio\\":\\"inherit\\"}
",
"* execa.commandSync command: yarn --version options: {\\"stdio\\":\\"inherit\\"}
",
"* ensureDir dir: react-native-alice-bobbi
Expand Down Expand Up @@ -792,13 +790,21 @@ content:
<<<<<<<< ======== >>>>>>>>
",
"* execa.commandSync command: react-native init example --version react-native@latest options: {\\"cwd\\":\\"./react-native-alice-bobbi\\",\\"stdio\\":\\"inherit\\"}
",
"* ensureDir dir: react-native-alice-bobbi/example/
Object {
"call": "reactNativeInit",
"nameArray": Array [
"example",
],
"options": Object {
"directory": "react-native-alice-bobbi/example",
"template": "react-native@latest",
},
},
"* ensureDir dir: .../react-native-alice-bobbi/example/
",
"* ensureDir dir: react-native-alice-bobbi/example/
"* ensureDir dir: .../react-native-alice-bobbi/example/
",
"* outputFile name: react-native-alice-bobbi/example/metro.config.js
"* outputFile name: .../react-native-alice-bobbi/example/metro.config.js
content:
--------
// metro.config.js
Expand Down Expand Up @@ -832,7 +838,7 @@ module.exports = {
<<<<<<<< ======== >>>>>>>>
",
"* outputFile name: react-native-alice-bobbi/example/App.js
"* outputFile name: .../react-native-alice-bobbi/example/App.js
content:
--------
/**
Expand Down Expand Up @@ -883,11 +889,11 @@ const styles = StyleSheet.create({
<<<<<<<< ======== >>>>>>>>
",
"* execa.commandSync command: yarn add link:../ options: {\\"cwd\\":\\"./react-native-alice-bobbi/example\\",\\"stdio\\":\\"inherit\\"}
"* execa.commandSync command: yarn add link:../ options: {\\"cwd\\":\\".../react-native-alice-bobbi/example\\",\\"stdio\\":\\"inherit\\"}
",
"* execa.commandSync command: pod --version options: {\\"cwd\\":\\"./react-native-alice-bobbi/example/ios\\",\\"stdio\\":\\"inherit\\"}
"* execa.commandSync command: pod --version options: {\\"cwd\\":\\".../react-native-alice-bobbi/example/ios\\",\\"stdio\\":\\"inherit\\"}
",
"* execa.commandSync command: pod install options: {\\"cwd\\":\\"./react-native-alice-bobbi/example/ios\\",\\"stdio\\":\\"inherit\\"}
"* execa.commandSync command: pod install options: {\\"cwd\\":\\".../react-native-alice-bobbi/example/ios\\",\\"stdio\\":\\"inherit\\"}
",
]
`;
Loading

0 comments on commit 56e7dbf

Please sign in to comment.