<commit_before>// Copyright (c) 2013-2014 Quildreen Motta <quildreen@gmail.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/**
 * @module lib/maybe
 */
module.exports = Maybe

// -- Aliases ----------------------------------------------------------
var clone         = Object.create
var unimplemented = function(){ throw new Error('Not implemented.') }
var noop          = function(){ return this                         }

// -- Implementation ---------------------------------------------------

/**
 * A structure for values that may not be present, or computations that may
 * fail. `Maybe(a)` explicitly models the effects that are implicit in
 * `Nullable` types, thus has none of the problems associated with
 * `null` or `undefined` — like `NullPointerExceptions`.
 *
 * The class models two different cases:
 *
 *  + `Just a` — represents a `Maybe(a)` that contains a value. `a` may
 *     be any value, including `null` or `undefined`.
 *
 *  + `Nothing` — represents a `Maybe(a)` that has no values. Or a
 *     failure that needs no additional information.
 *
 * Common uses of this structure includes modelling values that may or may
 * not be present in a collection, thus instead of needing a
 * `collection.has(a)`, the `collection.get(a)` operation gives you all
 * the information you need — `collection.get(a).is-nothing` being
 * equivalent to `collection.has(a)`; Similarly the same reasoning may
 * be applied to computations that may fail to provide a value, e.g.:
 * `collection.find(predicate)` can safely return a `Maybe(a)` instance,
 * even if the collection contains nullable values.
 *
 * Furthermore, the values of `Maybe(a)` can be combined and manipulated
 * by using the expressive monadic operations. This allows safely
 * sequencing operations that may fail, and safely composing values that
 * you don't know whether they're present or not, failing early
 * (returning a `Nothing`) if any of the operations fail.
 *
 * If one wants to store additional information about failures, the
 * [Either][] and [Validation][] structures provide such a capability, and
 * should be used instead of the `Maybe(a)` structure.
 *
 * [Either]: https://github.com/folktale/data.either
 * [Validation]: https://github.com/folktale/data.validation
 *
 *
 * @class
 */
function Maybe() {}

// The case for successful values
Just.prototype = clone(Maybe.prototype)
function Just(a){
  this.value = a
}

// The case for failure values
Nothing.prototype = clone(Maybe.prototype)
function Nothing(){}

// -- Constructors -----------------------------------------------------

/**
 * Constructs a new `Maybe[α]` structure with an absent value. Commonly used
 * to represent a failure.
 *
 * @summary Void → Maybe[α]
 */
Maybe.Nothing = function() {
  return new Nothing
}
Maybe.prototype.Nothing = Maybe.Nothing

/**
 * Constructs a new `Maybe[α]` structure that holds the single value
 * `α`. Commonly used to represent a success.
 *
 * `α` can be any value, including `null`, `undefined` or another
 * `Maybe[α]` structure.
 *
 * @summary α → Maybe[α]
 */
Maybe.Just = function(a) {
  return new Just(a)
}
Maybe.prototype.Just = Maybe.Just

// -- Conversions ------------------------------------------------------

/**
 * Constructs a new `Maybe[α]` structure from a nullable type.
 *
 * If the value is either `null` or `undefined`, this function returns a
 * `Nothing`, otherwise the value is wrapped in a `Just(α)`.
 *
 * @summary α → Maybe[α]
 */
Maybe.fromNullable = function(a) {
  return a != null?       new Just(a)
  :      /* otherwise */  new Nothing
}
Maybe.prototype.fromNullable = Maybe.fromNullable

/**
 * Constructs a new `Maybe[β]` structure from an `Either[α, β]` type.
 *
 * The left side of the `Either` becomes `Nothing`, and the right side
 * is wrapped in a `Just(β)`.
 *
 * @summary Either[α, β] → Maybe[β]
 */
Maybe.fromEither = function(a) {
  return a.fold(Maybe.Nothing, Maybe.Just)
}
Maybe.prototype.fromEither = Maybe.fromEither

/**
 * Constructs a new `Maybe[β]` structure from a `Validation[α, β]` type.
 *
 * The failure side of the `Validation` becomes `Nothing`, and the right
 * side is wrapped in a `Just(β)`.
 *
 * @method
 * @summary Validation[α, β] → Maybe[β]
 */
Maybe.fromValidation           = Maybe.fromEither
Maybe.prototype.fromValidation = Maybe.fromEither

// -- Predicates -------------------------------------------------------

/**
 * True if the `Maybe[α]` structure contains a failure (i.e.: `Nothing`).
 *
 * @summary Boolean
 */
Maybe.prototype.isNothing   = false
Nothing.prototype.isNothing = true

/**
 * True if the `Maybe[α]` structure contains a single value (i.e.: `Just(α)`).
 *
 * @summary Boolean
 */
Maybe.prototype.isJust = false
Just.prototype.isJust  = true

// -- Applicative ------------------------------------------------------

/**
 * Creates a new `Maybe[α]` structure holding the single value `α`.
 *
 * `α` can be any value, including `null`, `undefined`, or another
 * `Maybe[α]` structure.
 *
 * @summary α → Maybe[α]
 */
Maybe.of = function(a) {
  return Maybe.prototype.Just(a)
}
Maybe.prototype.of = Maybe.of

/**
 * Applies the function inside the `Maybe[α]` structure to another
 * applicative type.
 *
 * The `Maybe[α]` structure should contain a function value, otherwise a
 * `TypeError` is thrown.
 *
 * @method
 * @summary (@Maybe[α → β], f:Applicative[_]) => f[α] → f[β]
 */
Maybe.prototype.ap = unimplemented

Nothing.prototype.ap = function(b) {
  return b
}

Just.prototype.ap = function(b) {
  return b.map(this.value)
}

// -- Functor ----------------------------------------------------------

/**
 * Transforms the value of the `Maybe[α]` structure using a regular unary
 * function.
 *
 * @method
 * @summary @Maybe[α] => (α → β) → Maybe[β]
 */
Maybe.prototype.map   = unimplemented
Nothing.prototype.map = noop

Just.prototype.map = function(f) {
  return this.of(f(this.value))
}

// -- Chain ------------------------------------------------------------

/**
 * Transforms the value of the `Maybe[α]` structure using an unary function
 * to monads.
 *
 * @method
 * @summary (@Maybe[α], m:Monad[_]) => (α → m[β]) → m[β]
 */
Maybe.prototype.chain   = unimplemented
Nothing.prototype.chain = noop

Just.prototype.chain = function(f) {
  return f(this.value)
}

// -- Show -------------------------------------------------------------

/**
 * Returns a textual representation of the `Maybe[α]` structure.
 *
 * @method
 * @summary @Maybe[α] => Void → String
 */
Maybe.prototype.toString = unimplemented

Nothing.prototype.toString = function() {
  return 'Maybe.Nothing'
}

Just.prototype.toString = function() {
  return 'Maybe.Just(' + this.value + ')'
}

// -- Eq ---------------------------------------------------------------

/**
 * Tests if a `Maybe[α]` structure is equal to another `Maybe[α]` structure.
 *
 * @method
 * @summary @Maybe[α] => Maybe[α] → Boolean
 */
Maybe.prototype.isEqual = unimplemented

Nothing.prototype.isEqual = function(b) {
  return b.isNothing
}

Just.prototype.isEqual = function(b) {
  return b.isJust
  &&     b.value === this.value
}

// -- Extracting and recovering ----------------------------------------

/**
 * Extracts the value out of the `Maybe[α]` structure, if it
 * exists. Otherwise throws a `TypeError`.
 *
 * @method
 * @summary @Maybe[α] => Void → a,      :: partial, throws
 * @see {@link module:lib/maybe~Maybe#getOrElse} — A getter that can handle failures
 * @throws {TypeError} if the structure has no value (`Nothing`).
 */
Maybe.prototype.get = unimplemented

Nothing.prototype.get = function() {
  throw new TypeError("Can't extract the value of a Nothing.")
}

Just.prototype.get = function() {
  return this.value
}

/**
 * Extracts the value out of the `Maybe[α]` structure. If there is no value,
 * returns the given default.
 *
 * @method
 * @summary @Maybe[α] => α → α
 */
Maybe.prototype.getOrElse = unimplemented

Nothing.prototype.getOrElse = function(a) {
  return a
}

Just.prototype.getOrElse = function(_) {
  return this.value
}

/**
 * Transforms a failure into a new `Maybe[α]` structure. Does nothing if the
 * structure already contains a value.
 *
 * @method
 * @summary @Maybe[α] => (Void → Maybe[α]) → Maybe[α]
 */
Maybe.prototype.orElse = unimplemented

Nothing.prototype.orElse = function(f) {
  return f()
}

Just.prototype.orElse = function(_) {
  return this
}

/**
 * Catamorphism.
 *
 * @method
 * @summary @Maybe[α] => { Nothing: Void → β, Just: α → β } → β
 */
Maybe.prototype.cata = unimplemented

Nothing.prototype.cata = function(pattern) {
  return pattern.Nothing()
}

Just.prototype.cata = function(pattern) {
  return pattern.Just(this.value);
}<commit_msg>JSON serialisation<commit_after>// Copyright (c) 2013-2014 Quildreen Motta <quildreen@gmail.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/**
 * @module lib/maybe
 */
module.exports = Maybe

// -- Aliases ----------------------------------------------------------
var clone         = Object.create
var unimplemented = function(){ throw new Error('Not implemented.') }
var noop          = function(){ return this                         }

// -- Implementation ---------------------------------------------------

/**
 * A structure for values that may not be present, or computations that may
 * fail. `Maybe(a)` explicitly models the effects that are implicit in
 * `Nullable` types, thus has none of the problems associated with
 * `null` or `undefined` — like `NullPointerExceptions`.
 *
 * The class models two different cases:
 *
 *  + `Just a` — represents a `Maybe(a)` that contains a value. `a` may
 *     be any value, including `null` or `undefined`.
 *
 *  + `Nothing` — represents a `Maybe(a)` that has no values. Or a
 *     failure that needs no additional information.
 *
 * Common uses of this structure includes modelling values that may or may
 * not be present in a collection, thus instead of needing a
 * `collection.has(a)`, the `collection.get(a)` operation gives you all
 * the information you need — `collection.get(a).is-nothing` being
 * equivalent to `collection.has(a)`; Similarly the same reasoning may
 * be applied to computations that may fail to provide a value, e.g.:
 * `collection.find(predicate)` can safely return a `Maybe(a)` instance,
 * even if the collection contains nullable values.
 *
 * Furthermore, the values of `Maybe(a)` can be combined and manipulated
 * by using the expressive monadic operations. This allows safely
 * sequencing operations that may fail, and safely composing values that
 * you don't know whether they're present or not, failing early
 * (returning a `Nothing`) if any of the operations fail.
 *
 * If one wants to store additional information about failures, the
 * [Either][] and [Validation][] structures provide such a capability, and
 * should be used instead of the `Maybe(a)` structure.
 *
 * [Either]: https://github.com/folktale/data.either
 * [Validation]: https://github.com/folktale/data.validation
 *
 *
 * @class
 */
