<commit_before>/*global define*/
/*jslint white:true,browser:true*/
define([
    'bluebird',
    'kb_common/html',
    'common/validation',
    'common/events',
    'common/dom',
    'bootstrap',
    'css!font-awesome'
], function (Promise, html, Validation, Events, Dom) {
    'use strict';

    // Constants
    var t = html.tag,
        div = t('div'), select = t('select'), option = t('option');

    function factory(config) {
        var options = {},
            spec = config.parameterSpec,
            parent,
            dom,
            container,
            bus = config.bus,
            model = {
                availableValues: null,
                value: null
            };

        // Validate configuration.
        // Nothing to do...

        options.enabled = true;

        model.availableValues = spec.spec.dropdown_options.options;

        /*
         * If the parameter is optional, and is empty, return null.
         * If it allows multiple values, wrap single results in an array
         * There is a weird twist where if it ...
         * well, hmm, the only consumer of this, isValid, expects the values
         * to mirror the input rows, so we shouldn't really filter out any
         * values.
         */

        function getInputValue() {
            var control = dom.getElement('input-container.input'),
                selected = control.selectedOptions;

            if (selected.length === 0) {
                return;
            }

            // we are modeling a single string value, so we always just get the
            // first selected element, which is all there should be!
            return selected.item(0).value;
        }

        /*
         *
         * Text fields can occur in multiples.
         * We have a choice, treat single-text fields as a own widget
         * or as a special case of multiple-entry --
         * with a min-items of 1 and max-items of 1.
         *
         *
         */

        function validate() {
            return Promise.try(function () {
                if (!options.enabled) {
                    return {
                        isValid: true,
                        validated: false,
                        diagnosis: 'disabled'
                    };
                }

                var rawValue = getInputValue(),
                    validationResult = Validation.validateTextString(rawValue, {
                        required: options.required
                    });

                return {
                    isValid: validationResult.isValid,
                    validated: true,
                    diagnosis: validationResult.diagnosis,
                    errorMessage: validationResult.errorMessage,
                    value: validationResult.parsedValue
                };
            });
        }

        function makeInputControl(events) {
            var selected,
                selectOptions = model.availableValues.map(function (item) {
                    selected = false;
                    if (item.value === model.value) {
                        selected = true;
                    }

                    return option({
                        value: item.value,
                        selected: selected
                    }, item.display);
                });

            // CONTROL
            return select({
                id: events.addEvent({type: 'change', handler: function () {
                        validate()
                            .then(function (result) {
                                if (result.isValid) {
                                    bus.emit('changed', {
                                        newValue: result.value
                                    });
                                }
                                bus.emit('validation', {
                                    errorMessage: result.errorMessage,
                                    diagnosis: result.diagnosis
                                });
                            });
                    }}),
                class: 'form-control',
                dataElement: 'input'
            }, [option({value: ''}, '')].concat(selectOptions));
        }

        function render(input) {
            Promise.try(function () {
                var events = Events.make(),
                    inputControl = makeInputControl(events);

                dom.setContent('input-container', inputControl);
                events.attachEvents(container);
            })
                .then(function () {
                    autoValidate();
                });
        }

        function layout(events) {
            var content = div({
                dataElement: 'main-panel'
            }, [
                div({dataElement: 'input-container'})
            ]);
            return {
                content: content,
                events: events
            };
        }

        function autoValidate() {
            validate()
                .then(function (result) {
                    bus.emit('validation', {
                        errorMessage: result.errorMessage,
                        diagnosis: result.diagnosis
                    });
                });
        }

        function setModelValue(value) {
            return Promise.try(function () {
                if (model.value !== value) {
                    model.value = value;
                    return true;
                }
                return false;
            })
                .then(function (changed) {
                    render();
                });
        }

        function unsetModelValue() {
            return Promise.try(function () {
                model.value = undefined;
            })
                .then(function (changed) {
                    render();
                });
        }

        function resetModelValue() {
            if (spec.spec.default_values && spec.spec.default_values.length > 0) {
                setModelValue(spec.spec.default_values[0]);
            } else {
                unsetModelValue();
            }
        }

        // LIFECYCLE API

        function start() {
            return Promise.try(function () {
                bus.on('run', function (message) {
                    parent = message.node;
                    container = parent.appendChild(document.createElement('div'));
                    dom = Dom.make({node: container});

                    var events = Events.make(),
                        theLayout = layout(events);

                    container.innerHTML = theLayout.content;
                    events.attachEvents(container);

                    bus.on('reset-to-defaults', function () {
                        resetModelValue();
                    });
                    bus.on('update', function (message) {
                        setModelValue(message.value);
                    });
                    bus.emit('sync');
                });
            });
        }

//        function run(input) {
//            return Promise.try(function () {
//                return render(input);
//            })
//            .then(function () {
//                return autoValidate();
//            });
//        }

        return {
            start: start
        };
    }

    return {
        make: function (config) {
            return factory(config);
        }
    };
});<commit_msg>improve validation return value<commit_after>/*global define*/
/*jslint white:true,browser:true*/
define([
    'bluebird',
    'kb_common/html',
    'common/validation',
    'common/events',
    'common/dom',
    'bootstrap',
    'css!font-awesome'
], function (Promise, html, Validation, Events, Dom) {
    'use strict';

    // Constants
    var t = html.tag,
        div = t('div'), select = t('select'), option = t('option');

    function factory(config) {
        var options = {},
            spec = config.parameterSpec,
            parent,
            dom,
            container,
            bus = config.bus,
            model = {
                availableValues: null,
                value: null
            };

        // Validate configuration.
        // Nothing to do...

        options.enabled = true;

        model.availableValues = spec.spec.dropdown_options.options;

        /*
         * If the parameter is optional, and is empty, return null.
         * If it allows multiple values, wrap single results in an array
         * There is a weird twist where if it ...
         * well, hmm, the only consumer of this, isValid, expects the values
         * to mirror the input rows, so we shouldn't really filter out any
         * values.
         */

        function getInputValue() {
            var control = dom.getElement('input-container.input'),
                selected = control.selectedOptions;

            if (selected.length === 0) {
                return;
            }

            // we are modeling a single string value, so we always just get the
            // first selected element, which is all there should be!
            return selected.item(0).value;
        }

        /*
         *
         * Text fields can occur in multiples.
         * We have a choice, treat single-text fields as a own widget
         * or as a special case of multiple-entry --
         * with a min-items of 1 and max-items of 1.
         *
         *
         */

        function validate() {
            return Promise.try(function () {
                if (!options.enabled) {
                    return {
                        isValid: true,
                        validated: false,
                        diagnosis: 'disabled'
                    };
                }

                var rawValue = getInputValue(),
                    validationResult = Validation.validateTextString(rawValue, {
                        required: options.required
                    });

                return validationResult;
            });
        }

        function makeInputControl(events) {
            var selected,
                selectOptions = model.availableValues.map(function (item) {
                    selected = false;
                    if (item.value === model.value) {
                        selected = true;
                    }

                    return option({
                        value: item.value,
                        selected: selected
                    }, item.display);
                });

            // CONTROL
            return select({
                id: events.addEvent({type: 'change', handler: function () {
                        validate()
                            .then(function (result) {
                                if (result.isValid) {
                                    bus.emit('changed', {
                                        newValue: result.value
                                    });
                                }
                                bus.emit('validation', {
                                    errorMessage: result.errorMessage,
                                    diagnosis: result.diagnosis
                                });
                            });
                    }}),
                class: 'form-control',
                dataElement: 'input'
            }, [option({value: ''}, '')].concat(selectOptions));
        }

        function render(input) {
            Promise.try(function () {
                var events = Events.make(),
                    inputControl = makeInputControl(events);

                dom.setContent('input-container', inputControl);
                events.attachEvents(container);
            })
                .then(function () {
                    autoValidate();
                });
        }

        function layout(events) {
            var content = div({
                dataElement: 'main-panel'
            }, [
                div({dataElement: 'input-container'})
            ]);
            return {
                content: content,
                events: events
            };
        }

        function autoValidate() {
            validate()
                .then(function (result) {
                    bus.emit('validation', {
                        errorMessage: result.errorMessage,
                        diagnosis: result.diagnosis
                    });
                });
        }

        function setModelValue(value) {
            return Promise.try(function () {
                if (model.value !== value) {
                    model.value = value;
                    return true;
                }
                return false;
            })
                .then(function (changed) {
                    render();
                });
        }

        function unsetModelValue() {
            return Promise.try(function () {
                model.value = undefined;
            })
                .then(function (changed) {
                    render();
                });
        }

        function resetModelValue() {
            if (spec.spec.default_values && spec.spec.default_values.length > 0) {
                setModelValue(spec.spec.default_values[0]);
            } else {
                unsetModelValue();
            }
        }

        // LIFECYCLE API

        function start() {
            return Promise.try(function () {
                bus.on('run', function (message) {
                    parent = message.node;
                    container = parent.appendChild(document.createElement('div'));
                    dom = Dom.make({node: container});

                    var events = Events.make(),
                        theLayout = layout(events);

                    container.innerHTML = theLayout.content;
                    events.attachEvents(container);

                    bus.on('reset-to-defaults', function () {
                        resetModelValue();
                    });
                    bus.on('update', function (message) {
                        setModelValue(message.value);
                    });
                    bus.emit('sync');
                });
            });
        }

//        function run(input) {
//            return Promise.try(function () {
//                return render(input);
//            })
//            .then(function () {
//                return autoValidate();
//            });
//        }

        return {
            start: start
        };
    }

    return {
        make: function (config) {
            return factory(config);
        }
    };
});<|endoftext|>


<commit_before>const sample = require('lodash.sample');
const argv = require('minimist')(process.argv.slice(2));
const isArray = require('lodash.isarray');

const customLaunchers = {
  bs_win81_ie_11: {
    base: 'BrowserStack',
    browser: 'ie',
    browser_version: '11.0',
    os: 'Windows',
    os_version: '8.1',
  },
  bs_win8_ie_10: {
    base: 'BrowserStack',
    browser: 'ie',
    browser_version: '10.0',
    os: 'Windows',
    os_version: '8',
  },
  bs_mavericks_chrome_44: {
    base: 'BrowserStack',
    device: null,
    os: 'OS X',
    browser_version: '44.0',
    browser: 'chrome',
    os_version: 'Mavericks',
  },
  bs_yosemite_firefox_40: {
    base: 'BrowserStack',
    device: null,
    os: 'OS X',
    browser_version: '40.0',
    browser: 'firefox',
    os_version: 'Yosemite',
  },
  bs_sierra_safari_10: {
    base: 'BrowserStack',
    device: null,
    os: 'OS X',
    browser_version: '10.0',
    browser: 'safari',
    os_version: 'Sierra',
  },
  bs_yosemite_safari_8: {
    base: 'BrowserStack',
    device: null,
    os: 'OS X',
    browser_version: '8.0',
    browser: 'safari',
    os_version: 'Yosemite',
  },
  bs_win81_opera_31: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '31',
    browser: 'opera',
    os_version: '8.1',
  },
  bs_win7_firefox_20: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '20.0',
    browser: 'firefox',
    os_version: '7',
  },
  bs_win7_firefox_15: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '15.0',
    browser: 'firefox',
    os_version: '7',
  },
  bs_win81_chrome_22: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '22.0',
    browser: 'chrome',
    os_version: '8.1',
  },
  bs_win10_edge_13: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '13.0',
    browser: 'edge',
    os_version: '10',
  },
  bs_win10_edge_14: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '14.0',
    browser: 'edge',
    os_version: '10',
  },
  bs_win10_firefox_46: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '46.0',
    browser: 'firefox',
    os_version: '10',
  },
  bs_win10_firefox_52: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '52.0',
    browser: 'firefox',
    os_version: '10',
  },
  bs_win10_chrome_50: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '50.0',
    browser: 'chrome',
    os_version: '10',
  },
  bs_win10_chrome_57: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '57.0',
    browser: 'chrome',
    os_version: '10',
  },
  bs_win10_chrome_59: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '59.0',
    browser: 'chrome',
    os_version: '10',
  },
};

