Skip to content

Commit

Permalink
v1.2 CLI
Browse files Browse the repository at this point in the history
Change list:

1. Creating a zero-configuration CLI.
2. Updated ReadMe with how to use the CLI.
3. Re-ordering directories and cleanup of unused code.
4. default rootElement now will be a new element instead of searching for an arbitrary className.
  • Loading branch information
NoamELB authored Oct 13, 2017
2 parents 74409fd + b6454b7 commit 689ec54
Show file tree
Hide file tree
Showing 29 changed files with 692 additions and 79 deletions.
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: ./node_modules/.bin/rollup -c rollup-build.config.js -o dist/index.js -f iife -n UiZoo -g underscore:_,react:React,react-dom:ReactDOM,react-router-dom:ReactRouterDOM,doctrine:doctrine-standalone,babel-standalone:Babel && node server/main.js
web: ./node_modules/.bin/rollup -c rollup.config.js -o dist/index.js -f iife -n UiZoo && node lib/server/main.js
45 changes: 28 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,51 @@ This tool can be used for developing, for Product Managers to know what is possi
![React UiZoo 3](https://imgur.com/f3B2TDj.gif)

## How To UiZoo?
Git clone by:

Just use our zero-configuration CLI! it's easy as pie! 🍽

```
git clone [email protected]:myheritage/uizoo.js.git
npm i -g uizoo
```
then

In a directory, do:
```
cd uizoo.js && npm i
gulp
uizoo
```
This will start a server on http://localhost:5000 with the UiZoo
you can change the [components file](https://github.com/myheritage/uizoo.js/blob/master/client/components.js) and the [documentation file](https://github.com/myheritage/uizoo.js/blob/master/client/documentation.js) to start rapidly.
We recommend updating those files by a script automatically when files are changing (we plan to create plugins to help with this in the next future).

*or* npm install by:
It will create a [webpack development server](https://webpack.js.org/configuration/dev-server/) fully configured with [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/) to watch your files while you develop!

For example:

![React UiZoo CLI](https://imgur.com/v3PbP8U.gif)

Start the server with the newly added script:
```
npm i -S uizoo
npm start uizoo
```
then in your code, add:

### Customization
The CLI creates a directory called `uizoo-app`, in it there is a file called `config.js` that determine basic stuff like the server's port, glob to find your components and more. There is also a very simple webpack configuration called `webpack.uizoo.js`.


### Local installation
*If you don't want to install UiZoo globally, you can instead do:*
```
import 'uizoo/dist/index.css';
import UiZoo from 'uizoo';
UiZoo.init(documentation, components, rootElement);
npm i -D uizoo && ./node_modules/.bin/uizoo
```

### init
### API
```
import UiZoo from 'uizoo';
UiZoo.init(documentation: Object, components: Object, rootElement: HTMLElement?, baseRoute: String?)
```

**documentation** - Object, mapping of component name to its documentation. See [example](https://github.com/myheritage/uizoo.js/blob/master/client/documentation.js).

**components** - Object, mapping of components name to components. See [example](https://github.com/myheritage/uizoo.js/blob/master/client/components.js).

**rootElement** - HTMLElement, will bootstrap UiZoo on that Element. Default is an element with the id 'library-_-root'
**rootElement** - HTMLElement, will bootstrap UiZoo on that Element. Default is a new element on the body.

**baseRoute** Route to be the base before the UiZoo routes. Default to '/'. for example if the UiZoo is on your site like so: 'www.mysite.com/my/zoo/', the base route should be '/my/zoo/'.

Expand Down Expand Up @@ -108,7 +119,7 @@ To add tests, use the following steps -

First, make sure the app is up and running:
```
gulp
npm start
```
The first time tests are run, install the npm dependencies:
```
Expand Down
12 changes: 12 additions & 0 deletions bin/uizoo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env node

const chalk = require('chalk');
const logo = require('../lib/logo');
const log = console.log.bind(console);

log(`
Welcome to the ~
${chalk.bold(chalk.cyan(logo))}
`);

require('../lib/generate')();
1 change: 1 addition & 0 deletions client/Components/UI/Tooltip/UiTooltip/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import _ from 'underscore';

import {SIDES, SIDE_TOP, ALIGNMENTS, ALIGNMENT_CENTER, TRIGGER_EVENTS, TRIGGER_EVENT_HOVER} from './constants';
import './index.scss';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _ from 'underscore';
import {
SIDE_TOP,
SIDE_BOTTOM,
Expand Down
19 changes: 12 additions & 7 deletions client/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import './index.scss';
import React from 'react';
import ReactDOM from 'react-dom';
import _ from 'underscore';
import { BrowserRouter, Route } from 'react-router-dom';

import libraryData from './components';
Expand All @@ -9,22 +10,26 @@ import { checkDependencies } from './services/checkHealth';
import { createCompiler } from './services/compileWithContext';
import { parseDocumentation } from './services/parseDocumentation';
import App from './Components/App';
import mapComponentsByModule from "./services/componentByModuleMapper";
import mapComponentsByModule from './services/componentByModuleMapper';

const defaultRoot = document.getElementById('library-_-root');
window._extend = _.extend; // to be used instead of Object.assign

/**
* Init
* @param {Object} documentation
* @param {Object} components
* @param {HTMLElement} rootElement
* Init - render UiZoo with documentation and components mappings
* @param {Object} [documentation]
* @param {Object} [components]
* @param {HTMLElement} [rootElement] will default to a new element on the body
*/
function init(
documentation = libraryDocs,
components = libraryData,
rootElement = defaultRoot,
rootElement,
baseRoute = '/'
) {
if (!rootElement) {
rootElement = document.createElement('div');
document.body.appendChild(rootElement);
}
checkDependencies(documentation, components);

const compiler = createCompiler(components); // JSX compiler
Expand Down
2 changes: 1 addition & 1 deletion client/services/compileWithContext.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import _ from 'underscore';
import Babel from 'babel-standalone';
import * as Babel from 'babel-standalone';

export function createCompiler(context) {
const iframe = createIframe();
Expand Down
19 changes: 6 additions & 13 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
let gulp = require('gulp'),
rollup = require('rollup'),
getRollupConfig = require('./rollup.config'),
rConfig = require('./rollup.config'),
chalk = require('chalk'),
nodemon = require("gulp-nodemon"),
nodemon = require('gulp-nodemon'),
livereload = require('gulp-livereload'),
execSync = require("child_process").execSync;

Expand Down Expand Up @@ -31,28 +31,21 @@ gulp.task("watch", () => {

function bundleClient() {
updateDocumentation();
return rollup.rollup(getRollupConfig({external: ['underscore', 'react', 'react-dom', 'react-router-dom', 'doctrine-standalone', 'babel-standalone']}))
return rollup.rollup(rConfig)
.then(bundle => {
bundle.write({
format: 'iife',
file: 'dist/index.js',
globals: {
'underscore': '_',
'react': 'React',
'react-dom': 'ReactDOM',
'react-router-dom':'ReactRouterDOM',
'doctrine-standalone': 'doctrine',
'babel-standalone': 'Babel',
},
name: 'UiZoo',
globals: rConfig.globals
});
})
.catch(handleError);
}

function startNodemonServer() {
nodemonStream = nodemon({
script: './server/main.js',
script: './lib/server/main.js',
ext: 'js html',
watch: false,
})
Expand All @@ -78,7 +71,7 @@ function handleError(error) {

function updateDocumentation() {
try {
execSync(`node documentationMapper.js "./client/Components/UI/*/index.js" "./client/Components/UI/(.+)/index.js" "./client/documentation.js"`);
execSync(`node lib/scripts/documentationMapper.js "./client/Components/UI/*/index.js" "./client/Components/UI/(.+)/index.js" "./client/documentation.js"`);
}
catch (err) {
console.error(err.message);
Expand Down
1 change: 0 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<link rel="stylesheet" href="/dist/index.css">
</head>
<body>
<div id="library-_-root"></div>
<script src="/node_modules/underscore/underscore-min.js"></script>
<script src="/node_modules/react/umd/react.production.min.js"></script>
<script src="/node_modules/react-dom/umd/react-dom.production.min.js"></script>
Expand Down
39 changes: 39 additions & 0 deletions lib/generate/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const path = require('path');

const appFolderPath = path.resolve('uizoo-app');
const uiZooScript = `node ${path.join('uizoo-app', 'webpack.uizoo.js')}`;

const neededPackages = [
'uizoo',
'webpack',
'webpack-dev-server',
'babel-loader',
'babel-preset-env',
'babel-preset-react',
'babel-plugin-transform-object-rest-spread',
'babel-plugin-syntax-dynamic-import',
'style-loader',
'css-loader',
'fs-extra',
'glob-stream'
];

const templatesToCopy = [
'index.html',
'index.js',
'webpack.uizoo.js',
'createConfigsScript.js',
'componentsContainer.js',
'documentationContainer.js',
'config.js',
];

const log = console.log.bind(console);

module.exports = {
appFolderPath,
uiZooScript,
neededPackages,
templatesToCopy,
log
};
23 changes: 23 additions & 0 deletions lib/generate/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const fs = require('fs-extra');
const opn = require('opn');

const {updatePackageJson} = require('./packageJsonService');
const {copyTemplate} = require('./templatesService');
const {executeCommand} = require('./processService');
const {log, templatesToCopy, appFolderPath} = require('./config');

function generate() {
log(' ~ Copying templates...\n');
updatePackageJson()
.then(() => fs.ensureDir(appFolderPath))
.then(() => Promise.all(templatesToCopy.map(copyTemplate)))
.then(() => log(' ~ Executing commands...\n'))
.then(() => executeCommand('npm i'))
.then(() => {setTimeout(() => opn('http://localhost:5005/uizoo'), 2500)})
.then(() => log(' ~ Done! Executing `uizoo` script:\n'))
.then(() => executeCommand('npm run uizoo'))
.then(() => process.exit(0))
.catch(e => console.error(e));
}

module.exports = generate;
55 changes: 55 additions & 0 deletions lib/generate/packageJsonService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const path = require('path');
const latestVersion = require('latest-version');
const fs = require('fs-extra');
const {resolveTemplatePath} = require('./templatesService');
const {uiZooScript, neededPackages} = require('./config');

module.exports = {
updatePackageJson
};

/**
* Update the folder's package.json with needed dependencies or use a fresh one from templates
* if there is none
* @return {Promise}
*/
function updatePackageJson() {
return new Promise((resolve, reject) => {
const pkgPath = path.resolve('package.json');
const defaultPkgPath = resolveTemplatePath('package.json');

fs.exists(pkgPath)
.then(exists => fs.readFile(exists ? pkgPath : defaultPkgPath))
.then(modifyPackage)
.then(pkg => fs.writeJSON(pkgPath, pkg, {spaces: 2}))
.then(resolve)
.catch(reject);
});
}

function modifyPackage(packageBuffer) {
return new Promise((resolve, reject) => {
Promise.all(neededPackages.map(latestVersion))
.then(neededPackagesVersions => {
let pkg = JSON.parse(packageBuffer.toString());

// Add dependencies
neededPackages.forEach((neededPackage, i) => {
if((!pkg.dependencies || !pkg.dependencies[neededPackage]) &&
(!pkg.devDependencies || !pkg.devDependencies[neededPackage])) {

pkg.devDependencies = Object.assign({}, pkg.devDependencies, {
[neededPackage]: `~${neededPackagesVersions[i]}`
});
}
});

// Add scripts
pkg.scripts = Object.assign({}, pkg.scripts, {
"uizoo": uiZooScript
});
resolve(pkg);
})
.catch(reject);
});
}
21 changes: 21 additions & 0 deletions lib/generate/processService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const {spawn} = require('child_process');
const chalk = require('chalk');
const {log} = require('./config');

module.exports = {
executeCommand
};

/**
* Execute a command to terminal with inherit io, resolve when it is done
* @param {String} cmd
* @return {Promise}
*/
function executeCommand(cmd) {
return new Promise((resolve, reject) => {
log(chalk.grey(` ${cmd}\n`));
let cmdParts = cmd.split(' ');
const ls = spawn(cmdParts.shift(), [].concat(cmdParts), {stdio: "inherit"});
ls.on('close', resolve);
});
}
1 change: 1 addition & 0 deletions lib/generate/templates/componentsContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default null;
Loading

0 comments on commit 689ec54

Please sign in to comment.