function Maybe() {}

// The case for successful values
Just.prototype = clone(Maybe.prototype)
function Just(a){
  this.value = a
}

// The case for failure values
Nothing.prototype = clone(Maybe.prototype)
function Nothing(){}

// -- Constructors -----------------------------------------------------

/**
 * Constructs a new `Maybe[α]` structure with an absent value. Commonly used
 * to represent a failure.
 *
 * @summary Void → Maybe[α]
 */
Maybe.Nothing = function() {
  return new Nothing
}
Maybe.prototype.Nothing = Maybe.Nothing

/**
 * Constructs a new `Maybe[α]` structure that holds the single value
 * `α`. Commonly used to represent a success.
 *
 * `α` can be any value, including `null`, `undefined` or another
 * `Maybe[α]` structure.
 *
 * @summary α → Maybe[α]
 */
Maybe.Just = function(a) {
  return new Just(a)
}
Maybe.prototype.Just = Maybe.Just

// -- Conversions ------------------------------------------------------

/**
 * Constructs a new `Maybe[α]` structure from a nullable type.
 *
 * If the value is either `null` or `undefined`, this function returns a
 * `Nothing`, otherwise the value is wrapped in a `Just(α)`.
 *
 * @summary α → Maybe[α]
 */
Maybe.fromNullable = function(a) {
  return a != null?       new Just(a)
  :      /* otherwise */  new Nothing
}
Maybe.prototype.fromNullable = Maybe.fromNullable

/**
 * Constructs a new `Maybe[β]` structure from an `Either[α, β]` type.
 *
 * The left side of the `Either` becomes `Nothing`, and the right side
 * is wrapped in a `Just(β)`.
 *
 * @summary Either[α, β] → Maybe[β]
 */
Maybe.fromEither = function(a) {
  return a.fold(Maybe.Nothing, Maybe.Just)
}
Maybe.prototype.fromEither = Maybe.fromEither

/**
 * Constructs a new `Maybe[β]` structure from a `Validation[α, β]` type.
 *
 * The failure side of the `Validation` becomes `Nothing`, and the right
 * side is wrapped in a `Just(β)`.
 *
 * @method
 * @summary Validation[α, β] → Maybe[β]
 */
Maybe.fromValidation           = Maybe.fromEither
Maybe.prototype.fromValidation = Maybe.fromEither

// -- Predicates -------------------------------------------------------

/**
 * True if the `Maybe[α]` structure contains a failure (i.e.: `Nothing`).
 *
 * @summary Boolean
 */
Maybe.prototype.isNothing   = false
Nothing.prototype.isNothing = true

/**
 * True if the `Maybe[α]` structure contains a single value (i.e.: `Just(α)`).
 *
 * @summary Boolean
 */
Maybe.prototype.isJust = false
Just.prototype.isJust  = true

// -- Applicative ------------------------------------------------------

/**
 * Creates a new `Maybe[α]` structure holding the single value `α`.
 *
 * `α` can be any value, including `null`, `undefined`, or another
 * `Maybe[α]` structure.
 *
 * @summary α → Maybe[α]
 */
Maybe.of = function(a) {
  return Maybe.prototype.Just(a)
}
Maybe.prototype.of = Maybe.of

/**
 * Applies the function inside the `Maybe[α]` structure to another
 * applicative type.
 *
 * The `Maybe[α]` structure should contain a function value, otherwise a
 * `TypeError` is thrown.
 *
 * @method
 * @summary (@Maybe[α → β], f:Applicative[_]) => f[α] → f[β]
 */
Maybe.prototype.ap = unimplemented

Nothing.prototype.ap = function(b) {
  return b
}

Just.prototype.ap = function(b) {
  return b.map(this.value)
}

// -- Functor ----------------------------------------------------------

/**
 * Transforms the value of the `Maybe[α]` structure using a regular unary
 * function.
 *
 * @method
 * @summary @Maybe[α] => (α → β) → Maybe[β]
 */
Maybe.prototype.map   = unimplemented
Nothing.prototype.map = noop

Just.prototype.map = function(f) {
  return this.of(f(this.value))
}

// -- Chain ------------------------------------------------------------

/**
 * Transforms the value of the `Maybe[α]` structure using an unary function
 * to monads.
 *
 * @method
 * @summary (@Maybe[α], m:Monad[_]) => (α → m[β]) → m[β]
 */
Maybe.prototype.chain   = unimplemented
Nothing.prototype.chain = noop

Just.prototype.chain = function(f) {
  return f(this.value)
}

// -- Show -------------------------------------------------------------

/**
 * Returns a textual representation of the `Maybe[α]` structure.
 *
 * @method
 * @summary @Maybe[α] => Void → String
 */
Maybe.prototype.toString = unimplemented

Nothing.prototype.toString = function() {
  return 'Maybe.Nothing'
}

Just.prototype.toString = function() {
  return 'Maybe.Just(' + this.value + ')'
}

// -- Eq ---------------------------------------------------------------

/**
 * Tests if a `Maybe[α]` structure is equal to another `Maybe[α]` structure.
 *
 * @method
 * @summary @Maybe[α] => Maybe[α] → Boolean
 */
Maybe.prototype.isEqual = unimplemented

Nothing.prototype.isEqual = function(b) {
  return b.isNothing
}

Just.prototype.isEqual = function(b) {
  return b.isJust
  &&     b.value === this.value
}

// -- Extracting and recovering ----------------------------------------

/**
 * Extracts the value out of the `Maybe[α]` structure, if it
 * exists. Otherwise throws a `TypeError`.
 *
 * @method
 * @summary @Maybe[α] => Void → a,      :: partial, throws
 * @see {@link module:lib/maybe~Maybe#getOrElse} — A getter that can handle failures
 * @throws {TypeError} if the structure has no value (`Nothing`).
 */
Maybe.prototype.get = unimplemented

Nothing.prototype.get = function() {
  throw new TypeError("Can't extract the value of a Nothing.")
}

Just.prototype.get = function() {
  return this.value
}

/**
 * Extracts the value out of the `Maybe[α]` structure. If there is no value,
 * returns the given default.
 *
 * @method
 * @summary @Maybe[α] => α → α
 */
Maybe.prototype.getOrElse = unimplemented

Nothing.prototype.getOrElse = function(a) {
  return a
}

Just.prototype.getOrElse = function(_) {
  return this.value
}

/**
 * Transforms a failure into a new `Maybe[α]` structure. Does nothing if the
 * structure already contains a value.
 *
 * @method
 * @summary @Maybe[α] => (Void → Maybe[α]) → Maybe[α]
 */
Maybe.prototype.orElse = unimplemented

Nothing.prototype.orElse = function(f) {
  return f()
}

Just.prototype.orElse = function(_) {
  return this
}

/**
 * Catamorphism.
 *
 * @method
 * @summary @Maybe[α] => { Nothing: Void → β, Just: α → β } → β
 */
Maybe.prototype.cata = unimplemented

Nothing.prototype.cata = function(pattern) {
  return pattern.Nothing()
}

Just.prototype.cata = function(pattern) {
  return pattern.Just(this.value);
}

/**
 * JSON serialisation
 *
 * @method
 * @summary @Maybe[α] => Void → Object
 */
Maybe.prototype.toJSON = unimplemented

Nothing.prototype.toJSON = function() {
  return { '#type': 'folktale:Maybe.Nothing' }
}

Just.prototype.toJSON = function() {
  return { '#type': 'folktale:Maybe.Just'
         , value: this.value }
}<|endoftext|>


<commit_before>var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var pkg = require('./package.json');

// Copy vendor files from /node_modules into /vendor
// NOTE: requires `npm install` before running!
gulp.task('copy', function() {
  gulp.src([
      'node_modules/bootstrap/dist/**/*',
      '!**/npm.js',
      '!**/bootstrap-theme.*',
      '!**/*.map'
    ])
    .pipe(gulp.dest('vendor/bootstrap'))

  gulp.src(['node_modules/jquery/dist/jquery.js', 'node_modules/jquery/dist/jquery.min.js'])
    .pipe(gulp.dest('vendor/jquery'))

  gulp.src(['node_modules/popper.js/dist/umd/popper.js', 'node_modules/popper.js/dist/umd/popper.min.js'])
    .pipe(gulp.dest('vendor/popper'))
})

// Default task
gulp.task('default', ['copy']);

// Configure the browserSync task
gulp.task('browserSync', function() {
  browserSync.init({
    server: {
      baseDir: ''
    },
  })
})

// Dev task with browserSync
gulp.task('dev', ['browserSync'], function() {
  // Reloads the browser whenever HTML or CSS files change
  gulp.watch('css/*.css', browserSync.reload);
  gulp.watch('*.html', browserSync.reload);
});
<commit_msg>remove popper from gulpfile<commit_after>var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var pkg = require('./package.json');

// Copy vendor files from /node_modules into /vendor
// NOTE: requires `npm install` before running!
gulp.task('copy', function() {
  gulp.src([
      'node_modules/bootstrap/dist/**/*',
      '!**/npm.js',
      '!**/bootstrap-theme.*',
      '!**/*.map'
    ])
    .pipe(gulp.dest('vendor/bootstrap'))

  gulp.src(['node_modules/jquery/dist/jquery.js', 'node_modules/jquery/dist/jquery.min.js'])
    .pipe(gulp.dest('vendor/jquery'))
})

// Default task
gulp.task('default', ['copy']);

// Configure the browserSync task
gulp.task('browserSync', function() {
  browserSync.init({
    server: {
      baseDir: ''
    },
  })
})

// Dev task with browserSync
gulp.task('dev', ['browserSync'], function() {
  // Reloads the browser whenever HTML or CSS files change
  gulp.watch('css/*.css', browserSync.reload);
  gulp.watch('*.html', browserSync.reload);
});
<|endoftext|>


<commit_before>'use strict'

const Joi = require('joi')
const _ = require('lodash')
const log = require('npmlog')

const hapiCrudHelper = require('./hapiCrudHelper.js')

