jsstore
Version:
Harness the power of JsStore to streamline database operations in your web applications. With its SQL-like API, JsStore simplifies IndexedDB interactions, enabling developers to easily query, filter, and manipulate data with familiar syntax and efficiency
1,415 lines (1,343 loc) • 175 kB
JavaScript
/*!
* @license :jsstore - V4.9.0 - 16/12/2024
* https://github.com/ujjwalguptaofficial/JsStore
* Copyright (c) 2024 @Ujjwal Gupta; Licensed MIT
*/
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ // The require scope
/******/ var __webpack_require__ = {};
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
QueryManager: () => (/* reexport */ QueryManager)
});
;// ./src/common/utils/promise_resolve.ts
var promiseResolve = function (value) {
return Promise.resolve(value);
};
;// ./src/common/utils/promise.ts
var promise = function (cb) {
return new Promise(cb);
};
;// ./src/common/enums.ts
var ERROR_TYPE = {
InvalidUpdateColumn: "invalid_update_column",
UndefinedColumn: "undefined_column",
UndefinedValue: "undefined_value",
UndefinedColumnName: "undefined_column_name",
UndefinedDbName: "undefined_database_name",
UndefinedColumnValue: "undefined_column_value",
NotArray: "not_array",
NoValueSupplied: "no_value_supplied",
ColumnNotExist: "column_not_exist",
NoIndexFound: "no_index_found",
InvalidOp: "invalid_operator",
NullValue: "null_value",
WrongDataType: "wrong_data_type",
TableNotExist: "table_not_exist",
DbNotExist: "db_not_exist",
ConnectionAborted: "connection_aborted",
ConnectionClosed: "connection_closed",
NotObject: "not_object",
InvalidConfig: "invalid_config",
DbBlocked: "Db_blocked",
IndexedDbNotSupported: "indexeddb_not_supported",
NullValueInWhere: "null_value_in_where",
InvalidJoinQuery: 'invalid_join_query',
InvalidQuery: 'invalid_query',
ImportScriptsFailed: 'import_scripts_failed',
MethodNotExist: 'method_not_exist',
Unknown: "unknown",
InvalidMiddleware: "invalid_middleware",
InvalidOrderQuery: 'invalid_order_query',
InvalidGroupQuery: 'invalid_group_query',
NoPrimaryKey: 'no_primary_key'
};
var WORKER_STATUS;
(function (WORKER_STATUS) {
WORKER_STATUS["Registered"] = "registerd";
WORKER_STATUS["Failed"] = "failed";
WORKER_STATUS["NotStarted"] = "not_started";
})(WORKER_STATUS || (WORKER_STATUS = {}));
var DATA_TYPE;
(function (DATA_TYPE) {
DATA_TYPE["String"] = "string";
DATA_TYPE["Object"] = "object";
DATA_TYPE["Array"] = "array";
DATA_TYPE["Number"] = "number";
DATA_TYPE["Boolean"] = "boolean";
DATA_TYPE["Null"] = "null";
DATA_TYPE["DateTime"] = "date_time";
})(DATA_TYPE || (DATA_TYPE = {}));
var API;
(function (API) {
API["InitDb"] = "init_db";
API["MapGet"] = "map_get";
API["MapSet"] = "map_set";
API["MapHas"] = "map_has";
API["MapDelete"] = "map_delete";
API["Select"] = "select";
API["Insert"] = "insert";
API["Update"] = "update";
API["Remove"] = "remove";
API["OpenDb"] = "open_db";
API["Clear"] = "clear";
API["DropDb"] = "drop_db";
API["Count"] = "count";
API["ChangeLogStatus"] = "change_log_status";
API["Terminate"] = "terminate";
API["Transaction"] = "transaction";
API["CloseDb"] = "close_db";
API["Union"] = "union";
API["Intersect"] = "intersect";
API["ImportScripts"] = "import_scripts";
API["Middleware"] = "middleware";
})(API || (API = {}));
var EVENT;
(function (EVENT) {
EVENT["RequestQueueEmpty"] = "requestQueueEmpty";
EVENT["RequestQueueFilled"] = "requestQueueFilled";
EVENT["Upgrade"] = "upgrade";
EVENT["Create"] = "create";
EVENT["Open"] = "open";
})(EVENT || (EVENT = {}));
var QUERY_OPTION;
(function (QUERY_OPTION) {
QUERY_OPTION["Where"] = "where";
QUERY_OPTION["Like"] = "like";
QUERY_OPTION["Regex"] = "regex";
QUERY_OPTION["In"] = "in";
QUERY_OPTION["Equal"] = "=";
QUERY_OPTION["Between"] = "-";
QUERY_OPTION["GreaterThan"] = ">";
QUERY_OPTION["LessThan"] = "<";
QUERY_OPTION["GreaterThanEqualTo"] = ">=";
QUERY_OPTION["LessThanEqualTo"] = "<=";
QUERY_OPTION["NotEqualTo"] = "!=";
QUERY_OPTION["Aggregate"] = "aggregate";
QUERY_OPTION["Max"] = "max";
QUERY_OPTION["Min"] = "min";
QUERY_OPTION["Avg"] = "avg";
QUERY_OPTION["Count"] = "count";
QUERY_OPTION["Sum"] = "sum";
QUERY_OPTION["List"] = "list";
QUERY_OPTION["Or"] = "or";
QUERY_OPTION["Skip"] = "skip";
QUERY_OPTION["Limit"] = "limit";
QUERY_OPTION["And"] = "and";
QUERY_OPTION["IgnoreCase"] = "ignoreCase";
QUERY_OPTION["Then"] = "then";
})(QUERY_OPTION || (QUERY_OPTION = {}));
var IDB_MODE;
(function (IDB_MODE) {
IDB_MODE["ReadOnly"] = "readonly";
IDB_MODE["ReadWrite"] = "readwrite";
})(IDB_MODE || (IDB_MODE = {}));
var OCCURENCE;
(function (OCCURENCE) {
OCCURENCE["First"] = "f";
OCCURENCE["Last"] = "l";
OCCURENCE["Any"] = "a";
})(OCCURENCE || (OCCURENCE = {}));
var CONNECTION_STATUS;
(function (CONNECTION_STATUS) {
CONNECTION_STATUS["Connected"] = "connected";
CONNECTION_STATUS["Closed"] = "closed";
CONNECTION_STATUS["NotStarted"] = "not_started";
CONNECTION_STATUS["UnableToStart"] = "unable_to_start";
CONNECTION_STATUS["ClosedByJsStore"] = "closed_by_jsstore";
})(CONNECTION_STATUS || (CONNECTION_STATUS = {}));
;// ./src/worker/model/table_meta.ts
var TableMeta = /** @class */ (function () {
function TableMeta(table) {
this.columns = [];
this.autoIncColumnValue = {};
this.columns = this.setColumn(table.columns);
this.name = table.name;
this.alter = table.alter || {};
}
TableMeta.prototype.setColumn = function (tableColumns) {
var columns = [];
var _loop_1 = function (columnName) {
var column = tableColumns[columnName];
column.name = columnName;
if (column.autoIncrement) {
this_1.autoIncColumnValue[columnName] = 0;
}
if (column.primaryKey) {
this_1.primaryKey = columnName;
this_1.keypath = column.keyPath || columnName;
}
column.enableSearch = column.enableSearch == null ? true : column.enableSearch;
var existingColumnIndex = this_1.columns.indexOf(function (q) { return q.name === columnName; });
if (existingColumnIndex < 0) {
columns.push(column);
}
else {
var existingColumn = this_1.columns[existingColumnIndex];
Object.assign(existingColumn, column);
}
};
var this_1 = this;
for (var columnName in tableColumns) {
_loop_1(columnName);
}
return columns;
};
return TableMeta;
}());
;// ./src/worker/meta_helper.ts
var MetaHelper = /** @class */ (function () {
function MetaHelper() {
}
MetaHelper.autoIncrementKey = function (tableName, columnName) {
return "JsStore_".concat(tableName, "_").concat(columnName, "_Value");
};
MetaHelper.getStore = function (util) {
if (!util.tx) {
util.createTransaction([MetaHelper.tableName]);
}
return util.objectStore(MetaHelper.tableName);
};
MetaHelper.set = function (key, value, util) {
var store = MetaHelper.getStore(util);
return promise(function (res, rej) {
var req = store.put({
key: key,
value: value
});
req.onsuccess = function () {
res();
};
req.onerror = rej;
});
};
MetaHelper.get = function (key, util) {
var store = MetaHelper.getStore(util);
return promise(function (res, rej) {
var req = store.get(util.keyRange(key));
req.onsuccess = function () {
var result = req.result;
res(result && result.value);
};
req.onerror = rej;
});
};
MetaHelper.remove = function (key, util) {
var store = MetaHelper.getStore(util);
return promise(function (res, rej) {
var req = store.delete(util.keyRange(key));
req.onsuccess = function () {
res();
};
req.onerror = rej;
});
};
MetaHelper.has = function (key, util) {
var store = MetaHelper.getStore(util);
return promise(function (res, rej) {
var req = store.count(util.keyRange(key));
req.onsuccess = function () {
var result = req.result;
res(result > 0);
};
req.onerror = rej;
});
};
MetaHelper.tableName = "JsStore_Meta";
MetaHelper.dbSchema = "JsStore_DbSchema";
return MetaHelper;
}());
;// ./src/worker/model/db_meta.ts
var DbMeta = /** @class */ (function () {
function DbMeta(db) {
this.name = db.name;
this.version = db.version || 1;
db.tables.push({
name: MetaHelper.tableName,
columns: {
key: {
primaryKey: true
},
value: {
enableSearch: false
}
},
});
this.tables = db.tables.map(function (table) {
return new TableMeta(table);
});
}
return DbMeta;
}());
;// ./src/common/utils/for_obj.ts
var forObj = function (obj, cb) {
for (var key in obj) {
cb(key, obj[key]);
}
};
;// ./src/worker/utils/log_helper.ts
var LogHelper = /** @class */ (function () {
function LogHelper(type, info) {
this.type = type;
this.info_ = info;
this.message = this.getMsg_();
}
LogHelper.prototype.log = function (msg) {
if (this.status) {
console.log(msg);
}
};
LogHelper.prototype.throw = function () {
throw this.get();
};
LogHelper.prototype.logError = function () {
console.error(this.get());
};
LogHelper.prototype.get = function () {
return {
message: this.message,
type: this.type
};
};
LogHelper.prototype.warn = function () {
console.warn(this.get());
};
LogHelper.prototype.getMsg_ = function () {
var _a, _b;
var errMsg;
var info = this.info_;
var errorHandler = (_a = {},
_a[ERROR_TYPE.NotArray] = function () {
errMsg = "Supplied value is not an array";
},
_a[ERROR_TYPE.UndefinedColumn] = function () {
errMsg = "Column is undefined in Where";
},
_a[ERROR_TYPE.UndefinedValue] = function () {
errMsg = "Value is undefined in Where";
},
_a[ERROR_TYPE.UndefinedColumnName] = function () {
errMsg = "Column name is undefined '" + info['TableName'] + "'";
},
_a[ERROR_TYPE.UndefinedDbName] = function () {
errMsg = "Database name is not supplied";
},
_a[ERROR_TYPE.UndefinedColumnValue] = function () {
errMsg = "Column value is undefined";
},
_a[ERROR_TYPE.NoValueSupplied] = function () {
errMsg = "No value is supplied";
},
_a[ERROR_TYPE.InvalidOp] = function () {
errMsg = "Invalid Op Value '" + info['Op'] + "'";
},
_a[ERROR_TYPE.ColumnNotExist] = function () {
var column = info['column'];
errMsg = info['isOrder'] ?
( true && info.isJoin ?
"Column '".concat(column, "' in order query is invalid. Please use '<table>.<column>' format for specifying a column in join query.") :
"Column '".concat(column, "' in order query does not exist")) :
"Column '".concat(column, "' does not exist");
},
_a[ERROR_TYPE.NoIndexFound] = function () {
errMsg = "No index found for column '" + info['column'] + "'. Query can not be executed without index.";
},
_a[ERROR_TYPE.NullValue] = function () {
errMsg = "Null value is not allowed for column '" + info['ColumnName'] + "'";
},
_a[ERROR_TYPE.WrongDataType] = function () {
errMsg = "Expected data type for the column ".concat(info['column'], " is ").concat(info['expected'], ", but received a ").concat(info['received'], ".");
// errMsg = "Supplied value for column '" + info['column'] +
// "' have wrong data type";
},
_a[ERROR_TYPE.TableNotExist] = function () {
errMsg = "Table '" + info['tableName'] + "' does not exist";
},
_a[ERROR_TYPE.DbNotExist] = function () {
errMsg = "Database with name ".concat(info['dbName'], " does not exist");
},
_a[ERROR_TYPE.NotObject] = function () {
errMsg = "supplied value is not object";
},
_a[ERROR_TYPE.InvalidConfig] = function () {
errMsg = "Invalid Config '" + info['Config'] + " '";
},
_a[ERROR_TYPE.DbBlocked] = function () {
errMsg = "database is blocked, cant be deleted right now";
},
_a[ERROR_TYPE.NullValueInWhere] = function () {
errMsg = "Null/undefined is not allowed in where. Column '".concat(info['column'], "' has null");
},
_a[ERROR_TYPE.MethodNotExist] = function () {
errMsg = "method '".concat(info, "' does not exist.");
},
_a[ERROR_TYPE.IndexedDbNotSupported] = function () {
errMsg = "Browser does not support indexeddb";
},
_a.getInfo = function () {
errMsg = info;
},
_a[ERROR_TYPE.InvalidJoinQuery] = function () {
errorHandler.getInfo();
},
_a[ERROR_TYPE.ImportScriptsFailed] = function () {
errorHandler.getInfo();
},
_a[ERROR_TYPE.InvalidMiddleware] = function () {
errMsg = "No function ".concat(info, " is found.");
},
_a);
if (true) {
Object.assign(errorHandler, (_b = {},
_b[ERROR_TYPE.InvalidOrderQuery] = function () {
errorHandler.getInfo();
},
_b[ERROR_TYPE.InvalidGroupQuery] = function () {
errorHandler.getInfo();
},
_b[ERROR_TYPE.NoPrimaryKey] = function () {
errMsg = "No primary key exists for the query table. The query ".concat(JSON.stringify(info), " will not yield proper output.");
},
_b));
}
var errorType = this.type;
var method = errorHandler[errorType];
if (method) {
method();
}
else {
if (!errorType) {
this.type = ERROR_TYPE.Unknown;
}
errMsg = this.message;
}
return errMsg;
};
return LogHelper;
}());
;// ./src/worker/idbutil/index.ts
var IDBUtil = /** @class */ (function () {
function IDBUtil() {
this.logger = new LogHelper(null);
}
IDBUtil.prototype.emptyTx = function () {
if (!this.tx)
return;
this.tx.oncomplete = null;
this.tx.onabort = null;
this.tx.onerror = null;
this.tx = null;
};
IDBUtil.prototype.createTransactionIfNotExist = function (tables, mode) {
if (!this.tx) {
this.createTransaction(tables, mode);
}
};
IDBUtil.prototype.createTransaction = function (tables, mode) {
var _this = this;
if (mode === void 0) { mode = IDB_MODE.ReadWrite; }
this.tx = this.con.transaction(tables, mode);
return promise(function (res, rej) {
_this.tx.oncomplete = res;
_this.tx.onabort = res;
_this.tx.onerror = rej;
});
};
IDBUtil.prototype.keyRange = function (value, op) {
var keyRange;
switch (op) {
case QUERY_OPTION.Between:
keyRange = IDBKeyRange.bound(value.low, value.high, false, false);
break;
case QUERY_OPTION.GreaterThan:
keyRange = IDBKeyRange.lowerBound(value, true);
break;
case QUERY_OPTION.GreaterThanEqualTo:
keyRange = IDBKeyRange.lowerBound(value);
break;
case QUERY_OPTION.LessThan:
keyRange = IDBKeyRange.upperBound(value, true);
break;
case QUERY_OPTION.LessThanEqualTo:
keyRange = IDBKeyRange.upperBound(value);
break;
default:
keyRange = IDBKeyRange.only(value);
break;
}
return keyRange;
};
IDBUtil.prototype.objectStore = function (name) {
return this.tx.objectStore(name);
};
IDBUtil.prototype.abortTransaction = function () {
if (this.tx) {
this.tx.abort();
}
};
IDBUtil.prototype.close = function () {
var _this = this;
if (this.con) {
this.con.close();
}
// wait for 100 ms before success
return promise(function (res) {
_this.con = null;
setTimeout(res, 100);
});
};
IDBUtil.prototype.initDb = function (db) {
var _this = this;
var isDbCreated = false;
var dbVersion = db.version;
var oldVersion;
var initLogic = function (res, rej) {
var dbOpenRequest = indexedDB.open(db.name, dbVersion);
dbOpenRequest.onsuccess = function () {
_this.con = dbOpenRequest.result;
_this.con.onversionchange = function (e) {
// if (e.newVersion === null) { // An attempt is made to delete the db
e.target.close(); // Manually close our connection to the db
// }
};
res({
isCreated: isDbCreated,
oldVersion: oldVersion,
newVersion: dbVersion
});
};
dbOpenRequest.onerror = function (e) {
console.error("error", e);
rej(e);
};
dbOpenRequest.onupgradeneeded = function (e) {
oldVersion = e.oldVersion;
var target = e.target;
var upgradeConnection = target.result;
isDbCreated = true;
var transaction = target.transaction;
var storeNames = upgradeConnection.objectStoreNames;
var createObjectStore = function (table) {
var option = table.primaryKey ? {
keyPath: table.keypath,
} : {
autoIncrement: true
};
var store = upgradeConnection.createObjectStore(table.name, option);
table.columns.forEach(function (column) {
addColumn(store, column);
});
};
var addColumn = function (store, column) {
var columnName = column.name;
if (column.enableSearch && !store.indexNames.contains(columnName)) {
var options = column.primaryKey ? { unique: true } : { unique: column.unique };
options['multiEntry'] = column.multiEntry;
var keyPath = column.keyPath == null ? columnName : column.keyPath;
store.createIndex(columnName, keyPath, options);
}
};
var deleteColumn = function (store, table, columnName) {
var index = table.columns.findIndex(function (q) { return q.name === columnName; });
if (index >= 0) {
table.columns.splice(index, 1);
store.deleteIndex(columnName);
}
};
db.tables.forEach(function (table) {
if (!storeNames.contains(table.name)) {
createObjectStore(table);
}
var store = transaction.objectStore(table.name);
for (var i = oldVersion + 1; i <= dbVersion; i++) {
var alterQuery = table.alter[i];
if (alterQuery) {
// handle new column add
if (alterQuery.add) {
var newColumns = table.setColumn(alterQuery.add);
newColumns.forEach(function (column) {
addColumn(store, column);
table.columns.push(column);
});
}
// handle delete column add
forObj(alterQuery.drop || {}, (function (columnName) {
deleteColumn(store, table, columnName);
}));
// handle modify column
forObj(alterQuery.modify || {}, (function (columnName, column) {
var shouldDelete = column.multiEntry || column.keyPath || column.unique;
var targetColumn = table.columns.find(function (q) { return q.name === columnName; });
var newColumn = Object.assign(targetColumn, column);
newColumn.name = columnName;
if (shouldDelete) {
deleteColumn(store, table, columnName);
addColumn(store, newColumn);
table.columns.push(newColumn);
}
}));
}
}
});
var _loop_1 = function (i, length_1) {
var storeName = storeNames.item(i);
var tableIndex = db.tables.findIndex(function (qry) { return qry.name === storeName; });
if (tableIndex < 0) {
upgradeConnection.deleteObjectStore(storeName);
}
};
for (var i = 0, length_1 = storeNames.length; i < length_1; i++) {
_loop_1(i, length_1);
}
};
};
return promise(initLogic);
};
return IDBUtil;
}());
;// ./src/common/utils/promise_all.ts
var promiseAll = function (promises) {
return Promise.all(promises);
};
;// ./src/worker/utils/promise_reject.ts
var promiseReject = function (value) {
return Promise.reject(value);
};
;// ./src/worker/utils/get_error.ts
var getError = function (e) {
var customError = e instanceof LogHelper;
if (customError) {
e.logError();
return e.get();
}
else {
var error = void 0;
if (e.name) {
error = new LogHelper(e.name);
error.message = e.message;
}
else {
error = new LogHelper(e.target.error.name);
error.message = e.target.error.message;
}
if (true) {
error.logError();
}
return error.get();
}
};
;// ./src/worker/utils/get_error_from_exception.ts
var getErrorFromException = function (ex, type) {
if (type === void 0) { type = ERROR_TYPE.InvalidQuery; }
ex.name = type;
return getError(ex);
};
;// ./src/worker/executors/base.ts
var Base = /** @class */ (function () {
function Base() {
this.rowAffected = 0;
this.isTxQuery = false;
this.results = [];
}
Object.defineProperty(Base.prototype, "db", {
get: function () {
return this.util.db;
},
enumerable: false,
configurable: true
});
Base.prototype.table = function (name) {
var tableName = name || this.tableName;
var table = this.db.tables.find(function (q) { return q.name === tableName; });
if (true) {
if (!table) {
console.warn("No table found with name ".concat(tableName));
}
}
return table;
};
Base.prototype.primaryKey = function (tableName) {
var query = this.query;
if (!query.from && query.store && query.meta) {
var primaryKey = query.meta.primaryKey;
if (true) {
if (primaryKey == null) {
delete query.store;
console.warn("no primary key found for query - ".concat(JSON.stringify(this.query)));
}
}
return primaryKey;
}
var table = this.table(tableName);
if (true) {
if (table == null && query.store) {
delete query.store;
var metaValue = query.meta;
if (!metaValue || !metaValue.primaryKey) {
console.warn("no primary key found for query - ".concat(JSON.stringify(this.query), ". Please supply primary key in meta field."));
}
}
}
return table.primaryKey;
};
Base.prototype.getColumnInfo = function (columnName, tableName) {
return this.table(tableName).columns.find(function (column) { return column.name === columnName; });
};
Base.prototype.onException = function (ex, type) {
console.error(ex);
this.util.abortTransaction();
return promiseReject(getErrorFromException(ex, type));
};
return Base;
}());
;// ./src/worker/utils/get_data_type.ts
var getDataType = function (value) {
if (value == null) {
return DATA_TYPE.Null;
}
var type = typeof value;
switch (type) {
case 'object':
if (Array.isArray(value)) {
return DATA_TYPE.Array;
}
if (value instanceof Date) {
return DATA_TYPE.DateTime;
}
}
return type;
};
;// ./src/worker/utils/is_null.ts
var isNull = function (value) {
if (value == null) {
return true;
}
else {
switch (typeof value) {
// case 'string': return value.length === 0;
case 'number': return isNaN(value);
}
}
return false;
};
;// ./src/worker/executors/insert/values_checker.ts
var ValuesChecker = /** @class */ (function () {
function ValuesChecker(table, autoIncValues) {
this.table = table;
this.autoIncrementValue = autoIncValues;
}
ValuesChecker.prototype.checkAndModifyValues = function (query) {
var _this = this;
var err;
this.query = query;
var values = query.values;
var ignoreIndexes = [];
values.every(function (item, index) {
err = _this.checkAndModifyValue(item);
if (query.ignore && err) {
ignoreIndexes.push(index);
err = null;
}
return err ? false : true;
});
ignoreIndexes.forEach(function (index) {
values.splice(index, 1);
});
return { err: err, values: values };
};
ValuesChecker.prototype.checkAndModifyValue = function (value) {
var _this = this;
var error;
this.table.columns.every(function (column) {
error = _this.checkAndModifyColumnValue_(column, value);
return error ? false : true;
});
return error;
};
ValuesChecker.prototype.checkNotNullAndDataType_ = function (column, value) {
// check not null schema
if (column.notNull && isNull(value[column.name])) {
return this.getError(ERROR_TYPE.NullValue, { ColumnName: column.name });
}
// check datatype
else if (column.dataType && !isNull(value[column.name])) {
var receivedType = getDataType(value[column.name]);
if (receivedType !== column.dataType) {
return this.getError(ERROR_TYPE.WrongDataType, { column: column.name, expected: column.dataType, received: receivedType });
}
}
};
ValuesChecker.prototype.checkAndModifyColumnValue_ = function (column, value) {
var columnValue = value[column.name];
// check auto increment scheme
if (column.autoIncrement) {
// if value is null, then create the autoincrement value
if (isNull(columnValue)) {
value[column.name] = ++this.autoIncrementValue[column.name];
}
else {
if (getDataType(columnValue) === DATA_TYPE.Number) {
// if column value is greater than autoincrement value saved, then make the
// column value as autoIncrement value
if (columnValue > this.autoIncrementValue[column.name]) {
this.autoIncrementValue[column.name] = columnValue;
}
}
}
}
// check Default Schema
else if (column.default !== undefined && isNull(columnValue)) {
value[column.name] = column.default;
}
var query = this.query;
if (query.validation) {
return this.checkNotNullAndDataType_(column, value);
}
};
ValuesChecker.prototype.getError = function (error, details) {
return new LogHelper(error, details);
};
return ValuesChecker;
}());
;// ./src/worker/executors/update/schema_checker.ts
var SchemaChecker = /** @class */ (function () {
function SchemaChecker(table) {
this.table = table;
}
SchemaChecker.prototype.check = function (setValue, tblName) {
var _this = this;
var log;
if (typeof setValue === DATA_TYPE.Object) {
if (this.table) {
// loop through table column and find data is valid
this.table.columns.every(function (column) {
if (column.name in setValue) {
log = _this.checkByColumn_(column, setValue[column.name]);
}
return log ? false : true;
});
}
else {
log = new LogHelper(ERROR_TYPE.TableNotExist, { tableName: tblName });
}
}
else {
log = new LogHelper(ERROR_TYPE.NotObject);
}
return log;
};
SchemaChecker.prototype.checkByColumn_ = function (column, value) {
// check not null schema
if (column.notNull === true && isNull(value)) {
return new LogHelper(ERROR_TYPE.NullValue, { ColumnName: column.name });
}
// check datatype
var type = getDataType(value);
var checkFurther = value != null;
if (column.dataType && checkFurther) {
if (type !== column.dataType && type !== 'object') {
return new LogHelper(ERROR_TYPE.WrongDataType, { column: column.name, expected: column.dataType, received: type });
}
}
// check allowed operators
if (checkFurther && type === 'object') {
var allowedOp = ['+', '-', '*', '/', '{push}'];
for (var prop in value) {
if (allowedOp.indexOf(prop) < 0 && column.dataType && type !== column.dataType) {
return new LogHelper(ERROR_TYPE.WrongDataType, { column: column.name, expected: column.dataType, received: type });
}
}
}
};
return SchemaChecker;
}());
;// ./src/worker/executors/query_helper.ts
var QueryHelper = /** @class */ (function () {
function QueryHelper(dbSchema) {
this.db = dbSchema;
}
QueryHelper.prototype.validate = function (api, query) {
switch (api) {
case API.Select:
case API.Remove:
case API.Count:
return this.checkSelect(query);
case API.Insert:
return this.checkInsertQuery(query);
case API.Update:
return this.checkUpdate(query);
}
};
QueryHelper.prototype.getTable_ = function (tableName) {
return this.db.tables.find(function (q) { return q.name === tableName; });
};
QueryHelper.prototype.isInsertQryValid = function (query) {
var table = this.getTable_(query.into);
var log;
if (table) {
switch (getDataType(query.values)) {
case DATA_TYPE.Array:
break;
case DATA_TYPE.Null:
log = new LogHelper(ERROR_TYPE.NoValueSupplied);
break;
default:
log = new LogHelper(ERROR_TYPE.NotArray);
}
}
else {
log = new LogHelper(ERROR_TYPE.TableNotExist, { tableName: query.into });
}
return {
table: table,
log: log
};
};
QueryHelper.prototype.checkUpdate = function (query) {
var err = new SchemaChecker(this.getTable_(query.in)).
check(query.set, query.in);
if (err)
return err;
if (query.where != null) {
err = this.checkForNullInWhere_(query);
if (err)
return err;
this.addGreatAndLessToNotOp_(query);
}
};
QueryHelper.prototype.checkSelect = function (query) {
if (!query.store) {
var table = this.getTable_(query.from);
if (!table) {
return new LogHelper(ERROR_TYPE.TableNotExist, { tableName: query.from });
}
}
if (query.where) {
var err = this.checkForNullInWhere_(query);
if (err)
return err;
this.addGreatAndLessToNotOp_(query);
}
};
QueryHelper.prototype.checkForNullInWhere_ = function (query) {
for (var columnName in query.where) {
if (query.where[columnName] == null) {
return new LogHelper(ERROR_TYPE.NullValueInWhere, { column: columnName });
}
}
};
QueryHelper.prototype.addGreatAndLessToNotOp_ = function (query) {
var whereQuery = query.where;
var containsNot = function (qry, keys) {
return keys.findIndex(function (key) { return qry[key][QUERY_OPTION.NotEqualTo] != null; }) >= 0;
};
var addToSingleQry = function (qry, keys) {
var value;
keys.forEach(function (prop) {
value = qry[prop];
if (value[QUERY_OPTION.NotEqualTo] != null) {
qry[prop][QUERY_OPTION.GreaterThan] = value[QUERY_OPTION.NotEqualTo];
if (qry[QUERY_OPTION.Or] === undefined) {
qry[QUERY_OPTION.Or] = {};
qry[QUERY_OPTION.Or][prop] = {};
}
else if (qry[QUERY_OPTION.Or][prop] === undefined) {
qry[QUERY_OPTION.Or][prop] = {};
}
qry[QUERY_OPTION.Or][prop][QUERY_OPTION.LessThan] = value[QUERY_OPTION.NotEqualTo];
delete qry[prop][QUERY_OPTION.NotEqualTo];
}
});
return qry;
};
switch (getDataType(whereQuery)) {
case DATA_TYPE.Object:
var queryKeys = Object.keys(whereQuery);
if (containsNot(whereQuery, queryKeys)) {
if (queryKeys.length === 1) {
query.where = addToSingleQry(whereQuery, queryKeys);
}
else {
var whereTmpQry_1 = [];
queryKeys.forEach(function (prop) {
var _a;
whereTmpQry_1.push(addToSingleQry((_a = {}, _a[prop] = whereQuery[prop], _a), [prop]));
});
query.where = whereTmpQry_1;
}
}
break;
default:
var whereTmp_1 = [];
whereQuery.forEach(function (qry) {
var qryKeys = Object.keys(qry);
if (containsNot(qry, qryKeys)) {
qry = addToSingleQry(qry, qryKeys);
}
whereTmp_1.push(qry);
});
query.where = whereTmp_1;
}
};
QueryHelper.prototype.checkInsertQuery = function (query) {
var validResult = this.isInsertQryValid(query);
var table = validResult.table;
var error = validResult.log;
if (error)
return error;
if (query.skipDataCheck)
return;
var valueCheckerInstance = new ValuesChecker(table, table.autoIncColumnValue);
var _a = valueCheckerInstance.checkAndModifyValues(query), values = _a.values, err = _a.err;
query.values = values;
return err;
};
return QueryHelper;
}());
;// ./src/worker/executors/insert/index.ts
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Insert = /** @class */ (function (_super) {
__extends(Insert, _super);
function Insert(query, util) {
var _this = _super.call(this) || this;
_this.valuesAffected_ = [];
if (query.validation == null) {
query.validation = true;
}
_this.query = query;
_this.util = util;
_this.tableName = query.into;
return _this;
}
Insert.prototype.execute = function (beforeInsert) {
var _this = this;
var db = this.db;
var err = new QueryHelper(db).validate(API.Insert, this.query);
if (err)
return promiseReject(err);
return beforeInsert().then(function (_) {
return _this.insertData_(db).then(function (_) {
return _this.query.return ? _this.valuesAffected_ : _this.rowAffected;
});
}).catch(function (err) {
_this.util.abortTransaction();
return promiseReject(err);
});
};
Insert.prototype.insertData_ = function (db) {
var _this = this;
var onInsertData;
var addMethod;
var query = this.query;
if (query.return) {
onInsertData = function (value) {
_this.valuesAffected_.push(value);
};
}
else {
onInsertData = function (value) {
++_this.rowAffected;
};
}
addMethod = (function () {
var idbMethod = query.upsert ? "put" : "add";
if (query.ignore && !_this.isTxQuery) {
return function (value) {
var tx = _this.util.con.transaction(query.into, IDB_MODE.ReadWrite);
var objectStore = tx.objectStore(query.into);
return objectStore[idbMethod](value);
};
}
if (!_this.isTxQuery) {
_this.util.createTransaction([query.into, MetaHelper.tableName]);
}
_this.objectStore = _this.util.objectStore(_this.tableName);
return function (value) {
return _this.objectStore[idbMethod](value);
};
})();
return promiseAll(query.values.map(function (value) {
return promise(function (res, rej) {
var addResult = addMethod(value);
addResult.onerror = function (err) {
if (query.ignore) {
res();
}
else {
rej(err);
}
};
addResult.onsuccess = function () {
onInsertData(value);
res();
};
});
})).then(function () {
return MetaHelper.set(MetaHelper.dbSchema, db, _this.util);
});
};
return Insert;
}(Base));
;// ./src/worker/utils/set_cross_browser_idb.ts
var setCrossBrowserIndexedDb = function () {
try {
if (!indexedDB) {
indexedDB = self.mozIndexedDB ||
self.webkitIndexedDB || self.msIndexedDB;
}
if (indexedDB) {
IDBTransaction = IDBTransaction ||
self.webkitIDBTransaction || self.msIDBTransaction;
self.IDBKeyRange = self.IDBKeyRange ||
self.webkitIDBKeyRange || self.msIDBKeyRange;
}
else {
return false;
}
}
catch (ex) {
return false;
}
return true;
};
;// ./src/worker/constants/index.ts
var IS_WORKER = typeof self.alert === 'undefined' && typeof ServiceWorkerGlobalScope === 'undefined';
var IS_IDB_SUPPORTED = setCrossBrowserIndexedDb();
;// ./src/worker/utils/is_array.ts
var isArray = function (value) {
return Array.isArray(value);
};
;// ./src/worker/utils/is_object.ts
var isObject = function (value) {
return typeof value === 'object';
};
;// ./src/worker/utils/get_keys.ts
var getKeys = function (value) {
return Object.keys(value);
};
;// ./src/worker/utils/get_length.ts
var getLength = function (value) {
return getKeys(value).length;
};
;// ./src/worker/executors/select/base_select.ts
var setPushResult = function () {
var _this = this;
var caseQuery = this.query.case;
if (caseQuery) {
this.pushResult = function (value) {
var columnName;
_this.thenEvaluator.setCaseAndValue(caseQuery, value);
for (columnName in caseQuery) {
value[columnName] = _this.thenEvaluator.setColumn(columnName).evaluate();
}
_this.results.push(value);
};
}
else {
this.pushResult = function (value) {
_this.results.push(value);
};
}
};
var setLimitAndSkipEvaluationAtEnd = function () {
if (this.query.limit) {
this.limitAtEnd = true;
}
if (this.query.skip) {
this.skipAtEnd = true;
}
};
var mergeWithResults = function (from) {
var datas = this.results;
var key = this.primaryKey();
if ( true && !key) {
new LogHelper(ERROR_TYPE.NoPrimaryKey, this.query).warn();
}
var lookupObject = new Map();
datas.forEach(function (data) {
lookupObject.set(data[key], 1);
});
from.forEach(function (item) {
if (!lookupObject.has(item[key])) {
datas.push(item);
}
});
};
;// ./src/worker/executors/select/then_evaluator.ts
var ThenEvaluator = /** @class */ (function () {
function ThenEvaluator() {
}
ThenEvaluator.prototype.setCaseAndValue = function (caseQuery, value) {
this.caseQuery_ = caseQuery;
this.setValue(value);
};
ThenEvaluator.prototype.setCaseAndColumn = function (caseQuery, columnName) {
this.caseQuery_ = caseQuery;
this.setColumn(columnName);
return this;
};
ThenEvaluator.prototype.setColumn = function (columnName) {
this.columnName_ = columnName;
this.caseColumnQuery_ = this.caseQuery_[this.columnName_];
this.length_ = this.caseColumnQuery_.length;
return this;
};
ThenEvaluator.prototype.setValue = function (value) {
this.value = value;
return this;
};
ThenEvaluator.prototype.evaluate = function () {
for (var i = 0; i < this.length_; i++) {
if (this.checkCase_(this.caseColumnQuery_[i]) === true) {
return this.caseColumnQuery_[i].then;
}
}
var lastThen = this.caseColumnQuery_[this.length_ - 1].then;
return lastThen == null ? this.value[this.columnName_] : lastThen;
};
ThenEvaluator.prototype.checkCase_ = function (cond) {
var queryOption;
for (queryOption in cond) {
switch (queryOption) {
case QUERY_OPTION.GreaterThan:
if (this.value[this.columnName_] > cond[queryOption]) {
return true;
}
break;
case QUERY_OPTION.Equal:
if (this.value[this.columnName_] === cond[queryOption]) {
return true;
}
break;
case QUERY_OPTION.LessThan:
if (this.value[this.columnName_] < cond[queryOption]) {
return true;
}
break;
case QUERY_OPTION.GreaterThanEqualTo:
if (this.value[this.columnName_] >= cond[queryOption]) {
return true;
}
break;
case QUERY_OPTION.LessThanEqualTo:
if (this.value[this.columnName_] <= cond[queryOption]) {
return true;
}
break;
case QUERY_OPTION.NotEqualTo:
if (this.value[this.columnName_] !== cond[queryOption]) {
return true;
}
break;
case QUERY_OPTION.Between:
if (this.value[this.columnName_] > cond[queryOption].low && this.value[this.columnName_] < cond[queryOption].high) {
return true;
}
break;
}
return false;
}
};
return ThenEvaluator;
}());
;// ./src/worker/executors/select/where.ts
var getCursorOnSuccess = function (simpleFn, limitFn, skipFn, skipAndLimitFn) {
if (this.limitAtEnd === false && this.skipAtEnd === false) {
if (this.skipRecord) {
return this.limitRecord ? skipAndLimitFn : skipFn;
}
if (this.limitRecord) {
return limitFn;
}
}
return simpleFn;
};
var executeWhereLogic = function (column, value, op, dir) {
var _this = this;
value = op ? value[op] : value;
var cursorRequest = this.objectStore.index(column).openCursor(this.util.keyRange(value, op), dir);
var onSuccess = getCursorOnSuccess.call(this, executeSimpleForWhere_, executeLimitForWhere_, executeSkipForWhere_, executeSkipAndLimitForWhere_);
return promise(function (res, rej) {
cursorRequest.onerror = rej;
cursorRequest.onsuccess = onSuccess.call(_this, res);
});
};
var executeSkipAndLimitForWhere_ = function (onFinish) {
var _this = this;
var recordSkipped = false;
return function (e) {
var cursor = e.target.result;
if (cursor) {
if (recordSkipped && _this.results.length !== _this.limitRecord) {
if (_this.shouldAddValue(cursor)) {
_this.pushResult(cursor.value);
}
cursor.continue();
}
else {
recordSkipped = true;
cursor.advance(_this.skipRecord);
}
}
else {
onFinish();
}
};
};
var executeSkipForWhere_ = function (onFinish) {
var _this = this;
var recordSkipped = false;
return function (e) {
var cursor = e.target.result;
if (cursor) {
if (recordSkipped) {
if (_this.s