<commit_before>(function () {
  "use strict";
  var jwt = require("jwt-simple");
  var rp = require("request-promise");
  var InputDataValidator = require("./validators");
  var Url = require("url");
  var moment = require("moment");
  var validator = require("validator");

  module.exports = function PayapiClient(params) {
    function rejectUnsafeEnvironmentVariable(params) {
      return new Promise(function(resolve, reject) {
        if(process.env.NODE_TLS_REJECT_UNAUTHORIZED && ["development", "test"].indexOf(process.env.NODE_ENV) < 0) {
          return reject(new Error("NODE_TLS_REJECT_UNAUTHORIZED is not allowed in environment '" + process.env.NODE_ENV+ "'"));
        } else {
          return resolve(params);
        }
      });
    }

    function print(key, value) {
      console.log(key + ":" + JSON.stringify(value, null, 2));
    }

    function toPaymentObject() {
      var jwtHeader64 = params.paymentToken.split(".")[0];
      var jwtHeader = JSON.parse(new Buffer(jwtHeader64, "base64").toString());
      var alg = jwtHeader.alg;
      if (alg === "HS512" ||
          alg === "HS384" ||
          alg === "HS256" ||
          alg === "RS256") {
        return jwt.decode(params.paymentToken, params.apiKey);
      } else {
        throw new Error("Only HS256, HS384, HS512 and RS256 algorithms are supported for JWT.");
      }
    }

    function sanitizeAndExtractBinAndLast4(apiKeyAndToken) {
      var paymentObject = toPaymentObject();
      if(params.optionalFields.indexOf("payment") < 0 &&
          params.optionalFields.indexOf("payment.creditCardNumber") < 0) {
        paymentObject.payment.creditCardNumber = paymentObject.payment.creditCardNumber.replace(/\s/g,"");
        paymentObject.payment.cardBin = paymentObject.payment.creditCardNumber
          .replace(/\s/g, "")
          .substring(0, 6);
      }
      return paymentObject;
    }

    function toPaymentToken() {
      return jwt.encode(params.payload, params.apiKey, "HS512");
    }

    if(params) {
      params.returningConsumer = params.returningConsumer || false;
      params.optionalFields = params.optionalFields || [];
      params.extra = params.extra || {};

      if(params.payment && params.payment.creditCardNumber) {
        params.payment.creditCardNumber = params.payment.creditCardNumber.replace(/\s/g, "");
        params.payment.cardBin = params.payment.creditCardNumber
          .replace(/\s/g, "")
          .substring(0, 6);
      }

      if(params.paymentToken) {
        // decode, sanitize and re-package
        params.payload = sanitizeAndExtractBinAndLast4();
        params.paymentToken = toPaymentToken();
      }
    }

    function validateApiKey(params) {
      return new Promise(function(resolve, reject) {
        if(!params.apiKey) {
          reject("apiKey must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    // secret is unused in v1, but is here as a placeholder for v2
    function validateSecret(params) {
      return new Promise(function(resolve, reject) {
        if(!params.secret) {
          reject("secret must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    function encodePayloadUriComponents(payload) {
      // product image
      if(payload.products && payload.products.length > 0) {
        for(var i = 0; i < payload.products.length; i++) {
          if(payload.products[i].imageUrl) {
            payload.products[i].imageUrl = Url.parse(payload.products[i].imageUrl).href;
          }
        }
      }

      // callbacks
      if(payload.callbacks && payload.callbacks.success) {
        payload.callbacks.success = Url.parse(payload.callbacks.success).href;
      }
      if(payload.callbacks && payload.callbacks.failed) {
        payload.callbacks.failed = Url.parse(payload.callbacks.failed).href;
      }
      if(payload.callbacks && payload.callbacks.chargeback) {
        payload.callbacks.chargeback = Url.parse(payload.callbacks.chargeback).href;
      }
      if(payload.callbacks && payload.callbacks.processing) {
        payload.callbacks.processing = Url.parse(payload.callbacks.processing).href;
      }

      // returnUrls
      if(payload.returnUrls && payload.returnUrls.success) {
        payload.returnUrls.success = Url.parse(payload.returnUrls.success).href;
      }
      if(payload.returnUrls && payload.returnUrls.cancel) {
        payload.returnUrls.cancel = Url.parse(payload.returnUrls.cancel).href;
      }
      if(payload.returnUrls && payload.returnUrls.failed) {
        payload.returnUrls.failed = Url.parse(payload.returnUrls.failed).href;
      }

      // ToS
      if(payload.order && payload.order.tosUrl) {
        payload.order.tosUrl = Url.parse(payload.order.tosUrl).href;
      }
      return payload;
    }

    function encodeURIComponentRecursive(extra) {
      for (var key in extra) {
        if (extra.hasOwnProperty(key) && extra[key] && typeof extra[key] === "object") {
          extra[encodeURIComponent(key)] = encodeURIComponentRecursive(extra[key]);
        } else if(extra.hasOwnProperty(key) && extra[key]) {
          extra[encodeURIComponent(key)] = encodeURIComponent(extra[key]);
        }
      }
      return extra;
    }

    function encodePayloadExtraComponents(payload) {
      if(payload.extra) {
        payload.extra = encodeURIComponentRecursive(payload.extra);
      }
      return payload;
    }

    function convertNumbersToStrings(payload) {
      if(payload.products && payload.products.length > 0) {
        for(var i = 0; i < payload.products.length; i++) {
          if(typeof payload.products[i].id === "number") {
            payload.products[i].id = payload.products[i].id + "";
          }
        }
      }
      return payload;
    }

    function validatePayload(params) {
      return new Promise(function(resolve, reject) {
        var payload = {
          transactionUuid: params.transactionUuid,
          authenticationToken: params.authenticationToken,
          payment: params.payment,
          consumer: params.consumer,
          order: params.order,
          products: params.products,
          callbacks: params.callbacks,
          shippingAddress: params.shippingAddress,
          returnUrls: params.returnUrls,
          returningConsumer: params.returningConsumer || false,
          optionalFields: params.optionalFields || [],
          extra: params.extra || {}
        };
        payload = encodePayloadUriComponents(payload);
        //payload = encodePayloadExtraComponents(payload);
        payload = convertNumbersToStrings(payload);
        var validationErrors = new InputDataValidator(payload).validate();
        if(validationErrors.length > 0) {
          reject(validationErrors);
        } else {
          params.payload = payload;
          resolve(params);
        }
      });
    }

    function createToken(params) {
      return new Promise(function(resolve, reject) {
        if(params.payload) {
          params.paymentToken = toPaymentToken(params.payload, params.apiKey, "HS512");
          resolve(params);
        } else if(params.paymentToken) {
          resolve(params);
        } else {
          reject(new Error("No payment token or payload to create a payment token from. Unable to continue."));
        }
      });
    }

    function stopMoment(timerName, startMoment, noisy, logger) {
      if(noisy === true) {
        if(!logger) {
          logger = console;
        }
        if(logger.log && logger.log.constructor && logger.log.constructor.name === "Function") {
          logger.log("%s took %s ms to execute", timerName, moment().diff(startMoment));
        } else {
          console.warn("The logger you have provided does not have a log('message') interface");
        }
      }
    }

    function doRestCall(params) {
      return new Promise(function(resolve, reject) {
        var uri;
        var startMoment = moment();
        var logger = params.logger;
        var debug = params.debug;
        switch(process.env.NODE_ENV) {
          case "production":
            uri = process.env.PA_PAYMENTS_URI || "https://input.payapi.io/v1/api/authorized/payments";
            break;
          case "staging":
            uri = process.env.PA_PAYMENTS_URI || "https://staging-input.payapi.io/v1/api/authorized/payments";
            break;
          default:
            uri = process.env.PA_PAYMENTS_URI || "http://localhost:3000/v1/api/authorized/payments";
        }
        rp({
          method: "POST",
          uri: uri,
          body: {
            authenticationToken: params.authenticationToken,
            paymentToken: params.paymentToken
          },
          json: true,
          timeout: 5000
        }).then(function(params) {
          stopMoment("POST to " + uri, startMoment, debug, logger);
          resolve(params);
        }).catch(function(err) {
          reject(err);
        });
      });
    }

    function handleError(err) {
      return new Promise(function(resolve, reject) {
        console.log("Payapi Client Error:" + JSON.stringify(err, null, 2));
        reject(err);
      });
    }

    function convertNumberToNumber(params) {
      return new Promise(function(resolve, reject) {
        if(params.payload.products && params.payload.products.length > 0) {
          for(var i = 0; i < params.payload.products.length; i++) {
            params.payload.products[i].quantity = Number(params.payload.products[i].quantity);
            params.payload.products[i].priceInCentsIncVat = Number(params.payload.products[i].priceInCentsIncVat);
            params.payload.products[i].priceInCentsExcVat = Number(params.payload.products[i].priceInCentsExcVat);
            params.payload.products[i].vatPercentage = Number(params.payload.products[i].vatPercentage);
          }
        }
        params.payload.order.sumInCentsIncVat = Number(params.payload.order.sumInCentsIncVat);
        params.payload.order.sumInCentsExcVat = Number(params.payload.order.sumInCentsExcVat);
        resolve(params);
      });
    }

    return {
      call: function(callParams) {
        if(callParams) {
          return rejectUnsafeEnvironmentVariable(callParams)
            .then(doRestCall)
            .catch(handleError);
        } else {
          return rejectUnsafeEnvironmentVariable(params)
            .then(validateApiKey)
            .then(validateSecret)
            .then(validatePayload)
            .then(convertNumberToNumber)
            .then(createToken)
            .then(doRestCall)
            .catch(handleError);
        }
      },
      paymentToken: function() {
        return validatePayload(params)
          .then(convertNumberToNumber)
          .then(createToken)
          .then(function(params) {
            return new Promise(function(resolve, reject) {
              resolve(params.paymentToken);
            });
          })
          .catch(function(err) {
            throw err;
          });
      },
      validate: function() {
        return validatePayload(params);
      },
      encodePaymentToken: function() {
        return toPaymentToken();
      },
      decodePaymentToken: function() {
        var paymentObject = toPaymentObject();
        if(typeof paymentObject !== "object") {
          throw [{
            'message': 'JSON is not a valid Object',
            'translationKey': 'invalid.json'
          }];
        } else {
          paymentObject.optionalFields = params.optionalFields;
          return validatePayload(paymentObject)
            .then(convertNumberToNumber)
            .then(function(result) {
              return result.payload;
            })
            .catch(function(err) {
              throw err;
            });
        }
      },
    };
  };
}());
<commit_msg>Converted ' to "<commit_after>(function () {
  "use strict";
  var jwt = require("jwt-simple");
  var rp = require("request-promise");
  var InputDataValidator = require("./validators");
  var Url = require("url");
  var moment = require("moment");
  var validator = require("validator");

  module.exports = function PayapiClient(params) {
    function rejectUnsafeEnvironmentVariable(params) {
      return new Promise(function(resolve, reject) {
        if(process.env.NODE_TLS_REJECT_UNAUTHORIZED && ["development", "test"].indexOf(process.env.NODE_ENV) < 0) {
          return reject(new Error("NODE_TLS_REJECT_UNAUTHORIZED is not allowed in environment '" + process.env.NODE_ENV+ "'"));
        } else {
          return resolve(params);
        }
      });
    }

    function print(key, value) {
      console.log(key + ":" + JSON.stringify(value, null, 2));
    }

    function toPaymentObject() {
      var jwtHeader64 = params.paymentToken.split(".")[0];
      var jwtHeader = JSON.parse(new Buffer(jwtHeader64, "base64").toString());
      var alg = jwtHeader.alg;
      if (alg === "HS512" ||
          alg === "HS384" ||
          alg === "HS256" ||
          alg === "RS256") {
        return jwt.decode(params.paymentToken, params.apiKey);
      } else {
        throw new Error("Only HS256, HS384, HS512 and RS256 algorithms are supported for JWT.");
      }
    }

    function sanitizeAndExtractBinAndLast4(apiKeyAndToken) {
      var paymentObject = toPaymentObject();
      if(params.optionalFields.indexOf("payment") < 0 &&
          params.optionalFields.indexOf("payment.creditCardNumber") < 0) {
        paymentObject.payment.creditCardNumber = paymentObject.payment.creditCardNumber.replace(/\s/g,"");
        paymentObject.payment.cardBin = paymentObject.payment.creditCardNumber
          .replace(/\s/g, "")
          .substring(0, 6);
      }
      return paymentObject;
    }

    function toPaymentToken() {
      return jwt.encode(params.payload, params.apiKey, "HS512");
    }

    if(params) {
      params.returningConsumer = params.returningConsumer || false;
      params.optionalFields = params.optionalFields || [];
      params.extra = params.extra || {};

      if(params.payment && params.payment.creditCardNumber) {
        params.payment.creditCardNumber = params.payment.creditCardNumber.replace(/\s/g, "");
        params.payment.cardBin = params.payment.creditCardNumber
          .replace(/\s/g, "")
          .substring(0, 6);
      }

      if(params.paymentToken) {
        // decode, sanitize and re-package
        params.payload = sanitizeAndExtractBinAndLast4();
        params.paymentToken = toPaymentToken();
      }
    }

    function validateApiKey(params) {
      return new Promise(function(resolve, reject) {
        if(!params.apiKey) {
          reject("apiKey must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    // secret is unused in v1, but is here as a placeholder for v2
    function validateSecret(params) {
      return new Promise(function(resolve, reject) {
        if(!params.secret) {
          reject("secret must not be empty");
        } else {
          resolve(params);
        }
      });
    }

    function encodePayloadUriComponents(payload) {
      // product image
      if(payload.products && payload.products.length > 0) {
        for(var i = 0; i < payload.products.length; i++) {
          if(payload.products[i].imageUrl) {
            payload.products[i].imageUrl = Url.parse(payload.products[i].imageUrl).href;
          }
        }
      }

      // callbacks
      if(payload.callbacks && payload.callbacks.success) {
        payload.callbacks.success = Url.parse(payload.callbacks.success).href;
      }
      if(payload.callbacks && payload.callbacks.failed) {
        payload.callbacks.failed = Url.parse(payload.callbacks.failed).href;
      }
      if(payload.callbacks && payload.callbacks.chargeback) {
        payload.callbacks.chargeback = Url.parse(payload.callbacks.chargeback).href;
      }
      if(payload.callbacks && payload.callbacks.processing) {
        payload.callbacks.processing = Url.parse(payload.callbacks.processing).href;
      }

      // returnUrls
      if(payload.returnUrls && payload.returnUrls.success) {
        payload.returnUrls.success = Url.parse(payload.returnUrls.success).href;
      }
      if(payload.returnUrls && payload.returnUrls.cancel) {
        payload.returnUrls.cancel = Url.parse(payload.returnUrls.cancel).href;
      }
      if(payload.returnUrls && payload.returnUrls.failed) {
        payload.returnUrls.failed = Url.parse(payload.returnUrls.failed).href;
      }

      // ToS
      if(payload.order && payload.order.tosUrl) {
        payload.order.tosUrl = Url.parse(payload.order.tosUrl).href;
      }
      return payload;
    }

    function encodeURIComponentRecursive(extra) {
      for (var key in extra) {
        if (extra.hasOwnProperty(key) && extra[key] && typeof extra[key] === "object") {
          extra[encodeURIComponent(key)] = encodeURIComponentRecursive(extra[key]);
        } else if(extra.hasOwnProperty(key) && extra[key]) {
          extra[encodeURIComponent(key)] = encodeURIComponent(extra[key]);
        }
      }
      return extra;
    }

    function encodePayloadExtraComponents(payload) {
      if(payload.extra) {
        payload.extra = encodeURIComponentRecursive(payload.extra);
      }
      return payload;
    }

    function convertNumbersToStrings(payload) {
      if(payload.products && payload.products.length > 0) {
        for(var i = 0; i < payload.products.length; i++) {
          if(typeof payload.products[i].id === "number") {
            payload.products[i].id = payload.products[i].id + "";
          }
        }
      }
      return payload;
    }

    function validatePayload(params) {
      return new Promise(function(resolve, reject) {
        var payload = {
          transactionUuid: params.transactionUuid,
          authenticationToken: params.authenticationToken,
          payment: params.payment,
          consumer: params.consumer,
          order: params.order,
          products: params.products,
          callbacks: params.callbacks,
          shippingAddress: params.shippingAddress,
          returnUrls: params.returnUrls,
          returningConsumer: params.returningConsumer || false,
          optionalFields: params.optionalFields || [],
          extra: params.extra || {}
        };
        payload = encodePayloadUriComponents(payload);
        //payload = encodePayloadExtraComponents(payload);
        payload = convertNumbersToStrings(payload);
        var validationErrors = new InputDataValidator(payload).validate();
        if(validationErrors.length > 0) {
          reject(validationErrors);
        } else {
          params.payload = payload;
          resolve(params);
        }
      });
    }

    function createToken(params) {
      return new Promise(function(resolve, reject) {
        if(params.payload) {
          params.paymentToken = toPaymentToken(params.payload, params.apiKey, "HS512");
          resolve(params);
        } else if(params.paymentToken) {
          resolve(params);
        } else {
          reject(new Error("No payment token or payload to create a payment token from. Unable to continue."));
        }
      });
    }

    function stopMoment(timerName, startMoment, noisy, logger) {
      if(noisy === true) {
        if(!logger) {
          logger = console;
        }
        if(logger.log && logger.log.constructor && logger.log.constructor.name === "Function") {
          logger.log("%s took %s ms to execute", timerName, moment().diff(startMoment));
        } else {
          console.warn("The logger you have provided does not have a log('message') interface");
        }
      }
    }

    function doRestCall(params) {
      return new Promise(function(resolve, reject) {
        var uri;
        var startMoment = moment();
        var logger = params.logger;
        var debug = params.debug;
        switch(process.env.NODE_ENV) {
          case "production":
            uri = process.env.PA_PAYMENTS_URI || "https://input.payapi.io/v1/api/authorized/payments";
            break;
          case "staging":
            uri = process.env.PA_PAYMENTS_URI || "https://staging-input.payapi.io/v1/api/authorized/payments";
            break;
          default:
            uri = process.env.PA_PAYMENTS_URI || "http://localhost:3000/v1/api/authorized/payments";
        }
        rp({
          method: "POST",
          uri: uri,
          body: {
            authenticationToken: params.authenticationToken,
            paymentToken: params.paymentToken
          },
          json: true,
          timeout: 5000
        }).then(function(params) {
          stopMoment("POST to " + uri, startMoment, debug, logger);
          resolve(params);
        }).catch(function(err) {
          reject(err);
        });
      });
    }

    function handleError(err) {
      return new Promise(function(resolve, reject) {
        console.log("Payapi Client Error:" + JSON.stringify(err, null, 2));
        reject(err);
      });
    }

    function convertNumberToNumber(params) {
      return new Promise(function(resolve, reject) {
        if(params.payload.products && params.payload.products.length > 0) {
          for(var i = 0; i < params.payload.products.length; i++) {
            params.payload.products[i].quantity = Number(params.payload.products[i].quantity);
            params.payload.products[i].priceInCentsIncVat = Number(params.payload.products[i].priceInCentsIncVat);
            params.payload.products[i].priceInCentsExcVat = Number(params.payload.products[i].priceInCentsExcVat);
            params.payload.products[i].vatPercentage = Number(params.payload.products[i].vatPercentage);
          }
        }
        params.payload.order.sumInCentsIncVat = Number(params.payload.order.sumInCentsIncVat);
        params.payload.order.sumInCentsExcVat = Number(params.payload.order.sumInCentsExcVat);
        resolve(params);
      });
    }

    return {
      call: function(callParams) {
        if(callParams) {
          return rejectUnsafeEnvironmentVariable(callParams)
            .then(doRestCall)
            .catch(handleError);
        } else {
          return rejectUnsafeEnvironmentVariable(params)
            .then(validateApiKey)
            .then(validateSecret)
            .then(validatePayload)
            .then(convertNumberToNumber)
            .then(createToken)
            .then(doRestCall)
            .catch(handleError);
        }
      },
      paymentToken: function() {
        return validatePayload(params)
          .then(convertNumberToNumber)
          .then(createToken)
          .then(function(params) {
            return new Promise(function(resolve, reject) {
              resolve(params.paymentToken);
            });
          })
          .catch(function(err) {
            throw err;
          });
      },
      validate: function() {
        return validatePayload(params);
      },
      encodePaymentToken: function() {
        return toPaymentToken();
      },
      decodePaymentToken: function() {
        var paymentObject = toPaymentObject();
        if(typeof paymentObject !== "object") {
          throw [{
            "message": "JSON is not a valid Object",
            "translationKey": "invalid.json"
          }];
        } else {
          paymentObject.optionalFields = params.optionalFields;
          return validatePayload(paymentObject)
            .then(convertNumberToNumber)
            .then(function(result) {
              return result.payload;
            })
            .catch(function(err) {
              throw err;
            });
        }
      },
    };
  };
}());
<|endoftext|>


<commit_before>var gulp =  require('gulp');
var pug =  require('gulp-pug');
var stylus =  require('gulp-stylus');
var connect =  require('gulp-connect');

gulp.task('pug', function(){
  gulp.src('./src/*.pug')
      .pipe(pug())
      .pipe(gulp.dest('./out'))
      .pipe(connect.reload());
});

gulp.task('stylus', function(){
  gulp.src('./src/assets/styles/*.styl')
      .pipe(stylus())
      .pipe(gulp.dest('./out/assets/styles'))
      .pipe(connect.reload());
});

gulp.task('watch', function(){
  gulp.watch(['./src/*.pug'], ['pug']);
  gulp.watch(['./src/assets/styles/*.styl'], ['stylus']);
});

gulp.task('serve', function(){
  connect.server({
    root: './out',
    livereload: true,
    port: 3210
  });
});

gulp.task('build', ['pug','stylus']);
gulp.task('server',['serve','watch']);
<commit_msg>Base do gulp file ok close #5<commit_after>var gulp = require('gulp');
var pug = require('gulp-pug');
var stylus = require('gulp-stylus');
var connect = require('gulp-connect');

gulp.task('pug', function () {
  gulp.src('./src/*.pug')
    .pipe(pug())
    .pipe(gulp.dest('./out'))
    .pipe(connect.reload());
});

gulp.task('stylus', function () {
  gulp.src('./src/assets/styles/*.styl')
    .pipe(stylus())
    .pipe(gulp.dest('./out/assets/styles'))
    .pipe(connect.reload());
});

gulp.task('watch', function () {
  gulp.watch(['./src/*.pug'], ['pug']);
  gulp.watch(['./src/assets/styles/*.styl'], ['stylus']);
});

gulp.task('serve', function () {
  connect.server({
    root: './out',
    livereload: true,
    port: 3210
  });
});

gulp.task('build', ['pug', 'stylus']);
gulp.task('server', ['serve', 'watch']);
<|endoftext|>


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

"use strict";

var iotdb = require('iotdb');
var _ = iotdb._;

var logger = iotdb.logger({
    name: 'iotdb-commands',
    module: 'match',
});

var format = require('iotdb-format');
var vocabulary = require('./vocabulary');
var stemmer = require('porter-stemmer').stemmer;

var _normalize_word = function(word) {
    return stemmer(word.toLowerCase());
};

/**
 *  This:
 *  - normalizes english words to make comparison possible
 */
var _prepare_item = function(item, paramd) {
    if (_.is.Empty(item)) {
        return;
    }

    item = _.d.clone.deep(item);

    /**
     *  If there's a "do" clause, then we default in an "ostate"
     *  rule that says there has to be a matching purpose
     */
    if (item.do) {
        if (!item.ostate) {
            item.ostate = {};
        }

        if (!item.ostate["iot:purpose"] && item.do["iot:purpose"]) {
            item.ostate["iot:purpose"] = item.do["iot:purpose"];
        }
    }

    /**
     *  Normalize human language words for matching purposes.
     *  We use _.d.transform as there's subdictionaries
     */
    item = _.d.transform(item, {
        pre: function(o, paramd) {
            var words = [
                "schema:name",
                "iot:zone",
            ];
            words.map(function(word) {
                var values = _.ld.list(o, word, []);
                if (!values.length) {
                    return;
                }

                o[word] = _.map(values, _normalize_word);
            });

            return o;
        },
    });

    return item;
};

/**
 *  This prepares all the items are turns the new list.
 *  Empty items are excluded.
 */
var _prepare_items = function(items, paramd) {
    var ds = [];

    items.map(function(d) {
        d = _prepare_item(d, paramd);
        if (d) {
            ds.push(d);
        }
    });

    return ds;
};

/**
 */
var _match_object = function(queryd, targetd) {
    var match = null;

    for (var query_key in queryd) {
        if (query_key.indexOf(':') === -1) {
            continue;
        }

        var query_values = _.ld.list(queryd, query_key, []);
        var target_values = _.ld.list(targetd, query_key, []);
        var common = _.intersection(query_values, target_values);

        if (common.length === 0) {
            match = false;
            break;
        }

        match = true;
    }

    return match;
}
/**
 */
var match = function(paramd, done) {
    paramd = _.d.compose.shallow(paramd, {
        user: null,
        verbose: false,
        transport: null,
        requestd: null,
    });

    paramd.verbose = true;

    if (!paramd.transport) {
        throw new Error("param.transport expected");
    }
    if (!paramd.requestd) {
        throw new Error("param.requestd expected");
    }

    // extensions - basically an over ride
    var xds = _prepare_items(vocabulary.extensions(paramd.requestd));

    // thing definitions - what to match
    var tds = _prepare_items(vocabulary.things(paramd.requestd.thing));

    // action and query definitions - what to do
    var ads = _prepare_items(vocabulary.actions(paramd.requestd.action));
    var qds = _prepare_items(vocabulary.querys(paramd.requestd.query));
    ads = ads.concat(qds);

    if (paramd.verbose) {
        logger.info({
            requestd: paramd.requestd,
            match: {
                things: tds,
                attributes: ads,
                // querys: qds,
            }
        }, "initial parameters (verbose)");
    }

    var matches = [];

    /**
     *  Level 1: extension match - note doesn't depend on Thing
     */
    var _level_1 = function() {
        var xds = vocabulary.extensions(paramd.requestd);
        xds.map(function(xd) {
            var resultd = {
                level: 10,
                extension: _.d.clone.shallow(xd),
            };
            matches.push(resultd);
        });

        /*
        if (xds.length) {
            console.log("PARAMD", paramd.requestd)
            console.log("XDS", xds)
            process.exit();
        };
         */
    };

    /**
     *  Level 2: action and thing; or query and thing match
     */
    var _level_2 = function(thingd) {
        /*
         *  band:meta match
         */
        var meta = _prepare_item(thingd.meta, paramd);

        var match_td = null;
        _.find(tds, function(td) {
            if (_match_object(td.meta, meta)) {
                match_td = td;
                return true;
            }
        });
        if (!match_td) {
            return;
        }

        /*
         *  band:istate and band:ostate match - on individual attributes
         */
        var match_attribute_code = null;
        var match_attribute = null;
        var match_ad = null;

        var bands = [ "istate", "ostate" ];
        bands.map(function(band) {
            if (match_ad) {
                return;
            }

            _.find(ads, function(ad) {
                var attributes = _.ld.list(thingd.model, "iot:attribute", []);
                for (var ai = 0; ai < attributes.length; ai++) {
                    var attribute = _prepare_item(attributes[ai], paramd);

                    var attribute_code = attribute['@id'].replace(/^.*#/, '');
                    var attribute_value = _.d.get(thingd[band] || {}, attribute_code);
                    if (attribute_value) {
                        attribute["@value"] = attribute_value;
                    }

                    if (_match_object(ad[band], attribute)) {
                        match_attribute_code = attribute_code;
                        match_attribute = attributes[ai];
                        match_ad = ad;
                        return true;
                    }
                }
            });
        });

        if (!match_ad) {
            return;
        }

        if (paramd.verbose) {
            logger.info({
                thing_name: _.ld.first(thingd.meta, "schema:name", ""),
                id: thingd.id,
            }, "MATCH (verbose)");
        };

        var resultd = {
            "level": 20,
            "response": "ok",
            "thing-id": thingd.id,
        };

        var ivalue = _.d.get(thingd.istate, match_attribute_code, null);
        var ovalue = null;

        if (match_ad.do) {
            /**
             *  This will REALLY be improved when we get the next-gen stuff
             *  working in IOTDB so we don't have to replicate all those rules here
             */
            var dod = match_ad.do;
            var dvalue = match_ad.do["@value"];
            if (dvalue === undefined) {
                dvalue = null;
            }
            var rule = dod["rule"] || "set";

            var amin = _.ld.first(match_attribute, "iot:minimum", null);
            var amax = _.ld.first(match_attribute, "iot:maximum", null);
            var atype = _.ld.first(match_attribute, "iot:type");
            var aunit = _.ld.first(match_attribute, "iot:unit");
            if (atype === "iot:type.boolean") {
                amin = false;
                amax = true;
            } else if (aunit === "iot-unit:math.fraction.unit") {
                amin = amin || 0;
                amax = amax || 1;
            } else if (aunit === "iot-unit:math.fraction.percent") {
                amin = amin || 0;
                amax = amax || 100;
            }

            if (rule === "set") {
                ovalue = dvalue;
            } else if (rule === "toggle") {
                if (ivalue === null) {
                } else if (amax === null) {
                } else if (amin === null) {
                } else if (ivalue === amax) {
                    ovalue = amin;
                } else {
                    ovalue = amax;
                }
            } else if (rule === "delta") {
                if ((ivalue === null) && (amin !== null)) {
                    ivalue = amin;
                }
                if (ivalue !== null) {
                    ovalue = ivalue + dvalue;
                }
            } else if (rule === "delta-percent") {
                if ((ivalue === null) && (amin !== null)) {
                    ivalue = amin;
                }
                if (amax === null) {
                } else if (amin === null) {
                } else if (ivalue !== null) {
                    ovalue = ivalue + (amax - amin) * dvalue / 100.0;
                }
            }

            if ((amin !== null) && (ovalue < amin)) {
                ovalue = amin;
            }
            if ((amax !== null) && (ovalue > amax)) {
                ovalue = amax;
            }

            resultd.ostate = {};
            resultd.ostate[match_attribute_code] = ovalue;
        }

        if (match_ad.response) {
            resultd.response = format.format(match_ad.response, {
                name: _.ld.first(thingd.meta, "schema:name"),
                value: _.d.get(thingd.istate, match_attribute_code),
            });
        }

        matches.push(resultd);
        return true;
    };

    var _process_thing = function(error, thingd) {
        if (paramd.verbose) {
            if (thingd) {
                logger.info({
                    thing_name: _.ld.first(thingd.meta, "schema:name", ""),
                    id: thingd.id,
                }, "check (verbose)");
            }

            logger.debug({
                thing: thingd,
            }, "full thing description (verbose)");
        };

        if (error) {
            return done(error);
        } else if (!thingd) {
            return done(null, matches);
        }

        // look for matches
        _level_2(thingd);
    };

    _level_1();

    paramd.transport.all({
        bands: [ "meta", "model", "istate", ],
        user: paramd.user,
    }, _process_thing);
};

/**
 */
exports.match = match;
<commit_msg>added rules for matching by name<commit_after>/*
 *  match.js
 *
 *  David Janes
 *  IOTDB.org
 *  2016-01-07
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var iotdb = require('iotdb');
var _ = iotdb._;

var logger = iotdb.logger({
    name: 'iotdb-commands',
    module: 'match',
});

var format = require('iotdb-format');
var vocabulary = require('./vocabulary');
var stemmer = require('porter-stemmer').stemmer;

var _normalize_word = function(word) {
    return stemmer(word.toLowerCase());
};

/**
 *  This:
 *  - normalizes english words to make comparison possible
 */
var _prepare_item = function(item, paramd) {
    if (_.is.Empty(item)) {
        return;
    }

    item = _.d.clone.deep(item);

    /**
     *  If there's a "do" clause, then we default in an "ostate"
     *  rule that says there has to be a matching purpose
     */
    if (item.do) {
        if (!item.ostate) {
            item.ostate = {};
        }

        if (!item.ostate["iot:purpose"] && item.do["iot:purpose"]) {
            item.ostate["iot:purpose"] = item.do["iot:purpose"];
        }
    }

    /**
     *  Normalize human language words for matching purposes.
     *  We use _.d.transform as there's subdictionaries
     */
    item = _.d.transform(item, {
        pre: function(o, paramd) {
            var words = [
                "schema:name",
                "iot:zone",
            ];
            words.map(function(word) {
                var values = _.ld.list(o, word, []);
                if (!values.length) {
                    return;
                }

                o[word] = _.map(values, _normalize_word);
            });

            return o;
        },
    });

    return item;
};

/**
 *  This prepares all the items are turns the new list.
 *  Empty items are excluded.
 */
var _prepare_items = function(items, paramd) {
    var ds = [];

    items.map(function(d) {
        d = _prepare_item(d, paramd);
        if (d) {
            ds.push(d);
        }
    });

    return ds;
};

/**
 */
var _match_object = function(queryd, targetd) {
    var match = null;

    for (var query_key in queryd) {
        if (query_key.indexOf(':') === -1) {
            continue;
        }

        var query_values = _.ld.list(queryd, query_key, []);
        var target_values = _.ld.list(targetd, query_key, []);
        var common = _.intersection(query_values, target_values);

        if (common.length === 0) {
            match = false;
            break;
        }

        match = true;
    }

    return match;
}
/**
 */
var match = function(paramd, done) {
    paramd = _.d.compose.shallow(paramd, {
        user: null,
        verbose: false,
        transport: null,
        requestd: null,
    });

    paramd.verbose = true;

    if (!paramd.transport) {
        throw new Error("param.transport expected");
    }
    if (!paramd.requestd) {
        throw new Error("param.requestd expected");
    }

    // extensions - basically an override
    var xds = _prepare_items(vocabulary.extensions(paramd.requestd));

    // thing definitions - what to match
    var tds = _prepare_items(vocabulary.things(paramd.requestd.thing));

    // action and query definitions - what to do
    var ads = _prepare_items(vocabulary.actions(paramd.requestd.action));
    var qds = _prepare_items(vocabulary.querys(paramd.requestd.query));
    ads = ads.concat(qds);

    if (paramd.verbose) {
        logger.info({
            requestd: paramd.requestd,
            match: {
                things: tds,
                attributes: ads,
                // querys: qds,
            }
        }, "initial parameters (verbose)");
    }

    var matches = [];

    /**
     *  Level 1: extension match - note doesn't depend on Thing
     */
    var _level_1 = function() {
        var xds = vocabulary.extensions(paramd.requestd);
        xds.map(function(xd) {
            var resultd = {
                level: 10,
                extension: _.d.clone.shallow(xd),
            };
            matches.push(resultd);
        });

        /*
        if (xds.length) {
            console.log("PARAMD", paramd.requestd)
            console.log("XDS", xds)
            process.exit();
        };
         */
    };

    /**
     *  Level 2: action and thing; or query and thing match
     */
    var _level_2 = function(thingd) {
        var cost = 0;

        /*
         *  band:meta match
         */
        var meta = _prepare_item(thingd.meta, paramd);

        var match_td = null;
        _.find(tds, function(td) {
            if (_match_object(td.meta, meta)) {
                match_td = td;
                return true;
            }
        });

        // if no match, do a match by name of the thing
        if (!match_td) {
            var by_named = _prepare_item({
                "schema:name": paramd.requestd.thing,
            });

            if (_match_object(by_named, meta)) {
                match_td = true;
                cost = 7;
            }
        }

        if (!match_td) {
            return;
        }

        /*
         *  band:istate and band:ostate match - on individual attributes
         */
        var match_attribute_code = null;
        var match_attribute = null;
        var match_ad = null;

        var bands = [ "istate", "ostate" ];
        bands.map(function(band) {
            if (match_ad) {
                return;
            }

            _.find(ads, function(ad) {
                var attributes = _.ld.list(thingd.model, "iot:attribute", []);
                for (var ai = 0; ai < attributes.length; ai++) {
                    var attribute = _prepare_item(attributes[ai], paramd);

                    var attribute_code = attribute['@id'].replace(/^.*#/, '');
                    var attribute_value = _.d.get(thingd[band] || {}, attribute_code);
                    if (attribute_value) {
                        attribute["@value"] = attribute_value;
                    }

                    if (_match_object(ad[band], attribute)) {
                        match_attribute_code = attribute_code;
                        match_attribute = attributes[ai];
                        match_ad = ad;
                        return true;
                    }
                }
            });
        });

        if (!match_ad) {
            return;
        }

        if (paramd.verbose) {
            logger.info({
                thing_name: _.ld.first(thingd.meta, "schema:name", ""),
                id: thingd.id,
            }, "MATCH (verbose)");
        };

        var resultd = {
            "level": 20,
            "response": "ok",
            "thing-id": thingd.id,
        };

        var ivalue = _.d.get(thingd.istate, match_attribute_code, null);
        var ovalue = null;

        if (match_ad.do) {
            /**
             *  This will REALLY be improved when we get the next-gen stuff
             *  working in IOTDB so we don't have to replicate all those rules here
             */
            var dod = match_ad.do;
            var dvalue = match_ad.do["@value"];
            if (dvalue === undefined) {
                dvalue = null;
            }
            var rule = dod["rule"] || "set";

            var amin = _.ld.first(match_attribute, "iot:minimum", null);
            var amax = _.ld.first(match_attribute, "iot:maximum", null);
            var atype = _.ld.first(match_attribute, "iot:type");
            var aunit = _.ld.first(match_attribute, "iot:unit");
            if (atype === "iot:type.boolean") {
                amin = false;
                amax = true;
            } else if (aunit === "iot-unit:math.fraction.unit") {
                amin = amin || 0;
                amax = amax || 1;
            } else if (aunit === "iot-unit:math.fraction.percent") {
                amin = amin || 0;
                amax = amax || 100;
            }

            if (rule === "set") {
                ovalue = dvalue;
            } else if (rule === "toggle") {
                if (ivalue === null) {
                } else if (amax === null) {
                } else if (amin === null) {
                } else if (ivalue === amax) {
                    ovalue = amin;
                } else {
                    ovalue = amax;
                }
            } else if (rule === "delta") {
                if ((ivalue === null) && (amin !== null)) {
                    ivalue = amin;
                }
                if (ivalue !== null) {
                    ovalue = ivalue + dvalue;
                }
            } else if (rule === "delta-percent") {
                if ((ivalue === null) && (amin !== null)) {
                    ivalue = amin;
                }
                if (amax === null) {
                } else if (amin === null) {
                } else if (ivalue !== null) {
                    ovalue = ivalue + (amax - amin) * dvalue / 100.0;
                }
            }

            if ((amin !== null) && (ovalue < amin)) {
                ovalue = amin;
            }
            if ((amax !== null) && (ovalue > amax)) {
                ovalue = amax;
            }

            resultd.ostate = {};
            resultd.ostate[match_attribute_code] = ovalue;
        }

        if (match_ad.response) {
            resultd.response = format.format(match_ad.response, {
                name: _.ld.first(thingd.meta, "schema:name"),
                value: _.d.get(thingd.istate, match_attribute_code),
            });
        }

        matches.push(resultd);
        return true;
    };

    var _process_thing = function(error, thingd) {
        if (paramd.verbose) {
            if (thingd) {
                logger.info({
                    thing_name: _.ld.first(thingd.meta, "schema:name", ""),
                    id: thingd.id,
                }, "check (verbose)");
            }

            logger.debug({
                thing: thingd,
            }, "full thing description (verbose)");
        };

        if (error) {
            return done(error);
        } else if (!thingd) {
            return done(null, matches);
        }

        // look for matches
        _level_2(thingd);
    };

    _level_1();

    paramd.transport.all({
        bands: [ "meta", "model", "istate", ],
        user: paramd.user,
    }, _process_thing);
};

/**
 */
exports.match = match;
<|endoftext|>


<commit_before>import styled from 'styled-components';
import get from 'extensions/themeGet';

const NavigationBar = styled.header.withConfig({
  displayName: 'NavigationBar',
})`
  background: ${get('colors.primary.default')};
  color: ${get('colors.text.inverted')};
  border-bottom: ${get('thicknesses.normal')} solid
    ${get('colors.shadow.default')};
  padding: 0 ${get('spacing.large')};
  display: flex;
  flex-shrink: 0;
  justify-content: space-between;
  z-index: 1000;

  /* we don't want the nav to expand or collapse, just keep its natural size */
  flex: 0 0 auto;

  & > * {
    margin: auto 0;
  }
`;

NavigationBar.Sub = NavigationBar.extend`
  background: ${get('colors.gray.light')};
  color: ${get('colors.text.default')};
`;

NavigationBar.Dark = NavigationBar.extend`
  background: ${get('colors.primary.dark')};
`;

export default NavigationBar;
<commit_msg>Remove z-index from navigation bar, since it's not fixed by default<commit_after>import styled from 'styled-components';
import get from 'extensions/themeGet';

const NavigationBar = styled.header.withConfig({
  displayName: 'NavigationBar',
})`
  background: ${get('colors.primary.default')};
  color: ${get('colors.text.inverted')};
  border-bottom: ${get('thicknesses.normal')} solid
    ${get('colors.shadow.default')};
  padding: 0 ${get('spacing.large')};
  display: flex;
  flex-shrink: 0;
  justify-content: space-between;

  /* we don't want the nav to expand or collapse, just keep its natural size */
  flex: 0 0 auto;

  & > * {
    margin: auto 0;
  }
`;

NavigationBar.Sub = NavigationBar.extend`
  background: ${get('colors.gray.light')};
  color: ${get('colors.text.default')};
`;

NavigationBar.Dark = NavigationBar.extend`
  background: ${get('colors.primary.dark')};
`;

export default NavigationBar;
<|endoftext|>


<commit_before>var integration = require('analytics.js-integration');
var each = require('each');

/**
 * Expose `DoubleClick` integration.
 */

var Pinterest = module.exports = integration('Pinterest')
  .assumesPageview()
  .mapping('events');

/**
 * Initialize Pinterest.
 *
 * @param {Facade} page
 */

Pinterest.prototype.initialize = function() {
  this.ready();
};

/**
 * Has the Pinterest library been loaded yet?
 *
 * @return {Boolean}
 */

Pinterest.prototype.loaded = function() {
  return true;
};

/**
 * Track a page view.
 *
 * @param {Facade} page
 */

Pinterest.prototype.page = function() {

};

/**
 * Track an event.
 *
 * @param {Facade} track
 */

Pinterest.prototype.track = function(track) {
  var self = this;
  var events = this.events(track.event());
  each(function(pixel) {
    self.fire(pixel);
  }, events);
};

/**
 * Fire the pixel.
 */

Pinterest.prototype.fire = function(pixel) {

  var src = 'https://ct.pinterest.com/?tid='+ pixel + '&value=0.00&quantity=1';

  var flDiv = document.head.appendChild(document.createElement('img'));
  flDiv.style.height = '1';
  flDiv.style.width = '1';
  flDiv.style.display = 'none';
  flDiv.setAttribute('alt', '');
  flDiv.setAttribute('src', src);
};<commit_msg>Append to body element<commit_after>var integration = require('analytics.js-integration');
var each = require('each');

/**
 * Expose `Pinterest Conversions` integration.
 */

var Pinterest = module.exports = integration('Pinterest')
  .assumesPageview()
  .mapping('events');

/**
 * Initialize Pinterest.
 *
 * @param {Facade} page
 */

Pinterest.prototype.initialize = function() {
  this.ready();
};

/**
 * Has the Pinterest library been loaded yet?
 *
 * @return {Boolean}
 */

Pinterest.prototype.loaded = function() {
  return true;
};

/**
 * Track a page view.
 *
 * @param {Facade} page
 */

Pinterest.prototype.page = function() {

};

/**
 * Track an event.
 *
 * @param {Facade} track
 */

Pinterest.prototype.track = function(track) {
  var self = this;
  var events = this.events(track.event());
  each(function(pixel) {
    self.fire(pixel);
  }, events);
};

/**
 * Fire the pixel.
 */

Pinterest.prototype.fire = function(pixel) {

  var src = 'https://ct.pinterest.com/?tid='+ pixel + '&value=0.00&quantity=1';

  var flDiv = document.body.appendChild(document.createElement('img'));
  flDiv.style.height = '1';
  flDiv.style.width = '1';
  flDiv.style.display = 'none';
  flDiv.setAttribute('alt', '');
  flDiv.setAttribute('src', src);
};
<|endoftext|>


<commit_before>'use strict';

let fs = require('fs');
let path = require('path');
let gulp = require('gulp');
let sass = require('gulp-sass');
let bourbon = require('node-bourbon');
let sourcemaps = require('gulp-sourcemaps');
let cssmin = require('gulp-cssmin');
let rename = require('gulp-rename');
let plumber = require('gulp-plumber');
let notify  = require('gulp-notify');
let uglify = require('gulp-uglify');
let ejs = require('gulp-ejs');
let gulpFilter = require('gulp-filter');
let bower = require('main-bower-files');
let concat = require("gulp-concat");
let less = require('gulp-less');
let imagemin = require('gulp-imagemin');
let browserSync = require('browser-sync').create();
let pngquant = require('imagemin-pngquant');
let mozjpeg = require('imagemin-mozjpeg');
let babel = require("gulp-babel");
let i18n = require("i18n");
let runSequence = require('run-sequence');
let browserify = require('browserify');
let babelify = require('babelify');
let source = require('vinyl-source-stream');
let buffer = require('vinyl-buffer');
let rimraf = require('rimraf');
let autoprefixer = require('gulp-autoprefixer');
let sitemap = require('gulp-sitemap');
let ftp = require('vinyl-ftp');

const distPath = "dest/";
const baseURL = "www.y-modify.org";
const protocol = "http";

const locales = {
  id: ['en', 'ja'],
  name: ['English', '日本語']
};

i18n.configure({
    locales: locales.id,
    directory: __dirname + '/locales'
});

gulp.task('browser-sync', function() {
  browserSync.init({
    proxy: "localhost:80"
  });
});

gulp.task('browser-reload', function() {
  browserSync.reload();
});

gulp.task('imagemin', function() {
  gulp.src('images/**/*')
    .pipe(imagemin([
         pngquant({
           quality: '80-90',
           speed: 1,
           floyd: 0
         }),
         mozjpeg({
           quality: 90,
           progressive: true
         }),
         imagemin.svgo(),
         imagemin.optipng(),
         imagemin.gifsicle()
       ]
    ))
    .pipe(gulp.dest(distPath+'/images'));
});

gulp.task('sass', function(){
  return gulp.src('sass/style.scss')
  .pipe(plumber({
    errorHandler: notify.onError("Sass error: <%= error.message %>")
  }))
  .pipe(sourcemaps.init())
  .pipe(sass({includePaths: bourbon.with('css')}))
  .pipe(autoprefixer({
            browsers: ['last 2 versions'],
            cascade: false
        }))
  .pipe(sourcemaps.write())
  .pipe(cssmin())
  .pipe(rename({suffix: '.min'}))
  .pipe(gulp.dest(distPath+'/css'));
});

gulp.task('fonts', function() {
  return gulp.src(['bower_components/font-awesome/fonts/**/*', 'fonts/**/*'])
  .pipe(gulp.dest(distPath+'/fonts'))
});

gulp.task('js', () => {
  return browserify('js/script.js', { debug: true })
    .transform("debowerify")
    .transform("babelify", {
      presets: ["es2015"],
      compact: false
    })
    .on("error", function (err) { notify.onError("js-babelify error: <%= err.message %>") })
    .bundle()
    .pipe(source('script.js'))
    .pipe(buffer())
    .pipe(uglify({preserveComments: 'some'}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(distPath+'/js'));
});

gulp.task('ejs', () => {
  const HISTORY = JSON.parse(fs.readFileSync('yamax/history.json', 'utf8'));
  const srcs = ['**/*.ejs', '!' + 'dest/**/*.ejs', '!' + '**/_*.ejs', '!' + 'alllang/**/*.ejs', '!' + 'node_modules/**/*.ejs'];
  let config = {
    history: HISTORY,
    t: (msg) => {
      return i18n.__(msg);
    },
    locale: "",
    locales: locales,
    baseURL: baseURL,
    twitter: "@ymodify314",
    sitename: "Y-modify",
    enbanner: false,
    bannerURL: "",//`http://blog.y-modify.org/${locales.id[index]}2017/03/02/10000views/`,
    bannerMessage: "banner-thanks",
    protocol: protocol,
    absolutePath: (filename) => {
      return filename.split(path.basename(__dirname))[filename.split(path.basename(__dirname)).length - 1].replace('.ejs','.php').replace('index.php', '');
    },
    relativePath: (absPath) => {
      return '../'.repeat([absPath.split('/').length - 2]);
    }
  };

  (function ep(index){
    new Promise(function(resolve, reject) {
      console.log(`${locales.name[index]}'s translation has started`);
      config.locale = locales.id[index];
      config.bannerURL = `http://blog.y-modify.org/${locales.id[index]}/2017/03/02/10000views/`;
      i18n.setLocale(locales.id[index]);
      gulp.src(srcs)
      .pipe(ejs(config, {"ext": ".php"})).on('error', (m) => {
        console.log(m);
        notify.onError("ejs error: <%= m %>");
        reject();
      })
      .pipe(gulp.dest(`${distPath}/${locales.id[index]}`))
      .on('end', () => {
        resolve();
        console.log(`${locales.name[index]}'s translation has done`);
      });
    }).then(() => {
      if(index+1 < locales.id.length)
        ep(index+1);
    });
  }(0));
});

gulp.task('alllang:ejs', function() {
  return gulp.src(['alllang/**/*.ejs', '!' + 'alllang/**/_*.ejs'])
  .pipe(ejs({
              locale: "en",
              baseURL: baseURL,
              twitter: "@ymodify314",
              sitename: "Y-modify",
              locales: locales,
              protocol: protocol,
              absolutePath: (filename) => {
                return filename.split(path.basename(__dirname))[filename.split(path.basename(__dirname)).length - 1].replace('.ejs','.php').replace('index.php', '');
              },
              relativePath: (absPath) => {
                return '../'.repeat([absPath.split('/').length - 2]);
              }
            }, {"ext": ".php"}))
  .pipe(gulp.dest(distPath));
});

gulp.task('alllang:all', () => {
  return gulp.src(['alllang/**/*', 'alllang/**/.*', '!' + 'alllang/**/*.ejs'])
  .pipe(gulp.dest(distPath));
});

gulp.task('alllang', ['alllang:ejs', 'alllang:all']);

gulp.task('sitemap', ()=>{
  return gulp.src(locales.id.map((element)=>distPath+element+"/**/*.php").concat(["!"+distPath+"**/error/**/*.php"]), {
        read: false
    })
    .pipe(sitemap({
        siteUrl: protocol+'://'+baseURL
    }))
    .pipe(gulp.dest(distPath));
});

gulp.task('imagecopy', function() {
  return gulp.src(['images/**/*'])
  .pipe(gulp.dest(distPath+'/images'));
});

gulp.task('deploy', () => {
  let config = JSON.parse(fs.readFileSync("ftp.json", 'utf8'));
  config.log = console.log;

  // デプロイ先ディレクトリ
  let remoteDest = '/home/y-modify/www/';

  let conn = ftp.create(config);
  return gulp.src([distPath+'**/*','!'+distPath+'**/.DS_Store'], {buffer: false, dot: true})
    .pipe(conn.newerOrDifferentSize(remoteDest))
    .pipe(conn.dest(remoteDest));
});

gulp.task('clean', function (cb) {
  rimraf(distPath, cb);
});

gulp.task('process', ['fonts', 'imagemin', 'sass', 'js', 'ejs', 'alllang']);

gulp.task('watch' ,['browser-sync'] ,function(){
    gulp.watch('sass/**/*.scss', ['sass']);
    gulp.watch(['js/**/*.js', '!' + 'js/**/_*.js'], ['js']);
    gulp.watch(['**/*.ejs', '!' + 'node_modules/**/*.ejs','!' + 'alllang/**/*.ejs', 'locales/*.json'], ['ejs']);
    gulp.watch(['alllang/**/*.ejs', '!' + 'alllang/**/_*.ejs'], ['alllang']);
    gulp.watch(['fonts/**/*', 'bower_components/font-awesome/fonts/**/*'], ['fonts']);
    gulp.watch(['images/**/*'], ['imagecopy']);
    gulp.watch(distPath+'/**/*', ['browser-reload']);
});

gulp.task('default', ['process']);
<commit_msg>Use const for all requires<commit_after>'use strict';

const fs = require('fs');
const path = require('path');
const gulp = require('gulp');
const sass = require('gulp-sass');
const bourbon = require('node-bourbon');
const sourcemaps = require('gulp-sourcemaps');
const cssmin = require('gulp-cssmin');
const rename = require('gulp-rename');
const plumber = require('gulp-plumber');
const notify  = require('gulp-notify');
const uglify = require('gulp-uglify');
const ejs = require('gulp-ejs');
const gulpFilter = require('gulp-filter');
const bower = require('main-bower-files');
const concat = require("gulp-concat");
const less = require('gulp-less');
const imagemin = require('gulp-imagemin');
const browserSync = require('browser-sync').create();
const pngquant = require('imagemin-pngquant');
const mozjpeg = require('imagemin-mozjpeg');
const babel = require("gulp-babel");
const i18n = require("i18n");
const runSequence = require('run-sequence');
const browserify = require('browserify');
const babelify = require('babelify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const rimraf = require('rimraf');
const autoprefixer = require('gulp-autoprefixer');
const sitemap = require('gulp-sitemap');
const ftp = require('vinyl-ftp');

const distPath = "dest/";
const baseURL = "www.y-modify.org";
const protocol = "http";

const locales = {
  id: ['en', 'ja'],
  name: ['English', '日本語']
};

i18n.configure({
    locales: locales.id,
    directory: __dirname + '/locales'
});

gulp.task('browser-sync', function() {
  browserSync.init({
    proxy: "localhost:80"
  });
});

gulp.task('browser-reload', function() {
  browserSync.reload();
});

gulp.task('imagemin', function() {
  gulp.src('images/**/*')
    .pipe(imagemin([
         pngquant({
           quality: '80-90',
           speed: 1,
           floyd: 0
         }),
         mozjpeg({
           quality: 90,
           progressive: true
         }),
         imagemin.svgo(),
         imagemin.optipng(),
         imagemin.gifsicle()
       ]
    ))
    .pipe(gulp.dest(distPath+'/images'));
});

gulp.task('sass', function(){
  return gulp.src('sass/style.scss')
  .pipe(plumber({
    errorHandler: notify.onError("Sass error: <%= error.message %>")
  }))
  .pipe(sourcemaps.init())
  .pipe(sass({includePaths: bourbon.with('css')}))
  .pipe(autoprefixer({
            browsers: ['last 2 versions'],
            cascade: false
        }))
  .pipe(sourcemaps.write())
  .pipe(cssmin())
  .pipe(rename({suffix: '.min'}))
  .pipe(gulp.dest(distPath+'/css'));
});

gulp.task('fonts', function() {
  return gulp.src(['bower_components/font-awesome/fonts/**/*', 'fonts/**/*'])
  .pipe(gulp.dest(distPath+'/fonts'))
});

gulp.task('js', () => {
  return browserify('js/script.js', { debug: true })
    .transform("debowerify")
    .transform("babelify", {
      presets: ["es2015"],
      compact: false
    })
    .on("error", function (err) { notify.onError("js-babelify error: <%= err.message %>") })
    .bundle()
    .pipe(source('script.js'))
    .pipe(buffer())
    .pipe(uglify({preserveComments: 'some'}))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest(distPath+'/js'));
});

gulp.task('ejs', () => {
  const HISTORY = JSON.parse(fs.readFileSync('yamax/history.json', 'utf8'));
  const srcs = ['**/*.ejs', '!' + 'dest/**/*.ejs', '!' + '**/_*.ejs', '!' + 'alllang/**/*.ejs', '!' + 'node_modules/**/*.ejs'];
  let config = {
    history: HISTORY,
    t: (msg) => {
      return i18n.__(msg);
    },
    locale: "",
    locales: locales,
    baseURL: baseURL,
    twitter: "@ymodify314",
    sitename: "Y-modify",
    enbanner: false,
    bannerURL: "",//`http://blog.y-modify.org/${locales.id[index]}2017/03/02/10000views/`,
    bannerMessage: "banner-thanks",
    protocol: protocol,
    absolutePath: (filename) => {
      return filename.split(path.basename(__dirname))[filename.split(path.basename(__dirname)).length - 1].replace('.ejs','.php').replace('index.php', '');
    },
    relativePath: (absPath) => {
      return '../'.repeat([absPath.split('/').length - 2]);
    }
  };

  (function ep(index){
    new Promise(function(resolve, reject) {
      console.log(`${locales.name[index]}'s translation has started`);
      config.locale = locales.id[index];
      config.bannerURL = `http://blog.y-modify.org/${locales.id[index]}/2017/03/02/10000views/`;
      i18n.setLocale(locales.id[index]);
      gulp.src(srcs)
      .pipe(ejs(config, {"ext": ".php"})).on('error', (m) => {
        console.log(m);
        notify.onError("ejs error: <%= m %>");
        reject();
      })
      .pipe(gulp.dest(`${distPath}/${locales.id[index]}`))
      .on('end', () => {
        resolve();
        console.log(`${locales.name[index]}'s translation has done`);
      });
    }).then(() => {
      if(index+1 < locales.id.length)
        ep(index+1);
    });
  }(0));
});

gulp.task('alllang:ejs', function() {
  return gulp.src(['alllang/**/*.ejs', '!' + 'alllang/**/_*.ejs'])
  .pipe(ejs({
              locale: "en",
              baseURL: baseURL,
              twitter: "@ymodify314",
              sitename: "Y-modify",
              locales: locales,
              protocol: protocol,
              absolutePath: (filename) => {
                return filename.split(path.basename(__dirname))[filename.split(path.basename(__dirname)).length - 1].replace('.ejs','.php').replace('index.php', '');
              },
              relativePath: (absPath) => {
                return '../'.repeat([absPath.split('/').length - 2]);
              }
            }, {"ext": ".php"}))
  .pipe(gulp.dest(distPath));
});

gulp.task('alllang:all', () => {
  return gulp.src(['alllang/**/*', 'alllang/**/.*', '!' + 'alllang/**/*.ejs'])
  .pipe(gulp.dest(distPath));
});

gulp.task('alllang', ['alllang:ejs', 'alllang:all']);

gulp.task('sitemap', ()=>{
  return gulp.src(locales.id.map((element)=>distPath+element+"/**/*.php").concat(["!"+distPath+"**/error/**/*.php"]), {
        read: false
    })
    .pipe(sitemap({
        siteUrl: protocol+'://'+baseURL
    }))
    .pipe(gulp.dest(distPath));
});

gulp.task('imagecopy', function() {
  return gulp.src(['images/**/*'])
  .pipe(gulp.dest(distPath+'/images'));
});

gulp.task('deploy', () => {
  let config = JSON.parse(fs.readFileSync("ftp.json", 'utf8'));
  config.log = console.log;

  // デプロイ先ディレクトリ
  let remoteDest = '/home/y-modify/www/';

  let conn = ftp.create(config);
  return gulp.src([distPath+'**/*','!'+distPath+'**/.DS_Store'], {buffer: false, dot: true})
    .pipe(conn.newerOrDifferentSize(remoteDest))
    .pipe(conn.dest(remoteDest));
});

gulp.task('clean', function (cb) {
  rimraf(distPath, cb);
});

gulp.task('process', ['fonts', 'imagemin', 'sass', 'js', 'ejs', 'alllang']);

gulp.task('watch' ,['browser-sync'] ,function(){
    gulp.watch('sass/**/*.scss', ['sass']);
    gulp.watch(['js/**/*.js', '!' + 'js/**/_*.js'], ['js']);
    gulp.watch(['**/*.ejs', '!' + 'node_modules/**/*.ejs','!' + 'alllang/**/*.ejs', 'locales/*.json'], ['ejs']);
    gulp.watch(['alllang/**/*.ejs', '!' + 'alllang/**/_*.ejs'], ['alllang']);
    gulp.watch(['fonts/**/*', 'bower_components/font-awesome/fonts/**/*'], ['fonts']);
    gulp.watch(['images/**/*'], ['imagecopy']);
    gulp.watch(distPath+'/**/*', ['browser-reload']);
});

gulp.task('default', ['process']);
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var debug = require('debug')('wpcom:media');

/**
 * Media methods
 *
 * @param {String} id
 * @param {String} sid site id
 * @param {WPCOM} wpcom
 * @api public
 */

function Media(id, sid, wpcom){
  if (!(this instanceof Media)) return new Media(id, sid, wpcom);

  this.wpcom = wpcom;
  this._sid = sid;
  this._id = id;

  if (!this._id) {
    debug('WARN: media id is not defined');
  }
}

/**
 * Get media
 *
 * @param {Object} [params]
 * @param {Function} fn
 * @api public
 */

Media.prototype.get = function(params, fn){
  var set = { site: this._sid, media_id: this._id };
  this.wpcom.sendRequest('media.get', set, params, fn);
};

/**
 * Add media
 *
 * @param {Object} body
 * @param {Function} fn
 * @api public
 */

Media.prototype.add = function(body, fn){
  var set = { site: this._sid };
  this.wpcom.sendRequest('media.add', set, { body: body }, fn);
};

/**
 * Edit media
 *
 * @param {Object} body
 * @param {Function} fn
 * @api public
 */

Media.prototype.update = function(body, fn){
  var set = { site: this._sid, media_id: this._id };
  this.wpcom.sendRequest('media.update', set, { body: body }, fn);
};

/**
 * Delete media
 *
 * @param {Function} fn
 * @api public
 */

Media.prototype.delete = function(fn){
  var set = { site: this._sid, media_id: this._id };
  this.wpcom.sendRequest('media.delete', set, fn);
};

/**
 * Expose `Media` module
 */

module.exports = Media;
<commit_msg>media: update methods<commit_after>
/**
 * Module dependencies.
 */

var debug = require('debug')('wpcom:media');

/**
 * Media methods
 *
 * @param {String} id
 * @param {String} sid site id
 * @param {WPCOM} wpcom
 * @api public
 */

function Media(id, sid, wpcom){
  if (!(this instanceof Media)) return new Media(id, sid, wpcom);

  this.wpcom = wpcom;
  this._sid = sid;
  this._id = id;

  if (!this._id) {
    debug('WARN: media id is not defined');
  }
}

/**
 * Get media
 *
 * @param {Object} [query]
 * @param {Function} fn
 * @api public
 */

Media.prototype.get = function(query, fn){
  var path = '/sites/' + this._sid + '/media/' + this._id;
  this.wpcom.sendRequest(path, query, null, fn);
};

/**
 * Add media
 *
 * @param {Object} body
 * @param {Function} fn
 * @api public
 */

Media.prototype.add = function(body, fn){
  var path = '/sites/' + this._sid + '/media/new';
  this.wpcom.sendRequest({ path: path, method: 'post' }, null, body, fn);
};

/**
 * Edit media
 *
 * @param {Object} body
 * @param {Function} fn
 * @api public
 */

Media.prototype.update = function(body, fn){
  var path = '/sites/' + this._sid + '/media/' + this._id;
  this.wpcom.sendRequest({ path: path, method: 'post' }, null, body, fn);
};

/**
 * Delete media
 *
 * @param {Function} fn
 * @api public
 */

Media.prototype.delete = function(fn){
  var path = '/sites/' + this._sid + '/media/' + this._id + '/delete';
  this.wpcom.sendRequest({ path: path, method: 'post' }, null, body, fn);
};

/**
 * Expose `Media` module
 */

module.exports = Media;
<|endoftext|>


<commit_before>require('../../stylus/components/_expansion-panel.styl')

import Themeable from '../../mixins/themeable'

export default {
  name: 'v-expansion-panel',

  mixins: [Themeable],

  provide () {
    return {
      panelClick: this.panelClick,
      focusable: this.focusable
    }
  },

  props: {
    expand: Boolean,
    focusable: Boolean,
    inset: Boolean,
    popout: Boolean
  },

  methods: {
    getChildren () {
      return this.$children.filter(c => {
        if (!c.$options) return

        return c.$options._componentTag === 'v-expansion-panel-content'
      })
    },
    panelClick (uid) {
      if (!this.expand) {
        return this.getChildren()
          .forEach(e => e.toggle(uid))
      }

      const panel = this.$children.find(e => e._uid === uid)

      panel && panel.toggle(uid)
    }
  },

  render (h) {
    return h('ul', {
      staticClass: 'expansion-panel',
      'class': {
        'expansion-panel--focusable': this.focusable,
        'expansion-panel--popout': this.popout,
        'expansion-panel--inset': this.inset,
        ...this.themeClasses
      }
    }, this.$slots.default)
  }
}
<commit_msg>fix: (VExpansionPanel) use component name instead of private property _componentTag (#2312)<commit_after>require('../../stylus/components/_expansion-panel.styl')

import Themeable from '../../mixins/themeable'

export default {
  name: 'v-expansion-panel',

  mixins: [Themeable],

  provide () {
    return {
      panelClick: this.panelClick,
      focusable: this.focusable
    }
  },

  props: {
    expand: Boolean,
    focusable: Boolean,
    inset: Boolean,
    popout: Boolean
  },

  methods: {
    getChildren () {
      return this.$children.filter(c => {
        if (!c.$options) return

        return c.$options.name === 'v-expansion-panel-content'
      })
    },
    panelClick (uid) {
      if (!this.expand) {
        return this.getChildren()
          .forEach(e => e.toggle(uid))
      }

      const panel = this.$children.find(e => e._uid === uid)

      panel && panel.toggle(uid)
    }
  },

  render (h) {
    return h('ul', {
      staticClass: 'expansion-panel',
      'class': {
        'expansion-panel--focusable': this.focusable,
        'expansion-panel--popout': this.popout,
        'expansion-panel--inset': this.inset,
        ...this.themeClasses
      }
    }, this.$slots.default)
  }
}
<|endoftext|>


<commit_before>var ModelUtilities = {
  extendObject: function (object, definition) {
    _.extend(object, definition._fields);
    _.each(definition._behaviors, function (behavior) {
      _.extend(object, behavior._fields);
    });
  },

  extendPrototype: function (prototype, definition) {
    _.extend(prototype, {
      _definition: definition,
    }, definition._methods);
    _.each(definition._behaviors, function (behavior) {
      _.extend(prototype, behavior._methods);
    });
  },

  setup: function (definition, setup) {
    if (_.isFunction(setup)) {
      setup.call(definition);
    } else if (_.isObject(setup)) {
      // List of allowed schema fields and its corresponding functions.
      var types = {
        constructor: 'setConstructor',
        fields: 'setFields',
        required: 'setRequired',
        validators: 'setValidators',
        methods: 'setMethods',
        events: 'setEvents',
        behaviors: 'setBehaviors'
      };
      _.each(setup, function (options, name) {
        if (types[name]) {
          definition[types[name]](options);
        }
      });
    }
  },

  checkRequired: function () {
    var self = this;

    // Get list of required fields from model.
    var required = _.extend({}, self._definition._required);
    // Get list of required fields from behaviors.
    _.each(self._definition._behaviors, function (behavior) {
      _.extend(required, behavior._required);
    });

    // Iterate over required fields and check if they are present in the object
    // and not null or undefined.
    _.each(required, function (errorMessage, fieldName) {
      if (!_.has(self, fieldName) || self[fieldName] === null || self[fieldName] === undefined) {
        throw new Meteor.Error(422, errorMessage);
      }
    });
  },

  getFields: function () {
    var self = this;

    // Get list of allowed fields from model.
    var fields = _.extend({}, self._definition._fields);
    // Get list of allowed fields from behaviors.
    _.each(self._definition._behaviors, function (behavior) {
      _.extend(fields, behavior._fields);
    });

    // Get only keys from the fields object.
    fields = _.keys(fields);

    // Pick only allowed fields from the object.
    var attrs = _.pick(self, fields);
    return _.omit(attrs, _.functions(attrs));
  },

  runEvents: function (name) {
    var self = this,
        events = [];

    // Get events from model.
    if (self._definition._events[name]) {
      events.push(self._definition._events[name]);
    }
    // Get events from behaviors.
    _.each(self._definition._behaviors, function (behavior) {
      if (behavior._events[name]) {
        events.push(behavior._events[name]);
      }
    });
    // Run events.
    _.each(events, function (event) {
      event.call(self);
    });
  }
};

var Definition = function (collection, setup) {
  this._collection = collection;
  this._constructor = function (attrs) {
    _.extend(this, attrs);
  };
  this._fields = {};
  this._required = {};
  this._validators = {};
  this._methods = {};
  this._events = {};
  this._behaviors = {};

  ModelUtilities.setup(this, setup);
};

Definition.prototype.getCollection = function () {
  return this._collection;
};

Definition.prototype.setConstructor = function (constructor) {
  if (!_.isFunction(constructor)) {
    throw new Error('Invalid constructor function');
  }
  this._constructor = constructor;
};

Definition.prototype.setFields = function (fields) {
  if (!_.isObject(fields)) {
    throw new Error('Invalid parameters passed to `setFields` function');
  }
  _.extend(this._fields, fields);
};

Definition.prototype.getFields = function () {
  return this._fields;
};

Definition.prototype.setRequired = function (required) {
  if (!_.isObject(required)) {
    throw new Error('Invalid parameters passed to `setRequired` function');
  }
  _.extend(this._required, required);
};

Definition.prototype.getRequired = function () {
  return this._required;
};

Definition.prototype.setValidator = function (name, options) {
  // Check parameters type validity.
  if(!_.isString(name) || !_.isObject(options)) {
    throw new Error('Invalid parameters type');
  }
  this._validators[name] = new Validators[name](options);
};

Definition.prototype.setValidators = function (validators) {
  var self = this;

  if (!_.isObject(validators)) {
    throw new Error('Invalid parameters passed to `setValidators` function');
  }
  _.each(validators, function (validator, name) {
    self.setValidator(name, validator);
  });
};

Definition.prototype.getValidator = function (name) {
  return this._validators[name];
};

Definition.prototype.getValidators = function () {
  return this._validators;
};

Definition.prototype.setMethods = function (methods) {
  if (!_.isObject(methods)) {
    throw new Error('Invalid parameters passed to `setMethods` function');
  }
  _.extend(this._methods, methods);
};

Definition.prototype.getMethods = function () {
  return this._methods;
};

Definition.prototype.setEvents = function (events) {
  if (!_.isObject(events)) {
    throw new Error('Invalid parameters passed to `setEvents` function');
  }
  _.extend(this._events, events);
};

Definition.prototype.getEvents = function () {
  return this._events;
};

Definition.prototype.setBehavior = function (name, options) {
  options = options || {};

  // Check parameters type validity.
  if(!_.isString(name) || !_.isObject(options)) {
    throw new Error('Invalid parameters type');
  }
  // Check if behavior exists in the `Behaviors` list.
  if (!_.has(Behaviors, name)) {
    throw new Error('`' + name + '` behavior does not exist');
  }
  // Get given behavior function.
  var BehaviorFunction = Behaviors[name];
  // Check if behavior is a function.
  if (!_.isFunction(BehaviorFunction)) {
    throw new Error('`' + name + '` behavior is not a function');
  }
  // Execute behavior function with model specific behavior options.
  this._behaviors[name] = new BehaviorFunction(options);
};

Definition.prototype.setBehaviors = function (behaviors) {
  var self = this;

  if (!_.isObject(behaviors)) {
    throw new Error('Invalid parameters passed to `setBehaviors` function');
  }
  _.each(behaviors, function (behavior, name) {
    self.setBehavior(name, behavior);
  });
};

Definition.prototype.getBehavior = function (name) {
  // Check if model implements given behavior.
  if (!_.has(this._behaviors, name)) {
    throw new Error('`' + name + '` behavior is not implemented');
  }
  return this._behaviors[name];
};

Definition.prototype.getBehaviors = function () {
  return this._behaviors;
};

ModelBase = function () {};

ModelBase.prototype.save = function () {
  var self = this;

  // Check if all required fields had been given.
  ModelUtilities.checkRequired.call(self);

  // Execute pre events.
  ModelUtilities.runEvents.call(self, 'preSave');
  if (self._id) {
    ModelUtilities.runEvents.call(self, 'preUpdate');
  } else {
    ModelUtilities.runEvents.call(self, 'preInsert');
  }

  // Get only fields that need to be save in database.
  var fields = ModelUtilities.getFields.call(self);

  // Decide if we need to update or insert document into collection.
  if (self._id) {
    self._definition._collection.update(self._id, { $set: fields });
  } else {
    self._id = self._definition._collection.insert(fields);
  }

  // Execute post events.
  if (self._id) {
    ModelUtilities.runEvents.call(self, 'postUpdate');
  } else {
    ModelUtilities.runEvents.call(self, 'postInsert');
  }
  ModelUtilities.runEvents.call(self, 'postSave');

  return self._id;
};

ModelBase.prototype.remove = function () {
  var self = this;

  ModelUtilities.runEvents.call(self, 'preRemove');
  self._definition._collection.remove(this._id);
  delete self._id;
  ModelUtilities.runEvents.call(self, 'postRemove');
};

Model = function (collection, setup) {
  // Check parameters validity.
  if (!(collection instanceof Meteor.Collection)) {
    throw new Error('Pass `Meteor.Collection` object');
  }
  if (!_.isFunction(setup) && !_.isObject(setup)) {
    throw new Error('Pass model definition setup function');
  }

  // Create model definition object.
  var definition = new Definition(collection, setup);

  // Create `Model` class for given `collection`.
  var Model = function () {
    var self = this,
        args = arguments;

    // Extend object of `Model` class with model definition.
    ModelUtilities.extendObject(self, definition);

    // Run constructor function.
    definition._constructor.apply(self, args);
  };

  // Extend `Model` class with `ModelBase` class and model definition.
  Model.prototype = new ModelBase();
  ModelUtilities.extendPrototype(Model.prototype, definition);
  Model.constructor = Model;

  return Model;
};
<commit_msg>Autotransform fetched documents<commit_after>var ModelUtilities = {
  extendObject: function (object, definition) {
    _.extend(object, definition._fields);
    _.each(definition._behaviors, function (behavior) {
      _.extend(object, behavior._fields);
    });
  },

  extendPrototype: function (prototype, definition) {
    _.extend(prototype, {
      _definition: definition,
    }, definition._methods);
    _.each(definition._behaviors, function (behavior) {
      _.extend(prototype, behavior._methods);
    });
  },

  setup: function (definition, setup) {
    if (_.isFunction(setup)) {
      setup.call(definition);
    } else if (_.isObject(setup)) {
      // List of allowed schema fields and its corresponding functions.
      var types = {
        constructor: 'setConstructor',
        fields: 'setFields',
        required: 'setRequired',
        validators: 'setValidators',
        methods: 'setMethods',
        events: 'setEvents',
        behaviors: 'setBehaviors'
      };
      _.each(setup, function (options, name) {
        if (types[name]) {
          definition[types[name]](options);
        }
      });
    }
  },

  checkRequired: function () {
    var self = this;

    // Get list of required fields from model.
    var required = _.extend({}, self._definition._required);
    // Get list of required fields from behaviors.
    _.each(self._definition._behaviors, function (behavior) {
      _.extend(required, behavior._required);
    });

    // Iterate over required fields and check if they are present in the object
    // and not null or undefined.
    _.each(required, function (errorMessage, fieldName) {
      if (!_.has(self, fieldName) || self[fieldName] === null || self[fieldName] === undefined) {
        throw new Meteor.Error(422, errorMessage);
      }
    });
  },

  getFields: function () {
    var self = this;

    // Get list of allowed fields from model.
    var fields = _.extend({}, self._definition._fields);
    // Get list of allowed fields from behaviors.
    _.each(self._definition._behaviors, function (behavior) {
      _.extend(fields, behavior._fields);
    });

    // Get only keys from the fields object.
    fields = _.keys(fields);

    // Pick only allowed fields from the object.
    var attrs = _.pick(self, fields);
    return _.omit(attrs, _.functions(attrs));
  },

  runEvents: function (name) {
    var self = this,
        events = [];

    // Get events from model.
    if (self._definition._events[name]) {
      events.push(self._definition._events[name]);
    }
    // Get events from behaviors.
    _.each(self._definition._behaviors, function (behavior) {
      if (behavior._events[name]) {
        events.push(behavior._events[name]);
      }
    });
    // Run events.
    _.each(events, function (event) {
      event.call(self);
    });
  }
};

var Definition = function (collection, setup) {
  this._collection = collection;
  this._constructor = function (attrs) {
    _.extend(this, attrs);
  };
  this._fields = {};
  this._required = {};
  this._validators = {};
  this._methods = {};
  this._events = {};
  this._behaviors = {};

  ModelUtilities.setup(this, setup);
};

Definition.prototype.getCollection = function () {
  return this._collection;
};

Definition.prototype.setConstructor = function (constructor) {
  if (!_.isFunction(constructor)) {
    throw new Error('Invalid constructor function');
  }
  this._constructor = constructor;
};

Definition.prototype.setFields = function (fields) {
  if (!_.isObject(fields)) {
    throw new Error('Invalid parameters passed to `setFields` function');
  }
  _.extend(this._fields, fields);
};

Definition.prototype.getFields = function () {
  return this._fields;
};

Definition.prototype.setRequired = function (required) {
  if (!_.isObject(required)) {
    throw new Error('Invalid parameters passed to `setRequired` function');
  }
  _.extend(this._required, required);
};

Definition.prototype.getRequired = function () {
  return this._required;
};

Definition.prototype.setValidator = function (name, options) {
  // Check parameters type validity.
  if(!_.isString(name) || !_.isObject(options)) {
    throw new Error('Invalid parameters type');
  }
  this._validators[name] = new Validators[name](options);
};

Definition.prototype.setValidators = function (validators) {
  var self = this;

  if (!_.isObject(validators)) {
    throw new Error('Invalid parameters passed to `setValidators` function');
  }
  _.each(validators, function (validator, name) {
    self.setValidator(name, validator);
  });
};

Definition.prototype.getValidator = function (name) {
  return this._validators[name];
};

Definition.prototype.getValidators = function () {
  return this._validators;
};

Definition.prototype.setMethods = function (methods) {
  if (!_.isObject(methods)) {
    throw new Error('Invalid parameters passed to `setMethods` function');
  }
  _.extend(this._methods, methods);
};

Definition.prototype.getMethods = function () {
  return this._methods;
};

Definition.prototype.setEvents = function (events) {
  if (!_.isObject(events)) {
    throw new Error('Invalid parameters passed to `setEvents` function');
  }
  _.extend(this._events, events);
};

Definition.prototype.getEvents = function () {
  return this._events;
};

Definition.prototype.setBehavior = function (name, options) {
  options = options || {};

  // Check parameters type validity.
  if(!_.isString(name) || !_.isObject(options)) {
    throw new Error('Invalid parameters type');
  }
  // Check if behavior exists in the `Behaviors` list.
  if (!_.has(Behaviors, name)) {
    throw new Error('`' + name + '` behavior does not exist');
  }
  // Get given behavior function.
  var BehaviorFunction = Behaviors[name];
  // Check if behavior is a function.
  if (!_.isFunction(BehaviorFunction)) {
    throw new Error('`' + name + '` behavior is not a function');
  }
  // Execute behavior function with model specific behavior options.
  this._behaviors[name] = new BehaviorFunction(options);
};

Definition.prototype.setBehaviors = function (behaviors) {
  var self = this;

  if (!_.isObject(behaviors)) {
    throw new Error('Invalid parameters passed to `setBehaviors` function');
  }
  _.each(behaviors, function (behavior, name) {
    self.setBehavior(name, behavior);
  });
};

Definition.prototype.getBehavior = function (name) {
  // Check if model implements given behavior.
  if (!_.has(this._behaviors, name)) {
    throw new Error('`' + name + '` behavior is not implemented');
  }
  return this._behaviors[name];
};

Definition.prototype.getBehaviors = function () {
  return this._behaviors;
};

ModelBase = function () {};

ModelBase.prototype.save = function () {
  var self = this;

  // Check if all required fields had been given.
  ModelUtilities.checkRequired.call(self);

  // Execute pre events.
  ModelUtilities.runEvents.call(self, 'preSave');
  if (self._id) {
    ModelUtilities.runEvents.call(self, 'preUpdate');
  } else {
    ModelUtilities.runEvents.call(self, 'preInsert');
  }

  // Get only fields that need to be save in database.
  var fields = ModelUtilities.getFields.call(self);

  // Decide if we need to update or insert document into collection.
  if (self._id) {
    self._definition._collection.update(self._id, { $set: fields });
  } else {
    self._id = self._definition._collection.insert(fields);
  }

  // Execute post events.
  if (self._id) {
    ModelUtilities.runEvents.call(self, 'postUpdate');
  } else {
    ModelUtilities.runEvents.call(self, 'postInsert');
  }
  ModelUtilities.runEvents.call(self, 'postSave');

  return self._id;
};

ModelBase.prototype.remove = function () {
  var self = this;

  ModelUtilities.runEvents.call(self, 'preRemove');
  self._definition._collection.remove(this._id);
  delete self._id;
  ModelUtilities.runEvents.call(self, 'postRemove');
};

Model = function (collection, setup, transform) {
  // Check parameters validity.
  if (!(collection instanceof Meteor.Collection)) {
    throw new Error('Pass `Meteor.Collection` object');
  }
  if (!_.isFunction(setup) && !_.isObject(setup)) {
    throw new Error('Pass model definition setup function');
  }
  transform = transform || true;

  // Create model definition object.
  var definition = new Definition(collection, setup);

  // Create `Model` class for given `collection`.
  var Model = function () {
    var self = this,
        args = arguments;

    // Extend object of `Model` class with model definition.
    ModelUtilities.extendObject(self, definition);

    // Run constructor function.
    definition._constructor.apply(self, args);
  };

  // Extend `Model` class with `ModelBase` class and model definition.
  Model.prototype = new ModelBase();
  ModelUtilities.extendPrototype(Model.prototype, definition);
  Model.constructor = Model;

  // Autotransform documents to model class.
  if (transform) {
    var transformFunction = function (doc) {
      return new Model(doc);
    };
    definition._collection._transform = Deps._makeNonreactive(transformFunction);
  } else {
    definition._collection._transform = null;
  }

  return Model;
};
<|endoftext|>