@xuda.io/runtime-bundle
Version:
The Xuda Runtime Bundle refers to a collection of scripts and libraries packaged together to provide the necessary runtime environment for executing plugins or components in the Xuda platform.
894 lines (790 loc) • 28.1 kB
JavaScript
const _this = {};
export const init_module = async (e) => {
_this.func = e.func;
_this.glb = e.glb;
_this.SESSION_OBJ = e.SESSION_OBJ;
_this.APP_OBJ = e.APP_OBJ;
_this.IS_DOCKER = e.IS_DOCKER;
_this.IS_API_SERVER = e.IS_API_SERVER;
_this.IS_PROCESS_SERVER = e.IS_PROCESS_SERVER;
if (!_this.xuda_dbs_plugin && typeof _this.IS_DOCKER === 'undefined' && typeof _this.IS_PROCESS_SERVER === 'undefined' && typeof _this.IS_API_SERVER === 'undefined') {
await init_xuda_dbs_plugin(e.SESSION_ID);
}
_this.db_replication_store;
_this.db_changes_store;
_this.db_replication_from_stat = 3;
_this.db_replication_to_stat = 3;
};
export let _db = {};
_db.save_data = async function (SESSION_ID, dsSessionP, keyP) {
// const app_id = _this.SESSION_OBJ[SESSION_ID].app_id;
var db_driver = await this.get_db_driver(SESSION_ID, dsSessionP);
if (db_driver === 'pouchdb' && _this.glb.IS_WORKER) {
var callback_id = _this.func.utils.set_callback_queue(SESSION_ID, callbackP);
var obj = _this.func.utils.clean_returned_datasource(SESSION_ID, dsSessionP);
return _this.func.utils.post_back_to_client(SESSION_ID, 'execute_local_sava_data', _this.SESSION_OBJ[SESSION_ID].worker_id, {
ds_obj: obj,
dsSessionP: dsSessionP,
keyP: keyP,
callback_id: callback_id,
});
}
_db.save_indicator(SESSION_ID, true);
var _ds = _this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];
let _view_obj = await _this.func.utils.VIEWS_OBJ.get(SESSION_ID, _ds.prog_id);
var dataSourceTableId = _view_obj?.progDataSource?.dataSourceTableId;
if (!dataSourceTableId) {
_db.save_indicator(SESSION_ID, false);
_this.func.utils.alerts.invoke(SESSION_ID, 'system_msg', 'SYS_MSG_0105'); //Table entry missing
return;
}
var db_driver = await _db.get_db_driver(SESSION_ID, dsSessionP);
let table_ret = await _this.func.utils.FILES_OBJ.get(SESSION_ID, dataSourceTableId);
if (!table_ret.tableIndexes || _.isEmpty(table_ret.tableIndexes)) {
_db.save_indicator(SESSION_ID, false);
_this.func.utils.alerts.invoke(SESSION_ID, 'system_msg', 'SYS_MSG_0104'); //index missing
return;
}
if (!_ds.data_feed.rows) {
return console.error('data_feed rows is empty');
}
const clean_virtual_fields = async function (table_id, data) {
let table_obj = await func.utils.VIEWS_OBJ.get(SESSION_ID, table_id);
var data_obj = {};
for (const [key, val] of Object.entries(data)) {
const _tableFieldsObj = func.common.find_item_by_key(table_obj.tableFields, 'field_id', key);
if (_tableFieldsObj) {
data_obj[key] = val;
}
}
return data_obj;
};
let save_ret;
// component
if (_view_obj.properties.menuType === 'component') {
if (_view_obj?.properties?.rwMode !== 'U') {
return _this.func.utils.alerts.invoke(SESSION_ID, 'system_msg', 'SYS_MSG_0126'); //Program Read Only
}
// check if rows exist
// ==============
// add
//===============
let data = { prog_id: _ds.prog_id };
if (_ds.data_feed.rows_added?.length) {
if (!_view_obj?.properties?.allowCreate) {
_this.func.utils.alerts.invoke(SESSION_ID, 'system_msg', 'SYS_MSG_0120'); //Create Mode Denied
}
_.forEach(_ds.data_feed.rows_added, function (val, key) {
data[key] = val;
});
delete _ds.data_feed.rows_added['newRecord'];
save_ret = await _this.func.common.db(SESSION_ID, 'dbs_create', data, {}, dsSessionP);
refresh_document_changes_for_realtime_update(SESSION_ID, {
row_id: save_ret.data.id,
table_id: dataSourceTableId,
});
return save_ret;
}
// ==============
// delete
//===============
if (_ds.data_feed.rows_deleted?.length) {
data.table_id = _ds._dataSourceTableId;
data.ids = [];
for await (const [key, val] of Object.entries(_ds.data_feed.rows_deleted)) {
data.ids.push(val);
try {
const row_idx = func.common.find_ROWID_idx(_ds, val);
delete _ds.data_feed.rows[row_idx];
} catch (error) {}
}
_ds.data_feed.rows_deleted = [];
save_ret = await _this.func.common.db(SESSION_ID, 'dbs_delete', data, {}, dsSessionP);
refresh_document_changes_for_realtime_update(SESSION_ID, {
row_id: save_ret.data?.id?.[0],
table_id: dataSourceTableId,
});
return save_ret;
}
// ==============
// update
//===============
if (_ds.data_feed.rows_changed?.length) {
for await (const [key, row_id] of Object.entries(_ds.data_feed.rows_changed)) {
if (row_id === 'datasource_main') continue;
let data = { prog_id: _ds.prog_id };
try {
const row_idx = func.common.find_ROWID_idx(_ds, row_id);
data.table_data = await clean_virtual_fields(_ds._dataSourceTableId, _ds.data_feed.rows[row_idx]);
} catch (err) {
console.error(err);
}
data.table_id = _ds._dataSourceTableId;
data.row_id = row_id;
save_ret = await _this.func.common.db(SESSION_ID, 'dbs_update', data, {}, dsSessionP);
refresh_document_changes_for_realtime_update(SESSION_ID, {
row_id: save_ret.data?.id?.[0],
table_id: dataSourceTableId,
});
}
return save_ret;
}
return;
}
// alert Program Read Only
if (_view_obj.properties.menuType !== 'set_data') {
return _this.func.utils.alerts.invoke(SESSION_ID, 'system_msg', 'SYS_MSG_0126'); //Program Read Only
}
// set_data
var mode = _ds.set_mode; //screenInfo.crudMode;
if (!mode || mode === 'U') {
let data = { prog_id: _ds.prog_id };
data.table_id = _ds._dataSourceTableId;
data.row_id = _ds.currentRecordId;
data.table_data = {};
try {
const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
data.table_data = await clean_virtual_fields(_ds._dataSourceTableId, _ds.data_feed.rows[row_idx]);
} catch (err) {
console.error(err);
}
save_ret = await _this.func.common.db(SESSION_ID, 'dbs_update', data, {}, dsSessionP);
refresh_document_changes_for_realtime_update(SESSION_ID, {
row_id: save_ret.data?.id?.[0],
table_id: dataSourceTableId,
});
}
if (mode === 'D') {
// _id = _ds.key._id;
let data = { prog_id: _ds.prog_id };
data.table_id = _ds._dataSourceTableId;
data.ids = [_ds.currentRecordId];
save_ret = await _this.func.common.db(SESSION_ID, 'dbs_delete', data, {}, dsSessionP);
refresh_document_changes_for_realtime_update(SESSION_ID, {
row_id: save_ret.data?.id?.[0],
table_id: dataSourceTableId,
});
return save_ret;
}
if (mode === 'C') {
if (_view_obj.properties.crudMode !== 'C' && _view_obj.properties.crudMode === 'U' && !_view_obj.properties.allowCreate) {
return _this.func.utils.alerts.invoke(SESSION_ID, 'system_msg', 'SYS_MSG_0120'); //Create Mode Denied
}
let data = { prog_id: _ds.prog_id };
data.table_id = _ds._dataSourceTableId;
try {
const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
data.table_data = _ds.data_feed.rows[row_idx];
save_ret = await _this.func.common.db(SESSION_ID, 'dbs_create', data, {}, dsSessionP);
refresh_document_changes_for_realtime_update(SESSION_ID, {
row_id: save_ret.data.id,
table_id: dataSourceTableId,
});
return save_ret;
} catch (err) {
console.error(err);
}
}
};
_db.get_db_driver = async function (SESSION_ID, dsSessionP) {
var db_driver;
if (dsSessionP) {
var _ds = _this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];
let _view_obj = await _this.func.utils.VIEWS_OBJ.get(SESSION_ID, _ds.prog_id);
var dataSourceTableId = _view_obj?.progDataSource?.dataSourceTableId;
if (!dataSourceTableId) {
_this.func.utils.alerts.invoke(SESSION_ID, 'system_msg', 'SYS_MSG_0105'); //Table repository missing
return;
}
let file_ret = await _this.func.utils.FILES_OBJ.get(SESSION_ID, dataSourceTableId);
db_driver = file_ret.properties.db_driver || 'xuda';
}
if (_this.SESSION_OBJ[SESSION_ID].engine_mode === 'live_preview' && !db_driver && _this.SESSION_OBJ[SESSION_ID].app_id === 'temp') {
db_driver = 'pouchdb';
}
return db_driver;
};
_db.get_query = async function (
SESSION_ID,
table_id,
queryP,
dsSessionP,
viewSourceDescP,
sourceP,
reduceP,
skipP,
limitP,
countP,
idsP,
sortModel,
sort_dir,
filterModel = {
filterModelNative,
filterModelMongo,
filterModelSql,
filterModelUserMongo,
filterModelUserSql,
},
dataSourceFilterModelType = 'index',
total_fields_info,
) {
const get_fields = async function (_ds) {
var fields = [];
const _view_obj = await _this.func.utils.VIEWS_OBJ.get(SESSION_ID, _ds.prog_id);
if (_view_obj.progFields) {
for (let val of _view_obj.progFields) {
if (val.data.type === 'table') {
fields.push(val.data.field_id);
}
}
}
return fields;
};
const run_local = async function () {
if (!_this.SESSION_OBJ[SESSION_ID]) return;
if (!_this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP]) return;
var ds = _this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP];
var v = ds.v;
var query_string;
if (queryP.indexId) {
if (countP && queryP.desc) {
query_string = `startkey=${JSON.stringify(queryP.endkey)}&endkey=${JSON.stringify(queryP.startkey)}`;
} else {
query_string = `startkey=${JSON.stringify(queryP.startkey)}&endkey=${JSON.stringify(queryP.endkey)}&desc=${queryP.desc}`;
}
} else {
query_string = 'key=' + queryP.table_id;
}
var db_driver = await _db.get_db_driver(SESSION_ID, dsSessionP);
var fields_arr = await get_fields(ds);
const response = {
success: async function (json) {
if (dsSessionP && !_this.SESSION_OBJ[SESSION_ID]?.DS_GLB?.[dsSessionP]) {
return;
}
if (json.code < 0) {
response.error(json.data);
return;
}
var data = json.data;
// if (!countP)
// //!reduceP &&
// data = {
// rows: data.rows.map((item) => ({
// ...item.value,
// _ROWID: item.id,
// })),
// };
// const get_locate = function (data) {
// var ret = false;
// _this.$_each2(data, function (key, val) {
// if (
// val >= v.locateQuery.startkey[2][key] &&
// val <= v.locateQuery.endkey[2][key]
// ) {
// ret = true;
// } else {
// ret = false;
// return;
// }
// });
// return ret;
// };
if (dsSessionP)
_this.func.utils.debug.log(SESSION_ID, ds._dataSourceTableId, {
module: ds.viewModule,
action: 'read',
prop: sourceP,
details: query_string,
result: data.rows ? data.rows.length : 0,
error: null,
source: viewSourceDescP,
json: data,
fields: _.assignIn(ds.locate_from, ds.locate_to),
type: 'file',
dsSession: dsSessionP,
});
return data;
},
error: async function (err) {
if (dsSessionP && !ds) return;
if (dsSessionP) {
var err_msg = err && err.data ? err.data : err;
_this.func.utils.debug.log(SESSION_ID, _this.SESSION_OBJ[SESSION_ID].DS_GLB[dsSessionP]._dataSourceTableId, {
module: ds.viewModule,
action: 'read',
prop: sourceP,
details: query_string,
result: null,
error: err_msg,
source: viewSourceDescP,
json: null,
fields: _.assignIn(ds.locate_from, ds.locate_to),
type: 'file',
dsSession: dsSessionP,
});
}
_this.func.utils.debug_report(SESSION_ID, 'datasource couchDB query ' + sourceP, err_msg, 'E');
return {
rows: [],
error: true,
};
},
};
var data = {
desc: queryP.desc,
indexId: queryP.indexId,
key: queryP.table_id,
reduce: reduceP,
viewSourceDesc: viewSourceDescP,
limit: limitP,
skip: skipP,
count: countP,
ids: idsP,
table_id: queryP.table_id,
prog_id: ds.prog_id,
};
data.filter_from = JSON.stringify(queryP.filter_from);
data.filter_to = JSON.stringify(queryP.filter_to);
data.sortOrder = queryP.sortOrder;
data.table_id = queryP.table_id;
data.startkey = JSON.stringify(queryP.startkey);
data.endkey = JSON.stringify(queryP.endkey);
if (countP && queryP.desc) {
data.sortOrder = 'asc';
data.startkey = JSON.stringify(queryP.endkey);
data.endkey = JSON.stringify(queryP.startkey);
}
data.dataSourceFilterModelType = dataSourceFilterModelType;
// if (dataSourceFilterModelType === "query") {
if (sortModel) {
data.sortModel = JSON.stringify(sortModel);
data.sort_dir = sort_dir;
}
if (!_.isEmpty(filterModel?.filterModelNative)) {
data.filterModelNative = JSON.stringify(filterModel.filterModelNative);
}
if (!_.isEmpty(filterModel?.filterModelMongo)) {
data.filterModelMongo = JSON.stringify(filterModel.filterModelMongo);
}
if (filterModel?.filterModelSql) {
data.filterModelSql = JSON.stringify(filterModel.filterModelSql);
}
if (!_.isEmpty(filterModel?.filterModelUserMongo)) {
data.filterModelUserMongo = JSON.stringify(filterModel.filterModelUserMongo);
}
if (filterModel?.filterModelUserSql) {
data.filterModelUserSql = JSON.stringify(filterModel.filterModelUserSql);
}
// }
if (total_fields_info) {
data.total_fields_info = JSON.stringify(total_fields_info);
}
if (!reduceP && !countP) {
data.fields = fields_arr; //[];
}
try {
const json = await _this.func.common.db(SESSION_ID, 'dbs_read', data, { node: true }, dsSessionP);
return await response.success(json);
} catch (e) {
return await response.error(e?.message || e?.data || e);
}
};
var db_driver = await this.get_db_driver(SESSION_ID, dsSessionP);
if (db_driver === 'pouchdb' && _this.glb.IS_WORKER && !_this.SESSION_OBJ[SESSION_ID].engine_mode === 'live_preview') {
var callback_id = _this.func.utils.set_callback_queue(SESSION_ID, callbackP);
var obj = _this.func.utils.clean_returned_datasource(SESSION_ID, dsSessionP);
return _this.func.utils.post_back_to_client(SESSION_ID, 'execute_local_db_query', _this.SESSION_OBJ[SESSION_ID].worker_id, {
ds_obj: obj,
dsSessionP,
table_id,
queryP,
dsSessionP,
viewSourceDescP,
sourceP,
reduceP,
skipP,
limitP,
countP,
idsP,
callback_id,
});
}
return await run_local();
};
_db.utils = {};
_db.save_indicator = function (SESSION_ID, stateP) {
if (!_this.glb.IS_WORKER) {
_this.func.UI.utils.save(SESSION_ID, stateP);
}
};
// _db.save_image = function (SESSION_ID, filename, base64) {
// var response = {
// success: function (jsonP, ajaxP) {
// // console.log(jsonP);
// _this.func.utils.post_back_to_client(
// SESSION_ID,
// "change_loaded_image",
// _this.SESSION_OBJ[SESSION_ID].worker_id,
// jsonP
// );
// },
// error: function (status) {
// console.log("error save_image:" + status);
// },
// fail: function (status) {
// console.log("error save_image:" + status);
// },
// };
// // const app_id = _this.SESSION_OBJ[SESSION_ID].app_id;
// let app_id = _this.SESSION_OBJ[SESSION_ID].app_id;
// let app_id_reference = APP_OBJ[app_id].app_id_reference;
// _this.$_ajax({
// url: _this.func.common.get_url(SESSION_ID, "rpi", "runtime_save_image"),
// dataType: "json",
// type: "POST",
// data: {
// base64: base64,
// filename: filename,
// app_id_reference: app_id_reference,
// app_id: app_id,
// },
// success: function (json) {
// response.success(json);
// },
// fail: function (jqXHR, textStatus) {
// response.error(jqXHR, textStatus, errorThrown);
// },
// error: function (jqXHR, textStatus, errorThrown) {
// response.error(jqXHR, textStatus, errorThrown);
// },
// timeout: 60000, //60 seconds timeout
// });
// };
const init_xuda_dbs_plugin = async function (SESSION_ID) {
var _session = _this.SESSION_OBJ[SESSION_ID];
const plugin_name = '@xuda.io/xuda-dbs-plugin-xuda';
const get_path = function (plugin_name, resource) {
var path = `https://${_session.domain}/plugins/${plugin_name}${resource ? '/' + resource : ''}?app_id=${_session.app_id}`;
return path;
};
try {
_this.xuda_dbs_plugin = await import(get_path(plugin_name, 'studio.mjs'));
const db = await func.utils.connect_pouchdb(SESSION_ID);
await _db.call_pouch_xuda_dbs_plugin(SESSION_ID, 'create_design', { db });
} catch (err) {
return console.error(err.message);
}
};
_db.call_pouch_xuda_dbs_plugin = async function (SESSION_ID, method, params) {
return new Promise(async (resolve, reject) => {
try {
// var table_obj = {};
if (params.e) {
params.table_obj = await func.utils.DOCS_OBJ.get(SESSION_ID, params.e.table_id);
}
await _this.xuda_dbs_plugin[method](params, resolve, reject);
} catch (err) {
reject();
}
});
};
_db.pouch = {};
_db.pouch.dbs_read = async function (SESSION_ID, e) {
const db = await func.utils.connect_pouchdb(SESSION_ID);
return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID, 'read', { db, e });
};
_db.pouch.dbs_create = async function (SESSION_ID, e) {
const db = await func.utils.connect_pouchdb(SESSION_ID);
return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID, 'create', { db, e });
};
_db.pouch.dbs_delete = async function (SESSION_ID, e) {
const db = await func.utils.connect_pouchdb(SESSION_ID);
return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID, 'del', { db, e });
};
_db.pouch.dbs_update = async function (SESSION_ID, e) {
const db = await func.utils.connect_pouchdb(SESSION_ID);
return await _db.call_pouch_xuda_dbs_plugin(SESSION_ID, 'update', { db, e });
};
_db.pouch.init_db_replication = async function (SESSION_ID) {
const db = await func.utils.connect_pouchdb(SESSION_ID);
var _session = _this.SESSION_OBJ[SESSION_ID];
if (_session.url_params.avoid_local || _session.engine_mode === 'miniapp' || (_session.engine_mode !== 'live_preview' && !_session.opt.enable_offline)) {
return;
}
// handle realtime refresh programs
const changes = db
.changes({
// since: "now",
live: true,
include_docs: true,
})
.on('change', function (change) {
// handle change
if (!change.doc.udfData) return;
// console.log("handle change", change);
func.UI.screen.refresh_document_changes_for_realtime_update(SESSION_ID, {
row_id: change.id,
table_id: change.doc.udfData.udffileid,
});
})
.on('complete', function (info) {
// changes() was canceled
console.log('complete', info);
})
.on('error', function (err) {
console.error(err);
});
set_replication_stat(SESSION_ID, null, 3);
// replicate to server
const db_name = APP_OBJ[_session.app_id].app_db_name;
const rep = db.replicate
.to(`https://${_session.domain}/db/${db_name}`, {
selector: { docType: 'database' },
live: true,
retry: true,
fetch: function (url, opts) {
if (_session.gtp_token) {
opts.headers.set('xu-gtp-token', _session.gtp_token);
}
if (_session.app_token) opts.headers.set('xu-app-token', _session.app_token);
{
opts.headers.set('xu-db', db_name);
}
return PouchDB.fetch(url, opts);
},
})
.on('change', function (info) {
// handle change
})
.on('paused', function (err) {
if (err) {
return set_replication_stat(SESSION_ID, null, 2);
}
set_replication_stat(SESSION_ID, null, 3);
// replication paused (e.g. replication up to date, user went offline)
})
.on('active', function () {
// replicate resumed (e.g. new changes replicating, user went back online)
})
.on('denied', function (err) {
set_replication_stat(SESSION_ID, null, 2);
// a document failed to replicate (e.g. due to permissions)
})
.on('complete', function (info) {
// handle complete
})
.on('error', function (err) {
set_replication_stat(SESSION_ID, null, 2);
// handle error
});
_db.pouch.set_db_replication_from_server(SESSION_ID);
};
_db.pouch.set_db_replication_from_server = async function (SESSION_ID) {
const db = await func.utils.connect_pouchdb(SESSION_ID);
const rep_docs = await _db.pouch.get_replications(SESSION_ID);
const _session = _this.SESSION_OBJ[SESSION_ID];
const db_name = APP_OBJ[_session.app_id].app_db_name;
const remote_db_url = `https://${_session.domain}/db/${db_name}`;
const remote_db = new PouchDB(remote_db_url, {
fetch: function (url, opts) {
if (_session.gtp_token) {
opts.headers.set('xu-gtp-token', _session.gtp_token);
}
if (_session.app_token) opts.headers.set('xu-app-token', _session.app_token);
{
opts.headers.set('xu-db', db_name);
}
return PouchDB.fetch(url, opts);
},
});
if (_this.db_changes_store) {
_this.db_changes_store.cancel();
}
const write_stat = async function (rep_id, stat, reason) {
try {
let doc = await db.get(rep_id);
// console.log("> replication ", stat, reason, doc);
doc.stat = stat;
doc.stat_reason = reason;
try {
db.put(doc);
} catch (err) {}
} catch (err) {}
};
const download_documents = async function (rep_doc) {
await write_stat(rep_doc._id, 2);
const remote_db = new PouchDB(remote_db_url, {
fetch: function (url, opts) {
opts.headers.set('xu-prog_id', rep_doc.prog_id);
if (_session.gtp_token) {
opts.headers.set('xu-gtp-token', _session.gtp_token);
}
if (_session.app_token) opts.headers.set('xu-app-token', _session.app_token);
{
opts.headers.set('xu-db', db_name);
}
return PouchDB.fetch(url, opts);
},
});
const ret = await remote_db.find({
selector: rep_doc.selector,
fields: ['_id'],
limit: 9999999999,
// prog_id: rep_doc.prog_id,
});
if (ret?.code < 0) {
return func.utils.debug_report(SESSION_ID, 'download_documents', ret.data, 'E');
}
try {
var doc_ids = [];
for await (let doc of ret.docs) {
doc_ids.push(doc._id);
}
db.replicate
.from(remote_db_url, {
doc_ids,
retry: true,
style: 'main_only',
fetch: function (url, opts) {
if (_session.gtp_token) {
opts.headers.set('xu-gtp-token', _session.gtp_token);
}
if (_session.app_token) opts.headers.set('xu-app-token', _session.app_token);
{
opts.headers.set('xu-db', db_name);
}
return PouchDB.fetch(url, opts);
},
})
.on('paused', async function (err) {
// replication paused (e.g. replication up to date, user went offline)
if (err) {
// set_replication_stat(SESSION_ID, 2);
return;
}
const read_ret = await _db.pouch.dbs_read(SESSION_ID, rep_doc.e); // trigger reindexing
await write_stat(rep_doc._id, 3);
});
} catch (err) {
await write_stat(rep_doc._id, 2, err.message);
console.error('replication from error', err);
}
// console.log(ret);
};
let filter_tables = [];
for (let doc of rep_docs) {
if (!filter_tables.includes(doc.table_id)) filter_tables.push(doc.table_id);
if (doc.stat < 3) await download_documents(doc);
}
try {
_this.db_changes_store = remote_db
.changes({
since: 'now',
live: true,
timeout: 300000, // 5 min
style: 'main_only',
include_docs: false,
// heartbeat: 10000
})
.on('change', async function (change) {
if (change.id.substr(0, 4) !== 'dbs-') return;
if (_this.db_replication_from_stat !== 3) {
set_replication_stat(SESSION_ID, 3);
}
try {
const existing_doc = await db.get(change.id);
db.replicate.from(remote_db_url, {
doc_ids: [change.id],
retry: true,
style: 'main_only',
fetch: function (url, opts) {
if (_session.gtp_token) {
opts.headers.set('xu-gtp-token', _session.gtp_token);
}
if (_session.app_token) opts.headers.set('xu-app-token', _session.app_token);
{
opts.headers.set('xu-db', db_name);
}
return PouchDB.fetch(url, opts);
},
});
} catch (err) {
// new doc change
try {
const table_id = change.id.split('_')[0].substr(4);
for (let doc of rep_docs) {
if (doc.table_id === table_id) {
download_documents(doc);
}
}
} catch (err) {
console.warn(err);
}
}
})
.on('complete', function (info) {
// changes() was canceled
})
.on('error', function (err) {
console.error(err);
set_replication_stat(SESSION_ID, 2);
_this.db_changes_store.cancel();
});
} catch (err) {
console.error(err);
}
return;
};
_db.pouch.remove_db_replication_from_server = async function (SESSION_ID, rep_id) {
const db = await func.utils.connect_pouchdb(SESSION_ID);
try {
const doc = await db.get(rep_id);
// _this.db_replication_store[rep_id].cancel();
db.remove(doc);
// delete _this.db_replication_store[rep_id];
} catch (error) {}
};
_db.pouch.get_replications = async function (SESSION_ID = Object.keys(SESSION_OBJ)[0]) {
const db = await func.utils.connect_pouchdb(SESSION_ID);
// source: "runtime"
let ret = await db.find({
selector: { docType: 'rep_request' },
});
return ret.docs;
};
_db.pouch.get_replication_stat = async function (SESSION_ID) {
const _session = _this.SESSION_OBJ[SESSION_ID];
return _session?.DS_GLB?.[0]?.data_system?.SYS_GLOBAL_BOL_REPLICATION_STAT;
};
const set_replication_stat = async function (SESSION_ID, from_stat, to_stat) {
var _session = _this.SESSION_OBJ[SESSION_ID];
if (!_session?.DS_GLB?.[0]) {
return setTimeout(function () {
set_replication_stat(SESSION_ID, from_stat, to_stat);
}, 1000);
}
if (from_stat) _this.db_replication_from_stat = from_stat;
if (to_stat) _this.db_replication_to_stat = to_stat;
var data = {};
if (_this.db_replication_from_stat === 3 && _this.db_replication_to_stat === 3) {
data.SYS_GLOBAL_BOL_REPLICATION_STAT = 1;
console.info('Replication On');
} else {
data.SYS_GLOBAL_BOL_REPLICATION_STAT = 0;
console.info('Replication Off');
}
var datasource_changes = {
[0]: {
['data_system']: data,
},
};
await func.datasource.update(SESSION_ID, datasource_changes);
};
const refresh_document_changes_for_realtime_update = function (SESSION_ID, doc_change) {
var _session = _this.SESSION_OBJ[SESSION_ID];
if (glb.IS_WORKER) {
return func.utils.post_back_to_client(SESSION_ID, 'refresh_document_changes_for_realtime_update', _session.worker_id, { doc_change });
}
func.UI.screen.refresh_document_changes_for_realtime_update(SESSION_ID, doc_change);
};