<commit_before>var INT_PG_HOST = process.env.INT_PG_HOST || 'localhost',
    INT_PG_PORT = process.env.INT_PG_PORT || 5432,
    INT_PG_USER = process.env.INT_PG_USER,
    INT_PG_PASS = process.env.INT_PG_PASS,
    INT_PG_DB   = process.env.INT_PG_DB || 'medic-analytics-test',
    INT_COUCHDB_URL = process.env.INT_COUCHDB_URL || 'http://admin:pass@localhost:5984/medic-analytics-test';

process.env.POSTGRESQL_URL = 'postgres://' +
  (INT_PG_USER ? INT_PG_USER : '') +
  (INT_PG_PASS ? INT_PG_PASS += ':' + INT_PG_PASS : '') +
  (INT_PG_USER ? '@' : '') +
  INT_PG_HOST + ':' + INT_PG_PORT + '/' + INT_PG_DB;
process.env.COUCHDB_URL = INT_COUCHDB_URL;

var _ = require('underscore'),
    RSVP = require('rsvp'),
    common = require('../../tests/common'),
    expect = common.expect,
    Promise = RSVP.Promise,
    pgp = require('pg-promise')({ 'promiseLib': Promise }),
    format = require('pg-format'),
    couch2pg = require('../../libs/couch2pg/index'),
    pouchdb = require('pouchdb'),
    log = require('loglevel');

log.setDefaultLevel('error'); // CHANGE ME FOR MORE DETAILS

var DOCS_TO_CREATE = 50;
var DOCS_TO_ADD = 10;
var DOCS_TO_EDIT = 10;
var DOCS_TO_DELETE = 10;

var createPgConnection = function(host, port, user, pass, database) {
  var options = {
    host: host,
    port: port
  };
  if (user) {
    options.user = user;
  }
  if (pass) {
    options.pass = pass;
  }
  if (database) {
    options.database = database;
  }

  return pgp(options);
};

// drop and re-create couchdb
var initialiseCouchDb = function() {
  return pouchdb(INT_COUCHDB_URL).destroy().then(function() {
    return new Promise(function(res) {
      res(pouchdb(INT_COUCHDB_URL));
    });
  });
};

// Drop and re-create postgres db
var initialisePostgresql = function() {
  var pg = createPgConnection(INT_PG_HOST, INT_PG_PORT, INT_PG_USER, INT_PG_PASS);
  return pg.query(format('DROP DATABASE %I', INT_PG_DB))
    .then(function() {}, function() {}) // don't care if it passed or failed
    .then(function() {
      return pg.query(format('CREATE DATABASE %I', INT_PG_DB)).then(function() {
        return new Promise(function(res) {
          res(createPgConnection(INT_PG_HOST, INT_PG_PORT, INT_PG_USER, INT_PG_PASS, INT_PG_DB));
        });
      });
    });
};

var randomData = function() {
  return [
    _.sample(['happy', 'sad', 'angry', 'scared', 'morose', 'pensive', 'quixotic']),
    _.sample(['red', 'blue', 'green', 'orange', 'pink', 'mustard', 'vermillion']),
    _.sample(['cat', 'dog', 'panda', 'tiger', 'ant', 'lemur', 'dugong', 'vontsira'])
    ].join('-');
};

var generateRandomDocument = function() {
  return {
    data: randomData()
  };
};

describe('couch2pg', function() {
  var couchdb, pgdb;

  var createDocs = function(docs) {
    return couchdb.bulkDocs(docs).then(function(results) {
      return _.zip(docs, results).map(function(docAndResult) {
        // TODO replace with destructuring when node supports it
        var doc = docAndResult[0];
        var result = docAndResult[1];

        if (!result.ok) {
          throw ['Document failed to be saved', result];
        }

        doc._id = result.id;
        doc._rev = result.rev;

        return doc;
      });
    });
  };

  var couchDbDocs = function() {
    return couchdb.allDocs({
      include_docs: true
    }).then(function(results) {
      return _.pluck(results.rows, 'doc');
    });
  };

  var itRunsSuccessfully = function() {
    return couch2pg.migrate().then(couch2pg.import);
  };

  var itHasTheSameNumberOfDocs = function() {
    return RSVP.all([
      pgdb.one('SELECT COUNT(*) FROM couchdb'),
      couchDbDocs()
    ]).then(function(results) {
      var pgCount = parseInt(results[0].count),
          couchCount = results[1].length;

      expect(pgCount).to.equal(couchCount);
    });
  };

  var itHasTheSameDocuments = function() {
    return RSVP.all([
      pgdb.query('SELECT * from couchdb'),
      couchDbDocs()
    ]).then(function(results) {
      var pgdocs = _.pluck(results[0], 'doc');
      var docs = results[1];

      expect(_.sortBy(pgdocs, '_id')).deep.equals(_.sortBy(docs, '_id'));
    });
  };

  before(function() {
    return initialiseCouchDb()
      .then(function(db) {
        console.log('Initialised couchdb');
        couchdb = db;
        return initialisePostgresql();
      }).then(function(db) {
        console.log('Initialised postgres');
        pgdb = db;
      });
  });

  describe('initial import into postgres', function() {
    before(function() {
      return _.range(DOCS_TO_CREATE).map(generateRandomDocument).createDocs;
    });

    it('runs successfully', itRunsSuccessfully);
    it('has the same number of documents as couch', itHasTheSameNumberOfDocs);
    it('has the same documents as couch', itHasTheSameDocuments);
  });
  describe('subsequent creations, updates and deletions', function() {
    before(function() {
      return couchDbDocs().then(function(docs) {
        var deletedDocs = _.sample(docs, DOCS_TO_DELETE);
        docs = _.difference(docs, deletedDocs);
        deletedDocs.forEach(function(doc) {
          doc._deleted = true;
        });

        var updatedDocs = _.sample(docs, DOCS_TO_EDIT);
        updatedDocs.forEach(function(doc) {
          doc.data = randomData();
        });

        var createdDocs =_.range(DOCS_TO_ADD).map(generateRandomDocument);

        return couchdb.bulkDocs(deletedDocs)
        .then(function() {
          return couchdb.bulkDocs(updatedDocs).then(function(results) {
            results.forEach(function(result) {
              var doc = docs.find(function(d) {
                return d._id === result.id;
              });

              doc._id = result.id;
              doc._rev = result.rev;
            });
          });
        })
        .then(function() {
          return createDocs(createdDocs).then(function(createdDocs) {
            docs = docs.concat(createdDocs);
          });
        });
      });
    });

    it('runs successfully', itRunsSuccessfully);
    it('has the same number of documents as couch', itHasTheSameNumberOfDocs);
    it('has the same documents as couch', itHasTheSameDocuments);
  });
  describe('no change', function() {
    it('runs successfully', itRunsSuccessfully);
    it('still has the same number of documents as couch', itHasTheSameNumberOfDocs);
    it('still has the same documents as couch', itHasTheSameDocuments);
  });
  describe('Escaping', function() {
    it('should handle documents with \\u0000 in it', function() {
      return couchdb.put({
        _id: 'u0000-escaped',
        data: 'blah blah \u0000\u0000\u0000\u0000 blah'
      }).then(itRunsSuccessfully).catch(function(err) {
        console.log(err);
        throw new Error(err);
      });
    });
  });
});
<commit_msg>actually create base docs<commit_after>var INT_PG_HOST = process.env.INT_PG_HOST || 'localhost',
    INT_PG_PORT = process.env.INT_PG_PORT || 5432,
    INT_PG_USER = process.env.INT_PG_USER,
    INT_PG_PASS = process.env.INT_PG_PASS,
    INT_PG_DB   = process.env.INT_PG_DB || 'medic-analytics-test',
    INT_COUCHDB_URL = process.env.INT_COUCHDB_URL || 'http://admin:pass@localhost:5984/medic-analytics-test';

process.env.POSTGRESQL_URL = 'postgres://' +
  (INT_PG_USER ? INT_PG_USER : '') +
  (INT_PG_PASS ? INT_PG_PASS += ':' + INT_PG_PASS : '') +
  (INT_PG_USER ? '@' : '') +
  INT_PG_HOST + ':' + INT_PG_PORT + '/' + INT_PG_DB;
process.env.COUCHDB_URL = INT_COUCHDB_URL;

var _ = require('underscore'),
    RSVP = require('rsvp'),
    common = require('../../tests/common'),
    expect = common.expect,
    Promise = RSVP.Promise,
    pgp = require('pg-promise')({ 'promiseLib': Promise }),
    format = require('pg-format'),
    couch2pg = require('../../libs/couch2pg/index'),
    pouchdb = require('pouchdb'),
    log = require('loglevel');

log.setDefaultLevel('error'); // CHANGE ME FOR MORE DETAILS

var DOCS_TO_CREATE = 50;
var DOCS_TO_ADD = 10;
var DOCS_TO_EDIT = 10;
var DOCS_TO_DELETE = 10;

var createPgConnection = function(host, port, user, pass, database) {
  var options = {
    host: host,
    port: port
  };
  if (user) {
    options.user = user;
  }
  if (pass) {
    options.pass = pass;
  }
  if (database) {
    options.database = database;
  }

  return pgp(options);
};

// drop and re-create couchdb
var initialiseCouchDb = function() {
  return pouchdb(INT_COUCHDB_URL).destroy().then(function() {
    return new Promise(function(res) {
      res(pouchdb(INT_COUCHDB_URL));
    });
  });
};

// Drop and re-create postgres db
var initialisePostgresql = function() {
  var pg = createPgConnection(INT_PG_HOST, INT_PG_PORT, INT_PG_USER, INT_PG_PASS);
  return pg.query(format('DROP DATABASE %I', INT_PG_DB))
    .then(function() {}, function() {}) // don't care if it passed or failed
    .then(function() {
      return pg.query(format('CREATE DATABASE %I', INT_PG_DB)).then(function() {
        return new Promise(function(res) {
          res(createPgConnection(INT_PG_HOST, INT_PG_PORT, INT_PG_USER, INT_PG_PASS, INT_PG_DB));
        });
      });
    });
};

var randomData = function() {
  return [
    _.sample(['happy', 'sad', 'angry', 'scared', 'morose', 'pensive', 'quixotic']),
    _.sample(['red', 'blue', 'green', 'orange', 'pink', 'mustard', 'vermillion']),
    _.sample(['cat', 'dog', 'panda', 'tiger', 'ant', 'lemur', 'dugong', 'vontsira'])
    ].join('-');
};

var generateRandomDocument = function() {
  return {
    data: randomData()
  };
};

