From 41c7f9cc75f8f9f9438a271eae1b3e9d26122088 Mon Sep 17 00:00:00 2001 From: shubh Date: Mon, 25 Nov 2024 17:12:13 +0100 Subject: [PATCH] new way to load plugin, new ver release --- package.json | 2 +- src/index.js | 92 +++++++++++++++++++++++++++++++++---- src/plugins/text_command.js | 6 +-- src/system_schema.js | 28 +++++++++-- 4 files changed, 111 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index bfb33ab..4f16667 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "beanbagdb", - "version": "0.5.70", + "version": "0.5.71", "description": "A JS library to introduce a schema layer to a No-SQL local database", "main": "src/index.js", "module": "src/index.js", diff --git a/src/index.js b/src/index.js index c090114..598588f 100644 --- a/src/index.js +++ b/src/index.js @@ -162,7 +162,7 @@ export class BeanBagDB { // this works on its own but is usually called by ready automatically if required // check for schema_scehma : if yes, check if latest and upgrade if required, if no create a new schema doc try { - let app_data = await this.initialize_app(sys_sch.default_app) + let app_data = await this.initialize_db(sys_sch.default_app) console.log(app_data) this.meta.beanbagdb_version_db = this._version; this.active = true; @@ -175,7 +175,7 @@ export class BeanBagDB { } - async initialize_app(app_data){ + async initialize_db(app_data){ // app_data : meta(name,description), schemas[] , default_records:[] // TODO check if add_data is valid // calculate the app_version @@ -697,18 +697,35 @@ export class BeanBagDB { } } + /** + * To load a plugin in the current BeanBagDB instance. + * Plug_module has to be loaded manually first. It must export an object containing fields: `actions` and `schema`. + * `actions` is an object of methods which can be called after loading the plugin. + * `schema` is an array of JSON schemas that are required by the plugin. Every time a plugin is loaded, this list is schemas is verified. New updates are added automatically to the database and logged + * methods inside actions must be async and must have at least one parameter : `db_instance` which is assumed to be the current instance of the BeanBagDB object itself. They ideally must also return some value. + * @param {string} plugin_name + * @param {object} plugin_module + */ async load_plugin(plugin_name, plugin_module) { this._check_ready_to_use(); this.plugins[plugin_name] = {}; - for (let func_name in plugin_module) { - if (typeof plugin_module[func_name] == "function") { - this.plugins[plugin_name][func_name] = plugin_module[func_name].bind(null,this) + //console.log(plugin_module) + if(plugin_module.actions){ + for (let func_name in plugin_module.actions) { + if (typeof plugin_module.actions[func_name] == "function") { + this.plugins[plugin_name][func_name] = plugin_module.actions[func_name].bind(null,this) + } } } - // Check if the plugin has an on_load method and call it - if (typeof this.plugins[plugin_name].on_load === "function") { - await this.plugins[plugin_name].on_load(); + + if(plugin_module.schemas){ + await this._upgrade_schema_in_bulk(plugin_module.schemas,true,`Updating ${plugin_name} plugin schemas`) } + + // Check if the plugin has an on_load method and call it + // if (typeof this.plugins[plugin_name].on_load === "function") { + // await this.plugins[plugin_name].on_load(); + // } } /////////////////////////////////////////////////////////// @@ -828,6 +845,65 @@ _check_nodes_edge(node1Rule, node2Rule, schema1, schema2) { //////////////// Internal methods //////////////////////// ////////////////////////////////////////////////////////// + +async _upgrade_schema_in_bulk(schemas,log_upgrade=false,log_message="Schema Upgrade in bulk"){ + // TODO add a check to now allow default system schema to be updated from this method + + let steps = ["schema update started"] + let update_was_required = false + for (let index = 0; index < schemas.length; index++) { + const schema_name = schemas[index]["name"]; + const schema_data = schemas[index] + steps.push(`checking.${schema_name}`) + try { + let schema1 = await this.get("schema",{name:schema_name}) + if (schema1["data"]["version"] != schema_data.version) { + steps.push(`old.${schema_name}.v.${schema1["data"]["version"]}`); + let full_doc = await this.db_api.get(schema1["_id"]); + full_doc["data"] = { ...schema_data }; + full_doc["meta"]["updated_on"] = this.util_get_now_unix_timestamp(); + console.log(full_doc) + await this.db_api.update(full_doc); + steps.push(`new.${schema_name}.v=${schema_data.version}`); + update_was_required = update_was_required || true + }else{ + steps.push(`${schema_name}.v.${schema1["data"]["version"]}=latest`) + } + } catch (error) { + // console.log(error); + if (error instanceof DocNotFoundError) { + // inserting new schema doc + let system_schema = sys_sch.default_app.schemas[0]["schema"] + let new_schema_doc = this._get_blank_schema_doc( + "schema", + system_schema, + schema_data + ); + await this.db_api.insert(new_schema_doc); + + steps.push(`init.${schema_name}.v=${schema_data.version}`); + update_was_required = update_was_required || true + }else{ + steps.push(`${schema_name}.error.message : ${error.message} `); + } + } + } + // console.log(JSON.stringify(steps)) + // console.log(update_was_required) + if (update_was_required && log_upgrade){ + // log it if asked + try { + let new_log_doc = this._get_blank_doc("system_log") + new_log_doc.data = {text:log_message,data:{steps},time:this.util_get_now_unix_timestamp()} + await this.db_api.insert(new_log_doc); + } catch (error) { + console.log(error) + } + + } + return {update_was_required,logs:steps} +} + /** * Retrieves the current version of the system by summing up the version numbers * of all system-defined schemas. diff --git a/src/plugins/text_command.js b/src/plugins/text_command.js index cc3eaff..3ef152e 100644 --- a/src/plugins/text_command.js +++ b/src/plugins/text_command.js @@ -1,6 +1,3 @@ - - - const commands = { new: { parse: async (instance,parts) => { @@ -187,7 +184,8 @@ const parse_and_run = async(instance, text) => { let command_result = await run(instance,command) return command_result } +// const schemas = [] export const text_command = { - parse,run,parse_and_run + actions: {parse,run,parse_and_run} }; \ No newline at end of file diff --git a/src/system_schema.js b/src/system_schema.js index 07ccd24..f1b6a96 100644 --- a/src/system_schema.js +++ b/src/system_schema.js @@ -8,23 +8,26 @@ export const default_app = { name: "schema", description:"Meta-schema or the schema for defining other schemas", system_generated:true, - version:0.70, + version:0.80, schema: { type: "object", additionalProperties: false, properties: { system_generated:{ + title:"System generated schema", type:"boolean", default:false }, version: { type: "number", + title:"Version", minimum: 0, default: 1, description:"This is an optional field.To be used primarily for system schemas" }, name: { type: "string", + title:"Name", minLength: 4, maxLength: 50, pattern: "^[a-zA-Z][a-zA-Z0-9_]*$", @@ -32,12 +35,14 @@ export const default_app = { }, description:{ type:"string", + title:"About", minLength:0, maxLength:1000, description:"A small description of what data in this schema stores." }, schema: { type: "object", + title:"JSON Schema specification", additionalProperties: true, minProperties: 1, maxProperties: 50, @@ -45,9 +50,11 @@ export const default_app = { }, settings: { type: "object", + title:"Additional Settings", additionalProperties: true, properties: { primary_keys: { + title:"Primary key", type: "array", default: [], items: { @@ -58,6 +65,7 @@ export const default_app = { }, non_editable_fields: { type: "array", + title:"Non editable fields", default: [], items: { type: "string", @@ -68,23 +76,35 @@ export const default_app = { }, encrypted_fields: { type: "array", + title:"List of fields encrypted", default: [], items: { type: "string", }, maxItems: 50, description:"Once set, all the data in this field will be encrypted before storing it in the database. Encryption key must be provided during the time of BeanBagDB initialization and must be managed by the user as it is NOT stored in the database" + }, + display_fields: { + type: "array", + title:"List of fields to show in short view", + default: [], + items: { + type: "string", + }, + maxItems: 50, + description:"These fields will be used when a record is displayed in short" } }, required :["primary_keys","non_editable_fields","encrypted_fields"] }, }, - required: ["name","description","schema", "settings"], + required: ["name","version","description","schema", "settings"], }, settings: { primary_keys: ["name"], non_editable_fields:[], - encrypted_fields:[] + encrypted_fields:[], + display_fields:["name","version","description"] }, }, { @@ -295,7 +315,7 @@ export const default_app = { non_editable_fields:[], encrypted_fields:[] }, - }, + } ], records:[] }