Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.6.0 updates part 1 #32

Merged
merged 31 commits into from
Jul 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b8506d1
Add example project name parameter
timojaask May 8, 2019
3d4200f
WIP
timojaask May 8, 2019
9186f26
Fix setting example project name
timojaask May 8, 2019
70cac8e
Fix .npmignore template to support custom example name
timojaask May 9, 2019
caac2b3
Pass exampleName to example template
timojaask May 9, 2019
d510ee0
Pass exampleName to comments in example template
timojaask May 9, 2019
3c738ae
Set podspec name to module name for conventions
timojaask May 9, 2019
658be86
Add AFNetworking pod to library as an example
timojaask May 9, 2019
4c12ca1
Add description, which is inherited and required by podspec
timojaask May 9, 2019
69e2ffa
Add ios example podfile
timojaask May 9, 2019
727a2be
Add AFNetworking test code
timojaask May 10, 2019
1700472
Add use cocoapods flag
timojaask May 10, 2019
8d4f516
Fix formatting
timojaask May 10, 2019
f0947e7
Fix Podfile generator but where module was hardcoded
timojaask May 10, 2019
1acf3e7
Make TestLibrary.xcworkspace compilable on its own
timojaask May 13, 2019
06020fa
Revert "Fix Podfile generator but where module was hardcoded"
timojaask May 13, 2019
07e76dd
Remove the Podfile from library ios project, because it messes up exa…
timojaask May 13, 2019
a12cbe8
Fix hardcoded target name in example Podfile
timojaask May 15, 2019
128798b
Quick lint fixes to templates/ios.js
Jul 7, 2019
e936f6f
Other lint fixes
Jul 7, 2019
abc2d05
eslint updates in devDependencies
Jul 7, 2019
0363059
Bump version to 0.6.0-dev
Jul 10, 2019
467b0ef
update-notifier@3 update
Jul 10, 2019
06622af
Cleanup & fix generateExampleWithName in lib.js
Jul 10, 2019
71e8724
Update doc for exampleName & useCocoapods options
Jul 10, 2019
64272c2
Completely remove npm fallback for example
Jul 10, 2019
1345354
Updated TODO comments in generated code
Jul 10, 2019
a6007f9
factor duplicated keys out of command.js
Jul 10, 2019
b150523
Fix some more fields in generated podspec
Jul 10, 2019
27ff5f3
Add exampleReactNativeVersion option
Jul 11, 2019
8ecfd80
eslint-config-standard@13 update in devDependencies
Jul 16, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ Options:
--author-email <authorEmail> The author's email (Default: `yourname@email.com`)
--license <license> The license type (Default: `Apache-2.0`)
--view Generate the module as a very simple native view component
--use-cocoapods Generate a library with a sample podspec and third party pod usage example
--generate-example Generate an example project and links the library module to it, requires both react-native-cli and yarn to be installed globally
--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@0.59`)
-h, --help output usage information
```

Expand Down Expand Up @@ -113,8 +116,11 @@ createLibraryModule({
authorName: String, /* The author's name (Default: `Your Name`) */
authorEmail: String, /* The author's email (Default: `yourname@email.com`) */
license: String, /* The license type of this library (Default: `Apache-2.0`) */
useCocoapods: Boolean, /* Generate a library with a sample podspec and third party pod usage example (Default: false) */
view: Boolean, /* Generate the module as a very simple native view component (Default: false) */
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) */
exampleName: String, /* Name for the example project (Default: `example`) */
exampleReactNativeVersion: String, /* React Native version for the generated example project (Default: `react-native@0.59`) */
}
```

Expand Down
64 changes: 38 additions & 26 deletions command.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,55 @@ const normalizedOptions = require('./normalized-options');

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

const postCreateInstructions = ({ moduleName, useCocoapods, exampleName }) => {
return `
====================================================
YOU'RE ALL SET!