describe('couch2pg', function() {
  var couchdb, pgdb;

  var createDocs = function(docs) {
    return couchdb.bulkDocs(docs).then(function(results) {
      return _.zip(docs, results).map(function(docAndResult) {
        // TODO replace with destructuring when node supports it
        var doc = docAndResult[0];
        var result = docAndResult[1];

        if (!result.ok) {
          throw ['Document failed to be saved', result];
        }

        doc._id = result.id;
        doc._rev = result.rev;

        return doc;
      });
    });
  };

  var couchDbDocs = function() {
    return couchdb.allDocs({
      include_docs: true
    }).then(function(results) {
      return _.pluck(results.rows, 'doc');
    });
  };

  var itRunsSuccessfully = function() {
    return couch2pg.migrate().then(couch2pg.import);
  };

  var itHasTheSameNumberOfDocs = function() {
    return RSVP.all([
      pgdb.one('SELECT COUNT(*) FROM couchdb'),
      couchDbDocs()
    ]).then(function(results) {
      var pgCount = parseInt(results[0].count),
          couchCount = results[1].length;

      expect(pgCount).to.equal(couchCount);
    });
  };

  var itHasTheSameDocuments = function() {
    return RSVP.all([
      pgdb.query('SELECT * from couchdb'),
      couchDbDocs()
    ]).then(function(results) {
      var pgdocs = _.pluck(results[0], 'doc');
      var docs = results[1];

      expect(_.sortBy(pgdocs, '_id')).deep.equals(_.sortBy(docs, '_id'));
    });
  };

  before(function() {
    return initialiseCouchDb()
      .then(function(db) {
        console.log('Initialised couchdb');
        couchdb = db;
        return initialisePostgresql();
      }).then(function(db) {
        console.log('Initialised postgres');
        pgdb = db;
      });
  });

  describe('initial import into postgres', function() {
    before(function() {
      return createDocs(_.range(DOCS_TO_CREATE).map(generateRandomDocument));
    });

    it('runs successfully', itRunsSuccessfully);
    it('has the same number of documents as couch', itHasTheSameNumberOfDocs);
    it('has the same documents as couch', itHasTheSameDocuments);
  });
  describe('subsequent creations, updates and deletions', function() {
    before(function() {
      return couchDbDocs().then(function(docs) {
        var deletedDocs = _.sample(docs, DOCS_TO_DELETE);
        docs = _.difference(docs, deletedDocs);
        deletedDocs.forEach(function(doc) {
          doc._deleted = true;
        });

        var updatedDocs = _.sample(docs, DOCS_TO_EDIT);
        updatedDocs.forEach(function(doc) {
          doc.data = randomData();
        });

        var createdDocs =_.range(DOCS_TO_ADD).map(generateRandomDocument);

        return couchdb.bulkDocs(deletedDocs)
        .then(function() {
          return couchdb.bulkDocs(updatedDocs).then(function(results) {
            results.forEach(function(result) {
              var doc = docs.find(function(d) {
                return d._id === result.id;
              });

              doc._id = result.id;
              doc._rev = result.rev;
            });
          });
        })
        .then(function() {
          return createDocs(createdDocs).then(function(createdDocs) {
            docs = docs.concat(createdDocs);
          });
        });
      });
    });

    it('runs successfully', itRunsSuccessfully);
    it('has the same number of documents as couch', itHasTheSameNumberOfDocs);
    it('has the same documents as couch', itHasTheSameDocuments);
  });
  describe('no change', function() {
    it('runs successfully', itRunsSuccessfully);
    it('still has the same number of documents as couch', itHasTheSameNumberOfDocs);
    it('still has the same documents as couch', itHasTheSameDocuments);
  });
  describe('Escaping', function() {
    it('should handle documents with \\u0000 in it', function() {
      return couchdb.put({
        _id: 'u0000-escaped',
        data: 'blah blah \u0000\u0000\u0000\u0000 blah'
      }).then(itRunsSuccessfully).catch(function(err) {
        console.log(err);
        throw new Error(err);
      });
    });
  });
});
<|endoftext|>


<commit_before>if(typeof require === 'function') {
  const buster  = require("buster")
      , Helpers = require('./buster-helpers')
      , dialect = Helpers.getTestDialect()
}

var qq = function(str) {
  if (dialect == 'postgres' || dialect == 'sqlite') {
    return '"' + str + '"'
  } else if (dialect == 'mysql' || dialect == 'mariadb') {
    return '`' + str + '`'
  } else {
    return str
  }
}

buster.spec.expose()

describe(Helpers.getTestDialectTeaser("Sequelize"), function() {
  before(function(done) {
    Helpers.initTests({
      dialect: dialect,
      beforeComplete: function(sequelize) { this.sequelize = sequelize }.bind(this),
      onComplete: done
    })
  })

  describe('isDefined', function() {
    it("returns false if the dao wasn't defined before", function() {
      expect(this.sequelize.isDefined('Project')).toBeFalse()
    })

    it("returns true if the dao was defined before", function() {
      this.sequelize.define('Project', {
        name: Helpers.Sequelize.STRING
      })
      expect(this.sequelize.isDefined('Project')).toBeTrue()
    })
  })

  describe('query', function() {
    before(function(done) {
      this.User = this.sequelize.define('User', {
        username: Helpers.Sequelize.STRING
      })

      this.insertQuery = "INSERT INTO " + qq(this.User.tableName) + " (username, " + qq("createdAt") + ", " + qq("updatedAt") + ") VALUES ('john', '2012-01-01 10:10:10', '2012-01-01 10:10:10')"

      this.User.sync().success(done).error(function(err) {
        console(err)
        done()
      })
    })

    it('executes a query the internal way', function(done) {
      this.sequelize.query(this.insertQuery, null, { raw: true })
      .complete(function(err, result) {
        if (err) {
          console.log(err)
        }
        expect(err).toBeNull()
        expect(result).toBeNull()
        done()
      })
    })

    it('executes a query if only the sql is passed', function(done) {
      this.sequelize.query(this.insertQuery)
      .complete(function(err, result) {
        if (err) {
          console.log(err)
        }
        expect(err).toBeNull()
        expect(result).not.toBeDefined()
        done()
      })
    })

    it('executes select queries correctly', function(done) {
      this.sequelize.query(this.insertQuery).success(function() {
        this.sequelize
          .query("select * from " + qq(this.User.tableName) + "")
          .complete(function(err, users) {
            if (err) {
              console.log(err)
            }
            expect(err).toBeNull()
            expect(users.map(function(u){ return u.username })).toEqual(['john'])
            done()
          })
      }.bind(this))
    })

    it('executes select query and parses dot notation results', function(done) {
      this.sequelize.query(this.insertQuery).success(function() {
        this.sequelize
          .query("select username as " + qq("user.username") + " from " + qq(this.User.tableName) + "")
          .complete(function(err, users) {
            if (err) {
              console.log(err)
            }
            expect(err).toBeNull()
            expect(users.map(function(u){ return u.user })).toEqual([{'username':'john'}])
            done()
          })
      }.bind(this))
    })

    if (dialect == 'mysql' || dialect == 'mariadb') {
      it('executes stored procedures', function(done) {
        this.sequelize.query(this.insertQuery).success(function() {
          this.sequelize.query('DROP PROCEDURE IF EXISTS foo').success(function() {
            this.sequelize.query(
              "CREATE PROCEDURE foo()\nSELECT * FROM " + this.User.tableName + ";"
            ).success(function() {
              this.sequelize.query('CALL foo()').success(function(users) {
                expect(users.map(function(u){ return u.username })).toEqual(['john'])
                done()
              })
            }.bind(this))
          }.bind(this))
        }.bind(this))
      })
    } else {
      console.log('FIXME: I want to be supported in this dialect as well :-(')
    }

    it('uses the passed DAOFactory', function(done) {
      this.sequelize.query(this.insertQuery).success(function() {
        this.sequelize.query("SELECT * FROM " + qq(this.User.tableName) + ";", this.User).success(function(users) {
          expect(users[0].__factory).toEqual(this.User)
          done()
        }.bind(this))
      }.bind(this))
    })

    it('destructs dot separated attributes when doing a raw query', function(done) {
      var tickChar = (dialect === 'postgres') ? '"' : '`'
        , sql      = "select 1 as " + Helpers.Sequelize.Utils.addTicks('foo.bar.baz', tickChar)

      this.sequelize.query(sql, null, { raw: true }).success(function(result) {
        expect(result).toEqual([ { foo: { bar: { baz: 1 } } } ])
        done()
      })
    })

    it('replaces token with the passed array', function(done) {
      this.sequelize.query('select ? as foo, ? as bar', null, { raw: true }, [ 1, 2 ]).success(function(result) {
        expect(result).toEqual([{ foo: 1, bar: 2 }])
        done()
      })
    })
  })

  describe('define', function() {
    [
      { type: Helpers.Sequelize.ENUM, values: ['scheduled', 'active', 'finished']},
      Helpers.Sequelize.ENUM('scheduled', 'active', 'finished')
    ].forEach(function(status) {
      describe('enum', function() {
        before(function(done) {
          this.Review = this.sequelize.define('review', { status: status })
          this.Review.sync({ force: true }).success(done)
        })

        it('raises an error if no values are defined', function() {
          Helpers.assertException(function() {
            this.sequelize.define('omnomnom', {
              bla: { type: Helpers.Sequelize.ENUM }
            })
          }.bind(this), 'Values for ENUM haven\'t been defined.')
        })

        it('correctly stores values', function(done) {
          this.Review.create({ status: 'active' }).success(function(review) {
            expect(review.status).toEqual('active')
            done()
          })
        })

        it('correctly loads values', function(done) {
          this.Review.create({ status: 'active' }).success(function() {
            this.Review.findAll().success(function(reviews) {
              expect(reviews[0].status).toEqual('active')
              done()
            })
          }.bind(this))
        })

        it("doesn't save an instance if value is not in the range of enums", function() {
          Helpers.assertException(function() {
            this.Review.create({ status: 'fnord' })
          }.bind(this), 'Value "fnord" for ENUM status is out of allowed scope. Allowed values: scheduled, active, finished')
        })
      })
    })
  })
})
<commit_msg>mariasql does not seem to support stored procedures - take back out \'executes stored procedures\' test<commit_after>if(typeof require === 'function') {
  const buster  = require("buster")
      , Helpers = require('./buster-helpers')
      , dialect = Helpers.getTestDialect()
}

var qq = function(str) {
  if (dialect == 'postgres' || dialect == 'sqlite') {
    return '"' + str + '"'
  } else if (dialect == 'mysql' || dialect == 'mariadb') {
    return '`' + str + '`'
  } else {
    return str
  }
}

buster.spec.expose()