const getAllBrowsers = () => Object.keys(customLaunchers);
const getRandomBrowser = () => sample(getAllBrowsers());

/**
 * Environment variables are passed into the script and the depth of testing
 * is affected accordginly.
 *
 * - Whenever on a PR we only want to probe test with Firefox
 * - Whenever we are on the most recent node version on Travis we test via BrowserStack
 * - If none of the prior mentioned holds we assume to be running local and respect the passed
 *   in borwsers argv
 */
const shouldProbeOnly = argv.shouldProbeOnly !== '';
const shouldTestOnBrowserStack = argv.shouldTestOnBrowserStack !== '';
const defaultBrowsers = ['Firefox'];
const argvBrowsers = isArray(argv.browsers)
  ? argv.browsers.split(' ')
  : defaultBrowsers;
const browsers = shouldTestOnBrowserStack
  ? shouldProbeOnly ? defaultBrowsers : getAllBrowsers()
  : argvBrowsers;

module.exports = {
  customLaunchers,
  browsers,
  getRandomBrowser,
};
<commit_msg>test: fix TRAVIS_PULL_REQUEST being false on master<commit_after>const sample = require('lodash.sample');
const argv = require('minimist')(process.argv.slice(2));
const isArray = require('lodash.isarray');

const customLaunchers = {
  bs_win81_ie_11: {
    base: 'BrowserStack',
    browser: 'ie',
    browser_version: '11.0',
    os: 'Windows',
    os_version: '8.1',
  },
  bs_win8_ie_10: {
    base: 'BrowserStack',
    browser: 'ie',
    browser_version: '10.0',
    os: 'Windows',
    os_version: '8',
  },
  bs_mavericks_chrome_44: {
    base: 'BrowserStack',
    device: null,
    os: 'OS X',
    browser_version: '44.0',
    browser: 'chrome',
    os_version: 'Mavericks',
  },
  bs_yosemite_firefox_40: {
    base: 'BrowserStack',
    device: null,
    os: 'OS X',
    browser_version: '40.0',
    browser: 'firefox',
    os_version: 'Yosemite',
  },
  bs_sierra_safari_10: {
    base: 'BrowserStack',
    device: null,
    os: 'OS X',
    browser_version: '10.0',
    browser: 'safari',
    os_version: 'Sierra',
  },
  bs_yosemite_safari_8: {
    base: 'BrowserStack',
    device: null,
    os: 'OS X',
    browser_version: '8.0',
    browser: 'safari',
    os_version: 'Yosemite',
  },
  bs_win81_opera_31: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '31',
    browser: 'opera',
    os_version: '8.1',
  },
  bs_win7_firefox_20: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '20.0',
    browser: 'firefox',
    os_version: '7',
  },
  bs_win7_firefox_15: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '15.0',
    browser: 'firefox',
    os_version: '7',
  },
  bs_win81_chrome_22: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '22.0',
    browser: 'chrome',
    os_version: '8.1',
  },
  bs_win10_edge_13: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '13.0',
    browser: 'edge',
    os_version: '10',
  },
  bs_win10_edge_14: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '14.0',
    browser: 'edge',
    os_version: '10',
  },
  bs_win10_firefox_46: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '46.0',
    browser: 'firefox',
    os_version: '10',
  },
  bs_win10_firefox_52: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '52.0',
    browser: 'firefox',
    os_version: '10',
  },
  bs_win10_chrome_50: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '50.0',
    browser: 'chrome',
    os_version: '10',
  },
  bs_win10_chrome_57: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '57.0',
    browser: 'chrome',
    os_version: '10',
  },
  bs_win10_chrome_59: {
    base: 'BrowserStack',
    device: null,
    os: 'Windows',
    browser_version: '59.0',
    browser: 'chrome',
    os_version: '10',
  },
};

const getAllBrowsers = () => Object.keys(customLaunchers);
const getRandomBrowser = () => sample(getAllBrowsers());

/**
 * Environment variables are passed into the script and the depth of testing
 * is affected accordginly.
 *
 * - Whenever on a PR we only want to probe test with Firefox
 * - Whenever we are on the most recent node version on Travis we test via BrowserStack
 * - If none of the prior mentioned holds we assume to be running local and respect the passed
 *   in borwsers argv
 */
const shouldProbeOnly = argv.shouldProbeOnly !== 'false';
const shouldTestOnBrowserStack = argv.shouldTestOnBrowserStack !== '';
const defaultBrowsers = ['Firefox'];
const argvBrowsers = isArray(argv.browsers)
  ? argv.browsers.split(' ')
  : defaultBrowsers;
const browsers = shouldTestOnBrowserStack
  ? shouldProbeOnly ? defaultBrowsers : getAllBrowsers()
  : argvBrowsers;

module.exports = {
  customLaunchers,
  browsers,
  getRandomBrowser,
};
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var _ = require('@sailshq/lodash');
var async = require('async');

//
// TODO
// Pull this into a separate module, since it's not specific to Sails.
//

/**
 * Mix-in an `after` function to an EventEmitter.
 *
 * If `events` have already fired, trigger fn immediately (with no args)
 * Otherwise bind a normal one-time event using `EventEmitter.prototype.once()`.
 * Useful for checking whether or not something has finished loading, etc.
 *
 * This is a lot like jQuery's `$(document).ready()`.
 *
 * @param  {EventEmitter} emitter
 */

module.exports = function mixinAfter(emitter) {

  /**
   * { emitter.warmEvents }
   *
   * Events which have occurred at least once
   * (Required to support `emitter.after()`)
   */
  emitter.warmEvents = {};

  /**
   * emitter.emit()
   *
   * Override `EventEmitter.prototype.emit`.
   * (Required to support `emitter.after()`)
   */

  var _emit = emitter.emit;
  emitter.emit = function(evName) {
    var args = Array.prototype.slice.call(arguments, 0);
    emitter.warmEvents[evName] = true;
    _emit.apply(emitter, args);
  };

  /**
   * `emitter.after()`
   *
   * Fires your handler **IF THE SPECIFIED EVENT HAS ALREADY BEEN TRIGGERED** or **WHEN IT IS TRIGGERED**.
   *
   * @param  {String|Array} events   [name of the event(s)]
   * @param  {Function}     fn       [event handler function]
   * @context {Sails}
   */

  emitter.after = function(events, fn) {

    // Support a single event or an array of events
    if (!_.isArray(events)) {
      events = [events];
    }

    // Convert named event dependencies into an array
    // of async-compatible functions.
    var dependencies = _.reduce(events,
      function(dependencies, event) {

        var handlerFn = function(cb) {
          if (emitter.warmEvents[event]) {
            cb();
          } else {
            emitter.once(event, cb);
          }
        };
        dependencies.push(handlerFn);
        return dependencies;
      }, []);

    // When all events have fired, call `fn`
    // (all arguments passed to `emit()` calls are discarded)
    async.parallel(dependencies, function(err) {
      if (err) sails.log.error(err);
      return fn();
    });

  };

};
<commit_msg>Make emit 100% EventEmitter.emit compatible<commit_after>/**
 * Module dependencies
 */

var _ = require('@sailshq/lodash');
var async = require('async');

//
// TODO
// Pull this into a separate module, since it's not specific to Sails.
//

/**
 * Mix-in an `after` function to an EventEmitter.
 *
 * If `events` have already fired, trigger fn immediately (with no args)
 * Otherwise bind a normal one-time event using `EventEmitter.prototype.once()`.
 * Useful for checking whether or not something has finished loading, etc.
 *
 * This is a lot like jQuery's `$(document).ready()`.
 *
 * @param  {EventEmitter} emitter The Sails application instance
 */

module.exports = function mixinAfter(emitter) {

  /**
   * { emitter.warmEvents }
   *
   * Events which have occurred at least once
   * (Required to support `emitter.after()`)
   */
  emitter.warmEvents = {};

  var _emit = emitter.emit;
  /**
   * emitter.emit()
   *
   * Synchronously calls each of the listeners registered for the event named eventName, in the order they were registered, passing the supplied arguments to each.
   *
   * Override `EventEmitter.prototype.emit` to keep track of all the events that have occurred once.
   * (Required to support `emitter.after()`)
   *
   * @param {String} eventName name of the event
   * @return {boolean} Returns true if the event had listeners, false otherwise.
   * @see https://nodejs.org/api/events.html#events_emitter_emit_eventname_args
   */
  emitter.emit = function(eventName) {
    var args = Array.prototype.slice.call(arguments, 0);
    emitter.warmEvents[eventName] = true;
    return _emit.apply(emitter, args);
  };

  /**
   * `emitter.after()`
   *
   * Fires your handler **IF THE SPECIFIED EVENT HAS ALREADY BEEN TRIGGERED** or **WHEN IT IS TRIGGERED**.
   *
   * @param  {String|Array} events   [name of the event(s)]
   * @param  {Function}     fn       [event handler function]
   * @context {Sails}
   */

  emitter.after = function(events, fn) {

    // Support a single event or an array of events
    if (!_.isArray(events)) {
      events = [events];
    }

    // Convert named event dependencies into an array
    // of async-compatible functions.
    var dependencies = _.reduce(events,
      function(dependencies, event) {

        var handlerFn = function(cb) {
          if (emitter.warmEvents[event]) {
            cb();
          } else {
            emitter.once(event, cb);
          }
        };
        dependencies.push(handlerFn);
        return dependencies;
      }, []);

    // When all events have fired, call `fn`
    // (all arguments passed to `emit()` calls are discarded)
    async.parallel(dependencies, function(err) {
      if (err) sails.log.error(err);
      return fn();
    });

  };

};
<|endoftext|>


<commit_before>const hapiPino = require('hapi-pino')
const escape = require('js-string-escape')
const pino = require('pino')
const colors = require('./colors')
const formats = require('./formats')
const tokens = require('./tokens')
const utils = require('./utils')

/**
 * @type RegExp
 * @private
 *
 * The regular expression to extract tokens
 */
