<commit_before>const rp = require('request-promise')

module.exports = function () {
  const { commands, hears, on: reservedCallback } = this.actions

  if (!this.longPollParams) {
    return this.api('messages.getLongPollServer', {
      need_pts: 1,
      lp_version: 2,
      access_token: this.token,
      v: 5.65
    })
      .then((body) => {
        if (!body.response || !body.response.server) {
          throw new Error(JSON.stringify(body))
        }

        this.longPollParams = body.response
        this.listen()
      })
      .catch((err) => {
        this.longPollParams = null
        return this.listen()
      })
  }

  return rp({
    url: `https://${this.longPollParams.server}`,
    qs: {
      ...this.longPollParams,
      act: 'a_check',
      wait: 25,
      mode: 2,
      version: 2
    },
    json: true
  })
    .then((body) => {
      if (body.failed) {
        if (body.failed && body.ts) {
          this.longPollParams.ts = body.ts
        } else {
          this.longPollParams = null
        }

        return this.listen()
      }

      if (body.ts) {
        this.longPollParams.ts = body.ts
      }

      this.listen()

      if (body.updates && body.updates.length) {
        body.updates.forEach((update) => {
          if (update[0] === 4 && (update[2] & 2) === 0) {
            const ctx = {
              user_id: update[3],
              body: update[5],
              attachments: update[6],
              date: update[4],
              message_id: update[1],
            }

            if (update[6].from) {
              ctx.from = +update[6].from
            }

            const getForward = (ctx) => {
              return new Promise((resolve) => {
                if (!ctx.attachments || !ctx.attachments.fwd) {
                  resolve(null)
                }

                this.execute('messages.getById', {
                  message_ids: ctx.message_id,
                  v: 5.67
                }, this.token, (data) => {
                  resolve(this.getLastMessage(data.items[0]))
                })
              })
            }

            getForward(ctx)
              .then((forward) => {
                if (forward) {
                  ctx.forward = forward
                  ctx.body = forward.body
                }

                const attachmentsKeys = Object.keys(ctx.attachments).filter(key => key.search('attach') > -1 && key.search('type') === -1 && key.search('kind') === -1)
                const attachments = []

                attachmentsKeys.forEach((key) => {
                  const file = {}

                  file['type'] = ctx.attachments[`${key}_type`]
                  file[file.type] = ctx.attachments[key]

                  attachments.push(file)
                })

                ctx.attachments = attachments
                ctx.body = ctx.body.replace(/
/g, '\n')

                ctx.reply = (message, attachment) => this.reply(ctx.user_id, message, attachment)
                ctx.sendMessage = (userId, message, attachment) => this.reply(userId, message, attachment)

                const message = ctx.body.toLowerCase()
                const commandKey = Object.keys(commands).filter(item => item.indexOf(message) > -1)[0]
                const commandCallback = commands[commandKey]
                const hearsKey = Object.keys(hears).filter((item) => {
                  const index = item.split(';')
                    .filter((item) => {
                      if (/^\/[\S]{1,}\/[a-z]{1,2}$/.test(item)) {
                        const string = item.substr(1).replace(/\/[a-z]{1,2}/i, '')
                        const type = item.substr(1).match(/\/[a-z]{1,2}/i)[0].substr(1)

                        return new RegExp(string, type).test(message)
                      } else {
                        return new RegExp(item, 'i').test(message)
                      }
                    })
                  return index.length
                })[0]
                const hearsCallback = hears[hearsKey]

                if (commandCallback !== undefined) {
                  return commandCallback(ctx)
                } else if (hearsCallback !== undefined) {
                  return hearsCallback(ctx)
                } else if (reservedCallback !== undefined) {
                  return reservedCallback(ctx)
                }
              })
              .catch((err) => {
                this.longPollParams = null
                return this.listen()
              })
          }
        })
      }
    })
    .catch((err) => {
      this.longPollParams = null
      return this.listen()
    })
}
<commit_msg>Add original message saver for forward case (#9)<commit_after>const rp = require('request-promise')

module.exports = function () {
  const { commands, hears, on: reservedCallback } = this.actions

  if (!this.longPollParams) {
    return this.api('messages.getLongPollServer', {
      need_pts: 1,
      lp_version: 2,
      access_token: this.token,
      v: 5.65
    })
      .then((body) => {
        if (!body.response || !body.response.server) {
          throw new Error(JSON.stringify(body))
        }

        this.longPollParams = body.response
        this.listen()
      })
      .catch((err) => {
        this.longPollParams = null
        return this.listen()
      })
  }

  return rp({
    url: `https://${this.longPollParams.server}`,
    qs: {
      ...this.longPollParams,
      act: 'a_check',
      wait: 25,
      mode: 2,
      version: 2
    },
    json: true
  })
    .then((body) => {
      if (body.failed) {
        if (body.failed && body.ts) {
          this.longPollParams.ts = body.ts
        } else {
          this.longPollParams = null
        }

        return this.listen()
      }

      if (body.ts) {
        this.longPollParams.ts = body.ts
      }

      this.listen()

      if (body.updates && body.updates.length) {
        body.updates.forEach((update) => {
          if (update[0] === 4 && (update[2] & 2) === 0) {
            const ctx = {
              user_id: update[3],
              body: update[5],
              attachments: update[6],
              date: update[4],
              message_id: update[1],
            }

            if (update[6].from) {
              ctx.from = +update[6].from
            }

            const getForward = (ctx) => {
              return new Promise((resolve) => {
                if (!ctx.attachments || !ctx.attachments.fwd) {
                  resolve(null)
                }

                this.execute('messages.getById', {
                  message_ids: ctx.message_id,
                  v: 5.67
                }, this.token, (data) => {
                  resolve(this.getLastMessage(data.items[0]))
                })
              })
            }

            getForward(ctx)
              .then((forward) => {
                if (forward) {
                  ctx.forward = forward
                  ctx.original = { body: ctx.body }
                  ctx.body = forward.body
                }

                const attachmentsKeys = Object.keys(ctx.attachments).filter(key => key.search('attach') > -1 && key.search('type') === -1 && key.search('kind') === -1)
                const attachments = []

                attachmentsKeys.forEach((key) => {
                  const file = {}

                  file['type'] = ctx.attachments[`${key}_type`]
                  file[file.type] = ctx.attachments[key]

                  attachments.push(file)
                })

                ctx.attachments = attachments
                ctx.body = ctx.body.replace(/
/g, '\n')

                ctx.reply = (message, attachment) => this.reply(ctx.user_id, message, attachment)
                ctx.sendMessage = (userId, message, attachment) => this.reply(userId, message, attachment)

                const message = ctx.body.toLowerCase()
                const commandKey = Object.keys(commands).filter(item => item.indexOf(message) > -1)[0]
                const commandCallback = commands[commandKey]
                const hearsKey = Object.keys(hears).filter((item) => {
                  const index = item.split(';')
                    .filter((item) => {
                      if (/^\/[\S]{1,}\/[a-z]{1,2}$/.test(item)) {
                        const string = item.substr(1).replace(/\/[a-z]{1,2}/i, '')
                        const type = item.substr(1).match(/\/[a-z]{1,2}/i)[0].substr(1)

                        return new RegExp(string, type).test(message)
                      } else {
                        return new RegExp(item, 'i').test(message)
                      }
                    })
                  return index.length
                })[0]
                const hearsCallback = hears[hearsKey]

                if (commandCallback !== undefined) {
                  return commandCallback(ctx)
                } else if (hearsCallback !== undefined) {
                  return hearsCallback(ctx)
                } else if (reservedCallback !== undefined) {
                  return reservedCallback(ctx)
                }
              })
              .catch((err) => {
                this.longPollParams = null
                return this.listen()
              })
          }
        })
      }
    })
    .catch((err) => {
      this.longPollParams = null
      return this.listen()
    })
}
<|endoftext|>


<commit_before>/*global define, $ */
'use strict';

define([
	'flight/lib/component',
	'text!templates/todo.html',
	'app/utils'
], function (defineComponent, todoTmpl, utils) {
	function todoList() {
		var ENTER_KEY = 13;
		var template = utils.tmpl(todoTmpl);

		this.attributes({
			destroySelector: 'button.destroy',
			toggleSelector: 'input.toggle',
			labelSelector: 'label',
			editSelector: '.edit'
		});

		this.renderAll = function (e, data) {
			this.$node.html('');
			data.todos.forEach(function (each) {
				this.render(e, { todo: each });
			}, this);
		};

		this.render = function (e, data) {
			if (e.type === 'dataTodoAdded' && data.filter === 'completed') {
				return;
			}

			this.$node.append(template(data.todo));
		};

		this.edit = function (e, data) {
			var $todoEl = $(data.el).parents('li');

			$todoEl.addClass('editing');
			this.select('editSelector').focus();
		};

		this.requestUpdate = function (e) {
			var $inputEl = $(e.currentTarget);
			var $todoEl = $inputEl.parents('li');
			var value = $inputEl.val().trim();
			var id = $todoEl.attr('id');

			if (!$todoEl.hasClass('editing')) {
				return;
			}

			$todoEl.removeClass('editing');

			if (value) {
				$todoEl.find('label').html(value);
				this.trigger('uiUpdateRequested',  { id: id, title: value });
			} else {
				this.trigger('uiRemoveRequested', { id: id });
			}
		};

		this.requestUpdateOnEnter = function (e, data) {
			if (e.which === ENTER_KEY) {
				this.requestUpdate(e, data);
			}
		};

		this.requestRemove = function (e, data) {
			var id = $(data.el).attr('id').split('_')[1];
			this.trigger('uiRemoveRequested', { id: id });
		};

		this.remove = function (e, data) {
			var $todoEl = this.$node.find('#' + data.id);
			$todoEl.remove();
		};

		this.toggle = function (e, data) {
			var $todoEl = $(data.el).parents('li');

			$todoEl.toggleClass('completed');
			this.trigger('uiToggleRequested', { id: $todoEl.attr('id') });
		};

		this.after('initialize', function () {
			this.on(document, 'dataTodoAdded', this.render);
			this.on(document, 'dataTodosLoaded', this.renderAll);
			this.on(document, 'dataTodosFiltered', this.renderAll);
			this.on(document, 'dataTodoToggledAll', this.renderAll);
			this.on(document, 'dataTodoRemoved', this.remove);

			this.on('click', { 'destroySelector': this.requestRemove });
			this.on('click', { 'toggleSelector': this.toggle });
			this.on('dblclick', { 'labelSelector': this.edit });

			this.$node.on('blur', '.edit', this.requestUpdate.bind(this));
			this.$node.on('keydown', '.edit', this.requestUpdateOnEnter.bind(this));

			// these don't work
			// this.on(this.attr.editSelector, 'blur', this.requestUpdate);
			// this.on('blur', { 'editSelector': this.requestUpdate });

			this.trigger('uiLoadRequested');
		});
	}

	return defineComponent(todoList);
});
<commit_msg>Flight: Cancel editing on ESCAPE key press (#1855)<commit_after>/*global define, $ */
'use strict';

define([
	'flight/lib/component',
	'text!templates/todo.html',
	'app/utils'
], function (defineComponent, todoTmpl, utils) {
	function todoList() {
		var ENTER_KEY = 'Enter';
		var ESCAPE_KEY = 'Escape';
		var template = utils.tmpl(todoTmpl);

		this.attributes({
			destroySelector: 'button.destroy',
			toggleSelector: 'input.toggle',
			labelSelector: 'label',
			editSelector: '.edit'
		});

		this.renderAll = function (e, data) {
			this.$node.html('');
			data.todos.forEach(function (each) {
				this.render(e, { todo: each });
			}, this);
		};

		this.render = function (e, data) {
			if (e.type === 'dataTodoAdded' && data.filter === 'completed') {
				return;
			}

			this.$node.append(template(data.todo));
		};

		this.edit = function (e, data) {
			var $todoEl = $(data.el).parents('li');
			var $inputEl = $todoEl.find('input');
			var value = $todoEl.find('label').text();

			$todoEl.addClass('editing');
			$inputEl.val(value);
			this.select('editSelector').focus();
		};

		this.requestUpdate = function (e) {
			var $inputEl = $(e.currentTarget);
			var $todoEl = $inputEl.parents('li');
			var value = $inputEl.val().trim();
			var id = $todoEl.attr('id');

			if (!$todoEl.hasClass('editing')) {
				return;
			}

			$todoEl.removeClass('editing');

			if (value) {
				$todoEl.find('label').html(value);
				this.trigger('uiUpdateRequested',  { id: id, title: value });
			} else {
				this.trigger('uiRemoveRequested', { id: id });
			}
		};

		this.requestCancel = function (e) {
			var $inputEl = $(e.currentTarget);
			var $todoEl = $inputEl.parents('li');

			$todoEl.removeClass('editing');
			$inputEl.val('');

			this.trigger('uiUpdateRequested');
		};

		this.requestUpdateOrCancelEvent = function (e, data) {
			if (e.key === ENTER_KEY) {
				this.requestUpdate(e, data);
			} else if (e.key === ESCAPE_KEY) {
				this.requestCancel(e, data);
			}
		};

		this.requestRemove = function (e, data) {
			var id = $(data.el).attr('id').split('_')[1];
			this.trigger('uiRemoveRequested', { id: id });
		};

		this.remove = function (e, data) {
			var $todoEl = this.$node.find('#' + data.id);
			$todoEl.remove();
		};

		this.toggle = function (e, data) {
			var $todoEl = $(data.el).parents('li');

			$todoEl.toggleClass('completed');
			this.trigger('uiToggleRequested', { id: $todoEl.attr('id') });
		};

		this.after('initialize', function () {
			this.on(document, 'dataTodoAdded', this.render);
			this.on(document, 'dataTodosLoaded', this.renderAll);
			this.on(document, 'dataTodosFiltered', this.renderAll);
			this.on(document, 'dataTodoToggledAll', this.renderAll);
			this.on(document, 'dataTodoRemoved', this.remove);

			this.on('click', { 'destroySelector': this.requestRemove });
			this.on('click', { 'toggleSelector': this.toggle });
			this.on('dblclick', { 'labelSelector': this.edit });

			this.$node.on('blur', '.edit', this.requestUpdate.bind(this));
			this.$node.on('keydown', '.edit', this.requestUpdateOrCancelEvent.bind(this));

			// these don't work
			// this.on(this.attr.editSelector, 'blur', this.requestUpdate);
			// this.on('blur', { 'editSelector': this.requestUpdate });

			this.trigger('uiLoadRequested');
		});
	}

	return defineComponent(todoList);
});
<|endoftext|>


<commit_before>"use strict";

var evaluate = require('../util/test')
var isPlainObj = require('../util').isPlainObj
var createPath
var getPath

exports.clean = function( obj, index ){
  if(obj.constructor === Array){
    return obj.splice(0,index)
  }
  while(obj[index]){
    delete obj[index++]
  }
  return obj
}

exports.createPath = createPath = function( obj, path, length, set ){
  var setObj = {}
  var nextObj = setObj
  var i = 0
  var field

  for(; i < length - 1; i++ ) {
    field = path[i]
    nextObj[field] = {}
    nextObj = nextObj[field]
  }

  if(set !== void 0){
    nextObj[path[i]] = set
  }else{
    nextObj[path[i]] = {}
  }
  obj.set(setObj)
  return getPath( obj, path, length )
}

exports.getPath = getPath = function( obj, path, length, filter, set ) {
  var i = 0
  var result = obj[path[0]]

  while (result) {
    console.log('yes got something', result && result.$val)
    if ( ++i === length ) {
      if( filter === void 0 || filter(result) ){
        console.log('length reached, return dat result')
        return result
      }
    }
    if(typeof result === 'function'){
      return result.call(obj,path.splice(i), filter)
    }
    obj = result
    result = result[path[i]]
  }

  if(set !== void 0){
    return createPath(obj, path.splice(i), length - i, set)
  }
}

exports.returnFilter = function( options ){
  if( options !== void 0 ){
    var conditions
    var filter

    if( typeof options === 'function' ){
      return options
    }

    if( isPlainObj( options ) ){
      conditions = options.conditions

      if( conditions ){
        return function( subject ){
            return evaluate( subject, conditions )
          }
      }

      if( options instanceof RegExp ){
        return function( subject ){
          return options.test ( subject )
        }
      }

      if( options.contructor === Array ){
        var length = options.length
        return function( subject ){
          for( var i = length - 1; i >= 0; i-- ) {
            var value = options[i]
            if( subject === value || subject._$val === value ){
              return true
            }
          }
        }
      }

    } else {
      return function( subject ){
        return subject === options || subject._$val === options
      }
    }
  }
}

exports.returnPath = function( path ){
  return typeof path === 'string' ? path.split('.') : path
}<commit_msg>cleaned up methods (formatting)<commit_after>"use strict";

var evaluate = require('../util/test')
var isPlainObj = require('../util').isPlainObj
var createPath
var getPath

exports.clean = function( obj, index ){
  if(obj.constructor === Array){
    return obj.splice(0,index)
  }
  while(obj[index]){
    delete obj[index++]
  }
  return obj
}

exports.createPath = createPath = function( obj, path, length, set ){
  var setObj = {}
  var nextObj = setObj
  var i = 0
  var field
  for(;i < length - 1; i++ ) {
    field = path[i]
    nextObj[field] = {}
    nextObj = nextObj[field]
  }
  if(set !== void 0){
    nextObj[path[i]] = set
  }else{
    nextObj[path[i]] = {}
  }
  obj.set(setObj)
  return getPath( obj, path, length )
}

exports.getPath = getPath = function( obj, path, length, filter, set ) {
  var i = 0
  var result = obj[path[0]]

  while (result) {
    console.log('yes got something', result && result.$val)
    if ( ++i === length ) {
      if( filter === void 0 || filter(result) ){
        console.log('length reached, return dat result')
        return result
      }
    }
    if(typeof result === 'function'){
      return result.call(obj,path.splice(i), filter)
    }
    obj = result
    result = result[path[i]]
  }

  if(set !== void 0){
    return createPath(obj, path.splice(i), length - i, set)
  }
}

exports.returnFilter = function( options ){
  if( options !== void 0 ){
    var conditions
    var filter

    if( typeof options === 'function' ){
      return options
    }

    if( isPlainObj( options ) ){
      conditions = options.conditions

      if( conditions ){
        return function( subject ){
            return evaluate( subject, conditions )
          }
      }

      if( options instanceof RegExp ){
        return function( subject ){
          return options.test ( subject )
        }
      }

      if( options.contructor === Array ){
        var length = options.length
        return function( subject ){
          for( var i = length - 1; i >= 0; i-- ) {
            var value = options[i]
            if( subject === value || subject._$val === value ){
              return true
            }
          }
        }
      }

    } else {
      return function( subject ){
        return subject === options || subject._$val === options
      }
    }
  }
}

exports.returnPath = function( path ){
  return typeof path === 'string' ? path.split('.') : path
}<|endoftext|>


<commit_before>// question.js
//
// data object representing an question
//
// Copyright 2011, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var DatabankObject = require('databank').DatabankObject;

var Question = DatabankObject.subClass('question');

exports.Question = Question;
<commit_msg>ActivityObject, schema for question<commit_after>// question.js
//
// data object representing an question
//
// Copyright 2011, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var DatabankObject = require('databank').DatabankObject,
    ActivityObject = require('./activityobject').ActivityObject;

var Question = DatabankObject.subClass('question', ActivityObject);

Question.schema = {
    pkey: "id",
    fields: ['author',
             'content',
             'displayName',
             'options',
             'published',
             'updated',
             'url']
};

exports.Question = Question;
<|endoftext|>


<commit_before>
// # Neuron Core

// ## CommonJS
// Neuron 3.x or newer is not the implementation of any CommonJs proposals
// but [module/1.0](http://wiki.commonjs.org/wiki/Modules/1.0), one of the stable CommonJs standards only.
// And by using neuron and [cortex](http://github.com/kaelzhang/cortex), user could write module/1.0 modules.

// ## Naming Conventions
// All naming of variables should accord to this.
// `'a@1.0.0/relative'`

// ### package
// The package which the current module belongs to.
// - name or package name: {string}  package `name`: 'a'
// - package or package id: {string}    contains package `name` and `version` and the splitter `'@'`. 'a@1.0.0' for instance.

// ### module
// A package is consist of several module objects.
// - mod: {object} the module object. use `mod` instead of `module` to avoid confliction
// - id or module id: the descripter that contains package name, version, and path information
//      {string} for example, `'a@1.0.0/relative'` is a module id(entifier)

// ### version
// Package version: '1.0.0'

// ### main entry
// The module of a package that designed to be accessed from the outside

// map -> identifier: module
var __mods = makeSureObject(neuron, 'mods');

// module define
// ---------------------------------------------------------------------------------------------------

// Method to define a module, `define` has no fault tolerance in neuron 2.0,
// because `define` method is no longer designed for human to use.
// `define` should be generated by some develop environment such as [cortex](http://ctx.io)
// @private

// @param {string} identifier (optional) module identifier
// @param {Array.<string>} dependencies ATTENSION! `dependencies` must be array of standard module identifier and
//    there will be NO fault tolerance for argument `dependencies`. Be carefull!
// @param {function(...[*])} factory
// @param {Object=} options

// @return {undefined}
function define (identifier, dependencies, factory, options){
    if(
        typeof identifier === 'string' &&
        isArray(dependencies) &&
        typeof factory === 'function'
    ){
        options = options || {};

        var mod = getModuleById(identifier, null, options.main);
        mod.o = options;

        // a single module might be defined more than once.
        // use this trick to prevent module redefining, avoiding the subsequent side effect.
        // mod.f        -> already defined
        // mod.exports  -> the module initialization is done
        if( !mod.f && !mod.exports ){
            mod.f = factory;

            // if has dependencies
            if ( dependencies.length ) {
                mod.deps = dependencies;

                // ['a@0.0.1']  -> {'a' -> 'a@0.0.1'}
                generateModuleVersionMap(dependencies, mod.v);
                if ( options.asyncDeps ) {
                    generateModuleVersionMap(options.asyncDeps, mod.v);
                }

                _provide(
                    dependencies,
                    function(){
                        generateExports(mod);
                    }, mod, true
                );

            }else{
                // for standalone modules, run factory immediately.
                generateExports(mod);
            }

            neuron.emit('define', {
                mod: mod
            });
        }
    }
}

// @private
// create version info of the dependencies of current module into current sandbox
// @param {Array.<string>} modules no type detecting
// @param {Object} host

// ['a@~0.1.0', 'b@~2.3.9']
// ->
// {
//     a: '~0.1.0',
//     b: '~2.3.9'
// }
function generateModuleVersionMap (modules, host){
    modules.forEach(function(mod) {
        var name = mod.split('@')[0];
        host[name] = mod;
    });
}

// Generate the exports
// @param {Object} mod
function generateExports (mod){
    var exports = {};
    var module = {
            exports: exports
        };

    // clean module properties, free memory

    // to keep the object mod away from the executing context of factory,
    // use `factory` instead `mod.f`,
    // preventing user from fetching runtime data by 'this'
    var factory = mod.f;
    factory(createRequire(mod), exports, module);
    delete mod.f;

    // during the execution of `factory`, `module.exports` might be changed
    // exports:
    // TWO ways to define the exports of a module
    // 1.
    // exports.method1 = method1;
    // exports.method2 = method2;

    // 2.
    // module.exports = {
    //        method1: method1,
    //        method2: method2
    // }

    // priority: 2 > 1
    mod.exports = module.exports;

    // execute pending callbacks and clean
    mod.p.forEach(function(c){
        c();
    });
    mod.p.length = 0;
    delete mod.p;

    // never delete `mod.v`, coz `require` method might be executed after module factory executed

    //      module.exports = {
    //          abc: function() {
    //              return require('b');
    //          }
    //      }

    neuron.emit('ready', {
        mod: mod
    });
}

// module load
// ---------------------------------------------------------------------------------------------------

var GLOBAL_ENV = {
    v: {}
};

// method to load a module
// @public
// @param {Array.<String>} dependencies
// @param {(function(...[number]))=} callback (optional)
function provide (dependencies, callback){
    dependencies = makeArray(dependencies);

    _provide(dependencies, callback, GLOBAL_ENV);
}

// @private
// @param {Array.<String>} dependencies
// @param {(function()} callback
// @param {Object} env Environment for cyclic detecting and generating the uri of child modules
//     {
//         r: {string} the uri that its child dependent modules referring to
//         n: {string} namespace of the current module
//     }
// @param {boolean=} noCallbackArgs Whether callback method need arguments, for inner use
// @param {boolean=} async Whether we should provide modules as asynchronous modules.
function _provide (dependencies, callback, env, noCallbackArgs, async){
    var counter = dependencies.length;
    var args = [];
    var cb;

    if(typeof callback === 'function'){
        cb = noCallbackArgs ?
            callback :
            function(){
                callback.apply(null, args);
            };
    }

    dependencies.forEach(function(dep, i){
        if (dep) {
            var mod = getModuleById(dep, env);

            if ( async ) {
                mod.async = true;
            }

            registerModuleLoadCallback(mod, function(){
                if(cb){
                    -- counter;

                    if(!noCallbackArgs){
                        args[i] = createRequire(env)(dep);
                    }

                    if(counter === 0){
                        cb();
                        args.length = 0;
                        // prevent memleak
                        cb = callback = args = null;
                    }
                }
            });
        }
    });
}

// provide
// method to provide a module
// @param {Object} mod
// @param {function()} callback
function registerModuleLoadCallback (mod, callback){
    var loaded = !!mod.exports;

    // if mod is ready, it will initialize its factory function
    loaded ?
        callback()
      : mod.p.push(callback);

    // everytime we encounter a module which is depended by the other module, `'use'` event fires
    neuron.emit('use', {
        mod: mod,

        // prevent duplicate loading
        // @type {boolean=} whether the module is already fetched, i.e. we don't need to fetch it from the remote server
        defined: loaded || !!mod.f
    });
}

// use the sandbox to specify the environment for every id that required in the current module
// @param {Object} env The object of the current module.
// @return {function}
function createRequire (env){
    var require = function(id){
        return getModuleById(env.v[id] || id, env).exports;
    };

    require.async = function (dependencies, callback) {
        _provide(makeArray(dependencies), callback, env, false, true);
    };

    return require;
}

// cases:

// 1. calculate relative paths
// 2. load modules

// ```
// 'a@0.0.1/b.js'
// -> define('a@0.0.1/b', ['./c'], factory, {main: true});
// if main entry is not
// -> {
//     'a@0.0.1/b': mod_b,
//     'a@0.0.1': mod_b
// }
// -> 'a/0.0.1/a.js'

// 'a@0.0.1/c'
// -> define('a@0.0.1/c', [], factory, {});
// -> {
//     'a@0.0.1/c': mod_c
// }
// ```

// get a module by id. if not exists, a ghost module(which will be filled after its first `define`) will be created
// @param {string} id
// @param {Object} env the environment module,
// @param {boolean=} main Whether it is a main entry
function getModuleById (id, env, isMain){
    var parsed;

    // `env` exists, which means
    if ( env ) {
        // pathResolve('align', 'jquery')   -> 'jquery'
        // pathResolve('align', './')
        id = pathResolve(env.id, id);

        // 'a@1.0.0'    -> 'a@1.0.0'
        // 'a'          -> 'a@latest'
        // 'a/inner'    -> 'a@latest/inner'
        parsed = parseModuleId(id);

        // Suppose:
        // {
        //     'a': {
        //         '~1.2.3': '1.2.12'
        //     }
        // }

        // We route a package of certain range to a specific version,
        // so several modules may point to a same exports

        // `NEURON_CONF` is generated by `neuron.config`
        parsed.v = NEURON_CONF.transform(parsed.v, parsed.n);
        id = formatModuleId(parsed);

    } else {
        parsed = parseModuleId(id);
    }

    var mod = __mods[id];
    if ( !mod ) {
        var pkg = formatPackageId(parsed);

        if ( isMain ) {
            mod =
            __mods[id] =
            __mods[pkg] =

            // The module id of main entry is the package id.
            __mods[pkg]
                || createModule(parsed, id, pkg);

            // There is only posibility to run `getModuleById` with `isMain` set by `true`:
            // ```
            // define(id, dependencies, factory, {main: true}).
            // ```
            // And, before this,
            // `__mods[pkg]` might have already been assigned with a falsy `id` property.

            // For example
            // {
            //     name: 'a',
            //     version: '0.0.1',
            //     main: 'lib/index.js'
            // }

            // 1. `getModuleById('a@0.0.1')`, and load 'a/0.0.1/a.js'
            // {
            //     id: 'a@0.0.1',
            //     pkg: 'a@0.0.1'
            // }

            // 2. (in a.js), define('a@0.0.1/lib/index', [], factory, {main: true})
            // Then, `getModuleById('a@0.0.1/lib/index')` will get the result of the 1st step.
            // Obviously,
            // 'a@0.0.1' is not the real module id of the main entry,
            // while 'a@0.0.1/lib/index' is, so:
            mod.id = id;

        } else {
            mod = __mods[id] = createModule(parsed, id, pkg);
        }
    }

    return mod;
}

function createModule (parsed, id, pkg){
    return {
        // package name: 'a'
        name    : parsed.n,
        // package version: '1.1.0'
        version : parsed.v,
        // module path: '/b.js'
        path    : parsed.p,
        // module id: 'a@1.1.0/b.js'
        id      : id,
        // package id: 'a@1.1.0'
        pkg     : pkg,
        // @type {Array.<function()>} pending callbacks
        p       : [],
        // @type {Object} version map of the current module
        v       : {}
    };
}

// @const
// 'a@1.2.3/abc' ->
// ['a@1.2.3/abc', 'a', '1.2.3', '/abc']

//                    01            2         3
var REGEX_PARSE_ID = /^([^\/]+?)(?:@([^\/]+))?(\/.*)?$/;

// @param {string} resolved path-resolved module identifier
function parseModuleId (resolved) {
    var match   = resolved.match(REGEX_PARSE_ID);
    var name    = match[1];

    // 'a/inner' -> 'a@latest/inner'
    var version = match[2] || 'latest';
    var path    = match[3] || '';

    // There always be matches
    return {
        n: name,
        v: version,
        p: path
    };
}

// Format package id
function formatPackageId (parsed){
    return parsed.n + '@' + parsed.v;
}

// Format module id
function formatModuleId (parsed) {
    return formatPackageId(parsed) + parsed.p;
}

// module tools
// ---------------------------------------------------------------------------------------------------

// greedy match:
var REGEX_DIR_MATCHER = /.*(?=\/.*$)/;

// get the current directory from the location
//
// http://jsperf.com/regex-vs-split/2
// vs: http://jsperf.com/regex-vs-split
function dirname (uri){
    var m = uri.match(REGEX_DIR_MATCHER);

    // abc/def  -> abc
    // abc      -> abc
    // abc/     -> abc
    return m ? m[0] : uri;
}

// Canonicalize path
// similar to path.resolve() of node.js

// pathResolve('a/b/c') ==> 'a/b/c'
// pathResolve('a/b/../c') ==> 'a/c'
// pathResolve('a/b/./c') ==> '/a/b/c'
// pathResolve('a/b/c/') ==> 'a/b/c/'
// pathResolve('a//b/c') ==> 'a//b/c'   - for 'a//b/c' is a valid uri
function pathResolve (from, to) {
    // relative
    if(to.indexOf('./') === 0 || to.indexOf('../') === 0){
        var old = (dirname(from) + '/' + to).split('/');
        var ret = [];

        old.forEach(function(part){
            if (part === '..') {
                ret.pop();

            } else if (part !== '.') {
                ret.push(part);
            }
        });

        to = ret.join('/');
    }

    return to;
}

// @public
// ----------------------------------------------------------------------------------

// event support
// mix(loader, Event);

/**
 change log:

 import ./ChangeLog.md;

 */<commit_msg>#66: module-manager: remove `async` argument of _provide<commit_after>
// # Neuron Core

// ## CommonJS
// Neuron 3.x or newer is not the implementation of any CommonJs proposals
// but [module/1.0](http://wiki.commonjs.org/wiki/Modules/1.0), one of the stable CommonJs standards only.
// And by using neuron and [cortex](http://github.com/kaelzhang/cortex), user could write module/1.0 modules.

// ## Naming Conventions
// All naming of variables should accord to this.
// `'a@1.0.0/relative'`

// ### package
// The package which the current module belongs to.
// - name or package name: {string}  package `name`: 'a'
// - package or package id: {string}    contains package `name` and `version` and the splitter `'@'`. 'a@1.0.0' for instance.

// ### module
// A package is consist of several module objects.
// - mod: {object} the module object. use `mod` instead of `module` to avoid confliction
// - id or module id: the descripter that contains package name, version, and path information
//      {string} for example, `'a@1.0.0/relative'` is a module id(entifier)

// ### version
// Package version: '1.0.0'

// ### main entry
// The module of a package that designed to be accessed from the outside

// map -> identifier: module
var __mods = makeSureObject(neuron, 'mods');

// module define
// ---------------------------------------------------------------------------------------------------

// Method to define a module, `define` has no fault tolerance in neuron 2.0,
// because `define` method is no longer designed for human to use.
// `define` should be generated by some develop environment such as [cortex](http://ctx.io)
// @private

// @param {string} identifier (optional) module identifier
// @param {Array.<string>} dependencies ATTENSION! `dependencies` must be array of standard module identifier and
//    there will be NO fault tolerance for argument `dependencies`. Be carefull!
// @param {function(...[*])} factory
// @param {Object=} options

// @return {undefined}
function define (identifier, dependencies, factory, options){
    if(
        typeof identifier === 'string' &&
        isArray(dependencies) &&
        typeof factory === 'function'
    ){
        options = options || {};

        var mod = getModuleById(identifier, null, options.main);
        mix(mod, options);

        // a single module might be defined more than once.
        // use this trick to prevent module redefining, avoiding the subsequent side effect.
        // mod.f        -> already defined
        // mod.exports  -> the module initialization is done
        if( !mod.f && !mod.exports ){
            mod.f = factory;

            // if has dependencies
            if ( dependencies.length ) {
                mod.deps = dependencies;

                // ['a@0.0.1']  -> {'a' -> 'a@0.0.1'}
                generateModuleVersionMap(dependencies, mod.v);
                if ( options.asyncDeps ) {
                    generateModuleVersionMap(options.asyncDeps, mod.v);
                }

                _provide(
                    dependencies,
                    function(){
                        generateExports(mod);
                    }, mod, true
                );

            }else{
                // for standalone modules, run factory immediately.
                generateExports(mod);
            }

            neuron.emit('define', {
                mod: mod
            });
        }
    }
}

// @private
// create version info of the dependencies of current module into current sandbox
// @param {Array.<string>} modules no type detecting
// @param {Object} host

// ['a@~0.1.0', 'b@~2.3.9']
// ->
// {
//     a: '~0.1.0',
//     b: '~2.3.9'
// }
function generateModuleVersionMap (modules, host){
    modules.forEach(function(mod) {
        var name = mod.split('@')[0];
        host[name] = mod;
    });
}

// Generate the exports
// @param {Object} mod
function generateExports (mod){
    var exports = {};
    var module = {
            exports: exports
        };

    // clean module properties, free memory

    // to keep the object mod away from the executing context of factory,
    // use `factory` instead `mod.f`,
    // preventing user from fetching runtime data by 'this'
    var factory = mod.f;
    factory(createRequire(mod), exports, module);
    delete mod.f;

    // during the execution of `factory`, `module.exports` might be changed
    // exports:
    // TWO ways to define the exports of a module
    // 1.
    // exports.method1 = method1;
    // exports.method2 = method2;

    // 2.
    // module.exports = {
    //        method1: method1,
    //        method2: method2
    // }

    // priority: 2 > 1
    mod.exports = module.exports;

    // execute pending callbacks and clean
    mod.p.forEach(function(c){
        c();
    });
    mod.p.length = 0;
    delete mod.p;

    // never delete `mod.v`, coz `require` method might be executed after module factory executed

    //      module.exports = {
    //          abc: function() {
    //              return require('b');
    //          }
    //      }

    neuron.emit('ready', {
        mod: mod
    });
}

// module load
// ---------------------------------------------------------------------------------------------------

var GLOBAL_ENV = {
    v: {}
};

// method to load a module
// @public
// @param {Array.<String>} dependencies
// @param {(function(...[number]))=} callback (optional)
function provide (dependencies, callback){
    dependencies = makeArray(dependencies);

    _provide(dependencies, callback, GLOBAL_ENV);
}

// @private
// @param {Array.<String>} dependencies
// @param {(function()} callback
// @param {Object} env Environment for cyclic detecting and generating the uri of child modules
//     {
//         r: {string} the uri that its child dependent modules referring to
//         n: {string} namespace of the current module
//     }
// @param {boolean=} noCallbackArgs Whether callback method need arguments, for inner use
function _provide (dependencies, callback, env, noCallbackArgs){
    var counter = dependencies.length;
    var args = [];
    var cb;

    if(typeof callback === 'function'){
        cb = noCallbackArgs ?
            callback :
            function(){
                callback.apply(null, args);
            };
    }

    dependencies.forEach(function(dep, i){
        if (dep) {
            var mod = getModuleById(dep, env);

            registerModuleLoadCallback(mod, function(){
                if(cb){
                    -- counter;

                    if(!noCallbackArgs){
                        args[i] = createRequire(env)(dep);
                    }

                    if(counter === 0){
                        cb();
                        args.length = 0;
                        // prevent memleak
                        cb = callback = args = null;
                    }
                }
            });
        }
    });
}

// provide
// method to provide a module
// @param {Object} mod
// @param {function()} callback
function registerModuleLoadCallback (mod, callback){
    var loaded = !!mod.exports;

    // if mod is ready, it will initialize its factory function
    loaded ?
        callback()
      : mod.p.push(callback);

    // everytime we encounter a module which is depended by the other module, `'use'` event fires
    neuron.emit('use', {
        mod: mod,

        // prevent duplicate loading
        // @type {boolean=} whether the module is already fetched, i.e. we don't need to fetch it from the remote server
        defined: loaded || !!mod.f
    });
}

// use the sandbox to specify the environment for every id that required in the current module
// @param {Object} env The object of the current module.
// @return {function}
function createRequire (env){
    var require = function(id){
        return getModuleById(env.v[id] || id, env).exports;
    };

    require.async = function (dependencies, callback) {
        _provide(makeArray(dependencies), callback, env);
    };

    return require;
}

// cases:

// 1. calculate relative paths
// 2. load modules

// ```
// 'a@0.0.1/b.js'
// -> define('a@0.0.1/b', ['./c'], factory, {main: true});
// if main entry is not
// -> {
//     'a@0.0.1/b': mod_b,
//     'a@0.0.1': mod_b
// }
// -> 'a/0.0.1/a.js'

// 'a@0.0.1/c'
// -> define('a@0.0.1/c', [], factory, {});
// -> {
//     'a@0.0.1/c': mod_c
// }
// ```

// get a module by id. if not exists, a ghost module(which will be filled after its first `define`) will be created
// @param {string} id
// @param {Object} env the environment module,
// @param {boolean=} main Whether it is a main entry
function getModuleById (id, env, isMain){
    var parsed;

    // `env` exists, which means
    if ( env ) {
        // pathResolve('align', 'jquery')   -> 'jquery'
        // pathResolve('align', './')
        id = pathResolve(env.id, id);

        // 'a@1.0.0'    -> 'a@1.0.0'
        // 'a'          -> 'a@latest'
        // 'a/inner'    -> 'a@latest/inner'
        parsed = parseModuleId(id);

        // Suppose:
        // {
        //     'a': {
        //         '~1.2.3': '1.2.12'
        //     }
        // }

        // We route a package of certain range to a specific version,
        // so several modules may point to a same exports

        // `NEURON_CONF` is generated by `neuron.config`
        parsed.v = NEURON_CONF.transform(parsed.v, parsed.n);
        id = formatModuleId(parsed);

    } else {
        parsed = parseModuleId(id);
    }

    var mod = __mods[id];
    if ( !mod ) {
        var pkg = formatPackageId(parsed);

        if ( isMain ) {
            mod =
            __mods[id] =
            __mods[pkg] =

            // The module id of main entry is the package id.
            __mods[pkg]
                || createModule(parsed, id, pkg);

            // There is only posibility to run `getModuleById` with `isMain` set by `true`:
            // ```
            // define(id, dependencies, factory, {main: true}).
            // ```
            // And, before this,
            // `__mods[pkg]` might have already been assigned with a falsy `id` property.

            // For example
            // {
            //     name: 'a',
            //     version: '0.0.1',
            //     main: 'lib/index.js'
            // }

            // 1. `getModuleById('a@0.0.1')`, and load 'a/0.0.1/a.js'
            // {
            //     id: 'a@0.0.1',
            //     pkg: 'a@0.0.1'
            // }

            // 2. (in a.js), define('a@0.0.1/lib/index', [], factory, {main: true})
            // Then, `getModuleById('a@0.0.1/lib/index')` will get the result of the 1st step.
            // Obviously,
            // 'a@0.0.1' is not the real module id of the main entry,
            // while 'a@0.0.1/lib/index' is, so:
            mod.id = id;

        } else {
            mod = __mods[id] = createModule(parsed, id, pkg);
        }
    }

    return mod;
}

function createModule (parsed, id, pkg){
    return {
        // package name: 'a'
        name    : parsed.n,
        // package version: '1.1.0'
        version : parsed.v,
        // module path: '/b'
        path    : parsed.p,
        // module id: 'a@1.1.0/b'
        id      : id,
        // package id: 'a@1.1.0'
        pkg     : pkg,
        // @type {Array.<function()>} pending callbacks
        p       : [],
        // @type {Object} version map of the current module
        v       : {}
    };
}

// @const
// 'a@1.2.3/abc' ->
// ['a@1.2.3/abc', 'a', '1.2.3', '/abc']

//                    01            2         3
var REGEX_PARSE_ID = /^([^\/]+?)(?:@([^\/]+))?(\/.*)?$/;

// @param {string} resolved path-resolved module identifier
function parseModuleId (resolved) {
    var match   = resolved.match(REGEX_PARSE_ID);
    var name    = match[1];

    // 'a/inner' -> 'a@latest/inner'
    var version = match[2] || 'latest';
    var path    = match[3] || '';

    // There always be matches
    return {
        n: name,
        v: version,
        p: path
    };
}

// Format package id
function formatPackageId (parsed){
    return parsed.n + '@' + parsed.v;
}

// Format module id
function formatModuleId (parsed) {
    return formatPackageId(parsed) + parsed.p;
}

// module tools
// ---------------------------------------------------------------------------------------------------

// greedy match:
var REGEX_DIR_MATCHER = /.*(?=\/.*$)/;

// get the current directory from the location
//
// http://jsperf.com/regex-vs-split/2
// vs: http://jsperf.com/regex-vs-split
function dirname (uri){
    var m = uri.match(REGEX_DIR_MATCHER);

    // abc/def  -> abc
    // abc      -> abc
    // abc/     -> abc
    return m ? m[0] : uri;
}

// Canonicalize path
// similar to path.resolve() of node.js

// pathResolve('a/b/c') ==> 'a/b/c'
// pathResolve('a/b/../c') ==> 'a/c'
// pathResolve('a/b/./c') ==> '/a/b/c'
// pathResolve('a/b/c/') ==> 'a/b/c/'
// pathResolve('a//b/c') ==> 'a//b/c'   - for 'a//b/c' is a valid uri
function pathResolve (from, to) {
    // relative
    if(to.indexOf('./') === 0 || to.indexOf('../') === 0){
        var old = (dirname(from) + '/' + to).split('/');
        var ret = [];

        old.forEach(function(part){
            if (part === '..') {
                ret.pop();

            } else if (part !== '.') {
                ret.push(part);
            }
        });

        to = ret.join('/');
    }

    return to;
}

// @public
// ----------------------------------------------------------------------------------

// event support
// mix(loader, Event);

/**
 change log:

 import ./ChangeLog.md;

 */<|endoftext|>


<commit_before>/**

  Bundler.js

  Wrapper for module bundling: currently uses webpack.

  Statics
  • fromFile

  Instance
  • construtor
  • get

**/

//
//  Dependencies
//

var Utils        = require("./utils"),
    Promise      = require("bluebird"),
    chokidar     = require("chokidar"),
    path         = require("path"),
    webpack      = require("webpack"),
    readFile     = Promise.promisify(global.fs.readFile.bind(global.fs));

/**

  Wraps a webpack instance, writing to in-memory file system.

  options
  • <String>  entry              : input file
  • <String>  filename           : output filename
  • <Boolean> [compile=true]     : compile upon instantiation
  • <Boolean> [watch=true]       : watch for recompilation
  • <String>  [path="/scripts"]  : in-memory path

  @param {Object} options
  @returns {Bundler} Instance of this class

**/

var Bundler = module.exports = function(options) {

  // Determine which extensions to look for
  var self = this,
      exts = Utils.uniqueExtensions(path.join(options.entry, "..")).concat([""]);

  // Set up defaults
  options = Object.assign({ compile: true, watch : true, path : "/scripts/" }, options);

  // Configure
  this.config = {
    entry      : options.entry,
    output     : {
      path     : options.path,
      filename : options.filename
    },
    module     : {
      loaders  : [ { test: /.+/, loader: "superloader" } ]
    },
    resolve    : { extensions: exts }
  };

  // Store path
  this.path = path.join(this.config.output.path, options.filename);

  // Set up bundler with in-memory file sysstem
  this.bundler = webpack(this.config);
  this.bundler.outputFileSystem = global.fs;

  // Bind functions
  this.get = this.get.bind(this);
  this.compile = Promise.promisify(this.bundler.run.bind(this.bundler));

  // Optionally compile
  if (options.compile) this.compile();

  if (options.watch) {

    // Only watch directory with index file: breaks outside watchers otherwise
    // Note that this may fetch the file multiple times: once when "reload" is triggered,
    // and again a second time when the file is called (e.g. from HTML)

    chokidar.watch(path.join(path.dirname(options.entry), "**", "*")).on("all", function(event, file) {
      self.bundler.run(function(err, stats) {
        global.server.reload(self.path);
      });
    });
  }

};

/**

  Reads the most recently compiled version of a file from in-memory file system.

  @returns {String} Compiled file.

**/

Bundler.prototype.get = function() {
  return readFile(this.path, "utf8");
};

/**

  Creates a bundler from a file, modifies file for proper routing.

  @param {File} file Modified file object, as returned by Utils#mapFiles
  @param {String} type Type of the output file

**/

Bundler.fromFile = function(file, type) {
  file.folder = "";
  file.name = file.dir.replace(Utils.makePathAbsolute(file.basePath), "").slice(1);
  return new Bundler({ entry : file.path, filename : file.name + "." + type });
};
<commit_msg>Bundler: improves comments<commit_after>/**

  Bundler.js

  Wrapper for module bundling: currently uses webpack.

  Statics
  • fromFile

  Instance
  • construtor
  • get

**/

//
//  Dependencies
//

var Utils        = require("./utils"),
    Promise      = require("bluebird"),
    chokidar     = require("chokidar"),
    path         = require("path"),
    webpack      = require("webpack"),
    readFile     = Promise.promisify(global.fs.readFile.bind(global.fs));

/**

  Wraps a webpack instance, writing to in-memory file system.

  options
  • <String>  entry              : input file
  • <String>  filename           : output filename
  • <Boolean> [compile=true]     : compile upon instantiation
  • <Boolean> [watch=true]       : watch for recompilation
  • <String>  [path="/scripts"]  : in-memory path

  @param {Object} options
  @returns {Bundler} Instance of this class

**/

var Bundler = module.exports = function(options) {

  // Determine which extensions to look for
  var self = this,
      exts = Utils.uniqueExtensions(path.join(options.entry, "..")).concat([""]);

  // Set up defaults
  options = Object.assign({ compile: true, watch : true, path : "/scripts/" }, options);

  // Configure webpack
  this.config = {
    entry      : options.entry,
    output     : {
      path     : options.path,
      filename : options.filename
    },
    module     : {
      loaders  : [ { test: /.+/, loader: "superloader" } ]
    },
    resolve    : { extensions: exts }
  };

  // Store path to compiled file
  this.path = path.join(this.config.output.path, options.filename);

  // Set up bundler with in-memory file sysstem
  this.bundler = webpack(this.config);
  this.bundler.outputFileSystem = global.fs;

  // Bind functions
  this.get = this.get.bind(this);
  this.compile = Promise.promisify(this.bundler.run.bind(this.bundler));

  // Optionally compile
  if (options.compile) this.compile();

  // Only watch directory with index file: breaks outside watchers otherwise
  if (options.watch) {
    chokidar.watch(path.join(path.dirname(options.entry), "**", "*")).on("all", function(event, file) {
      self.bundler.run(function(err, stats) {
        global.server.reload(self.path);
      });
    });
  }

};

/**

  Reads the most recently compiled version of a file from in-memory file system.

  @returns {String} Compiled file.

**/

Bundler.prototype.get = function() {
  console.log("GETTING");
  return readFile(this.path, "utf8");
};

/**

  Creates a bundler from a file, modifies file for proper routing.

  @param {File} file Modified file object, as returned by Utils#mapFiles
  @param {String} type Type of the output file

**/

Bundler.fromFile = function(file, type) {
  file.folder = "";
  file.name = file.dir.replace(Utils.makePathAbsolute(file.basePath), "").slice(1);
  return new Bundler({ entry : file.path, filename : file.name + "." + type });
};
<|endoftext|>


<commit_before>
import {Mongo} from 'meteor/mongo';
import {DDP} from 'meteor/ddp-client'

class RemoteCollectionManager {
    constructor() {
        this.REMOTE_COLLECTIONS = {};
        this.remotes = {};
        this.subscriptions = {};
        this.debug = false;
        this.debugObserveFct = {
            added: function (item) {
                console.log('-- remote item added--');
                console.log(item);
            },

            removed: function (item) {
                console.log('-- remote items removed--');
                console.log(item);
            }
        };
        this._loadCollection = this._loadCollection.bind(this);
        this._loadRemoteSubscription = this._loadRemoteSubscription.bind(this);
    }

    getCollections() {
        return this.REMOTE_COLLECTIONS;
    }

    /**
     * Returns the ddp connection object reference, returns null if not set.
     * @returns {null|any|*}
     */
    getDDPConnection(id) {
        return this.remotes[id];
    }

    getAllDDPConnectionIds() {
        return Object.keys(this.remotes);
    }

    /**
     * Returns all added ddp connection objects.
     */
    getAllDDPConnections() {
        return this.remotes;
    }

    getAllSubscriptions(){
        return this.subscriptions;
    }

    getSubscriptionsById(id){
        return this.subscriptions[id];
    }

    /**
     * Sets debugging mode on.
     * @param value boolean, true for debugging
     */
    setDebug(value) {
        this.debug = value;
    }

    /**
     * Sets the target from where you want to retrieve your collections
     * @param urlString The full url to connect via ddp
     */
    addDDPConnectionURL(id, urlString) {
        this.remotes[id] = DDP.connect(urlString);
    }

    /**
     * Loads remote collections via given ddp method. Can be connected to multiple remote objects via id.
     * @param params.id the id of the remote objects to call. Use single string for single call, array of ids for multiple call or leave empty if call all.
     * @param params.method the method name. Must not be null
     * @param params.observe optional observe function to observe changes. If undefined and debug is true, a console log will be initiated
     * @returns {{}} Returns an object with id-boolean pairs. (For each id a result value is attached.)
     */
    loadRemoteCollections(params) {
        return this._loadRemote(params, this._loadCollection);
    }

    /**
     * Subscribes to remote collections via ddp. Call on/in meteor.startup() function.
     * @param params.id the id of the remote objects to call. Use single string for single call, array of ids for multiple call or leave empty if call all.
     * @param params.method the method name. Must not be null
     * @returns {{}} Returns an object with id-boolean pairs. (For each id a result value is attached.)
     */
    loadRemoteSubscriptions(params) {
        return this._loadRemote(params, this._loadRemoteSubscription);
    }

    _loadRemote(params, fct){
        this._checkInputParams(params); //throw errors if wrong
        let results = {};
        const ids = this._parseInputIds(params.id);
        console.log("load remote");
        for (let currentId of ids) {

            results[currentId] = fct.call(this, currentId, params.method, params.observe);
        }
        console.log(results);
        return results;
    }

    _checkInputParams(params) {
        if (!params)
            throw new Meteor.Error("Must set a parameter object!");
        if (!params.method)
            throw new Meteor.Error("Must set a remote method name to be used to load!");
    }

    _parseInputIds(idObj) {
        if (idObj === null || typeof idObj === 'undefined')
            return this.getAllDDPConnectionIds();
        else if (idObj instanceof Array || Array.isArray(obj))
            return idObj;//call multiple from array
        else
            return [idObj];
    }

    _loadCollection( id, remoteMethodName, observeFct) {
        try {
            const remote = this.remotes[id];
            if (!remote)
                throw new Meteor.Error("Connection by id not found, did you add any?");

            const collections = remote.call(remoteMethodName);
            if (!collections)
                throw new Meteor.Error("No collections received from external call. Id=" + id + " / methodname=" + remoteMethodName);

            for (let collectionName of collections) {
                console.log(collectionName+" found");
                this.REMOTE_COLLECTIONS[collectionName] = new Mongo.Collection(collectionName, {connection: remote});
                if (!observeFct && this.debug)
                    observeFct = debugObserveFct;
                if (observeFct)
                    this.REMOTE_COLLECTIONS[collectionName].find().observe(observeFct);
            }
            return true;
        }
        catch (e) {
            if (this.debug)
                console.log(e.stack);
            return false;
        }
    }

    _loadRemoteSubscription(id, subscriptionName) {
        console.log("LOAD SUB: "+id+" / "+subscriptionName);
        try {
            const remote = this.remotes[id];
            if (!remote)
                throw new Meteor.Error("Connection by id not found, did you add any?");

            //get all subscriptions
            let availableSubscriptions = remote.call(subscriptionName);
            if (availableSubscriptions) {
                //if there are any, subscribe now!
                for (let subsciptionName of availableSubscriptions) {
                    if (this.subscriptions[id] === null || typeof this.subscriptions[id] === 'undefined')
                        this.subscriptions[id] = {};

                    const currentSubs = this.subscriptions[id];
                    currentSubs[subsciptionName] = remote.subscribe(subsciptionName);
                    this.subscriptions[id] = currentSubs;
                }
            }
            return true;
        } catch (e) {
            if (this.debug)
                console.log(e.stack);
            return false;
        }

    }
}

export const RemoteCollections = new RemoteCollectionManager();<commit_msg>fixed a reference error due to wrong naming<commit_after>
import {Mongo} from 'meteor/mongo';
import {DDP} from 'meteor/ddp-client'

class RemoteCollectionManager {
    constructor() {
        this.REMOTE_COLLECTIONS = {};
        this.remotes = {};
        this.subscriptions = {};
        this.debug = false;
        this.debugObserveFct = {
            added: function (item) {
                console.log('-- remote item added--');
                console.log(item);
            },

            removed: function (item) {
                console.log('-- remote items removed--');
                console.log(item);
            }
        };
        this._loadCollection = this._loadCollection.bind(this);
        this._loadRemoteSubscription = this._loadRemoteSubscription.bind(this);
    }

    getCollections() {
        return this.REMOTE_COLLECTIONS;
    }

    /**
     * Returns the ddp connection object reference, returns null if not set.
     * @returns {null|any|*}
     */
    getDDPConnection(id) {
        return this.remotes[id];
    }

    getAllDDPConnectionIds() {
        return Object.keys(this.remotes);
    }

    /**
     * Returns all added ddp connection objects.
     */
    getAllDDPConnections() {
        return this.remotes;
    }

    getAllSubscriptions(){
        return this.subscriptions;
    }

    getSubscriptionsById(id){
        return this.subscriptions[id];
    }

    /**
     * Sets debugging mode on.
     * @param value boolean, true for debugging
     */
    setDebug(value) {
        this.debug = value;
    }

    /**
     * Sets the target from where you want to retrieve your collections
     * @param urlString The full url to connect via ddp
     */
    addDDPConnectionURL(id, urlString) {
        this.remotes[id] = DDP.connect(urlString);
    }

    /**
     * Loads remote collections via given ddp method. Can be connected to multiple remote objects via id.
     * @param params.id the id of the remote objects to call. Use single string for single call, array of ids for multiple call or leave empty if call all.
     * @param params.method the method name. Must not be null
     * @param params.observe optional observe function to observe changes. If undefined and debug is true, a console log will be initiated
     * @returns {{}} Returns an object with id-boolean pairs. (For each id a result value is attached.)
     */
    loadRemoteCollections(params) {
        return this._loadRemote(params, this._loadCollection);
    }

    /**
     * Subscribes to remote collections via ddp. Call on/in meteor.startup() function.
     * @param params.id the id of the remote objects to call. Use single string for single call, array of ids for multiple call or leave empty if call all.
     * @param params.method the method name. Must not be null
     * @returns {{}} Returns an object with id-boolean pairs. (For each id a result value is attached.)
     */
    loadRemoteSubscriptions(params) {
        return this._loadRemote(params, this._loadRemoteSubscription);
    }

    _loadRemote(params, fct){
        this._checkInputParams(params); //throw errors if wrong
        let results = {};
        const ids = this._parseInputIds(params.id);
        console.log("load remote");
        for (let currentId of ids) {

            results[currentId] = fct.call(this, currentId, params.method, params.observe);
        }
        console.log(results);
        return results;
    }

    _checkInputParams(params) {
        if (!params)
            throw new Meteor.Error("Must set a parameter object!");
        if (!params.method)
            throw new Meteor.Error("Must set a remote method name to be used to load!");
    }

    _parseInputIds(idObj) {
        if (idObj === null || typeof idObj === 'undefined')
            return this.getAllDDPConnectionIds();
        else if (idObj instanceof Array || Array.isArray(idObj))
            return idObj;//call multiple from array
        else
            return [idObj];
    }

    _loadCollection( id, remoteMethodName, observeFct) {
        try {
            const remote = this.remotes[id];
            if (!remote)
                throw new Meteor.Error("Connection by id not found, did you add any?");

            const collections = remote.call(remoteMethodName);
            if (!collections)
                throw new Meteor.Error("No collections received from external call. Id=" + id + " / methodname=" + remoteMethodName);

            for (let collectionName of collections) {
                console.log(collectionName+" found");
                this.REMOTE_COLLECTIONS[collectionName] = new Mongo.Collection(collectionName, {connection: remote});
                if (!observeFct && this.debug)
                    observeFct = debugObserveFct;
                if (observeFct)
                    this.REMOTE_COLLECTIONS[collectionName].find().observe(observeFct);
            }
            return true;
        }
        catch (e) {
            if (this.debug)
                console.log(e.stack);
            return false;
        }
    }

    _loadRemoteSubscription(id, subscriptionName) {
        console.log("LOAD SUB: "+id+" / "+subscriptionName);
        try {
            const remote = this.remotes[id];
            if (!remote)
                throw new Meteor.Error("Connection by id not found, did you add any?");

            //get all subscriptions
            let availableSubscriptions = remote.call(subscriptionName);
            if (availableSubscriptions) {
                //if there are any, subscribe now!
                for (let subsciptionName of availableSubscriptions) {
                    if (this.subscriptions[id] === null || typeof this.subscriptions[id] === 'undefined')
                        this.subscriptions[id] = {};

                    const currentSubs = this.subscriptions[id];
                    currentSubs[subsciptionName] = remote.subscribe(subsciptionName);
                    this.subscriptions[id] = currentSubs;
                }
            }
            return true;
        } catch (e) {
            if (this.debug)
                console.log(e.stack);
            return false;
        }

    }
}

export const RemoteCollections = new RemoteCollectionManager();<|endoftext|>


<commit_before>const webpack = require('webpack');
const path = require('path');
const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
const ProvidePlugin = webpack.ProvidePlugin;
const DefinePlugin = webpack.DefinePlugin;
const OccurenceOrderPlugin = webpack.optimize.OccurenceOrderPlugin;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const chalk = require('chalk');
const NODE_ENV = process.env.NODE_ENV;
const ENV_PRODUCTION = NODE_ENV === 'production';
const ENV_DEVELOPMENT = NODE_ENV === 'development' || !ENV_PRODUCTION;
const ENV_TRAVIS = process.env.TRAVIS || false;
const PORT = 8080;
var isTest = process.env.npm_lifecycle_event === 'test' || process.env.npm_lifecycle_event === 'test-watch';
const METADATA = {
  title: 'WAS',
  port: 8080,
  baseUrl: '/'
};
module.exports = {
  metadata: METADATA,
  /**
   * Entry
   * Reference: http://webpack.github.io/docs/configuration.html#entry
   */
  entry: {
    'polyfills': './src/polyfills.ts',
    'vendor': './src/vendors.ts',
    'app': './src/main.ts' // our angular app
  },
  /**
   * Resolve
   * Reference: http://webpack.github.io/docs/configuration.html#resolve
   */
  resolve: {
    //cache: false,
    root: path.resolve('.'),
    // only discover files that have those extensions
    extensions: ['', '.ts', '.js', '.json', '.css', '.scss', '.sass', '.html'],
    alias: {
      'app': 'src/app',
      'common': 'src/common'
    },
    modulesDirectories: ['node_modules']
  },
  // ts: {
  //   silent: true
  // },
  module: {
    noParse: [/.+zone\.js\/dist\/.+/, /.+angular2\/bundles\/.+/, /angular2-polyfills\.js/],
    preLoaders: [],
    loaders: [{
        test: /\.ts$/,
        loader: 'ts',
        query: {
          'ignoreDiagnostics': [
            2403, // 2403 -> Subsequent variable declarations
            2300, // 2300 -> Duplicate identifier
            2374, // 2374 -> Duplicate number index signature
            2375, // 2375 -> Duplicate string index signature
            2502 // 2502 -> Referenced directly or indirectly
          ]
        },
        exclude: [isTest ? /\.(e2e)\.ts$/ : /\.(spec|e2e)\.ts$/, /node_modules\/(?!(ng2-.+))/]
      }, {
        test: /\.(woff2?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
        loader: "file?name=fonts/[name]-[hash:7].[ext]"
      },
      // copy those assets to output,
      {
        test: /\.(png|jpe?g|gif|svg)$/,
        loader: 'file?name=img/[name].[ext]'
      },
      // Support for CSS as raw text
      // use 'null' loader in test mode (https://github.com/webpack/null-loader)
      {
        test: /\.css$/,
        exclude: path.resolve('src/app'),
        loader: isTest ? 'null' : ExtractTextPlugin.extract('style', 'css?sourceMap!postcss')
      },
      // support for .scss files
      // use 'null' loader in test mode (https://github.com/webpack/null-loader)
      {
        test: /\.(scss|sass)$/,
        exclude: path.resolve('src/app'),
        loader: isTest ? 'null' : ExtractTextPlugin.extract('style', 'css?sourceMap!postcss!sass')
      },
      // support for .html as raw text
      {
        test: /\.html$/,
        loader: 'raw'
      }
    ]
  },
  plugins: [

    // // Define env variables to help with builds
    // // Reference: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
    //new OccurenceOrderPlugin(true),
    new CommonsChunkPlugin({
      name: ['vendor', 'polyfills']
    }),
    // Copy assets from the public folder
    // Reference: https://github.com/kevlened/copy-webpack-plugin
    new CopyWebpackPlugin([{
      from: path.resolve('src/public')
    }], {
      ignore: [{
        glob: '**/*.db',
        dot: true
      }]
    }),
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    }),
    // Inject script and link tags into html files
    // Reference: https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      template: './src/public/index.html',
      inject: 'body',
      chunksSortMode: 'dependency'
    }),
    // Extract css files
    // Reference: https://github.com/webpack/extract-text-webpack-plugin
    new ExtractTextPlugin('css/[name]-[hash:7].css')
  ],
  /**
   * Sass
   * Reference: https://github.com/jtangelder/sass-loader
   */
  sassLoader: {
    includePaths: [path.resolve(__dirname, "../node_modules/foundation-sites/scss")]
  }
};
<commit_msg>ignore non-foundation jquery<commit_after>const webpack = require('webpack');
const path = require('path');
const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
const ProvidePlugin = webpack.ProvidePlugin;
const DefinePlugin = webpack.DefinePlugin;
const OccurenceOrderPlugin = webpack.optimize.OccurenceOrderPlugin;
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const chalk = require('chalk');
const NODE_ENV = process.env.NODE_ENV;
const ENV_PRODUCTION = NODE_ENV === 'production';
const ENV_DEVELOPMENT = NODE_ENV === 'development' || !ENV_PRODUCTION;
const ENV_TRAVIS = process.env.TRAVIS || false;
const PORT = 8080;
var isTest = process.env.npm_lifecycle_event === 'test' || process.env.npm_lifecycle_event === 'test-watch';
const METADATA = {
  title: 'WAS',
  port: 8080,
  baseUrl: '/'
};
module.exports = {
  metadata: METADATA,
  /**
   * Entry
   * Reference: http://webpack.github.io/docs/configuration.html#entry
   */
  entry: {
    'polyfills': './src/polyfills.ts',
    'vendor': './src/vendors.ts',
    'app': './src/main.ts' // our angular app
  },
  /**
   * Resolve
   * Reference: http://webpack.github.io/docs/configuration.html#resolve
   */
  resolve: {
    //cache: false,
    root: path.resolve('.'),
    // only discover files that have those extensions
    extensions: ['', '.ts', '.js', '.json', '.css', '.scss', '.sass', '.html'],
    alias: {
      'app': 'src/app',
      'common': 'src/common'
    },
    modulesDirectories: ['node_modules']
  },
  // ts: {
  //   silent: true
  // },
  module: {
    noParse: [/.+zone\.js\/dist\/.+/, /.+angular2\/bundles\/.+/, /angular2-polyfills\.js/],
    preLoaders: [],
    loaders: [{
        test: /\.ts$/,
        loader: 'ts',
        query: {
          'ignoreDiagnostics': [
            2403, // 2403 -> Subsequent variable declarations
            2300, // 2300 -> Duplicate identifier
            2374, // 2374 -> Duplicate number index signature
            2375, // 2375 -> Duplicate string index signature
            2502 // 2502 -> Referenced directly or indirectly
          ]
        },
        exclude: [isTest ? /\.(e2e)\.ts$/ : /\.(spec|e2e)\.ts$/, /node_modules\/(?!(ng2-.+))/]
      }, {
        test: /\.(woff2?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
        loader: "file?name=fonts/[name]-[hash:7].[ext]"
      },
      // copy those assets to output,
      {
        test: /\.(png|jpe?g|gif|svg)$/,
        loader: 'file?name=img/[name].[ext]'
      },
      // Support for CSS as raw text
      // use 'null' loader in test mode (https://github.com/webpack/null-loader)
      {
        test: /\.css$/,
        exclude: path.resolve('src/app'),
        loader: isTest ? 'null' : ExtractTextPlugin.extract('style', 'css?sourceMap!postcss')
      },
      // support for .scss files
      // use 'null' loader in test mode (https://github.com/webpack/null-loader)
      {
        test: /\.(scss|sass)$/,
        exclude: path.resolve('src/app'),
        loader: isTest ? 'null' : ExtractTextPlugin.extract('style', 'css?sourceMap!postcss!sass')
      },
      // support for .html as raw text
      {
        test: /\.html$/,
        loader: 'raw'
      }, {
        test: /jquery\.js/,
        loader: 'null-loader',
       exclude: path.resolve('node_modules/foundation-sites/')
      },
    ]
  },
  plugins: [

    // // Define env variables to help with builds
    // // Reference: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
    //new OccurenceOrderPlugin(true),
    new CommonsChunkPlugin({
      name: ['vendor', 'polyfills']
    }),
    // Copy assets from the public folder
    // Reference: https://github.com/kevlened/copy-webpack-plugin
    new CopyWebpackPlugin([{
      from: path.resolve('src/public')
    }], {
      ignore: [{
        glob: '**/*.db',
        dot: true
      }]
    }),
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    }),
    // Inject script and link tags into html files
    // Reference: https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      template: './src/public/index.html',
      inject: 'body',
      chunksSortMode: 'dependency'
    }),
    // Extract css files
    // Reference: https://github.com/webpack/extract-text-webpack-plugin
    new ExtractTextPlugin('css/[name]-[hash:7].css')
  ],
  /**
   * Sass
   * Reference: https://github.com/jtangelder/sass-loader
   */
  sassLoader: {
    includePaths: [path.resolve(__dirname, "../node_modules/foundation-sites/scss")]
  }
};
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const autoprefixer = require('autoprefixer');

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const NamedModulesPlugin = require('webpack/lib/NamedModulesPlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

const helpers = require('./helpers');

module.exports = function(options) {
  const NODE_ENV = options.env;
  return {
    resolve: {
      extensions: ['.ts', '.js'],
      mainFields: ['module', 'browser', 'main'],
      modules: [
        path.resolve('.'),
        'node_modules'
      ]
    },
    entry: {
      polyfills: './src/polyfills.ts'
    },
    output: {
      path: path.resolve('./public'),
      publicPath: '/'
    },
    module: {
      rules: [
        helpers.rules.html,
        helpers.rules.css,
        helpers.rules.scss,
        helpers.rules.typescript
      ]
    },
    plugins: [
      new DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(NODE_ENV)
      }),
      new NamedModulesPlugin(),
      new LoaderOptionsPlugin({
        debug: false,
        minimize: NODE_ENV === 'production',
        options: {
          postcss: [
            autoprefixer({ browsers: ['last 3 versions'] })
          ],
          resolve: {},
          sassLoader: {
            includePaths: ['src/shared'],
            outputStyle: 'compressed',
            precision: 10,
            sourceComments: false
          }
        }
      }),
      new ContextReplacementPlugin(
        /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
        path.resolve('src')
      ),
      new BundleAnalyzerPlugin({
        // this config can be removed when HMR will be supported
        // https://github.com/th0r/webpack-bundle-analyzer/issues/37
        analyzerMode: 'disabled',
        generateStatsFile: true,
        statsFilename: 'stats.json'
      }),
      new CommonsChunkPlugin({
        name: ['polyfills'],
        minChunks: Infinity
      }),
      new HtmlWebpackPlugin({
        chunkSortMeta: 'dependency',
        filename: 'index.html',
        hash: false,
        inject: 'body',
        template: './src/index.html'
      })
    ]
  }
};
<commit_msg>build: resolve webpack angular4 issue<commit_after>'use strict';

