mirror of
https://github.com/frappe/books.git
synced 2024-12-22 10:58:59 +00:00
first commit
This commit is contained in:
commit
2ed02ea846
8
.eslintrc
Normal file
8
.eslintrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"parser": "babel-eslint"
|
||||
}
|
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
test.db
|
||||
*.log
|
||||
|
||||
/dist
|
||||
/temp
|
||||
|
||||
# ignore everything in 'app' folder what had been generated from 'src' folder
|
||||
/app/app.js
|
||||
/app/background.js
|
||||
/app/**/*.map
|
23
README.md
Normal file
23
README.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Frappe Core
|
||||
|
||||
Core libs for Frappe Framework JS
|
||||
|
||||
### Examples
|
||||
|
||||
const frappe = require('frappe-core);
|
||||
|
||||
# init database
|
||||
frappe.init();
|
||||
|
||||
# make a new todo
|
||||
let todo = frappe.get_doc({doctype: 'ToDo', subject: 'something'})
|
||||
todo.insert()
|
||||
|
||||
# get all todos
|
||||
let total_open = 0;
|
||||
for (let d of frappe.get_all('ToDo')) {
|
||||
todo = frappe.get_doc('ToDo', d.name);
|
||||
if (todo.status == 'Open') total_open += 1;
|
||||
}
|
||||
|
||||
|
60
frappe/index.js
Normal file
60
frappe/index.js
Normal file
@ -0,0 +1,60 @@
|
||||
const path = require('path')
|
||||
module.exports = {
|
||||
init(db_path, user, user_key) {
|
||||
this.db_path = db_path || 'test.db';
|
||||
if (this._initialized) return;
|
||||
this.init_config();
|
||||
this.init_errors();
|
||||
this.init_globals();
|
||||
this.init_libs();
|
||||
this.init_db();
|
||||
this._initialized = true;
|
||||
this.login(user, user_key);
|
||||
},
|
||||
init_config() {
|
||||
this.config = {};
|
||||
},
|
||||
init_errors() {
|
||||
this.ValueError = class extends Error { };
|
||||
},
|
||||
init_globals() {
|
||||
this.meta_cache = {};
|
||||
},
|
||||
init_libs() {
|
||||
this.utils = require('./utils');
|
||||
Object.assign(this, this.utils);
|
||||
let models = require('./model/models');
|
||||
this.models = new models.Models();
|
||||
this.model = require('./model');
|
||||
this.document = require('./model/document');
|
||||
this.meta = require('./model/meta');
|
||||
this.session_lib = require('./session');
|
||||
},
|
||||
init_db() {
|
||||
let database = require('./model/database');
|
||||
this.db = new database.Database(this.db_path);
|
||||
},
|
||||
get_meta(doctype) {
|
||||
if (!this.meta_cache[doctype]) {
|
||||
this.meta_cache[doctype] = new this.meta.Meta(this.models.get('DocType', doctype));
|
||||
}
|
||||
return this.meta_cache[doctype];
|
||||
},
|
||||
get_doc(data, name) {
|
||||
if (typeof data==='string' && typeof name==='string') {
|
||||
let controller_class = this.models.get_controller(data);
|
||||
var doc = new controller_class({doctype:data, name: name});
|
||||
doc.load();
|
||||
} else {
|
||||
let controller_class = this.models.get_controller(data.doctype);
|
||||
var doc = new controller_class(data);
|
||||
}
|
||||
return doc;
|
||||
},
|
||||
login(user, user_key) {
|
||||
this.session = new this.session_lib.Session(user);
|
||||
if (user && user_key) {
|
||||
this.login(user_key);
|
||||
}
|
||||
}
|
||||
};
|
124
frappe/model/database.js
Normal file
124
frappe/model/database.js
Normal file
@ -0,0 +1,124 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const SQL = require('sql.js');
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
class Database {
|
||||
constructor(db_path) {
|
||||
this.db_file_name = db_path;
|
||||
this.connect();
|
||||
}
|
||||
|
||||
connect() {
|
||||
if (this.db_path) {
|
||||
const filebuffer = fs.readFileSync(this.db_path);
|
||||
this._conn = new SQL.Database(filebuffer);
|
||||
} else {
|
||||
this._conn = new SQL.Database();
|
||||
}
|
||||
}
|
||||
|
||||
write() {
|
||||
if (this.db_path) {
|
||||
let data = this._conn.export();
|
||||
fs.writeFileSync(this.db_path, new Buffer(data));
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
this.write();
|
||||
this._conn.close();
|
||||
}
|
||||
|
||||
create_db() {
|
||||
// Create a database.
|
||||
let db = new SQL.Database();
|
||||
let query = SCHEMA;
|
||||
let result = db.exec(query);
|
||||
if (Object.keys(result).length === 0 &&
|
||||
typeof result.constructor === 'function') {
|
||||
return db;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
create_table(doctype) {
|
||||
let meta = frappe.get_meta(doctype);
|
||||
let columns = [];
|
||||
|
||||
// add standard fields
|
||||
let fields = frappe.model.standard_fields.slice();
|
||||
if (meta.istable) {
|
||||
fields = fields.concat(model.child_fields);
|
||||
}
|
||||
|
||||
// add model fields
|
||||
fields = fields.concat(meta.fields);
|
||||
|
||||
for (let df of fields) {
|
||||
if (frappe.model.type_map[df.fieldtype]) {
|
||||
columns.push(`${df.fieldname} ${frappe.model.type_map[df.fieldtype]} ${df.reqd ? "not null" : ""} ${df.default ? ("default " + frappe.utils.sqlescape(df.default)) : ""}`);
|
||||
}
|
||||
}
|
||||
|
||||
const query = `CREATE TABLE IF NOT EXISTS ${frappe.slug(doctype)} (
|
||||
${columns.join(", ")})`;
|
||||
|
||||
return this.sql(query);
|
||||
}
|
||||
|
||||
get(doctype, name) {
|
||||
let doc = frappe.db.sql(`select * from ${frappe.slug(doctype)} where name = ${frappe.db.escape(name)}`);
|
||||
return doc ? doc[0] : {};
|
||||
}
|
||||
|
||||
insert(doctype, doc) {
|
||||
this.sql(`insert into ${frappe.slug(doctype)}
|
||||
(${Object.keys(doc).join(", ")})
|
||||
values (${Object.values(doc).map(d => frappe.db.escape(d)).join(", ")})`);
|
||||
}
|
||||
|
||||
update(doctype, doc) {
|
||||
let assigns = [];
|
||||
for (let key in doc) {
|
||||
assigns.push(`${key} = ${this.escape(doc[key])}`);
|
||||
}
|
||||
this.sql(`update ${frappe.slug(doctype)}
|
||||
set ${assigns.join(", ")}`);
|
||||
}
|
||||
|
||||
sql(query, opts={}) {
|
||||
//console.log(query);
|
||||
const result = frappe.db._conn.exec(query);
|
||||
if (result.length > 0) {
|
||||
if (opts.as_list)
|
||||
return result[0];
|
||||
else
|
||||
return sql_result_to_obj(result[0]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
get_value(doctype, name, fieldname='name') {
|
||||
let value = this.sql(`select ${fieldname} from ${frappe.slug(doctype)}
|
||||
where name=${this.escape(name)}`);
|
||||
return value.length ? value[0][fieldname] : null;
|
||||
}
|
||||
|
||||
escape(value) {
|
||||
return frappe.utils.sqlescape(value);
|
||||
}
|
||||
}
|
||||
|
||||
function sql_result_to_obj(result) {
|
||||
const columns = result.columns;
|
||||
return result.values.map(row => {
|
||||
return columns.reduce((res, col, i) => {
|
||||
res[col] = row[i];
|
||||
return res;
|
||||
}, {});
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = { Database: Database };
|
109
frappe/model/document.js
Normal file
109
frappe/model/document.js
Normal file
@ -0,0 +1,109 @@
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
class Document {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
|
||||
get(key) {
|
||||
return this[key];
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
this.validate_field(key, value);
|
||||
this[key] = value;
|
||||
}
|
||||
|
||||
set_name() {
|
||||
// assign a random name by default
|
||||
// override this to set a name
|
||||
if (!this.name) {
|
||||
this.name = Math.random().toString(36).substr(3);
|
||||
}
|
||||
}
|
||||
|
||||
get meta() {
|
||||
if (!this._meta) {
|
||||
this._meta = frappe.get_meta(this.doctype);
|
||||
}
|
||||
return this._meta;
|
||||
}
|
||||
|
||||
append(key, document) {
|
||||
if (!this[key]) {
|
||||
this[key] = [];
|
||||
}
|
||||
this[key].push(this.init_doc(document));
|
||||
}
|
||||
|
||||
init_doc(data) {
|
||||
if (data.prototype instanceof Document) {
|
||||
return data;
|
||||
} else {
|
||||
return new Document(d);
|
||||
}
|
||||
}
|
||||
|
||||
validate_field (key, value) {
|
||||
let df = this.meta.get_field(key);
|
||||
if (df.fieldtype=='Select') {
|
||||
this.meta.validate_select(df, value);
|
||||
}
|
||||
}
|
||||
|
||||
validate() { }
|
||||
before_insert() { }
|
||||
after_insert() { }
|
||||
before_update() { }
|
||||
after_update() { }
|
||||
after_save() { }
|
||||
|
||||
get_valid_dict() {
|
||||
let doc = {};
|
||||
for(let df of this.meta.get_valid_fields()) {
|
||||
doc[df.fieldname] = this.get(df.fieldname);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
set_standard_values() {
|
||||
let now = new Date();
|
||||
if (this.docstatus === null || this.docstatus === undefined) {
|
||||
this.docstatus = 0;
|
||||
}
|
||||
if (!this.owner) {
|
||||
this.owner = frappe.session.user;
|
||||
this.creation = now;
|
||||
}
|
||||
this.modified_by = frappe.session.user;
|
||||
this.modified = now;
|
||||
}
|
||||
|
||||
load() {
|
||||
Object.assign(this, frappe.db.get(this.doctype, this.name));
|
||||
return this;
|
||||
}
|
||||
|
||||
insert() {
|
||||
this.set_name();
|
||||
this.set_standard_values();
|
||||
this.validate();
|
||||
this.before_insert();
|
||||
frappe.db.insert(this.doctype, this.get_valid_dict())
|
||||
this.after_insert();
|
||||
this.after_save();
|
||||
return this;
|
||||
}
|
||||
|
||||
update() {
|
||||
this.set_standard_values();
|
||||
this.validate();
|
||||
this.before_insert();
|
||||
frappe.db.update(this.doctype, this.get_valid_dict());
|
||||
this.after_update();
|
||||
this.after_save();
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { Document: Document };
|
63
frappe/model/index.js
Normal file
63
frappe/model/index.js
Normal file
@ -0,0 +1,63 @@
|
||||
module.exports = {
|
||||
standard_fields: [
|
||||
{
|
||||
fieldname: 'name', fieldtype: 'Data', reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'owner', fieldtype: 'Link', reqd: 1, options: 'User'
|
||||
},
|
||||
{
|
||||
fieldname: 'modified_by', fieldtype: 'Link', reqd: 1, options: 'User'
|
||||
},
|
||||
{
|
||||
fieldname: 'creation', fieldtype: 'Datetime', reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'modified', fieldtype: 'Datetime', reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'docstatus', fieldtype: 'Int', reqd: 1, default: 0
|
||||
}
|
||||
],
|
||||
child_fields: [
|
||||
{
|
||||
fieldname: 'idx', fieldtype: 'Int', reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'parent', fieldtype: 'Data', reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'parenttype', fieldtype: 'Link', reqd: 1, options: 'DocType'
|
||||
},
|
||||
{
|
||||
fieldname: 'parentfield', fieldtype: 'Data', reqd: 1
|
||||
}
|
||||
],
|
||||
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'
|
||||
}
|
||||
};
|
70
frappe/model/meta.js
Normal file
70
frappe/model/meta.js
Normal file
@ -0,0 +1,70 @@
|
||||
const Document = require('./document').Document;
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
class Meta extends Document {
|
||||
constructor(data) {
|
||||
super(data);
|
||||
this.event_handlers = {};
|
||||
}
|
||||
|
||||
get_field(fieldname) {
|
||||
if (!this.field_map) {
|
||||
this.field_map = {};
|
||||
for (let df of this.fields) {
|
||||
this.field_map[df.fieldname] = df;
|
||||
}
|
||||
}
|
||||
return this.field_map[fieldname];
|
||||
}
|
||||
|
||||
on(key, fn) {
|
||||
if (!this.event_handlers[key]) {
|
||||
this.event_handlers[key] = [];
|
||||
}
|
||||
this.event_handlers[key].push(fn);
|
||||
}
|
||||
|
||||
get_valid_fields() {
|
||||
if (!this._valid_fields) {
|
||||
this._valid_fields = [];
|
||||
|
||||
// standard fields
|
||||
for (let df of frappe.model.standard_fields) {
|
||||
this._valid_fields.push(df);
|
||||
}
|
||||
|
||||
// parent fields
|
||||
if (this.istable) {
|
||||
for (let df of frappe.model.child_fields) {
|
||||
this._valid_fields.push(df);
|
||||
}
|
||||
}
|
||||
|
||||
// doctype fields
|
||||
for (let df of this.fields) {
|
||||
if (frappe.model.type_map[df.fieldtype]) {
|
||||
this._valid_fields.push(df);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this._valid_fields;
|
||||
}
|
||||
|
||||
validate_select(df, value) {
|
||||
let options = df.options;
|
||||
if (typeof options === 'string') {
|
||||
// values given as string
|
||||
options = df.options.split('\n');
|
||||
}
|
||||
if (!options.includes(value)) {
|
||||
throw new frappe.ValueError(`${value} must be one of ${options.join(", ")}`);
|
||||
}
|
||||
}
|
||||
|
||||
trigger(key) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Meta: Meta }
|
68
frappe/model/models.js
Normal file
68
frappe/model/models.js
Normal file
@ -0,0 +1,68 @@
|
||||
const walk = require('walk');
|
||||
const path = require('path');
|
||||
const process = require('process');
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
class Models {
|
||||
constructor() {
|
||||
this.data = {};
|
||||
this.controllers = {};
|
||||
this.setup_path_map();
|
||||
}
|
||||
|
||||
get(doctype, name) {
|
||||
if (!this.data[doctype]) {
|
||||
this.data[doctype] = {};
|
||||
}
|
||||
if (!this.data[doctype][name]) {
|
||||
this.data[doctype][name] = require(
|
||||
this.path_map[frappe.slug(doctype)][frappe.slug(name)]);
|
||||
}
|
||||
return this.data[doctype][name];
|
||||
}
|
||||
|
||||
get_controller(doctype) {
|
||||
doctype = frappe.slug(doctype);
|
||||
if (!this.controllers[doctype]) {
|
||||
this.controllers[doctype] = require(this.controller_map[doctype])[doctype];
|
||||
}
|
||||
return this.controllers[doctype];
|
||||
}
|
||||
|
||||
setup_path_map() {
|
||||
const cwd = process.cwd();
|
||||
this.path_map = {};
|
||||
this.controller_map = {};
|
||||
|
||||
if (!frappe.config.apps) {
|
||||
frappe.config.apps = [];
|
||||
}
|
||||
frappe.config.apps.unshift('frappe-core');
|
||||
|
||||
for (let app_name of frappe.config.apps) {
|
||||
let start = path.resolve(require.resolve(app_name), '../models');
|
||||
walk.walkSync(start, {
|
||||
listeners: {
|
||||
file: (basepath, file_data, next) => {
|
||||
const doctype = path.basename(path.dirname(basepath));
|
||||
const name = path.basename(basepath);
|
||||
const file_path = path.resolve(basepath, file_data.name);
|
||||
if (file_data.name.endsWith('.json')) {
|
||||
if (!this.path_map[doctype]) {
|
||||
this.path_map[doctype] = {};
|
||||
}
|
||||
|
||||
this.path_map[doctype][name] = file_path;
|
||||
}
|
||||
if (doctype==='doctype' && file_data.name.endsWith('.js')) {
|
||||
this.controller_map[name] = file_path;
|
||||
}
|
||||
next();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Models: Models }
|
11
frappe/models/doctype/todo/todo.js
Normal file
11
frappe/models/doctype/todo/todo.js
Normal file
@ -0,0 +1,11 @@
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
class todo extends frappe.document.Document {
|
||||
validate() {
|
||||
if (!this.status) {
|
||||
this.status = 'Open';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { todo: todo };
|
30
frappe/models/doctype/todo/todo.json
Normal file
30
frappe/models/doctype/todo/todo.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"autoname": "hash",
|
||||
"name": "ToDo",
|
||||
"doctype": "DocType",
|
||||
"issingle": 0,
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "subject",
|
||||
"label": "Subject",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"label": "Description",
|
||||
"fieldtype": "Text"
|
||||
},
|
||||
{
|
||||
"fieldname": "status",
|
||||
"label": "Status",
|
||||
"fieldtype": "Select",
|
||||
"options": [
|
||||
"Open",
|
||||
"Closed"
|
||||
],
|
||||
"default": "Open",
|
||||
"reqd": 1
|
||||
}
|
||||
]
|
||||
}
|
17
frappe/session.js
Normal file
17
frappe/session.js
Normal file
@ -0,0 +1,17 @@
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
class Session {
|
||||
constructor(user, user_key) {
|
||||
this.user = user || 'guest';
|
||||
if (this.user !== 'guest') {
|
||||
this.login(user_key);
|
||||
}
|
||||
}
|
||||
|
||||
login(user_key) {
|
||||
// could be password, sessionid, otp
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = { Session: Session };
|
18
frappe/tests/test_controller.js
Normal file
18
frappe/tests/test_controller.js
Normal file
@ -0,0 +1,18 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
describe('Controller', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
frappe.db.create_table('ToDo');
|
||||
});
|
||||
|
||||
it('should call controller method', () => {
|
||||
let doc = frappe.get_doc({
|
||||
doctype:'ToDo',
|
||||
subject: 'test'
|
||||
});
|
||||
doc.validate();
|
||||
assert.equal(doc.status, 'Open');
|
||||
});
|
||||
});
|
13
frappe/tests/test_database.js
Normal file
13
frappe/tests/test_database.js
Normal file
@ -0,0 +1,13 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
describe('Document', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
});
|
||||
|
||||
// it('should create a table', () => {
|
||||
// frappe.db.create_table('ToDo');
|
||||
// frappe.db.write();
|
||||
// });
|
||||
});
|
62
frappe/tests/test_document.js
Normal file
62
frappe/tests/test_document.js
Normal file
@ -0,0 +1,62 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
describe('Document', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
frappe.db.create_table('ToDo');
|
||||
});
|
||||
|
||||
it('should insert a doc', () => {
|
||||
let doc1 = test_doc();
|
||||
doc1.subject = 'insert subject 1';
|
||||
doc1.description = 'insert description 1';
|
||||
doc1.insert();
|
||||
|
||||
// get it back from the db
|
||||
let doc2 = frappe.get_doc(doc1.doctype, doc1.name);
|
||||
assert.equal(doc1.subject, doc2.subject);
|
||||
assert.equal(doc1.description, doc2.description);
|
||||
});
|
||||
|
||||
it('should update a doc', () => {
|
||||
let doc = test_doc().insert();
|
||||
|
||||
assert.notEqual(frappe.db.get_value(doc.doctype, doc.name, 'subject'), 'subject 2');
|
||||
|
||||
doc.subject = 'subject 2'
|
||||
doc.update();
|
||||
|
||||
assert.equal(frappe.db.get_value(doc.doctype, doc.name, 'subject'), 'subject 2');
|
||||
})
|
||||
|
||||
it('should get a value', () => {
|
||||
assert.equal(test_doc().get('subject'), 'testing 1');
|
||||
});
|
||||
|
||||
it('should set a value', () => {
|
||||
let doc = test_doc();
|
||||
doc.set('subject', 'testing 1')
|
||||
assert.equal(doc.get('subject'), 'testing 1');
|
||||
});
|
||||
|
||||
it('should not allow incorrect Select option', () => {
|
||||
let doc = test_doc();
|
||||
assert.throws(
|
||||
() => {
|
||||
doc.set('status', 'Illegal');
|
||||
},
|
||||
frappe.ValueError
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
const test_doc = () => {
|
||||
return frappe.get_doc({
|
||||
doctype: 'ToDo',
|
||||
status: 'Open',
|
||||
subject: 'testing 1',
|
||||
description: 'test description 1'
|
||||
});
|
||||
}
|
21
frappe/tests/test_meta.js
Normal file
21
frappe/tests/test_meta.js
Normal file
@ -0,0 +1,21 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
describe('Meta', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
});
|
||||
|
||||
it('should get init from json file', () => {
|
||||
let todo = frappe.get_meta('ToDo');
|
||||
assert.equal(todo.issingle, 0);
|
||||
});
|
||||
|
||||
it('should get fields from meta', () => {
|
||||
let todo = frappe.get_meta('ToDo');
|
||||
let fields = todo.fields.map((df) => df.fieldname);
|
||||
assert.ok(fields.includes('subject'));
|
||||
assert.ok(fields.includes('description'));
|
||||
assert.ok(fields.includes('status'));
|
||||
});
|
||||
});
|
13
frappe/tests/test_models.js
Normal file
13
frappe/tests/test_models.js
Normal file
@ -0,0 +1,13 @@
|
||||
const assert = require('assert');
|
||||
const frappe = require('frappe-core');
|
||||
|
||||
describe('Models', () => {
|
||||
before(function() {
|
||||
frappe.init();
|
||||
});
|
||||
|
||||
it('should get todo json', () => {
|
||||
let todo = frappe.models.get('DocType', 'ToDo');
|
||||
assert.equal(todo.issingle, 0);
|
||||
});
|
||||
});
|
23
frappe/utils.js
Normal file
23
frappe/utils.js
Normal file
@ -0,0 +1,23 @@
|
||||
module.exports = {
|
||||
slug(text) {
|
||||
return text.toLowerCase().replace(/ /g, '_');
|
||||
},
|
||||
sqlescape(value) {
|
||||
if (value===null || value===undefined) {
|
||||
// null
|
||||
return 'null';
|
||||
|
||||
} else if (value instanceof Date) {
|
||||
// date
|
||||
return `'${value.toISOString()}'`;
|
||||
|
||||
} else if (typeof value==='string') {
|
||||
// text
|
||||
return "'" + value.replace(/'/g, '\'').replace(/"/g, '\"') + "'";
|
||||
|
||||
} else {
|
||||
// number
|
||||
return value + '';
|
||||
}
|
||||
}
|
||||
}
|
4114
package-lock.json
generated
Normal file
4114
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
package.json
Normal file
29
package.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "frappe-core",
|
||||
"version": "1.0.0",
|
||||
"description": "Frappe Core",
|
||||
"main": "frappe/index.js",
|
||||
"scripts": {
|
||||
"test": "mocha frappe/tests"
|
||||
},
|
||||
"dependencies": {
|
||||
"sql.js": "^0.4.0",
|
||||
"walk": "^2.3.9"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/frappe/frappe-js.git"
|
||||
},
|
||||
"author": "Frappe",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/frappe/frappe-js/issues"
|
||||
},
|
||||
"homepage": "https://github.com/frappe/frappe-js#readme",
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^8.0.1",
|
||||
"eslint": "^4.9.0",
|
||||
"mocha": "^4.0.1",
|
||||
"webpack": "^3.8.1"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user