123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- process.env.DEBUG = 'app:*';
- const debug = require('debug')('app:demos');
- const commander = require('commander');
- const connect = require('connect');
- const getPort = require('get-port');
- const http = require('http');
- const open = require('open');
- const serveStatic = require('serve-static');
- const bodyParser = require('body-parser');
- const parseurl = require('parseurl');
- const url = require('url');
- const assign = require('lodash').assign;
- const path = require('path');
- const resolve = path.resolve;
- const join = path.join;
- const fs = require('fs');
- const JSZip = require('jszip');
- const readFileSync = fs.readFileSync;
- const writeFileSync = fs.writeFileSync;
- const nunjucks = require('nunjucks');
- const renderString = nunjucks.renderString;
- const shelljs = require('shelljs');
- const webpack = require('webpack');
- const webpackConfig = require('../webpack.config');
- const pkg = require('../package.json');
- const blocks = require('./data/blocks.json');
- const template = require('./data/template');
- shelljs.config.execPath = shelljs.which('node');
- commander
- .version(pkg.version)
- .option('-w, --web')
- .option('-p, --port <port>', 'specify a port number to run on', parseInt)
- .parse(process.argv);
- function startService(port) {
- const server = connect();
- server
- .use(bodyParser.urlencoded({
- extended: true
- }))
- .use((req, res, next) => { // pre-handlers
- const urlInfo = url.parse(req.url, true);
- const query = urlInfo.query || {};
- const body = req.body || {};
- req._urlInfo = urlInfo;
- req._pathname = urlInfo.pathname;
- // add req._params (combination of query and body)
- const params = Object.assign({}, query, body);
- req._params = params;
- req._query = query;
- req._body = body;
- res._sendRes = (str, contentType) => {
- const buf = new Buffer(str);
- contentType = contentType || 'text/html;charset=utf-8';
- res.setHeader('Content-Type', contentType);
- res.setHeader('Content-Length', buf.length);
- res.end(buf);
- };
- // res._JSONRes(data) (generate JSON response)
- res._JSONRes = data => {
- res._sendRes(JSON.stringify(data), 'application/json;charset=utf-8');
- };
- // TODO res._JSONError()
- // res._HTMLRes(data) (generate HTML response)
- res._HTMLRes = res._sendRes;
- return next();
- })
- .use((req, res, next) => {
- const pathname = parseurl(req).pathname;
- if (req.method === 'GET') {
- if (pathname === '/bundler/index.html') {
- res.end(renderString(readFileSync(join(__dirname, './index.njk'), 'utf8'), {
- blocks
- }));
- } else {
- next();
- }
- } else if (req.method === 'POST') {
- if (pathname === '/bundle') {
- // step1: prepare entry __index.js
- const entryPath = resolve(process.cwd(), './src/__index.js');
- const ids = req.body.ids.map(id => parseInt(id, 10));
- const codeBlocks = blocks
- .filter((item, index) => ids.indexOf(index) !== -1)
- .map(item => item.code)
- .join('\n');
- const entryFileContent = template(codeBlocks);
- writeFileSync(entryPath, template(codeBlocks), 'utf8');
- // step2: build it
- const distPath = resolve(process.cwd(), './__dist');
- shelljs.rm('-rf', distPath);
- shelljs.mkdir('-p', distPath);
- const config = Object.assign({}, webpackConfig);
- config.entry = {
- g2: './src/__index.js'
- };
- config.output.path = distPath;
- webpack(config, (err, stats) => {
- // shelljs.rm(entryPath);
- if (err || stats.hasErrors()) {
- // Handle errors here
- // shelljs.rm('-rf', distPath);
- shelljs.rm(entryPath);
- shelljs.rm('-rf', distPath);
- }
- // step3: uglify
- shelljs.exec('uglifyjs -c -m -o __dist/g2.min.js -- __dist/g2.js');
- // step4: zipping it
- const zip = new JSZip();
- zip.folder('g2-dist').file('entry.js', entryFileContent);
- zip.folder('g2-dist').file('g2.js', readFileSync(join(distPath, './g2.js'), 'utf8'));
- zip.folder('g2-dist').file('g2.js.map', readFileSync(join(distPath, './g2.js.map'), 'utf8'));
- zip.folder('g2-dist').file('g2.min.js', readFileSync(join(distPath, './g2.min.js'), 'utf8'));
- res.writeHead(200, {
- 'Content-Type': 'application/zip'
- });
- zip
- .generateNodeStream({ type: 'nodebuffer', streamFiles: true })
- .pipe(res)
- .on('finish', function() {
- // step5: clear up
- shelljs.rm(entryPath);
- shelljs.rm('-rf', distPath);
- res.end();
- });
- });
- }
- } else {
- next();
- }
- });
- server.use(serveStatic(process.cwd()));
- http.createServer(server).listen(port);
- const urlPath = `http://127.0.0.1:${port}/bundler/index.html`;
- debug(`server started, bundler available! ${urlPath}`);
- if (commander.web) {
- debug('running on web!');
- open(urlPath);
- } else {
- debug('running on electron!');
- const app = require('electron').app;
- const BrowserWindow = require('electron').BrowserWindow;
- const windowBoundsConfig = require('torchjs/lib/windowBoundsConfig')(
- resolve(app.getPath('userData'), './g2-bundler-config.json')
- );
- let win;
- app.once('ready', () => {
- win = new BrowserWindow(assign({
- // transparent: true
- webPreferences: {
- nodeIntegration: false
- }
- }, windowBoundsConfig.get('bundler')));
- win.loadURL(urlPath);
- win.on('close', () => {
- windowBoundsConfig.set('bundler', win.getBounds());
- });
- win.on('closed', () => {
- win = null;
- });
- });
- app.on('window-all-closed', () => {
- app.quit();
- });
- }
- }
- if (commander.port) {
- startService(commander.port);
- } else {
- getPort().then(port => {
- startService(port);
- });
- }
|