To build and run iOS example project, do:
----
cd ${moduleName}/${exampleName}
yarn
${useCocoapods ? `cd ios
pod install
cd ..
`
: ``}react-native run-ios
----
`;
};

module.exports = {
name: 'create-library',
description: 'creates a React Native library module for one or more platforms',
usage: '[options] <name>',
func: (args, config, options) => {
const name = args[0];
const prefix = options.prefix;
const moduleName = options.moduleName;
const modulePrefix = options.modulePrefix;
const packageIdentifier = options.packageIdentifier;
const platforms = (options.platforms) ? options.platforms.split(',') : options.platforms;
const githubAccount = options.githubAccount;
const authorName = options.authorName;
const authorEmail = options.authorEmail;
const license = options.license;
const view = options.view;
const generateExample = options.generateExample;

const beforeCreation = Date.now();

const platforms = (options.platforms)
? options.platforms.split(',') : options.platforms;

const preNormalizedOptions = Object.assign({}, { name }, options, {
platforms
});

// NOTE: There is a trick where the new normalizedOptions()
// from normalized-options.js is applied by both command.js & lib.js.
// This is to ensure that the CLI gets the correct module name for the
// final log message, and that the exported programmatic
// function can be completely tested from using the CLI.

const createOptions = normalizedOptions({
name,
prefix,
moduleName,
modulePrefix,
packageIdentifier,
platforms,
githubAccount,
authorName,
authorEmail,
license,
view,
generateExample,
});
const createOptions = normalizedOptions(preNormalizedOptions);

const rootModuleName = createOptions.moduleName;

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

Expand Down Expand Up @@ -98,8 +99,19 @@ ${emoji.get('arrow_right')} To get started type \`cd ./${rootModuleName}\` and
}, {
command: '--view',
description: 'Generate the module as a very simple native view component',
}, {
command: '--use-cocoapods',
description: 'Generate a library with a sample podspec and third party pod usage example',
}, {
command: '--generate-example',
description: 'Generate an example project and links the library module to it, requires both react-native-cli and yarn to be installed globally',
}, {
command: '--example-name [exampleName]',
description: 'Name for the example project',
default: 'example',
}, {
command: '--example-react-native-version [exampleReactNativeVersion]',
description: 'React Native version for the generated example project',
default: 'react-native@0.59',
}]
};
31 changes: 22 additions & 9 deletions lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ const DEFAULT_GITHUB_ACCOUNT = 'github_account';
const DEFAULT_AUTHOR_NAME = 'Your Name';
const DEFAULT_AUTHOR_EMAIL = 'yourname@email.com';
const DEFAULT_LICENSE = 'Apache-2.0';
const DEFAULT_USE_COCOAPODS = false;
const DEFAULT_GENERATE_EXAMPLE = false;
const DEFAULT_EXAMPLE_NAME = 'example';
const DEFAULT_EXAMPLE_REACT_NATIVE_VERSION = 'react-native@0.59';

const renderTemplateIfValid = (root, template, templateArgs) => {
const name = template.name(templateArgs);
Expand Down Expand Up @@ -44,7 +47,10 @@ const generateWithOptions = ({
authorEmail = DEFAULT_AUTHOR_EMAIL,
license = DEFAULT_LICENSE,
view = false,
useCocoapods = DEFAULT_USE_COCOAPODS,
generateExample = DEFAULT_GENERATE_EXAMPLE,
exampleName = DEFAULT_EXAMPLE_NAME,
exampleReactNativeVersion = DEFAULT_EXAMPLE_REACT_NATIVE_VERSION,
}) => {
if (packageIdentifier === DEFAULT_PACKAGE_IDENTIFIER) {
console.warn(`While \`{DEFAULT_PACKAGE_IDENTIFIER}\` is the default package
Expand All @@ -70,7 +76,9 @@ const generateWithOptions = ({
authorEmail: ${authorEmail}
license: ${license}
view: ${view}
useCocoapods: ${useCocoapods}
generateExample: ${generateExample}
exampleName: ${exampleName}
`);

