beanbagdb 0.5.46 → 0.5.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,38 @@
1
+ name: Generate and Deploy JSDoc
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - release
7
+ permissions:
8
+ contents: read
9
+ pages: write
10
+ id-token: write
11
+ jobs:
12
+ # Single deploy job since we're just deploying
13
+ deploy:
14
+ environment:
15
+ name: github-pages
16
+ url: ${{ steps.deployment.outputs.page_url }}
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v4
21
+ - name: Set up Node.js
22
+ uses: actions/setup-node@v3
23
+ with:
24
+ node-version: '18'
25
+ - name: Install dependencies
26
+ run: npm install
27
+ - name: Generate JSDoc
28
+ run: npx jsdoc -c jsdoc.json
29
+ - name: Setup Pages
30
+ uses: actions/configure-pages@v5
31
+ - name: Upload artifact
32
+ uses: actions/upload-pages-artifact@v3
33
+ with:
34
+ # Upload entire repository
35
+ path: './docs-static'
36
+ - name: Deploy to GitHub Pages
37
+ id: deployment
38
+ uses: actions/deploy-pages@v4
@@ -4,7 +4,7 @@ name: Release npm Package
4
4
  on:
5
5
  push:
6
6
  branches:
7
- - main
7
+ - release
8
8
 
9
9
  jobs:
10
10
  build:
@@ -30,8 +30,8 @@ jobs:
30
30
  run: npm install
31
31
 
32
32
  # Step 4: Run tests
33
- # - name: Run tests
34
- # run: npm test
33
+ - name: Run tests
34
+ run: npm test
35
35
 
36
36
  # Step 5: Publish to npm if tests pass
37
37
  - name: Publish to npm
@@ -0,0 +1,36 @@
1
+ name: Test code on master
2
+
3
+ # Trigger the workflow on push to the "main" branch
4
+ on:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ id-token: write
15
+ steps:
16
+ # Step 1: Check out the code from the repository
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ # Step 2: Set up Node.js environment
21
+ - name: Setup Node.js
22
+ uses: actions/setup-node@v4
23
+ with:
24
+ node-version: '20.17.0'
25
+ cache: 'npm'
26
+ registry-url: 'https://registry.npmjs.org'
27
+
28
+ # Step 3: Install dependencies
29
+ - name: Install dependencies
30
+ run: npm install
31
+
32
+ # Step 4: Run tests
33
+ - name: Run tests
34
+ run: npm test
35
+
36
+
package/index.md ADDED
@@ -0,0 +1 @@
1
+ This is where i write the documentation
package/jsdoc.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "source": {
3
+ "include": ["src"],
4
+ "includePattern": ".+\\.js(doc|x)?$",
5
+ "excludePattern": "(^|\\/|\\\\)_"
6
+ },
7
+ "opts": {
8
+ "destination": "./docs-static",
9
+ "recurse": true,
10
+ "readme":"./index.md",
11
+ "tutorials": "./docs"
12
+ },
13
+ "plugins": [
14
+ "plugins/markdown"
15
+ ],
16
+ "templates": {
17
+ "default": {
18
+ "outputSourceFiles": false
19
+ }
20
+ }
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beanbagdb",
3
- "version": "0.5.46",
3
+ "version": "0.5.50",
4
4
  "description": "A JS library to introduce a schema layer to a No-SQL local database",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -29,6 +29,7 @@
29
29
  "ajv": "^8.17.1",
30
30
  "chai": "^5.1.1",
31
31
  "dotenv": "^16.4.5",
32
+ "jsdoc": "^4.0.3",
32
33
  "mocha": "^10.7.3",
33
34
  "nano": "^10.1.4",
34
35
  "pouchdb": "^9.0.0",
package/src/index.js CHANGED
@@ -159,7 +159,36 @@ class BeanBagDB {
159
159
  }
160
160
 
