Skip to content

Commit

Permalink
Merge pull request #27 from shubhvjain/main
Browse files Browse the repository at this point in the history
added text_command pluging
  • Loading branch information
shubhvjain authored Oct 21, 2024
2 parents d62be9e + 45a1cac commit 40a386b
Show file tree
Hide file tree
Showing 7 changed files with 447 additions and 131 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,6 @@ dist
.DS_Store
test_database_*

docs-static
docs-static

cli
24 changes: 23 additions & 1 deletion doc-src/3_plugins.md
Original file line number Diff line number Diff line change
@@ -1 +1,23 @@
# How to use plugins
# How to use plugins

```
// MyPlugin.js
const MyPlugin = {
// This function will be bound to the class instance (passed as 'thisArg')
on_load: async function(instance) {
console.log("Plugin loaded with instance:", instance);
// You can access instance properties and methods here
instance.someMethod();
},
// Another plugin function
doSomething: function(instance, arg) {
console.log("Plugin doing something with arg:", arg);
// Access the class instance here as 'instance'
instance.someMethod();
}
};
export default MyPlugin;
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "beanbagdb",
"version": "0.5.53",
"version": "0.5.54",
"description": "A JS library to introduce a schema layer to a No-SQL local database",
"main": "src/index.js",
"module": "src/index.js",
Expand Down
27 changes: 26 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ export class BeanBagDB {
async delete(criteria) {
this._check_ready_to_use();
let doc = await this.read(criteria)
const delete_blocked = ["schema","setting",""]
const delete_blocked = ["schema","setting","key"]
if (delete_blocked.includes(doc.schema)){
throw new Error(`Deletion of ${doc.schema} doc is not support yet.`)
}
Expand Down Expand Up @@ -597,6 +597,7 @@ export class BeanBagDB {
async get(special_doc_type,criteria={}){
// this method returns special types of documents such as schema doc, or a blank doc for a given schema and other system related things
const fetch_docs = {
// to return schema object for the given name
schema:async (criteria)=>{
let schemaSearch = await this.db_api.search({
selector: { schema: "schema", "data.name": criteria.name },
Expand All @@ -606,6 +607,30 @@ export class BeanBagDB {
throw new DocNotFoundError(BeanBagDB.error_codes.schema_not_found);
}
return schemaSearch.docs[0];
},
// schema list
schema_list:async (criteria)=>{
let schemaSearch = await this.db_api.search({
selector: { schema: "schema" },
});
// console.log(schemaSearch)
if (schemaSearch.docs.length == 0) {
throw new DocNotFoundError(BeanBagDB.error_codes.schema_not_found);
}else{
let schemas = []
schemaSearch.docs.map(doc=>{
schemas.push({
name: doc.data.name,
version: doc.data.version,
system_defined : doc.data.system_generated,
description: doc.data.description,
link: doc.meta.link,
_id:doc._id
})
})
return schemas
}

}
}
if(Object.keys(fetch_docs).includes(special_doc_type)){
Expand Down
193 changes: 193 additions & 0 deletions src/plugins/text_command.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@



const commands = {
new: {
parse: async (instance,parts) => {
let criteria = {}
criteria.schema = parts.length==0?"":parts.join("")
return criteria
},
run: async (instance,command) => {
if (command.criteria.schema==""){
// return a list of all schemas present in the DB
let all_schema = await instance.get("schema_list")
return all_schema
}else{
// return the schema object for the given schema if not found throw error
let schema_obj = await instance.search({"selector":{"schema":"schema","data.name":command.criteria.schema}})
//console.log(schema_obj)
if(schema_obj.docs.length==0){
throw new Error("Schema with this name does not exists")
}
return schema_obj.docs[0]
}
},
help: `To create a new record. Format : new/"schema_name(optional)". If no schema name provided, a list of valid schema name is returned`
},
open:{
parse: async (instance,parts) => {
let criteria = {}
if (parts.length==0){
throw new Error("Invalid arguments.open command needs unique id")
}
let id_type = parts[0]
if(id_type=="id"){
parts.shift()
criteria["_id"] = parts.join("")
}else if(id_type=="link"){
parts.shift()
criteria["link"] = parts.join("")
}else if(id_type=="key"){
parts.shift()
let text= parts.join()
let p = text.split(",")

p.map(itm=>{
let p1 = itm.split("=")
if(p1[0]=="schema"){
criteria["schema"] = p1[1]
}else{
criteria["data"][p1[0]] = p1[1]
}
})

if(!criteria["schema"]){
throw new Error("Key requires a schema")
}
}else{
throw new Error("Invalid unique key")
}
return criteria
},
run: async (instance,command) => {
try {
let data = await instance.read(command.criteria,true)
return data
} catch (error) {
throw error
}
},
help: `To open a record using it's unique id. Format : open/"id||link|key"/"value". In case of key field name must be provided as : field1=value1,fields2=value2...`
},
tool:{
parse : async (instance,parts)=>{
let criteria = {}
criteria.type = parts.length==0?"info":parts.join("")
return criteria
},
run : async (instance,command)=>{
let c_type = command.criteria.type
let data = {}
if (c_type=="info"){
// to get all basic info about the database
let data = {
meta: instance.metadata(),
schemas : {},
logs:[]
}
let schemas = await instance.get("schema_list")
data.schemas = schemas

let logs_doc = await instance.read({"schema":"system_settings","data":{name:"system_logs"}})
//console.log(logs_doc)
data =logs_doc.doc.data.value
return data

}else if(c_type=="plugins"){
// to show list of all plugins installed
// todo later not implemented yet
}else if(c_type=="settings"){
// to show the list of all setting docs available
let search = instance.search({"selector":{"schema":"system_settings"}})
return {docs:search.docs}
}
else if(c_type=="keys"){
// to show the list of all keys present in the db
let search = instance.search({"selector":{"schema":"system_keys"}})
return {docs:search.docs}
}
else{
throw new Error("Invalid tool command")
}
},
}
};