const re = /:(\w{2,})(?:\[([^\]]+)])?/g

/**
 * @function
 * @private
 *
 * Compile the passed format string based on the aggregated
 * data and further options, see below. If the format is
 * disabled, get the stringified data. Otherwise get a the
 * evaluated and – if necessary – stringified format string.
 *
 * @param {string | boolean} format The format to be compiled
 * @param {Object.<Function>} tokens The list of all registered tokens
 * @param {boolean} isJSON The format is a JSON-like string
 * @param {string | number} space The indentation for `JSON.stringify`
 * @param {Object} data The data aggregated by `pino`
 * @returns {string} The compiled format string
 */
/* eslint-disable no-eval */
function compile (format, tokens, isJSON, space, data) {
  if (format === false) {
    return JSON.stringify(data, null, space)
  }

  const js = escape(format).replace(re, (m, name, arg) => {
    const tokenArgs = 'Array.prototype.slice.call(arguments).slice(4)'
    const template = `tokens[${utils.stringify(name)}](...(${tokenArgs}), ${utils.stringify(arg)}) || undefined`
    const token = tokens[name]

    if (!token) {
      return isJSON ? utils.stringify(m) : m
    } else if (!isJSON) {
      const interim = eval(template)
      return typeof interim === 'object' ? utils.stringify(interim) : interim
    }

    return template
  })

  if (isJSON) {
    return JSON.stringify(eval(js), null, space)
  }

  return js
}
/* eslint-enable no-eval */

/**
 * @function
 * @private
 *
 * Get the configuration for the `pino` logger based
 * on the passed `laabr` options.
 *
 * @param {Object} options The `laabr` plugin related options
 * @returns {Object} The overriden `pino` configs
 */
function getLoggerConfig (options) {
  return Object.assign(options.pino, {
    browser: {},
    timestamp: true,
    prettyPrint: {
      formatter: (data) => {
        const format = formats.get(data)
        const isJSON = utils.isJSON(format)
        const pictor = colors.get(data, isJSON || !options.colored)

        return compile(format, tokens, isJSON, options.indent, data, pictor)
      }
    }
  })
}

/**
 * @function
 * @private
 *
 * Get the configuration for the `hapi-pino` plugin based
 * on the passed `laabr` options.
 *
 * @param {Object} options The `laabr` plugin related options
 * @returns {Object} The overriden `hapi-pino` configs
 */
function getPluginConfig (options, loggerConfig) {
  return Object.assign(options.plugin, {
    instance: pino(loggerConfig, options.stream),
    prettyPrint: false,
    mergeHapiLogData: false
  })
}

/**
 * @function
 * @public
 *
 * Compose the `hapi-pino` plugin registration object based
 * on the passed `laabr` options and a prio `pino` instance.
 *
 * @param {Object} options The `laabr` plugin related options
 * @returns {Object.<Function|Object>} The composed plugin registration object
 */
function get (options) {
  const loggerConfig = getLoggerConfig(options)
  const pluginConfig = getPluginConfig(options, loggerConfig)

  return {
    register: hapiPino,
    options: pluginConfig
  }
}

module.exports = get
<commit_msg>change default<commit_after>const hapiPino = require('hapi-pino')
const escape = require('js-string-escape')
const pino = require('pino')
const colors = require('./colors')
const formats = require('./formats')
const tokens = require('./tokens')
const utils = require('./utils')

/**
 * @type RegExp
 * @private
 *
 * The regular expression to extract tokens
 */
const re = /:(\w{2,})(?:\[([^\]]+)])?/g

/**
 * @function
 * @private
 *
 * Compile the passed format string based on the aggregated
 * data and further options, see below. If the format is
 * disabled, get the stringified data. Otherwise get a the
 * evaluated and – if necessary – stringified format string.
 *
 * @param {string | boolean} format The format to be compiled
 * @param {Object.<Function>} tokens The list of all registered tokens
 * @param {boolean} isJSON The format is a JSON-like string
 * @param {string | number} space The indentation for `JSON.stringify`
 * @param {Object} data The data aggregated by `pino`
 * @returns {string} The compiled format string
 */
/* eslint-disable no-eval */
function compile (format, tokens, isJSON, space, data) {
  if (format === false) {
    return JSON.stringify(data, null, space)
  }

  const js = escape(format).replace(re, (m, name, arg) => {
    const tokenArgs = 'Array.prototype.slice.call(arguments).slice(4)'
    const template = `tokens[${utils.stringify(name)}](...(${tokenArgs}), ${utils.stringify(arg)}) || "-"`
    const token = tokens[name]

    if (!token) {
      return isJSON ? utils.stringify(m) : m
    } else if (!isJSON) {
      const interim = eval(template)
      return typeof interim === 'object' ? utils.stringify(interim) : interim
    }

    return template
  })

  if (isJSON) {
    return JSON.stringify(eval(js), null, space)
  }

  return js
}
/* eslint-enable no-eval */

/**
 * @function
 * @private
 *
 * Get the configuration for the `pino` logger based
 * on the passed `laabr` options.
 *
 * @param {Object} options The `laabr` plugin related options
 * @returns {Object} The overriden `pino` configs
 */
function getLoggerConfig (options) {
  return Object.assign(options.pino, {
    browser: {},
    timestamp: true,
    prettyPrint: {
      formatter: (data) => {
        const format = formats.get(data)
        const isJSON = utils.isJSON(format)
        const pictor = colors.get(data, isJSON || !options.colored)

        return compile(format, tokens, isJSON, options.indent, data, pictor)
      }
    }
  })
}

/**
 * @function
 * @private
 *
 * Get the configuration for the `hapi-pino` plugin based
 * on the passed `laabr` options.
 *
 * @param {Object} options The `laabr` plugin related options
 * @returns {Object} The overriden `hapi-pino` configs
 */
function getPluginConfig (options, loggerConfig) {
  return Object.assign(options.plugin, {
    instance: pino(loggerConfig, options.stream),
    prettyPrint: false,
    mergeHapiLogData: false
  })
}

/**
 * @function
 * @public
 *
 * Compose the `hapi-pino` plugin registration object based
 * on the passed `laabr` options and a prio `pino` instance.
 *
 * @param {Object} options The `laabr` plugin related options
 * @returns {Object.<Function|Object>} The composed plugin registration object
 */
function get (options) {
  const loggerConfig = getLoggerConfig(options)
  const pluginConfig = getPluginConfig(options, loggerConfig)

  return {
    register: hapiPino,
    options: pluginConfig
  }
}

module.exports = get
<|endoftext|>


<commit_before>"use strict";
var crc = require("../basic/crc");
var path = require("path");
var fs = require("fs");
var report = require("./report");
var setting = require("./setting");
var getArgs = require('./getArgs');
var strings = require("../basic/strings");
var r21 = "'()*+,-./0123456789:;"
var r29 = "?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[";
var r34 = "]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var memory = require("../efront/memery");
var codetemp = function (delta) {
    var temp = [];
    while (delta > 0) {
        var mode = delta % 84;
        if (mode < 21) {
            temp.push(r21[mode])
        }
        else if (mode < 50) {
            temp.push(r29[mode - 21]);
        }
        else {
            temp.push(r34[mode - 50]);
        }
        delta = delta / 84 | 0;
    }
    return temp;
}
var encrypt = function (text, efrontsign) {
    text = String(text);
    if (!encoded) return text;
    var start = parseInt(efrontsign, 36) % 128;
    var rest = [];
    for (var cx = 0, dx = text.length; cx < dx; cx++) {
        var code = text.charCodeAt(cx);
        var delta = code - start;
        if (delta < 0) {
            delta = -delta;
            if (delta < 5) {
                rest.push(r21[delta])
            } else if (delta < 34) {
                rest.push(r29[delta - 5]);
            } else {
                var temp = codetemp(delta - 33);
                rest.push(r21[10 + temp.length]);
                rest.push.apply(rest, temp);
            }
        }
        else {
            if (delta < 6) {
                rest.push(r21[delta + 5]);
            }
            else if (delta < 40) {
                rest.push(r34[delta - 6]);
            } else {
                var temp = codetemp(delta - 39);
                rest.push(r21[15 + temp.length]);
                rest.push.apply(rest, temp);
            }
        }
        start = code;
    }
    return rest.join("");
}
var encoded = memory.ENCRYPT;
var compress = memory.COMPRESS;
var ReleaseTime = new Date();
if (encoded) encoded = (Math.random() * ReleaseTime | 0).toString(36);

