mirror of
https://github.com/frappe/books.git
synced 2025-01-22 22:58:28 +00:00
added database baseclass and moving to camelCase
This commit is contained in:
parent
b9424c43e9
commit
ed4dbb496c
19
.eslintrc
19
.eslintrc
@ -4,8 +4,27 @@
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017,
|
||||
"sourceType": "module"
|
||||
},
|
||||
|
||||
"globals": {
|
||||
"document": false,
|
||||
"escape": false,
|
||||
"navigator": false,
|
||||
"unescape": false,
|
||||
"window": false,
|
||||
"describe": true,
|
||||
"before": true,
|
||||
"it": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"no-unused-vars": [2, { "vars": "all", "args": "none" }],
|
||||
"no-trailing-spaces": 2,
|
||||
"no-undef": 2,
|
||||
"no-undef-init": 2
|
||||
}
|
||||
}
|
2
app.js
2
app.js
@ -2,5 +2,5 @@ const server = require('frappejs/server');
|
||||
|
||||
server.start({
|
||||
backend: 'sqllite',
|
||||
connection_params: {db_path: 'test.db'}
|
||||
connection_params: {dbPath: 'test.db'}
|
||||
});
|
303
backends/database.js
Normal file
303
backends/database.js
Normal file
@ -0,0 +1,303 @@
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class Database {
|
||||
constructor() {
|
||||
this.initTypeMap();
|
||||
}
|
||||
|
||||
async connect() {
|
||||
// this.conn
|
||||
}
|
||||
|
||||
close() {
|
||||
this.conn.close();
|
||||
}
|
||||
|
||||
async migrate() {
|
||||
for (let doctype in frappe.modules) {
|
||||
// check if controller module
|
||||
if (frappe.modules[doctype].Meta) {
|
||||
if (await this.tableExists(doctype)) {
|
||||
await this.alterTable(doctype);
|
||||
} else {
|
||||
await this.createTable(doctype);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
await this.commit();
|
||||
}
|
||||
|
||||
async createTable(doctype) {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let columns = [];
|
||||
let values = [];
|
||||
|
||||
for (let df of meta.getValidFields({ with_children: false })) {
|
||||
if (this.type_map[df.fieldtype]) {
|
||||
columns.push(this.getColumnDefinition(df));
|
||||
}
|
||||
}
|
||||
|
||||
return await this.runCreateTableQuery(doctype, columns, values);
|
||||
}
|
||||
|
||||
async tableExists(table) {
|
||||
// return true if table exists
|
||||
}
|
||||
|
||||
async runCreateTableQuery(doctype, columns, values) {
|
||||
// override
|
||||
}
|
||||
|
||||
getColumnDefinition(df) {
|
||||
return `${df.fieldname} ${this.type_map[df.fieldtype]} ${df.reqd && !df.default ? "not null" : ""} ${df.default ? `default ${df.default}` : ""}`
|
||||
}
|
||||
|
||||
async alterTable(doctype) {
|
||||
// get columns
|
||||
let tableColumns = await this.getTableColumns(doctype);
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let values = [];
|
||||
|
||||
for (let field of meta.getValidFields({ with_children: false })) {
|
||||
if (!tableColumns.includes(field.fieldname) && this.type_map[field.fieldtype]) {
|
||||
values = []
|
||||
if (field.default) {
|
||||
values.push(field.default);
|
||||
}
|
||||
await this.runAlterTableQuery(doctype, field, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getTableColumns(doctype) {
|
||||
return [];
|
||||
}
|
||||
|
||||
async runAlterTableQuery(doctype, field, values) {
|
||||
// alter table {doctype} add column ({column_def});
|
||||
}
|
||||
|
||||
async get(doctype, name, fields = '*') {
|
||||
// load parent
|
||||
let doc = await this.getOne(doctype, name, fields);
|
||||
|
||||
// load children
|
||||
let tableFields = frappe.getMeta(doctype).getTableFields();
|
||||
for (let field of tableFields) {
|
||||
doc[field.fieldname] = await this.getAll({
|
||||
doctype: field.childtype,
|
||||
fields: ["*"],
|
||||
filters: { parent: doc.name },
|
||||
order_by: 'idx',
|
||||
order: 'asc'
|
||||
});
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
async getOne(doctype, name, fields = '*') {
|
||||
// select {fields} form {doctype} where name = ?
|
||||
}
|
||||
|
||||
prepareFields(fields) {
|
||||
if (fields instanceof Array) {
|
||||
fields = fields.join(", ");
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
async insert(doctype, doc) {
|
||||
// insert parent
|
||||
await this.insertOne(doctype, doc);
|
||||
|
||||
// insert children
|
||||
let tableFields = frappe.getMeta(doctype).getTableFields();
|
||||
for (let field of tableFields) {
|
||||
let idx = 0;
|
||||
for (let child of (doc[field.fieldname] || [])) {
|
||||
this.prepareChild(doctype, doc.name, child, field, idx);
|
||||
await this.insertOne(field.childtype, child);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
async insertOne(doctype, doc) {
|
||||
// insert into {doctype} ({fields}) values ({values})
|
||||
}
|
||||
|
||||
async update(doctype, doc) {
|
||||
// update parent
|
||||
await this.updateOne(doctype, doc);
|
||||
|
||||
// insert or update children
|
||||
let tableFields = frappe.getMeta(doctype).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);
|
||||
if (await this.exists(field.childtype, child.name)) {
|
||||
await this.updateOne(field.childtype, child);
|
||||
} else {
|
||||
await this.insertOne(field.childtype, child);
|
||||
}
|
||||
added.push(child.name);
|
||||
}
|
||||
|
||||
await this.runDeleteOtherChildren(field, added);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
async updateOne(doctype, doc) {
|
||||
// update {doctype} set {field=value} where name=?
|
||||
}
|
||||
|
||||
async runDeleteOtherChildren(field, added) {
|
||||
// delete from doctype where parent = ? and name not in (?, ?, ?)
|
||||
}
|
||||
|
||||
prepareChild(parenttype, parent, child, field, idx) {
|
||||
if (!child.name) {
|
||||
child.name = frappe.getRandomName();
|
||||
}
|
||||
child.parent = parent;
|
||||
child.parenttype = parenttype;
|
||||
child.parentfield = field.fieldname;
|
||||
child.idx = idx;
|
||||
}
|
||||
|
||||
getKeys(doctype) {
|
||||
return frappe.getMeta(doctype).getValidFields({ with_children: false });
|
||||
}
|
||||
|
||||
getFormattedValues(fields, doc) {
|
||||
let values = fields.map(field => {
|
||||
let value = doc[field.fieldname];
|
||||
if (value instanceof Date) {
|
||||
return value.toISOString();
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
async delete(doctype, name) {
|
||||
await this.deleteOne(doctype, name);
|
||||
|
||||
// delete children
|
||||
let tableFields = frappe.getMeta(doctype).getTableFields();
|
||||
for (let field of tableFields) {
|
||||
await this.deleteChildren(frappe.slug(field.childtype), name);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteOne(doctype, name) {
|
||||
// delete from {doctype} where name = ?
|
||||
}
|
||||
|
||||
async deleteChildren(parenttype, parent) {
|
||||
// delete from {parenttype} where parent = ?
|
||||
}
|
||||
|
||||
async exists(doctype, name) {
|
||||
return (await this.get_value(doctype, name)) ? true : false;
|
||||
}
|
||||
|
||||
async get_value(doctype, filters, fieldname = 'name') {
|
||||
if (typeof filters === 'string') {
|
||||
filters = { name: filters };
|
||||
}
|
||||
|
||||
let row = await this.getAll({
|
||||
doctype: doctype,
|
||||
fields: [fieldname],
|
||||
filters: filters,
|
||||
start: 0,
|
||||
limit: 1,
|
||||
order_by: 'name',
|
||||
order: 'asc'
|
||||
});
|
||||
return row.length ? row[0][fieldname] : null;
|
||||
}
|
||||
|
||||
getAll({ doctype, fields, filters, start, limit, order_by = 'modified', order = 'desc' } = {}) {
|
||||
// select {fields} from {doctype} where {filters} order by {order_by} {order} limit {start} {limit}
|
||||
}
|
||||
|
||||
getFilterConditions(filters) {
|
||||
// {"status": "Open"} => `status = "Open"`
|
||||
// {"status": "Open", "name": ["like", "apple%"]}
|
||||
// => `status="Open" and name like "apple%"
|
||||
let conditions = [];
|
||||
let values = [];
|
||||
for (let key in filters) {
|
||||
const value = filters[key];
|
||||
if (value instanceof Array) {
|
||||
// if its like, we should add the wildcard "%" if the user has not added
|
||||
if (value[0].toLowerCase() === 'like' && !value[1].includes('%')) {
|
||||
value[1] = `%${value[1]}%`;
|
||||
}
|
||||
conditions.push(`${key} ${value[0]} ?`);
|
||||
values.push(value[1]);
|
||||
} else {
|
||||
conditions.push(`${key} = ?`);
|
||||
values.push(value);
|
||||
}
|
||||
}
|
||||
return {
|
||||
conditions: conditions.length ? conditions.join(" and ") : "",
|
||||
values: values
|
||||
};
|
||||
}
|
||||
|
||||
async run(query, params) {
|
||||
// run query
|
||||
}
|
||||
|
||||
async sql(query, params) {
|
||||
// run sql
|
||||
}
|
||||
|
||||
async commit() {
|
||||
// commit
|
||||
}
|
||||
|
||||
initTypeMap() {
|
||||
this.type_map = {
|
||||
'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'
|
||||
, 'Dynamic Link': 'text'
|
||||
, 'Password': 'text'
|
||||
, 'Select': 'text'
|
||||
, 'Read Only': 'text'
|
||||
, 'Attach': 'text'
|
||||
, 'Attach Image': 'text'
|
||||
, 'Signature': 'text'
|
||||
, 'Color': 'text'
|
||||
, 'Barcode': 'text'
|
||||
, 'Geolocation': 'text'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -6,7 +6,7 @@ module.exports = class RESTClient {
|
||||
this.server = server;
|
||||
this.protocol = protocol;
|
||||
|
||||
this.init_type_map();
|
||||
this.initTypeMap();
|
||||
|
||||
this.json_headers = {
|
||||
'Accept': 'application/json',
|
||||
@ -39,7 +39,7 @@ module.exports = class RESTClient {
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async get_all({doctype, fields, filters, start, limit, sort_by, order}) {
|
||||
async getAll({doctype, fields, filters, start, limit, sort_by, order}) {
|
||||
let url = this.protocol + '://' + path.join(this.server, `/api/resource/${frappe.slug(doctype)}`);
|
||||
|
||||
url = url + "?" + this.get_query_string({
|
||||
@ -98,7 +98,7 @@ module.exports = class RESTClient {
|
||||
return (await response.json()).value;
|
||||
}
|
||||
|
||||
init_type_map() {
|
||||
initTypeMap() {
|
||||
this.type_map = {
|
||||
'Currency': true
|
||||
,'Int': true
|
||||
|
@ -1,19 +1,20 @@
|
||||
const frappe = require('frappejs');
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
const Database = require('./database');
|
||||
const debug = false;
|
||||
|
||||
class sqliteDatabase {
|
||||
constructor({ db_path }) {
|
||||
this.db_path = db_path;
|
||||
this.init_type_map();
|
||||
module.exports = class sqliteDatabase extends Database {
|
||||
constructor({ dbPath }) {
|
||||
super();
|
||||
this.dbPath = dbPath;
|
||||
}
|
||||
|
||||
connect(db_path) {
|
||||
if (db_path) {
|
||||
this.db_path = db_path;
|
||||
connect(dbPath) {
|
||||
if (dbPath) {
|
||||
this.dbPath = dbPath;
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
this.conn = new sqlite3.Database(this.db_path, () => {
|
||||
this.conn = new sqlite3.Database(this.dbPath, () => {
|
||||
if (debug) {
|
||||
this.conn.on('trace', (trace) => console.log(trace));
|
||||
}
|
||||
@ -22,86 +23,32 @@ class sqliteDatabase {
|
||||
});
|
||||
}
|
||||
|
||||
async migrate() {
|
||||
for (let doctype in frappe.modules) {
|
||||
// check if controller module
|
||||
if (frappe.modules[doctype].Meta) {
|
||||
if (await this.table_exists(doctype)) {
|
||||
await this.alter_table(doctype);
|
||||
} else {
|
||||
await this.create_table(doctype);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
await this.commit();
|
||||
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;
|
||||
}
|
||||
|
||||
async create_table(doctype) {
|
||||
let meta = frappe.get_meta(doctype);
|
||||
let columns = [];
|
||||
let values = [];
|
||||
|
||||
for (let df of meta.get_valid_fields({ with_children: false })) {
|
||||
if (this.type_map[df.fieldtype]) {
|
||||
columns.push(this.get_column_definition(df));
|
||||
}
|
||||
}
|
||||
|
||||
async runCreateTableQuery(doctype, columns, values) {
|
||||
const query = `CREATE TABLE IF NOT EXISTS ${frappe.slug(doctype)} (
|
||||
${columns.join(", ")})`;
|
||||
|
||||
return await this.run(query, values);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.conn.close();
|
||||
}
|
||||
|
||||
get_column_definition(df) {
|
||||
getColumnDefinition(df) {
|
||||
return `${df.fieldname} ${this.type_map[df.fieldtype]} ${df.reqd && !df.default ? "not null" : ""} ${df.default ? `default ${df.default}` : ""}`
|
||||
}
|
||||
|
||||
async alter_table(doctype) {
|
||||
// get columns
|
||||
let table_columns = (await this.sql(`PRAGMA table_info(${doctype})`)).map(d => d.name);
|
||||
let meta = frappe.get_meta(doctype);
|
||||
let values = [];
|
||||
|
||||
for (let df of meta.get_valid_fields({ with_children: false })) {
|
||||
if (!table_columns.includes(df.fieldname) && this.type_map[df.fieldtype]) {
|
||||
values = []
|
||||
if (df.default) {
|
||||
values.push(df.default);
|
||||
}
|
||||
await this.run(`ALTER TABLE ${frappe.slug(doctype)} ADD COLUMN ${this.get_column_definition(df)}`, values);
|
||||
}
|
||||
}
|
||||
async getTableColumns(doctype) {
|
||||
return (await this.sql(`PRAGMA table_info(${doctype})`)).map(d => d.name);
|
||||
}
|
||||
|
||||
async get(doctype, name, fields = '*') {
|
||||
// load parent
|
||||
let doc = await this.get_one(doctype, name, fields);
|
||||
|
||||
// load children
|
||||
let table_fields = frappe.get_meta(doctype).get_table_fields();
|
||||
for (let field of table_fields) {
|
||||
doc[field.fieldname] = await this.get_all({
|
||||
doctype: field.childtype,
|
||||
fields: ["*"],
|
||||
filters: { parent: doc.name },
|
||||
order_by: 'idx',
|
||||
order: 'asc'
|
||||
});
|
||||
}
|
||||
return doc;
|
||||
async runAlterTableQuery(doctype, field, values) {
|
||||
await this.run(`ALTER TABLE ${frappe.slug(doctype)} ADD COLUMN ${this.getColumnDefinition(field)}`, values);
|
||||
}
|
||||
|
||||
get_one(doctype, name, fields = '*') {
|
||||
if (fields instanceof Array) {
|
||||
fields = fields.join(", ");
|
||||
}
|
||||
|
||||
getOne(doctype, name, fields = '*') {
|
||||
fields = this.prepareFields(fields);
|
||||
return new Promise((resolve, reject) => {
|
||||
this.conn.get(`select ${fields} from ${frappe.slug(doctype)}
|
||||
where name = ?`, name,
|
||||
@ -111,72 +58,23 @@ class sqliteDatabase {
|
||||
});
|
||||
}
|
||||
|
||||
async insert(doctype, doc) {
|
||||
// insert parent
|
||||
await this.insert_one(doctype, doc);
|
||||
|
||||
// insert children
|
||||
let table_fields = frappe.get_meta(doctype).get_table_fields();
|
||||
for (let field of table_fields) {
|
||||
let idx = 0;
|
||||
for (let child of (doc[field.fieldname] || [])) {
|
||||
this.prepare_child(doctype, doc.name, child, field, idx);
|
||||
await this.insert_one(field.childtype, child);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
async insert_one(doctype, doc) {
|
||||
let fields = this.get_keys(doctype);
|
||||
async insertOne(doctype, doc) {
|
||||
let fields = this.getKeys(doctype);
|
||||
let placeholders = fields.map(d => '?').join(', ');
|
||||
|
||||
if (!doc.name) {
|
||||
doc.name = frappe.get_random_name();
|
||||
doc.name = frappe.getRandomName();
|
||||
}
|
||||
|
||||
return await this.run(`insert into ${frappe.slug(doctype)}
|
||||
(${fields.map(field => field.fieldname).join(", ")})
|
||||
values (${placeholders})`, this.get_formatted_values(fields, doc));
|
||||
values (${placeholders})`, this.getFormattedValues(fields, doc));
|
||||
}
|
||||
|
||||
async update(doctype, doc) {
|
||||
// update parent
|
||||
await this.update_one(doctype, doc);
|
||||
|
||||
// insert or update children
|
||||
let table_fields = frappe.get_meta(doctype).get_table_fields();
|
||||
for (let field of table_fields) {
|
||||
|
||||
// first key is "parent" - for SQL params
|
||||
let added_children = [doc.name];
|
||||
for (let child of (doc[field.fieldname] || [])) {
|
||||
this.prepare_child(doctype, doc.name, child, field, added_children.length - 1);
|
||||
if (await this.exists(field.childtype, child.name)) {
|
||||
await this.update_one(field.childtype, child);
|
||||
} else {
|
||||
await this.insert_one(field.childtype, child);
|
||||
}
|
||||
added_children.push(child.name);
|
||||
}
|
||||
|
||||
// delete other children
|
||||
// `delete from doctype where parent = ? and name not in (?, ?, ?)}`
|
||||
|
||||
await this.run(`delete from ${frappe.slug(field.childtype)}
|
||||
where
|
||||
parent = ? and
|
||||
name not in (${added_children.slice(1).map(d => '?').join(', ')})`, added_children);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
async update_one(doctype, doc) {
|
||||
let fields = this.get_keys(doctype);
|
||||
async updateOne(doctype, doc) {
|
||||
let fields = this.getKeys(doctype);
|
||||
let assigns = fields.map(field => `${field.fieldname} = ?`);
|
||||
let values = this.get_formatted_values(fields, doc);
|
||||
let values = this.getFormattedValues(fields, doc);
|
||||
|
||||
// additional name for where clause
|
||||
values.push(doc.name);
|
||||
@ -185,69 +83,29 @@ class sqliteDatabase {
|
||||
set ${assigns.join(", ")} where name=?`, values);
|
||||
}
|
||||
|
||||
prepare_child(parenttype, parent, child, field, idx) {
|
||||
if (!child.name) {
|
||||
child.name = frappe.get_random_name();
|
||||
}
|
||||
child.parent = parent;
|
||||
child.parenttype = parenttype;
|
||||
child.parentfield = field.fieldname;
|
||||
child.idx = idx;
|
||||
async runDeleteOtherChildren(field, added) {
|
||||
// delete other children
|
||||
// `delete from doctype where parent = ? and name not in (?, ?, ?)}`
|
||||
await this.run(`delete from ${frappe.slug(field.childtype)}
|
||||
where
|
||||
parent = ? and
|
||||
name not in (${added.slice(1).map(d => '?').join(', ')})`, added);
|
||||
}
|
||||
|
||||
get_keys(doctype) {
|
||||
return frappe.get_meta(doctype).get_valid_fields({ with_children: false });
|
||||
async deleteOne(doctype, name) {
|
||||
return await this.run(`delete from ${frappe.slug(doctype)} where name=?`, name);
|
||||
}
|
||||
|
||||
get_formatted_values(fields, doc) {
|
||||
let values = fields.map(field => {
|
||||
let value = doc[field.fieldname];
|
||||
if (value instanceof Date) {
|
||||
return value.toISOString();
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
return values;
|
||||
async deleteChildren(parenttype, parent) {
|
||||
await this.run(`delete from ${parent} where parent=?`, parent);
|
||||
}
|
||||
|
||||
async delete(doctype, name) {
|
||||
await this.run(`delete from ${frappe.slug(doctype)} where name=?`, name);
|
||||
|
||||
// delete children
|
||||
let table_fields = frappe.get_meta(doctype).get_table_fields();
|
||||
for (let field of table_fields) {
|
||||
await this.run(`delete from ${frappe.slug(field.childtype)} where parent=?`, name)
|
||||
}
|
||||
}
|
||||
|
||||
async exists(doctype, name) {
|
||||
return (await this.get_value(doctype, name)) ? true : false;
|
||||
}
|
||||
|
||||
async get_value(doctype, filters, fieldname = 'name') {
|
||||
if (typeof filters === 'string') {
|
||||
filters = { name: filters };
|
||||
}
|
||||
|
||||
let row = await this.get_all({
|
||||
doctype: doctype,
|
||||
fields: [fieldname],
|
||||
filters: filters,
|
||||
start: 0,
|
||||
limit: 1,
|
||||
order_by: 'name',
|
||||
order: 'asc'
|
||||
});
|
||||
return row.length ? row[0][fieldname] : null;
|
||||
}
|
||||
|
||||
get_all({ doctype, fields, filters, start, limit, order_by = 'modified', order = 'desc' } = {}) {
|
||||
getAll({ doctype, fields, filters, start, limit, order_by = 'modified', order = 'desc' } = {}) {
|
||||
if (!fields) {
|
||||
fields = frappe.get_meta(doctype).get_keyword_fields();
|
||||
fields = frappe.getMeta(doctype).getKeywordFields();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let conditions = this.get_filter_conditions(filters);
|
||||
let conditions = this.getFilterConditions(filters);
|
||||
|
||||
this.conn.all(`select ${fields.join(", ")}
|
||||
from ${frappe.slug(doctype)}
|
||||
@ -264,34 +122,7 @@ class sqliteDatabase {
|
||||
});
|
||||
}
|
||||
|
||||
get_filter_conditions(filters) {
|
||||
// {"status": "Open"} => `status = "Open"`
|
||||
// {"status": "Open", "name": ["like", "apple%"]}
|
||||
// => `status="Open" and name like "apple%"
|
||||
let conditions = [];
|
||||
let values = [];
|
||||
for (let key in filters) {
|
||||
const value = filters[key];
|
||||
if (value instanceof Array) {
|
||||
// if its like, we should add the wildcard "%" if the user has not added
|
||||
if (value[0].toLowerCase() === 'like' && !value[1].includes('%')) {
|
||||
value[1] = `%${value[1]}%`;
|
||||
}
|
||||
conditions.push(`${key} ${value[0]} ?`);
|
||||
values.push(value[1]);
|
||||
} else {
|
||||
conditions.push(`${key} = ?`);
|
||||
values.push(value);
|
||||
}
|
||||
}
|
||||
return {
|
||||
conditions: conditions.length ? conditions.join(" and ") : "",
|
||||
values: values
|
||||
};
|
||||
}
|
||||
|
||||
run(query, params) {
|
||||
// TODO promisify
|
||||
return new Promise((resolve, reject) => {
|
||||
this.conn.run(query, params, (err) => {
|
||||
if (err) {
|
||||
@ -324,12 +155,7 @@ class sqliteDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
async table_exists(table) {
|
||||
const name = await this.sql(`SELECT name FROM sqlite_master WHERE type='table' AND name='${table}'`);
|
||||
return (name && name.length) ? true : false;
|
||||
}
|
||||
|
||||
init_type_map() {
|
||||
initTypeMap() {
|
||||
this.type_map = {
|
||||
'Currency': 'real'
|
||||
, 'Int': 'integer'
|
||||
@ -358,7 +184,4 @@ class sqliteDatabase {
|
||||
, 'Geolocation': 'text'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = { Database: sqliteDatabase };
|
||||
|
@ -4,7 +4,7 @@ const frappejs = require('frappejs');
|
||||
|
||||
module.exports = class FormPage extends Page {
|
||||
constructor(doctype) {
|
||||
let meta = frappe.get_meta(doctype)
|
||||
let meta = frappe.getMeta(doctype)
|
||||
super(`Edit ${meta.name}`);
|
||||
this.meta = meta;
|
||||
|
||||
|
@ -3,7 +3,7 @@ const view = require('frappejs/client/view');
|
||||
|
||||
module.exports = class FormPage extends Page {
|
||||
constructor(doctype) {
|
||||
let meta = frappe.get_meta(doctype);
|
||||
let meta = frappe.getMeta(doctype);
|
||||
super(`List ${meta.name}`);
|
||||
this.list = new (view.get_list_class(doctype))({
|
||||
doctype: doctype,
|
||||
|
@ -19,7 +19,7 @@ class LinkControl extends BaseControl {
|
||||
}
|
||||
|
||||
async get_list(query) {
|
||||
return (await frappe.db.get_all({
|
||||
return (await frappe.db.getAll({
|
||||
doctype: this.target,
|
||||
filters: this.get_filters(query),
|
||||
limit: 50
|
||||
|
@ -116,7 +116,7 @@ class TableControl extends BaseControl {
|
||||
}
|
||||
|
||||
get_child_fields() {
|
||||
return frappe.get_meta(this.childtype).fields;
|
||||
return frappe.getMeta(this.childtype).fields;
|
||||
}
|
||||
|
||||
get_default_data() {
|
||||
|
@ -12,7 +12,7 @@ module.exports = class BaseForm extends Observable {
|
||||
this.controls = {};
|
||||
this.controls_list = [];
|
||||
|
||||
this.meta = frappe.get_meta(this.doctype);
|
||||
this.meta = frappe.getMeta(this.doctype);
|
||||
if (this.setup) {
|
||||
this.setup();
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ module.exports = class BaseList {
|
||||
this.parent = parent;
|
||||
this.fields = fields;
|
||||
|
||||
this.meta = frappe.get_meta(this.doctype);
|
||||
this.meta = frappe.getMeta(this.doctype);
|
||||
|
||||
this.start = 0;
|
||||
this.page_length = 20;
|
||||
@ -36,7 +36,7 @@ module.exports = class BaseList {
|
||||
}
|
||||
|
||||
async get_data() {
|
||||
return await frappe.db.get_all({
|
||||
return await frappe.db.getAll({
|
||||
doctype: this.doctype,
|
||||
fields: this.get_fields(),
|
||||
filters: this.get_filters(),
|
||||
|
6
index.js
6
index.js
@ -40,14 +40,14 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
get_meta(doctype) {
|
||||
getMeta(doctype) {
|
||||
if (!this.meta_cache[doctype]) {
|
||||
this.meta_cache[doctype] = new (this.get_meta_class(doctype))();
|
||||
this.meta_cache[doctype] = new (this.getMeta_class(doctype))();
|
||||
}
|
||||
return this.meta_cache[doctype];
|
||||
},
|
||||
|
||||
get_meta_class(doctype) {
|
||||
getMeta_class(doctype) {
|
||||
doctype = this.slug(doctype);
|
||||
if (this.modules[doctype] && this.modules[doctype].Meta) {
|
||||
return this.modules[doctype].Meta;
|
||||
|
@ -36,13 +36,13 @@ module.exports = class BaseDocument {
|
||||
// assign a random name by default
|
||||
// override this to set a name
|
||||
if (!this.name) {
|
||||
this.name = frappe.get_random_name();
|
||||
this.name = frappe.getRandomName();
|
||||
}
|
||||
}
|
||||
|
||||
set_keywords() {
|
||||
let keywords = [];
|
||||
for (let fieldname of this.meta.get_keyword_fields()) {
|
||||
for (let fieldname of this.meta.getKeywordFields()) {
|
||||
keywords.push(this[fieldname]);
|
||||
}
|
||||
this.keywords = keywords.join(', ');
|
||||
@ -50,7 +50,7 @@ module.exports = class BaseDocument {
|
||||
|
||||
get meta() {
|
||||
if (!this._meta) {
|
||||
this._meta = frappe.get_meta(this.doctype);
|
||||
this._meta = frappe.getMeta(this.doctype);
|
||||
}
|
||||
return this._meta;
|
||||
}
|
||||
@ -80,7 +80,7 @@ module.exports = class BaseDocument {
|
||||
|
||||
get_valid_dict() {
|
||||
let data = {};
|
||||
for (let field of this.meta.get_valid_fields()) {
|
||||
for (let field of this.meta.getValidFields()) {
|
||||
data[field.fieldname] = this[field.fieldname];
|
||||
}
|
||||
return data;
|
||||
@ -114,7 +114,7 @@ module.exports = class BaseDocument {
|
||||
}
|
||||
|
||||
clear_values() {
|
||||
for (let field of this.meta.get_valid_fields()) {
|
||||
for (let field of this.meta.getValidFields()) {
|
||||
if(this[field.fieldname]) {
|
||||
delete this[field.fieldname];
|
||||
}
|
||||
@ -123,7 +123,7 @@ module.exports = class BaseDocument {
|
||||
|
||||
set_child_idx() {
|
||||
// renumber children
|
||||
for (let field of this.meta.get_valid_fields()) {
|
||||
for (let field of this.meta.getValidFields()) {
|
||||
if (field.fieldtype==='Table') {
|
||||
for(let i=0; i < (this[field.fieldname] || []).length; i++) {
|
||||
this[field.fieldname][i].idx = i;
|
||||
|
@ -23,11 +23,11 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
return this._field_map[fieldname];
|
||||
}
|
||||
|
||||
get_table_fields() {
|
||||
if (!this._table_fields) {
|
||||
this._table_fields = this.fields.filter(field => field.fieldtype === 'Table');
|
||||
getTableFields() {
|
||||
if (!this._tableFields) {
|
||||
this._tableFields = this.fields.filter(field => field.fieldtype === 'Table');
|
||||
}
|
||||
return this._table_fields;
|
||||
return this._tableFields;
|
||||
}
|
||||
|
||||
on(key, fn) {
|
||||
@ -46,7 +46,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
return this[fieldname];
|
||||
}
|
||||
|
||||
get_valid_fields({ with_children = true } = {}) {
|
||||
getValidFields({ with_children = true } = {}) {
|
||||
if (!this._valid_fields) {
|
||||
|
||||
this._valid_fields = [];
|
||||
@ -104,7 +104,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
}
|
||||
}
|
||||
|
||||
get_keyword_fields() {
|
||||
getKeywordFields() {
|
||||
return this.keyword_fields || this.meta.fields.filter(field => field.reqd).map(field => field.fieldname);
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
async init_db({backend, connection_params}) {
|
||||
frappe.db = await new backends[backend].Database(connection_params);
|
||||
frappe.db = await new backends[backend](connection_params);
|
||||
await frappe.db.connect();
|
||||
await frappe.db.migrate();
|
||||
},
|
||||
|
@ -10,7 +10,7 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
let data = await frappe.db.get_all({
|
||||
let data = await frappe.db.getAll({
|
||||
doctype: request.params.doctype,
|
||||
fields: request.query.fields,
|
||||
filters: request.query.filters,
|
||||
|
@ -6,7 +6,7 @@ module.exports = {
|
||||
server.init_models();
|
||||
server.init_db({
|
||||
backend: 'sqlite',
|
||||
connection_params: {db_path: 'test.db'}
|
||||
connection_params: {dbPath: 'test.db'}
|
||||
});
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ describe('Database', () => {
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 3'});
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 2'});
|
||||
|
||||
let subjects = await frappe.db.get_all({doctype:'ToDo', fields:['name', 'subject']})
|
||||
let subjects = await frappe.db.getAll({doctype:'ToDo', fields:['name', 'subject']})
|
||||
subjects = subjects.map(d => d.subject);
|
||||
|
||||
assert.ok(subjects.includes('testing 1'));
|
||||
@ -29,7 +29,7 @@ describe('Database', () => {
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 3', status: 'Open'});
|
||||
await frappe.insert({doctype:'ToDo', subject: 'testing 2', status: 'Closed'});
|
||||
|
||||
subjects = await frappe.db.get_all({doctype:'ToDo', fields:['name', 'subject'],
|
||||
subjects = await frappe.db.getAll({doctype:'ToDo', fields:['name', 'subject'],
|
||||
filters:{status: 'Open'}});
|
||||
subjects = subjects.map(d => d.subject);
|
||||
|
||||
@ -37,7 +37,7 @@ describe('Database', () => {
|
||||
assert.ok(subjects.includes('testing 3'));
|
||||
assert.equal(subjects.includes('testing 2'), false);
|
||||
|
||||
subjects = await frappe.db.get_all({doctype:'ToDo', fields:['name', 'subject'],
|
||||
subjects = await frappe.db.getAll({doctype:'ToDo', fields:['name', 'subject'],
|
||||
filters:{status: 'Closed'}});
|
||||
subjects = subjects.map(d => d.subject);
|
||||
|
||||
|
@ -8,12 +8,12 @@ describe('Meta', () => {
|
||||
});
|
||||
|
||||
it('should get init from json file', () => {
|
||||
let todo = frappe.get_meta('ToDo');
|
||||
let todo = frappe.getMeta('ToDo');
|
||||
assert.equal(todo.is_single, 0);
|
||||
});
|
||||
|
||||
it('should get fields from meta', () => {
|
||||
let todo = frappe.get_meta('ToDo');
|
||||
let todo = frappe.getMeta('ToDo');
|
||||
let fields = todo.fields.map((df) => df.fieldname);
|
||||
assert.ok(fields.includes('subject'));
|
||||
assert.ok(fields.includes('description'));
|
||||
|
@ -8,7 +8,7 @@ describe('Models', () => {
|
||||
});
|
||||
|
||||
it('should get todo json', () => {
|
||||
let todo = frappe.get_meta('todo');
|
||||
let todo = frappe.getMeta('todo');
|
||||
assert.equal(todo.is_single, 0);
|
||||
});
|
||||
});
|
@ -2,7 +2,7 @@ const assert = require('assert');
|
||||
const frappe = require('frappejs');
|
||||
const helpers = require('./helpers');
|
||||
|
||||
describe('Document', () => {
|
||||
describe('Number Series', () => {
|
||||
before(async function() {
|
||||
await helpers.init_sqlite();
|
||||
});
|
||||
|
@ -56,7 +56,7 @@ describe('REST', () => {
|
||||
await frappe.insert({doctype:'ToDo', subject:'all test 1'});
|
||||
await frappe.insert({doctype:'ToDo', subject:'all test 2'});
|
||||
|
||||
let data = await frappe.db.get_all({doctype:'ToDo'});
|
||||
let data = await frappe.db.getAll({doctype:'ToDo'});
|
||||
let subjects = data.map(d => d.subject);
|
||||
assert.ok(subjects.includes('all test 1'));
|
||||
assert.ok(subjects.includes('all test 2'));
|
||||
|
@ -3,6 +3,6 @@ const server = require('frappejs/server');
|
||||
if (require.main === module) {
|
||||
server.start({
|
||||
backend: 'sqlite',
|
||||
connection_params: {db_path: 'test.db'}
|
||||
connection_params: {dbPath: 'test.db'}
|
||||
});
|
||||
}
|
@ -15,7 +15,7 @@ module.exports = {
|
||||
return text.toLowerCase().replace(/ /g, '_');
|
||||
},
|
||||
|
||||
get_random_name() {
|
||||
getRandomName() {
|
||||
return Math.random().toString(36).substr(3);
|
||||
},
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user