module.exports = function (server, options) {

  const functionality = function (server, options) {
    return {
      crud: function (config) {
        initModel(config)

        // find all
        this.route({
          method: 'GET',
          path: config.basePath,
          handler: function (request, reply) {
            return filterQueryParams(config.bookshelfModel.where(findAllQueryParams(request, config)), request).fetchAll().then(function (collection) {
              reply(collection)
            })
          },
		  validate: false,
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

        // find by id
        this.route({
          method: 'GET',
          path: config.basePath + '/{id}',
          handler: function (request, reply) {
            return config.bookshelfModel.where(findByIdQueryParams(request, config)).fetch().then(function (entity) {
              if (entity !== null) {
                reply(entity)
              }
              else {
                reply().code(404)
              }
            })
          },
		  validate: false,
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

        // add
        this.route({
          method: 'POST',
          path: config.basePath,
          handler: function (request, reply) {
            return config.bookshelfModel.forge(request.payload).save().then(function (entity) {
              if (typeof config.afterAdd !== 'undefined') {
                config.afterAdd(entity)
              }
              reply(entity).header('Location', getBaseUrl(request) + config.basePath + '/' + entity.id)
            })
          },
		  beforeValidate: function(request) {
			if (typeof request.payload.id !== 'undefined' && request.payload.id !== null) {
				throw {message: "Request body entity's id field is expected to be be null.", code: 'BodyIdIsNotNullException'}
			}
		  },
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

        // update
        this.route({
          method: 'PUT',
          path: config.basePath + '/{id}',
          handler: function (request, reply) {
			request.payload.id = Number(request.params.id) // enforce id if null
            return config.bookshelfModel.forge(request.payload).save().then(function (entity) {
              if (typeof config.afterUpdate !== 'undefined') {
                config.afterUpdate(entity)
              }
              reply(entity).header('Location', getBaseUrl(request) + config.basePath + '/' + entity.id)
            })
          },
		  beforeValidate: function(request) {
			if (typeof request.payload.id !== 'undefined' && request.payload.id !== null && request.payload.id !== Number(request.params.id)) {
				throw {message: "Request body entity's id field is expected to be empty or to match id path parameter.", code: 'BodyIdDoesNotMatchPathException'}
			}
		  },
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

        // delete
        this.route({
          method: 'DELETE',
          path: config.basePath + '/{id}',
          handler: function (request, reply) {
            return config.bookshelfModel.where(findByIdQueryParams(request, config)).destroy().then(function (entity) {
              reply().code(204)
            })
          },
		  validate: false,
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

		// delete all
        this.route({
          method: 'DELETE',
          path: config.basePath,
          handler: function (request, reply) {
		    // We need an artificial where() clause that is always true (https://github.com/tgriesser/bookshelf/issues/1144)
			return config.bookshelfModel.where(findAllQueryParams(request, config)).where('id', '!=', '0').destroy().then(function (entity) {
              reply().code(204)
            })
          },
		  validate: false,
		  isAllowed: options.allowDeleteAll,
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })
      },

      route: function (config) {
		// set default config
		if (typeof config === 'undefined') {
			config = {}
		}
		config = _.merge({
			validate: true,
			isAllowed: true,
		}, config)

        server.route({
          method: config.method,
          path: config.path,
          handler: function (request, reply) {
			if (!config.isAllowed) {
				reply.response().code(403)
				return
			}

            var validationError = null
            if (request.payload !== null) {
              setForeignKeys(request, config.baseQuery)
              formatNumber(request.payload, config.bookshelfModel.prototype.schema)
              formatDate(request.payload, config.bookshelfModel.prototype.schema)

			  try {
				config.beforeValidate(request)
			  }
			  catch (error) {
				handleError(error, reply, options)
				return
			  }
            }
			if (config.validate) {
				Joi.validate(request.payload, Joi.object().keys(pickJoiConstraints(config.bookshelfModel.prototype.schema)), {abortEarly: false, allowUnknown: true}, function(err, value) {
                validationError = err
                // update payload with default values
                request.payload = value
              })
			}

            if (validationError === null) {
              // empty relationships that shouldn't be set
              empty(request.payload, config.bookshelfModel.prototype.schema, Empty)
              // call the actual bookshelf model function
              config.handler(request, reply)
              // handle errors
              .catch(function (error) {
				log.error(error)
                handleError(error, reply, options)
				return
              })
            }
            else {
              reply.response(transformConstraintViolationMessages(validationError)).code(400)
            }
          },
        })
      },

      empty: function() {
        return Empty
      },
    }
  }

  const Empty = {}

  // Set default options
  if (typeof options === 'undefined') {
	options = {}
  }
  options = _.merge({
	returnExceptionBody: true,
	allowDeleteAll: true,
  }, options)

  return functionality(server, options)
}

function handleError(error, reply, options) {
	if (options.returnExceptionBody) {
		reply.response(transformErrorMessage(error)).code(400)
	}
	else {
		reply.response().code(400)
	}
}

const getBaseUrl = hapiCrudHelper.getBaseUrl
const findAllQueryParams = hapiCrudHelper.findAllQueryParams
const findByIdQueryParams = hapiCrudHelper.findByIdQueryParams
const filterQueryParams = hapiCrudHelper.filterQueryParams
const underscore = hapiCrudHelper.underscore
const empty = hapiCrudHelper.empty
const pickJoiConstraints = hapiCrudHelper.pickJoiConstraints
const initModel = hapiCrudHelper.initModel
const addConstraintsForForeignKeys = hapiCrudHelper.addConstraintsForForeignKeys
const initJsonDateFormat = hapiCrudHelper.initJsonDateFormat
const formatNumber = hapiCrudHelper.formatNumber
const formatDate = hapiCrudHelper.formatDate
const setForeignKeys = hapiCrudHelper.setForeignKeys
const transformErrorMessage = hapiCrudHelper.transformErrorMessage
const transformConstraintViolationMessages = hapiCrudHelper.transformConstraintViolationMessages<commit_msg>#9: Add filter option<commit_after>'use strict'

const Joi = require('joi')
const _ = require('lodash')
const log = require('npmlog')

const hapiCrudHelper = require('./hapiCrudHelper.js')

module.exports = function (server, options) {

  const functionality = function (server, options) {
    return {
      crud: function (config) {
        initModel(config)

        // find all
        this.route({
          method: 'GET',
          path: config.basePath,
          handler: function (request, reply) {
			let ret = config.bookshelfModel.where(findAllQueryParams(request, config))
			if (options.allowFilters) {
				ret = filterQueryParams(ret, request)
			}
            return ret.fetchAll().then(function (collection) {
              reply(collection)
            })
          },
		  validate: false,
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

        // find by id
        this.route({
          method: 'GET',
          path: config.basePath + '/{id}',
          handler: function (request, reply) {
            return config.bookshelfModel.where(findByIdQueryParams(request, config)).fetch().then(function (entity) {
              if (entity !== null) {
                reply(entity)
              }
              else {
                reply().code(404)
              }
            })
          },
		  validate: false,
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

        // add
        this.route({
          method: 'POST',
          path: config.basePath,
          handler: function (request, reply) {
            return config.bookshelfModel.forge(request.payload).save().then(function (entity) {
              if (typeof config.afterAdd !== 'undefined') {
                config.afterAdd(entity)
              }
              reply(entity).header('Location', getBaseUrl(request) + config.basePath + '/' + entity.id)
            })
          },
		  beforeValidate: function(request) {
			if (typeof request.payload.id !== 'undefined' && request.payload.id !== null) {
				throw {message: "Request body entity's id field is expected to be be null.", code: 'BodyIdIsNotNullException'}
			}
		  },
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

        // update
        this.route({
          method: 'PUT',
          path: config.basePath + '/{id}',
          handler: function (request, reply) {
			request.payload.id = Number(request.params.id) // enforce id if null
            return config.bookshelfModel.forge(request.payload).save().then(function (entity) {
              if (typeof config.afterUpdate !== 'undefined') {
                config.afterUpdate(entity)
              }
              reply(entity).header('Location', getBaseUrl(request) + config.basePath + '/' + entity.id)
            })
          },
		  beforeValidate: function(request) {
			if (typeof request.payload.id !== 'undefined' && request.payload.id !== null && request.payload.id !== Number(request.params.id)) {
				throw {message: "Request body entity's id field is expected to be empty or to match id path parameter.", code: 'BodyIdDoesNotMatchPathException'}
			}
		  },
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

        // delete
        this.route({
          method: 'DELETE',
          path: config.basePath + '/{id}',
          handler: function (request, reply) {
            return config.bookshelfModel.where(findByIdQueryParams(request, config)).destroy().then(function (entity) {
              reply().code(204)
            })
          },
		  validate: false,
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })

		// delete all
        this.route({
          method: 'DELETE',
          path: config.basePath,
          handler: function (request, reply) {
		    // We need an artificial where() clause that is always true (https://github.com/tgriesser/bookshelf/issues/1144)
			return config.bookshelfModel.where(findAllQueryParams(request, config)).where('id', '!=', '0').destroy().then(function (entity) {
              reply().code(204)
            })
          },
		  validate: false,
		  isAllowed: options.allowDeleteAll,
          baseQuery: config.baseQuery,
          bookshelfModel: config.bookshelfModel,
        })
      },

      route: function (config) {
		// set default config
		if (typeof config === 'undefined') {
			config = {}
		}
		config = _.merge({
			validate: true,
			isAllowed: true,
		}, config)

        server.route({
          method: config.method,
          path: config.path,
          handler: function (request, reply) {
			if (!config.isAllowed) {
				reply.response().code(403)
				return
			}

            var validationError = null
            if (request.payload !== null) {
              setForeignKeys(request, config.baseQuery)
              formatNumber(request.payload, config.bookshelfModel.prototype.schema)
              formatDate(request.payload, config.bookshelfModel.prototype.schema)

			  try {
				config.beforeValidate(request)
			  }
			  catch (error) {
				handleError(error, reply, options)
				return
			  }
            }
			if (config.validate) {
				Joi.validate(request.payload, Joi.object().keys(pickJoiConstraints(config.bookshelfModel.prototype.schema)), {abortEarly: false, allowUnknown: true}, function(err, value) {
                validationError = err
                // update payload with default values
                request.payload = value
              })
			}

            if (validationError === null) {
              // empty relationships that shouldn't be set
              empty(request.payload, config.bookshelfModel.prototype.schema, Empty)
              // call the actual bookshelf model function
              config.handler(request, reply)
              // handle errors
              .catch(function (error) {
				log.error(error)
                handleError(error, reply, options)
				return
              })
            }
            else {
              reply.response(transformConstraintViolationMessages(validationError)).code(400)
            }
          },
        })
      },

      empty: function() {
        return Empty
      },
    }
  }

  const Empty = {}

  // Set default options
  if (typeof options === 'undefined') {
	options = {}
  }
  options = _.merge({
	returnExceptionBody: true,
	allowDeleteAll: true,
	allowFilters: true,
  }, options)

  return functionality(server, options)
}

function handleError(error, reply, options) {
	if (options.returnExceptionBody) {
		reply.response(transformErrorMessage(error)).code(400)
	}
	else {
		reply.response().code(400)
	}
}

const getBaseUrl = hapiCrudHelper.getBaseUrl
const findAllQueryParams = hapiCrudHelper.findAllQueryParams
const findByIdQueryParams = hapiCrudHelper.findByIdQueryParams
const filterQueryParams = hapiCrudHelper.filterQueryParams
const underscore = hapiCrudHelper.underscore
const empty = hapiCrudHelper.empty
const pickJoiConstraints = hapiCrudHelper.pickJoiConstraints
const initModel = hapiCrudHelper.initModel
const addConstraintsForForeignKeys = hapiCrudHelper.addConstraintsForForeignKeys
const initJsonDateFormat = hapiCrudHelper.initJsonDateFormat
const formatNumber = hapiCrudHelper.formatNumber
const formatDate = hapiCrudHelper.formatDate
const setForeignKeys = hapiCrudHelper.setForeignKeys
const transformErrorMessage = hapiCrudHelper.transformErrorMessage
const transformConstraintViolationMessages = hapiCrudHelper.transformConstraintViolationMessages<|endoftext|>


<commit_before>/**
 * gulpfile.js
 *
 * All the yummy build stuff!
 *
 * @author Fredrik Frodlund (contact@frippz.se)
 */

// Requirements
var gulp             = require('gulp'),
    gulpif           = require('gulp-if'),
    gutil            = require('gulp-util'),
    plumber          = require('gulp-plumber'),
    sourcemaps       = require('gulp-sourcemaps'),
    autoprefixer     = require('gulp-autoprefixer'),
    cssnano          = require('gulp-cssnano'),
    concat           = require('gulp-concat'),
    uglify           = require('gulp-uglify'),
    postcss          = require('gulp-postcss'),
    watch            = require('gulp-watch'),
    customProperties = require('postcss-custom-properties'),
    eslint           = require('gulp-eslint'),
    liveServer       = require('live-server'),
    syncy            = require('syncy'),
    hashsum          = require('gulp-hashsum'),
    stylelint        = require('gulp-stylelint'),
    svgSprite        = require('gulp-svg-sprite'),
    exec             = require('child_process').exec;

// Configur paths
var paths = {

  // Inputs
  jsFiles: ['./src/js/**/*.js'],
  cssFiles: ['./src/css/**/*.css'],

  // Static assets
  images: ['./src/i/**'],

  // SVG icons
  svg: ['./src/svg/**/*.svg'],

  // Outputs
  jsOutput: 'main.js',
  cssOutput: 'styles.css',

  // Destinations
  jsDest: './gui/js/',
  cssDest: './gui/css/',
  imgDest: './gui/i',
  svgDest: './_includes/',

  // Jekyll build files
  jekyllHTML: ['./_site/**/*.html'],

  // Jekyll build triggers
  jekyllBuild: [
    '**/*.html',
    '**/*.+(md|markdown|MD)',
    'src/**/*.*',
    '_data/**.*+(yml|yaml|csv|json)',
    '!dist/**/*.*',
    '!_site/**/*.*',
    '!README.md'
  ]

};

// Error handler
var onError = function (err) {
  gutil.beep();
  console.log(err);
};

// Check for production
var isProduction = process.env.NODE_ENV === 'production';

// Process stylesheets
gulp.task('css', function () {
  return gulp.src(paths.cssFiles)
    .pipe(plumber({
      errorHandler: onError
    }))
    .pipe(stylelint({
      reporters: [{
        formatter: 'string',
        console: true
      }]
    }))
    .pipe(sourcemaps.init())
    .pipe(autoprefixer({
      browsers: ['last 2 versions'],
      cascade: false
    }))
    .pipe(postcss([customProperties()]))
    .pipe(concat(paths.cssOutput))
    .pipe(cssnano({
      discardComments: { removeAll: true }
    }))
    .pipe(hashsum({ filename: './_data/cache_bust_css.yml', hash: 'md5' }))
    .pipe(gulpif(!isProduction, sourcemaps.write()))
    .pipe(gulp.dest(paths.cssDest));
});

// Concatenate and minify JavaScript
gulp.task('js', function () {
  return gulp.src(paths.jsFiles)
    .pipe(plumber({
      errorHandler: onError
    }))
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(sourcemaps.init())
    .pipe(concat(paths.jsOutput))
    .pipe(uglify())
    .pipe(hashsum({ filename: './_data/cache_bust_js.yml', hash: 'md5' }))
    .pipe(gulpif(!isProduction, sourcemaps.write('.')))
    .pipe(gulp.dest(paths.jsDest));
});

// SVG sprite generation
var svgConfig = {
  svg: {
    doctypeDeclaration: false,
    xmlDeclaration: false
  },
  mode: {
    symbol: {
      inline: true,
      dest: '.',
      sprite: 'sprite-symbol.svg'
    }
  }
};

gulp.task('svg-sprite', function () {
  return gulp.src(paths.svg)
    .pipe(svgSprite(svgConfig))
    .pipe(gulp.dest(paths.svgDest));
    // .pipe(gulp.dest(paths.imgDest));
});

// eslint
gulp.task('eslint', function () {
  return gulp.src(paths.jsFiles)
    .pipe(plumber({
      errorHandler: onError
    }))
    .pipe(eslint())
    .pipe(eslint.format());
});

// Watch for changes
gulp.task('watch', function () {
  watch(paths.cssFiles, function () {
    gulp.start(['css']);
  });
  watch(paths.jsFiles, function () {
    gulp.start(['js', 'eslint']);
  });
  watch(paths.images, function () {
    gulp.start(['images']);
  });
  watch(paths.svg, function () {
    gulp.start(['svg-sprite']);
  });
  watch(paths.jekyllBuild, function () {
    gulp.start(['jekyll-build']);
  });
});

// Copy image assets to /gui
gulp.task('images', function () {
  syncy(paths.images, paths.imgDest, {
    base: './src/i/'
  })
    .catch(console.error);
});

// Jekyll
gulp.task('jekyll-build', function () {
  gulpif(!isProduction, exec('bundle exec jekyll build -q', function (err) {
    if (err) {
      console.log(err);
    }
  }));
});

// Live server
gulp.task('live-server', function () {
  liveServer.start({
    port: 4000,
    host: '0.0.0.0',
    root: '_site',
    open: false,
    quiet: true,
    file: 'index.html',
    wait: 500
  });
});

// Build
gulp.task('build', ['css', 'js', 'images', 'svg-sprite', 'jekyll-build']);

// Deploy
gulp.task('deploy', ['css', 'js', 'images', 'svg-sprite']);

// Default
gulp.task('default', ['build', 'watch', 'live-server']);
<commit_msg>Remove commented line<commit_after>/**
 * gulpfile.js
 *
 * All the yummy build stuff!
 *
 * @author Fredrik Frodlund (contact@frippz.se)
 */

// Requirements
var gulp             = require('gulp'),
    gulpif           = require('gulp-if'),
    gutil            = require('gulp-util'),
    plumber          = require('gulp-plumber'),
    sourcemaps       = require('gulp-sourcemaps'),
    autoprefixer     = require('gulp-autoprefixer'),
    cssnano          = require('gulp-cssnano'),
    concat           = require('gulp-concat'),
    uglify           = require('gulp-uglify'),
    postcss          = require('gulp-postcss'),
    watch            = require('gulp-watch'),
    customProperties = require('postcss-custom-properties'),
    eslint           = require('gulp-eslint'),
    liveServer       = require('live-server'),
    syncy            = require('syncy'),
    hashsum          = require('gulp-hashsum'),
    stylelint        = require('gulp-stylelint'),
    svgSprite        = require('gulp-svg-sprite'),
    exec             = require('child_process').exec;

// Configur paths
var paths = {

  // Inputs
  jsFiles: ['./src/js/**/*.js'],
  cssFiles: ['./src/css/**/*.css'],

  // Static assets
  images: ['./src/i/**'],

  // SVG icons
  svg: ['./src/svg/**/*.svg'],

  // Outputs
  jsOutput: 'main.js',
  cssOutput: 'styles.css',

  // Destinations
  jsDest: './gui/js/',
  cssDest: './gui/css/',
  imgDest: './gui/i',
  svgDest: './_includes/',

  // Jekyll build files
  jekyllHTML: ['./_site/**/*.html'],

  // Jekyll build triggers
  jekyllBuild: [
    '**/*.html',
    '**/*.+(md|markdown|MD)',
    'src/**/*.*',
    '_data/**.*+(yml|yaml|csv|json)',
    '!dist/**/*.*',
    '!_site/**/*.*',
    '!README.md'
  ]

};

// Error handler
var onError = function (err) {
  gutil.beep();
  console.log(err);
};

// Check for production
var isProduction = process.env.NODE_ENV === 'production';

// Process stylesheets
gulp.task('css', function () {
  return gulp.src(paths.cssFiles)
    .pipe(plumber({
      errorHandler: onError
    }))
    .pipe(stylelint({
      reporters: [{
        formatter: 'string',
        console: true
      }]
    }))
    .pipe(sourcemaps.init())
    .pipe(autoprefixer({
      browsers: ['last 2 versions'],
      cascade: false
    }))
    .pipe(postcss([customProperties()]))
    .pipe(concat(paths.cssOutput))
    .pipe(cssnano({
      discardComments: { removeAll: true }
    }))
    .pipe(hashsum({ filename: './_data/cache_bust_css.yml', hash: 'md5' }))
    .pipe(gulpif(!isProduction, sourcemaps.write()))
    .pipe(gulp.dest(paths.cssDest));
});

// Concatenate and minify JavaScript
gulp.task('js', function () {
  return gulp.src(paths.jsFiles)
    .pipe(plumber({
      errorHandler: onError
    }))
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(sourcemaps.init())
    .pipe(concat(paths.jsOutput))
    .pipe(uglify())
    .pipe(hashsum({ filename: './_data/cache_bust_js.yml', hash: 'md5' }))
    .pipe(gulpif(!isProduction, sourcemaps.write('.')))
    .pipe(gulp.dest(paths.jsDest));
});

// SVG sprite generation
var svgConfig = {
  svg: {
    doctypeDeclaration: false,
    xmlDeclaration: false
  },
  mode: {
    symbol: {
      inline: true,
      dest: '.',
      sprite: 'sprite-symbol.svg'
    }
  }
};

gulp.task('svg-sprite', function () {
  return gulp.src(paths.svg)
    .pipe(svgSprite(svgConfig))
    .pipe(gulp.dest(paths.svgDest));
});

// eslint
gulp.task('eslint', function () {
  return gulp.src(paths.jsFiles)
    .pipe(plumber({
      errorHandler: onError
    }))
    .pipe(eslint())
    .pipe(eslint.format());
});

// Watch for changes
gulp.task('watch', function () {
  watch(paths.cssFiles, function () {
    gulp.start(['css']);
  });
  watch(paths.jsFiles, function () {
    gulp.start(['js', 'eslint']);
  });
  watch(paths.images, function () {
    gulp.start(['images']);
  });
  watch(paths.svg, function () {
    gulp.start(['svg-sprite']);
  });
  watch(paths.jekyllBuild, function () {
    gulp.start(['jekyll-build']);
  });
});

// Copy image assets to /gui
gulp.task('images', function () {
  syncy(paths.images, paths.imgDest, {
    base: './src/i/'
  })
    .catch(console.error);
});

// Jekyll
gulp.task('jekyll-build', function () {
  gulpif(!isProduction, exec('bundle exec jekyll build -q', function (err) {
    if (err) {
      console.log(err);
    }
  }));
});

// Live server
gulp.task('live-server', function () {
  liveServer.start({
    port: 4000,
    host: '0.0.0.0',
    root: '_site',
    open: false,
    quiet: true,
    file: 'index.html',
    wait: 500
  });
});

// Build
gulp.task('build', ['css', 'js', 'images', 'svg-sprite', 'jekyll-build']);

// Deploy
gulp.task('deploy', ['css', 'js', 'images', 'svg-sprite']);

// Default
gulp.task('default', ['build', 'watch', 'live-server']);
<|endoftext|>


<commit_before>jQuery(document).ready(function() {

    var windowWidth = $(window).width();
    $(window).on('load resize', function(){
        updateReadingBar();
        updateActiveMenuItem();

        windowWidth = $(window).width();

        if(windowWidth > 998){
            if($('.chapter-links').length){
                $('.chapter-links').css('display','inline-block');
                if($('.chapter-links').hasClass('open')){
                    $('.chapter-links').removeClass('open');
                    $('.fa').toggleClass('fa-chevron-down fa-chevron-up');
                }
            }
        }
        if(windowWidth < 998){
            if($('.chapter-links').length && (!($('.chapter-links').hasClass('open')))){
                $('.chapter-links').css('display', 'none');
            }
        }
    });

    if($('.feature-image-overlay').length){
        $('.feature-image-overlay').css('opacity', '0');
    }

    $('#mobile-chapter-menu').click(function(e) {
        $('.chapter-links').slideToggle().toggleClass('open');
        $('.fa').toggleClass('fa-chevron-down fa-chevron-up');
    });

    if($('.story .block-RelatedItems').length){
        $('.story').before( '

' );
        setRelatedMenu();
        $('.related-content-menu').click(function(e){
            $('.story .block-RelatedItems').slideToggle();
            $('.story .block-RelatedItems').closest('.container-clear-none').addClass('open');
            $('.related-content-menu i').toggleClass('fa-close fa-bars');
        });
    }

    function setRelatedMenu(){
        if($('.related-content-menu').length){
            var fromTop = $('.related-content-menu').offset().top - $(window).scrollTop() - 200;
            //console.log($(window).scrollTop() + ' ' + fromTop);
            var windowPosition = $(window).scrollTop();
            if(fromTop <= 0){
                $('.related-content-menu').addClass('fixed');
                $('.story .container-clear-none').addClass('fixed');
            }
            if(windowPosition < 550){
                $('.related-content-menu').removeClass('fixed');
                $('.story .container-clear-none').removeClass('fixed');
            }
        }
    }

    function unsetRelatedMenu(){
        if($('footer .block-RelatedItems').length){
            var fromBottom = $('footer').offset().top - $(window).scrollTop();
            if(fromBottom < 350){
                $('.related-content-menu').removeClass('fixed');
                $('.story .container-clear-none').removeClass('fixed');
            }
        }
    }

    function updateReadingBar() {
        var s = $(window).scrollTop(); // Current scroll mark
        ap = $('#article-page').last();
        s = s - ap.position().top; // Start counting at the top of the article
        d = ap.height(); // The end of the article page element
        c = $(window).height(); // Height of the element
        scrollPercent = (s / (d-c)) * 100;
        if (scrollPercent > 100) scrollPercent = 100;
        else if (scrollPercent < 0) scrollPercent = 0;
        $('.readingbar').width(scrollPercent + '%');
    }

    /*** update selected chapter in header menu on scroll */
    function updateActiveMenuItem() {
       // Get container scroll position
       var fromTop = $(this).scrollTop() + chapterMenuHeight;

       // Get id of current scroll item
       var cur = scrollItems.map(function(){
         if ($(this).offset().top < fromTop)
           return this;
       });
       // Get the id of the current element
       cur = cur[cur.length-1];
       var id = cur && cur.length ? cur[0].id : "";
       // Set/remove active class
       menuItems
         .parent().removeClass("active")
         .end().filter("[href='#"+id+"']").parent().addClass("active");
    }

    // Keeping track of position in article to update active page in menu
    var chapterMenu = $(".chapter-links ul"),
        chapterMenuHeight = chapterMenu.outerHeight(),
        // All list items
        menuItems = chapterMenu.find("a"),
        // Anchors corresponding to menu items
        scrollItems = menuItems.map(function(){
          var item = $($(this).attr("href"));
          if (item.length) { return item; }
        });

    // Bind click handler to menu items to scroll down to chapter on page
    menuItems.click(function(e){
      var href = $(this).attr("href"),
          offsetTop = href === "#" ? 0 : $(href).offset().top-chapterMenuHeight+1;
      $('html, body').stop().animate({
          scrollTop: offsetTop
      }, 300);
      e.preventDefault();
    });

// Bind to scroll
    $(window).scroll(function(){
       updateReadingBar();
       updateActiveMenuItem();
       setRelatedMenu();
       unsetRelatedMenu();
    });

//close related items menu if body is clicked
    $(window).click(function(e) {
        if(!$(e.target).closest('.story .block-RelatedItems').length && !$(e.target).closest('.related-content-menu').length) {
            if($('.story .block-RelatedItems').is(":visible")) {
                $('.story .block-RelatedItems').slideToggle();
                $('.related-content-menu i').toggleClass('fa-close fa-bars');

            }
        }
    });

});
<commit_msg>incase overlay is open when transitioning to small screen hide it<commit_after>jQuery(document).ready(function() {

    var windowWidth = $(window).width();
    $(window).on('load resize', function(){
        updateReadingBar();
        updateActiveMenuItem();
        windowWidth = $(window).width();

        if(windowWidth > 998){
            if($('.chapter-links').length){
                $('.chapter-links').css('display','inline-block');
                if($('.chapter-links').hasClass('open')){
                    $('.chapter-links').removeClass('open');
                    $('.fa').toggleClass('fa-chevron-down fa-chevron-up');
                }
            }
        }
        if(windowWidth < 998){
            if($('.chapter-links').length && (!($('.chapter-links').hasClass('open')))){
                $('.chapter-links').css('display', 'none');
            }
        }
        if(windowWidth < 768){
            if($('.story .block-RelatedItems').is(':visible')){
                $('.story .block-RelatedItems').hide();
                $('.related-content-menu i').toggleClass('fa-close fa-bars');
            }
        }
    });

    if($('.feature-image-overlay').length){
        $('.feature-image-overlay').css('opacity', '0');
    }

    $('#mobile-chapter-menu').click(function(e) {
        $('.chapter-links').slideToggle().toggleClass('open');
        $('.fa').toggleClass('fa-chevron-down fa-chevron-up');
    });

    if($('.story .block-RelatedItems').length){
        $('.story').before( '

' );
        setRelatedMenu();
        $('.related-content-menu').click(function(e){
            $('.story .block-RelatedItems').slideToggle();
            $('.story .block-RelatedItems').closest('.container-clear-none').addClass('open');
            $('.related-content-menu i').toggleClass('fa-close fa-bars');
        });
    }

    function setRelatedMenu(){
        if($('.related-content-menu').length){
            var fromTop = $('.related-content-menu').offset().top - $(window).scrollTop() - 200;
            //console.log($(window).scrollTop() + ' ' + fromTop);
            var windowPosition = $(window).scrollTop();
            if(fromTop <= 0){
                $('.related-content-menu').addClass('fixed');
                $('.story .container-clear-none').addClass('fixed');
            }
            if(windowPosition < 550){
                $('.related-content-menu').removeClass('fixed');
                $('.story .container-clear-none').removeClass('fixed');
            }
        }
    }

    function unsetRelatedMenu(){
        if($('footer .block-RelatedItems').length){
            var fromBottom = $('footer').offset().top - $(window).scrollTop();
            if(fromBottom < 350){
                $('.related-content-menu').removeClass('fixed');
                $('.story .container-clear-none').removeClass('fixed');
            }
        }
    }

    function updateReadingBar() {
        var s = $(window).scrollTop(); // Current scroll mark
        ap = $('#article-page').last();
        s = s - ap.position().top; // Start counting at the top of the article
        d = ap.height(); // The end of the article page element
        c = $(window).height(); // Height of the element
        scrollPercent = (s / (d-c)) * 100;
        if (scrollPercent > 100) scrollPercent = 100;
        else if (scrollPercent < 0) scrollPercent = 0;
        $('.readingbar').width(scrollPercent + '%');
    }

    /*** update selected chapter in header menu on scroll */
    function updateActiveMenuItem() {
       // Get container scroll position
       var fromTop = $(this).scrollTop() + chapterMenuHeight;

       // Get id of current scroll item
       var cur = scrollItems.map(function(){
         if ($(this).offset().top < fromTop)
           return this;
       });
       // Get the id of the current element
       cur = cur[cur.length-1];
       var id = cur && cur.length ? cur[0].id : "";
       // Set/remove active class
       menuItems
         .parent().removeClass("active")
         .end().filter("[href='#"+id+"']").parent().addClass("active");
    }

    // Keeping track of position in article to update active page in menu
    var chapterMenu = $(".chapter-links ul"),
        chapterMenuHeight = chapterMenu.outerHeight(),
        // All list items
        menuItems = chapterMenu.find("a"),
        // Anchors corresponding to menu items
        scrollItems = menuItems.map(function(){
          var item = $($(this).attr("href"));
          if (item.length) { return item; }
        });

    // Bind click handler to menu items to scroll down to chapter on page
    menuItems.click(function(e){
      var href = $(this).attr("href"),
          offsetTop = href === "#" ? 0 : $(href).offset().top-chapterMenuHeight+1;
      $('html, body').stop().animate({
          scrollTop: offsetTop
      }, 300);
      e.preventDefault();
    });

// Bind to scroll
    $(window).scroll(function(){
       updateReadingBar();
       updateActiveMenuItem();
       setRelatedMenu();
       unsetRelatedMenu();
    });

//close related items menu if body is clicked
    $(window).click(function(e) {
        if(!$(e.target).closest('.story .block-RelatedItems').length && !$(e.target).closest('.related-content-menu').length) {
            if($('.story .block-RelatedItems').is(":visible")) {
                $('.story .block-RelatedItems').slideToggle();
                $('.related-content-menu i').toggleClass('fa-close fa-bars');

            }
        }
    });

});
<|endoftext|>


<commit_before>(function(define) {'use strict';
define(function(require) {

   /**
    * Mixes into the first argument (`target`) the key-values of
    * all subsequent arguments, in the given order. Later assignments
    * will overwrite the earlier ones.
    */
   var mixin = function mixin(target) {
      Array.prototype.slice.call(arguments, 1)
         .forEach(function(source) {
            Object.keys(source || {}).forEach(function(key) {
               target[key] = source[key];
            });
         });
      return target;
   };

   /**
    * Perform a deeper mixin, where objects and arrays are
    * recursively cloned. It will however not descend into
    * the entries of an array, and will assume they are
    * primitive values (numbers/strings/booleans).
    */
   mixin.deep = function(target) {
      Array.prototype.slice.call(arguments, 1)
         .forEach(function(source) {
            Object.keys(source || {}).forEach(function(key) {
               if (Array.isArray(source[key])) {
                  target[key] = source[key].slice();
               } else if (typeof source[key] === 'object') {
                  target[key] = mixin.deep({}, source[key]);
               } else {
                  target[key] = source[key];
               }
            });
         });
      return target;
   };

   return mixin;

});

}(typeof define === 'function' && define.amd ? define : function(factory) {
   'use strict';
   module.exports = factory(require);
}));
<commit_msg>Add mixin.existing<commit_after>(function(define) {'use strict';
define(function(require) {

   /**
    * Mixes into the first argument (`target`) the key-values of
    * all subsequent arguments, in the given order. Later assignments
    * will overwrite the earlier ones.
    */
   var mixin = function mixin(target) {
      Array.prototype.slice.call(arguments, 1)
         .forEach(function(source) {
            Object.keys(source || {}).forEach(function(key) {
               target[key] = source[key];
            });
         });
      return target;
   };

   /**
    * Perform a deeper mixin, where objects and arrays are
    * recursively cloned. It will however not descend into
    * the entries of an array, and will assume they are
    * primitive values (numbers/strings/booleans).
    */
   mixin.deep = function(target) {
      Array.prototype.slice.call(arguments, 1)
         .forEach(function(source) {
            Object.keys(source || {}).forEach(function(key) {
               if (Array.isArray(source[key])) {
                  target[key] = source[key].slice();
               } else if (typeof source[key] === 'object') {
                  target[key] = mixin.deep({}, source[key]);
               } else {
                  target[key] = source[key];
               }
            });
         });
      return target;
   };

   /**
    * Like regular mixin, but only mixes for the keys which already exist
    * in `target`. Later assignments will overwrite the earlier ones.
    */
   mixin.existing = function(target) {
      Array.prototype.slice.call(arguments, 1)
         .forEach(function(source) {
            Object.keys(source || {}).forEach(function(key) {
               if (target.hasOwnProperty(key)) {
                     target[key] = source[key];
               }
            });
         });
      return target;
   };

   return mixin;

});

}(typeof define === 'function' && define.amd ? define : function(factory) {
   'use strict';
   module.exports = factory(require);
}));
<|endoftext|>


<commit_before>'use strict';

var request = require('request');
var urljoin = require('url-join');
var _ = require('lodash');
var async = require('async');

module.exports = function(config) {
  var interceptors = [];

  var api = _.mapValues(config.resources, function (routes, key) {
    return _.mapValues(routes, function(route){
      return function (params, data, cb) {
        if (typeof params === 'function') {
          cb = params;
          params = {};
          data = {};
        }
        else if (typeof data === 'function') {
          cb = data;
          data = {};
        }

        cb = cb || _.noop;

        var routePath = route.path;

        _.forEach(params, function(value, key) {
          routePath = routePath.replace(':'+key, value);
        });

        var requestObject = {
          uri: urljoin(config.host, key, routePath),
          method: route.method,
          json: data
        };

        var requests = [function (cb) {
          cb(null, requestObject);
        }].concat(_.pluck(_.filter(interceptors, 'request'), 'request'));

        async.waterfall(requests, function(err, interceptedRequest){
          if(err) {
            return cb(err);
          }

          request(interceptedRequest, function (err, response, body) {
            if (err) {
              return cb(err);
            }
            var responseObject = {response: response, body: body};

            var responses = [function (cb) {
              cb(null, responseObject);
            }].concat(_.pluck(_.filter(interceptors, 'response'), 'response'));

            async.waterfall(responses, function (err, interceptedResponse) {
              if (err) {
                return cb(err);
              }

              if (interceptedResponse.statusCode === 500) {
                return cb(responseObject);
              }

              cb(null, interceptedResponse.body);
            });

            interceptors.shift();
          });
        });
      };
    });
  });

  return _.merge(api, {
    inject: function(interceptor)
    {
      if(!interceptor || (!interceptor.request && !interceptor.response) ) {
        throw new Error('This is not a valid interceptor, it must contain request or response');
      }

      interceptors.push(interceptor);
    }
  });
};<commit_msg>fixed error checking<commit_after>'use strict';

var request = require('request');
var urljoin = require('url-join');
var _ = require('lodash');
var async = require('async');

module.exports = function(config) {
  var interceptors = [];

  var api = _.mapValues(config.resources, function (routes, key) {
    return _.mapValues(routes, function(route){
      return function (params, data, cb) {
        if (typeof params === 'function') {
          cb = params;
          params = {};
          data = {};
        }
        else if (typeof data === 'function') {
          cb = data;
          data = {};
        }

        cb = cb || _.noop;

        var routePath = route.path;

        _.forEach(params, function(value, key) {
          routePath = routePath.replace(':'+key, value);
        });

        var requestObject = {
          uri: urljoin(config.host, key, routePath),
          method: route.method,
          json: data
        };

        var requests = [function (cb) {
          cb(null, requestObject);
        }].concat(_.pluck(_.filter(interceptors, 'request'), 'request'));

        async.waterfall(requests, function(err, interceptedRequest){
          if(err) {
            return cb(err);
          }

          request(interceptedRequest, function (err, response, body) {
            if (err) {
              return cb(err);
            }
            var responseObject = {response: response, body: body};

            var responses = [function (cb) {
              cb(null, responseObject);
            }].concat(_.pluck(_.filter(interceptors, 'response'), 'response'));

            async.waterfall(responses, function (err, interceptedResponse) {
              if (err) {
                return cb(err);
              }

              if (interceptedResponse.response.statusCode >= 400) {
                return cb(responseObject);
              }

              cb(null, interceptedResponse.body);
            });

            interceptors.shift();
          });
        });
      };
    });
  });

  return _.merge(api, {
    inject: function(interceptor)
    {
      if(!interceptor || (!interceptor.request && !interceptor.response) ) {
        throw new Error('This is not a valid interceptor, it must contain request or response');
      }

      interceptors.push(interceptor);
    }
  });
};<|endoftext|>


<commit_before>exports.show_list = function(head, req) {
    var row;
    start({
        code: 200,
        headers: {
            'Content-Type': 'text/json; charset=utf-8',
        }
    });
    while (row = getRow()) {
        if (row.key === req.query.l) {
            send(JSON.stringify(row.value) + "\n");
        }
    }
};<commit_msg>List view now outputs an enum for the list items. Sorted by the 'order' property<commit_after>exports.show_list = function(head, req) {
    var row;
    start({
        code: 200,
        headers: {
            'Content-Type': 'text/json; charset=utf-8',
        }
    });
    send('{"$schema": "http://json-schema.org/draft-04/schema#",\n "type": "object", \n"properties": \n{ "thelist": {\n"type":"string", \n"enum ": [\n');
    while (row = getRow()) {
        if (row.key === req.query.l) {
            send(JSON.stringify(row.value.name) + ",\n");
        }
    }
    send("]\n}\n}\n}");
};<|endoftext|>


<commit_before>// dna.js
// gulp configuration and tasks

const gulp =        require('gulp');
const fileInclude = require('gulp-file-include');
const filesize =    require('gulp-filesize');
const header =      require('gulp-header');
const htmlHint =    require('gulp-htmlhint');
const jsHint =      require('gulp-jshint');
const rename =      require('gulp-rename');
const replace =     require('gulp-replace');
const uglify =      require('gulp-uglify');
const w3cjs =       require('gulp-w3cjs');
const del =         require('del');

const webContext = {
   pkg:  require('./package.json'),
   size: '16 kb',
   youTube: {
      intro:    'jMOZOI-UkNI',
      tutorial: 'juIru5qHZFM'
      },
   jsFiddle: {
      addABook:       'eo3gpfmo',
      bookFinder:     'zxb2x6dv',
      dataClick:      '5dsbvacd',
      liveModel:      '8gnyLovu',
      panelsClick:    'uzm44vrf',
      panelsDropDown: 'qt95wt46',
      smartUpdates:   '4a0tpmxp',
      toDo:           'wo6og0z8'
      }
   };
webContext.title = 'dna.js';  //default page title
const banner = '//dna.js v' + webContext.pkg.version + ' ~~ dnajs.org/license\n';
const versionPatternStrs = [
   'dna[.]js v',     //example (dna.css):      /* dna.js v1.0.0 ~~ dnajs.org/license */
   "version:\\s*'",  //example (dna.js):       version: '1.0.0',
   '"version":\\s*"' //example (package.json): "version":  "1.0.0",
   ];
const versionPatterns = new RegExp('(' + versionPatternStrs.join('|') + ')[0-9.]*', 'g');
const httpdocsFolder = 'website/httpdocs';
const htmlHintConfig = { 'attr-value-double-quotes': false };
const jsHintConfig = {
   strict: 'implied',
   undef:  true,
   unused: true,
   jquery: true,
   node:   true,
   mocha:  true,
   globals: {
      app:     false,
      console: false,
      $:       true,
      window:  true
      }
   };
const jsHintConfigEs6 = Object.assign({}, jsHintConfig, { esversion: 6 });

function setVersionNumber() {
   const stream = gulp.src(['dna.js', 'dna.css'])
      .pipe(replace(versionPatterns, '$1' + webContext.pkg.version))
      .pipe(gulp.dest('.'));
   return stream;
   }

function runJsHint() {
   gulp.src(['dna.js', 'website/*.js'])
      .pipe(jsHint(jsHintConfig))
      .pipe(jsHint.reporter());
   gulp.src(['gulpfile.js', 'spec.js'])
      .pipe(jsHint(jsHintConfigEs6))
      .pipe(jsHint.reporter());
   }

function runUglify() {
   gulp.src('dna.js')
      .pipe(rename('dna.min.js'))
      .pipe(uglify())
      .pipe(header(banner))
      .pipe(gulp.dest('.'));
   }

function reportSize() {
   gulp.src('dna.*')
      .pipe(filesize());
   }

function cleanWebsite() {
    return del(httpdocsFolder + '/**');
    }

function buildWebsite() {
   const findToDoLine = /.*To-Do Application.*/;
   const findIntroLine = /.*Introduction to dna.js.*/;
   const newToDoLine =
      '* [Sample To-Do Application](http://jsfiddle.net/' + webContext.jsFiddle.toDo + '/) (jsfiddle)';
   const newIntroLine =
      '* [Introduction to dna.js](https://youtu.be/' + webContext.youTube.intro + ') (YouTube)';
   gulp.src('README.md')
      .pipe(replace(findToDoLine,  newToDoLine))
      .pipe(replace(findIntroLine, newIntroLine))
      .pipe(filesize())
      .pipe(gulp.dest('.'));
   gulp.src('website/static/**')
      .pipe(gulp.dest(httpdocsFolder));
   gulp.src(['website/static/**/*.html', 'spec/visual.html'])
      .pipe(w3cjs())
      .pipe(w3cjs.reporter())
      .pipe(htmlHint(htmlHintConfig))
      .pipe(htmlHint.reporter());
   gulp.src('website/root/**/*.html')
      .pipe(fileInclude({ basepath: '@root', indent: true, webContext: webContext }))
      .pipe(w3cjs())
      .pipe(w3cjs.reporter())
      .pipe(htmlHint(htmlHintConfig))
      .pipe(htmlHint.reporter())
      .pipe(gulp.dest(httpdocsFolder));
   }

gulp.task('set-version', setVersionNumber);
gulp.task('lint',        runJsHint);
gulp.task('minify',      ['set-version'], runUglify);
gulp.task('build',       ['lint', 'minify'], reportSize);
gulp.task('clean-web',   cleanWebsite);
gulp.task('web',         ['clean-web'], buildWebsite);
<commit_msg>Fix web context variables<commit_after>// dna.js
// gulp configuration and tasks

const gulp =        require('gulp');
const fileInclude = require('gulp-file-include');
const filesize =    require('gulp-filesize');
const header =      require('gulp-header');
const htmlHint =    require('gulp-htmlhint');
const jsHint =      require('gulp-jshint');
const rename =      require('gulp-rename');
const replace =     require('gulp-replace');
const uglify =      require('gulp-uglify');
const w3cjs =       require('gulp-w3cjs');
const del =         require('del');

const webContext = {
   pkg:  require('./package.json'),
   size: '16 kb',
   youTube: {
      intro:    'jMOZOI-UkNI',
      tutorial: 'juIru5qHZFM'
      },
   jsFiddle: {
      addABook:       'eo3gpfmo',
      bookFinder:     'zxb2x6dv',
      dataClick:      '5dsbvacd',
      liveModel:      '8gnyLovu',
      panelsClick:    'uzm44vrf',
      panelsDropDown: 'qt95wt46',
      smartUpdates:   '4a0tpmxp',
      toDo:           'wo6og0z8'
      }
   };
webContext.title = 'dna.js';  //default page title
const banner = '//dna.js v' + webContext.pkg.version + ' ~~ dnajs.org/license\n';
const versionPatternStrs = [
   'dna[.]js v',     //example (dna.css):      /* dna.js v1.0.0 ~~ dnajs.org/license */
   "version:\\s*'",  //example (dna.js):       version: '1.0.0',
   '"version":\\s*"' //example (package.json): "version":  "1.0.0",
   ];
const versionPatterns = new RegExp('(' + versionPatternStrs.join('|') + ')[0-9.]*', 'g');
const httpdocsFolder = 'website/httpdocs';
const htmlHintConfig = { 'attr-value-double-quotes': false };
const jsHintConfig = {
   strict: 'implied',
   undef:  true,
   unused: true,
   jquery: true,
   node:   true,
   mocha:  true,
   globals: {
      app:     false,
      console: false,
      $:       true,
      window:  true
      }
   };
const jsHintConfigEs6 = Object.assign({}, jsHintConfig, { esversion: 6 });

function setVersionNumber() {
   const stream = gulp.src(['dna.js', 'dna.css'])
      .pipe(replace(versionPatterns, '$1' + webContext.pkg.version))
      .pipe(gulp.dest('.'));
   return stream;
   }

function runJsHint() {
   gulp.src(['dna.js', 'website/*.js'])
      .pipe(jsHint(jsHintConfig))
      .pipe(jsHint.reporter());
   gulp.src(['gulpfile.js', 'spec.js'])
      .pipe(jsHint(jsHintConfigEs6))
      .pipe(jsHint.reporter());
   }

function runUglify() {
   gulp.src('dna.js')
      .pipe(rename('dna.min.js'))
      .pipe(uglify())
      .pipe(header(banner))
      .pipe(gulp.dest('.'));
   }

function reportSize() {
   gulp.src('dna.*')
      .pipe(filesize());
   }

function cleanWebsite() {
    return del(httpdocsFolder + '/**');
    }

function buildWebsite() {
   const findToDoLine = /.*To-Do Application.*/;
   const findIntroLine = /.*Introduction to dna.js.*/;
   const newToDoLine =
      '* [Sample To-Do Application](http://jsfiddle.net/' + webContext.jsFiddle.toDo + '/) (jsfiddle)';
   const newIntroLine =
      '* [Introduction to dna.js](https://youtu.be/' + webContext.youTube.intro + ') (YouTube)';
   gulp.src('README.md')
      .pipe(replace(findToDoLine,  newToDoLine))
      .pipe(replace(findIntroLine, newIntroLine))
      .pipe(filesize())
      .pipe(gulp.dest('.'));
   gulp.src('website/static/**')
      .pipe(gulp.dest(httpdocsFolder));
   gulp.src(['website/static/**/*.html', 'spec/visual.html'])
      .pipe(w3cjs())
      .pipe(w3cjs.reporter())
      .pipe(htmlHint(htmlHintConfig))
      .pipe(htmlHint.reporter());
   gulp.src('website/root/**/*.html')
      .pipe(fileInclude({ basepath: '@root', indent: true, context: webContext }))
      .pipe(w3cjs())
      .pipe(w3cjs.reporter())
      .pipe(htmlHint(htmlHintConfig))
      .pipe(htmlHint.reporter())
      .pipe(gulp.dest(httpdocsFolder));
   }

gulp.task('set-version', setVersionNumber);
gulp.task('lint',        runJsHint);
gulp.task('minify',      ['set-version'], runUglify);
gulp.task('build',       ['lint', 'minify'], reportSize);
gulp.task('clean-web',   cleanWebsite);
gulp.task('web',         ['clean-web'], buildWebsite);
<|endoftext|>


<commit_before>import getFiles from './get-files';
import hash from './hash';
import retry from './retry';
import Agent from './agent';
import EventEmitter from 'events';
import { resolve } from 'path';
import { stat, readFile } from 'fs-promise';

export default class Now extends EventEmitter {
  constructor (token, { forceNew = false, debug = false }) {
    super();
    this._token = token;
    this._debug = debug;
    this._forceNew = forceNew;
    this._agent = new Agent('api.now.sh', { debug });
    this._onRetry = this._onRetry.bind(this);
  }

  async create (path, { forceNew }) {
    this._path = path;

    try {
      await stat(path);
    } catch (err) {
      throw new Error(`Could not read directory ${path}.`);
    }

    let pkg;
    try {
      pkg = await readFile(resolve(path, 'package.json'));
      pkg = JSON.parse(pkg);
    } catch (err) {
      throw new Error(`Failed to read JSON in "${path}/package.json"`);
    }

    if (this._debug) console.time('> [debug] Getting files');
    const files = await getFiles(path, pkg);
    if (this._debug) console.timeEnd('> [debug] Getting files');

    if (this._debug) console.time('> [debug] Computing hashes');
    const hashes = await hash(files);
    if (this._debug) console.timeEnd('> [debug] Computing hashes');

    this._files = hashes;

    const deployment = await retry(async (bail) => {
      const res = await this._fetch('/create', {
        method: 'POST',
        body: {
          forceNew,
          files: Array.from(this._files).map(([sha, { data }]) => {
            return {
              sha,
              size: Buffer.byteLength(data)
            };
          })
        }
      });

      // no retry on 403
      if (403 === res.status) {
        if (this._debug) {
          console.log('> [debug] bailing on creating due to 403');
        }
        return bail(responseError(res));
      }

      if (200 !== res.status) {
        throw new Error('Deployment initialization failed');
      }

      return res.json();
    }, { retries: 3, minTimeout: 2500, onRetry: this._onRetry });

    this._id = deployment.deploymentId;
    this._url = deployment.url;
    this._missing = deployment.missing || [];

    return this._url;
  }

  upload () {
    Promise.all(this._missing.map((sha) => retry(async (bail) => {
      const file = this._files.get(sha);
      const { data, name } = file;
      const res = await this._fetch('/sync', {
        method: 'POST',
        body: {
          sha,
          data,
          file: toRelative(name, this._path),
          deploymentId: this._id
        }
      });

      // no retry on 403
      if (403 === res.status) {
        if (this._debug) console.log('> [debug] bailing on creating due to 403');
        return bail(responseError(res));
      }

      this.emit('upload', file);
    }, { retries: 5, randomize: true, onRetry: this._onRetry })))
    .then(() => this.emit('complete'))
    .catch((err) => this.emit('error', err));
  }

  _onRetry (err) {
    if (this._debug) {
      console.log(`> [debug] Retrying: ${err.stack}`);
    }
  }

  close () {
    this._agent.close();
  }

  get url () {
    return this._url;
  }

  get syncAmount () {
    if (!this._syncAmount) {
      this._syncAmount = this._missing
      .map((sha) => Buffer.byteLength(this._files.get(sha).data))
      .reduce((a, b) => a + b, 0);
    }
    return this._syncAmount;
  }

  async _fetch (url, opts) {
    opts.headers = opts.headers || {};
    opts.headers.authorization = `Bearer ${this._token}`;
    return await this._agent.fetch(url, opts);
  }
}

function toRelative (path, base) {
  const fullBase = /\/$/.test(base) ? base + '/' : base;
  return path.substr(fullBase.length);
}

function responseError (res) {
  const err = new Error('Response error');
  err.status = res.status;
  return err;
}
<commit_msg>Send data as string<commit_after>import getFiles from './get-files';
import hash from './hash';
import retry from './retry';
import Agent from './agent';
import EventEmitter from 'events';
import { resolve } from 'path';
import { stat, readFile } from 'fs-promise';

export default class Now extends EventEmitter {
  constructor (token, { forceNew = false, debug = false }) {
    super();
    this._token = token;
    this._debug = debug;
    this._forceNew = forceNew;
    this._agent = new Agent('api.now.sh', { debug });
    this._onRetry = this._onRetry.bind(this);
  }

  async create (path, { forceNew }) {
    this._path = path;

    try {
      await stat(path);
    } catch (err) {
      throw new Error(`Could not read directory ${path}.`);
    }

    let pkg;
    try {
      pkg = await readFile(resolve(path, 'package.json'));
      pkg = JSON.parse(pkg);
    } catch (err) {
      throw new Error(`Failed to read JSON in "${path}/package.json"`);
    }

    if (this._debug) console.time('> [debug] Getting files');
    const files = await getFiles(path, pkg);
    if (this._debug) console.timeEnd('> [debug] Getting files');

    if (this._debug) console.time('> [debug] Computing hashes');
    const hashes = await hash(files);
    if (this._debug) console.timeEnd('> [debug] Computing hashes');

    this._files = hashes;

    const deployment = await retry(async (bail) => {
      const res = await this._fetch('/create', {
        method: 'POST',
        body: {
          forceNew,
          files: Array.from(this._files).map(([sha, { data }]) => {
            return {
              sha,
              size: Buffer.byteLength(data)
            };
          })
        }
      });

      // no retry on 403
      if (403 === res.status) {
        if (this._debug) {
          console.log('> [debug] bailing on creating due to 403');
        }
        return bail(responseError(res));
      }

      if (200 !== res.status) {
        throw new Error('Deployment initialization failed');
      }

      return res.json();
    }, { retries: 3, minTimeout: 2500, onRetry: this._onRetry });

    this._id = deployment.deploymentId;
    this._url = deployment.url;
    this._missing = deployment.missing || [];

    return this._url;
  }

  upload () {
    Promise.all(this._missing.map((sha) => retry(async (bail) => {
      const file = this._files.get(sha);
      const { data, name } = file;
      const res = await this._fetch('/sync', {
        method: 'POST',
        body: {
          sha,
          data: data.toString(),
          file: toRelative(name, this._path),
          deploymentId: this._id
        }
      });

      // no retry on 403
      if (403 === res.status) {
        if (this._debug) console.log('> [debug] bailing on creating due to 403');
        return bail(responseError(res));
      }

      this.emit('upload', file);
    }, { retries: 5, randomize: true, onRetry: this._onRetry })))
    .then(() => this.emit('complete'))
    .catch((err) => this.emit('error', err));
  }

  _onRetry (err) {
    if (this._debug) {
      console.log(`> [debug] Retrying: ${err.stack}`);
    }
  }

  close () {
    this._agent.close();
  }

  get url () {
    return this._url;
  }

  get syncAmount () {
    if (!this._syncAmount) {
      this._syncAmount = this._missing
      .map((sha) => Buffer.byteLength(this._files.get(sha).data))
      .reduce((a, b) => a + b, 0);
    }
    return this._syncAmount;
  }

  async _fetch (url, opts) {
    opts.headers = opts.headers || {};
    opts.headers.authorization = `Bearer ${this._token}`;
    return await this._agent.fetch(url, opts);
  }
}

function toRelative (path, base) {
  const fullBase = /\/$/.test(base) ? base + '/' : base;
  return path.substr(fullBase.length);
}

function responseError (res) {
  const err = new Error('Response error');
  err.status = res.status;
  return err;
}
<|endoftext|>


<commit_before>'use strict';

const {david} = require('@cedx/gulp-david');
const {spawn} = require('child_process');
const del = require('del');
const gulp = require('gulp');
const eslint = require('gulp-eslint');
const {normalize} = require('path');

/**
 * Deletes all generated files and reset any saved state.
 */
gulp.task('clean', () => del(['.nyc_output', 'doc/api', 'var/**/*', 'web']));

/**
 * Sends the results of the code coverage.
 */
gulp.task('coverage', () => _exec('node_modules/.bin/coveralls', ['var/lcov.info']));

/**
 * Checks the package dependencies.
 */
gulp.task('deps:outdated', () => gulp.src('package.json').pipe(david()));
gulp.task('deps:security', () => _exec('node_modules/.bin/nsp', ['check']));
gulp.task('deps', gulp.series('deps:outdated', 'deps:security'));

/**
 * Builds the documentation.
 */
gulp.task('doc:api', () => _exec('node_modules/.bin/esdoc'));
gulp.task('doc:web', () => _exec('mkdocs', ['build']));
gulp.task('doc', gulp.series('doc:api', 'doc:web'));

/**
 * Fixes the coding standards issues.
 */
gulp.task('fix', () => gulp.src(['*.js', 'lib/**/*.js', 'test/**/*.js'], {base: '.'})
  .pipe(eslint({fix: true}))
  .pipe(gulp.dest('.'))
);

/**
 * Performs static analysis of source code.
 */
gulp.task('lint', () => gulp.src(['*.js', 'lib/**/*.js', 'test/**/*.js'])
  .pipe(eslint())
  .pipe(eslint.format())
);

/**
 * Runs the unit tests.
 */
gulp.task('test', () => _exec('node_modules/.bin/nyc', [normalize('node_modules/.bin/mocha')]));

/**
 * Watches for file changes.
 */
gulp.task('watch', () => gulp.watch(['lib/**/*.js', 'test/**/*.js'], gulp.task('test')));

/**
 * Runs the default tasks.
 */
gulp.task('default', gulp.task('test'));

/**
 * Spawns a new process using the specified command.
 * @param {string} command The command to run.
 * @param {string[]} [args] The command arguments.
 * @param {object} [options] The settings to customize how the process is spawned.
 * @return {Promise} Completes when the command is finally terminated.
 */
async function _exec(command, args = [], options = {shell: true, stdio: 'inherit'}) {
  return new Promise((resolve, reject) => spawn(normalize(command), args, options)
    .on('close', code => code ? reject(new Error(`${command}: ${code}`)) : resolve())
  );
}
<commit_msg>Added an "upgrade" build task<commit_after>'use strict';

const {david} = require('@cedx/gulp-david');
const {spawn} = require('child_process');
const del = require('del');
const gulp = require('gulp');
const eslint = require('gulp-eslint');
const {normalize} = require('path');

/**
 * Deletes all generated files and reset any saved state.
 */
gulp.task('clean', () => del(['.nyc_output', 'doc/api', 'var/**/*', 'web']));

/**
 * Sends the results of the code coverage.
 */
gulp.task('coverage', () => _exec('node_modules/.bin/coveralls', ['var/lcov.info']));

/**
 * Checks the package dependencies.
 */
gulp.task('deps:outdated', () => gulp.src('package.json').pipe(david()));
gulp.task('deps:security', () => _exec('node_modules/.bin/nsp', ['check']));
gulp.task('deps', gulp.series('deps:outdated', 'deps:security'));

/**
 * Builds the documentation.
 */
gulp.task('doc:api', () => _exec('node_modules/.bin/esdoc'));
gulp.task('doc:web', () => _exec('mkdocs', ['build']));
gulp.task('doc', gulp.series('doc:api', 'doc:web'));

/**
 * Fixes the coding standards issues.
 */
gulp.task('fix', () => gulp.src(['*.js', 'lib/**/*.js', 'test/**/*.js'], {base: '.'})
  .pipe(eslint({fix: true}))
  .pipe(gulp.dest('.'))
);

/**
 * Performs static analysis of source code.
 */
gulp.task('lint', () => gulp.src(['*.js', 'lib/**/*.js', 'test/**/*.js'])
  .pipe(eslint())
  .pipe(eslint.format())
);

/**
 * Runs the unit tests.
 */
gulp.task('test:browser', () => _exec('node_modules/.bin/karma', ['start', '--single-run']));
gulp.task('test:node', () => _exec('node_modules/.bin/nyc', [normalize('node_modules/.bin/mocha')]));
gulp.task('test', gulp.series('test:browser', 'test:node'));

/**
 * Upgrades the project to the latest revision.
 */
gulp.task('upgrade', async () => {
  await _exec('git', ['reset', '--hard']);
  await _exec('git', ['fetch', '--all', '--prune']);
  await _exec('git', ['pull', '--rebase']);
  await _exec('npm', ['install']);
  return _exec('npm', ['update']);
});

/**
 * Watches for file changes.
 */
gulp.task('watch', () => gulp.watch(['lib/**/*.js', 'test/**/*.js'], gulp.task('test:node')));

/**
 * Runs the default tasks.
 */
gulp.task('default', gulp.task('test'));

/**
 * Spawns a new process using the specified command.
 * @param {string} command The command to run.
 * @param {string[]} [args] The command arguments.
 * @param {Object} [options] The settings to customize how the process is spawned.
 * @return {Promise} Completes when the command is finally terminated.
 */
async function _exec(command, args = [], options = {shell: true, stdio: 'inherit'}) {
  return new Promise((resolve, reject) => spawn(normalize(command), args, options)
    .on('close', code => code ? reject(new Error(`${command}: ${code}`)) : resolve())
  );
}
<|endoftext|>


<commit_before>define([
    'underscore', 'jquery',
    'views/proto/base',
    'text!templates/events.html'
], function (_, $, Base, html) {

    var el = $(html);
    var templates = {};
    el.find('script').each(function () {
        var item = $(this);
        templates[item.attr('class')] = _.template(item.text());
    });

    return Base.extend({
        template: function () {
            var eventName = this.model.get('action') + '-' + this.model.get('object_type');
            var templateElem = $('#template-event-' + this.model.get('action') + '-' + this.model.get('object_type'));
            if (templates[eventName]) {
                return templates[eventName];
            }
            else {
              return templates['unknown'];
            }
        },

        render: function () {
            var template = this.template();
            var params = this.model.toJSON();
            params.partial = this.partial;
            this.$el.html(template(params));
            return this;
        }
    });
});
<commit_msg>views/event/normal uses event.name()<commit_after>define([
    'underscore', 'jquery',
    'views/proto/base',
    'text!templates/events.html'
], function (_, $, Base, html) {

    var el = $(html);
    var templates = {};
    el.find('script').each(function () {
        var item = $(this);
        templates[item.attr('class')] = _.template(item.text());
    });

    return Base.extend({
        template: function () {
            var eventName = this.model.name();
            if (templates[eventName]) {
                return templates[eventName];
            }
            else {
              return templates['unknown'];
            }
        },

        render: function () {
            var template = this.template();
            var params = this.model.toJSON();
            params.partial = this.partial;
            this.$el.html(template(params));
            return this;
        }
    });
});
<|endoftext|>