mirror of
https://github.com/frappe/books.git
synced 2024-11-10 07:40:55 +00:00
Merge pull request #110 from frappe/knex
feat: Use Knex for query building
This commit is contained in:
commit
218b1a7a6b
19
.travis.yml
19
.travis.yml
@ -1,19 +1,10 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- "8"
|
||||
|
||||
services:
|
||||
- mysql
|
||||
|
||||
before_install:
|
||||
- mysql -u root -e 'create database test_frappejs'
|
||||
- echo "USE mysql;\nCREATE USER 'test_frappejs'@'localhost' IDENTIFIED BY 'test_frappejs';\nFLUSH PRIVILEGES;\n"
|
||||
- echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappejs\`.* TO 'test_frappejs'@'localhost';\n"
|
||||
- "git clone https://github.com/frappe/frappejs && cd frappejs"
|
||||
- "npm install -g yarn"
|
||||
- "yarn"
|
||||
- 8
|
||||
|
||||
script:
|
||||
- "yarn link && yarn link frappejs"
|
||||
- "yarn run test"
|
||||
- yarn
|
||||
- yarn link
|
||||
- yarn link frappejs
|
||||
- yarn test
|
||||
|
@ -1,18 +1,23 @@
|
||||
const frappe = require('frappejs');
|
||||
const Observable = require('frappejs/utils/observable');
|
||||
const Knex = require('knex');
|
||||
|
||||
module.exports = class Database extends Observable {
|
||||
constructor() {
|
||||
super();
|
||||
this.initTypeMap();
|
||||
this.connectionParams = {};
|
||||
}
|
||||
|
||||
async connect() {
|
||||
// this.conn
|
||||
connect() {
|
||||
this.knex = Knex(this.connectionParams);
|
||||
this.knex.on('query-error', error => {
|
||||
error.type = this.getError(error);
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
this.conn.close();
|
||||
//
|
||||
}
|
||||
|
||||
async migrate() {
|
||||
@ -31,30 +36,21 @@ module.exports = class Database extends Observable {
|
||||
await this.commit();
|
||||
}
|
||||
|
||||
async createTable(doctype, newName = null) {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let columns = [];
|
||||
let indexes = [];
|
||||
tableExists(table) {
|
||||
return this.knex.schema.hasTable(table);
|
||||
}
|
||||
|
||||
for (let field of meta.getValidFields({ withChildren: false })) {
|
||||
if (this.typeMap[field.fieldtype]) {
|
||||
this.updateColumnDefinition(field, columns, indexes);
|
||||
async createTable(doctype, tableName = null) {
|
||||
let fields = this.getValidFields(doctype);
|
||||
return await this.runCreateTableQuery(tableName || doctype, fields);
|
||||
}
|
||||
|
||||
runCreateTableQuery(doctype, fields) {
|
||||
return this.knex.schema.createTable(doctype, table => {
|
||||
for (let field of fields) {
|
||||
this.buildColumnForTable(table, field);
|
||||
}
|
||||
}
|
||||
|
||||
return await this.runCreateTableQuery(newName || doctype, columns, indexes);
|
||||
}
|
||||
|
||||
async tableExists(table) {
|
||||
// return true if table exists
|
||||
}
|
||||
|
||||
async runCreateTableQuery(doctype, columns, indexes) {
|
||||
// override
|
||||
}
|
||||
|
||||
updateColumnDefinition(field, columns, indexes) {
|
||||
// return `${df.fieldname} ${this.typeMap[df.fieldtype]} ${ ? "PRIMARY KEY" : ""} ${df.required && !df.default ? "NOT NULL" : ""} ${df.default ? `DEFAULT ${df.default}` : ""}`
|
||||
});
|
||||
}
|
||||
|
||||
async alterTable(doctype) {
|
||||
@ -62,26 +58,66 @@ module.exports = class Database extends Observable {
|
||||
let diff = await this.getColumnDiff(doctype);
|
||||
let newForeignKeys = await this.getNewForeignKeys(doctype);
|
||||
|
||||
if (diff.added.length) {
|
||||
await this.addColumns(doctype, diff.added);
|
||||
return this.knex.schema
|
||||
.table(doctype, table => {
|
||||
if (diff.added.length) {
|
||||
for (let field of diff.added) {
|
||||
this.buildColumnForTable(table, field);
|
||||
}
|
||||
}
|
||||
|
||||
if (diff.removed.length) {
|
||||
this.removeColumns(doctype, diff.removed);
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (newForeignKeys.length) {
|
||||
return this.addForeignKeys(doctype, newForeignKeys);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
buildColumnForTable(table, field) {
|
||||
let columnType = this.getColumnType(field);
|
||||
let column = table[columnType](field.fieldname);
|
||||
|
||||
// primary key
|
||||
if (field.fieldname === 'name') {
|
||||
column.primary();
|
||||
}
|
||||
|
||||
if (diff.removed.length) {
|
||||
await this.removeColumns(doctype, diff.removed);
|
||||
// default value
|
||||
if (field.default) {
|
||||
column.defaultTo(field.default);
|
||||
}
|
||||
|
||||
if (newForeignKeys.length) {
|
||||
await this.addForeignKeys(doctype, newForeignKeys);
|
||||
// required
|
||||
if (field.required) {
|
||||
column.notNullable();
|
||||
}
|
||||
|
||||
// link
|
||||
if (field.fieldtype === 'Link' && field.target && column.foreign) {
|
||||
let meta = frappe.getMeta(field.target);
|
||||
column
|
||||
.foreign(field.fieldname)
|
||||
.references('name')
|
||||
.inTable(meta.getBaseDocType())
|
||||
.onUpdate('CASCADE')
|
||||
.onDelete('RESTRICT');
|
||||
}
|
||||
}
|
||||
|
||||
async getColumnDiff(doctype) {
|
||||
const tableColumns = await this.getTableColumns(doctype);
|
||||
const validFields = frappe.getMeta(doctype).getValidFields({ withChildren: false });
|
||||
const validFields = this.getValidFields(doctype);
|
||||
const diff = { added: [], removed: [] };
|
||||
|
||||
for (let field of validFields) {
|
||||
if (!tableColumns.includes(field.fieldname) && this.typeMap[field.fieldtype]) {
|
||||
if (
|
||||
!tableColumns.includes(field.fieldname) &&
|
||||
this.getColumnType(field)
|
||||
) {
|
||||
diff.added.push(field);
|
||||
}
|
||||
}
|
||||
@ -96,25 +132,21 @@ module.exports = class Database extends Observable {
|
||||
return diff;
|
||||
}
|
||||
|
||||
async addColumns(doctype, added) {
|
||||
for (let field of added) {
|
||||
await this.runAddColumnQuery(doctype, field);
|
||||
}
|
||||
}
|
||||
|
||||
async removeColumns(doctype, removed) {
|
||||
for (let column of removed) {
|
||||
await this.runRemoveColumnQuery(doctype, column);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async getNewForeignKeys(doctype) {
|
||||
let foreignKeys = await this.getForeignKeys(doctype);
|
||||
let newForeignKeys = [];
|
||||
let meta = frappe.getMeta(doctype);
|
||||
for (let field of meta.getValidFields({ withChildren: false })) {
|
||||
if (field.fieldtype === 'Link' && !foreignKeys.includes(field.fieldname)) {
|
||||
if (
|
||||
field.fieldtype === 'Link' &&
|
||||
!foreignKeys.includes(field.fieldname)
|
||||
) {
|
||||
newForeignKeys.push(field);
|
||||
}
|
||||
}
|
||||
@ -127,18 +159,14 @@ module.exports = class Database extends Observable {
|
||||
}
|
||||
}
|
||||
|
||||
async getForeignKey(doctype, field) {
|
||||
|
||||
async getForeignKeys(doctype, field) {
|
||||
return []
|
||||
}
|
||||
|
||||
async getTableColumns(doctype) {
|
||||
return [];
|
||||
}
|
||||
|
||||
async runAddColumnQuery(doctype, field) {
|
||||
// alter table {doctype} add column ({column_def});
|
||||
}
|
||||
|
||||
async get(doctype, name = null, fields = '*') {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let doc;
|
||||
@ -161,7 +189,7 @@ module.exports = class Database extends Observable {
|
||||
for (let field of tableFields) {
|
||||
doc[field.fieldname] = await this.getAll({
|
||||
doctype: field.childtype,
|
||||
fields: ["*"],
|
||||
fields: ['*'],
|
||||
filters: { parent: doc.name },
|
||||
orderBy: 'idx',
|
||||
order: 'asc'
|
||||
@ -184,15 +212,15 @@ module.exports = class Database extends Observable {
|
||||
return doc;
|
||||
}
|
||||
|
||||
async getOne(doctype, name, fields = '*') {
|
||||
// select {fields} form {doctype} where name = ?
|
||||
}
|
||||
getOne(doctype, name, fields = '*') {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let baseDoctype = meta.getBaseDocType();
|
||||
|
||||
prepareFields(fields) {
|
||||
if (fields instanceof Array) {
|
||||
fields = fields.join(", ");
|
||||
}
|
||||
return fields;
|
||||
return this.knex
|
||||
.select(fields)
|
||||
.from(baseDoctype)
|
||||
.where('name', name)
|
||||
.first();
|
||||
}
|
||||
|
||||
triggerChange(doctype, name) {
|
||||
@ -225,12 +253,11 @@ module.exports = class Database extends Observable {
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
async insertChildren(meta, doc, doctype) {
|
||||
let tableFields = meta.getTableFields();
|
||||
for (let field of tableFields) {
|
||||
let idx = 0;
|
||||
for (let child of (doc[field.fieldname] || [])) {
|
||||
for (let child of doc[field.fieldname] || []) {
|
||||
this.prepareChild(doctype, doc.name, child, field, idx);
|
||||
await this.insertOne(field.childtype, child);
|
||||
idx++;
|
||||
@ -238,8 +265,15 @@ module.exports = class Database extends Observable {
|
||||
}
|
||||
}
|
||||
|
||||
async insertOne(doctype, doc) {
|
||||
// insert into {doctype} ({fields}) values ({values})
|
||||
insertOne(doctype, doc) {
|
||||
let fields = this.getValidFields(doctype);
|
||||
|
||||
if (!doc.name) {
|
||||
doc.name = frappe.getRandomString();
|
||||
}
|
||||
|
||||
let formattedDoc = this.getFormattedDoc(fields, doc);
|
||||
return this.knex(doctype).insert(formattedDoc);
|
||||
}
|
||||
|
||||
async update(doctype, doc) {
|
||||
@ -265,28 +299,37 @@ module.exports = class Database extends Observable {
|
||||
async updateChildren(meta, doc, doctype) {
|
||||
let tableFields = meta.getTableFields();
|
||||
for (let field of tableFields) {
|
||||
// first key is "parent" - for SQL params
|
||||
let added = [doc.name];
|
||||
for (let child of (doc[field.fieldname] || [])) {
|
||||
this.prepareChild(doctype, doc.name, child, field, added.length - 1);
|
||||
let added = [];
|
||||
for (let child of doc[field.fieldname] || []) {
|
||||
this.prepareChild(doctype, doc.name, child, field, added.length);
|
||||
if (await this.exists(field.childtype, child.name)) {
|
||||
await this.updateOne(field.childtype, child);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
await this.insertOne(field.childtype, child);
|
||||
}
|
||||
added.push(child.name);
|
||||
}
|
||||
await this.runDeleteOtherChildren(field, added);
|
||||
await this.runDeleteOtherChildren(field, doc.name, added);
|
||||
}
|
||||
}
|
||||
|
||||
async updateOne(doctype, doc) {
|
||||
// update {doctype} set {field=value} where name=?
|
||||
updateOne(doctype, doc) {
|
||||
let validFields = this.getValidFields(doctype);
|
||||
let fieldsToUpdate = Object.keys(doc).filter(f => f !== 'name');
|
||||
let fields = validFields.filter(df => fieldsToUpdate.includes(df.fieldname));
|
||||
let formattedDoc = this.getFormattedDoc(fields, doc);
|
||||
|
||||
return this.knex(doctype)
|
||||
.where('name', doc.name)
|
||||
.update(formattedDoc);
|
||||
}
|
||||
|
||||
async runDeleteOtherChildren(field, added) {
|
||||
// delete from doctype where parent = ? and name not in (?, ?, ?)
|
||||
runDeleteOtherChildren(field, parent, added) {
|
||||
// delete other children
|
||||
return this.knex(field.childtype)
|
||||
.where('parent', parent)
|
||||
.andWhere('name', 'not in', added)
|
||||
.delete();
|
||||
}
|
||||
|
||||
async updateSingle(meta, doc, doctype) {
|
||||
@ -299,18 +342,25 @@ module.exports = class Database extends Observable {
|
||||
parent: doctype,
|
||||
fieldname: field.fieldname,
|
||||
value: value
|
||||
})
|
||||
});
|
||||
await singleValue.insert();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async deleteSingleValues(name) {
|
||||
// await frappe.db.run('delete from SingleValue where parent=?', name)
|
||||
deleteSingleValues(name) {
|
||||
return this.knex('SingleValue')
|
||||
.where('parent', name)
|
||||
.delete();
|
||||
}
|
||||
|
||||
async rename(doctype, oldName, newName) {
|
||||
// await frappe.db.run('update doctype set name = ? where name = ?', name)
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let baseDoctype = meta.getBaseDocType();
|
||||
await this.knex(baseDoctype)
|
||||
.update({ name: newName })
|
||||
.where('name', oldName);
|
||||
await frappe.db.commit();
|
||||
}
|
||||
|
||||
prepareChild(parenttype, parent, child, field, idx) {
|
||||
@ -323,16 +373,17 @@ module.exports = class Database extends Observable {
|
||||
child.idx = idx;
|
||||
}
|
||||
|
||||
getKeys(doctype) {
|
||||
getValidFields(doctype) {
|
||||
return frappe.getMeta(doctype).getValidFields({ withChildren: false });
|
||||
}
|
||||
|
||||
getFormattedValues(fields, doc) {
|
||||
let values = fields.map(field => {
|
||||
getFormattedDoc(fields, doc) {
|
||||
let formattedDoc = {};
|
||||
fields.map(field => {
|
||||
let value = doc[field.fieldname];
|
||||
return this.getFormattedValue(field, value);
|
||||
formattedDoc[field.fieldname] = this.getFormattedValue(field, value);
|
||||
});
|
||||
return values;
|
||||
return formattedDoc;
|
||||
}
|
||||
|
||||
getFormattedValue(field, value) {
|
||||
@ -387,11 +438,15 @@ module.exports = class Database extends Observable {
|
||||
}
|
||||
|
||||
async deleteOne(doctype, name) {
|
||||
// delete from {doctype} where name = ?
|
||||
return this.knex(doctype)
|
||||
.where('name', name)
|
||||
.delete();
|
||||
}
|
||||
|
||||
async deleteChildren(parenttype, parent) {
|
||||
// delete from {parenttype} where parent = ?
|
||||
deleteChildren(parenttype, parent) {
|
||||
return this.knex(parenttype)
|
||||
.where('parent', parent)
|
||||
.delete();
|
||||
}
|
||||
|
||||
async exists(doctype, name) {
|
||||
@ -427,14 +482,57 @@ module.exports = class Database extends Observable {
|
||||
}
|
||||
|
||||
async setValues(doctype, name, fieldValuePair) {
|
||||
//
|
||||
let doc = Object.assign({}, fieldValuePair, { name });
|
||||
return this.updateOne(doctype, doc);
|
||||
}
|
||||
|
||||
getAll({ doctype, fields, filters, start, limit, orderBy = 'modified', order = 'desc' } = {}) {
|
||||
// select {fields} from {doctype} where {filters} order by {orderBy} {order} limit {start} {limit}
|
||||
getAll({
|
||||
doctype,
|
||||
fields,
|
||||
filters,
|
||||
start,
|
||||
limit,
|
||||
groupBy,
|
||||
orderBy = 'creation',
|
||||
order = 'desc'
|
||||
} = {}) {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let baseDoctype = meta.getBaseDocType();
|
||||
if (!fields) {
|
||||
fields = meta.getKeywordFields();
|
||||
fields.push('name');
|
||||
}
|
||||
if (typeof fields === 'string') {
|
||||
fields = [fields];
|
||||
}
|
||||
if (meta.filters) {
|
||||
filters = Object.assign({}, filters, meta.filters);
|
||||
}
|
||||
|
||||
let builder = this.knex.select(fields).from(baseDoctype);
|
||||
|
||||
this.applyFiltersToBuilder(builder, filters);
|
||||
|
||||
if (orderBy) {
|
||||
builder.orderBy(orderBy, order);
|
||||
}
|
||||
|
||||
if (groupBy) {
|
||||
builder.groupBy(groupBy);
|
||||
}
|
||||
|
||||
if (start) {
|
||||
builder.offset(start);
|
||||
}
|
||||
|
||||
if (limit) {
|
||||
builder.limit(limit);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
getFilterConditions(filters) {
|
||||
applyFiltersToBuilder(builder, filters) {
|
||||
// {"status": "Open"} => `status = "Open"`
|
||||
|
||||
// {"status": "Open", "name": ["like", "apple%"]}
|
||||
@ -445,9 +543,8 @@ module.exports = class Database extends Observable {
|
||||
|
||||
let filtersArray = [];
|
||||
|
||||
for (let key in filters) {
|
||||
let value = filters[key];
|
||||
let field = key;
|
||||
for (let field in filters) {
|
||||
let value = filters[field];
|
||||
let operator = '=';
|
||||
let comparisonValue = value;
|
||||
|
||||
@ -460,7 +557,7 @@ module.exports = class Database extends Observable {
|
||||
operator = 'like';
|
||||
}
|
||||
|
||||
if (['like', 'includes'].includes(operator) && !comparisonValue.includes('%')) {
|
||||
if (operator === 'like' && !comparisonValue.includes('%')) {
|
||||
comparisonValue = `%${comparisonValue}%`;
|
||||
}
|
||||
}
|
||||
@ -475,74 +572,41 @@ module.exports = class Database extends Observable {
|
||||
}
|
||||
}
|
||||
|
||||
let conditions = filtersArray.map(filter => {
|
||||
filtersArray.map(filter => {
|
||||
const [field, operator, comparisonValue] = filter;
|
||||
|
||||
let placeholder = Array.isArray(comparisonValue) ?
|
||||
comparisonValue.map(v => '?').join(', ') :
|
||||
'?';
|
||||
|
||||
return `ifnull(${field}, '') ${operator} (${placeholder})`;
|
||||
builder.where(field, operator, comparisonValue);
|
||||
});
|
||||
|
||||
let values = filtersArray.reduce((acc, filter) => {
|
||||
const comparisonValue = filter[2];
|
||||
if (Array.isArray(comparisonValue)) {
|
||||
acc = acc.concat(comparisonValue);
|
||||
} else {
|
||||
acc.push(comparisonValue);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
return {
|
||||
conditions: conditions.length ? conditions.join(" and ") : "",
|
||||
values
|
||||
};
|
||||
}
|
||||
|
||||
async run(query, params) {
|
||||
run(query, params) {
|
||||
// run query
|
||||
return this.sql(query, params);
|
||||
}
|
||||
|
||||
async sql(query, params) {
|
||||
sql(query, params) {
|
||||
// run sql
|
||||
return this.knex.raw(query, params);
|
||||
}
|
||||
|
||||
async commit() {
|
||||
// commit
|
||||
}
|
||||
|
||||
initTypeMap() {
|
||||
this.typeMap = {
|
||||
'AutoComplete': 'text'
|
||||
, 'Currency': 'real'
|
||||
, 'Int': 'integer'
|
||||
, 'Float': 'real'
|
||||
, 'Percent': 'real'
|
||||
, 'Check': 'integer'
|
||||
, 'Small Text': 'text'
|
||||
, 'Long Text': 'text'
|
||||
, 'Code': 'text'
|
||||
, 'Text Editor': 'text'
|
||||
, 'Date': 'text'
|
||||
, 'Datetime': 'text'
|
||||
, 'Time': 'text'
|
||||
, 'Text': 'text'
|
||||
, 'Data': 'text'
|
||||
, 'Link': 'text'
|
||||
, 'DynamicLink': 'text'
|
||||
, 'Password': 'text'
|
||||
, 'Select': 'text'
|
||||
, 'Read Only': 'text'
|
||||
, 'File': 'text'
|
||||
, 'Attach': 'text'
|
||||
, 'AttachImage': 'text'
|
||||
, 'Signature': 'text'
|
||||
, 'Color': 'text'
|
||||
, 'Barcode': 'text'
|
||||
, 'Geolocation': 'text'
|
||||
try {
|
||||
await this.sql('commit');
|
||||
} catch (e) {
|
||||
if (e.type !== frappe.errors.CannotCommitError) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
getColumnType(field) {
|
||||
return this.typeMap[field.fieldtype];
|
||||
}
|
||||
|
||||
getError(err) {
|
||||
return frappe.errors.DatabaseError;
|
||||
}
|
||||
|
||||
initTypeMap() {
|
||||
this.typeMap = {};
|
||||
}
|
||||
};
|
||||
|
@ -1,294 +1,92 @@
|
||||
const frappe = require('frappejs');
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
const Database = require('./database');
|
||||
const errors = require('frappejs/common/errors');
|
||||
const debug = false;
|
||||
|
||||
class SqliteDatabase extends Database {
|
||||
constructor({ dbPath }) {
|
||||
super();
|
||||
this.dbPath = dbPath;
|
||||
}
|
||||
|
||||
connect(dbPath) {
|
||||
if (dbPath) {
|
||||
this.dbPath = dbPath;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this.conn = new sqlite3.Database(this.dbPath, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
reject(err);
|
||||
return;
|
||||
this.connectionParams = {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: this.dbPath
|
||||
},
|
||||
pool: {
|
||||
afterCreate(conn, done) {
|
||||
conn.run('PRAGMA foreign_keys=ON');
|
||||
done();
|
||||
}
|
||||
if (debug) {
|
||||
this.conn.on('trace', (trace) => console.log(trace));
|
||||
}
|
||||
this.run('PRAGMA foreign_keys=ON').then(resolve);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async tableExists(table) {
|
||||
const name = await this.sql(`SELECT name FROM sqlite_master WHERE type='table' AND name='${table}'`);
|
||||
return (name && name.length) ? true : false;
|
||||
},
|
||||
useNullAsDefault: true
|
||||
};
|
||||
}
|
||||
|
||||
async addForeignKeys(doctype, newForeignKeys) {
|
||||
await this.run('PRAGMA foreign_keys=OFF');
|
||||
await this.run('BEGIN TRANSACTION');
|
||||
await this.sql('PRAGMA foreign_keys=OFF');
|
||||
await this.sql('BEGIN TRANSACTION');
|
||||
|
||||
const tempName = 'TEMP' + doctype
|
||||
const tempName = 'TEMP' + doctype;
|
||||
|
||||
// create temp table
|
||||
await this.createTable(doctype, tempName);
|
||||
|
||||
const columns = (await this.getTableColumns(tempName)).join(', ');
|
||||
|
||||
// copy from old to new table
|
||||
await this.run(`INSERT INTO ${tempName} (${columns}) SELECT ${columns} from ${doctype}`);
|
||||
await this.knex(tempName).insert(this.knex.select().from(doctype));
|
||||
|
||||
// drop old table
|
||||
await this.run(`DROP TABLE ${doctype}`);
|
||||
await this.knex.schema.dropTable(doctype);
|
||||
|
||||
// rename new table
|
||||
await this.run(`ALTER TABLE ${tempName} RENAME TO ${doctype}`);
|
||||
await this.knex.schema.renameTable(tempName, doctype);
|
||||
|
||||
await this.run('COMMIT');
|
||||
await this.run('PRAGMA foreign_keys=ON');
|
||||
await this.sql('COMMIT');
|
||||
await this.sql('PRAGMA foreign_keys=ON');
|
||||
}
|
||||
|
||||
removeColumns() {
|
||||
// pass
|
||||
}
|
||||
|
||||
async runCreateTableQuery(doctype, columns, indexes) {
|
||||
const query = `CREATE TABLE IF NOT EXISTS ${doctype} (
|
||||
${columns.join(", ")} ${indexes.length ? (", " + indexes.join(", ")) : ''})`;
|
||||
|
||||
return await this.run(query);
|
||||
}
|
||||
|
||||
updateColumnDefinition(field, columns, indexes) {
|
||||
let def = this.getColumnDefinition(field);
|
||||
|
||||
columns.push(def);
|
||||
|
||||
if (field.fieldtype === 'Link' && field.target) {
|
||||
let meta = frappe.getMeta(field.target);
|
||||
indexes.push(`FOREIGN KEY (${field.fieldname}) REFERENCES ${meta.getBaseDocType()} ON UPDATE CASCADE ON DELETE RESTRICT`);
|
||||
}
|
||||
}
|
||||
|
||||
getColumnDefinition(field) {
|
||||
let defaultValue = field.default;
|
||||
if (typeof defaultValue === 'string') {
|
||||
defaultValue = `'${defaultValue}'`
|
||||
}
|
||||
let def = [
|
||||
field.fieldname,
|
||||
this.typeMap[field.fieldtype],
|
||||
field.fieldname === 'name' ? 'PRIMARY KEY NOT NULL' : '',
|
||||
field.required ? 'NOT NULL' : '',
|
||||
field.default ? `DEFAULT ${defaultValue}` : ''
|
||||
].join(' ');
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
async getTableColumns(doctype) {
|
||||
return (await this.sql(`PRAGMA table_info(${doctype})`)).map(d => d.name);
|
||||
}
|
||||
|
||||
async getForeignKeys(doctype) {
|
||||
return (await this.sql(`PRAGMA foreign_key_list(${doctype})`)).map(d => d.from);
|
||||
}
|
||||
|
||||
async runAddColumnQuery(doctype, field, values) {
|
||||
await this.run(`ALTER TABLE ${doctype} ADD COLUMN ${this.getColumnDefinition(field)}`, values);
|
||||
}
|
||||
|
||||
getOne(doctype, name, fields = '*') {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let baseDoctype = meta.getBaseDocType();
|
||||
fields = this.prepareFields(fields);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.conn.get(`select ${fields} from ${baseDoctype}
|
||||
where name = ?`, name,
|
||||
(err, row) => {
|
||||
resolve(row || {});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async insertOne(doctype, doc) {
|
||||
let fields = this.getKeys(doctype);
|
||||
let placeholders = fields.map(d => '?').join(', ');
|
||||
|
||||
if (!doc.name) {
|
||||
doc.name = frappe.getRandomString();
|
||||
}
|
||||
|
||||
return await this.run(`insert into ${doctype}
|
||||
(${fields.map(field => field.fieldname).join(", ")})
|
||||
values (${placeholders})`, this.getFormattedValues(fields, doc));
|
||||
}
|
||||
|
||||
async updateOne(doctype, doc) {
|
||||
let fields = this.getKeys(doctype);
|
||||
let assigns = fields.map(field => `${field.fieldname} = ?`);
|
||||
let values = this.getFormattedValues(fields, doc);
|
||||
|
||||
// additional name for where clause
|
||||
values.push(doc.name);
|
||||
|
||||
return await this.run(`update ${doctype}
|
||||
set ${assigns.join(", ")} where name=?`, values);
|
||||
}
|
||||
|
||||
async runDeleteOtherChildren(field, added) {
|
||||
// delete other children
|
||||
// `delete from doctype where parent = ? and name not in (?, ?, ?)}`
|
||||
await this.run(`delete from ${field.childtype}
|
||||
where
|
||||
parent = ? and
|
||||
name not in (${added.slice(1).map(d => '?').join(', ')})`, added);
|
||||
}
|
||||
|
||||
async deleteOne(doctype, name) {
|
||||
return await this.run(`delete from ${doctype} where name=?`, name);
|
||||
}
|
||||
|
||||
async deleteChildren(parenttype, parent) {
|
||||
await this.run(`delete from ${parenttype} where parent=?`, parent);
|
||||
}
|
||||
|
||||
async deleteSingleValues(name) {
|
||||
await frappe.db.run('delete from SingleValue where parent=?', name)
|
||||
}
|
||||
|
||||
async rename(doctype, oldName, newName) {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let baseDoctype = meta.getBaseDocType();
|
||||
await frappe.db.run(`update ${baseDoctype} set name = ? where name = ?`, [newName, oldName]);
|
||||
await frappe.db.commit();
|
||||
}
|
||||
|
||||
async setValues(doctype, name, fieldValuePair) {
|
||||
const meta = frappe.getMeta(doctype);
|
||||
const baseDoctype = meta.getBaseDocType();
|
||||
const validFields = this.getKeys(doctype);
|
||||
const validFieldnames = validFields.map(df => df.fieldname);
|
||||
const fieldsToUpdate = Object.keys(fieldValuePair)
|
||||
.filter(fieldname => validFieldnames.includes(fieldname))
|
||||
|
||||
// assignment part of query
|
||||
const assigns = fieldsToUpdate.map(fieldname => `${fieldname} = ?`);
|
||||
|
||||
// values
|
||||
const values = fieldsToUpdate.map(fieldname => {
|
||||
const field = meta.getField(fieldname);
|
||||
const value = fieldValuePair[fieldname];
|
||||
return this.getFormattedValue(field, value);
|
||||
});
|
||||
|
||||
// additional name for where clause
|
||||
values.push(name);
|
||||
|
||||
return await this.run(`update ${baseDoctype}
|
||||
set ${assigns.join(', ')} where name=?`, values);
|
||||
}
|
||||
|
||||
getAll({ doctype, fields, filters, start, limit, orderBy = 'modified', groupBy, order = 'desc' } = {}) {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let baseDoctype = meta.getBaseDocType();
|
||||
if (!fields) {
|
||||
fields = meta.getKeywordFields();
|
||||
}
|
||||
if (typeof fields === 'string') {
|
||||
fields = [fields];
|
||||
}
|
||||
if (meta.filters) {
|
||||
filters = Object.assign({}, filters, meta.filters);
|
||||
}
|
||||
|
||||
let conditions = this.getFilterConditions(filters);
|
||||
let query = `select ${fields.join(", ")}
|
||||
from ${baseDoctype}
|
||||
${conditions.conditions ? "where" : ""} ${conditions.conditions}
|
||||
${groupBy ? ("group by " + groupBy.join(', ')) : ""}
|
||||
${orderBy ? ("order by " + orderBy) : ""} ${orderBy ? (order || "asc") : ""}
|
||||
${limit ? ("limit " + limit) : ""} ${start ? ("offset " + start) : ""}`;
|
||||
|
||||
return this.sql(query, conditions.values);
|
||||
}
|
||||
|
||||
run(query, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.conn.run(query, params, (err) => {
|
||||
if (err) {
|
||||
console.error('Error in sql:', query);
|
||||
let Error = this.getError(err);
|
||||
reject(new Error());
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
sql(query, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.conn.all(query, params, (err, rows) => {
|
||||
if (err) {
|
||||
console.error('Error in sql:', query);
|
||||
reject(err)
|
||||
}
|
||||
resolve(rows);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async commit() {
|
||||
try {
|
||||
await this.run('commit');
|
||||
} catch (e) {
|
||||
if (e.name !== 'CannotCommitError') {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return (await this.sql(`PRAGMA foreign_key_list(${doctype})`)).map(
|
||||
d => d.from
|
||||
);
|
||||
}
|
||||
|
||||
initTypeMap() {
|
||||
// prettier-ignore
|
||||
this.typeMap = {
|
||||
'AutoComplete': 'text'
|
||||
, 'Currency': 'real'
|
||||
, 'Int': 'integer'
|
||||
, 'Float': 'real'
|
||||
, 'Percent': 'real'
|
||||
, 'Check': 'integer'
|
||||
, 'Small Text': 'text'
|
||||
, 'Long Text': 'text'
|
||||
, 'Code': 'text'
|
||||
, 'Text Editor': 'text'
|
||||
, 'Date': 'text'
|
||||
, 'Datetime': 'text'
|
||||
, 'Time': 'text'
|
||||
, 'Text': 'text'
|
||||
, 'Data': 'text'
|
||||
, 'Link': 'text'
|
||||
, 'DynamicLink': 'text'
|
||||
, 'Password': 'text'
|
||||
, 'Select': 'text'
|
||||
, 'Read Only': 'text'
|
||||
, 'File': 'text'
|
||||
, 'Attach': 'text'
|
||||
, 'AttachImage': 'text'
|
||||
, 'Signature': 'text'
|
||||
, 'Color': 'text'
|
||||
, 'Barcode': 'text'
|
||||
, 'Geolocation': 'text'
|
||||
}
|
||||
'AutoComplete': 'text',
|
||||
'Currency': 'float',
|
||||
'Int': 'integer',
|
||||
'Float': 'float',
|
||||
'Percent': 'float',
|
||||
'Check': 'integer',
|
||||
'Small Text': 'text',
|
||||
'Long Text': 'text',
|
||||
'Code': 'text',
|
||||
'Text Editor': 'text',
|
||||
'Date': 'text',
|
||||
'Datetime': 'text',
|
||||
'Time': 'text',
|
||||
'Text': 'text',
|
||||
'Data': 'text',
|
||||
'Link': 'text',
|
||||
'DynamicLink': 'text',
|
||||
'Password': 'text',
|
||||
'Select': 'text',
|
||||
'Read Only': 'text',
|
||||
'File': 'text',
|
||||
'Attach': 'text',
|
||||
'AttachImage': 'text',
|
||||
'Signature': 'text',
|
||||
'Color': 'text',
|
||||
'Barcode': 'text',
|
||||
'Geolocation': 'text'
|
||||
};
|
||||
}
|
||||
|
||||
getError(err) {
|
||||
@ -296,18 +94,13 @@ class SqliteDatabase extends Database {
|
||||
return frappe.errors.LinkValidationError;
|
||||
}
|
||||
if (err.message.includes('SQLITE_ERROR: cannot commit')) {
|
||||
return SqliteDatabase.CannotCommitError;
|
||||
return frappe.errors.CannotCommitError;
|
||||
}
|
||||
return {
|
||||
19: frappe.errors.DuplicateEntryError
|
||||
}[err.errno] || Error;
|
||||
}
|
||||
}
|
||||
|
||||
SqliteDatabase.CannotCommitError = class CannotCommitError extends errors.DatabaseError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'CannotCommitError';
|
||||
return (
|
||||
{
|
||||
19: frappe.errors.DuplicateEntryError
|
||||
}[err.errno] || Error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,13 @@ class DatabaseError extends BaseError {
|
||||
}
|
||||
}
|
||||
|
||||
class CannotCommitError extends DatabaseError {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'CannotCommitError';
|
||||
}
|
||||
}
|
||||
|
||||
class ValueError extends ValidationError {}
|
||||
class Conflict extends ValidationError {}
|
||||
|
||||
@ -86,6 +93,7 @@ module.exports = {
|
||||
DuplicateEntryError,
|
||||
LinkValidationError,
|
||||
DatabaseError,
|
||||
CannotCommitError,
|
||||
MandatoryError,
|
||||
throw: throwError
|
||||
};
|
||||
|
@ -231,7 +231,7 @@ module.exports = class BaseDocument extends Observable {
|
||||
|
||||
async load() {
|
||||
let data = await frappe.db.get(this.doctype, this.name);
|
||||
if (data.name) {
|
||||
if (data && data.name) {
|
||||
this.syncValues(data);
|
||||
if (this.meta.isSingle) {
|
||||
this.setDefaults();
|
||||
|
@ -42,8 +42,13 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
].concat(this.fields);
|
||||
}
|
||||
|
||||
// attach default precision to Float and Currency
|
||||
this.fields = this.fields.map(df => {
|
||||
// name field is always required
|
||||
if (df.fieldname === 'name') {
|
||||
df.required = 1;
|
||||
}
|
||||
|
||||
// attach default precision to Float and Currency
|
||||
if (['Float', 'Currency'].includes(df.fieldtype)) {
|
||||
let defaultPrecision = frappe.SystemSettings ? frappe.SystemSettings.floatPrecision : 2;
|
||||
df.precision = df.precision || defaultPrecision;
|
||||
|
@ -7,7 +7,7 @@
|
||||
"frappe": "cli.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "NODE_ENV=test mocha --timeout 3000 tests",
|
||||
"test": "NODE_ENV=test mocha --timeout 3000 tests --exit",
|
||||
"test-watch": "NODE_ENV=test mocha --timeout 3000 tests --watch --reporter=min",
|
||||
"start": "nodemon app.js"
|
||||
},
|
||||
@ -33,6 +33,7 @@
|
||||
"file-loader": "^1.1.11",
|
||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"knex": "^0.20.3",
|
||||
"luxon": "^1.0.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"morgan": "^1.9.0",
|
||||
@ -44,7 +45,7 @@
|
||||
"sass-loader": "^7.0.3",
|
||||
"showdown": "^1.8.6",
|
||||
"socket.io": "^2.0.4",
|
||||
"sqlite3": "^4.0.9",
|
||||
"sqlite3": "^4.1.1",
|
||||
"tailwindcss": "1.1.1",
|
||||
"vue": "^2.6.10",
|
||||
"vue-flatpickr-component": "^8.1.2",
|
||||
|
@ -14,7 +14,6 @@ const common = require('frappejs/common');
|
||||
const bodyParser = require('body-parser');
|
||||
const fs = require('fs');
|
||||
const { setupExpressRoute: setRouteForPDF } = require('frappejs/server/pdf');
|
||||
const auth = require('./../auth/auth')();
|
||||
const morgan = require('morgan');
|
||||
const { addWebpackMiddleware } = require('../webpack/serve');
|
||||
const { getAppConfig, resolveAppDir } = require('../webpack/utils');
|
||||
@ -26,7 +25,7 @@ require.extensions['.html'] = function (module, filename) {
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
async start({backend, connectionParams, models, authConfig=null}) {
|
||||
async start({backend, connectionParams, models}) {
|
||||
await this.init();
|
||||
|
||||
if (models) {
|
||||
@ -49,10 +48,6 @@ module.exports = {
|
||||
app.use(cors());
|
||||
}
|
||||
|
||||
if(authConfig) {
|
||||
this.setupAuthentication(app, authConfig);
|
||||
}
|
||||
|
||||
// socketio
|
||||
io.on('connection', function (socket) {
|
||||
frappe.db.bindSocketServer(socket);
|
||||
@ -80,7 +75,7 @@ module.exports = {
|
||||
|
||||
async init() {
|
||||
frappe.isServer = true;
|
||||
await frappe.init();
|
||||
frappe.init();
|
||||
frappe.registerModels(frappeModels, 'server');
|
||||
frappe.registerLibs(common);
|
||||
|
||||
@ -92,11 +87,4 @@ module.exports = {
|
||||
await frappe.db.connect();
|
||||
await frappe.db.migrate();
|
||||
},
|
||||
|
||||
setupAuthentication(app, authConfig) {
|
||||
app.post("/api/signup", auth.signup);
|
||||
app.post("/api/login", auth.login);
|
||||
app.use(auth.initialize(authConfig));
|
||||
app.all("/api/resource/*", auth.authenticate());
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,5 @@ async function handlePDFRequest(req, res) {
|
||||
|
||||
module.exports = {
|
||||
makePDF,
|
||||
setupExpressRoute,
|
||||
getPDFForElectron
|
||||
setupExpressRoute
|
||||
};
|
||||
|
@ -1,15 +1,16 @@
|
||||
const server = require('frappejs/server');
|
||||
const frappe = require('frappejs');
|
||||
const server = require('frappejs/server');
|
||||
const SQLite = require('frappejs/backends/sqlite');
|
||||
|
||||
module.exports = {
|
||||
async initSqlite({dbPath = '_test.db', models} = {}) {
|
||||
server.init();
|
||||
if (models) {
|
||||
frappe.registerModels(models, 'server');
|
||||
}
|
||||
await server.initDb({
|
||||
backend: 'sqlite',
|
||||
connectionParams: {dbPath: dbPath},
|
||||
});
|
||||
async initSqlite({ dbPath = '_test.db', models } = {}) {
|
||||
server.init();
|
||||
if (models) {
|
||||
frappe.registerModels(models, 'server');
|
||||
}
|
||||
}
|
||||
|
||||
frappe.db = new SQLite({ dbPath });
|
||||
await frappe.db.connect();
|
||||
await frappe.db.migrate();
|
||||
}
|
||||
};
|
||||
|
@ -3,47 +3,90 @@ const frappe = require('frappejs');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
describe('Database', () => {
|
||||
before(async function() {
|
||||
await helpers.initSqlite();
|
||||
before(async function() {
|
||||
await helpers.initSqlite();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await frappe.db.sql('delete from todo');
|
||||
|
||||
await frappe.insert({
|
||||
doctype: 'ToDo',
|
||||
subject: 'testing 1',
|
||||
status: 'Open'
|
||||
});
|
||||
await frappe.insert({
|
||||
doctype: 'ToDo',
|
||||
subject: 'testing 3',
|
||||
status: 'Open'
|
||||
});
|
||||
await frappe.insert({
|
||||
doctype: 'ToDo',
|
||||
subject: 'testing 2',
|
||||
status: 'Closed'
|
||||
});
|
||||
});
|
||||
|
||||
it('should insert and get values', async () => {
|
||||
let subjects = await frappe.db.getAll({
|
||||
doctype: 'ToDo',
|
||||
fields: ['name', 'subject']
|
||||
});
|
||||
subjects = subjects.map(d => d.subject);
|
||||
|
||||
assert.ok(subjects.includes('testing 1'));
|
||||
assert.ok(subjects.includes('testing 2'));
|
||||
assert.ok(subjects.includes('testing 3'));
|
||||
});
|
||||
|
||||
it('should filter correct values', async () => {
|
||||
let todos = await frappe.db.getAll({
|
||||
doctype: 'ToDo',
|
||||
fields: ['name', 'subject'],
|
||||
filters: { status: 'Open' }
|
||||
});
|
||||
let subjects = todos.map(d => d.subject);
|
||||
|
||||
assert.ok(subjects.includes('testing 1'));
|
||||
assert.ok(subjects.includes('testing 3'));
|
||||
assert.equal(subjects.includes('testing 2'), false);
|
||||
|
||||
todos = await frappe.db.getAll({
|
||||
doctype: 'ToDo',
|
||||
fields: ['name', 'subject'],
|
||||
filters: { status: 'Closed' }
|
||||
});
|
||||
subjects = todos.map(d => d.subject);
|
||||
|
||||
assert.equal(subjects.includes('testing 1'), false);
|
||||
assert.equal(subjects.includes('testing 3'), false);
|
||||
assert.ok(subjects.includes('testing 2'));
|
||||
});
|
||||
|
||||
it('should delete records', async () => {
|
||||
let todos = await frappe.db.getAll({ doctype: 'ToDo' });
|
||||
frappe.db.delete('ToDo', todos[0].name);
|
||||
|
||||
todos = await frappe.db.getAll({ doctype: 'ToDo' });
|
||||
assert.equal(todos.length, 2);
|
||||
});
|
||||
|
||||
it('should update records', async () => {
|
||||
let todo = (await frappe.db.getAll({ doctype: 'ToDo', limit: 1 }))[0];
|
||||
|
||||
frappe.db.update('ToDo', {
|
||||
name: todo.name,
|
||||
subject: 'updated subject'
|
||||
});
|
||||
|
||||
it('should insert and get values', async () => {
|
||||
await frappe.db.sql('delete from todo');
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 1'});
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 3'});
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 2'});
|
||||
todo = (
|
||||
await frappe.db.getAll({
|
||||
doctype: 'ToDo',
|
||||
fields: ['subject'],
|
||||
filters: { name: todo.name }
|
||||
})
|
||||
)[0];
|
||||
|
||||
let subjects = await frappe.db.getAll({doctype:'ToDo', fields:['name', 'subject']})
|
||||
subjects = subjects.map(d => d.subject);
|
||||
|
||||
assert.ok(subjects.includes('testing 1'));
|
||||
assert.ok(subjects.includes('testing 2'));
|
||||
assert.ok(subjects.includes('testing 3'));
|
||||
});
|
||||
|
||||
it('should filter correct values', async () => {
|
||||
let subjects = null;
|
||||
|
||||
await frappe.db.sql('delete from todo');
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 1', status: 'Open'});
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 3', status: 'Open'});
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 2', status: 'Closed'});
|
||||
|
||||
subjects = await frappe.db.getAll({doctype:'ToDo', fields:['name', 'subject'],
|
||||
filters:{status: 'Open'}});
|
||||
subjects = subjects.map(d => d.subject);
|
||||
|
||||
assert.ok(subjects.includes('testing 1'));
|
||||
assert.ok(subjects.includes('testing 3'));
|
||||
assert.equal(subjects.includes('testing 2'), false);
|
||||
|
||||
subjects = await frappe.db.getAll({doctype:'ToDo', fields:['name', 'subject'],
|
||||
filters:{status: 'Closed'}});
|
||||
subjects = subjects.map(d => d.subject);
|
||||
|
||||
assert.equal(subjects.includes('testing 1'), false);
|
||||
assert.equal(subjects.includes('testing 3'), false);
|
||||
assert.ok(subjects.includes('testing 2'));
|
||||
|
||||
});
|
||||
});
|
||||
assert.equal(todo.subject, 'updated subject');
|
||||
});
|
||||
});
|
||||
|
@ -167,9 +167,11 @@ function makeConfig() {
|
||||
}
|
||||
};
|
||||
|
||||
let modifiedConfig = appConfig.configureWebpack(config);
|
||||
if (modifiedConfig) {
|
||||
return modifiedConfig;
|
||||
if (appConfig.configureWebpack) {
|
||||
let modifiedConfig = appConfig.configureWebpack(config);
|
||||
if (modifiedConfig) {
|
||||
return modifiedConfig;
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
|
303
yarn.lock
303
yarn.lock
@ -442,6 +442,11 @@ arr-union@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
|
||||
integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
|
||||
|
||||
array-each@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f"
|
||||
integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8=
|
||||
|
||||
array-find-index@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
|
||||
@ -457,6 +462,11 @@ array-flatten@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
|
||||
integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
|
||||
|
||||
array-slice@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4"
|
||||
integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==
|
||||
|
||||
array-union@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
|
||||
@ -814,6 +824,11 @@ bluebird@^3.1.1, bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.5:
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
|
||||
integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
|
||||
|
||||
bluebird@^3.7.1:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
|
||||
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
|
||||
|
||||
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
|
||||
version "4.11.8"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
|
||||
@ -1419,6 +1434,11 @@ color-name@1.1.3:
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||
|
||||
colorette@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.1.0.tgz#1f943e5a357fac10b4e0f5aaef3b14cdc1af6ec7"
|
||||
integrity sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
@ -1441,6 +1461,11 @@ commander@^2.13.0, commander@^2.20.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
|
||||
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
|
||||
|
||||
commander@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-4.0.1.tgz#b67622721785993182e807f4883633e6401ba53c"
|
||||
integrity sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA==
|
||||
|
||||
commander@~2.19.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
|
||||
@ -1865,6 +1890,13 @@ debug@3.1.0, debug@~3.1.0:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4.1.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^3.0.0, debug@^3.1.0, debug@^3.2.5, debug@^3.2.6:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||
@ -1872,13 +1904,6 @@ debug@^3.0.0, debug@^3.1.0, debug@^3.2.5, debug@^3.2.6:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.1.0, debug@^4.1.1, debug@~4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
@ -1994,6 +2019,11 @@ destroy@~1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
||||
|
||||
detect-file@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
|
||||
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
|
||||
|
||||
detect-indent@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
|
||||
@ -2548,6 +2578,13 @@ expand-brackets@^2.1.4:
|
||||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
expand-tilde@^2.0.0, expand-tilde@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
|
||||
integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
|
||||
dependencies:
|
||||
homedir-polyfill "^1.0.1"
|
||||
|
||||
express@^4.16.2, express@^4.17.1:
|
||||
version "4.17.1"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
||||
@ -2599,7 +2636,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
|
||||
assign-symbols "^1.0.0"
|
||||
is-extendable "^1.0.1"
|
||||
|
||||
extend@~3.0.2:
|
||||
extend@^3.0.0, extend@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
@ -2758,6 +2795,32 @@ find-up@^3.0.0:
|
||||
dependencies:
|
||||
locate-path "^3.0.0"
|
||||
|
||||
findup-sync@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1"
|
||||
integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==
|
||||
dependencies:
|
||||
detect-file "^1.0.0"
|
||||
is-glob "^4.0.0"
|
||||
micromatch "^3.0.4"
|
||||
resolve-dir "^1.0.1"
|
||||
|
||||
fined@^1.0.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b"
|
||||
integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==
|
||||
dependencies:
|
||||
expand-tilde "^2.0.2"
|
||||
is-plain-object "^2.0.3"
|
||||
object.defaults "^1.1.0"
|
||||
object.pick "^1.2.0"
|
||||
parse-filepath "^1.0.1"
|
||||
|
||||
flagged-respawn@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41"
|
||||
integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==
|
||||
|
||||
flatpickr@^4.5.1:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/flatpickr/-/flatpickr-4.6.2.tgz#50e1b4fc84fbf67c5b0919ba3ddc330221f126da"
|
||||
@ -2949,6 +3012,11 @@ get-value@^2.0.3, get-value@^2.0.6:
|
||||
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
||||
integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
|
||||
|
||||
getopts@2.2.5:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b"
|
||||
integrity sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==
|
||||
|
||||
getpass@^0.1.1:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
||||
@ -2995,6 +3063,26 @@ global-dirs@^0.1.0:
|
||||
dependencies:
|
||||
ini "^1.3.4"
|
||||
|
||||
global-modules@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
|
||||
integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
|
||||
dependencies:
|
||||
global-prefix "^1.0.1"
|
||||
is-windows "^1.0.1"
|
||||
resolve-dir "^1.0.0"
|
||||
|
||||
global-prefix@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
|
||||
integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
|
||||
dependencies:
|
||||
expand-tilde "^2.0.2"
|
||||
homedir-polyfill "^1.0.1"
|
||||
ini "^1.3.4"
|
||||
is-windows "^1.0.1"
|
||||
which "^1.2.14"
|
||||
|
||||
globals@^9.18.0:
|
||||
version "9.18.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
||||
@ -3210,6 +3298,13 @@ home-or-tmp@^2.0.0:
|
||||
os-homedir "^1.0.0"
|
||||
os-tmpdir "^1.0.1"
|
||||
|
||||
homedir-polyfill@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
|
||||
integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
|
||||
dependencies:
|
||||
parse-passwd "^1.0.0"
|
||||
|
||||
hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047"
|
||||
@ -3466,7 +3561,7 @@ inflight@^1.0.4:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@ -3494,6 +3589,11 @@ internal-ip@^4.3.0:
|
||||
default-gateway "^4.2.0"
|
||||
ipaddr.js "^1.9.0"
|
||||
|
||||
interpret@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.0.0.tgz#b783ffac0b8371503e9ab39561df223286aa5433"
|
||||
integrity sha512-e0/LknJ8wpMMhTiWcjivB+ESwIuvHnBSlBbmP/pSb8CQJldoj1p2qv7xGZ/+BtbTziYRFSz8OsvdbiX45LtYQA==
|
||||
|
||||
invariant@^2.2.2:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||
@ -3531,6 +3631,14 @@ ipaddr.js@^1.9.0:
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
is-absolute@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576"
|
||||
integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==
|
||||
dependencies:
|
||||
is-relative "^1.0.0"
|
||||
is-windows "^1.0.1"
|
||||
|
||||
is-accessor-descriptor@^0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
|
||||
@ -3748,6 +3856,13 @@ is-regex@^1.0.4:
|
||||
dependencies:
|
||||
has "^1.0.1"
|
||||
|
||||
is-relative@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
|
||||
integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==
|
||||
dependencies:
|
||||
is-unc-path "^1.0.0"
|
||||
|
||||
is-retry-allowed@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
|
||||
@ -3770,12 +3885,19 @@ is-typedarray@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
||||
|
||||
is-unc-path@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d"
|
||||
integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==
|
||||
dependencies:
|
||||
unc-path-regex "^0.1.2"
|
||||
|
||||
is-utf8@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
|
||||
integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
|
||||
|
||||
is-windows@^1.0.0, is-windows@^1.0.2:
|
||||
is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
|
||||
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
|
||||
@ -3984,6 +4106,27 @@ kind-of@^6.0.0, kind-of@^6.0.2:
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
|
||||
integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
|
||||
|
||||
knex@^0.20.3:
|
||||
version "0.20.3"
|
||||
resolved "https://registry.yarnpkg.com/knex/-/knex-0.20.3.tgz#85178cd6873f75827be86d054c4e117bb4d9657b"
|
||||
integrity sha512-zzYO34pSCCYVqRTbCp8xL+Z7fvHQl5anif3Oacu6JaHFDubB7mFGWRRJBNSO3N8Ql4g4CxUgBctaPiliwoOsNA==
|
||||
dependencies:
|
||||
bluebird "^3.7.1"
|
||||
colorette "1.1.0"
|
||||
commander "^4.0.1"
|
||||
debug "4.1.1"
|
||||
getopts "2.2.5"
|
||||
inherits "~2.0.4"
|
||||
interpret "^2.0.0"
|
||||
liftoff "3.1.0"
|
||||
lodash "^4.17.15"
|
||||
mkdirp "^0.5.1"
|
||||
pg-connection-string "2.1.0"
|
||||
tarn "^2.0.0"
|
||||
tildify "2.0.0"
|
||||
uuid "^3.3.3"
|
||||
v8flags "^3.1.3"
|
||||
|
||||
latest-version@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
|
||||
@ -4017,6 +4160,20 @@ lcid@^2.0.0:
|
||||
dependencies:
|
||||
invert-kv "^2.0.0"
|
||||
|
||||
liftoff@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3"
|
||||
integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==
|
||||
dependencies:
|
||||
extend "^3.0.0"
|
||||
findup-sync "^3.0.0"
|
||||
fined "^1.0.1"
|
||||
flagged-respawn "^1.0.0"
|
||||
is-plain-object "^2.0.4"
|
||||
object.map "^1.0.0"
|
||||
rechoir "^0.6.2"
|
||||
resolve "^1.1.7"
|
||||
|
||||
load-json-file@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
|
||||
@ -4083,6 +4240,11 @@ lodash@^4.17.11, lodash@^4.17.3, lodash@^4.17.4:
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba"
|
||||
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==
|
||||
|
||||
lodash@^4.17.15:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
|
||||
loglevel@^1.6.3:
|
||||
version "1.6.3"
|
||||
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.3.tgz#77f2eb64be55a404c9fd04ad16d57c1d6d6b1280"
|
||||
@ -4153,6 +4315,13 @@ make-dir@^2.0.0:
|
||||
pify "^4.0.1"
|
||||
semver "^5.6.0"
|
||||
|
||||
make-iterator@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6"
|
||||
integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==
|
||||
dependencies:
|
||||
kind-of "^6.0.2"
|
||||
|
||||
mamacro@^0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4"
|
||||
@ -4165,7 +4334,7 @@ map-age-cleaner@^0.1.1:
|
||||
dependencies:
|
||||
p-defer "^1.0.0"
|
||||
|
||||
map-cache@^0.2.2:
|
||||
map-cache@^0.2.0, map-cache@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
|
||||
integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
|
||||
@ -4253,7 +4422,7 @@ methods@~1.1.2:
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
|
||||
|
||||
micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8:
|
||||
micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8:
|
||||
version "3.1.10"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
|
||||
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
|
||||
@ -4817,6 +4986,16 @@ object-visit@^1.0.0:
|
||||
dependencies:
|
||||
isobject "^3.0.0"
|
||||
|
||||
object.defaults@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf"
|
||||
integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=
|
||||
dependencies:
|
||||
array-each "^1.0.1"
|
||||
array-slice "^1.0.0"
|
||||
for-own "^1.0.0"
|
||||
isobject "^3.0.0"
|
||||
|
||||
object.getownpropertydescriptors@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
|
||||
@ -4825,7 +5004,15 @@ object.getownpropertydescriptors@^2.0.3:
|
||||
define-properties "^1.1.2"
|
||||
es-abstract "^1.5.1"
|
||||
|
||||
object.pick@^1.3.0:
|
||||
object.map@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37"
|
||||
integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=
|
||||
dependencies:
|
||||
for-own "^1.0.0"
|
||||
make-iterator "^1.0.0"
|
||||
|
||||
object.pick@^1.2.0, object.pick@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
|
||||
integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
|
||||
@ -5048,6 +5235,15 @@ parse-color@^1.0.0:
|
||||
dependencies:
|
||||
color-convert "~0.5.0"
|
||||
|
||||
parse-filepath@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891"
|
||||
integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=
|
||||
dependencies:
|
||||
is-absolute "^1.0.0"
|
||||
map-cache "^0.2.0"
|
||||
path-root "^0.1.1"
|
||||
|
||||
parse-json@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
|
||||
@ -5063,6 +5259,11 @@ parse-json@^4.0.0:
|
||||
error-ex "^1.3.1"
|
||||
json-parse-better-errors "^1.0.1"
|
||||
|
||||
parse-passwd@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
|
||||
integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
|
||||
|
||||
parseqs@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
|
||||
@ -5129,6 +5330,18 @@ path-parse@^1.0.6:
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
||||
|
||||
path-root-regex@^0.1.0:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d"
|
||||
integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=
|
||||
|
||||
path-root@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7"
|
||||
integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=
|
||||
dependencies:
|
||||
path-root-regex "^0.1.0"
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
@ -5171,6 +5384,11 @@ performance-now@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
|
||||
pg-connection-string@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.1.0.tgz#e07258f280476540b24818ebb5dca29e101ca502"
|
||||
integrity sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg==
|
||||
|
||||
pify@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||
@ -5651,6 +5869,13 @@ readdirp@^2.2.1:
|
||||
micromatch "^3.1.10"
|
||||
readable-stream "^2.0.2"
|
||||
|
||||
rechoir@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||
integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
|
||||
dependencies:
|
||||
resolve "^1.1.6"
|
||||
|
||||
redent@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
|
||||
@ -5819,6 +6044,14 @@ resolve-cwd@^2.0.0:
|
||||
dependencies:
|
||||
resolve-from "^3.0.0"
|
||||
|
||||
resolve-dir@^1.0.0, resolve-dir@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
|
||||
integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
|
||||
dependencies:
|
||||
expand-tilde "^2.0.0"
|
||||
global-modules "^1.0.0"
|
||||
|
||||
resolve-from@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
|
||||
@ -5829,6 +6062,13 @@ resolve-url@^0.2.1:
|
||||
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
|
||||
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
|
||||
|
||||
resolve@^1.1.6, resolve@^1.1.7:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16"
|
||||
integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
resolve@^1.10.0:
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e"
|
||||
@ -6310,10 +6550,10 @@ sprintf-js@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
||||
|
||||
sqlite3@^4.0.9:
|
||||
version "4.0.9"
|
||||
resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-4.0.9.tgz#cff74550fa5a1159956815400bdef69245557640"
|
||||
integrity sha512-IkvzjmsWQl9BuBiM4xKpl5X8WCR4w0AeJHRdobCdXZ8dT/lNc1XS6WqvY35N6+YzIIgzSBeY5prdFObID9F9tA==
|
||||
sqlite3@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-4.1.1.tgz#539a42e476640796578e22d589b3283c28055242"
|
||||
integrity sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==
|
||||
dependencies:
|
||||
nan "^2.12.1"
|
||||
node-pre-gyp "^0.11.0"
|
||||
@ -6569,6 +6809,11 @@ tar@^4:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.3"
|
||||
|
||||
tarn@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tarn/-/tarn-2.0.0.tgz#c68499f69881f99ae955b4317ca7d212d942fdee"
|
||||
integrity sha512-7rNMCZd3s9bhQh47ksAQd92ADFcJUjjbyOvyFjNLwTPpGieFHMC84S+LOzw0fx1uh6hnDz/19r8CPMnIjJlMMA==
|
||||
|
||||
temp-file@^3.3.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.3.4.tgz#73af868cd7cb7400a44e4bb03e653b2280ce2878"
|
||||
@ -6635,6 +6880,11 @@ thunky@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.3.tgz#f5df732453407b09191dae73e2a8cc73f381a826"
|
||||
integrity sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==
|
||||
|
||||
tildify@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tildify/-/tildify-2.0.0.tgz#f205f3674d677ce698b7067a99e949ce03b4754a"
|
||||
integrity sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==
|
||||
|
||||
timed-out@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
|
||||
@ -6782,6 +7032,11 @@ uglify-js@3.4.x:
|
||||
commander "~2.19.0"
|
||||
source-map "~0.6.1"
|
||||
|
||||
unc-path-regex@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
|
||||
integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
|
||||
|
||||
undefsafe@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76"
|
||||
@ -6986,6 +7241,18 @@ uuid@^3.0.1, uuid@^3.3.2:
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
|
||||
|
||||
uuid@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
|
||||
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
|
||||
|
||||
v8flags@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8"
|
||||
integrity sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==
|
||||
dependencies:
|
||||
homedir-polyfill "^1.0.1"
|
||||
|
||||
validate-npm-package-license@^3.0.1:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
|
||||
@ -7204,7 +7471,7 @@ which-module@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
||||
|
||||
which@^1.2.9:
|
||||
which@^1.2.14, which@^1.2.9:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
|
||||
|
Loading…
Reference in New Issue
Block a user