This commit is contained in:
lxsang 2020-06-17 21:06:55 +02:00
parent 1812f25d8a
commit 5ff637138c
4 changed files with 143 additions and 44 deletions

View File

@ -65,6 +65,14 @@ interface String {
*/ */
unescape(): string; unescape(): string;
/**
* Escape the current string using backslash
*
* @returns {string}
* @memberof String
*/
escape(): string;
/** /**
* Convert the current string to uint8 array * Convert the current string to uint8 array
* *
@ -371,6 +379,16 @@ namespace OS {
return this.__().unescape(); return this.__().unescape();
} }
/**
* Escape the formatted string
*
* @returns {string}
* @memberof FormattedString
*/
escape(): string {
return this.__().escape();
}
/** /**
* Convert the formatted string to uint8 array * Convert the formatted string to uint8 array
* *
@ -612,15 +630,47 @@ namespace OS {
) )
); );
}; };
String.prototype.escape = function (): string {
return this.replace(/[\0\x08\x09\x1a\n\r"'\\\%]/g, function (
c: string
) {
switch (c) {
case "\0":
return "\\0";
case "\x08":
return "\\b";
case "\x09":
return "\\t";
case "\x1a":
return "\\z";
case "\n":
return "\\n";
case "\r":
return "\\r";
case '"':
case "'":
case "\\":
case "%":
return "\\" + c; // prepends a backslash to backslash, percent,
// and double/single quotes
default:
return c;
}
});
};
String.prototype.unescape = function (): string { String.prototype.unescape = function (): string {
let d = this; let d = this;
d = d.replace(/\\\\/g, "\\"); d = d.replace(/\\\\/g, "\\");
d = d.replace(/\\"/g, '"'); d = d.replace(/\\"/g, '"');
d = d.replace(/\\'/g, "'");
d = d.replace(/\\%/g, '%');
d = d.replace(/\\0/g, "\0");
d = d.replace(/\\n/g, "\n"); d = d.replace(/\\n/g, "\n");
d = d.replace(/\\t/g, "\t"); d = d.replace(/\\t/g, "\t");
d = d.replace(/\\b/g, "\b"); d = d.replace(/\\b/g, "\b");
d = d.replace(/\\f/g, "\f"); d = d.replace(/\\f/g, "\f");
d = d.replace(/\\r/g, "\r"); d = d.replace(/\\r/g, "\r");
d = d.replace(/\\z/g, "\x1a");
return d; return d;
}; };
String.prototype.asUint8Array = function (): Uint8Array { String.prototype.asUint8Array = function (): Uint8Array {
@ -916,6 +966,14 @@ namespace OS {
*/ */
iconclass?: string; iconclass?: string;
/**
* VFS application icon path
*
* @type {string}
* @memberof PackageMetaType
*/
icon?: string;
/** /**
* Package information * Package information
* *

View File

@ -19,41 +19,63 @@
namespace OS { namespace OS {
export namespace API { export namespace API {
/** /**
* Simple Virtual Database (VDB) application API.
* *
* This API abstracts and provides a standard way to
* connect to a server-side relational database (e.g. sqlite).
*
* Each user when connected has their own database previously
* created. All VDB operations related to that user will be
* performed on this database.
*
* The creation of user database need to be managed by the server-side API.
* The VDB API assumes that the database already exist. All operations
* is performed in tables level
* *
* @export * @export
* @class DB * @class DB
*/ */
export class DB { export class DB {
table: GenericObject<any>; /**
* A table name on the user's database
*
* @private
* @type {string}
* @memberof DB
*/
private table: string;
/** /**
*Creates an instance of DB. *Creates an instance of DB.
* @param {GenericObject<any>} table * @param {string} table table name
* @memberof DB * @memberof DB
*/ */
constructor(table: GenericObject<any>) { constructor(table: string) {
this.table = table; this.table = table;
} }
/** /**
* Save data to the current table. The input
* data must conform to the table record format.
* *
* On the server side, if the table doest not
* exist yet, it should be created automatically
* by inferring the data structure of the input
* object
* *
* @param {*} d * @param {GenericObject<any>} d data object represents a current table record
* @returns {Promise<API.RequestResult>} * @returns {Promise<API.RequestResult>}
* @memberof DB * @memberof DB
*/ */
save(d: any): Promise<API.RequestResult> { save(d: GenericObject<any>): Promise<API.RequestResult> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
const r = await Ant.OS.API.handle.dbquery("save", { const r = await API.handle.dbquery("save", {
table: this.table, table: this.table,
data: d, data: d,
}); });
if (r.error) { if (r.error) {
return reject( return reject(API.throwe(r.error.toString()));
Ant.OS.API.throwe(r.error.toString())
);
} }
return resolve(r); return resolve(r);
} catch (e) { } catch (e) {
@ -63,29 +85,46 @@ namespace OS {
} }
/** /**
* delete record(s) from the current table by
* a conditional object
* *
* @param {*} c conditional object, c can be:
*
* * a `number`: the operation will delete the record with `id = c`
* * a `string`: The SQL string condition that selects record to delete
* * a conditional object represents a SQL condition statement as an object,
* example: `pid = 10 AND cid = 2` is represented by:
*
* ```typescript
* {
* exp: {
* "and": {
* pid: 10,
* cid: 2
* }
* }
* ```
* *
* @param {*} c
* @returns {Promise<API.RequestResult>} * @returns {Promise<API.RequestResult>}
* @memberof DB * @memberof DB
*/ */
delete(c: any): Promise<API.RequestResult> { delete(
c: GenericObject<any> | number | string
): Promise<API.RequestResult> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
const rq: any = { table: this.table }; const rq: any = { table: this.table };
if (!c || c === "") { if (!c || c === "") {
reject(Ant.OS.API.throwe("OS.DB: unkown condition")); reject(API.throwe("OS.DB: unknown condition"));
} }
if (isNaN(c)) { if (isNaN(c as number)) {
rq.cond = c; rq.cond = c;
} else { } else {
rq.id = c; rq.id = c;
} }
try { try {
const r = await Ant.OS.API.handle.dbquery("delete", rq); const r = await API.handle.dbquery("delete", rq);
if (r.error) { if (r.error) {
return reject( return reject(API.throwe(r.error.toString()));
Ant.OS.API.throwe(r.error.toString())
);
} }
return resolve(r); return resolve(r);
} catch (e) { } catch (e) {
@ -95,23 +134,21 @@ namespace OS {
} }
/** /**
* Get a record in the table by its primary key
* *
* * @param {number} id the primary key value
* @param {number} id * @returns {Promise<GenericObject<any>>} Promise on returned record data
* @returns {Promise<GenericObject<any>>}
* @memberof DB * @memberof DB
*/ */
get(id: number): Promise<GenericObject<any>> { get(id: number): Promise<GenericObject<any>> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
const r = await Ant.OS.API.handle.dbquery("get", { const r = await API.handle.dbquery("get", {
table: this.table, table: this.table,
id: id, id: id,
}); });
if (r.error) { if (r.error) {
return reject( return reject(API.throwe(r.error.toString()));
Ant.OS.API.throwe(r.error.toString())
);
} }
return resolve(r.result as GenericObject<any>); return resolve(r.result as GenericObject<any>);
} catch (e) { } catch (e) {
@ -121,23 +158,38 @@ namespace OS {
} }
/** /**
* Find records by a condition
* *
* @param {GenericObject<any>} cond conditional object
* *
* @param {GenericObject<any>} cond * a conditional object represents a SQL condition statement as an object,
* example: `pid = 10 AND cid = 2 ORDER BY date DESC` is represented by:
*
* ```typescript
* {
* exp: {
* "and": {
* pid: 10,
* cid: 2
* }
* },
* order: {
* date: "DESC"
* }
* }
* ```
* @returns {Promise<GenericObject<any>[]>} * @returns {Promise<GenericObject<any>[]>}
* @memberof DB * @memberof DB
*/ */
find(cond: GenericObject<any>): Promise<GenericObject<any>[]> { find(cond: GenericObject<any>): Promise<GenericObject<any>[]> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
const r = await Ant.OS.API.handle.dbquery("select", { const r = await API.handle.dbquery("select", {
table: this.table, table: this.table,
cond, cond,
}); });
if (r.error) { if (r.error) {
return reject( return reject(API.throwe(r.error.toString()));
Ant.OS.API.throwe(r.error.toString())
);
} }
return resolve(r.result as GenericObject<any>[]); return resolve(r.result as GenericObject<any>[]);
} catch (e) { } catch (e) {

View File

@ -1,10 +1,3 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
// Copyright 2017-2018 Xuan Sang LE <xsang.le AT gmail DOT com> // Copyright 2017-2018 Xuan Sang LE <xsang.le AT gmail DOT com>
// AnTOS Web desktop is is licensed under the GNU General Public // AnTOS Web desktop is is licensed under the GNU General Public
@ -23,6 +16,9 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see https://www.gnu.org/licenses/. // along with this program. If not, see https://www.gnu.org/licenses/.
namespace OS { namespace OS {
/**
*
*/
export namespace GUI { export namespace GUI {
/** /**
* *

View File

@ -1,10 +1,3 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* DS208: Avoid top-level this
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
// Copyright 2017-2018 Xuan Sang LE <xsang.le AT gmail DOT com> // Copyright 2017-2018 Xuan Sang LE <xsang.le AT gmail DOT com>
// AnTOS Web desktop is is licensed under the GNU General Public // AnTOS Web desktop is is licensed under the GNU General Public