describe(Helpers.getTestDialectTeaser("Sequelize"), function() {
  before(function(done) {
    Helpers.initTests({
      dialect: dialect,
      beforeComplete: function(sequelize) { this.sequelize = sequelize }.bind(this),
      onComplete: done
    })
  })

  describe('isDefined', function() {
    it("returns false if the dao wasn't defined before", function() {
      expect(this.sequelize.isDefined('Project')).toBeFalse()
    })

    it("returns true if the dao was defined before", function() {
      this.sequelize.define('Project', {
        name: Helpers.Sequelize.STRING
      })
      expect(this.sequelize.isDefined('Project')).toBeTrue()
    })
  })

  describe('query', function() {
    before(function(done) {
      this.User = this.sequelize.define('User', {
        username: Helpers.Sequelize.STRING
      })

      this.insertQuery = "INSERT INTO " + qq(this.User.tableName) + " (username, " + qq("createdAt") + ", " + qq("updatedAt") + ") VALUES ('john', '2012-01-01 10:10:10', '2012-01-01 10:10:10')"

      this.User.sync().success(done).error(function(err) {
        console(err)
        done()
      })
    })

    it('executes a query the internal way', function(done) {
      this.sequelize.query(this.insertQuery, null, { raw: true })
      .complete(function(err, result) {
        if (err) {
          console.log(err)
        }
        expect(err).toBeNull()
        expect(result).toBeNull()
        done()
      })
    })

    it('executes a query if only the sql is passed', function(done) {
      this.sequelize.query(this.insertQuery)
      .complete(function(err, result) {
        if (err) {
          console.log(err)
        }
        expect(err).toBeNull()
        expect(result).not.toBeDefined()
        done()
      })
    })

    it('executes select queries correctly', function(done) {
      this.sequelize.query(this.insertQuery).success(function() {
        this.sequelize
          .query("select * from " + qq(this.User.tableName) + "")
          .complete(function(err, users) {
            if (err) {
              console.log(err)
            }
            expect(err).toBeNull()
            expect(users.map(function(u){ return u.username })).toEqual(['john'])
            done()
          })
      }.bind(this))
    })

    it('executes select query and parses dot notation results', function(done) {
      this.sequelize.query(this.insertQuery).success(function() {
        this.sequelize
          .query("select username as " + qq("user.username") + " from " + qq(this.User.tableName) + "")
          .complete(function(err, users) {
            if (err) {
              console.log(err)
            }
            expect(err).toBeNull()
            expect(users.map(function(u){ return u.user })).toEqual([{'username':'john'}])
            done()
          })
      }.bind(this))
    })

    if (dialect == 'mysql') {
      it('executes stored procedures', function(done) {
        this.sequelize.query(this.insertQuery).success(function() {
          this.sequelize.query('DROP PROCEDURE IF EXISTS foo').success(function() {
            this.sequelize.query(
              "CREATE PROCEDURE foo()\nSELECT * FROM " + this.User.tableName + ";"
            ).success(function() {
              this.sequelize.query('CALL foo()').success(function(users) {
                expect(users.map(function(u){ return u.username })).toEqual(['john'])
                done()
              })
            }.bind(this))
          }.bind(this))
        }.bind(this))
      })
    } else {
      console.log('FIXME: I want to be supported in this dialect as well :-(')
    }

    it('uses the passed DAOFactory', function(done) {
      this.sequelize.query(this.insertQuery).success(function() {
        this.sequelize.query("SELECT * FROM " + qq(this.User.tableName) + ";", this.User).success(function(users) {
          expect(users[0].__factory).toEqual(this.User)
          done()
        }.bind(this))
      }.bind(this))
    })

    it('destructs dot separated attributes when doing a raw query', function(done) {
      var tickChar = (dialect === 'postgres') ? '"' : '`'
        , sql      = "select 1 as " + Helpers.Sequelize.Utils.addTicks('foo.bar.baz', tickChar)

      this.sequelize.query(sql, null, { raw: true }).success(function(result) {
        expect(result).toEqual([ { foo: { bar: { baz: 1 } } } ])
        done()
      })
    })

    it('replaces token with the passed array', function(done) {
      this.sequelize.query('select ? as foo, ? as bar', null, { raw: true }, [ 1, 2 ]).success(function(result) {
        expect(result).toEqual([{ foo: 1, bar: 2 }])
        done()
      })
    })
  })

  describe('define', function() {
    [
      { type: Helpers.Sequelize.ENUM, values: ['scheduled', 'active', 'finished']},
      Helpers.Sequelize.ENUM('scheduled', 'active', 'finished')
    ].forEach(function(status) {
      describe('enum', function() {
        before(function(done) {
          this.Review = this.sequelize.define('review', { status: status })
          this.Review.sync({ force: true }).success(done)
        })

        it('raises an error if no values are defined', function() {
          Helpers.assertException(function() {
            this.sequelize.define('omnomnom', {
              bla: { type: Helpers.Sequelize.ENUM }
            })
          }.bind(this), 'Values for ENUM haven\'t been defined.')
        })

        it('correctly stores values', function(done) {
          this.Review.create({ status: 'active' }).success(function(review) {
            expect(review.status).toEqual('active')
            done()
          })
        })

        it('correctly loads values', function(done) {
          this.Review.create({ status: 'active' }).success(function() {
            this.Review.findAll().success(function(reviews) {
              expect(reviews[0].status).toEqual('active')
              done()
            })
          }.bind(this))
        })

        it("doesn't save an instance if value is not in the range of enums", function() {
          Helpers.assertException(function() {
            this.Review.create({ status: 'fnord' })
          }.bind(this), 'Value "fnord" for ENUM status is out of allowed scope. Allowed values: scheduled, active, finished')
        })
      })
    })
  })
})
<|endoftext|>


<commit_before>const d3Array = require("d3-array"),
      d3Collection = require("d3-collection"),
      multiSort = require("../utils/multiSort"),
      slugMap = require("../utils/slugMap");

const f = (a, b) => [].concat(...a.map(d => b.map(e => [].concat(d, e))));
const cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a.map(x => [x]);

function intersect(a, b) {
  return [...new Set(a)].filter(x => new Set(b).has(x));
}

module.exports = function(app) {

  const {cache, db} = app.settings;
  const {client, measures, pops, years} = cache.cube;

  app.get("/api/data/", (req, res) => {

    let {
      drilldowns
    } = req.query;

    if (drilldowns) drilldowns = drilldowns.split(",");
    else drilldowns = [];

    const {
      measure,
      order = "Year",
      sort = "desc",
      year = "all"
    } = req.query;

    if (!measure) res.json({error: "Query must contain at least one measure."});
    const required = measure.split(",");

    let bigGeos = true;
    const dimensions = [];
    ["geo", "naics", "soc", "university", "cip"].forEach(t => {
      if (req.query[t]) {
        const ids = req.query[t].split(",");
        dimensions.push({
          type: t,
          id: ids
        });
        if (t === "geo") bigGeos = ids.every(g => pops[g] && pops[g] >= 250000);
      }
    });

    const queries = {};
    required.forEach(measure => {
      const cubes = measures[measure]
        .filter(cube => !cube.name.match(/_[0-9]$/g) ||
          cube.name.match(bigGeos ? /_1$/g : /_5$/g));

      if (cubes.length === 1) {
        const cube = cubes[0];
        if (!queries[cube.name]) {
          queries[cube.name] = {measures: [], ...cube};
        }
        queries[cube.name].measures.push(measure);
      }
      else {
        console.log(`Unable to determine cube for ${measure}`);
        console.log(cubes);
      }

    });

    Promise.all(dimensions.map(d => db.search.findAll({where: d})))
      .then(attributes => {

        const cuts = d3Array.merge(attributes).reduce((obj, d) => {
          const dim = slugMap[d.type];
          if (!obj[dim]) obj[dim] = {};
          if (!obj[dim][d.sumlevel]) obj[dim][d.sumlevel] = [];
          obj[dim][d.sumlevel].push(d);
          return obj;
        }, {});

        let queryCrosses = [];
        const queryPromises = [];
        Object.keys(queries).forEach(name => {

          const cube = queries[name];

          const dims = Object.keys(cube.dimensions)
            .filter(dim => dim in cuts)
            .map(dim => intersect(cube.dimensions[dim], Object.keys(cuts[dim])).map(d => ({[dim]: d})));

          const crosses = cartesian(...dims);
          queryCrosses = queryCrosses.concat(crosses);

          crosses.forEach(dimSet => {

            const q = client.cube(name)
              .then(c => {

                const query = c.query;

                if ("Year" in cube.dimensions) {
                  query.drilldown("Year", "Year", "Year");
                  if (year !== "all") {
                    const queryYears = year.split(",").map(y => {
                      if (y === "latest") return years[name].latest;
                      if (y === "previous") return years[name].previous;
                      if (y === "oldest") return years[name].oldest;
                      return y;
                    });
                    query.cut(`{${queryYears.map(y => `[Year].[Year].[Year].&[${y}]`).join(", ")}}`);
                  }
                }

                drilldowns.forEach(drill => {
                  query.drilldown(drill, drill, drill);
                });

                dimSet.forEach(dim => {
                  const type = Object.keys(dim)[0];
                  const level = dim[type];
                  query
                    .drilldown(type, level, level)
                    .cut(`{${cuts[type][level].map(g => `[${type}].[${level}].[${level}].&[${g.id}]`).join(", ")}}`);
                });

                cube.measures.forEach(measure => query.measure(measure));
                return client.query(query, "jsonrecords");
              });

            queryPromises.push(q);

          });

        });

        return Promise.all([queryCrosses, Promise.all(queryPromises)]);

      })
      .then(([crosses, data]) => {

        const flatArray = data.reduce((arr, d, i) => {

          const cross = crosses[i];
          const newArray = d.data.data.map(row => {
            cross.forEach(c => {
              const type = Object.keys(c)[0];
              const level = c[type];
              if (level in row) {
                row[type] = row[level];
                row[`${type} ID`] = row[`ID ${level}`];
                delete row[level];
                delete row[`ID ${level}`];
              }
              delete row["ID Year"];
            });
            return row;
          });

          arr = arr.concat(newArray);

          return arr;

        }, []);

        const keys = d3Array.merge([
          crosses[0].map(d => Object.keys(d)[0]),
          drilldowns,
          ["Year"]
        ]);

        const mergedData = d3Collection.nest()
          .key(d => keys.map(key => d[key]).join("_"))
          .entries(flatArray)
          .map(d => Object.assign(...d.values));

        const sortedData = multiSort(mergedData, order.split(","), sort);

        return sortedData;

      })
      .then(data => res.json({data, source: Object.values(queries)}).end());

  });

};
<commit_msg>full dimension/cut support in logicLayer<commit_after>const d3Array = require("d3-array"),
      d3Collection = require("d3-collection"),
      multiSort = require("../utils/multiSort"),
      slugMap = require("../utils/slugMap");

const debug = process.env.NODE_ENV === "development";

const f = (a, b) => [].concat(...a.map(d => b.map(e => [].concat(d, e))));
const cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a.map(x => [x]);

function intersect(a, b) {
  return [...new Set(a)].filter(x => new Set(b).has(x));
}

function findDimension(flatDims, level) {
  let dims = flatDims.filter(d => d.level === level);
  if (dims.length > 1) {
    const hierarchyMatches = dims.filter(d => d.hierarchy === level);
    if (hierarchyMatches.length) dims = hierarchyMatches;
  }
  return dims[0];
}