const parse = async (instance, text) => {
let data = {
errors: [],
valid: false,
name: "",
criteria: {},
};
if (!text) {
data.errors.push(
"No text command provided. Format : command_name/parameter"
);
}
let parts = text.split("/");
if (parts.length == 0) {
data.errors.push("Invalid text command");
}
let command_name = parts[0];
if (!commands[command_name]) {
data.errors.push(
"Invalid command name. Valid : " + Object.keys(commands).join(",")
);
}
data.name = command_name;
try {
parts.shift();
let criteria = await commands[command_name].parse(instance,parts);
data.criteria = criteria;
} catch (error) {
data.errors.push(error.message);
}
if (data.errors.length == 0) {
data.valid = true;
}
return data;
};

const run = async (instance, command) => {
let data = {
result:{},
errors:[],
valid:false
};

if (!command) {
data.errors.push("No command object provided ");
}
if (!command.valid){
data.errors["Command cannot be run"]

}
if(!commands[command.name]){
data.errors["Invalid command name"]
}

try {
let data1 = await commands[command.name].run(instance,command)
//console.log(data)
data.result = data1
} catch (error) {
data.errors.push(error.message)
}
if(data.errors.length==0){
data.valid = true
}
return data
};

const parse_and_run = async(instance, text) => {
let command = await parse(instance,text)
console.log(command)
let command_result = await run(instance,command)
return command_result
}

export const text_command = {
parse,run,parse_and_run
};
55 changes: 55 additions & 0 deletions test/plugin.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// to test database operations. assuming the class is initialized successfully
// to test initialization of the BeanBagDB class
import { get_pdb_doc } from "./pouchdb.js";
import assert, { throws, strictEqual, rejects } from "assert";
import { BeanBagDB, DocCreationError, EncryptionError, ValidationError,DocNotFoundError, DocUpdateError } from "../src/index.js";

import {text_command} from "../src/plugins/text_command.js"

import * as chai from 'chai';
import chaiAsPromised from 'chai-as-promised';

chai.use(chaiAsPromised);

// Then either:
const expect = chai.expect;

let database; // this is the global db object


describe("Testing plugin load", async () => {


before(async () => {
let doc_obj = get_pdb_doc("test_database_30", "qwertyuiopaqwsde1254");
database = new BeanBagDB(doc_obj);
await database.ready(); // Ensure the database is ready before running tests
console.log("Ready for more tests...");
});



it('successfully loads the plugin', async () => {
try {
await database.load_plugin("txtcmd",text_command)
chai.expect(database.plugins).to.not.be.empty
} catch (error) {
console.log(error)
throw error
}
})

it('successfully runs the loaded the plugin method', async () => {
try {

let command = await database["txtcmd"].parse("new/system_keys")
console.log(command)
assert (1 ==2)
} catch (error) {
console.log(error)
throw error
}
})
});


Loading

0 comments on commit 40a386b

Please sign in to comment.