├── .build
├── __app.js
├── index.html
└── index.js
├── .gitignore
├── README.markdown
├── index.js
├── package.json
├── processFile.js
├── setupFs.js
├── surge.js
└── watcher.js
/.build/__app.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var ReactDOM = require('react-dom');
3 | var AppRoot = require('../index');
4 |
5 | ReactDOM.render(
6 | ,
7 | document.getElementById('app')
8 | );
9 |
--------------------------------------------------------------------------------
/.build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.build/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brentvatne/resurge/50145ab90a2883803d7b78df053011ff315f9aa3/.build/index.js
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/**/*
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | ```
2 | ________ _______ ___________ ____
3 | / ___/ _ \/ ___/ / / / ___/ __ `/ _ \
4 | / / / __(__ ) /_/ / / / /_/ / __/
5 | /_/ \___/____/\__,_/_/ \__, /\___/
6 | /____/
7 | ```
8 |
9 | Make and share a small React project with minimal effort. In response to
10 | [@vjeux's fun challenge](https://twitter.com/Vjeux/status/680769537550102530).
11 |
12 | 1. `npm i resurge -g`
13 | 2. `mkdir your-project && cd your-project`
14 | 3. `touch index.js`, [add a React component](#sample-starter-app) and export it
15 | 4. Run `resurge`
16 |
17 | ### My project name is taken
18 |
19 | Rename the directory and try again? :p
20 |
21 | ### Commands
22 |
23 | - `resurge` will build and publish your app
24 | - `resurge --watch` will watch your directory for changes and publish
25 | them to surge automatically
26 | - `resurge --list` will show you apps you have deployed to surge.sh
27 |
28 | ### Can I use xyz?
29 |
30 | - Install any npm package you want. Your project will have react/react-dom by default.
31 | - This uses Babel/Browserfiy, with [stage-3](https://babeljs.io/docs/plugins/preset-stage-3/) and [react](http://babeljs.io/docs/plugins/preset-react/) plugins.
32 |
33 | ### Sample starter app
34 |
35 | ```javascript
36 | 'use strict';
37 | var React = require('react');
38 |
39 | class App extends React.Component {
40 | render() {
41 | return (
42 | Hello world
43 | );
44 | }
45 | }
46 |
47 | module.exports = App;
48 | ```
49 |
50 | ### Contribute
51 |
52 | - Feel free to contribute in any way you want as long as it doesn't make
53 | this project any more difficult to get into. Creating a new project
54 | and publishing it should never take more than the 4 simple steps
55 | described above.
56 | - You could make the CLI better, like this:
57 | https://github.com/sintaxi/harp/blob/ko-with-surge/bin/harp
58 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | const argv = require('yargs').argv;
5 | const surge = require('./surge');
6 | const processFile = require('./processFile');
7 | const fs = require('fs-extra');
8 | const main = 'index.js';
9 | const buildPath = `${process.cwd()}/.build`;
10 |
11 | if (argv.list) {
12 | surge.list();
13 | } else {
14 | // Copy node_modules over, this sucks but babel doesn't support multiple
15 | // sourceRoots right now :(
16 | require('./setupFs')();
17 |
18 | try {
19 | fs.statSync(main);
20 | } catch (err) {
21 | console.error(`Missing ${main} -- create it and have it export your root React component`);
22 | process.exit(1);
23 | }
24 |
25 | console.log('Running initial build...');
26 | compileAndPublish();
27 |
28 | if (argv.watch) {
29 | const watcher = require('./watcher')();
30 | watcher.on('change', (path, stats) => {
31 | console.log(`${path} changed, compiling..`);
32 | compileAndPublish();
33 | });
34 |
35 | watcher.on('unlink', (path, stats) => {
36 | console.log(`${path} removed, compiling..`);
37 | compileAndPublish();
38 | });
39 | }
40 | }
41 |
42 | function compileAndPublish() {
43 | try {
44 | processFile('./.build/__app.js', `${buildPath}/${main}`).then((result) => {
45 | let pathParts = process.cwd().split('/');
46 | let domain = 'resurge-' + pathParts[pathParts.length - 1] + '.surge.sh';
47 |
48 | surge.publish({
49 | project: buildPath,
50 | domain: domain,
51 | });
52 | });
53 | } catch(err) {
54 | console.log(err);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "resurge",
3 | "version": "0.4.0",
4 | "description": "Instant React app setup and deploy with surge.sh",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "MIT",
11 | "dependencies": {
12 | "babel-core": "^6.3.26",
13 | "babel-preset-react": "^6.3.13",
14 | "babel-preset-stage-3": "^6.3.13",
15 | "babelify": "^7.2.0",
16 | "browserify": "^12.0.1",
17 | "chokidar": "^1.4.1",
18 | "fs-extra": "^0.26.3",
19 | "react": "^0.14.3",
20 | "react-dom": "^0.14.3",
21 | "surge": "^0.17.4",
22 | "yargs": "^3.31.0"
23 | },
24 | "bin": {
25 | "resurge": "index.js"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/processFile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const browserify = require('browserify');
5 |
6 | const config = {
7 | "presets": ["stage-3", "react"],
8 | };
9 |
10 | function processFile(file, dest) {
11 | let result = fs.createWriteStream(dest);
12 |
13 | return new Promise((resolve, reject) => {
14 | browserify(file)
15 | .transform('babelify', config)
16 | .bundle()
17 | .on('error', (error) => { console.log(error.message) })
18 | .on('data', (data) => { result.write(data) })
19 | .on('end', () => { resolve('hiiiiii'); });
20 | });
21 | }
22 |
23 | module.exports = processFile;
24 |
--------------------------------------------------------------------------------
/setupFs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs-extra');
4 |
5 | module.exports = function() {
6 | const rootPath = __dirname;
7 | const rootNodeModulesPath = `${rootPath}/node_modules`;
8 | const projectPath = process.cwd();
9 | const projectNodeModulesPath = `${projectPath}/node_modules`;
10 |
11 | const whitelist = [
12 | 'babel-core',
13 | 'babel-preset-react',
14 | 'babel-preset-stage-3',
15 | 'react',
16 | 'react-dom',
17 | 'babelify',
18 | 'browserify',
19 | ];
20 |
21 | fs.mkdirpSync(projectNodeModulesPath);
22 | whitelist.forEach((module) => {
23 | let source = `${rootNodeModulesPath}/${module}`;
24 | let destination = `${projectNodeModulesPath}/${module}`;
25 |
26 | if (!fs.existsSync(destination)) {
27 | try {
28 | fs.copySync(source, destination);
29 | } catch (err) {
30 | console.log(err.message);
31 | }
32 | };
33 | });
34 |
35 |
36 | const projectBuildPath = `${projectPath}/.build`;
37 | const templateBuildPath = `${rootPath}/.build`;
38 | fs.removeSync(projectBuildPath);
39 | fs.mkdirpSync(projectBuildPath);
40 |
41 | try {
42 | fs.copySync(`${templateBuildPath}/index.html`, `${projectBuildPath}/index.html`);
43 | fs.copySync(`${templateBuildPath}/__app.js`, `${projectBuildPath}/__app.js`);
44 | } catch(err) {
45 | console.log(err.message);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/surge.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var spawn = require('child_process').spawn
4 | var path = require('path')
5 | var surge = path.resolve(path.dirname(require.resolve('surge')), '../../.bin/surge' + (process.platform === 'win32' ? '.cmd' : ''))
6 |
7 | module.exports = {
8 | list: function() {
9 | return spawn(surge, ['list'], { stdio: 'inherit' })
10 | },
11 |
12 | publish: function(options) {
13 | return spawn(surge, [options.project, options.domain], { stdio: 'inherit' })
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/watcher.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | var chokidar = require('chokidar');
5 |
6 | var log = console.log.bind(console);
7 |
8 | module.exports = function() {
9 | let watcher = chokidar.watch('./**/*', {
10 | persistent: true,
11 |
12 | ignored: './build/**/*',
13 | ignoreInitial: false,
14 | followSymlinks: true,
15 | cwd: '.',
16 |
17 | usePolling: true,
18 | interval: 100,
19 | binaryInterval: 300,
20 | depth: 50,
21 | awaitWriteFinish: {
22 | stabilityThreshold: 1000,
23 | pollInterval: 100
24 | },
25 |
26 | ignorePermissionErrors: false,
27 | atomic: true
28 | });
29 |
30 |
31 | // Stop watching.
32 | process.on('SIGINT', () => {
33 | console.log('');
34 | console.log('Shutting down resurge');
35 | watcher.close();
36 | process.exit(0);
37 | });
38 |
39 | return watcher;
40 | }
41 |
--------------------------------------------------------------------------------