161
161
  validate_schema_object(schema_doc){
162
+ let errors = []
163
+ if(!schema_doc["schema"]["type"]){
164
+ errors.push("Schema must have the field schema.'type' which can only be 'object' ")
165
+ }else{
166
+ if(schema_doc["schema"]["type"]!="object"){
167
+ errors.push("The schema.'type' value is invalid.Only 'object' allowed")
168
+ }
169
+ }
170
+ if(!schema_doc["schema"]["properties"]){
171
+ errors.push("The schema.'properties' object does not exists")
172
+ }else{
173
+ if(typeof(schema_doc["schema"]["properties"])!="object"){
174
+ errors.push("Invalid schema.properties. It must be an object and must have atleast one field inside.")
175
+ }
176
+ if(Object.keys(schema_doc["schema"]["properties"]).length==0){
177
+ errors.push("You must define at least one property")
178
+ }
179
+ }
162
180
 
181
+ if(!schema_doc["schema"]["additionalProperties"]){
182
+ errors.push("The schema.'additionalProperties' field is required")
183
+ }else{
184
+ if(typeof(schema_doc["schema"]["additionalProperties"])!="boolean"){
185
+ errors.push("Invalid schema.additionalProperties. It must be a boolean value")
186
+ }
187
+ }
188
+
189
+ if(errors.length>0){
190
+ throw new Error("Schema validation errors- "+errors.join(","))
191
+ }
163
192
  }
164
193
 
165
194
  /**
@@ -255,7 +284,7 @@ class BeanBagDB {
255
284
  * @param {Object} data e.g {"name":"","mobile":""...}
256
285
  * @param {Object} settings (optional)
257
286
  */