module.exports = function(app) {

  const {cache, db} = app.settings;
  const {client, measures, pops, years} = cache.cube;

  app.get("/api/cubes", (req, res) => {
    res.json({measures, pops, years}).end();
  });

  app.get("/api/data/", (req, res) => {

    let {
      cuts,
      drilldowns
    } = req.query;

    if (cuts) cuts = cuts.split(",").map(cut => cut.split(":"));
    else cuts = [];

    if (drilldowns) drilldowns = drilldowns.split(",");
    else drilldowns = [];

    const {
      measure,
      order = "Year",
      sort = "desc",
      year = "all"
    } = req.query;

    if (!measure) res.json({error: "Query must contain at least one measure."});
    const required = measure.split(",");

    let bigGeos = true;
    const dimensions = [];
    ["geo", "naics", "soc", "university", "cip"].forEach(t => {
      if (req.query[t]) {
        const ids = req.query[t].split(",");
        dimensions.push({
          type: t,
          id: ids
        });
        if (t === "geo") bigGeos = ids.every(g => pops[g] && pops[g] >= 250000);
      }
    });

    const queries = {};
    Promise.all(dimensions.map(d => db.search.findAll({where: d})))
      .then(attributes => {

        const dimCuts = d3Array.merge(attributes).reduce((obj, d) => {
          const dim = slugMap[d.type];
          if (!obj[dim]) obj[dim] = {};
          if (!obj[dim][d.sumlevel]) obj[dim][d.sumlevel] = [];
          obj[dim][d.sumlevel].push(d);
          return obj;
        }, {});

        const dimDrills = d3Array.merge(Object.values(dimCuts).map(d => Object.keys(d)));

        required.forEach(measure => {

          // filter out cubes that don't match cuts and dimensions
          let cubes = measures[measure]
            .filter(cube => {
              const flatDims = cube.flatDims = d3Array.merge(Object.values(cube.dimensions));
              let allowed = true;

              for (let i = 0; i < dimDrills.length; i++) {
                const drilldownDim = flatDims.find(d => d.level === dimDrills[i]);
                if (!drilldownDim) {
                  allowed = false;
                  break;
                }
              }

              if (allowed) {
                for (let i = 0; i < drilldowns.length; i++) {
                  const drilldownDim = flatDims.find(d => d.level === drilldowns[i]);
                  if (!drilldownDim) {
                    allowed = false;
                    break;
                  }
                }
              }

              if (allowed) {
                for (let i = 0; i < cuts.length; i++) {
                  const cutDim = flatDims.find(d => d.level === cuts[i][0]);
                  if (!cutDim) {
                    allowed = false;
                    break;
                  }
                }
              }

              return allowed;
            });

          // 5-year vs 1-year logic
          cubes = cubes = d3Collection.nest()
            .key(d => d.name.replace(/_[0-9]$/g, ""))
            .entries(cubes)
            .map(d => {
              if (d.values.length > 1) d.values = d.values.filter(cube => !cube.name.match(/_[0-9]$/g) || cube.name.match(bigGeos ? /_1$/g : /_5$/g));
              return d.values[0];
            });

          // remove B tables in favor of C tables
          cubes = d3Collection.nest()
            .key(d => d.name.replace("_c_", "_"))
            .entries(cubes)
            .map(d => {
              if (d.values.length > 1) d.values = d.values.filter(c => c.name.includes("_c_"));
              return d.values[0];
            });

          // filter out cubes with additional unused dimensions
          if (cubes.length > 1) {
            const minDims = d3Array.min(cubes.map(c => Object.keys(c.dimensions).length));
            cubes = cubes.filter(c => Object.keys(c.dimensions).length === minDims);
          }

          if (cubes.length === 1) {
            const cube = cubes[0];
            if (!queries[cube.name]) {
              queries[cube.name] = {measures: [], ...cube};
            }
            queries[cube.name].measures.push(measure);
          }
          else if (cubes.length === 0) {
            console.log("\nNo cubes matched.");
          }
          else {
            console.log(`\nUnable to determine cube for ${measure}:`);
            console.log(cubes);
          }

        });

        let queryCrosses = [];
        const queryPromises = [];
        Object.keys(queries).forEach(name => {

          const cube = queries[name];
          const flatDims = cube.flatDims;

          const dims = Object.keys(cube.dimensions)
            .filter(dim => dim in dimCuts)
            .map(dim => intersect(
              cube.dimensions[dim].map(d => d.level),
              Object.keys(dimCuts[dim])
            ).map(d => ({[dim]: d})));

          const crosses = cartesian(...dims);
          queryCrosses = queryCrosses.concat(crosses);

          crosses.forEach(dimSet => {

            const q = client.cube(name)
              .then(c => {

                const query = c.query;

                if (debug) console.log(`\nLogic Layer Query: ${name}`);

                if ("Year" in cube.dimensions) {
                  query.drilldown("Year", "Year", "Year");
                  if (debug) console.log("Cut: Year - Year - Year");
                  if (year !== "all") {
                    const queryYears = year.split(",").map(y => {
                      if (y === "latest") return years[name].latest;
                      if (y === "previous") return years[name].previous;
                      if (y === "oldest") return years[name].oldest;
                      return y;
                    });
                    const yearCut = `{${queryYears.map(y => `[Year].[Year].[Year].&[${y}]`).join(", ")}}`;
                    if (debug) console.log(`Cut: ${yearCut}`);
                    query.cut(yearCut);
                  }
                }

                drilldowns.forEach(level => {
                  const {dimension, hierarchy} = findDimension(flatDims, level);
                  if (debug) console.log(`Drilldown: ${dimension} - ${hierarchy} - ${level}`);
                  query.drilldown(dimension, hierarchy, level);
                });

                cuts.forEach(([level, value]) => {
                  const {dimension, hierarchy} = findDimension(flatDims, level);
                  if (!drilldowns.includes(level)) {
                    if (debug) console.log(`Drilldown: ${dimension} - ${hierarchy} - ${level}`);
                    query.drilldown(dimension, hierarchy, level);
                  }
                  const cut = `[${dimension}].[${hierarchy}].[${level}].&[${value}]`;
                  if (debug) console.log(`Cut: ${cut}`);
                  query.cut(cut);
                });

                dimSet.forEach(dim => {
                  const dimension = Object.keys(dim)[0];
                  const level = dim[dimension];
                  const {hierarchy} = findDimension(flatDims, level);
                  const dimCut = `{${dimCuts[dimension][level].map(g => `[${dimension}].[${hierarchy}].[${level}].&[${g.id}]`).join(", ")}}`;
                  if (debug) {
                    console.log(`Drilldown: ${dimension} - ${hierarchy} - ${level}`);
                    console.log(`Cut: ${dimCut}`);
                  }
                  query
                    .drilldown(dimension, hierarchy, level)
                    .cut(dimCut);
                });

                cube.measures.forEach(measure => {
                  if (debug) console.log(`Measure: ${measure}`);
                  query.measure(measure);
                });

                return client.query(query, "jsonrecords");
              });

            queryPromises.push(q);

          });

        });

        return Promise.all([queryCrosses, Promise.all(queryPromises)]);

      })
      .then(([crosses, data]) => {

        const flatArray = data.reduce((arr, d, i) => {

          const cross = crosses[i];
          const newArray = d.data.data.map(row => {
            cross.forEach(c => {
              const type = Object.keys(c)[0];
              const level = c[type];
              if (level in row) {
                row[type] = row[level];
                row[`${type} ID`] = row[`ID ${level}`];
                delete row[level];
                delete row[`ID ${level}`];
              }
              delete row["ID Year"];
            });
            return row;
          });

          arr = arr.concat(newArray);

          return arr;

        }, []);

        const keys = d3Array.merge([
          crosses.length ? crosses[0].map(d => Object.keys(d)[0]) : [],
          drilldowns,
          cuts.map(d => d[0]),
          ["Year"]
        ]);

        const mergedData = d3Collection.nest()
          .key(d => keys.map(key => d[key]).join("_"))
          .entries(flatArray)
          .map(d => Object.assign(...d.values));

        const sortedData = multiSort(mergedData, order.split(","), sort);

        return sortedData;

      })
      .then(data => {

        const source = Object.values(queries).map(d => {
          delete d.flatDims;
          return d;
        });

        res.json({data, source}).end();
      });

  });

};
<|endoftext|>


<commit_before>// load dependencies
var _ = require('lodash');
var striptags = require('striptags');
var Utils = require('./utils/utils');
var Tfidf = require('./helpers/tfidf');
var Article = require('./model/articles');

module.exports = (function() {
    var Aggregator = function() {

        var keywordTotal = 4;
        var articleDocs;
        var collection = [];

        var processDocs = function() {
            var collection = articleDocs.map(function(item) {
                return item.title + " " + striptags(item.content);
            });

            for (var i = 0, n = collection.length; i < n; i++) {
                getKeywords(collection[i], collection);
            }
        };

        var getKeywords = function(doc, collection) {
            console.log("process article");

            var wordHash = [];

            var words = Utils.splitWords(doc);
            for (var i = 0, n = words.length; i < n; i++) {
                var word = words[i];
                var tfidf = Tfidf.tfidf(word, doc, collection);
                wordHash.push({
                    word: word,
                    freq: tfidf
                });
            }

            var keywords = identifyKeywords(wordHash);
        };

        function identifyKeywords(wordHash) {

            var keywords = wordHash.sort(function(a, b) {
                if (a.freq > b.freq) {
                    return -1;
                }
                if (a.freq < b.freq) {
                    return 1;
                }

                return 0;
            }).map(function(obj) {
                return obj.word;
            }).slice(0, keywordTotal);

            console.log("keywords: ", keywords);

            return keywords;
        }

        var handleError = function(err) {
            console.log("process article error: ", err);
        };

        Aggregator.prototype.init = function() {
            Article.find().exec(function(err, docs) {
                if (err) return handleError(err);

                articleDocs = docs;

                processDocs();
            });
        }
    };

    return Aggregator;
})();
<commit_msg>Make words unique<commit_after>// load dependencies
var _ = require('lodash');
var striptags = require('striptags');
var Utils = require('./utils/utils');
var Tfidf = require('./helpers/tfidf');
var Article = require('./model/articles');

module.exports = (function() {
    var Aggregator = function() {

        var keywordTotal = 4;
        var articleDocs;
        var collection = [];

        var processDocs = function() {
            var collection = articleDocs.map(function(item) {
                return item.title + " " + striptags(item.content);
            });

            for (var i = 0, n = collection.length; i < n; i++) {
                getKeywords(collection[i], collection);
            }
        };

        var getKeywords = function(doc, collection) {
            console.log("process article");

            var wordHash = [];

            var words = _.uniq(Utils.splitWords(doc));
            for (var i = 0, n = words.length; i < n; i++) {
                var word = words[i];
                var tfidf = Tfidf.tfidf(word, doc, collection);
                wordHash.push({
                    word: word,
                    freq: tfidf
                });
            }

            var keywords = identifyKeywords(wordHash);
        };

        function identifyKeywords(wordHash) {

            var keywords = wordHash.sort(function(a, b) {
                if (a.freq > b.freq) {
                    return -1;
                }
                if (a.freq < b.freq) {
                    return 1;
                }

                return 0;
            }).map(function(obj) {
                return obj.word;
            }).slice(0, keywordTotal);

            console.log("keywords: ", keywords);

            return keywords;
        }

        var handleError = function(err) {
            console.log("process article error: ", err);
        };

        Aggregator.prototype.init = function() {
            Article.find().exec(function(err, docs) {
                if (err) return handleError(err);

                articleDocs = docs;

                processDocs();
            });
        }
    };

    return Aggregator;
})();
<|endoftext|>


<commit_before>/**
 * Small wrapper around `superagent` module to make it easier to consume
 * the API the same way on client & server.
 */
var superagent = require('superagent')
  , isServer = typeof window === 'undefined'
  , apiPort = process.env.API_PORT || 3031
;

module.exports = {
  get: function(path, callback) {
    if (isServer) {
      // Prepend host and port of the API server to the path.
      path = 'http://localhost:' + apiPort + path;
    } else {
      // Prepend `/api` to relative URL, to proxy to API server.
      path = '/api' + path;
    }

    superagent.get(path, callback);
  }
};
<commit_msg>api_client: proxy all HTTP verbs<commit_after>/**
 * Small wrapper around `superagent` module to make it easier to consume
 * the API the same way on client & server.
 */
var superagent = require('superagent')
  , isServer = typeof window === 'undefined'
  , apiPort = process.env.API_PORT || 3031
;

/**
 * Proxy each method to `superagent`, formatting the URL.
 */
['get', 'post', 'put', 'path', 'del'].forEach(function(method) {
  exports[method] = function(path) {
    var args = Array.prototype.slice.call(arguments, 1);
    superagent[method].apply(null, [formatUrl(path)].concat(args));
  };
});

