<commit_before>function getFunctionName (fn) {
  return fn.name || fn.toString().match(/function (.*?)\s*\(/)[1]
}

function getFunctionTypeName (fn) {
  return fn.toJSON ? fn.toJSON() : getFunctionName(fn)
}

function getTypeName (value) {
  if (nativeTypes.Null(value)) return ''

  return getFunctionName(value.constructor)
}

function tfErrorString (typeName, value) {
  var valueType = getTypeName(value)

  return 'Expected ' + typeName + ', got ' + (valueType && valueType + ' ') + JSON.stringify(value)
}

function tfPropertyErrorString (type, name, value) {
  var typeName

  if (nativeTypes.Function(type)) {
    typeName = getFunctionTypeName(type)

  } else if (nativeTypes.Object(type)) {
    typeName = JSON.stringify(type)

  } else if (nativeTypes.String(type)) {
    typeName = type
  }

  return tfErrorString('property \"' + name + '\" of type ' + typeName, value)
}

var nativeTypes = {
  Array (value) { return value !== null && value !== undefined && value.constructor === Array },
  Boolean (value) { return typeof value === 'boolean' },
  Buffer (value) { return Buffer.isBuffer(value) },
  Function (value) { return typeof value === 'function' },
  Null (value) { return value === undefined || value === null },
  Number (value) { return typeof value === 'number' },
  Object (value) { return typeof value === 'object' },
  String (value) { return typeof value === 'string' },
  '' () { return true }
}

var otherTypes = {
  arrayOf (type) {
    function arrayOf (value, strict) {
      if (!nativeTypes.Array(value)) return false

      return value.every(x => {
        try {
          return typeforce(type, x, strict)

        } catch (e) {
          return false
        }
      })
    }
    arrayOf.toJSON = function () { return '[' + JSON.stringify(type) + ']' }

    return arrayOf
  },

  maybe (type) {
    function maybe (value, strict) {
      if (nativeTypes.Null(value, strict)) return true

      return typeforce(type, value, strict)
    }
    maybe.toJSON = function () { return '?' + (type.toJSON && type.toJSON() || JSON.stringify(type)) }

    return maybe
  },

  object (type) {
    function object (value, strict) {
      typeforce(nativeTypes.Object, value, strict)

      for (var propertyName in type) {
        var propertyType = type[propertyName]
        var propertyValue = value[propertyName]

        try {
          typeforce(propertyType, propertyValue, strict)

        } catch (e) {
          throw new TypeError(tfPropertyErrorString(propertyType, propertyName, propertyValue))
        }
      }

      if (strict) {
        for (propertyName in value) {
          if (type[propertyName]) continue

          throw new TypeError('Unexpected property "' + propertyName + '"')
        }
      }

      return true
    }
    object.toJSON = function () { return JSON.stringify(type) }

    return object
  },

  oneOf (types) {
    return function oneOf (value, strict) {
      return types.some(type => {
        try {
          typeforce(type, value, strict)

          return true
        } catch (e) {
          return false
        }
      })
    }
  },

  compile (type) {
    if (nativeTypes.String(type)) {
      if (type[0] === '?') {
        type = type.slice(1)

        return otherTypes.maybe(otherTypes.compile(type))
      }

      var nativeType = nativeTypes[type]
      if (nativeType) return nativeType

    } else if (nativeTypes.Object(type)) {
      if (nativeTypes.Array(type)) {
        return otherTypes.arrayOf(otherTypes.compile(type[0]))
      }

      var compiled = {}

      for (var propertyName in type) {
        compiled[propertyName] = otherTypes.compile(type[propertyName])
      }

      return compiled
    }

    return type
  },

  value (expected) {
    return function value (actual) {
      return actual === expected
    }
  }
}

function typeforce (type, value, strict) {
  switch (typeof type) {
    case 'function':
      if (type(value, strict)) return true

      throw new TypeError(tfErrorString(getFunctionTypeName(type), value))

    case 'object':
      if (nativeTypes.Array(type)) return typeforce(otherTypes.arrayOf(type[0]), value, strict)

      return typeforce(otherTypes.object(type), value, strict)

    case 'string':
      if (type[0] === '?') {
        type = type.slice(1)

        return typeforce(otherTypes.maybe(type), value, strict)
      }

      var tfType = nativeTypes[type]
      if (tfType) return typeforce(tfType, value, strict)
      if (type === getTypeName(value)) return true

      break
  }

  // catch all
  throw new TypeError(tfErrorString(type, value))
}

// assign all types to typeforce function
var typeName
Object.keys(nativeTypes).forEach(typeName => {
  var nativeType = nativeTypes[typeName]
  nativeType.toJSON = () => typeName

  typeforce[typeName] = nativeType
})

for (typeName in otherTypes) {
  typeforce[typeName] = otherTypes[typeName]
}

module.exports = typeforce
<commit_msg>extract exceptions out of the loops<commit_after>function getFunctionName (fn) {
  return fn.name || fn.toString().match(/function (.*?)\s*\(/)[1]
}

function getFunctionTypeName (fn) {
  return fn.toJSON ? fn.toJSON() : getFunctionName(fn)
}

function getTypeName (value) {
  if (nativeTypes.Null(value)) return ''

  return getFunctionName(value.constructor)
}

function tfErrorString (typeName, value) {
  var valueType = getTypeName(value)

  return 'Expected ' + typeName + ', got ' + (valueType && valueType + ' ') + JSON.stringify(value)
}

function tfPropertyErrorString (type, name, value) {
  var typeName

  if (nativeTypes.Function(type)) {
    typeName = getFunctionTypeName(type)

  } else if (nativeTypes.Object(type)) {
    typeName = JSON.stringify(type)

  } else if (nativeTypes.String(type)) {
    typeName = type
  }

  return tfErrorString('property \"' + name + '\" of type ' + typeName, value)
}

var nativeTypes = {
  Array (value) { return value !== null && value !== undefined && value.constructor === Array },
  Boolean (value) { return typeof value === 'boolean' },
  Buffer (value) { return Buffer.isBuffer(value) },
  Function (value) { return typeof value === 'function' },
  Null (value) { return value === undefined || value === null },
  Number (value) { return typeof value === 'number' },
  Object (value) { return typeof value === 'object' },
  String (value) { return typeof value === 'string' },
  '' () { return true }
}

var otherTypes = {
  arrayOf (type) {
    function arrayOf (value, strict) {
      try {
        return nativeTypes.Array(value) && value.every(x => typeforce(type, x, strict))

      } catch (e) {
        return false
      }
    }
    arrayOf.toJSON = function () { return '[' + JSON.stringify(type) + ']' }

    return arrayOf
  },

  maybe (type) {
    function maybe (value, strict) {
      return nativeTypes.Null(value, strict) || typeforce(type, value, strict)
    }
    maybe.toJSON = function () { return '?' + (type.toJSON && type.toJSON() || JSON.stringify(type)) }

    return maybe
  },

  object (type) {
    function object (value, strict) {
      typeforce(nativeTypes.Object, value, strict)

      var propertyName, propertyType, propertyValue

      try {
        for (propertyName in type) {
          propertyType = type[propertyName]
          propertyValue = value[propertyName]

          typeforce(propertyType, propertyValue, strict)
        }

      } catch (e) {
        throw new TypeError(tfPropertyErrorString(propertyType, propertyName, propertyValue))
      }

      if (strict) {
        for (propertyName in value) {
          if (type[propertyName]) continue

          throw new TypeError('Unexpected property "' + propertyName + '"')
        }
      }

      return true
    }
    object.toJSON = function () { return JSON.stringify(type) }

    return object
  },

  oneOf (types) {
    return function oneOf (value, strict) {
      return types.some(type => {
        try {
          typeforce(type, value, strict)

          return true
        } catch (e) {
          return false
        }
      })
    }
  },

  compile (type) {
    if (nativeTypes.String(type)) {
      if (type[0] === '?') {
        type = type.slice(1)

        return otherTypes.maybe(otherTypes.compile(type))
      }

      var nativeType = nativeTypes[type]
      if (nativeType) return nativeType

    } else if (nativeTypes.Object(type)) {
      if (nativeTypes.Array(type)) {
        return otherTypes.arrayOf(otherTypes.compile(type[0]))
      }

      var compiled = {}

      for (var propertyName in type) {
        compiled[propertyName] = otherTypes.compile(type[propertyName])
      }

      return compiled
    }

    return type
  },

  value (expected) {
    return function value (actual) {
      return actual === expected
    }
  }
}

function typeforce (type, value, strict) {
  switch (typeof type) {
    case 'function':
      if (type(value, strict)) return true

      throw new TypeError(tfErrorString(getFunctionTypeName(type), value))

    case 'object':
      if (nativeTypes.Array(type)) return typeforce(otherTypes.arrayOf(type[0]), value, strict)

      return typeforce(otherTypes.object(type), value, strict)

    case 'string':
      if (type[0] === '?') {
        type = type.slice(1)

        return typeforce(otherTypes.maybe(type), value, strict)
      }

      var tfType = nativeTypes[type]
      if (tfType) return typeforce(tfType, value, strict)
      if (type === getTypeName(value)) return true

      break
  }

  // catch all
  throw new TypeError(tfErrorString(type, value))
}

// assign all types to typeforce function
var typeName
Object.keys(nativeTypes).forEach(typeName => {
  var nativeType = nativeTypes[typeName]
  nativeType.toJSON = () => typeName

  typeforce[typeName] = nativeType
})

for (typeName in otherTypes) {
  typeforce[typeName] = otherTypes[typeName]
}

module.exports = typeforce
<|endoftext|>


<commit_before>var Logger = require('./jaws-logger.js');

function logger(id, credentials) {
        var logTransport = process.env.JAWS_LOG_TRANSPORT || 'papertrail',
            stage = process.env.JAWS_STAGE || '';

        stage = stage && ' ['+stage+'] ';

        credentials = credentials || {};
        credentials.level = credentials.level || process.env.JAWS_LOG_LEVEL;
        credentials.hostname = credentials.hostname || process.env.JAWS_LOG_PAPERTRAIL_HOSTNAME + stage;
        credentials.host = credentials.host || process.env.JAWS_LOG_PAPERTRAIL_HOST;
        credentials.port = credentials.port || process.env.JAWS_LOG_PAPERTRAIL_PORT;
        credentials.name = credentials.name || process.env.JAWS_LOG_LOGGLY_NAME + stage;
        credentials.token = credentials.token || process.env.JAWS_LOG_LOGGLY_TOKEN;
        credentials.subdomain = credentials.subdomain || process.env.JAWS_LOG_LOGGLY_SUBDOMAIN;

        console.log(credentials);
        return Logger.CreateLogger(id, logTransport, credentials)
}

module.exports = function(id, credentials){
        return logger(id, credentials);
}

<commit_msg>default to console when no config present<commit_after>var Logger = require('./jaws-logger.js');

function logger(id, credentials) {
        var logTransport = process.env.JAWS_LOG_TRANSPORT || 'console',
            stage = process.env.JAWS_STAGE || '';

        stage = stage && ' ['+stage+'] ';

        credentials = credentials || {};
        credentials.level = credentials.level || process.env.JAWS_LOG_LEVEL;
        credentials.hostname = credentials.hostname || process.env.JAWS_LOG_PAPERTRAIL_HOSTNAME + stage;
        credentials.host = credentials.host || process.env.JAWS_LOG_PAPERTRAIL_HOST;
        credentials.port = credentials.port || process.env.JAWS_LOG_PAPERTRAIL_PORT;
        credentials.name = credentials.name || process.env.JAWS_LOG_LOGGLY_NAME + stage;
        credentials.token = credentials.token || process.env.JAWS_LOG_LOGGLY_TOKEN;
        credentials.subdomain = credentials.subdomain || process.env.JAWS_LOG_LOGGLY_SUBDOMAIN;

        console.log(credentials);
        return Logger.CreateLogger(id, logTransport, credentials)
}

module.exports = function(id, credentials){
        return logger(id, credentials);
}

<|endoftext|>


<commit_before>var type = require("type"),
    utils = require("utils");

var translationCache = {};

module.exports = i18n;

function i18n(key, locale) {
    var translations;

    if (!type.isString(key)) {
        throw new TypeError("i18n(key[, locale]) key must be a String");
    }

    translations = i18n.get(locale);

    if (translations === null) {
        throw new Error("i18n(key[, locale]) no translations for " + locale + " locale");
    }

    return translate(key, locale, translations, slice(arguments, 2));
}

i18n.get = function(locale) {

    return translationCache[locale] || null;
};

i18n.set = function(locale, object) {
    if (!type.isHash(object)) {
        throw new TypeError("i18n.set(locale, object) object must be an Object");
    }

    translationCache[locale] = object;
};

i18n.add = function(locale, object) {
    var translations = translationCache[locale] || (translationCache[locale] = {});

    if (!type.isHash(object)) {
        throw new TypeError("i18n.add(locale, object) object must be an Object");
    }

    utils.mixin(translations, object);
};

function translate(key, locale, translations, args) {
    var keys = key.split("."),
        length = keys.length - 1,
        i = 0,
        value = translations[keys[i]];

    while (i++ < length) {
        key = keys[i];

        if (type.isObject(value)) {
            value = value[key];

            if (value === undefined) {
                throw new Error("i18n(key[, locale]) missing translations for " + locale + " locale, key " + keys.join("."));
            }
        } else {
            throw new Error("i18n(key[, locale]) missing translations for " + locale + " locale, key " + keys.join("."));
        }
    }

    if (type.isObject(value)) {
        throw new TypeError("i18n(key[, locale]) translations for " + locale + " locale, key " + keys.join(".") + " is not a primitive");
    }

    return args.length !== 0 ? utils.formatArgs(value, args) : value;
}

function slice(array, offset) {
    var result = [],
        i = (offset || 0) - 1,
        length = array.length - 1,
        j = 0;

    while (i++ < length) {
        result[j++] = array[i];
    }

    return result;
}
<commit_msg>updates<commit_after>var type = require("type"),
    utils = require("utils");

var translationCache = {};

module.exports = i18n;

function i18n(key, locale) {
    var translations;

    if (!type.isString(key)) {
        throw new TypeError("i18n(key[, locale]) key must be a String");
    }

    translations = i18n.get(locale);

    if (translations === null) {
        throw new Error("i18n(key[, locale]) no translations for " + locale + " locale");
    }

    return translate(key, locale, translations, slice(arguments, 2));
}

i18n.get = function(locale) {

    return translationCache[locale] || null;
};

i18n.set = function(locale, object) {
    if (!type.isHash(object)) {
        throw new TypeError("i18n.set(locale, object) object must be an Object");
    }

    translationCache[locale] = object;
};

i18n.add = function(locale, object) {
    var translations = translationCache[locale] || (translationCache[locale] = {});

    if (!type.isHash(object)) {
        throw new TypeError("i18n.add(locale, object) object must be an Object");
    }

    utils.mixin(translations, object);
};

function translate(key, locale, translations, args) {
    var keys = key.split("."),
        length = keys.length - 1,
        i = 0,
        value = translations[keys[i]];

    while (i++ < length) {
        key = keys[i];

        if (type.isObject(value)) {
            value = value[key];

            if (value === undefined) {
                throw new Error("i18n(key[, locale]) missing translations for " + locale + " locale, key " + keys.join("."));
            }
        } else {
            throw new Error("i18n(key[, locale]) missing translations for " + locale + " locale, key " + keys.join("."));
        }
    }

    if (type.isObject(value)) {
        throw new TypeError("i18n(key[, locale]) translations for " + locale + " locale, key " + keys.join(".") + " is not a primitive");
    }

    return args.length !== 0 ? utils.formatArgs(value, args) : value;
}

function slice(array, offset) {
    var length, i, il, result, j;

    offset = offset || 0;

    length = array.length;
    i = offset - 1;
    il = length - 1;
    result = new Array(length - offset);
    j = 0;

    while (i++ < il) {
        result[j++] = array[i];
    }

    return result;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017, Two Sigma Open Source
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of git-meta nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

const assert  = require("chai").assert;
const co      = require("co");
const NodeGit = require("nodegit");

const SubmoduleFetcher = require("./submodule_fetcher");

/**
 * Return most reset ancestor of the specified `metaCommit` in the specified
 * meta `repo` that introduces the specified `subCommit` in the submodule
 * having the specified `submoduleName`, or null if no such commit exists.  Use
 * the specified `subRepo` to resolve submodule commits and check for
 * ancestor/descendant relations.  Use the specified `subFetcher` to retrieve
 * submodule commits.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             metaCommit
 * @param {String}             subCommit
 * @param {String}             submoduleName
 * @param {NodeGit.Repository} subRepo
 * @param {SubmoduleFetcher}   subFetcher
 * @return {NodeGit.Commit|null}
 */
exports.findMetaCommit = co.wrap(function *(repo,
                                            metaCommit,
                                            subCommit,
                                            submoduleName,
                                            subRepo,
                                            subFetcher) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(metaCommit, NodeGit.Commit);
    assert.instanceOf(subCommit, NodeGit.Commit);
    assert.isString(submoduleName);
    assert.instanceOf(subRepo, NodeGit.Repository);
    assert.instanceOf(subFetcher, SubmoduleFetcher);

    // First, resolve the committishes and throw if they cannot be resolved.

    const subSha = subCommit.id().tostrS();

    // While a recursive solution would be very simple, I'm afraid we'd
    // overflow (v8 does not support tail call optimization at the moment).
    // Furthermore, we need to do a breadth-first-search: we don't want to
    // search the entire left side of a merge commit before checking the right.
    //
    // Strategy: walk back, starting from `metaCommit`, return the first
    // commit where the sha for our submodule references (directly or
    // indirectly) `subCommit`, but its parents don't.

    let   toCheck = [metaCommit];   // commits left to check
    const checked = new Set();      // SHAs checked
    const existsInSha = new Map();  // repo sha to bool if target included

    const doesExistInCommit = co.wrap(function *(commit) {
        const sha = commit.id().tostrS();
        if (existsInSha.has(sha)) {
            return existsInSha.get(sha);
        }
        let result;

        // Check to see if the repo references `subSha` directly, or one of
        // its descendants.

        const tree = yield commit.getTree();
        let subShaForCommit;
        try {
            subShaForCommit = (yield tree.entryByPath(submoduleName)).sha();
        }
        catch (e) {
            // Submodule doesn't exist in this commit; stop checking earlier
            // commits.

            result = false;
        }
        if (undefined !== subShaForCommit) {
            if (subShaForCommit === subSha) {
                result = true;
            }
            else {
                // Ensure that the commit we're checking against is present.

                yield subFetcher.fetchSha(subRepo,
                                          submoduleName,
                                          subShaForCommit);
                result = (yield NodeGit.Graph.descendantOf(
                                       subRepo,
                                       NodeGit.Oid.fromString(subShaForCommit),
                                       subCommit.id())) !== 0;
            }
        }
        existsInSha.set(sha, result);
        return result;
    });

    while (0 !== toCheck.length) {

        // This could be slow (O(N^2)) w.r.t. the number of commits in the
        // repository if the repository is "insane" -- e.g., one commit with
        // all other commits as direct parents.  For normal structions I expect
        // `toCheck` to rarely exceed length of 10.  If we determine this to be
        // a bottleneck, we can adopt a third-party deque library.

        const commit = toCheck.shift();
        const sha = commit.id().tostrS();
        // Bail if we've already checked this one.

        if (checked.has(sha)) {
            continue;                                               // CONTINUE
        }
        checked.add(sha);

        const MAX_PARENTS = 500000;  // arbitrary limit
        const parents = yield commit.getParents(MAX_PARENTS);

        const existsHere = yield doesExistInCommit(commit);

        toCheck = toCheck.concat(parents);

        // Bail if the commit doesn't here.

        if (!existsHere) {
            continue;                                               // CONTINUE
        }

        // If the commit isn't referenced in any parent, this one is the
        // winner.

        let notInParents = true;
        for (let i = 0; notInParents && i < parents.length; ++i) {
            notInParents = !(yield doesExistInCommit(parents[i]));
        }

        if (notInParents) {
            return sha;                                               // RETURN
        }
    }
    return null;
});
<commit_msg>Cache dependency check in find-meta search<commit_after>/*
 * Copyright (c) 2017, Two Sigma Open Source
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of git-meta nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

const assert  = require("chai").assert;
const co      = require("co");
const NodeGit = require("nodegit");

const SubmoduleFetcher = require("./submodule_fetcher");

/**
 * Return most reset ancestor of the specified `metaCommit` in the specified
 * meta `repo` that introduces the specified `subCommit` in the submodule
 * having the specified `submoduleName`, or null if no such commit exists.  Use
 * the specified `subRepo` to resolve submodule commits and check for
 * ancestor/descendant relations.  Use the specified `subFetcher` to retrieve
 * submodule commits.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {String}             metaCommit
 * @param {String}             subCommit
 * @param {String}             submoduleName
 * @param {NodeGit.Repository} subRepo
 * @param {SubmoduleFetcher}   subFetcher
 * @return {NodeGit.Commit|null}
 */
exports.findMetaCommit = co.wrap(function *(repo,
                                            metaCommit,
                                            subCommit,
                                            submoduleName,
                                            subRepo,
                                            subFetcher) {
    assert.instanceOf(repo, NodeGit.Repository);
    assert.instanceOf(metaCommit, NodeGit.Commit);
    assert.instanceOf(subCommit, NodeGit.Commit);
    assert.isString(submoduleName);
    assert.instanceOf(subRepo, NodeGit.Repository);
    assert.instanceOf(subFetcher, SubmoduleFetcher);

    // First, resolve the committishes and throw if they cannot be resolved.

    const subSha = subCommit.id().tostrS();

    // While a recursive solution would be very simple, I'm afraid we'd
    // overflow (v8 does not support tail call optimization at the moment).
    // Furthermore, we need to do a breadth-first-search: we don't want to
    // search the entire left side of a merge commit before checking the right.
    //
    // Strategy: walk back, starting from `metaCommit`, return the first
    // commit where the sha for our submodule references (directly or
    // indirectly) `subCommit`, but its parents don't.

    let   toCheck = [metaCommit];   // commits left to check
    const checked = new Set();      // SHAs checked
    const existsInSha = new Map();  // repo sha to bool if target included
    const isDescended = new Map();  // cache of descendant check

    const doesExistInCommit = co.wrap(function *(commit) {
        const sha = commit.id().tostrS();
        if (existsInSha.has(sha)) {
            return existsInSha.get(sha);
        }
        let result;

        // Check to see if the repo references `subSha` directly, or one of
        // its descendants.

        const tree = yield commit.getTree();
        let subShaForCommit;
        try {
            subShaForCommit = (yield tree.entryByPath(submoduleName)).sha();
        }
        catch (e) {
            // Submodule doesn't exist in this commit; stop checking earlier
            // commits.

            result = false;
        }
        if (undefined !== subShaForCommit) {
            if (subShaForCommit === subSha) {
                result = true;
            }
            else {
                // Check to see if the commit  we're looking for is descended
                // from the current commit.  First, look in the cache.

                if (isDescended.has(subShaForCommit)) {
                    result = isDescended.get(subShaForCommit);
                }
                else {
                    // Ensure that the commit we're checking against is
                    // present; we can't do a descendant check otherwise.

                    yield subFetcher.fetchSha(subRepo,
                                              submoduleName,
                                              subShaForCommit);
                    result = (yield NodeGit.Graph.descendantOf(
                                       subRepo,
                                       NodeGit.Oid.fromString(subShaForCommit),
                                       subCommit.id())) !== 0;
                    isDescended.set(subShaForCommit, result);
                }
            }
        }
        existsInSha.set(sha, result);
        return result;
    });

    while (0 !== toCheck.length) {

        // This could be slow (O(N^2)) w.r.t. the number of commits in the
        // repository if the repository is "insane" -- e.g., one commit with
        // all other commits as direct parents.  For normal structions I expect
        // `toCheck` to rarely exceed length of 10.  If we determine this to be
        // a bottleneck, we can adopt a third-party deque library.

        const commit = toCheck.shift();
        const sha = commit.id().tostrS();
        // Bail if we've already checked this one.

        if (checked.has(sha)) {
            continue;                                               // CONTINUE
        }
        checked.add(sha);

        const MAX_PARENTS = 500000;  // arbitrary limit
        const parents = yield commit.getParents(MAX_PARENTS);

        const existsHere = yield doesExistInCommit(commit);

        toCheck = toCheck.concat(parents);

        // Bail if the commit doesn't here.

        if (!existsHere) {
            continue;                                               // CONTINUE
        }

        // If the commit isn't referenced in any parent, this one is the
        // winner.

        let notInParents = true;
        for (let i = 0; notInParents && i < parents.length; ++i) {
            notInParents = !(yield doesExistInCommit(parents[i]));
        }

        if (notInParents) {
            return sha;                                               // RETURN
        }
    }
    return null;
});
<|endoftext|>


<commit_before>import Proto from 'uberproto'
import filter from 'feathers-query-filters'
import isPlainObject from 'is-plain-object'
import errorHandler from './error-handler'
import { errors } from 'feathers-errors'

const METHODS = {
  $or: 'orWhere',
  $and: 'andWhere',
  $ne: 'whereNot',
  $in: 'whereIn',
  $nin: 'whereNotIn'
}

const OPERATORS = {
  $lt: '<',
  $lte: '<=',
  $gt: '>',
  $gte: '>=',
  $like: 'like'
}

/**
 * Class representing an feathers adapter for objection.js ORM.
 * @param {object} options
 * @param {string} [id='id'] - database id field
 * @param {object} options.model - an objection model
 * @param {object} [options.paginate]
 * @param {string} [allowedEager] - Objection eager loading string.
 */
class Service {
  constructor (options) {
    if (!options) {
      throw new Error('Objection options have to be provided')
    }

    if (!options.model) {
      throw new Error('You must provide an Objection Model')
    }

    this.options = options || {}
    this.id = options.id || 'id'
    this.idSeparator = options.idSeparator || ','
    this.paginate = options.paginate || {}
    this.events = options.events || []
    this.Model = options.model
    this.allowedEager = options.allowedEager || '[]'
    this.namedEagerFilters = options.namedEagerFilters
    this.eagerFilters = options.eagerFilters
  }

  extend (obj) {
    return Proto.extend(obj, this)
  }

  extractIds (id) {
    if (typeof id === 'object') { return Object.values(id) }
    if (id[0] === '[' && id[id.length - 1] === ']') { return JSON.parse(id) }
    if (id[0] === '{' && id[id.length - 1] === '}') { return Object.values(JSON.parse(id)) }

    return id.split(this.idSeparator)
  }

  // Create a new query that re-queries all ids that were originally changed
  getIdsQuery (id, idList) {
    const query = {}

    if (Array.isArray(this.id)) {
      let ids = id

      if (id && !Array.isArray(id)) {
        ids = this.extractIds(id)
      }

      this.id.forEach((idKey, index) => {
        if (!ids) {
          if (idList) {
            if (idList[index]) {
              query[idKey] = { $in: idList[index] }
            }
          } else {
            query[idKey] = null
          }
        } else if (ids[index]) {
          query[idKey] = ids[index]
        } else {
          throw new errors.BadRequest('When using composite primary key, id must contain values for all primary keys')
        }
      })
    } else {
      query[this.id] = idList ? { $in: idList } : id
    }

    return query
  }

  /**
   * Maps a feathers query to the objection/knex schema builder functions.
   * @param query - a query object. i.e. { type: 'fish', age: { $lte: 5 }
   * @param params
   * @param parentKey
   */
  objectify (query, params, parentKey) {
    // Delete $eager
    if (params.$eager) {
      delete params.$eager
    }

    // Delete $joinEager
    if (params.$joinEager) {
      delete params.$joinEager
    }
    Object.keys(params || {}).forEach(key => {
      const value = params[key]

      if (isPlainObject(value)) {
        return this.objectify(query, value, key)
      }

      const column = parentKey || key
      const method = METHODS[key]
      const operator = OPERATORS[key] || '='

      if (method) {
        if (key === '$or' || key === '$and') {
          const self = this

          return value.forEach(condition => {
            query[method](function () {
              self.objectify(this, condition)
            })
          })
        }

        return query[method].call(query, column, value) // eslint-disable-line no-useless-call
      }

      return operator === '=' ? query.where(column, value) : query.where(column, operator, value)
    })
  }

  _createQuery (params = {}) {
    let trx = params.transaction ? params.transaction.trx : null
    let q = this.Model.query(trx)
    return q
  }

  createQuery (params = {}) {
    const { filters, query } = filter(params.query || {})
    let q = this._createQuery(params)
      .skipUndefined()
      .allowEager(this.allowedEager)

    // $select uses a specific find syntax, so it has to come first.
    if (filters.$select) {
      q = q.select(...filters.$select.concat(this.id))
    }

    // $eager for objection eager queries

    if (query && query.$eager) {
      q.eager(query.$eager, this.namedEagerFilters)
      delete query.$eager
    }

    if (query && query.$joinEager) {
      q
        .eagerAlgorithm(this.Model.JoinEagerAlgorithm)
        .eager(query.$joinEager, this.namedEagerFilters)
      delete query.$joinEager
    }

    // apply eager filters if specified
    if (this.eagerFilters) {
      const eagerFilters = this.eagerFilters
      if (Array.isArray(eagerFilters)) {
        for (var eagerFilter of eagerFilters) {
          q.filterEager(eagerFilter.expression, eagerFilter.filter)
        }
      } else {
        q.filterEager(eagerFilters.expression, eagerFilters.filter)
      }
    }

    // build up the knex query out of the query params
    this.objectify(q, query)

    if (filters.$sort) {
      Object.keys(filters.$sort).forEach(key => {
        q = q.orderBy(key, filters.$sort[key] === 1 ? 'asc' : 'desc')
      })
    }

    return q
  }

  _find (params, count, getFilter = filter) {
    const { filters, query } = getFilter(params.query || {})
    const q = params.objection || this.createQuery(params)

    // Handle $limit
    if (filters.$limit) {
      q.limit(filters.$limit)
    }

    // Handle $skip
    if (filters.$skip) {
      q.offset(filters.$skip)
    }

    let executeQuery = total => {
      return q.then(data => {
        return {
          total,
          limit: filters.$limit,
          skip: filters.$skip || 0,
          data
        }
      })
    }

    if (filters.$limit === 0) {
      executeQuery = total => {
        return Promise.resolve({
          total,
          limit: filters.$limit,
          skip: filters.$skip || 0,
          data: []
        })
      }
    }

    if (count) {
      let countQuery = this.Model.query()
        .skipUndefined()
        .count('* as total')

      this.objectify(countQuery, query)

      return countQuery
        .then(count => parseInt(count[0].total, 10))
        .then(executeQuery)
    }

    return executeQuery().catch(errorHandler)
  }

  /**
   * `find` service function for objection.
   * @param params
   */
  find (params) {
    const paginate =
      params && typeof params.paginate !== 'undefined'
        ? params.paginate
        : this.paginate
    const result = this._find(params, !!paginate.default, query =>
      filter(query, paginate)
    )

    if (!paginate.default) {
      return result.then(page => page.data)
    }

    return result
  }

  _get (id, params) {
    const query = Object.assign({}, params.query, this.getIdsQuery(id))

    return this._find(Object.assign({}, params, { query }))
      .then(page => {
        if (page.data.length !== 1) {
          throw new errors.NotFound(`No record found for id '${id}'`)
        }

        return page.data[0]
      })
      .catch(errorHandler)
  }

  /**
   * `get` service function for objection.
   * @param {...object} args
   * @return {Promise} - promise containing the data being retrieved
   */
  get (...args) {
    return this._get(...args)
  }

  _create (data, params) {
    return this._createQuery(params)
      .insert(data, this.id)
      .then(row => {
        let id = null

        if (Array.isArray(this.id)) {
          id = []

          for (const idKey of this.id) {
            id.push(typeof data[idKey] !== 'undefined' ? data[idKey] : row[idKey])
          }
        } else {
          id = typeof data[this.id] !== 'undefined' ? data[this.id] : row[this.id]
        }

        return this._get(id, params)
      })
      .catch(errorHandler)
  }

  /**
   * `create` service function for objection.
   * @param {object} data
   * @param {object} params
   */
  create (data, params) {
    if (Array.isArray(data)) {
      return Promise.all(data.map(current => this._create(current, params)))
    }

    return this._create(data, params)
  }

  /**
   * `update` service function for objection.
   * @param id
   * @param data
   * @param params
   */
  update (id, data, params) {
    if (Array.isArray(data)) {
      return Promise.reject(
        new Error('Not replacing multiple records. Did you mean `patch`?')
      )
    }

    // NOTE (EK): First fetch the old record so
    // that we can fill any existing keys that the
    // client isn't updating with null;
    return this._get(id, params)
      .then(oldData => {
        let newObject = {}

        for (var key of Object.keys(oldData)) {
          if (data[key] === undefined) {
            newObject[key] = null
          } else {
            newObject[key] = data[key]
          }
        }

        // NOTE (EK): Delete id field so we don't update it
        if (Array.isArray(this.id)) {
          for (const idKey of this.id) {
            delete newObject[idKey]
          }
        } else {
          delete newObject[this.id]
        }

        return this._createQuery(params)
          .where(this.getIdsQuery(id))
          .update(newObject)
          .then(() => {
            // NOTE (EK): Restore the id field so we can return it to the client
            if (Array.isArray(this.id)) {
              newObject = Object.assign({}, newObject, this.getIdsQuery(id))
            } else {
              newObject[this.id] = id
            }

            return newObject
          })
      })
      .catch(errorHandler)
  }

  /**
   * `patch` service function for objection.
   * @param id
   * @param data
   * @param params
   */
  patch (id, raw, params) {
    let query = filter(params.query || {}).query
    const data = Object.assign({}, raw)

    const mapIds = page => Array.isArray(this.id)
      ? this.id.map(idKey => [...new Set(page.data.map(current => current[idKey]))])
      : page.data.map(current => current[this.id])

    // By default we will just query for the one id. For multi patch
    // we create a list of the ids of all items that will be changed
    // to re-query them after the update
    const ids =
      id === null ? this._find(params).then(mapIds) : Promise.resolve([id])

    if (id !== null) {
      if (Array.isArray(this.id)) {
        query = Object.assign({}, query, this.getIdsQuery(id))
      } else {
        query[this.id] = id
      }
    }

    let q = this._createQuery(params)

    this.objectify(q, query)

    delete data[this.id]

    return ids
      .then(idList => {
        // Create a new query that re-queries all ids that
        // were originally changed
        const findParams = Object.assign({}, params, { query: Object.assign({}, this.getIdsQuery(id, idList), { $select: params.query && params.query.$select }) })

        return q.patch(data).then(() => {
          return this._find(findParams).then(page => {
            const items = page.data

            if (id !== null) {
              if (items.length === 1) {
                return items[0]
              } else {
                throw new errors.NotFound(`No record found for id '${id}'`)
              }
            }

            return items
          })
        })
      })
      .catch(errorHandler)
  }

  /**
   * `remove` service function for objection.
   * @param id
   * @param params
   */
  remove (id, params) {
    params.query = Object.assign({}, params.query)

    // NOTE (EK): First fetch the record so that we can return
    // it when we delete it.
    if (id !== null) {
      if (Array.isArray(this.id)) {
        params.query = Object.assign({}, params.query, this.getIdsQuery(id))
      } else {
        params.query[this.id] = id
      }
    }

    return this._find(params)
      .then(page => {
        const items = page.data
        const { query: queryParams } = filter(params.query || {})
        const query = this._createQuery(params)

        this.objectify(query, queryParams)

        return query.delete().then(() => {
          if (id !== null) {
            if (items.length === 1) {
              return items[0]
            } else {
              throw new errors.NotFound(`No record found for id '${id}'`)
            }
          }

          return items
        })
      })
      .catch(errorHandler)
  }
}

export default function init (options) {
  return new Service(options)
}

init.Service = Service
<commit_msg>Fixed order issue in extractsIds object handling<commit_after>import Proto from 'uberproto'
import filter from 'feathers-query-filters'
import isPlainObject from 'is-plain-object'
import errorHandler from './error-handler'
import { errors } from 'feathers-errors'

const METHODS = {
  $or: 'orWhere',
  $and: 'andWhere',
  $ne: 'whereNot',
  $in: 'whereIn',
  $nin: 'whereNotIn'
}

const OPERATORS = {
  $lt: '<',
  $lte: '<=',
  $gt: '>',
  $gte: '>=',
  $like: 'like'
}

/**
 * Class representing an feathers adapter for objection.js ORM.
 * @param {object} options
 * @param {string} [id='id'] - database id field
 * @param {object} options.model - an objection model
 * @param {object} [options.paginate]
 * @param {string} [allowedEager] - Objection eager loading string.
 */
class Service {
  constructor (options) {
    if (!options) {
      throw new Error('Objection options have to be provided')
    }

    if (!options.model) {
      throw new Error('You must provide an Objection Model')
    }

    this.options = options || {}
    this.id = options.id || 'id'
    this.idSeparator = options.idSeparator || ','
    this.paginate = options.paginate || {}
    this.events = options.events || []
    this.Model = options.model
    this.allowedEager = options.allowedEager || '[]'
    this.namedEagerFilters = options.namedEagerFilters
    this.eagerFilters = options.eagerFilters
  }

  extend (obj) {
    return Proto.extend(obj, this)
  }

  extractIds (id) {
    if (typeof id === 'object') { return this.id.map(idKey => id[idKey]) }
    if (id[0] === '[' && id[id.length - 1] === ']') { return JSON.parse(id) }
    if (id[0] === '{' && id[id.length - 1] === '}') { return Object.values(JSON.parse(id)) }

    return id.split(this.idSeparator)
  }

  // Create a new query that re-queries all ids that were originally changed
  getIdsQuery (id, idList) {
    const query = {}

    if (Array.isArray(this.id)) {
      let ids = id

      if (id && !Array.isArray(id)) {
        ids = this.extractIds(id)
      }

      this.id.forEach((idKey, index) => {
        if (!ids) {
          if (idList) {
            if (idList[index]) {
              query[idKey] = { $in: idList[index] }
            }
          } else {
            query[idKey] = null
          }
        } else if (ids[index]) {
          query[idKey] = ids[index]
        } else {
          throw new errors.BadRequest('When using composite primary key, id must contain values for all primary keys')
        }
      })
    } else {
      query[this.id] = idList ? { $in: idList } : id
    }

    return query
  }

  /**
   * Maps a feathers query to the objection/knex schema builder functions.
   * @param query - a query object. i.e. { type: 'fish', age: { $lte: 5 }
   * @param params
   * @param parentKey
   */
  objectify (query, params, parentKey) {
    // Delete $eager
    if (params.$eager) {
      delete params.$eager
    }

    // Delete $joinEager
    if (params.$joinEager) {
      delete params.$joinEager
    }
    Object.keys(params || {}).forEach(key => {
      const value = params[key]

      if (isPlainObject(value)) {
        return this.objectify(query, value, key)
      }

      const column = parentKey || key
      const method = METHODS[key]
      const operator = OPERATORS[key] || '='

      if (method) {
        if (key === '$or' || key === '$and') {
          const self = this

          return value.forEach(condition => {
            query[method](function () {
              self.objectify(this, condition)
            })
          })
        }

        return query[method].call(query, column, value) // eslint-disable-line no-useless-call
      }

      return operator === '=' ? query.where(column, value) : query.where(column, operator, value)
    })
  }

  _createQuery (params = {}) {
    let trx = params.transaction ? params.transaction.trx : null
    let q = this.Model.query(trx)
    return q
  }

  createQuery (params = {}) {
    const { filters, query } = filter(params.query || {})
    let q = this._createQuery(params)
      .skipUndefined()
      .allowEager(this.allowedEager)

    // $select uses a specific find syntax, so it has to come first.
    if (filters.$select) {
      q = q.select(...filters.$select.concat(this.id))
    }

    // $eager for objection eager queries

    if (query && query.$eager) {
      q.eager(query.$eager, this.namedEagerFilters)
      delete query.$eager
    }

    if (query && query.$joinEager) {
      q
        .eagerAlgorithm(this.Model.JoinEagerAlgorithm)
        .eager(query.$joinEager, this.namedEagerFilters)
      delete query.$joinEager
    }

    // apply eager filters if specified
    if (this.eagerFilters) {
      const eagerFilters = this.eagerFilters
      if (Array.isArray(eagerFilters)) {
        for (var eagerFilter of eagerFilters) {
          q.filterEager(eagerFilter.expression, eagerFilter.filter)
        }
      } else {
        q.filterEager(eagerFilters.expression, eagerFilters.filter)
      }
    }

    // build up the knex query out of the query params
    this.objectify(q, query)

    if (filters.$sort) {
      Object.keys(filters.$sort).forEach(key => {
        q = q.orderBy(key, filters.$sort[key] === 1 ? 'asc' : 'desc')
      })
    }

    return q
  }

  _find (params, count, getFilter = filter) {
    const { filters, query } = getFilter(params.query || {})
    const q = params.objection || this.createQuery(params)

    // Handle $limit
    if (filters.$limit) {
      q.limit(filters.$limit)
    }

    // Handle $skip
    if (filters.$skip) {
      q.offset(filters.$skip)
    }

    let executeQuery = total => {
      return q.then(data => {
        return {
          total,
          limit: filters.$limit,
          skip: filters.$skip || 0,
          data
        }
      })
    }

    if (filters.$limit === 0) {
      executeQuery = total => {
        return Promise.resolve({
          total,
          limit: filters.$limit,
          skip: filters.$skip || 0,
          data: []
        })
      }
    }

    if (count) {
      let countQuery = this.Model.query()
        .skipUndefined()
        .count('* as total')

      this.objectify(countQuery, query)

      return countQuery
        .then(count => parseInt(count[0].total, 10))
        .then(executeQuery)
    }

    return executeQuery().catch(errorHandler)
  }

  /**
   * `find` service function for objection.
   * @param params
   */
  find (params) {
    const paginate =
      params && typeof params.paginate !== 'undefined'
        ? params.paginate
        : this.paginate
    const result = this._find(params, !!paginate.default, query =>
      filter(query, paginate)
    )

    if (!paginate.default) {
      return result.then(page => page.data)
    }

    return result
  }

  _get (id, params) {
    const query = Object.assign({}, params.query, this.getIdsQuery(id))

    return this._find(Object.assign({}, params, { query }))
      .then(page => {
        if (page.data.length !== 1) {
          throw new errors.NotFound(`No record found for id '${id}'`)
        }

        return page.data[0]
      })
      .catch(errorHandler)
  }

  /**
   * `get` service function for objection.
   * @param {...object} args
   * @return {Promise} - promise containing the data being retrieved
   */
  get (...args) {
    return this._get(...args)
  }

  _create (data, params) {
    return this._createQuery(params)
      .insert(data, this.id)
      .then(row => {
        let id = null

        if (Array.isArray(this.id)) {
          id = []

          for (const idKey of this.id) {
            id.push(typeof data[idKey] !== 'undefined' ? data[idKey] : row[idKey])
          }
        } else {
          id = typeof data[this.id] !== 'undefined' ? data[this.id] : row[this.id]
        }

        return this._get(id, params)
      })
      .catch(errorHandler)
  }

  /**
   * `create` service function for objection.
   * @param {object} data
   * @param {object} params
   */
  create (data, params) {
    if (Array.isArray(data)) {
      return Promise.all(data.map(current => this._create(current, params)))
    }

    return this._create(data, params)
  }

  /**
   * `update` service function for objection.
   * @param id
   * @param data
   * @param params
   */
  update (id, data, params) {
    if (Array.isArray(data)) {
      return Promise.reject(
        new Error('Not replacing multiple records. Did you mean `patch`?')
      )
    }

    // NOTE (EK): First fetch the old record so
    // that we can fill any existing keys that the
    // client isn't updating with null;
    return this._get(id, params)
      .then(oldData => {
        let newObject = {}

        for (var key of Object.keys(oldData)) {
          if (data[key] === undefined) {
            newObject[key] = null
          } else {
            newObject[key] = data[key]
          }
        }

        // NOTE (EK): Delete id field so we don't update it
        if (Array.isArray(this.id)) {
          for (const idKey of this.id) {
            delete newObject[idKey]
          }
        } else {
          delete newObject[this.id]
        }

        return this._createQuery(params)
          .where(this.getIdsQuery(id))
          .update(newObject)
          .then(() => {
            // NOTE (EK): Restore the id field so we can return it to the client
            if (Array.isArray(this.id)) {
              newObject = Object.assign({}, newObject, this.getIdsQuery(id))
            } else {
              newObject[this.id] = id
            }

            return newObject
          })
      })
      .catch(errorHandler)
  }

  /**
   * `patch` service function for objection.
   * @param id
   * @param data
   * @param params
   */
  patch (id, raw, params) {
    let query = filter(params.query || {}).query
    const data = Object.assign({}, raw)

    const mapIds = page => Array.isArray(this.id)
      ? this.id.map(idKey => [...new Set(page.data.map(current => current[idKey]))])
      : page.data.map(current => current[this.id])

    // By default we will just query for the one id. For multi patch
    // we create a list of the ids of all items that will be changed
    // to re-query them after the update
    const ids =
      id === null ? this._find(params).then(mapIds) : Promise.resolve([id])

    if (id !== null) {
      if (Array.isArray(this.id)) {
        query = Object.assign({}, query, this.getIdsQuery(id))
      } else {
        query[this.id] = id
      }
    }

    let q = this._createQuery(params)

    this.objectify(q, query)

    delete data[this.id]

    return ids
      .then(idList => {
        // Create a new query that re-queries all ids that
        // were originally changed
        const findParams = Object.assign({}, params, { query: Object.assign({}, this.getIdsQuery(id, idList), { $select: params.query && params.query.$select }) })

        return q.patch(data).then(() => {
          return this._find(findParams).then(page => {
            const items = page.data

            if (id !== null) {
              if (items.length === 1) {
                return items[0]
              } else {
                throw new errors.NotFound(`No record found for id '${id}'`)
              }
            }

            return items
          })
        })
      })
      .catch(errorHandler)
  }

  /**
   * `remove` service function for objection.
   * @param id
   * @param params
   */
  remove (id, params) {
    params.query = Object.assign({}, params.query)

    // NOTE (EK): First fetch the record so that we can return
    // it when we delete it.
    if (id !== null) {
      if (Array.isArray(this.id)) {
        params.query = Object.assign({}, params.query, this.getIdsQuery(id))
      } else {
        params.query[this.id] = id
      }
    }

    return this._find(params)
      .then(page => {
        const items = page.data
        const { query: queryParams } = filter(params.query || {})
        const query = this._createQuery(params)

        this.objectify(query, queryParams)

        return query.delete().then(() => {
          if (id !== null) {
            if (items.length === 1) {
              return items[0]
            } else {
              throw new errors.NotFound(`No record found for id '${id}'`)
            }
          }

          return items
        })
      })
      .catch(errorHandler)
  }
}

export default function init (options) {
  return new Service(options)
}

init.Service = Service
<|endoftext|>


<commit_before>import Planner from './components/planner';
import Catalog from './catalog/catalog';
import ToolbarButton from './components/toolbar/toolbar-button';
import Ruler from './components/viewer2d/ruler';

console.info(`react-planner started`); //MIT LICENSE COMPLIANT

export {
  Planner, Catalog, ToolbarButton, Ruler
};
<commit_msg>add Models to public elements<commit_after>import Planner from './components/planner';
import Catalog from './catalog/catalog';
import ToolbarButton from './components/toolbar/toolbar-button';
import Ruler from './components/viewer2d/ruler';
import * as Models from './models'

console.info(`react-planner started`); //MIT LICENSE COMPLIANT

export {
  Planner, Catalog, ToolbarButton, Ruler, Models
};
<|endoftext|>


<commit_before>define([
    "jquery",
    "handlebars"
], function($, hb) {
    "use strict";

    var view_template = hb.compile(
        '
' +
        'Resolution' +
        '<select class="form-control" id="resolution-model-{{ index }}">' +
        '{{#each options}}' +
           '<option value="{{this}}">{{this}}</option>' +
        '{{/each}}' +
        '
'
    );

    var ResolutionModel = function () {
        // Model for the resolution configurable.
        var self = this;
        this.resolution = "Window";
        this.resolution_options = ["Window", "1920x1080", "1280x1024", "1280x800", "1024x768"];

        self.view = function (index) {
            // Creates the View to add to the application entry.
            var widget = $(view_template({
                options: self.resolution_options,
                index: index
            }));

            widget.find("select").change(function() {
                if (this.selectedIndex) {
                    self.resolution = this.options[this.selectedIndex].value;
                }
            });

            return widget;
        };
    };

    ResolutionModel.prototype.tag = "resolution";

    ResolutionModel.prototype.as_config_dict = function() {
        // Returns the configuration dict to hand over to the API request.
        // e.g.
        // {
        //    "resolution" : "1024x768"
        // }
        // The returned dictionary must be added to the configurable
        // parameter under the key given by the tag member.
        var resolution = this.resolution;

        if (resolution === 'Window') {
            resolution = this._viewport_resolution();
        }

        return {
            "resolution": resolution
        };
    };

    ResolutionModel.prototype._viewport_resolution = function () {
        // Returns the current viewport resolution as a "WxH" string
        var e = window, a = 'inner';
        if ( !( 'innerWidth' in window ) ) {
            a = 'client';
            e = document.documentElement || document.body;
        }
        return e[ a+'Width' ]+"x"+e[ a+'Height' ];
    };

    // Define all your configurables here.
    var configurables = {
        ResolutionModel: ResolutionModel
    };

    var from_tag = function (tag) {
        // Given a tag, lookup the appropriate configurable and
        // return it. If the tag matches no configurable, returns null
        for (var conf in configurables) {
            if (configurables[conf].prototype.tag === tag) {
                return configurables[conf];
            }
        }
        return null;
    };

    var ns = {
        from_tag: from_tag
    };

    return $.extend(ns, configurables);

});
<commit_msg>Returning appropriate config dict<commit_after>define([
    "jquery",
    "handlebars",
    "utils"
], function($, hb, utils) {
    "use strict";

    var view_template = hb.compile(
        '
' +
        'Resolution' +
        '<select class="form-control" id="resolution-model-{{ index }}">' +
        '{{#each options}}' +
           '<option value="{{this}}">{{this}}</option>' +
        '{{/each}}' +
        '
'
    );

    var ResolutionModel = function () {
        // Model for the resolution configurable.
        var self = this;
        this.resolution = "Window";
        this.resolution_options = ["Window", "1920x1080", "1280x1024", "1280x800", "1024x768"];

        self.view = function (index) {
            // Creates the View to add to the application entry.
            var widget = $(view_template({
                options: self.resolution_options,
                index: index
            }));

            widget.find("select").change(function() {
                if (this.selectedIndex) {
                    self.resolution = this.options[this.selectedIndex].value;
                }
            });

            return widget;
        };
    };

    ResolutionModel.prototype.tag = "resolution";

    ResolutionModel.prototype.as_config_dict = function() {
        // Returns the configuration dict to hand over to the API request.
        // e.g.
        // {
        //    "resolution" : "1024x768"
        // }
        // The returned dictionary must be added to the configurable
        // parameter under the key given by the tag member.
        var resolution = this.resolution;

        if (resolution === 'Window') {
            var max_size = utils.max_iframe_size();
            resolution = max_size[0]+"x"+max_size[1];
        }

        return {
            "resolution": resolution
        };
    };

    // Define all your configurables here.
    var configurables = {
        ResolutionModel: ResolutionModel
    };

    var from_tag = function (tag) {
        // Given a tag, lookup the appropriate configurable and
        // return it. If the tag matches no configurable, returns null
        for (var conf in configurables) {
            if (configurables[conf].prototype.tag === tag) {
                return configurables[conf];
            }
        }
        return null;
    };

    var ns = {
        from_tag: from_tag
    };

    return $.extend(ns, configurables);

});
<|endoftext|>


<commit_before>import rm from '../vendor/ba-routematcher'

function Router() {

  let onHashChangeUserSuppliedCallback = null,
    ignoreHashChange = false,
    controllers = {},
    routes = [];

  /**
   * @returns {*}
   */
  function getHash(){
    if (window.location.hash) {
      return window.location.hash.substring(1);
    } else {
      return false;
    }
  }

  /**
   * @param id
   * @param params
   * @private
   */
  function _callControllerFromObj(id, params) {
    if (controllers[id]) {
      controllers[id].call(undefined, params);
    } else {
      throw("router: controller[" + id + '] does not exist.');
    }
  }

  /**
   * Returns a hash string from a route ID and parameter map. If id does not exist, throws an Exception.
   * @param id
   * @param params
   * @returns {*|String}
   * @private
   */
  function _getHashFromObj(id, params) {
    let hash = routes[id];
    if (!hash) {
      throw("Undefined route '" + id + "'");
    }
    let matched = rm(hash);
    return matched.stringify(params || {});
  }

  /**
   * Returns an object with the id and params object {id:[String],params:{}} from a hash string. Returns false if no
   * match was found.
   * @param hash
   * @returns {*}
   */
  function getObjFromHash(hash) {
    if (!hash) {
      return false;
    }

    for (let k in routes) {
      if (routes.hasOwnProperty(k)) {
        let rm = rm(routes[k]);
        let p = rm.parse(hash);
        if (p !== null) {
          return {id:k, params:p};
        }
      }
    }

    return false;
  }

  /**
   * onHashChange event handler.
   */
  function onHashChange() {

    let o = getObjFromHash(getHash());
    if (o) {

      if(ignoreHashChange){
        //ignore just once, then reset.
        ignoreHashChange = false;
        return;
      }

      if(typeof onHashChangeUserSuppliedCallback === 'function'){
        if(!onHashChangeUserSuppliedCallback()){
          //halt if callback returns false, and go back to the previous route
          ignoreHashChange = true;
          window.history.go(-1);
          return;
        }
      }

      _callControllerFromObj(o.id, o.params);
      return true;
    } else {
      return false;
    }
  }

  /**
   * Returns an object which represents the current hash.
   * @return {*}
   */
  function status() {
    return getObjFromHash(getHash());
  }

  /**
   * Changes the hash, which then is handled by onHashChange, which calls the controller.
   * @param id
   * @param params
   * @param {boolean=} doNotRoute //change the hash without actually routing
   */
  function go2(id, params, doNotRoute) {

    let new_hash = _getHashFromObj(id, params || {});
    ignoreHashChange = doNotRoute;

    //if the hashes are the same, just ignore.
    if(new_hash === window.location.hash.replace('#','')){
      return;
    }

    window.location.hash = new_hash;
  }

  /**
   * Routes based on current hash. Returns true if a match was found, false otherwise.
   * NavigateAwayCallback is ignored.
   * @return boolean
   */
  function route() {
    let o = status(); //get current hash object.
    if (o) {
      _callControllerFromObj(o.id, o.params);
      return true;
    } else {
      return false;
    }
  }

  /**
   * Bind onhashchange to window
   */
  function init() {
    window.onhashchange = onHashChange;
  }

  function setRoutes(map) {
    Object.assign(routes, map);
  }

  function getRoutes() {
    return routes;
  }

  function setControllers(map) {
    Object.assign(controllers, map);
  }

  function getControllers() {
    return controllers;
  }

  function clearRoutes() {
    routes = [];
  }

  function clearControllers() {
    controllers = [];
  }

  function setOnHashChange(fn) {
    onHashChangeUserSuppliedCallback = fn;
  }

  init();

  return {
    route,
    status,
    go2,
    getObjFromHash,
    setRoutes,
    getRoutes,
    setControllers,
    getControllers,
    clearRoutes,
    clearControllers,
    setOnHashChange
  };

}

function setup() {

  console.log('ROUTER BEING DEFINED');

  /* This creates a singleton, instantiating on window (window). */

  //do not bind twice
  if (window.MrRouter) return window.MrRouter;

  console.log('ROUTER BEING INSTANTIATED');

  window.MrRouter = new Router();

}

setup();

export default window.MrRouter<commit_msg>fix dependency issue<commit_after>const rm = require('../vendor/ba-routematcher.js');

function Router() {

  let onHashChangeUserSuppliedCallback = null,
    ignoreHashChange = false,
    controllers = {},
    routes = [];

  /**
   * @returns {*}
   */
  function getHash(){
    if (window.location.hash) {
      return window.location.hash.substring(1);
    } else {
      return false;
    }
  }

  /**
   * @param id
   * @param params
   * @private
   */
  function _callControllerFromObj(id, params) {
    if (controllers[id]) {
      controllers[id].call(undefined, params);
    } else {
      throw("router: controller[" + id + '] does not exist.');
    }
  }

  /**
   * Returns a hash string from a route ID and parameter map. If id does not exist, throws an Exception.
   * @param id
   * @param params
   * @returns {*|String}
   * @private
   */
  function _getHashFromObj(id, params) {
    let hash = routes[id];
    if (!hash) {
      throw("Undefined route '" + id + "'");
    }
    let matched = rm(hash);
    return matched.stringify(params || {});
  }

  /**
   * Returns an object with the id and params object {id:[String],params:{}} from a hash string. Returns false if no
   * match was found.
   * @param hash
   * @returns {*}
   */
  function getObjFromHash(hash) {
    if (!hash) {
      return false;
    }

    for (let k in routes) {
      if (routes.hasOwnProperty(k)) {
        let rm = rm(routes[k]);
        let p = rm.parse(hash);
        if (p !== null) {
          return {id:k, params:p};
        }
      }
    }

    return false;
  }

  /**
   * onHashChange event handler.
   */
  function onHashChange() {

    let o = getObjFromHash(getHash());
    if (o) {

      if(ignoreHashChange){
        //ignore just once, then reset.
        ignoreHashChange = false;
        return;
      }

      if(typeof onHashChangeUserSuppliedCallback === 'function'){
        if(!onHashChangeUserSuppliedCallback()){
          //halt if callback returns false, and go back to the previous route
          ignoreHashChange = true;
          window.history.go(-1);
          return;
        }
      }

      _callControllerFromObj(o.id, o.params);
      return true;
    } else {
      return false;
    }
  }

  /**
   * Returns an object which represents the current hash.
   * @return {*}
   */
  function status() {
    return getObjFromHash(getHash());
  }

  /**
   * Changes the hash, which then is handled by onHashChange, which calls the controller.
   * @param id
   * @param params
   * @param {boolean=} doNotRoute //change the hash without actually routing
   */
  function go2(id, params, doNotRoute) {

    let new_hash = _getHashFromObj(id, params || {});
    ignoreHashChange = doNotRoute;

    //if the hashes are the same, just ignore.
    if(new_hash === window.location.hash.replace('#','')){
      return;
    }

    window.location.hash = new_hash;
  }

  /**
   * Routes based on current hash. Returns true if a match was found, false otherwise.
   * NavigateAwayCallback is ignored.
   * @return boolean
   */
  function route() {
    let o = status(); //get current hash object.
    if (o) {
      _callControllerFromObj(o.id, o.params);
      return true;
    } else {
      return false;
    }
  }

  /**
   * Bind onhashchange to window
   */
  function init() {
    window.onhashchange = onHashChange;
  }

  function setRoutes(map) {
    Object.assign(routes, map);
  }

  function getRoutes() {
    return routes;
  }

  function setControllers(map) {
    Object.assign(controllers, map);
  }

  function getControllers() {
    return controllers;
  }

  function clearRoutes() {
    routes = [];
  }

  function clearControllers() {
    controllers = [];
  }

  function setOnHashChange(fn) {
    onHashChangeUserSuppliedCallback = fn;
  }

  init();

  return {
    route,
    status,
    go2,
    getObjFromHash,
    setRoutes,
    getRoutes,
    setControllers,
    getControllers,
    clearRoutes,
    clearControllers,
    setOnHashChange
  };

}

function setup() {

  console.log('ROUTER BEING DEFINED');

  /* This creates a singleton, instantiating on window (window). */

  //do not bind twice
  if (window.MrRouter) return window.MrRouter;

  console.log('ROUTER BEING INSTANTIATED');

  window.MrRouter = new Router();

}

setup();

export default window.MrRouter<|endoftext|>


<commit_before>var HttpError = require("http_error"),
    multiparty = require('multiparty'),
    qs = require("qs");

function BodyParser(opts) {
    opts || (opts = {});

    this.rejectUnknown = opts.rejectUnknown ? !!opts.rejectUnknown : false;
    this.limit = typeof(opts.limit) === "number" ? opts.limit : false;
}

BodyParser.express = function(opts) {
    var bodyParser = new BodyParser(opts);

    return function(req, res, next) {

        bodyParser.middleware(req, res, next);
    };
};

BodyParser.connect = BodyParser.express;

BodyParser.prototype.middleware = function(req, res, next) {
    var _this = this,
        contentLength = req.contentLength,
        contentType = req.contentType,
        bytesReceived = 0,
        limit = this.limit,
        method = req.method;

    req.body = {};

    if (!req.headers["transfer-encoding"] && contentLength <= 0) {
        next();
        return;
    }

    if (limit && contentLength > limit) {
        next(new HttpError(413, "Request body size exceeds " + limit));
        return;
    }
    if (method === "HEAD" || (method === "GET")) {
        next();
        return;
    }

    if (
        contentType === "multipart/form-data" ||
        contentType === "text/tsv" ||
        contentType === "text/tab-separated-values" ||
        contentType === "text/csv"
    ) {
        new multiparty.Form().parse(req, function(err, fields, files) {
            if (err) {
                next(err);
                return;
            }

            req.files = files;
            mixin(req.body, params);

            next();
        });
        return;
    }

    if (!contentType ||
        contentType === "application/json" ||
        contentType === "application/x-www-form-urlencoded" ||
        contentType.substr(0, 5) === "text/"
    ) {
        req.rawBody = "";
        if (limit) {
            req.on("data", function(chunk) {
                bytesReceived += Buffer.byteLength(chunk);
                if (bytesReceived > limit) return;

                req.rawBody += chunk.toString(req.charset);
            });
        } else {
            req.on("data", function(chunk) {
                req.rawBody += chunk.toString(req.charset);
            });
        }
    } else {
        req.rawBody = new Buffer(0);
        if (limit) {
            req.on("data", function(chunk) {
                bytesReceived += chunk.length;
                if (bytesReceived > limit) return;

                req.rawBody = Buffer.concat([req.rawBody, chunk]);
            });
        } else {
            req.on("data", function(chunk) {
                req.rawBody = Buffer.concat([req.rawBody, chunk]);
            });
        }
    }

    req.on("end", function(err) {
        if (err) {
            next(err);
            return;
        }
        if (bytesReceived > limit) {
            next(new HttpError(413));
            return;
        }

        _this.parse(req, res, next);
    });
};

BodyParser.prototype.parse = function(req, res, next) {
    var contentType = req.contentType,
        parser;

    if (contentType === "application/json") {
        parser = jsonParser;
    } else if (contentType === "application/x-www-form-urlencoded") {
        parser = urlEncodedParser;
    }

    if (parser) {
        parser(req, next);
        return;
    }

    if (this.rejectUnknown) {
        next(new HttpError(415));
        return;
    }

    next();
};

function jsonParser(req, next) {
    var body, params;

    if (!req.rawBody) {
        next();
        return;
    }

    body = req.rawBody;

    try {
        params = JSON.parse(body);
    } catch (e) {
        next(new HttpError(415, "Invalid JSON: " + e.message));
        return;
    }

    mixin(req.body, params);

    next();
}

function urlEncodedParser(req, next) {
    var body, params;

    if (!req.rawBody) {
        next();
        return;
    }

    body = req.rawBody;

    try {
        params = qs.parse(body);
    } catch (e) {
        next(new HttpError(415, "Invalid URL: " + e.message));
        return;
    }

    mixin(req.body, params);

    next();
}

function mixin(a, b) {
    var key, value;

    for (key in b) {
        if (a[key] == null && (value = b[key]) != null) a[key] = value;
    }
    return a;
}

module.exports = BodyParser;
<commit_msg>updates<commit_after>var HttpError = require("http_error"),
    multiparty = require('multiparty'),
    qs = require("qs");

function BodyParser(options) {
    options || (options = {});

    this.rejectUnknown = options.rejectUnknown ? !!options.rejectUnknown : false;
    this.limit = typeof(options.limit) === "number" ? options.limit : false;
    this.multipartOptions = options.multipart || {};
}

BodyParser.express = function(options) {
    var bodyParser = new BodyParser(options);

    return function(req, res, next) {

        bodyParser.middleware(req, res, next);
    };
};

BodyParser.connect = BodyParser.express;

BodyParser.prototype.middleware = function(req, res, next) {
    var _this = this,
        contentLength = req.contentLength,
        contentType = req.contentType,
        bytesReceived = 0,
        limit = this.limit,
        method = req.method;

    req.body = {};

    if (!req.headers["transfer-encoding"] && contentLength <= 0) {
        next();
        return;
    }

    if (limit && contentLength > limit) {
        next(new HttpError(413, "Request body size exceeds " + limit));
        return;
    }
    if (method === "HEAD" || (method === "GET")) {
        next();
        return;
    }

    if (
        contentType === "multipart/form-data" ||
        contentType === "text/tsv" ||
        contentType === "text/tab-separated-values" ||
        contentType === "text/csv"
    ) {
        new multiparty.Form(this.multipartOptions).parse(req, function(err, fields, files) {
            if (err) {
                next(err);
                return;
            }

            req.files = typeof(req.files) === "object" ? mixin(req.files, files) : files;
            mixin(req.body, fields);

            next();
        });
        return;
    }

    if (!contentType ||
        contentType === "application/x-www-form-urlencoded" ||
        contentType === "application/json" ||
        contentType.substr(0, 5) === "text/"
    ) {
        req.rawBody = "";
        if (limit) {
            req.on("data", function(chunk) {
                bytesReceived += Buffer.byteLength(chunk);
                if (bytesReceived > limit) return;

                req.rawBody += chunk.toString(req.charset);
            });
        } else {
            req.on("data", function(chunk) {
                req.rawBody += chunk.toString(req.charset);
            });
        }
    } else {
        req.rawBody = new Buffer(0);
        if (limit) {
            req.on("data", function(chunk) {
                bytesReceived += chunk.length;
                if (bytesReceived > limit) return;

                req.rawBody = Buffer.concat([req.rawBody, chunk]);
            });
        } else {
            req.on("data", function(chunk) {
                req.rawBody = Buffer.concat([req.rawBody, chunk]);
            });
        }
    }

    req.on("end", function(err) {
        if (err) {
            next(err);
            return;
        }
        if (bytesReceived > limit) {
            next(new HttpError(413));
            return;
        }

        _this.parse(req, res, next);
    });
};

BodyParser.prototype.parse = function(req, res, next) {
    var contentType = req.contentType,
        parser;

    if (contentType === "application/json") {
        parser = jsonParser;
    } else if (contentType === "application/x-www-form-urlencoded") {
        parser = urlEncodedParser;
    }

    if (parser) {
        parser(req, next);
        return;
    }

    if (this.rejectUnknown) {
        next(new HttpError(415));
        return;
    }

    next();
};

function jsonParser(req, next) {
    var body, params;

    if (!req.rawBody) {
        next();
        return;
    }

    body = req.rawBody;

    try {
        params = JSON.parse(body);
    } catch (e) {
        next(new HttpError(415, "Invalid JSON: " + e.message));
        return;
    }

    mixin(req.body, params);

    next();
}

function urlEncodedParser(req, next) {
    var body, params;

    if (!req.rawBody) {
        next();
        return;
    }

    body = req.rawBody;

    try {
        params = qs.parse(body);
    } catch (e) {
        next(new HttpError(415, "Invalid URL: " + e.message));
        return;
    }

    mixin(req.body, params);

    next();
}

function mixin(a, b) {
    var key, value;

    for (key in b) {
        if (a[key] == null && (value = b[key]) != null) a[key] = value;
    }
    return a;
}

module.exports = BodyParser;
<|endoftext|>