Skip to content

Commit 81f8109

Browse files
author
Chris Brody
authored
Merge pull request #32 from brodybits/0.6.0-part-1
0.6.0 updates part 1
2 parents 417a88b + 8ecfd80 commit 81f8109

File tree

9 files changed

+554
-244
lines changed

9 files changed

+554
-244
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ Options:
8383
--author-email <authorEmail> The author's email (Default: `[email protected]`)
8484
--license <license> The license type (Default: `Apache-2.0`)
8585
--view Generate the module as a very simple native view component
86+
--use-cocoapods Generate a library with a sample podspec and third party pod usage example
8687
--generate-example Generate an example project and links the library module to it, requires both react-native-cli and yarn to be installed globally
88+
--example-name <exampleName> Name for the example project (default: `example`)
89+
--example-react-native-version <version> React Native version for the generated example project (default: `[email protected]`)
8790
-h, --help output usage information
8891
```
8992

@@ -113,8 +116,11 @@ createLibraryModule({
113116
authorName: String, /* The author's name (Default: `Your Name`) */
114117
authorEmail: String, /* The author's email (Default: `[email protected]`) */
115118
license: String, /* The license type of this library (Default: `Apache-2.0`) */
119+
useCocoapods: Boolean, /* Generate a library with a sample podspec and third party pod usage example (Default: false) */
116120
view: Boolean, /* Generate the module as a very simple native view component (Default: false) */
117121
generateExample: Boolean, /* Generate an example project and links the library module to it, requires both react-native-cli and yarn to be installed globally (Default: false) */
122+
exampleName: String, /* Name for the example project (Default: `example`) */
123+
exampleReactNativeVersion: String, /* React Native version for the generated example project (Default: `[email protected]`) */
118124
}
119125
```
120126

command.js

+38-26
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,55 @@ const normalizedOptions = require('./normalized-options');
44

55
const createLibraryModule = require('./lib');
66