ReleaseTime = String(ReleaseTime);
var buildHtml = function (html, code) {
    var isZimoliDetected = false;
    var poweredByComment;
    var html = html.toString()
        .replace(/^\s*(<!doctype[^>]*?>\s*)?<!--([\s\S]*?)--!?>/i, function (_, doctype, message) {
            // `${doctype}<!--${message}\r\n${efrontReloadVersionAttribute}-->`
            poweredByComment = _;
            return "";
        })
        .replace(/<!--[\s\S]*?--!?>/g, "")
        .replace(/<title>(.*?)<\/title>/i, `<title>${memory.TITLE || "$1"}</title>`)
        .replace(/<script\b[\s\S]*?<\/script>\s*/ig, function (script) {
            if (/(["'`])post\1\s*,\s*(['`"])comm\/main\2/i.test(script)) {
                isZimoliDetected = true;
                return "";
            }
            if (/<script\s[^>]*?(type\s*=\s*)?(["']|)efront\-?(?:hook|main|host|script|loader)\1[^>]*?>/i.test(script)) {
                isZimoliDetected = true;
            }
            if (/\b((delete|ignore)oncompile|efrontworker)\b/i.test(script)) {
                return "";
            }
            return script;
        });

    if (isZimoliDetected)
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script compiledinfo${encoded ? '-' + encoded : ''}="${ReleaseTime} by efront ${require(path.join(__dirname, "../../package.json")).version}">\r\n<!--\r\n-function(){${code}}.call(this)\r\n-->\r\n</script>\r\n${head}`);
    if (memory.IN_WATCH_MODE) {
        let WATCH_PORT = memory.WATCH_PORT;
        let reloadVersion = +new Date();
        let efrontReloadVersionAttribute = "efront-reload-version";
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script ${efrontReloadVersionAttribute}=${reloadVersion}>
        -function(){
            "use strict";
            var load = function(url, onload, method){
                var xhr = new XMLHttpRequest;
                xhr.open(method, url);
                xhr.timeout = 0;
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4 && xhr.status === 200) onload(xhr);
                };
                xhr.send("${reloadVersion}");
            };
            var reloader = function(){
                load(location.pathname + "?time=" + +new Date(), function(xhr){
                    var version = xhr.responseText.match(/\\b${efrontReloadVersionAttribute}\\s*=\\s*(\\d+)\\b/);
                    console.info("当前版本:${reloadVersion},目标版本:" + targetVersion + "正在重新加载,..");
                    if( !version || +version[1] !== ${reloadVersion}) location.reload() | console.warn("reload..", new Date);
                    else setTimeout(reloader, 200);
                }, "get");
            };
            var targetVersion = ${reloadVersion};
            var checkUpdate = function(xhr){
                targetVersion = xhr.responseText||xhr.response;
                reloader();
            };
            load("http://localhost${WATCH_PORT ? ":" + WATCH_PORT : ""}/reload/${reloadVersion}", checkUpdate, "post");
        }();
        </script>\r\n${head}`);
        memory.WATCH_PROJECT_VERSION = reloadVersion;
    }
    if (poweredByComment) {
        html = html.replace(/^\s*(?:<!doctype[\s\S]*?>)?/i, poweredByComment);
    }
    return html;
};
function toApplication(responseTree) {
    var mainScript = responseTree.main || responseTree["main.js"] || null;
    var indexHtml = responseTree["/index.html"] || responseTree["@index.html"];
    if (!indexHtml) {
        var htmlPath = path.join(__dirname, "../../apps", "index.html");
        indexHtml = {
            time: 0,
            needed: true,
            fullpath: htmlPath,
            data: fs.readFileSync(htmlPath),
            realpath: htmlPath,
            version: fs.statSync(htmlPath).mtime,
            destpath: path.join("index.html"),
        };
        responseTree["/index.html"] = indexHtml;
    }
    if (mainScript) {
        Object.keys(responseTree).forEach(function (key) {
            if (/\.(jsp|php|html|asp)$/i.test(key)) {
                var response = responseTree[key];
                if (response && response.data) {
                    response.data = buildHtml(response.data, mainScript.data);
                }
            }
        });
    }
    delete responseTree["main"];
    delete responseTree["main.js"];
    return responseTree;
}
var rebuildData = function (responseTree) {
    var keys = Object.keys(responseTree).sort();
    var keysmap = Object.create(null);
    var renmap = Object.create(null);
    keys.forEach(function (k) {
        var o = responseTree[k];
        if (!o.data || !o.destpath || !o.realpath) {
            return;
        }
        var k0 = k.toLowerCase().replace(/\d+$/, '');
        if (k === 'Item') console.log(k, k0, 'k');
        if (k0 in keysmap) {
            keysmap[k0]++;
            k0 = k0 + keysmap[k0];
            if (k0 !== k) renmap[k] = k0;
        } else {
            keysmap[k0] = 1;
        }
    });
    Object.keys(renmap).forEach(k => {
        var o = responseTree[k];
        if (o.type !== '') {
            delete renmap[k];
            console.warn("发现可能被覆盖的路径", o.destpath);
            return;
        }

        var k1 = renmap[k];
        delete responseTree[k];
        responseTree[k1] = o;
        k1 = k1.replace(/^[\s\S]*?([^\/\\]*?)(\.[^\/\\\.]+)?$/, '$1');
        var m = /^([\s\S]*?)[^\/\\]*?(\.[^\/\\\.]+)?$/.exec(o.destpath);
        if (m[1]) {
            o.destpath = m[1] + k1 + m[2];
        }
    });

    Object.keys(responseTree).forEach(function (k) {
        var imageIndex = 0;
        var rep = function (e) {
            if (typeof e !== "string") return String(e);

            return strings.encode(e.replace(/(["`']|)data(\.\w+)\:([\w\+\/\=,;\-\.]+)\1/gi, function (_, quote, ext, data) {
                var match = /^([\w\-\.\/]+;base64)?,([\w\+\/\-\=]+)$/i.exec(data);
                if (!match) return _;
                do {
                    imageIndex++;
                    var name = k + "-" + imageIndex + ext;
                } while (name in responseTree);
                var destpath = response.destpath.replace(/\.[\w]+$/, '') + '-' + imageIndex + ext;
                responseTree[name] = { destpath, data: Buffer.from(match[2], "base64"), realpath: true, url: name };
                return quote + destpath.replace(/\\/g, '/') + quote;
            }));
        };
        var response = responseTree[k];
        if (!response.data) return;
        var data = String(response.data);

        var { argNames, args, required, dependenceNamesOffset, strs, strend } = getArgs(data);
        if (strs && strs.length > 0) {
            strs = `[${strs.map(rep)}]`;
            data = response.data = data.slice(0, dependenceNamesOffset) + (strs.length * 2).toString(36) + strs + data.slice(strend);
        }
        if (!dependenceNamesOffset || !required) return;
        args = args.map(a => {
            if (!(a in renmap)) return a;
            return renmap[a];
        });
        var argstr = args.concat(argNames, required.split(";").map(a => {
            return a.replace(/\.(\w+)$/g, '').replace(/\-(\w)/g, (_, a) => a.toUpperCase());
        }).join(";")).join(",");
        var arglen = (argstr.length << 1).toString(36);
        while (arglen.length < 3) {
            arglen = "0" + arglen;
        }
        response.data = arglen + argstr + data.slice(dependenceNamesOffset);
    });
};
module.exports = function (responseTree) {
    rebuildData(responseTree);
    report(responseTree);
    if (!responseTree["main"] && !responseTree["main.js"]) {
        console.log(Object.keys(responseTree).join(','))
        console.warn("在您所编译的项目中没有发现主程序");
        return toApplication(responseTree);
    }
    var commbuilder = require("../efront/commbuilder");
    commbuilder.compress = false;
    var mainScript = responseTree.main || responseTree["main.js"];
    var mainScriptData = commbuilder(mainScript.data, "main.js", mainScript.realpath, []);
    commbuilder.compress = +compress;
    var versionTree = {};
    if (setting.is_file_target) {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(v.name) || !v.data) return;
            if (v.type === "@") return;
            if (v.name !== "main") {
                versionTree[v.name] = encrypt(v.data, encoded);
                delete responseTree[k];
            }
        });
    } else {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (!v) return;
            if (v.type === "@") return;
            if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(v.name) || !v.data) return;
            if (v.name !== "main") {
                v.data = encrypt(v.data, encoded);
                var responseVersion = crc([].map.call(v.data.toString(), e => e.charCodeAt(0))).toString(36) + (+v.data.length).toString(36);
                versionTree[v.name] = responseVersion;
            }
        });
    }

    return Promise.resolve(mainScriptData).then(function (mainScriptData) {
        if (setting.is_file_target) {
            var xTreeName = /(?:\bresponseTree\s*|\[\s*(["'])responseTree\1\s*\])\s*\:\s*(.+?)\b/m.exec(mainScriptData)[2];
            commbuilder.prepare = false;
        } else {
            var xTreeName = /(?:\bversionTree\s*|\[\s*(["'])versionTree\1\s*\])\s*\:\s*(.+?)\b/m.exec(mainScriptData)[2];
        }

        var code = "{\r\n" + Object.keys(versionTree).map(k => `["${k}"]:"${versionTree[k]}"`).join(",\r\n\t") + "\r\n}";
        var versionVariableName;
        code = mainScriptData.toString()
            .replace(/var\s+killCircle[\s\S]*?\}\s*\};/, 'var killCircle=function(){};')
            .replace(/(?:\.send|\[\s*(["'])send\1\s*\])\s*\((.*?)\)/g, (match, quote, data) => (versionVariableName = data || "", quote ? `[${quote}send${quote}]()` : ".send()"))
            .replace(/(['"])post\1\s*,(.*?)\s*\)/ig, `$1get$1,$2${versionVariableName && `+"${memory.EXTT}?"+` + versionVariableName})`)
            .replace(
                new RegExp(/\b/.source + xTreeName + /(\s*)=(\s*)\{.*?\}/.source),
                function (m, s1, s2) {
                    return xTreeName + `${s1}=${s2}${code}`;
                }
            );
        return commbuilder(code, "main.js", mainScript.realpath, []);
    }).then(function (mainScriptData) {
        mainScript.data = mainScriptData;
        return toApplication(responseTree);
    });
};<commit_msg>删除log<commit_after>"use strict";
var crc = require("../basic/crc");
var path = require("path");
var fs = require("fs");
var report = require("./report");
var setting = require("./setting");
var getArgs = require('./getArgs');
var strings = require("../basic/strings");
var r21 = "'()*+,-./0123456789:;"
var r29 = "?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[";
var r34 = "]^_`abcdefghijklmnopqrstuvwxyz{|}~";
var memory = require("../efront/memery");
var codetemp = function (delta) {
    var temp = [];
    while (delta > 0) {
        var mode = delta % 84;
        if (mode < 21) {
            temp.push(r21[mode])
        }
        else if (mode < 50) {
            temp.push(r29[mode - 21]);
        }
        else {
            temp.push(r34[mode - 50]);
        }
        delta = delta / 84 | 0;
    }
    return temp;
}
var encrypt = function (text, efrontsign) {
    text = String(text);
    if (!encoded) return text;
    var start = parseInt(efrontsign, 36) % 128;
    var rest = [];
    for (var cx = 0, dx = text.length; cx < dx; cx++) {
        var code = text.charCodeAt(cx);
        var delta = code - start;
        if (delta < 0) {
            delta = -delta;
            if (delta < 5) {
                rest.push(r21[delta])
            } else if (delta < 34) {
                rest.push(r29[delta - 5]);
            } else {
                var temp = codetemp(delta - 33);
                rest.push(r21[10 + temp.length]);
                rest.push.apply(rest, temp);
            }
        }
        else {
            if (delta < 6) {
                rest.push(r21[delta + 5]);
            }
            else if (delta < 40) {
                rest.push(r34[delta - 6]);
            } else {
                var temp = codetemp(delta - 39);
                rest.push(r21[15 + temp.length]);
                rest.push.apply(rest, temp);
            }
        }
        start = code;
    }
    return rest.join("");
}
var encoded = memory.ENCRYPT;
var compress = memory.COMPRESS;
var ReleaseTime = new Date();
if (encoded) encoded = (Math.random() * ReleaseTime | 0).toString(36);

ReleaseTime = String(ReleaseTime);
var buildHtml = function (html, code) {
    var isZimoliDetected = false;
    var poweredByComment;
    var html = html.toString()
        .replace(/^\s*(<!doctype[^>]*?>\s*)?<!--([\s\S]*?)--!?>/i, function (_, doctype, message) {
            // `${doctype}<!--${message}\r\n${efrontReloadVersionAttribute}-->`
            poweredByComment = _;
            return "";
        })
        .replace(/<!--[\s\S]*?--!?>/g, "")
        .replace(/<title>(.*?)<\/title>/i, `<title>${memory.TITLE || "$1"}</title>`)
        .replace(/<script\b[\s\S]*?<\/script>\s*/ig, function (script) {
            if (/(["'`])post\1\s*,\s*(['`"])comm\/main\2/i.test(script)) {
                isZimoliDetected = true;
                return "";
            }
            if (/<script\s[^>]*?(type\s*=\s*)?(["']|)efront\-?(?:hook|main|host|script|loader)\1[^>]*?>/i.test(script)) {
                isZimoliDetected = true;
            }
            if (/\b((delete|ignore)oncompile|efrontworker)\b/i.test(script)) {
                return "";
            }
            return script;
        });

    if (isZimoliDetected)
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script compiledinfo${encoded ? '-' + encoded : ''}="${ReleaseTime} by efront ${require(path.join(__dirname, "../../package.json")).version}">\r\n<!--\r\n-function(){${code}}.call(this)\r\n-->\r\n</script>\r\n${head}`);
    if (memory.IN_WATCH_MODE) {
        let WATCH_PORT = memory.WATCH_PORT;
        let reloadVersion = +new Date();
        let efrontReloadVersionAttribute = "efront-reload-version";
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script ${efrontReloadVersionAttribute}=${reloadVersion}>
        -function(){
            "use strict";
            var load = function(url, onload, method){
                var xhr = new XMLHttpRequest;
                xhr.open(method, url);
                xhr.timeout = 0;
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4 && xhr.status === 200) onload(xhr);
                };
                xhr.send("${reloadVersion}");
            };
            var reloader = function(){
                load(location.pathname + "?time=" + +new Date(), function(xhr){
                    var version = xhr.responseText.match(/\\b${efrontReloadVersionAttribute}\\s*=\\s*(\\d+)\\b/);
                    console.info("当前版本:${reloadVersion},目标版本:" + targetVersion + "正在重新加载,..");
                    if( !version || +version[1] !== ${reloadVersion}) location.reload() | console.warn("reload..", new Date);
                    else setTimeout(reloader, 200);
                }, "get");
            };
            var targetVersion = ${reloadVersion};
            var checkUpdate = function(xhr){
                targetVersion = xhr.responseText||xhr.response;
                reloader();
            };
            load("http://localhost${WATCH_PORT ? ":" + WATCH_PORT : ""}/reload/${reloadVersion}", checkUpdate, "post");
        }();
        </script>\r\n${head}`);
        memory.WATCH_PROJECT_VERSION = reloadVersion;
    }
    if (poweredByComment) {
        html = html.replace(/^\s*(?:<!doctype[\s\S]*?>)?/i, poweredByComment);
    }
    return html;
};
function toApplication(responseTree) {
    var mainScript = responseTree.main || responseTree["main.js"] || null;
    var indexHtml = responseTree["/index.html"] || responseTree["@index.html"];
    if (!indexHtml) {
        var htmlPath = path.join(__dirname, "../../apps", "index.html");
        indexHtml = {
            time: 0,
            needed: true,
            fullpath: htmlPath,
            data: fs.readFileSync(htmlPath),
            realpath: htmlPath,
            version: fs.statSync(htmlPath).mtime,
            destpath: path.join("index.html"),
        };
        responseTree["/index.html"] = indexHtml;
    }
    if (mainScript) {
        Object.keys(responseTree).forEach(function (key) {
            if (/\.(jsp|php|html|asp)$/i.test(key)) {
                var response = responseTree[key];
                if (response && response.data) {
                    response.data = buildHtml(response.data, mainScript.data);
                }
            }
        });
    }
    delete responseTree["main"];
    delete responseTree["main.js"];
    return responseTree;
}
var rebuildData = function (responseTree) {
    var keys = Object.keys(responseTree).sort();
    var keysmap = Object.create(null);
    var renmap = Object.create(null);
    keys.forEach(function (k) {
        var o = responseTree[k];
        if (!o.data || !o.destpath || !o.realpath) {
            return;
        }
        var k0 = k.toLowerCase().replace(/\d+$/, '');
        if (k0 in keysmap) {
            keysmap[k0]++;
            k0 = k0 + keysmap[k0];
            if (k0 !== k) renmap[k] = k0;
        } else {
            keysmap[k0] = 1;
        }
    });
    Object.keys(renmap).forEach(k => {
        var o = responseTree[k];
        if (o.type !== '') {
            delete renmap[k];
            console.warn("发现可能被覆盖的路径", o.destpath);
            return;
        }

        var k1 = renmap[k];
        delete responseTree[k];
        responseTree[k1] = o;
        k1 = k1.replace(/^[\s\S]*?([^\/\\]*?)(\.[^\/\\\.]+)?$/, '$1');
        var m = /^([\s\S]*?)[^\/\\]*?(\.[^\/\\\.]+)?$/.exec(o.destpath);
        if (m[1]) {
            o.destpath = m[1] + k1 + m[2];
        }
    });

    Object.keys(responseTree).forEach(function (k) {
        var imageIndex = 0;
        var rep = function (e) {
            if (typeof e !== "string") return String(e);

            return strings.encode(e.replace(/(["`']|)data(\.\w+)\:([\w\+\/\=,;\-\.]+)\1/gi, function (_, quote, ext, data) {
                var match = /^([\w\-\.\/]+;base64)?,([\w\+\/\-\=]+)$/i.exec(data);
                if (!match) return _;
                do {
                    imageIndex++;
                    var name = k + "-" + imageIndex + ext;
                } while (name in responseTree);
                var destpath = response.destpath.replace(/\.[\w]+$/, '') + '-' + imageIndex + ext;
                responseTree[name] = { destpath, data: Buffer.from(match[2], "base64"), realpath: true, url: name };
                return quote + destpath.replace(/\\/g, '/') + quote;
            }));
        };
        var response = responseTree[k];
        if (!response.data) return;
        var data = String(response.data);

        var { argNames, args, required, dependenceNamesOffset, strs, strend } = getArgs(data);
        if (strs && strs.length > 0) {
            strs = `[${strs.map(rep)}]`;
            data = response.data = data.slice(0, dependenceNamesOffset) + (strs.length * 2).toString(36) + strs + data.slice(strend);
        }
        if (!dependenceNamesOffset || !required) return;
        args = args.map(a => {
            if (!(a in renmap)) return a;
            return renmap[a];
        });
        var argstr = args.concat(argNames, required.split(";").map(a => {
            return a.replace(/\.(\w+)$/g, '').replace(/\-(\w)/g, (_, a) => a.toUpperCase());
        }).join(";")).join(",");
        var arglen = (argstr.length << 1).toString(36);
        while (arglen.length < 3) {
            arglen = "0" + arglen;
        }
        response.data = arglen + argstr + data.slice(dependenceNamesOffset);
    });
};
module.exports = function (responseTree) {
    rebuildData(responseTree);
    report(responseTree);
    if (!responseTree["main"] && !responseTree["main.js"]) {
        console.warn("在您所编译的项目中没有发现主程序");
        return toApplication(responseTree);
    }
    var commbuilder = require("../efront/commbuilder");
    commbuilder.compress = false;
    var mainScript = responseTree.main || responseTree["main.js"];
    var mainScriptData = commbuilder(mainScript.data, "main.js", mainScript.realpath, []);
    commbuilder.compress = +compress;
    var versionTree = {};
    if (setting.is_file_target) {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(v.name) || !v.data) return;
            if (v.type === "@") return;
            if (v.name !== "main") {
                versionTree[v.name] = encrypt(v.data, encoded);
                delete responseTree[k];
            }
        });
    } else {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (!v) return;
            if (v.type === "@") return;
            if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(v.name) || !v.data) return;
            if (v.name !== "main") {
                v.data = encrypt(v.data, encoded);
                var responseVersion = crc([].map.call(v.data.toString(), e => e.charCodeAt(0))).toString(36) + (+v.data.length).toString(36);
                versionTree[v.name] = responseVersion;
            }
        });
    }

    return Promise.resolve(mainScriptData).then(function (mainScriptData) {
        if (setting.is_file_target) {
            var xTreeName = /(?:\bresponseTree\s*|\[\s*(["'])responseTree\1\s*\])\s*\:\s*(.+?)\b/m.exec(mainScriptData)[2];
            commbuilder.prepare = false;
        } else {
            var xTreeName = /(?:\bversionTree\s*|\[\s*(["'])versionTree\1\s*\])\s*\:\s*(.+?)\b/m.exec(mainScriptData)[2];
        }

        var code = "{\r\n" + Object.keys(versionTree).map(k => `["${k}"]:"${versionTree[k]}"`).join(",\r\n\t") + "\r\n}";
        var versionVariableName;
        code = mainScriptData.toString()
            .replace(/var\s+killCircle[\s\S]*?\}\s*\};/, 'var killCircle=function(){};')
            .replace(/(?:\.send|\[\s*(["'])send\1\s*\])\s*\((.*?)\)/g, (match, quote, data) => (versionVariableName = data || "", quote ? `[${quote}send${quote}]()` : ".send()"))
            .replace(/(['"])post\1\s*,(.*?)\s*\)/ig, `$1get$1,$2${versionVariableName && `+"${memory.EXTT}?"+` + versionVariableName})`)
            .replace(
                new RegExp(/\b/.source + xTreeName + /(\s*)=(\s*)\{.*?\}/.source),
                function (m, s1, s2) {
                    return xTreeName + `${s1}=${s2}${code}`;
                }
            );
        return commbuilder(code, "main.js", mainScript.realpath, []);
    }).then(function (mainScriptData) {
        mainScript.data = mainScriptData;
        return toApplication(responseTree);
    });
};<|endoftext|>


<commit_before>/*
 * Copyright 2019 Google LLC
 *
 * 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
 *
 *    https://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.
 */

const assert = require('assert');
const mocha = require('mocha');
const extension = require('./../lib/index.js');
const admin = require('firebase-admin');

// Unit test app parameters
const testCollection = "_user_presence";
const testUser = "unit-test";
const testSession = "sess0";
const docRef = admin.firestore().collection(testCollection).doc(testUser);

/**
 * testTransaction is a helper function that commits a transaction with a timestamp/payload pair.
 * The assertCallback is used to ensure the written data is correct.
 *
 * @param testName: describes the result expected (e.g. "should have an online session")
 * @param payload: payload (or delete field) to emulate online/offline/metadata operation
 * @param timestamp: timestamp of the operation
 * @param assertCallback: callback on a DocumentSnapshot, should be used to assert the state of the document
 */
const testTransaction = (testName, payload, timestamp, assertCallback) => {
  it(testName, function(done){
    extension.firestoreTransaction(docRef, payload, timestamp, testUser, testSession)
        .then(() => {
          docRef.get().then((docSnap) => {
            assertCallback(docSnap);
            done();
          }).catch((error) => {
            done(error);
          });
        })
        .catch( (error) => {
          done(error);
        });
  });
};

/**
 * Deletes the document, should be run prior to running any test
 */
const resetTestEnvironment = () => {
  it("Reset Environment: should succeed", function(done) {
      docRef.delete().then(() => {
        done();
      }).catch((error) => {
        done(error);
      })
    });
};

/**
 * Takes an array of elements, returns an array of all array permutations
 * @param baseArr: arbitrary array of elements
 * @return {*[]|Array}: array of all permutations
 */
const getPermutations = (baseArr) => {

  // Return if there are no elements left to iterate over
  if (baseArr.length <= 1) {
    return [baseArr];
  }

  // Permute over all possible
  const permutationArr = [];
  baseArr.forEach( (el, ind) => {
    // Remove the element from the baseArray
    const baseArrCopy = [...baseArr];
    baseArrCopy.splice(ind, 1);

    // Get the permutations of the remaining elements
    getPermutations(baseArrCopy).forEach((singleArr) => {
      singleArr.push(el);
      permutationArr.push(singleArr);
    });
  });

  return permutationArr;
};

/**
 * Smoke tests for basic functionality (online/offline)
 */
mocha.describe('Smoke Test', function() {
  resetTestEnvironment();
  testTransaction("Online: should have 1 active session", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal("test", docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Online: should have 0 active sessions", admin.firestore.FieldValue.delete(), 1,(docSnap) => {
    assert.equal(1, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
});

/**
 * Tests for idempotency of online/offline calls
 */
mocha.describe('Idempotency', function() {
  resetTestEnvironment();
  testTransaction("Online: should have 1 active session", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal("test", docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Online: should have 1 active session (NOOP)", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal("test", docSnap.data()["sessions"][testSession]);
  });

  testTransaction("Online: should have 0 active sessions", admin.firestore.FieldValue.delete(), 1,(docSnap) => {
    assert.equal(1, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Offline: should have 0 active sessions (NOOP)", admin.firestore.FieldValue.delete(), 1,(docSnap) => {
    assert.equal(1, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
});

/**
 * Offline should overwrite a online state if timestamps are equivalent. Online will not overwrite.
 */
mocha.describe('Equivalent timestamp tie-breaker (offline should always win)', function() {
  resetTestEnvironment();
  testTransaction("Online: should have 1 active session", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal("test", docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Offline: should have 0 active sessions (overwrite)", admin.firestore.FieldValue.delete(), 0,(docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Offline: online write should fail", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
});

/**
 * Tests the robustness of the extension when Cloud Functions does not fire in the correct order
 */
mocha.describe('Permuted Operations', function() {

  // The operations to permute are (1) online, (2) metadata update 1, (3) metadata update 2, and (4) offline
  const testArr = {
    0: true,
    1: "hello",
    2: "world!",
    3: admin.firestore.FieldValue.delete()
  };

  const permutations = getPermutations(Object.keys(testArr));

  // Iterate over all possible permutations of operations. The most recent operation should persist correctly
  // Keep track of the most recent operation per sequence.
  permutations.forEach((operationSequence, index) => {
    const groupName = `Permutation ${index + 1}/${permutations.length}: ${JSON.stringify(operationSequence)}`;
    let recentOp = -1;

    // Group by different permutations
    mocha.describe(groupName, function() {
      resetTestEnvironment();
      operationSequence.forEach((op) => {
        // Define a log that will describe what operation is occurring and what the expected result is
        let testName = `(Operation ${recentOp}) should still be operation: ${recentOp}, data: ${JSON.stringify(testArr[recentOp])}`;
        if (recentOp < parseInt(op)) {
          recentOp = parseInt(op);
          testName = `(Operation ${recentOp}) should succeed, data: ${JSON.stringify(testArr[recentOp])}`;
        }

        // Commit the transaction and compare the result from firestore
        // The expectedOP needs to be copied over because of the nature of the callback.
        let expectedOp = recentOp;
        testTransaction(testName, testArr[op], op, (docSnap) => {
          assert.equal(expectedOp, docSnap.data()["last_updated"][testSession]);
          if (testArr[expectedOp] === admin.firestore.FieldValue.delete()) {
            assert.equal(undefined, docSnap.data()["sessions"][testSession]);
          } else {
            assert.equal(testArr[expectedOp], docSnap.data()["sessions"][testSession]);
          }
        });
      });
    });
  });
});<commit_msg>more comments<commit_after>/*
 * Copyright 2019 Google LLC
 *
 * 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
 *
 *    https://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.
 */

const assert = require('assert');
const mocha = require('mocha');
const extension = require('./../lib/index.js');
const admin = require('firebase-admin');

// Unit test app parameters
const testCollection = "_user_presence";
const testUser = "unit-test";
const testSession = "sess0";
const docRef = admin.firestore().collection(testCollection).doc(testUser);

/**
 * testTransaction is a helper function that commits a transaction with a timestamp/payload pair.
 * The assertCallback is used to ensure the written data is correct.
 *
 * @param testName: describes the result expected (e.g. "should have an online session")
 * @param payload: payload (or delete field) to emulate online/offline/metadata operation
 * @param timestamp: timestamp of the operation
 * @param assertCallback: callback on a DocumentSnapshot, should be used to assert the state of the document
 */
const testTransaction = (testName, payload, timestamp, assertCallback) => {
  it(testName, function(done){
    extension.firestoreTransaction(docRef, payload, timestamp, testUser, testSession)
        .then(() => {
          docRef.get().then((docSnap) => {
            assertCallback(docSnap);
            done();
          }).catch((error) => {
            done(error);
          });
        })
        .catch( (error) => {
          done(error);
        });
  });
};

/**
 * Deletes the document, should be run prior to running any test
 */
const resetTestEnvironment = () => {
  it("Reset Environment: should succeed", function(done) {
      docRef.delete().then(() => {
        done();
      }).catch((error) => {
        done(error);
      })
    });
};

/**
 * Takes an array of elements, returns an array of all array permutations
 * @param baseArr: arbitrary array of elements
 * @return {*[]|Array}: array of all permutations
 */
const getPermutations = (baseArr) => {

  // Return if there are no elements left to iterate over
  if (baseArr.length <= 1) {
    return [baseArr];
  }

  // Permute over all possible
  const permutationArr = [];
  baseArr.forEach( (el, ind) => {
    // Remove the element from the baseArray
    const baseArrCopy = [...baseArr];
    baseArrCopy.splice(ind, 1);

    // Get the permutations of the remaining elements
    getPermutations(baseArrCopy).forEach((singleArr) => {
      singleArr.push(el);
      permutationArr.push(singleArr);
    });
  });

  return permutationArr;
};

/**
 * Smoke tests for basic functionality (online/offline)
 */
mocha.describe('Smoke Test', function() {
  resetTestEnvironment();
  testTransaction("Online: should have 1 active session", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal("test", docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Online: should have 0 active sessions", admin.firestore.FieldValue.delete(), 1,(docSnap) => {
    assert.equal(1, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
});

/**
 * Tests for idempotency of online/offline calls
 */
mocha.describe('Idempotency', function() {
  resetTestEnvironment();
  testTransaction("Online: should have 1 active session", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal("test", docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Online: should have 1 active session (NOOP)", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal("test", docSnap.data()["sessions"][testSession]);
  });

  testTransaction("Online: should have 0 active sessions", admin.firestore.FieldValue.delete(), 1,(docSnap) => {
    assert.equal(1, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Offline: should have 0 active sessions (NOOP)", admin.firestore.FieldValue.delete(), 1,(docSnap) => {
    assert.equal(1, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
});

/**
 * Offline should overwrite a online state if timestamps are equivalent. Online will not overwrite.
 */
mocha.describe('Equivalent timestamp tie-breaker (offline should always win)', function() {
  resetTestEnvironment();
  testTransaction("Online: should have 1 active session", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal("test", docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Offline: should have 0 active sessions (overwrite)", admin.firestore.FieldValue.delete(), 0,(docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
  testTransaction("Offline: online write should fail", "test", 0, (docSnap) => {
    assert.equal(0, docSnap.data()["last_updated"][testSession]);
    assert.equal(undefined, docSnap.data()["sessions"][testSession]);
  });
});

/**
 * Tests the robustness of the extension when Cloud Functions does not fire in the correct order
 */
mocha.describe('Permuted Operations', function() {

  // The operations to permute are (1) online, (2) metadata update 1, (3) metadata update 2, and (4) offline
  const testArr = {
    0: true,
    1: "hello",
    2: "world!",
    3: admin.firestore.FieldValue.delete()
  };

  // Get array of all permutations of the 4 operations
  const permutations = getPermutations(Object.keys(testArr));

  // Iterate over all possible permutations of operations. The most recent operation should persist correctly
  // Keep track of the most recent operation per sequence.
  permutations.forEach((operationSequence, index) => {
    const groupName = `Permutation ${index + 1}/${permutations.length}: ${JSON.stringify(operationSequence)}`;
    let recentOp = -1;

    // Group by different permutations
    mocha.describe(groupName, function() {
      resetTestEnvironment();
      operationSequence.forEach((op) => {
        // Define a log that will describe what operation is occurring and what the expected result is
        let testName = `(Operation ${recentOp}) should still be operation: ${recentOp}, data: ${JSON.stringify(testArr[recentOp])}`;
        if (recentOp < parseInt(op)) {
          recentOp = parseInt(op);
          testName = `(Operation ${recentOp}) should succeed, data: ${JSON.stringify(testArr[recentOp])}`;
        }

        // Commit the transaction and compare the result from firestore
        // The expectedOP needs to be copied over because of the nature of the callback.
        let expectedOp = recentOp;
        testTransaction(testName, testArr[op], op, (docSnap) => {
          assert.equal(expectedOp, docSnap.data()["last_updated"][testSession]);
          if (testArr[expectedOp] === admin.firestore.FieldValue.delete()) {
            assert.equal(undefined, docSnap.data()["sessions"][testSession]);
          } else {
            assert.equal(testArr[expectedOp], docSnap.data()["sessions"][testSession]);
          }
        });
      });
    });
  });
});<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2021 The Stdlib Authors.
*
* 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.
*/

'use strict';

// MODULES //

var basename = require( 'path' ).basename;
var dirname = require( 'path' ).dirname;
var join = require( 'path' ).join;
var endsWith = require( '@stdlib/string/ends-with' );
var isString = require( '@stdlib/assert/is-string' ).isPrimitive;
var trim = require( '@stdlib/string/trim' );
var readDir = require( '@stdlib/fs/read-dir' ).sync;
var contains = require( '@stdlib/assert/contains' );

// VARIABLES //

var rule;
var ORDER_COMMENT = 'When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.';
var RE_CUSTOM_EXCLUDES = /The following modules are intentionally not exported: ?([^\n]+)\n/;
var EXCLUDE_LIST = [
	'node_modules',
	'package.json',
	'benchmark',
	'data',
	'docs',
	'etc',
	'examples',
	'lib',
	'include',
	'scripts',
	'src',
	'test',
	'README.md'
];

// FUNCTIONS //

/**
* Rule for validating that a namespace `index.js` exports all packages in the respective namespace directory.
*
* @param {Object} context - ESLint context
* @returns {Object} validators
*/
function main( context ) {
	var requires;
	var packages;
	var filename;
	var excludes;
	var source;
	var match;
	var arr;
	var dir;
	var i;

	source = context.getSourceCode();
	if ( !contains( source.text, ORDER_COMMENT ) ) {
		return {};
	}
	match = RE_CUSTOM_EXCLUDES.exec( source.text );
	if ( match ) {
		excludes = EXCLUDE_LIST.slice();
		arr = match[ 1 ].split( ',' );
		for ( i = 0; i < arr.length; i++ ) {
			excludes.push( trim( arr[ i ] ) );
		}
	} else {
		excludes = EXCLUDE_LIST;
	}
	filename = context.getFilename();
	if ( !filename || !endsWith( filename, 'index.js' ) ) {
		return {};
	}
	dir = join( dirname( filename ), '..' );
	packages = packageDirectories( readDir( dir ) );
	requires = [];

	/**
	* Checks for existence of require paths in the current program and registers them.
	*
	* @private
	* @param {ASTNode} node - node to examine
	*/
	function validate( node ) {
		var requirePath;
		var pkg;
		if ( node.callee.name === 'require' ) {
			requirePath = node.arguments[ 0 ].value;
			if ( isString( requirePath ) ) {
				pkg = basename( requirePath );
				if ( !contains( requires, pkg ) ) {
					requires.push( pkg );
				}
			}
		}
	}

	/**
	* Callback invoked upon program exit.
	*
	* @private
	* @param {Object} node - AST node
	*/
	function finish( node ) {
		var errs;
		var i;

		errs = [];
		for ( i = 0; i < packages.length; i++ ) {
			if ( !contains( requires, packages[ i ] ) ) {
				errs.push( packages[ i ] );
			}
		}
		if ( errs.length ) {
			report( errs, node );
		}
		requires.length = 0; // reset the require cache
	}

	/**
	* Reports the error message.
	*
	* @private
	* @param {StringArray} errs - array of packages not exported from `index.js`
	* @param {ASTNode} node - AST node
	*/
	function report( errs, node ) {
		var pkg;
		var msg;
		var i;
		for ( i = 0; i < errs.length; i++ ) {
			pkg = errs[ i ];
			msg = '`' + pkg + '` should be exported from namespace `index.js`';
			context.report({
				'node': node,
				'message': msg
			});
		}
	}

	/**
	* Filters out any non-package directories from a list of directory contents.
	*
	* @private
	* @param {Array} contents - directory contents
	* @returns {Array} namespace package directories
	*/
	function packageDirectories( contents ) {
		var out;
		var i;

		out = [];
		for ( i = 0; i < contents.length; i++ ) {
			if ( !contains( excludes, contents[ i ] ) ) {
				out.push( contents[ i ] );
			}
		}
		return out;
	}

	return {
		'CallExpression': validate,
		'Program:exit': finish
	};
}

// MAIN //

rule = {
	'meta': {
		'docs': {
			'description': 'enforce that a namespace `index.js` exports all packages in the respective namespace directory'
		},
		'schema': []
	},
	'create': main
};

// EXPORTS //

module.exports = rule;
<commit_msg>Filter out files from list of contents<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2021 The Stdlib Authors.
*
* 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.
*/

'use strict';

// MODULES //

var basename = require( 'path' ).basename;
var dirname = require( 'path' ).dirname;
var join = require( 'path' ).join;
var statSync = require( 'fs' ).statSync; // eslint-disable-line no-sync
var endsWith = require( '@stdlib/string/ends-with' );
var isString = require( '@stdlib/assert/is-string' ).isPrimitive;
var trim = require( '@stdlib/string/trim' );
var readDir = require( '@stdlib/fs/read-dir' ).sync;
var contains = require( '@stdlib/assert/contains' );

// VARIABLES //

var rule;
var ORDER_COMMENT = 'When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.';
var RE_CUSTOM_EXCLUDES = /The following modules are intentionally not exported: ?([^\n]+)\n/;
var EXCLUDE_LIST = [
	'node_modules',
	'benchmark',
	'data',
	'docs',
	'etc',
	'examples',
	'lib',
	'include',
	'scripts',
	'src',
	'test'
];

// FUNCTIONS //

/**
* Checks whether a directory content is a file.
*
* @private
* @param {string} content - directory content path
* @returns {boolean} boolean indicating whether the directory content is a file
*/
function isFile( content ) {
	var stat = statSync( content );
	return stat.isFile();
}

/**
* Rule for validating that a namespace `index.js` exports all packages in the respective namespace directory.
*
* @param {Object} context - ESLint context
* @returns {Object} validators
*/
function main( context ) {
	var requires;
	var packages;
	var filename;
	var excludes;
	var source;
	var match;
	var arr;
	var dir;
	var i;

	source = context.getSourceCode();
	if ( !contains( source.text, ORDER_COMMENT ) ) {
		return {};
	}
	match = RE_CUSTOM_EXCLUDES.exec( source.text );
	if ( match ) {
		excludes = EXCLUDE_LIST.slice();
		arr = match[ 1 ].split( ',' );
		for ( i = 0; i < arr.length; i++ ) {
			excludes.push( trim( arr[ i ] ) );
		}
	} else {
		excludes = EXCLUDE_LIST;
	}
	filename = context.getFilename();
	if ( !filename || !endsWith( filename, 'index.js' ) ) {
		return {};
	}
	dir = join( dirname( filename ), '..' );
	packages = packageDirectories( readDir( dir ) );
	requires = [];

	/**
	* Checks for existence of require paths in the current program and registers them.
	*
	* @private
	* @param {ASTNode} node - node to examine
	*/
	function validate( node ) {
		var requirePath;
		var pkg;
		if ( node.callee.name === 'require' ) {
			requirePath = node.arguments[ 0 ].value;
			if ( isString( requirePath ) ) {
				pkg = basename( requirePath );
				if ( !contains( requires, pkg ) ) {
					requires.push( pkg );
				}
			}
		}
	}

	/**
	* Callback invoked upon program exit.
	*
	* @private
	* @param {Object} node - AST node
	*/
	function finish( node ) {
		var errs;
		var i;

		errs = [];
		for ( i = 0; i < packages.length; i++ ) {
			if ( !contains( requires, packages[ i ] ) ) {
				errs.push( packages[ i ] );
			}
		}
		if ( errs.length ) {
			report( errs, node );
		}
		requires.length = 0; // reset the require cache
	}

	/**
	* Reports the error message.
	*
	* @private
	* @param {StringArray} errs - array of packages not exported from `index.js`
	* @param {ASTNode} node - AST node
	*/
	function report( errs, node ) {
		var pkg;
		var msg;
		var i;
		for ( i = 0; i < errs.length; i++ ) {
			pkg = errs[ i ];
			msg = '`' + pkg + '` should be exported from namespace `index.js`';
			context.report({
				'node': node,
				'message': msg
			});
		}
	}

	/**
	* Filters out any non-package directories from a list of directory contents.
	*
	* @private
	* @param {Array} contents - directory contents
	* @returns {Array} namespace package directories
	*/
	function packageDirectories( contents ) {
		var content;
		var out;
		var i;

		out = [];
		for ( i = 0; i < contents.length; i++ ) {
			content = contents[ i ];
			if (
				!isFile( join( dir, content ) ) &&
				!contains( excludes, content )
			) {
				out.push( content );
			}
		}
		return out;
	}

	return {
		'CallExpression': validate,
		'Program:exit': finish
	};
}

// MAIN //

rule = {
	'meta': {
		'docs': {
			'description': 'enforce that a namespace `index.js` exports all packages in the respective namespace directory'
		},
		'schema': []
	},
	'create': main
};

// EXPORTS //

module.exports = rule;
<|endoftext|>


<commit_before>Tinytest.add('basic - works', function (test) {
  Test = new Mongo.Collection('test' + test.id);
  Test.insert({ test: true });
  var find = Mongo.Collection.get('test' + test.id).find({ test: true });
  test.equal(find.count(), 1);
});
<commit_msg>added another test<commit_after>Tinytest.add('basic - works Mongo.Collection', function (test) {
  Test = new Mongo.Collection('test' + test.id);
  Test.insert({ test: true });
  var find = Mongo.Collection.get('test' + test.id).find({ test: true });
  test.equal(find.count(), 1);
});

Tinytest.add('basic - works Meteor.Collection', function (test) {
  Test = new Meteor.Collection('test' + test.id);
  Test.insert({ test: true });
  var find = Meteor.Collection.get('test' + test.id).find({ test: true });
  test.equal(find.count(), 1);
});<|endoftext|>


<commit_before>const tap = require("tap");

const sumCheck = require("../../src/badges/sum_check");
const sumStats = require("../fixtures/badges/sum_stats.json");

const userWithNoBadges = sumStats.user_with_no_badges;
const userWithTierOneBadges = sumStats.user_with_tier1_badges;
const userWithTierTwoBadges = sumStats.user_with_tier2_badges;
const userWithTierThreeBadges = sumStats.user_with_tier3_badges;

// note: road counts and road mod counts were removed
tap.test("badge logic - sum metrics", t => {
  t.deepEqual(
    sumCheck(userWithNoBadges),
    {},
    "a user with all <level 1 metrics should return an empty object"
  );

  t.deepEqual(
    sumCheck(userWithTierOneBadges),
    {
      // roads: { category: 1, level: 1 },
      // roadMods: { category: 2, level: 1 },
      pois: { category: 3, level: 1 },
      buildings: { category: 4, level: 1 },
      gpsTraces: { category: 5, level: 1 },
      roadKms: { category: 6, level: 1 },
      roadKmMods: { category: 7, level: 1 },
      waterways: { category: 8, level: 1 },
      countries: { category: 9, level: 1 },
      tasks: { category: 10, level: 1 },
      // taskEdits: { category: 11, level: 1 },
      josm: { category: 12, level: 1 },
      hashtags: { category: 13, level: 1 }
    },
    "a user with all level 1 metrics should return object of badge keys with all 1s"
  );

  t.deepEqual(
    sumCheck(userWithTierTwoBadges),
    {
      // roads: { category: 1, level: 2 },
      // roadMods: { category: 2, level: 2 },
      pois: { category: 3, level: 2 },
      buildings: { category: 4, level: 2 },
      gpsTraces: { category: 5, level: 2 },
      roadKms: { category: 6, level: 2 },
      roadKmMods: { category: 7, level: 2 },
      waterways: { category: 8, level: 2 },
      countries: { category: 9, level: 2 },
      tasks: { category: 10, level: 2 },
      // taskEdits: { category: 11, level: 2 },
      josm: { category: 12, level: 2 },
      hashtags: { category: 13, level: 2 }
    },
    "a user with all level 2 metrics should return object of badge keys with all 2s"
  );

  t.deepEqual(
    sumCheck(userWithTierThreeBadges),
    {
      // roads: { category: 1, level: 3 },
      // roadMods: { category: 2, level: 3 },
      pois: { category: 3, level: 3 },
      buildings: { category: 4, level: 3 },
      gpsTraces: { category: 5, level: 3 },
      roadKms: { category: 6, level: 3 },
      roadKmMods: { category: 7, level: 3 },
      waterways: { category: 8, level: 3 },
      countries: { category: 9, level: 3 },
      tasks: { category: 10, level: 3 },
      // taskEdits: { category: 11, level: 3 },
      josm: { category: 12, level: 3 },
      hashtags: { category: 13, level: 3 }
    },
    "a user with all level 3 metrics should return object of badge keys with all 3s"
  );

  t.end();
});
<commit_msg>Remove gpsTraces traces from tests<commit_after>const tap = require("tap");

const sumCheck = require("../../src/badges/sum_check");
const sumStats = require("../fixtures/badges/sum_stats.json");

const userWithNoBadges = sumStats.user_with_no_badges;
const userWithTierOneBadges = sumStats.user_with_tier1_badges;
const userWithTierTwoBadges = sumStats.user_with_tier2_badges;
const userWithTierThreeBadges = sumStats.user_with_tier3_badges;

// note: road counts and road mod counts were removed
tap.test("badge logic - sum metrics", t => {
  t.deepEqual(
    sumCheck(userWithNoBadges),
    {},
    "a user with all <level 1 metrics should return an empty object"
  );

  t.deepEqual(
    sumCheck(userWithTierOneBadges),
    {
      // roads: { category: 1, level: 1 },
      // roadMods: { category: 2, level: 1 },
      pois: { category: 3, level: 1 },
      buildings: { category: 4, level: 1 },
      roadKms: { category: 6, level: 1 },
      roadKmMods: { category: 7, level: 1 },
      waterways: { category: 8, level: 1 },
      countries: { category: 9, level: 1 },
      tasks: { category: 10, level: 1 },
      // taskEdits: { category: 11, level: 1 },
      josm: { category: 12, level: 1 },
      hashtags: { category: 13, level: 1 }
    },
    "a user with all level 1 metrics should return object of badge keys with all 1s"
  );

  t.deepEqual(
    sumCheck(userWithTierTwoBadges),
    {
      // roads: { category: 1, level: 2 },
      // roadMods: { category: 2, level: 2 },
      pois: { category: 3, level: 2 },
      buildings: { category: 4, level: 2 },
      roadKms: { category: 6, level: 2 },
      roadKmMods: { category: 7, level: 2 },
      waterways: { category: 8, level: 2 },
      countries: { category: 9, level: 2 },
      tasks: { category: 10, level: 2 },
      // taskEdits: { category: 11, level: 2 },
      josm: { category: 12, level: 2 },
      hashtags: { category: 13, level: 2 }
    },
    "a user with all level 2 metrics should return object of badge keys with all 2s"
  );

  t.deepEqual(
    sumCheck(userWithTierThreeBadges),
    {
      // roads: { category: 1, level: 3 },
      // roadMods: { category: 2, level: 3 },
      pois: { category: 3, level: 3 },
      buildings: { category: 4, level: 3 },
      roadKms: { category: 6, level: 3 },
      roadKmMods: { category: 7, level: 3 },
      waterways: { category: 8, level: 3 },
      countries: { category: 9, level: 3 },
      tasks: { category: 10, level: 3 },
      // taskEdits: { category: 11, level: 3 },
      josm: { category: 12, level: 3 },
      hashtags: { category: 13, level: 3 }
    },
    "a user with all level 3 metrics should return object of badge keys with all 3s"
  );

  t.end();
});
<|endoftext|>


<commit_before>/**
 * module  loader/assets
 */
;(function(K, NULL){

var

DOC = K.__HOST.document;

if(!DOC){
    return;
}

var

HEAD = DOC.getElementsByTagName('head')[0],

REGEX_FILE_TYPE = /\.(\w+)$/i,

/**
 * method to load a resource file
 * @param {string} uri uri of resource
 * @param {function()=} callback callback function
 * @param {string=} type the explicitily assigned type of the resource,
 	can be 'js', 'css', or 'img'. default to 'img'. (optional)
 */
loadSrc = function(uri, callback, type){
	var extension = type || uri.match(REGEX_FILE_TYPE)[1];

	return extension ?
		( loadSrc[ extension.toLowerCase() ] || loadSrc.img )(uri, callback)
		: NULL;
};

/**
 * static resource loader
 * meta functions for assets
 * --------------------------------------------------------------------------------------------------- */

/**
 * @param {string} url
 * @param {function()=} callback
 */
loadSrc.css = function(uri, callback){
	var node = DOC.createElement('link');

	node.href = uri;
	node.rel = 'stylesheet';

	callback && assetOnload.css(node, callback);

	// insert new CSS in the end of `<head>` to maintain priority
	HEAD.appendChild(node);

	return node;
};

/**
 * @param {string} url
 * @param {function()=} callback
 */
loadSrc.js = function(uri, callback){
	var node = DOC.createElement('script');

	node.src = uri;
	node.async = true;

	callback && assetOnload.js(node, callback);

	loadSrc.__pending = uri;
	HEAD.insertBefore(node, HEAD.firstChild);
	loadSrc.__pending = NULL;

	return node;
};

/**
 * @param {string} url
 * @param {function()=} callback
 */
loadSrc.img = function(uri, callback){
	var node = DOC.createElement('img'),
		delay = setTimeout;

	function complete(name){
		node.onload = node.onabort = node.onerror = complete = NULL;

		// on IE, `onload` event may be fired during the setting{1} of the src of image node
		// so setTimeout to make sure the callback function will be executed after the current loadSrc.img stack.
		setTimeout(function(){
			callback.call(node, {type: name});
			node = NULL;
		}, 0);
	};

	callback && ['load', 'abort', 'error'].forEach(function(name){
		node['on' + name] = function(){
			complete(name);
		};
	});

	// {1}
	node.src = uri;

	callback && node.complete && complete && complete('load');

	return node;
};

var

// @this {element}
assetOnload = {
	js: ( DOC.createElement('script').readyState ?

		/**
		 * @param {DOMElement} node
		 * @param {!function()} callback asset.js makes sure callback is not null
		 */
		function(node, callback){
	    	node.onreadystatechange = function(){
	        	var rs = node.readyState;
	        	if (rs === 'loaded' || rs === 'complete'){
	            	node.onreadystatechange = NULL;

	            	callback.call(this);
	        	}
	    	};
		} :

		function(node, callback){
			node.addEventListener('load', callback, false);
		}
	)
},

// assert.css from jQuery
cssOnload = ( DOC.createElement('css').attachEvent ?
	function(node, callback){
		node.attachEvent('onload', callback);
	} :

	function(node, callback){
		var is_loaded = false,
			sheet = node['sheet'];

		if(sheet){
			if(K.UA.webkit){
				is_loaded = true;

			}else{
				try {
					if(sheet.cssRules) {
						is_loaded = true;
					}
				} catch (ex) {
					if (ex.name === 'NS_ERROR_DOM_SECURITY_ERR') {
						is_loaded = true;
					}
				}
			}
		}

	    if (is_loaded) {
	    	setTimeout(function(){
	    		callback.call(node);
	    	}, 0);
	    }else {
			setTimeout(function(){
				cssOnload(node, callback);
			}, 10);
	    }
	}
); // end var

assetOnload.css = cssOnload;

/**
 * load a static source
 * NR.load(src, cb);
 * NR.load.js(src, cb);
 * NR.load.css(src, cb);
 * NR.load.img(src, cb);
 */
K['load'] = loadSrc;

})(NR, null);

/**
 change log:

 2012-06-29  Kael:
 - fix a bug of NR.load.img on IE,

 */
<commit_msg>loader/assets: adjust code indent as 4 whitespaces; remove detection for document<commit_after>/**
 * module  loader/assets
 */
;(function(K, NULL){

var

DOC = K.__HOST.document;

// assets.js will always be executed on browser environment, otherwise, we use another package configuration
// if(!DOC){
//    return;
// }

var

HEAD = DOC.getElementsByTagName('head')[0],

REGEX_FILE_TYPE = /\.(\w+)$/i,

/**
 * method to load a resource file
 * @param {string} uri uri of resource
 * @param {function()=} callback callback function
 * @param {string=} type the explicitily assigned type of the resource,
     can be 'js', 'css', or 'img'. default to 'img'. (optional)
 */
loadSrc = function(uri, callback, type){
    var extension = type || uri.match(REGEX_FILE_TYPE)[1];

    return extension ?
        ( loadSrc[ extension.toLowerCase() ] || loadSrc.img )(uri, callback)
        : NULL;
};

/**
 * static resource loader
 * meta functions for assets
 * --------------------------------------------------------------------------------------------------- */

/**
 * @param {string} url
 * @param {function()=} callback
 */
loadSrc.css = function(uri, callback){
    var node = DOC.createElement('link');

    node.href = uri;
    node.rel = 'stylesheet';

    callback && assetOnload.css(node, callback);

    // insert new CSS in the end of `<head>` to maintain priority
    HEAD.appendChild(node);

    return node;
};

/**
 * @param {string} url
 * @param {function()=} callback
 */
loadSrc.js = function(uri, callback){
    var node = DOC.createElement('script');

    node.src = uri;
    node.async = true;

    callback && assetOnload.js(node, callback);

    loadSrc.__pending = uri;
    HEAD.insertBefore(node, HEAD.firstChild);
    loadSrc.__pending = NULL;

    return node;
};

/**
 * @param {string} url
 * @param {function()=} callback
 */
loadSrc.img = function(uri, callback){
    var node = DOC.createElement('img'),
        delay = setTimeout;

    function complete(name){
        node.onload = node.onabort = node.onerror = complete = NULL;

        // on IE, `onload` event may be fired during the setting{1} of the src of image node
        // so setTimeout to make sure the callback function will be executed after the current loadSrc.img stack.
        setTimeout(function(){
            callback.call(node, {type: name});
            node = NULL;
        }, 0);
    };

    callback && ['load', 'abort', 'error'].forEach(function(name){
        node['on' + name] = function(){
            complete(name);
        };
    });

    // {1}
    node.src = uri;

    callback && node.complete && complete && complete('load');

    return node;
};

var

// @this {element}
assetOnload = {
    js: ( DOC.createElement('script').readyState ?

        /**
         * @param {DOMElement} node
         * @param {!function()} callback asset.js makes sure callback is not null
         */
        function(node, callback){
            node.onreadystatechange = function(){
                var rs = node.readyState;
                if (rs === 'loaded' || rs === 'complete'){
                    node.onreadystatechange = NULL;

                    callback.call(this);
                }
            };
        } :

        function(node, callback){
            node.addEventListener('load', callback, false);
        }
    )
},

// assert.css from jQuery
cssOnload = ( DOC.createElement('css').attachEvent ?
    function(node, callback){
        node.attachEvent('onload', callback);
    } :

    function(node, callback){
        var is_loaded = false,
            sheet = node['sheet'];

        if(sheet){
            if(K.UA.webkit){
                is_loaded = true;

            }else{
                try {
                    if(sheet.cssRules) {
                        is_loaded = true;
                    }
                } catch (ex) {
                    if (ex.name === 'NS_ERROR_DOM_SECURITY_ERR') {
                        is_loaded = true;
                    }
                }
            }
        }

        if (is_loaded) {
            setTimeout(function(){
                callback.call(node);
            }, 0);
        }else {
            setTimeout(function(){
                cssOnload(node, callback);
            }, 10);
        }
    }
); // end var

assetOnload.css = cssOnload;

/**
 * load a static source
 * NR.load(src, cb);
 * NR.load.js(src, cb);
 * NR.load.css(src, cb);
 * NR.load.img(src, cb);
 */
K['load'] = loadSrc;

})(NR, null);

/**
 change log:

 2012-06-29  Kael:
 - fix a bug of NR.load.img on IE,

 */
<|endoftext|>