import { join } from 'path';
import webpack from 'webpack';
import MemoryFS from 'memory-fs';
import { Observable } from 'rx';
import { fromCallback } from 'bluebird';
import { RenderError } from '../Error';

/**
 * Bundle JS file with CommonJS module, return the bundled JS file as string
 *
 * @param {string} targetDir - The directory contains `js.js` file
 *
 * @return {Promise<string>} Bundled js file content
 */
export function createBundle(targetDir) {
  return fromCallback((done) => {
    const fs = new MemoryFS();

    const compiler = webpack({
      entry: [join(targetDir, 'js.js')],
      output: {
        path: targetDir,
        filename: 'bundle.js',
      }
    });

    compiler.outputFileSystem = fs;

    compiler.run((err, stats) => {
      if (err) {
        done(err);
        return;
      }

      const fcontent = fs.readFileSync(join(targetDir, 'bundle.js'), 'utf8');
      done(null, fcontent);
    });
  });
}

/**
 * Create a stream that emits JS file on file changes
 *
 * @param {string} targetDir - The directory contains `js.js` file
 *
 * @return {Observable<string>} Emit bundled JS file content
 */
export function createBundlerStream(targetDir) {
  return Observable.create((observer) => {
    const fs = new MemoryFS();

    const compiler = webpack({
      entry: [join(targetDir, 'js.js')],
      output: {
        path: targetDir,
        filename: 'bundle.js',
      }
    });

    compiler.outputFileSystem = fs;

    const watcher = compiler.watch({}, (err, stats) => {
      if (err) {
        observer.onNext(new RenderError(err.message));
        return;
      }

      const fontent = fs.readFileSync(join(targetDir, 'bundle.js'), 'utf8');
      observer.onNext(fontent);
    });

    return () => watcher.close();
  });
}

@@ -202,16 +202,410 @@
 rror';%0A%0A
+function createOptions(targetDir) %7B%0A  return %7B%0A    entry: %5Bjoin(targetDir, 'js.js')%5D,%0A    output: %7B%0A      path: targetDir,%0A      filename: 'bundle.js',%0A    %7D,%0A    loaders: %5B%0A      %7B%0A        test: /%5C.(js%7Ces6%7Ces%7Cjsx)$/,%0A        exclude: /(node_modules%7Cbower_components)/,%0A        loader: 'babel',%0A        query: %7B%0A          presets: %5B'es2015', 'react', 'stage-0'%5D%0A        %7D%0A      %7D%0A    %5D%0A  %7D;%0A%7D%0A%0A
 /**%0A * B
@@ -948,136 +948,32 @@
 ack(
-%7B%0A      entry: %5Bjoin(targetDir, 'js.js')%5D,%0A      output: %7B%0A        path: targetDir,%0A        filename: 'bundle.js',%0A      %7D%0A    %7D
+createOptions(targetDir)
 );%0A%0A
@@ -1581,136 +1581,32 @@
 ack(
-%7B%0A      entry: %5Bjoin(targetDir, 'js.js')%5D,%0A      output: %7B%0A        path: targetDir,%0A        filename: 'bundle.js',%0A      %7D%0A    %7D
+createOptions(targetDir)
 );%0A%0A

Apply babel loader