7+
const postCreateInstructions = ({ moduleName, useCocoapods, exampleName }) => {
8+
return `
9+
====================================================
10+
YOU'RE ALL SET!
11+
12+
To build and run iOS example project, do:
13+
----
14+
cd ${moduleName}/${exampleName}
15+
yarn
16+
${useCocoapods ? `cd ios
17+
pod install
18+
cd ..
19+
`
20+
: ``}react-native run-ios
21+
----
22+
`;
23+
};
24+
725
module.exports = {
826
name: 'create-library',
927
description: 'creates a React Native library module for one or more platforms',
1028
usage: '[options] <name>',
1129
func: (args, config, options) => {
1230
const name = args[0];
13-
const prefix = options.prefix;
14-
const moduleName = options.moduleName;
15-
const modulePrefix = options.modulePrefix;
16-
const packageIdentifier = options.packageIdentifier;
17-
const platforms = (options.platforms) ? options.platforms.split(',') : options.platforms;
18-
const githubAccount = options.githubAccount;
19-
const authorName = options.authorName;
20-
const authorEmail = options.authorEmail;
21-
const license = options.license;
22-
const view = options.view;
23-
const generateExample = options.generateExample;
2431

2532
const beforeCreation = Date.now();
2633

34+
const platforms = (options.platforms)
35+
? options.platforms.split(',') : options.platforms;
36+
37+
const preNormalizedOptions = Object.assign({}, { name }, options, {
38+
platforms
39+
});
40+
2741
// NOTE: There is a trick where the new normalizedOptions()
2842
// from normalized-options.js is applied by both command.js & lib.js.
2943
// This is to ensure that the CLI gets the correct module name for the
3044
// final log message, and that the exported programmatic
3145
// function can be completely tested from using the CLI.
3246

33-
const createOptions = normalizedOptions({
34-
name,
35-
prefix,
36-
moduleName,
37-
modulePrefix,
38-
packageIdentifier,
39-
platforms,
40-
githubAccount,
41-
authorName,
42-
authorEmail,
43-
license,
44-
view,
45-
generateExample,
46-
});
47+
const createOptions = normalizedOptions(preNormalizedOptions);
4748

4849
const rootModuleName = createOptions.moduleName;
4950

5051
createLibraryModule(createOptions).then(() => {
5152
console.log(`
5253
${emoji.get('books')} Created library module ${rootModuleName} in \`./${rootModuleName}\`.
5354
${emoji.get('clock9')} It took ${Date.now() - beforeCreation}ms.
54-
${emoji.get('arrow_right')} To get started type \`cd ./${rootModuleName}\` and run \`npm install\``);
55+
${postCreateInstructions(createOptions)}`);
5556
}).catch((err) => {
5657
console.error(`Error while creating library module ${rootModuleName}`);
5758

@@ -98,8 +99,19 @@ ${emoji.get('arrow_right')} To get started type \`cd ./${rootModuleName}\` and
9899
}, {
99100
command: '--view',
100101
description: 'Generate the module as a very simple native view component',
102+
}, {
103+
command: '--use-cocoapods',
104+
description: 'Generate a library with a sample podspec and third party pod usage example',
101105
}, {
102106
command: '--generate-example',
103107
description: 'Generate an example project and links the library module to it, requires both react-native-cli and yarn to be installed globally',
108+
}, {
109+
command: '--example-name [exampleName]',
110+
description: 'Name for the example project',
111+
default: 'example',
112+
}, {
113+
command: '--example-react-native-version [exampleReactNativeVersion]',
114+
description: 'React Native version for the generated example project',
115+
default: '[email protected]',
104116
}]
105117
};

lib.js

+22-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ const DEFAULT_GITHUB_ACCOUNT = 'github_account';
1313
const DEFAULT_AUTHOR_NAME = 'Your Name';
1414
const DEFAULT_AUTHOR_EMAIL = '[email protected]';
1515
const DEFAULT_LICENSE = 'Apache-2.0';
16+
const DEFAULT_USE_COCOAPODS = false;
1617
const DEFAULT_GENERATE_EXAMPLE = false;
18+
const DEFAULT_EXAMPLE_NAME = 'example';
19+
const DEFAULT_EXAMPLE_REACT_NATIVE_VERSION = '[email protected]';
1720

1821
const renderTemplateIfValid = (root, template, templateArgs) => {
1922
const name = template.name(templateArgs);
@@ -44,7 +47,10 @@ const generateWithOptions = ({
4447
authorEmail = DEFAULT_AUTHOR_EMAIL,
4548
license = DEFAULT_LICENSE,
4649
view = false,
50+
useCocoapods = DEFAULT_USE_COCOAPODS,
4751
generateExample = DEFAULT_GENERATE_EXAMPLE,
52+
exampleName = DEFAULT_EXAMPLE_NAME,
53+
exampleReactNativeVersion = DEFAULT_EXAMPLE_REACT_NATIVE_VERSION,
4854
}) => {
4955
if (packageIdentifier === DEFAULT_PACKAGE_IDENTIFIER) {
5056
console.warn(`While \`{DEFAULT_PACKAGE_IDENTIFIER}\` is the default package
@@ -70,7 +76,9 @@ const generateWithOptions = ({
7076
authorEmail: ${authorEmail}
7177
license: ${license}
7278
view: ${view}
79+
useCocoapods: ${useCocoapods}
7380
generateExample: ${generateExample}
81+
exampleName: ${exampleName}
7482
`);
7583

7684
if (generateExample) {
@@ -124,7 +132,9 @@ const generateWithOptions = ({
124132
authorEmail,
125133
license,
126134
view,
135+
useCocoapods,
127136
generateExample,
137+
exampleName,
128138
};
129139

130140
return renderTemplateIfValid(moduleName, template, templateArgs);
@@ -135,14 +145,15 @@ const generateWithOptions = ({
135145
// The separate promise makes it easier to generate
136146
// multiple test/sample projects, if needed.
137147
const generateExampleWithName =
138-
(exampleName, commandOptions) => {
139-
console.info('CREATE: Generating the example app');
148+
(exampleName) => {
149+
const exampleReactNativeInitCommand =
150+
`react-native init ${exampleName} --version ${exampleReactNativeVersion}`;
151+
152+
console.info(
153+
`CREATE example app with the following command: ${exampleReactNativeInitCommand}`);
140154

141-
const addOptions = commandOptions
142-
? ` ${commandOptions}`
143-
: '';
144155
const execOptions = { cwd: `./${moduleName}`, stdio: 'inherit' };
145-
return exec(`react-native init ${exampleName}${addOptions}`, execOptions)
156+
return exec(exampleReactNativeInitCommand, execOptions)
146157
.then(() => {
147158
// Execute the example template
148159
const exampleTemplates = require('./templates/example');
@@ -151,6 +162,8 @@ const generateWithOptions = ({
151162
name: className,
152163
moduleName,
153164
view,
165+
useCocoapods,
166+
exampleName,
154167
};
155168

156169
return Promise.all(
@@ -176,8 +189,8 @@ const generateWithOptions = ({
176189
try {
177190
execSync('yarn add file:../', addLinkLibraryOptions);
178191
} catch (e) {
179-
execSync('npm install ../', addLinkLibraryOptions);
180-
execSync('npm install', addLinkLibraryOptions);
192+
console.error('Yarn failure for example, aborting');
193+
throw (e);
181194
}
182195
execSync('react-native link', addLinkLibraryOptions);
183196

@@ -188,7 +201,7 @@ const generateWithOptions = ({
188201

189202
return generateWithoutExample().then(() => {
190203
return (generateExample
191-
? generateExampleWithName('example')
204+
? generateExampleWithName(exampleName)
192205
: Promise.resolve()
193206
);
194207
});

package.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "create-react-native-module",
3-
"version": "0.5.1-dev",
3+
"version": "0.6.0-dev",
44
"description": "Tool to create a React Native library module or view module with a single command",
55
"bin": "cli.js",
66
"main": "lib.js",
@@ -47,15 +47,15 @@
4747
"node-emoji": "^1.10.0",
4848
"param-case": "^2.1.1",
4949
"pascal-case": "^2.0.1",
50-
"update-notifier": "^2.5.0",
50+
"update-notifier": "^3.0.1",
5151
"uuid": "^3.3.2"
5252
},
5353
"devDependencies": {
54-
"eslint": "^5.16.0",
55-
"eslint-config-standard": "^12.0.0",
56-
"eslint-plugin-import": "^2.16.0",
57-
"eslint-plugin-node": "^8.0.1",
58-
"eslint-plugin-promise": "^4.1.1",
54+
"eslint": "^6.0.1",
55+
"eslint-config-standard": "^13.0.1",
56+
"eslint-plugin-import": "^2.18.0",
57+
"eslint-plugin-node": "^9.1.0",
58+
"eslint-plugin-promise": "^4.2.1",
5959
"eslint-plugin-standard": "^4.0.0",
6060
"shelljs": "^0.8.3"
6161
},

templates/android.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public class ${name}Module extends ReactContextBaseJavaModule {
164164
165165
@ReactMethod
166166
public void sampleMethod(String stringArgument, int numberArgument, Callback callback) {
167-
// TODO: Implement some real useful functionality
167+
// TODO: Implement some actually useful functionality
168168
callback.invoke("Received numberArgument: " + numberArgument + " stringArgument: " + stringArgument);
169169
}
170170
}
@@ -196,7 +196,7 @@ public class ${name}Manager extends SimpleViewManager<View> {
196196
197197
@Override
198198
public View createViewInstance(ThemedReactContext c) {
199-
// TODO: Implement some real useful functionality
199+
// TODO: Implement some actually useful functionality
200200
AppCompatCheckBox cb = new AppCompatCheckBox(c);
201201
cb.setChecked(true);
202202
return cb;

templates/example.js

+39-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module.exports = [{
44
name: () => 'scripts/examples_postinstall.js',
5-
content: () =>
5+
content: ({ exampleName }) =>
66
`#!/usr/bin/env node
77
88
/*
@@ -50,7 +50,7 @@ module.exports = [{
5050
fs.rmdirSync(fileDirPath);
5151
};
5252
53-
/// Remove example/node_modules/react-native-library-name/node_modules directory
53+
/// Remove ${exampleName}/node_modules/react-native-library-name/node_modules directory
5454
const removeLibraryNodeModulesPath = (libraryNodeModulesPath) => {
5555
const nodeModulesPath = path.resolve(libraryNodeModulesPath, 'node_modules')
5656
@@ -68,7 +68,7 @@ module.exports = [{
6868
}
6969
};
7070
71-
/// Remove all entries from the .npmignore within example/node_modules/react-native-library-name/
71+
/// Remove all entries from the .npmignore within ${exampleName}/node_modules/react-native-library-name/
7272
const removeLibraryNpmIgnorePaths = (npmIgnorePath, libraryNodeModulesPath) => {
7373
if (!fs.existsSync(npmIgnorePath)) {
7474
console.log(\`No .npmignore path found at \${npmIgnorePath}. Skipping deleting content.\`);
@@ -116,7 +116,42 @@ module.exports = [{
116116
})();
117117
`
118118
}, {
119-
name: () => 'example/App.js',
119+
name: ({ useCocoapods, exampleName }) =>
120+
useCocoapods ? `${exampleName}/ios/Podfile` : undefined,
121+
content: ({ moduleName, exampleName }) => `platform :ios, '10.0'
122+
123+
target '${exampleName}' do
124+
rn_path = '../node_modules/react-native'
125+
126+
pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec"
127+
pod 'DoubleConversion', :podspec => "#{rn_path}/third-party-podspecs/DoubleConversion.podspec"
128+
pod 'Folly', :podspec => "#{rn_path}/third-party-podspecs/Folly.podspec"
129+
pod 'glog', :podspec => "#{rn_path}/third-party-podspecs/GLog.podspec"
130+
pod 'React', path: rn_path, subspecs: [
131+
'Core',
132+
'CxxBridge',
133+
'RCTAnimation',
134+
'RCTActionSheet',
135+
'RCTImage',
136+
'RCTLinkingIOS',
137+
'RCTNetwork',
138+
'RCTSettings',
139+
'RCTText',
140+
'RCTVibration',
141+
'RCTWebSocket',
142+
'RCTPushNotification',
143+
'RCTCameraRoll',
144+
'RCTSettings',
145+
'RCTBlob',
146+
'RCTGeolocation',
147+
'DevSupport'
148+
]
149+
150+
pod '${moduleName}', :path => '../../${moduleName}.podspec'
151+
end
152+
`,
153+
}, {
154+
name: ({ exampleName }) => `${exampleName}/App.js`,
120155
content: ({ moduleName, name, view }) =>
121156
`/**
122157
* Sample React Native App

templates/general.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ ${name};
9999
"name": "${moduleName}",
100100
"title": "${moduleName.split('-').map(word => word[0].toUpperCase() + word.substr(1)).join(' ')}",
101101
"version": "1.0.0",
102-
"description": "",
102+
"description": "TODO",
103103
"main": "index.js",
104104
"scripts": {
105105
"test": "echo \\"Error: no test specified\\" && exit 1"
@@ -214,9 +214,9 @@ buck-out/
214214
}
215215
}, {
216216
name: () => '.npmignore',
217-
content: ({ generateExample }) => {
217+
content: ({ generateExample, exampleName }) => {
218218
if (generateExample) {
219-
return 'example\n';
219+
return `${exampleName}\n`;
220220
}
221221

222222
return '';

0 commit comments

Comments
 (0)