if (generateExample) {
Expand Down Expand Up @@ -124,7 +132,9 @@ const generateWithOptions = ({
authorEmail,
license,
view,
useCocoapods,
generateExample,
exampleName,
};

return renderTemplateIfValid(moduleName, template, templateArgs);
Expand All @@ -135,14 +145,15 @@ const generateWithOptions = ({
// The separate promise makes it easier to generate
// multiple test/sample projects, if needed.
const generateExampleWithName =
(exampleName, commandOptions) => {
console.info('CREATE: Generating the example app');
(exampleName) => {
const exampleReactNativeInitCommand =
`react-native init ${exampleName} --version ${exampleReactNativeVersion}`;

console.info(
`CREATE example app with the following command: ${exampleReactNativeInitCommand}`);

const addOptions = commandOptions
? ` ${commandOptions}`
: '';
const execOptions = { cwd: `./${moduleName}`, stdio: 'inherit' };
return exec(`react-native init ${exampleName}${addOptions}`, execOptions)
return exec(exampleReactNativeInitCommand, execOptions)
.then(() => {
// Execute the example template
const exampleTemplates = require('./templates/example');
Expand All @@ -151,6 +162,8 @@ const generateWithOptions = ({
name: className,
moduleName,
view,
useCocoapods,
exampleName,
};

return Promise.all(
Expand All @@ -176,8 +189,8 @@ const generateWithOptions = ({
try {
execSync('yarn add file:../', addLinkLibraryOptions);
} catch (e) {
execSync('npm install ../', addLinkLibraryOptions);
execSync('npm install', addLinkLibraryOptions);
console.error('Yarn failure for example, aborting');
throw (e);
}
execSync('react-native link', addLinkLibraryOptions);

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

return generateWithoutExample().then(() => {
return (generateExample
? generateExampleWithName('example')
? generateExampleWithName(exampleName)
: Promise.resolve()
);
});
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-react-native-module",
"version": "0.5.1-dev",
"version": "0.6.0-dev",
"description": "Tool to create a React Native library module or view module with a single command",
"bin": "cli.js",
"main": "lib.js",
Expand Down Expand Up @@ -47,15 +47,15 @@
"node-emoji": "^1.10.0",
"param-case": "^2.1.1",
"pascal-case": "^2.0.1",
"update-notifier": "^2.5.0",
"update-notifier": "^3.0.1",
"uuid": "^3.3.2"
},
"devDependencies": {
"eslint": "^5.16.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.1.1",
"eslint": "^6.0.1",
"eslint-config-standard": "^13.0.1",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-node": "^9.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"shelljs": "^0.8.3"
},
Expand Down
4 changes: 2 additions & 2 deletions templates/android.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public class ${name}Module extends ReactContextBaseJavaModule {

@ReactMethod
public void sampleMethod(String stringArgument, int numberArgument, Callback callback) {
// TODO: Implement some real useful functionality
// TODO: Implement some actually useful functionality
callback.invoke("Received numberArgument: " + numberArgument + " stringArgument: " + stringArgument);
}
}
Expand Down Expand Up @@ -196,7 +196,7 @@ public class ${name}Manager extends SimpleViewManager<View> {

@Override
public View createViewInstance(ThemedReactContext c) {
// TODO: Implement some real useful functionality
// TODO: Implement some actually useful functionality
AppCompatCheckBox cb = new AppCompatCheckBox(c);
cb.setChecked(true);
return cb;
Expand Down
43 changes: 39 additions & 4 deletions templates/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module.exports = [{
name: () => 'scripts/examples_postinstall.js',
content: () =>
content: ({ exampleName }) =>
`#!/usr/bin/env node

/*
Expand Down Expand Up @@ -50,7 +50,7 @@ module.exports = [{
fs.rmdirSync(fileDirPath);
};

/// Remove example/node_modules/react-native-library-name/node_modules directory
/// Remove ${exampleName}/node_modules/react-native-library-name/node_modules directory
const removeLibraryNodeModulesPath = (libraryNodeModulesPath) => {
const nodeModulesPath = path.resolve(libraryNodeModulesPath, 'node_modules')

Expand All @@ -68,7 +68,7 @@ module.exports = [{
}
};

/// Remove all entries from the .npmignore within example/node_modules/react-native-library-name/
/// Remove all entries from the .npmignore within ${exampleName}/node_modules/react-native-library-name/
const removeLibraryNpmIgnorePaths = (npmIgnorePath, libraryNodeModulesPath) => {
if (!fs.existsSync(npmIgnorePath)) {
console.log(\`No .npmignore path found at \${npmIgnorePath}. Skipping deleting content.\`);
Expand Down Expand Up @@ -116,7 +116,42 @@ module.exports = [{
})();
`
}, {
name: () => 'example/App.js',
name: ({ useCocoapods, exampleName }) =>
useCocoapods ? `${exampleName}/ios/Podfile` : undefined,
content: ({ moduleName, exampleName }) => `platform :ios, '10.0'

target '${exampleName}' do
rn_path = '../node_modules/react-native'

pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec"
pod 'DoubleConversion', :podspec => "#{rn_path}/third-party-podspecs/DoubleConversion.podspec"
pod 'Folly', :podspec => "#{rn_path}/third-party-podspecs/Folly.podspec"
pod 'glog', :podspec => "#{rn_path}/third-party-podspecs/GLog.podspec"
pod 'React', path: rn_path, subspecs: [
'Core',
'CxxBridge',
'RCTAnimation',
'RCTActionSheet',
'RCTImage',
'RCTLinkingIOS',
'RCTNetwork',
'RCTSettings',
'RCTText',
'RCTVibration',
'RCTWebSocket',
'RCTPushNotification',
'RCTCameraRoll',
'RCTSettings',
'RCTBlob',
'RCTGeolocation',
'DevSupport'
]

pod '${moduleName}', :path => '../../${moduleName}.podspec'
end
`,
}, {
name: ({ exampleName }) => `${exampleName}/App.js`,
content: ({ moduleName, name, view }) =>
`/**
* Sample React Native App
Expand Down
6 changes: 3 additions & 3 deletions templates/general.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ ${name};
"name": "${moduleName}",
"title": "${moduleName.split('-').map(word => word[0].toUpperCase() + word.substr(1)).join(' ')}",
"version": "1.0.0",
"description": "",
"description": "TODO",
"main": "index.js",
"scripts": {
"test": "echo \\"Error: no test specified\\" && exit 1"
Expand Down Expand Up @@ -214,9 +214,9 @@ buck-out/
}
}, {
name: () => '.npmignore',
content: ({ generateExample }) => {
content: ({ generateExample, exampleName }) => {
if (generateExample) {
return 'example\n';
return `${exampleName}\n`;
}

return '';
Expand Down
Loading