258
- async insert(schema, data, settings = {}) {
287
+ async insert(schema, data, meta= {},settings = {}) {
259
288
  try {
260
289
  let doc_obj = await this._insert_pre_checks(schema, data, settings);
261
290
  let new_rec = await this.db_api.insert(doc_obj);
@@ -563,6 +592,10 @@ class BeanBagDB {
563
592
 
564
593
  // special checks for special docs
565
594
  // @TODO : for schema dos: settings fields must be in schema field
595
+ if(schema=="schema"){
596
+ //more checks are required
597
+ this.validate_schema_object(data)
598
+ }
566
599
  // @TODO : check if single record setting is set to true
567
600
 
568
601
  // duplicate check
@@ -15,17 +15,20 @@ export const schema_schema = {
15
15
  minLength: 5,
16
16
  maxLength: 50,
17
17
  pattern: "^[a-zA-Z][a-zA-Z0-9_]*$",
18
+ description:"This is the name of the schema.It cannot be changed later"
18
19
  },
19
20
  description:{
20
21
  type:"string",
21
- minLength:1,
22
- maxLength:1000
22
+ minLength:0,
23
+ maxLength:1000,
24
+ description:"A small description of what data in this schema stores."
23
25
  },
24
26
  schema: {
25
27
  type: "object",
26
28
  additionalProperties: true,
27
29
  minProperties: 1,
28
30
  maxProperties: 50,
31
+ description:"This must be a valid JSON Schema which will be used to validate documents created with this schema.See this https://tour.json-schema.org/",
29
32
  },
30
33
  settings: {
31
34
  type: "object",
package/test/init.test.js CHANGED
@@ -1,83 +1,13 @@
1
- // to test initialization of the BeanBagDB class. using in memory pouch db for testing to avoid additional setup.
2
- import PouchDB from 'pouchdb';
3
- import pouchdbFind from 'pouchdb-find';
4
- PouchDB.plugin(pouchdbFind)
5
- import { scryptSync, randomBytes, createCipheriv, createDecipheriv } from 'crypto';
6
- const db_name = "test_database_24"
7
- const pdb = new PouchDB(db_name);
8
- import Ajv from 'ajv';
9
-
10
- const doc_obj = {
11
- name: db_name,
12
- encryption_key: "qwertyuiopaqwsde1254",
13
- api: {
14
- insert: async (doc) => {
15
- const result = await pdb.post(doc);
16
- return result;
17
- },
18
- // delete: ()=>{db1.destroy},
19
- update: async (doc) => {
20
- const result = await pdb.put(doc);
21
- return result;
22
- },
23
- search: async (query) => {
24
- const results = await pdb.find(query);
25
- return results; // of the form {docs:[],...}
26
- },
27
- get: async (id) => {
28
- const data = await pdb.get(id);
29
- return data;
30
- },
31
- delete: async (id) => {
32
- const doc = await pdb.get(id);
33
- const resp = await pdb.remove(doc);
34
- return resp;
35
- },
36
- createIndex: async (filter) => {
37
- const data = await pdb.createIndex(filter);
38
- return data;
39
- },
40
- },
41
- utils: {
42
- encrypt: (text, encryptionKey) => {
43
- const key = scryptSync(encryptionKey, "salt", 32); // Derive a 256-bit key
44
- const iv = randomBytes(16); // Initialization vector
45
- const cipher = createCipheriv("aes-256-cbc", key, iv);
46
- let encrypted = cipher.update(text, "utf8", "hex");
47
- encrypted += cipher.final("hex");
48
- return iv.toString("hex") + ":" + encrypted; // Prepend the IV for later use
49
- },
50
- decrypt: (encryptedText, encryptionKey) => {
51
- const key = scryptSync(encryptionKey, "salt", 32); // Derive a 256-bit key
52
- const [iv, encrypted] = encryptedText
53
- .split(":")
54
- .map((part) => Buffer.from(part, "hex"));
55
- const decipher = createDecipheriv("aes-256-cbc", key, iv);
56
- let decrypted = decipher.update(encrypted, "hex", "utf8");
57
- decrypted += decipher.final("utf8");
58
- return decrypted;
59
- },
60
- ping: () => {
61
- // @TODO ping the database to check connectivity when class is ready to use
62
- },
63
- validate_schema: (schema_obj, data_obj)=>{
64
- const ajv = new Ajv({code: {esm: true}}) // options can be passed, e.g. {allErrors: true}
65
- const validate = ajv.compile(schema_obj);
66
- const valid = validate(data_obj);
67
- return {valid,validate}
68
- }
69
- },
70
- }
71
-
72
- let the_correct_object = {};
73
-
1
+ // to test initialization of the BeanBagDB class
2
+ import { get_pdb_doc } from './pouchdb.js';
74
3
  import { throws, strictEqual } from "assert";
4
+ import BeanBagDB from '../src/index.js';
75
5
 
76
- import BeanBagDB from '../src/index.js';
77
6
  /**
78
7
  * Initial setup
79
8
  * database is the global var where the beanbag class is initialized
80
9
  */
10
+
81
11
  const test_set1 = [
82
12
  ["name", "sample"],
83
13
  ["encryption_key", "sample_key"],
@@ -210,6 +140,7 @@ describe("Successful database class init", async () => {
210
140
  });
211
141
 
212
142
  it("DB init successful", () => {
143
+ let doc_obj = get_pdb_doc("test_database_24","qwertyuiopaqwsde1254")
213
144
  database = new BeanBagDB(doc_obj);
214
145
  strictEqual(
215
146
  database instanceof BeanBagDB,
@@ -1 +1,145 @@
1
- // to test database operations. assuming the class is initialized successfully
1
+ // to test database operations. assuming the class is initialized successfully
2
+ // to test initialization of the BeanBagDB class
3
+ import { get_pdb_doc } from './pouchdb.js';
4
+ import { throws, strictEqual,rejects } from "assert";
5
+ import BeanBagDB from '../src/index.js';
6
+
7
+
8
+
9
+ let database // this is the global db object
10
+
11
+ describe("Successful database class init (required for further testing) ", async () => {
12
+ it("DB init successful", () => {
13
+ let doc_obj = get_pdb_doc("test_database_25","qwertyuiopaqwsde1254")
14
+ database = new BeanBagDB(doc_obj);
15
+ strictEqual(
16
+ database instanceof BeanBagDB,
17
+ true,
18
+ "The variable is initialized successfully"
19
+ );
20
+ });
21
+ });
22
+
23
+
24
+
25
+
26
+ describe("Testing creation of schema docs", async () => {
27
+ let schema_docs_invalid = [
28
+ {
29
+ name: "",
30
+ description: "",
31
+ schema: {},
32
+ settings: {},
33
+ },
34
+ {
35
+ name: "nos",
36
+ description: "",
37
+ schema: {},
38
+ settings: {},
39
+ },
40
+ {
41
+ name: "contact",
42
+ description: "",
43
+ schema: {},
44
+ settings: {},
45
+ },
46
+ {
47
+ name: "contact",
48
+ description: "This can be left blank",
49
+ schema: {},
50
+ settings: {},
51
+ },
52
+ {
53
+ name: "contact",
54
+ description: "This can be left blank",
55
+ schema: {
56
+ "abc":"something"
57
+ },
58
+ settings: {},
59
+ },
60
+ {
61
+ name: "contact",
62
+ description: "This can be left blank",
63
+ schema: {
64
+ "type":"something",
65
+ },
66
+ settings: {},
67
+ },
68
+ {
69
+ name: "contact",
70
+ description: "This can be left blank",
71
+ schema: {
72
+ "type":"object",
73
+ },
74
+ settings: {},
75
+ },
76
+ {
77
+ name: "contact",
78
+ description: "This can be left blank",
79
+ schema: {
80
+ "type":"object",
81
+ "properties":"something"
82
+ },
83
+ settings: {},
84
+ },
85
+ {
86
+ name: "contact",
87
+ description: "This can be left blank",
88
+ schema: {
89
+ "type":"object",
90
+ "properties":{}
91
+ },
92
+ settings: {},
93
+ },
94
+ {
95
+ name: "contact",
96
+ description: "This can be left blank",
97
+ schema: {
98
+ "type":"object",
99
+ "properties":{"name":{"type":"string"}}
100
+ },
101
+ settings: {},
102
+ },
103
+ {
104
+ name: "contact",
105
+ description: "This can be left blank",
106
+ schema: {
107
+ "type":"object",
108
+ "properties":{"name":{"type":"string"}},
109
+ "additionalProperties":"no"
110
+ },
111
+ settings: {},
112
+ },
113
+ // {
114
+ // name: "contact",
115
+ // description: "This can be left blank",
116
+ // schema: {
117
+ // "type":"object",
118
+ // "properties":{"name":{"type":"string"}},
119
+ // "additionalProperties":true
120
+ // },
121
+ // settings: {},
122
+ // },
123
+ ];
124
+
125
+ let doc_obj = get_pdb_doc("test_database_25", "qwertyuiopaqwsde1254");
126
+ let database = new BeanBagDB(doc_obj);
127
+ database.initialize_db();
128
+ database.ready();
129
+ // schema_docs_invalid.forEach(doc=>{})
130
+ for (let index = 0; index < schema_docs_invalid.length; index++) {
131
+ const element = schema_docs_invalid[index];
132
+
133
+ it("throws error", async () => {
134
+ await rejects(
135
+ async () => {
136
+ await database.insert("schema", element);
137
+ },
138
+ Error
139
+ );
140
+ });
141
+
142
+ }
143
+
144
+ });
145
+
@@ -0,0 +1,73 @@
1
+ // this is a pouch db instance of beanbagdb used for testing.
2
+ import Ajv from 'ajv';
3
+ import PouchDB from 'pouchdb';
4
+ import pouchdbFind from 'pouchdb-find';
5
+ PouchDB.plugin(pouchdbFind)
6
+ import { scryptSync, randomBytes, createCipheriv, createDecipheriv } from 'crypto';
7
+
8
+
9
+ export const get_pdb_doc = (dbname,secret)=>{
10
+ const pdb = new PouchDB(dbname);
11
+ const doc_obj = {
12
+ name: dbname,
13
+ encryption_key: secret,
14
+ api: {
15
+ insert: async (doc) => {
16
+ const result = await pdb.post(doc);
17
+ return result;
18
+ },
19
+ // delete: ()=>{db1.destroy},
20
+ update: async (doc) => {
21
+ const result = await pdb.put(doc);
22
+ return result;
23
+ },
24
+ search: async (query) => {
25
+ const results = await pdb.find(query);
26
+ return results; // of the form {docs:[],...}
27
+ },
28
+ get: async (id) => {
29
+ const data = await pdb.get(id);
30
+ return data;
31
+ },
32
+ delete: async (id) => {
33
+ const doc = await pdb.get(id);
34
+ const resp = await pdb.remove(doc);
35
+ return resp;
36
+ },
37
+ createIndex: async (filter) => {
38
+ const data = await pdb.createIndex(filter);
39
+ return data;
40
+ },
41
+ },
42
+ utils: {
43
+ encrypt: (text, encryptionKey) => {
44
+ const key = scryptSync(encryptionKey, "salt", 32); // Derive a 256-bit key
45
+ const iv = randomBytes(16); // Initialization vector
46
+ const cipher = createCipheriv("aes-256-cbc", key, iv);
47
+ let encrypted = cipher.update(text, "utf8", "hex");
48
+ encrypted += cipher.final("hex");
49
+ return iv.toString("hex") + ":" + encrypted; // Prepend the IV for later use
50
+ },
51
+ decrypt: (encryptedText, encryptionKey) => {
52
+ const key = scryptSync(encryptionKey, "salt", 32); // Derive a 256-bit key
53
+ const [iv, encrypted] = encryptedText
54
+ .split(":")
55
+ .map((part) => Buffer.from(part, "hex"));
56
+ const decipher = createDecipheriv("aes-256-cbc", key, iv);
57
+ let decrypted = decipher.update(encrypted, "hex", "utf8");
58
+ decrypted += decipher.final("utf8");
59
+ return decrypted;
60
+ },
61
+ ping: () => {
62
+ // @TODO ping the database to check connectivity when class is ready to use
63
+ },
64
+ validate_schema: (schema_obj, data_obj)=>{
65
+ const ajv = new Ajv({code: {esm: true}}) // options can be passed, e.g. {allErrors: true}
66
+ const validate = ajv.compile(schema_obj);
67
+ const valid = validate(data_obj);
68
+ return {valid,validate}
69
+ }
70
+ },
71
+ }
72
+ return doc_obj
73
+ }
package/test/test1.js CHANGED
@@ -154,4 +154,25 @@
154
154
  // // let db = new cbbdb(process.env.cdburl, process.env.cdbname, "sample_key");
155
155
  // // await db.ready();
156
156
  // // db.load_plugin("sample",pl1)
157
- // // })();
157
+ // // })();
158
+
159
+ import { get_pdb_doc } from './pouchdb.js';
160
+ import { throws, strictEqual } from "assert";
161
+ import BeanBagDB from '../src/index.js';
162
+
163
+ (async()=>{
164
+ let schema_docs_invalid = [
165
+ {
166
+ "name":"",
167
+ "description":"",
168
+ "schema":{},
169
+ "settings":{}
170
+ }
171
+
172
+ ]
173
+ let doc_obj = get_pdb_doc("test_database_26","qwertyuiopaqwsde1254")
174
+ let database = new BeanBagDB(doc_obj);
175
+ database.initialize_db()
176
+ database.ready()
177
+ let a = await database.insert("schema",schema_docs_invalid[0])
178
+ })()