function formatUrl(path) {
  var url;
  if (isServer) {
    // Prepend host and port of the API server to the path.
    url = 'http://localhost:' + apiPort + path;
  } else {
    // Prepend `/api` to relative URL, to proxy to API server.
    url = '/api' + path;
  }
  return url;
}
<|endoftext|>


<commit_before>// Written by Joshua Paul A. Chan
(function() {
"use strict";

// Import variables if present (from env.js) (thanks @jvandemo)
var env = {};
if(window){ Object.assign(env, window.__env); }

// Initialize app
angular.module('wr', ['ui.router', 'wr.controllers', 'wr.services', 'wr.directives', 'wr.components'])
.constant('__env', env)
.config(function($logProvider, $locationProvider, $stateProvider, $urlMatcherFactoryProvider, __env) {
    // enable/disable angular debug
    $logProvider.debugEnabled(__env.enableDebug);

    // FIXME locationProvider
    // $locationProvider.html5Mode(true);

    // make trailing slashes optional
    $urlMatcherFactoryProvider.strictMode(false);

    $stateProvider
        .state('convos', {
            url: "/conversations",
            templateUrl: "client/app/templates/conversations.html",
            deepStateRedirect: true
        })
        .state('convos.convo', {
            url: "/{convoId}",
            views: {
                convo: {
                    template: "<convo/>"
                }
            }
        });
});

// Initialize modules
angular.module('wr.controllers', []);
angular.module('wr.services', []);
angular.module('wr.directives', []);
angular.module('wr.components', []);
}());
<commit_msg>Remove Object.assign for testing compat<commit_after>// Written by Joshua Paul A. Chan
(function() {
"use strict";

// Import variables if present (from env.js) (thanks @jvandemo)
var env = {};
if(window){ env = window.__env; }

// Initialize app
angular.module('wr', ['ui.router', 'wr.controllers', 'wr.services', 'wr.directives', 'wr.components'])
.constant('__env', env)
.config(function($logProvider, $locationProvider, $stateProvider, $urlMatcherFactoryProvider, __env) {
    // enable/disable angular debug
    $logProvider.debugEnabled(__env.enableDebug);

    // FIXME locationProvider
    // $locationProvider.html5Mode(true);

    // make trailing slashes optional
    $urlMatcherFactoryProvider.strictMode(false);

    $stateProvider
        .state('convos', {
            url: "/conversations",
            templateUrl: "client/app/templates/conversations.html",
            deepStateRedirect: true
        })
        .state('convos.convo', {
            url: "/{convoId}",
            views: {
                convo: {
                    template: "<convo/>"
                }
            }
        });
});

// Initialize modules
angular.module('wr.controllers', []);
angular.module('wr.services', []);
angular.module('wr.directives', []);
angular.module('wr.components', []);
}());
<|endoftext|>


<commit_before>angular.module('chemPhyWebApp')
  .config(['$routeProvider',
    function($routeProvider) {
      $routeProvider.
        when('/home', {
          templateUrl: require('./components/home/home.html')
        }).
        when('/about', {
          templateUrl: require('./components/about/about.html')
        }).
        otherwise({
          redirectTo: '/home'
        });
  }]);
<commit_msg>Update route to point to new jade file<commit_after>angular.module('chemPhyWebApp')
  .config(['$routeProvider',
    function($routeProvider) {
      $routeProvider.
        when('/home', {
          templateUrl: require('./components/home/home.jade')
        }).
        when('/about', {
          templateUrl: require('./components/about/about.html')
        }).
        otherwise({
          redirectTo: '/home'
        });
  }]);
<|endoftext|>