const path = require('path');
const autoprefixer = require('autoprefixer');

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const NamedModulesPlugin = require('webpack/lib/NamedModulesPlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const helpers = require('./helpers');

module.exports = function(options) {
  const NODE_ENV = options.env;
  return {
    resolve: {
      extensions: ['.ts', '.js'],
      mainFields: ['module', 'browser', 'main'],
      modules: [
        path.resolve('.'),
        'node_modules'
      ]
    },
    entry: {
      polyfills: './src/polyfills.ts'
    },
    output: {
      path: path.resolve('./public'),
      publicPath: '/'
    },
    module: {
      rules: [
        helpers.rules.html,
        helpers.rules.css,
        helpers.rules.scss,
        helpers.rules.typescript
      ]
    },
    plugins: [
      new DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(NODE_ENV)
      }),
      new NamedModulesPlugin(),
      new LoaderOptionsPlugin({
        debug: false,
        minimize: NODE_ENV === 'production',
        options: {
          postcss: [
            autoprefixer({ browsers: ['last 3 versions'] })
          ],
          resolve: {},
          sassLoader: {
            includePaths: ['src/shared'],
            outputStyle: 'compressed',
            precision: 10,
            sourceComments: false
          }
        }
      }),
      new ContextReplacementPlugin(
        // /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
        /angular(\\|\/)core(\\|\/)@angular/,
        path.resolve('src')
      ),
      new BundleAnalyzerPlugin({
        // this config can be removed when HMR will be supported
        // https://github.com/th0r/webpack-bundle-analyzer/issues/37
        analyzerMode: 'disabled',
        generateStatsFile: true,
        statsFilename: 'stats.json'
      }),
      new CommonsChunkPlugin({
        name: ['polyfills'],
        minChunks: Infinity
      }),
      new HtmlWebpackPlugin({
        chunkSortMeta: 'dependency',
        filename: 'index.html',
        hash: false,
        inject: 'body',
        template: './src/index.html'
      })
    ]
  }
};
<|endoftext|>