<commit_before>enyo.kind({
	name: "enyo.canvas.Rectangle",
	kind: enyo.canvas.Control,
	published: {
		//* fill, stroke, or clear
		style: "fill"
	},
	renderSelf: function(ctx) {
		if (this.style != "clear") {
			ctx[this.style + "Style"] = this.color;
		}
		ctx[this.style + "Rect"](this.bounds.l, this.bounds.t, this.bounds.w, this.bounds.h);
	}
<commit_msg>forgot to close kind def in Rectangle<commit_after>enyo.kind({
	name: "enyo.canvas.Rectangle",
	kind: enyo.canvas.Control,
	published: {
		//* fill, stroke, or clear
		style: "fill"
	},
	renderSelf: function(ctx) {
		if (this.style != "clear") {
			ctx[this.style + "Style"] = this.color;
		}
		ctx[this.style + "Rect"](this.bounds.l, this.bounds.t, this.bounds.w, this.bounds.h);
	}
});
<|endoftext|>


<commit_before>//A Simple JavaScript Single Inheritance Framework
//As for IE, only IE9(inclusive)+ versions are supported by this library
//@Author: Sky Feng(im.sky@foxmail.com), MIT Licensed.
//      var derived = new Class(/*parentClass, mixins...*/);
//      var derived = Class(/*parentClass, mixins...*/);
//      var derived = Class.extend(/*parentClass, mixins...*/);
(function (name, global, factory) {
    if (typeof define === "function" && define.amd) define(factory);
    else if (typeof module === "object") module.exports = factory();
    else global[name] = factory();
})("Class", this, function () {
    function Class(/*parentClass, mixins...*/) {
        return Class.extend.apply(Class, arguments);
    }
    var mergeSingleProperty = function (target, propName, source) {
        var descriptor = Object.getOwnPropertyDescriptor(source, propName);
        if (descriptor && descriptor.enumerable) {
            descriptor.configurable = descriptor.writable = true;
            Object.defineProperty(target, propName, descriptor);
        }
    };
    var mergeSourceProperties = function privateMerge(derived, mixin) {
        var mixinIsFunction = typeof mixin === "function";
        var protoProps = mixinIsFunction ? mixin.prototype : (mixin || {});
        Object.getOwnPropertyNames(protoProps).forEach(function (propName) {
            if (propName == "initialize" && mixinIsFunction) return true;
            mergeSingleProperty(derived.prototype, propName, protoProps);
        });
    };
    var runParentInitializers = function (thisInstance, thisClass, args) {
        var allParentClasses = [], thisParentClass = thisClass.parent;
        for (; thisParentClass; thisParentClass = thisParentClass.parent)
            allParentClasses.unshift(thisParentClass);
        allParentClasses.forEach(function (thisParentClass, index) {
            thisParentClass.prototype.initialize.apply(thisInstance, args);
        });
    };
    var defaultClassInitializer = function defaultClassInitializer() { };
    Class.extend = function (parentClass/*, mixin...*/) {
        var childClass = function childClassConstructor() {
            var childInstance = Object.create(childClass.prototype);
            runParentInitializers(childInstance, childClass, arguments);
            childClass.prototype.initialize.apply(childInstance, arguments);
            return Object.freeze(childInstance);
        };
        if (typeof parentClass === "function") {
            childClass.prototype = Object.create(parentClass.prototype);
            childClass.parent = Object.freeze(parentClass/*immutable*/);
        }
        childClass.prototype.initialize = defaultClassInitializer;
        for (var dpdtIndex = 0; dpdtIndex < arguments.length; dpdtIndex++)
            mergeSourceProperties(childClass, arguments[dpdtIndex]);

        return childClass = Object.freeze(childClass);
    };
    return Object.freeze(Class/*immutable*/);
});
<commit_msg>Format code<commit_after>//A Simple JavaScript Single Inheritance Framework
//As for IE, only IE9(inclusive)+ versions are supported by this library
//@Author: Sky Feng(im.sky@foxmail.com), MIT Licensed.
//      var derived = new Class(/*parentClass, mixins...*/);
//      var derived = Class(/*parentClass, mixins...*/);
//      var derived = Class.extend(/*parentClass, mixins...*/);
(function (name, global, factory) {
    if (typeof define === "function" && define.amd) define(factory);
    else if (typeof module === "object") module.exports = factory();
    else global[name] = factory();
})("Class", this, function () {
    function Class(/*parentClass, mixins...*/) {
        return Class.extend.apply(Class, arguments);
    }
    var mergeSingleProperty = function (target, propName, source) {
        var descriptor = Object.getOwnPropertyDescriptor(source, propName);
        if (descriptor && descriptor.enumerable) {
            descriptor.configurable = descriptor.writable = true;
            Object.defineProperty(target, propName, descriptor);
        }
    };
    var mergeSourceProperties = function privateMerge(derived, mixin) {
        var mixinIsFunction = typeof mixin === "function";
        var protoProps = mixinIsFunction ? mixin.prototype : (mixin || {});
        Object.getOwnPropertyNames(protoProps).forEach(function (propName) {
            if (propName == "initialize" && mixinIsFunction) return true;
            mergeSingleProperty(derived.prototype, propName, protoProps);
        });
    };
    var runParentInitializers = function (thisInstance, thisClass, args) {
        var allParentClasses = [], thisParentClass = thisClass.parent;
        for (; thisParentClass; thisParentClass = thisParentClass.parent)
            allParentClasses.unshift(thisParentClass);
        allParentClasses.forEach(function (thisParentClass, index) {
            thisParentClass.prototype.initialize.apply(thisInstance, args);
        });
    };
    var defaultClassInitializer = function defaultClassInitializer() { };
    Class.extend = function (/*parentClass, mixin...*/) {
        var childClass = function childClassConstructor() {
            var childInstance = Object.create(childClass.prototype);
            runParentInitializers(childInstance, childClass, arguments);
            childClass.prototype.initialize.apply(childInstance, arguments);
            return Object.freeze(childInstance);
        };
        if (typeof parentClass === "function") {
            childClass.prototype = Object.create(parentClass.prototype);
            childClass.parent = Object.freeze(parentClass/*immutable*/);
        }
        childClass.prototype.initialize = defaultClassInitializer;
        for (var dpdtIndex = 0; dpdtIndex < arguments.length; dpdtIndex++)
            mergeSourceProperties(childClass, arguments[dpdtIndex]);

        return childClass = Object.freeze(childClass);
    };
    return Object.freeze(Class/*immutable*/);
});
<|endoftext|>


<commit_before>module.exports = {
  help: {
    name: '8ball',
    desc: 'Answers a yes-no question',
    usage: '<question>',
    aliases: ['8']
  },

  exec: (_, msg, params) => {
    let answers = ['Yes', 'Possibly', 'Maybe', 'Unlikely', 'No', 'Definitely'];
    let question = params.join(' ');
    let answer = answers[Math.floor(Math.random() * answers.length)];
    msg.edit(`\`\`\`apache\nQ: ${question}\nA: ${answer}\n\`\`\``).catch(console.error);
  }
}<commit_msg>Made eslint stop complaining about semi<commit_after>module.exports = {
  help: {
    name: '8ball',
    desc: 'Answers a yes-no question',
    usage: '<question>',
    aliases: ['8']
  },

  exec: (_, msg, params) => {
    let answers = ['Yes', 'Possibly', 'Maybe', 'Unlikely', 'No', 'Definitely'];
    let question = params.join(' ');
    let answer = answers[Math.floor(Math.random() * answers.length)];
    msg.edit(`\`\`\`apache\nQ: ${question}\nA: ${answer}\n\`\`\``).catch(console.error);
  }
};<|endoftext|>


<commit_before>module.exports = {
  help: {
    name: 'embed',
    desc: 'Displays an example for rich embeds',
    usage: '',
    aliases: []
  },

  exec: (client, msg, params) => {
    let embed = {
      color: 3447003,
      author: {
        name: msg.author.username,
        icon_url: msg.author.avatarURL // eslint-disable-line camelcase
      },
      title: 'THIS IS A TITLE',
      url: 'http://example.com', // The url for the title.
      description: '\nThis is a test embed to showcase what they look like and what they can do.\n[Code here](https://github.com/vzwGrey/discord-selfbot/blob/master/commands/embed.js)',
      fields: [
        {
          name: 'Fields',
          value: 'They can have different fields with small headlines.'
        },
        {
          name: 'Masked links',
          value: 'You can put [masked](https://github.com/vzwGrey/discord-selfbot/blob/master/commands/embed.js) links inside of rich embeds.'
        },
        {
          name: 'Markdown',
          value: 'You can put all the *usual* **__Markdown__** inside of them.'
        },
        {
          name: 'Inline fields',
          value: 'You can also have fields inline with eachother using the `inline` property',
          inline: true
        },
        {
          name: 'Images & thumbnails',
          value: 'You can also embed images, and use little thumbnails!',
          inline: true
        }
      ],
      /* thumbnail: {
        url: 'http://i.imgur.com/uaUxZtz.jpg'
      } */
      image: {
        url: 'http://i.imgur.com/uaUxZtz.jpg'
      },
      timestamp: new Date(),
      footer: {
        icon_url: msg.author.avatarURL, // eslint-disable-line camelcase
        text: '©vzwGrey'
      }
    };

    msg.channel.sendMessage('', { embed });
  }
};
<commit_msg>Remove unnecessary linebreak<commit_after>module.exports = {
  help: {
    name: 'embed',
    desc: 'Displays an example for rich embeds',
    usage: '',
    aliases: []
  },

  exec: (client, msg, params) => {
    let embed = {
      color: 3447003,
      author: {
        name: msg.author.username,
        icon_url: msg.author.avatarURL // eslint-disable-line camelcase
      },
      title: 'THIS IS A TITLE',
      url: 'http://example.com', // The url for the title.
      description: 'This is a test embed to showcase what they look like and what they can do.\n[Code here](https://github.com/vzwGrey/discord-selfbot/blob/master/commands/embed.js)',
      fields: [
        {
          name: 'Fields',
          value: 'They can have different fields with small headlines.'
        },
        {
          name: 'Masked links',
          value: 'You can put [masked](https://github.com/vzwGrey/discord-selfbot/blob/master/commands/embed.js) links inside of rich embeds.'
        },
        {
          name: 'Markdown',
          value: 'You can put all the *usual* **__Markdown__** inside of them.'
        },
        {
          name: 'Inline fields',
          value: 'You can also have fields inline with eachother using the `inline` property',
          inline: true
        },
        {
          name: 'Images & thumbnails',
          value: 'You can also embed images, and use little thumbnails!',
          inline: true
        }
      ],
      /* thumbnail: {
        url: 'http://i.imgur.com/uaUxZtz.jpg'
      } */
      image: {
        url: 'http://i.imgur.com/uaUxZtz.jpg'
      },
      timestamp: new Date(),
      footer: {
        icon_url: msg.author.avatarURL, // eslint-disable-line camelcase
        text: '©vzwGrey'
      }
    };

    msg.channel.sendMessage('', { embed });
  }
};
<|endoftext|>


<commit_before>var fs = require('fs');
var pathLib = require('path');
var request = require('request');
var libraries = require('nconf');
var q = require('q');
var program = require('commander');
var JSZip = require('node-zip');
var minifyCommand = require('./minify');
var utils = require('../lib/utils');

// add promise variants of program functions using q
utils.qifyProgram(program);

// json configuration file for standard libraries
libraries.file({ file: __dirname + '/../libraries.json' });

/**
 * Node Module Export
 * ------------------
 * Exports the fetch command for nodefront. This fetches libraries from the
 * web and adds them to the user's project.
 *
 * @param libraryName - the name of the library to fetch
 * @param env - the command-live environment
 *  If the -u/--url <url> parameter is specified, the library is fetched from
 *  the given <url>.
 *
 *  If the -p/--path <path> parameter is specified, the -u/--url <url>
 *  parameter must also be specified. This assumes that <url> points to a zip
 *  archive. <path> is a regular expression then references the path to the
 *  library file, relative to the zip file root, that should be extracted.
 *  If <path> is ambiguous, the first matching path will be chosen.
 *
 *  If the -v/--version <version> parameter is specified, the library at the
 *  version <version> will be fetched.
 *
 *  If the -o/--output <directory> parameter is specified, the library will be
 *  added to <directory>. Otherwise, it will be added to the current directory.
 *
 *  If the -t/--type <type> parameter is specified, the extension of the
 *  library will be <type>. Note that the format of the library file name will
 *  be <libraryName>-<version>.<type>. Defaults to js.
 *
 * @param omitSave - if true, omit saving the configuration for this library
 * @param shouldPromise - if true, returns a promise that yields completion
 */
module.exports = exports = function(libraryName, env, omitSave,
    shouldPromise) {
  if (env.interactive) {
    runInteractiveSession(libraryName, env);

    // runInteractiveSession will call this function again without interactive
    // mode enabled and with the interactive inputs
    return;
  }

  var url = env.url;
  var path = env.path;
  var version = env.version;
  var latest = env.latest;
  var type = env.type;
  var minify = env.minify;

  // normalize library names to lowercase
  libraryName = libraryName.toLowerCase();

  if (!url) {
    // find library information in the libraries file
    var library = libraries.get(libraryName);
    if (!library) {
      console.error('Could not find library ' + libraryName + '. Please' +
                    ' specify a URL via the -u/--url parameter or jump into' +
                    ' the interactive mode with -i/--interactive.');
      return;
    }

    url = library.url;
    path = library.path;
    type = library.type || 'js';

    if (!version) {
      // if no version was specified, assume the user wants the latest
      version = library.latest;
    }
    if (!minify) {
      minify = library.minify;
    }
  } else {
    // if library information is given, save it for future use
    libraries.set(libraryName, {
      type: type,
      url: url,
      path: path,
      latest: latest || version,
      minify: minify
    });

    if (!omitSave) {
      libraries.save(function(err) {
        if (err) {
          console.error('Could not save the library configuration to disk.');
        }
      });
    }
  }

  url = url.replace(/\{\{\s*version\s*\}\}/, version);
  var fileName;

  if (version) {
    fileName = libraryName + '-' + version + '.' + type;
  } else {
    fileName = libraryName + '.' + type;
  }

  var dirName = env.output;
  var promise;

  if (url && path) {
    // download the zip archive to a temporary file
    var toFileName = 'nodefront-' + libraryName + '-tmp';

    promise = downloadFile(url, toFileName)
      .then(function() {
        return utils.readFile(toFileName, true);
      })
      .then(function(buffer) {
        var pathRegex = new RegExp(path);
        var zip = new JSZip(buffer.toString('base64'), { base64: true });

        var files = zip.filter(function(path, file) {
          return !file.options.dir && pathRegex.test(path);
        });

        if (files.length === 0) {
          console.error('The path you specified could not be found.');
        } else {
          outputFileData(files[0].data, libraryName, fileName, dirName);

          if (minify) {
            return minifyFetchedFile(dirName, fileName);
          }
        }
      })
      .fin(function() {
        // delete the temporary file
        fs.unlinkSync(toFileName);
      });
  } else if (url) {
    // download the file at the URL and output it
    promise = downloadFile(url)
      .then(function(data) {
        var originalDir;
        outputFileData(data, libraryName, fileName, dirName);

        if (minify) {
          return minifyFetchedFile(dirName, fileName);
        }
      });
  }

  if (shouldPromise) {
    return promise;
  } else {
    promise.end();
  }
};

/**
 * Function: runInteractiveSession
 * -------------------------------
 * Runs an interactive session to fetch a library, querying the user for
 * a name, URL, path, etc.
 *
 * @param libraryName - the name of the library or undefined if not provided
 * @param env - the command-line environment
 */
function runInteractiveSession(libraryName, env) {
  console.log('To begin, please enter the name of the library you would\n' +
              'like to fetch. You will use this name to access the\n' +
              'library in the future and it will also be used to name the\n' +
              'fetched file.\n');

  program.qPromptDefault('Library name', libraryName)
    .then(function(name) {
      libraryName = name;

      console.log('\nWhat URL can this library be accessed at? You may\n' +
                  'specify either a direct link or a link to a zip file\n' +
                  'containing the library you are looking for.\n');
      console.log('For added flexibility in your library choice, you may\n' +
                  'include {{ version }} in your URL. This will be\n' +
                  'replaced by the version number being requested via\n' +
                  'the -v/--version parameter. This implies that you\n' +
                  'must find a flexible URL. If you cannot, that\'s fine;\n' +
                  'this feature is completely optional.\n');

      return program.qPromptDefault('URL', env.url);
    })
    .then(function(url) {
      env.url = url;

      console.log("\nWhat type of library is this (enter 'css' for CSS and\n" +
                  "'js'for JavaScript).\n");
      return program.qPromptDefault('Library type', env.type);
    })
    .then(function(type) {
      env.type = type;

      console.log('\nPlease enter in the latest version of this library:\n');
      return program.qPromptDefault('Latest version', env.latest ||
        env.version);
    })
    .then(function(latest) {
      env.latest = latest;

      console.log('\nIf you would like to fetch a version different from\n' +
                  'the one you just entered, please enter that here:\n');
      return program.qPromptDefault('Version', env.version || env.latest);
    })
    .then(function(version) {
      env.version = version;

      console.log('\nDoes the URL you entered earlier point to a zip\n' +
                  'archive?');
      return program.qConfirm('\nZip archive? ');
    })
    .then(function(isZip) {
      if (isZip) {
        var url = env.url.replace(/\{\{\s*version\s*\}\}/, env.version);
        console.log('\nYou will now need to select which file in the zip\n' +
                    'archive is the library you are looking for. Please\n' +
                    'choose from the list below.\n');

        var toFileName = 'nodefront-' + libraryName + '-zip';
        return downloadFile(url, toFileName)
          .then(function(toFileName) {
            return utils.readFile(toFileName, true);
          })
          .then(function(buffer) {
            var zip = new JSZip(buffer.toString('base64'), { base64: true });
            var files = zip.filter(function(path, file) {
              return !file.options.dir;
            });

            fs.unlinkSync(toFileName);
            // map files to just name
            return files.map(function(file) {
              return file.name;
            });
          })
          .then(function(entries) {
            return program.qChoose(entries)
              .then(function(index) {
                return entries[index];
              });
          });
      }
    })
    .then(function(path) {
      if (path) {
        // first part of the path is usually a variable/unknown directory name,
        // so strip it to ensure the library can always be found
        var firstSlash = path.indexOf('/');
        if (firstSlash !== -1) {
          path = path.substring(firstSlash + 1);
        }
        env.path = utils.regExpEscape(path);
      }

      console.log('\nWould you like the library to be minified upon ' +
                  'download?');
      return program.qConfirm('\nMinify the library? ');
    })
    .then(function(minify) {
      if (minify) {
        env.minify = minify;
      }

      console.log('\nAnd that\'s it! Your library will be fetched\n' +
                  'shortly.\n');
      delete env.interactive;

      // call fetch with the updated environment from interactive user input
      exports(libraryName, env);
      process.stdin.destroy();
    })
    .end();
}

/**
 * Function: minifyFetchedFile
 * ---------------------------
 * Minifies a fetched file given the directory it is in and its name.
 *
 * @param dirName - the directory the fetched file is in
 * @param fileName - the name of the fetched file
 */
function minifyFetchedFile(dirName, fileName) {
  var originalDir;

  if (dirName) {
    originalDir = process.cwd();
    // switch to output dir where the file to minify is located
    process.chdir(dirName);
  }

  return minifyCommand(utils.regExpEscape(fileName),
    { overwrite: true }, true)
    .then(function() {
      if (dirName) {
        // switch back to original dir
        process.chdir(originalDir);
      }
    });
}

/**
 * Function: outputFileData
 * ------------------------
 * Given the data of a file to output, log it to the console or save it as the
 * given file name.
 *
 * @param data - the data of a file
 * @param libraryName - the name of the library to print out to the user
 * @param fileName - if provided, the name of the file to output to
 * @param dirName - if provided, the directory to the store the file in
 */
function outputFileData(data, libraryName, fileName, dirName) {
  var dirDisplay = pathLib.relative('.', dirName);

  // append a slash to dirName if it doesn't already have one
  if (dirName && dirName[dirName.length] !== '/') {
    dirName += '/';
  }

  fs.writeFileSync(dirName + fileName, data);
  console.log('Fetched ' + libraryName + ' into ' + dirDisplay + '/' + fileName + '.');
}

/**
 * Function: downloadFile
 * ----------------------
 * Given a URL of a file, download it and promise the contents.
 *
 * @param url - the URL of the file.
 * @param toFileName - if specified, the contents will be put inside the file
 *  named toFileName and the promise will yield toFileName.
 *
 * @return promise that yields the contents of the file
 */
function downloadFile(url, toFileName) {
  var deferred = q.defer();

  if (!toFileName) {
    // download into RAM
    request(url, function(error, response, body) {
      if (error) {
        deferred.reject(error);
      } else if (response.statusCode != 200) {
        deferred.reject(new Error('Bad response status code ' +
          response.statusCode));
      } else {
        deferred.resolve(body);
      }
    });
  } else {
    var fileRequest = request(url);

    fileRequest.on('error', function(error) {
      deferred.reject(error);
    });

    fileRequest.on('end', function() {
      deferred.resolve(toFileName);
    });

    // download to the given file by piping it to a write stream
    fileRequest.pipe(fs.createWriteStream(toFileName));
  }

  return deferred.promise;
}
<commit_msg>Correct stale comment.<commit_after>var fs = require('fs');
var pathLib = require('path');
var request = require('request');
var libraries = require('nconf');
var q = require('q');
var program = require('commander');
var JSZip = require('node-zip');
var minifyCommand = require('./minify');
var utils = require('../lib/utils');

// add promise variants of program functions using q
utils.qifyProgram(program);

// json configuration file for standard libraries
libraries.file({ file: __dirname + '/../libraries.json' });

/**
 * Node Module Export
 * ------------------
 * Exports the fetch command for nodefront. This fetches libraries from the
 * web and adds them to the user's project.
 *
 * @param libraryName - the name of the library to fetch
 * @param env - the command-live environment
 *  If the -u/--url <url> parameter is specified, the library is fetched from
 *  the given <url>.
 *
 *  If the -p/--path <path> parameter is specified, the -u/--url <url>
 *  parameter must also be specified. This assumes that <url> points to a zip
 *  archive. <path> is a regular expression then references the path to the
 *  library file, relative to the zip file root, that should be extracted.
 *  If <path> is ambiguous, the first matching path will be chosen.
 *
 *  If the -v/--version <version> parameter is specified, the library at the
 *  version <version> will be fetched.
 *
 *  If the -o/--output <directory> parameter is specified, the library will be
 *  added to <directory>. Otherwise, it will be added to the current directory.
 *
 *  If the -t/--type <type> parameter is specified, the extension of the
 *  library will be <type>. Note that the format of the library file name will
 *  be <libraryName>-<version>.<type>. Defaults to js.
 *
 * @param omitSave - if true, omit saving the configuration for this library
 * @param shouldPromise - if true, returns a promise that yields completion
 */
module.exports = exports = function(libraryName, env, omitSave,
    shouldPromise) {
  if (env.interactive) {
    runInteractiveSession(libraryName, env);

    // runInteractiveSession will call this function again without interactive
    // mode enabled and with the interactive inputs
    return;
  }

  var url = env.url;
  var path = env.path;
  var version = env.version;
  var latest = env.latest;
  var type = env.type;
  var minify = env.minify;

  // normalize library names to lowercase
  libraryName = libraryName.toLowerCase();

  if (!url) {
    // find library information in the libraries file
    var library = libraries.get(libraryName);
    if (!library) {
      console.error('Could not find library ' + libraryName + '. Please' +
                    ' specify a URL via the -u/--url parameter or jump into' +
                    ' the interactive mode with -i/--interactive.');
      return;
    }

    url = library.url;
    path = library.path;
    type = library.type || 'js';

    if (!version) {
      // if no version was specified, assume the user wants the latest
      version = library.latest;
    }
    if (!minify) {
      minify = library.minify;
    }
  } else {
    // if library information is given, save it for future use
    libraries.set(libraryName, {
      type: type,
      url: url,
      path: path,
      latest: latest || version,
      minify: minify
    });

    if (!omitSave) {
      libraries.save(function(err) {
        if (err) {
          console.error('Could not save the library configuration to disk.');
        }
      });
    }
  }

  url = url.replace(/\{\{\s*version\s*\}\}/, version);
  var fileName;

  if (version) {
    fileName = libraryName + '-' + version + '.' + type;
  } else {
    fileName = libraryName + '.' + type;
  }

  var dirName = env.output;
  var promise;

  if (url && path) {
    // download the zip archive to a temporary file
    var toFileName = 'nodefront-' + libraryName + '-tmp';

    promise = downloadFile(url, toFileName)
      .then(function() {
        return utils.readFile(toFileName, true);
      })
      .then(function(buffer) {
        var pathRegex = new RegExp(path);
        var zip = new JSZip(buffer.toString('base64'), { base64: true });

        var files = zip.filter(function(path, file) {
          return !file.options.dir && pathRegex.test(path);
        });

        if (files.length === 0) {
          console.error('The path you specified could not be found.');
        } else {
          outputFileData(files[0].data, libraryName, fileName, dirName);

          if (minify) {
            return minifyFetchedFile(dirName, fileName);
          }
        }
      })
      .fin(function() {
        // delete the temporary file
        fs.unlinkSync(toFileName);
      });
  } else if (url) {
    // download the file at the URL and output it
    promise = downloadFile(url)
      .then(function(data) {
        var originalDir;
        outputFileData(data, libraryName, fileName, dirName);

        if (minify) {
          return minifyFetchedFile(dirName, fileName);
        }
      });
  }

  if (shouldPromise) {
    return promise;
  } else {
    promise.end();
  }
};

/**
 * Function: runInteractiveSession
 * -------------------------------
 * Runs an interactive session to fetch a library, querying the user for
 * a name, URL, path, etc.
 *
 * @param libraryName - the name of the library or undefined if not provided
 * @param env - the command-line environment
 */
function runInteractiveSession(libraryName, env) {
  console.log('To begin, please enter the name of the library you would\n' +
              'like to fetch. You will use this name to access the\n' +
              'library in the future and it will also be used to name the\n' +
              'fetched file.\n');

  program.qPromptDefault('Library name', libraryName)
    .then(function(name) {
      libraryName = name;

      console.log('\nWhat URL can this library be accessed at? You may\n' +
                  'specify either a direct link or a link to a zip file\n' +
                  'containing the library you are looking for.\n');
      console.log('For added flexibility in your library choice, you may\n' +
                  'include {{ version }} in your URL. This will be\n' +
                  'replaced by the version number being requested via\n' +
                  'the -v/--version parameter. This implies that you\n' +
                  'must find a flexible URL. If you cannot, that\'s fine;\n' +
                  'this feature is completely optional.\n');

      return program.qPromptDefault('URL', env.url);
    })
    .then(function(url) {
      env.url = url;

      console.log("\nWhat type of library is this (enter 'css' for CSS and\n" +
                  "'js'for JavaScript).\n");
      return program.qPromptDefault('Library type', env.type);
    })
    .then(function(type) {
      env.type = type;

      console.log('\nPlease enter in the latest version of this library:\n');
      return program.qPromptDefault('Latest version', env.latest ||
        env.version);
    })
    .then(function(latest) {
      env.latest = latest;

      console.log('\nIf you would like to fetch a version different from\n' +
                  'the one you just entered, please enter that here:\n');
      return program.qPromptDefault('Version', env.version || env.latest);
    })
    .then(function(version) {
      env.version = version;

      console.log('\nDoes the URL you entered earlier point to a zip\n' +
                  'archive?');
      return program.qConfirm('\nZip archive? ');
    })
    .then(function(isZip) {
      if (isZip) {
        var url = env.url.replace(/\{\{\s*version\s*\}\}/, env.version);
        console.log('\nYou will now need to select which file in the zip\n' +
                    'archive is the library you are looking for. Please\n' +
                    'choose from the list below.\n');

        var toFileName = 'nodefront-' + libraryName + '-zip';
        return downloadFile(url, toFileName)
          .then(function(toFileName) {
            return utils.readFile(toFileName, true);
          })
          .then(function(buffer) {
            var zip = new JSZip(buffer.toString('base64'), { base64: true });
            var files = zip.filter(function(path, file) {
              return !file.options.dir;
            });

            fs.unlinkSync(toFileName);
            // map files to just name
            return files.map(function(file) {
              return file.name;
            });
          })
          .then(function(entries) {
            return program.qChoose(entries)
              .then(function(index) {
                return entries[index];
              });
          });
      }
    })
    .then(function(path) {
      if (path) {
        // first part of the path is usually a variable/unknown directory name,
        // so strip it to ensure the library can always be found
        var firstSlash = path.indexOf('/');
        if (firstSlash !== -1) {
          path = path.substring(firstSlash + 1);
        }
        env.path = utils.regExpEscape(path);
      }

      console.log('\nWould you like the library to be minified upon ' +
                  'download?');
      return program.qConfirm('\nMinify the library? ');
    })
    .then(function(minify) {
      if (minify) {
        env.minify = minify;
      }

      console.log('\nAnd that\'s it! Your library will be fetched\n' +
                  'shortly.\n');
      delete env.interactive;

      // call fetch with the updated environment from interactive user input
      exports(libraryName, env);
      process.stdin.destroy();
    })
    .end();
}

/**
 * Function: minifyFetchedFile
 * ---------------------------
 * Minifies a fetched file given the directory it is in and its name.
 *
 * @param dirName - the directory the fetched file is in
 * @param fileName - the name of the fetched file
 */
function minifyFetchedFile(dirName, fileName) {
  var originalDir;

  if (dirName) {
    originalDir = process.cwd();
    // switch to output dir where the file to minify is located
    process.chdir(dirName);
  }

  return minifyCommand(utils.regExpEscape(fileName),
    { overwrite: true }, true)
    .then(function() {
      if (dirName) {
        // switch back to original dir
        process.chdir(originalDir);
      }
    });
}

/**
 * Function: outputFileData
 * ------------------------
 * Output the given data for a file to the provided file name.
 *
 * @param data - the data of a file
 * @param libraryName - the name of the library to print out to the user
 * @param fileName - if provided, the name of the file to output to
 * @param dirName - if provided, the directory to the store the file in
 */
function outputFileData(data, libraryName, fileName, dirName) {
  var dirDisplay = pathLib.relative('.', dirName);

  // append a slash to dirName if it doesn't already have one
  if (dirName && dirName[dirName.length] !== '/') {
    dirName += '/';
  }

  fs.writeFileSync(dirName + fileName, data);
  console.log('Fetched ' + libraryName + ' into ' + dirDisplay + '/' + fileName + '.');
}

/**
 * Function: downloadFile
 * ----------------------
 * Given a URL of a file, download it and promise the contents.
 *
 * @param url - the URL of the file.
 * @param toFileName - if specified, the contents will be put inside the file
 *  named toFileName and the promise will yield toFileName.
 *
 * @return promise that yields the contents of the file
 */
function downloadFile(url, toFileName) {
  var deferred = q.defer();

  if (!toFileName) {
    // download into RAM
    request(url, function(error, response, body) {
      if (error) {
        deferred.reject(error);
      } else if (response.statusCode != 200) {
        deferred.reject(new Error('Bad response status code ' +
          response.statusCode));
      } else {
        deferred.resolve(body);
      }
    });
  } else {
    var fileRequest = request(url);

    fileRequest.on('error', function(error) {
      deferred.reject(error);
    });

    fileRequest.on('end', function() {
      deferred.resolve(toFileName);
    });

    // download to the given file by piping it to a write stream
    fileRequest.pipe(fs.createWriteStream(toFileName));
  }

  return deferred.promise;
}
<|endoftext|>


<commit_before>'use strict';

var
  fs = require('fs'),

  chalk    = require('chalk'),
  chokidar = require('chokidar'),
  open     = require('open'),

  // TODO: Remove gulp dependencies (ex. include and use `less` instead of `gulp-less`, remove `gulp`, etc)
  gulp       = require('gulp'),
  rename     = require('gulp-rename'),
  less       = require('gulp-less'),
  handlebars = require('gulp-compile-handlebars'),
  connect    = require('gulp-connect'),

  helpers = require('../lib/handlebars-helpers.js');

var
  cwd,

  html,
  css,
  js,
  hbs,
  server,
  watch,
  openUrl,
  alphaMessage,

  command;

cwd = process.cwd();

html = function() {
  gulp.src('*.html')
    .pipe(connect.reload());
};

css = function() {
  gulp.src('assets/css/widget.less')
    .pipe(
      less()
    ).on('error', function(err) {
      console.log(chalk.red(err.message));
      this.emit('end');
    })
    .pipe(gulp.dest('assets/css'))
    .pipe(connect.reload());
};

js = function() {
  gulp.src('assets/javascript/*.js')
    .pipe(connect.reload());
};

hbs = function() {
  var
    templateData,
    options;

  templateData = JSON.parse(fs.readFileSync('./customer.json', 'utf-8'));

  options = {
    helpers: helpers,
    batch: ['templates']
  };

  gulp.src('templates/widget.hbs')
    .pipe(handlebars(templateData, options))
    .pipe(rename('index.html'))
    .pipe(gulp.dest(''));
};

watch = function() {
  chokidar.watch('*.html').on('change', html);
  chokidar.watch('assets/css/*.less').on('change', css);
  chokidar.watch('assets/javascript/*.js').on('change', js);
  chokidar.watch(['*.json', 'templates/**/*.hbs']).on('change', hbs);
};

server = function() {
  connect.server({
    root: process.cwd(),
    livereload: true,
    host: '0.0.0.0'
  });
};

openUrl = function() {
  open('http://0.0.0.0:8080');
};

alphaMessage = function() {
  console.log(chalk.yellow('The serve command is alpha and is not a perfect replica of the live environment.\nMore details: https://github.com/saasquatch/saasquatch-cli/#why-is-this-alpha'));
};

command = function(program) {
  var serve;

  serve = program.command('serve');

  serve
    .description('[alpha] Start a server for a theme')
    .action(function() {
      alphaMessage();
      server();
      hbs();
      css();
      watch();
      openUrl();
    });

  return serve;
};

module.exports = command;
<commit_msg>Watch CSS and JavaScript in subdirectories<commit_after>'use strict';

var
  fs = require('fs'),

  chalk    = require('chalk'),
  chokidar = require('chokidar'),
  open     = require('open'),

  // TODO: Remove gulp dependencies (ex. include and use `less` instead of `gulp-less`, remove `gulp`, etc)
  gulp       = require('gulp'),
  rename     = require('gulp-rename'),
  less       = require('gulp-less'),
  handlebars = require('gulp-compile-handlebars'),
  connect    = require('gulp-connect'),

  helpers = require('../lib/handlebars-helpers.js');

var
  cwd,

  html,
  css,
  js,
  hbs,
  server,
  watch,
  openUrl,
  alphaMessage,

  command;

cwd = process.cwd();

html = function() {
  gulp.src('*.html')
    .pipe(connect.reload());
};

css = function() {
  gulp.src('assets/css/widget.less')
    .pipe(
      less()
    ).on('error', function(err) {
      console.log(chalk.red(err.message));
      this.emit('end');
    })
    .pipe(gulp.dest('assets/css'))
    .pipe(connect.reload());
};

js = function(path) {
  gulp.src(path)
    .pipe(connect.reload());
};

hbs = function() {
  var
    templateData,
    options;

  templateData = JSON.parse(fs.readFileSync('./customer.json', 'utf-8'));

  options = {
    helpers: helpers,
    batch: ['templates']
  };

  gulp.src('templates/widget.hbs')
    .pipe(handlebars(templateData, options))
    .pipe(rename('index.html'))
    .pipe(gulp.dest(''));
};

watch = function() {
  chokidar.watch('*.html').on('change', html);
  chokidar.watch('assets/css/**/*.less').on('change', css);
  chokidar.watch('assets/javascript/**/*.js').on('change', js);
  chokidar.watch(['*.json', 'templates/**/*.hbs']).on('change', hbs);
};

server = function() {
  connect.server({
    root: process.cwd(),
    livereload: true,
    host: '0.0.0.0'
  });
};

openUrl = function() {
  open('http://0.0.0.0:8080');
};

alphaMessage = function() {
  console.log(chalk.yellow('The serve command is alpha and is not a perfect replica of the live environment.\nMore details: https://github.com/saasquatch/saasquatch-cli/#why-is-this-alpha'));
};

command = function(program) {
  var serve;

  serve = program.command('serve');

  serve
    .description('[alpha] Start a server for a theme')
    .action(function() {
      alphaMessage();
      server();
      hbs();
      css();
      watch();
      openUrl();
    });

  return serve;
};

module.exports = command;
<|endoftext|>


<commit_before>const Discord = require('discord.js');
const weather = require('weather-js');

module.exports = (client, message, args) => {

    weather.find({search: args.join(" "), degreeType: 'C'}, function(err, result) {
        if (err) message.channel.send(err);

        // lugar valido.
        if (result === undefined || result.length === 0) {
            message.channel.send('**Digite uma localidade válida!**')
            return;
        }
        else
        {
            // variaveis
            var current = result[0].current;
            var location = result[0].location;

            message.channel.send({embed:{
                color: 3447003,
                author: {  name: current.observationpoint, icon_url: current.imageUrl },
                title: `Informações do tempo`, description: `${current.skytext}`,
                fields:
                [
                  { name: `Fuso horário: `, value: `UTC${location.timezone}`, "inline": true },
                  { name: `Tipo de grau: `, value: location.degreetype , "inline": true,
                  { name: `Temperatura: `, value: `${current.temperature} Graus`, "inline": true },
                  { name: `Parece: `, value: `${current.feelslike} Graus`, "inline": true },
                  { name: `Vento: `, value: current.winddisplay, "inline": true },
                  { name: `Humidade: `, value: `${current.humidity}%`, "inline": true }
                ],
                timestamp: new Date(), footer: { icon_url: client.user.avatarURL , text: "© Verificado em" }
            }
          }).then(msg => {
            msg.delete(60000)
          });
        }
    })
    message.delete(60000);
};

/*.setDescription(`**${current.skytext}**`) // This is the text of what the sky looks like, remember you can find all of this on the weather-js npm page.
.setAuthor(`Weather for ${current.observationpoint}`) // This shows the current location of the weather.
.setThumbnail(current.imageUrl) // This sets the thumbnail of the embed
.setColor(0x00AE86) // This sets the color of the embed, you can set this to anything if you look put a hex color picker, just make sure you put 0x infront of the hex
.addField('Timezone',`UTC${location.timezone}`, true) // This is the first field, it shows the timezone, and the true means `inline`, you can read more about this on the official discord.js documentation
.addField('Degree Type',location.degreetype, true)// This is the field that shows the degree type, and is inline
.addField('Temperature',`${current.temperature} Degrees`, true)
.addField('Feels Like', `${current.feelslike} Degrees`, true)
.addField('Winds',current.winddisplay, true)
.addField('Humidity', `${current.humidity}%`, true)*/<commit_msg><commit_after>const Discord = require('discord.js');
const weather = require('weather-js');

module.exports = (client, message, args) => {

    weather.find({search: args.join(" "), degreeType: 'C'}, function(err, result) {
        if (err) message.channel.send(err);

        // lugar valido.
        if (result === undefined || result.length === 0) {
            message.channel.send('**Digite uma localidade válida!**')
            return;
        }
        else
        {
            // variaveis
            var current = result[0].current;
            var location = result[0].location;

            message.channel.send({embed:{
                color: 3447003,
                author: {  name: current.observationpoint, icon_url: current.imageUrl },
                title: `Informações do tempo`, description: `${current.skytext}`,
                fields:
                [
                  { name: `Fuso horário: `, value: `UTC${location.timezone}`, "inline": true },
                  { name: `Tipo de grau: `, value: location.degreetype , "inline": true},
                  { name: `Temperatura: `, value: `${current.temperature} Graus`, "inline": true },
                  { name: `Parece: `, value: `${current.feelslike} Graus`, "inline": true },
                  { name: `Vento: `, value: current.winddisplay, "inline": true },
                  { name: `Humidade: `, value: `${current.humidity}%`, "inline": true }
                ],
                timestamp: new Date(), footer: { icon_url: client.user.avatarURL , text: "© Verificado em" }
            }
          }).then(msg => {
            msg.delete(60000)
          });
        }
    })
    message.delete(60000);
};

/*.setDescription(`**${current.skytext}**`) // This is the text of what the sky looks like, remember you can find all of this on the weather-js npm page.
.setAuthor(`Weather for ${current.observationpoint}`) // This shows the current location of the weather.
.setThumbnail(current.imageUrl) // This sets the thumbnail of the embed
.setColor(0x00AE86) // This sets the color of the embed, you can set this to anything if you look put a hex color picker, just make sure you put 0x infront of the hex
.addField('Timezone',`UTC${location.timezone}`, true) // This is the first field, it shows the timezone, and the true means `inline`, you can read more about this on the official discord.js documentation
.addField('Degree Type',location.degreetype, true)// This is the field that shows the degree type, and is inline
.addField('Temperature',`${current.temperature} Degrees`, true)
.addField('Feels Like', `${current.feelslike} Degrees`, true)
.addField('Winds',current.winddisplay, true)
.addField('Humidity', `${current.humidity}%`, true)*/<|endoftext|>