beanbagdb 0.5.45 → 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.
- package/.github/workflows/deploy_docs.yml +38 -0
- package/.github/workflows/release.yml +3 -3
- package/.github/workflows/test_on_master.yml +36 -0
- package/index.md +1 -0
- package/jsdoc.json +21 -0
- package/package.json +2 -1
- package/src/index.js +58 -3
- package/src/system_schema.js +14 -5
- package/test/init.test.js +5 -74
- package/test/operations.test.js +145 -1
- package/test/pouchdb.js +73 -0
- package/test/test1.js +22 -1
|
@@ -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
|
-
-
|
|
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
|
-
|
|
34
|
-
|
|
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.
|
|
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
|
@@ -158,6 +158,39 @@ class BeanBagDB {
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
|
|
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
|
+
}
|
|
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
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
161
194
|
/**
|
|
162
195
|
* Returns a document with the provided ID
|
|
163
196
|
* @param {String} doc_id - the doc Id (not the primary key)
|
|
@@ -251,7 +284,7 @@ class BeanBagDB {
|
|
|
251
284
|
* @param {Object} data e.g {"name":"","mobile":""...}
|
|
252
285
|
* @param {Object} settings (optional)
|
|
253
286
|
*/
|
|
254
|
-
async insert(schema, data, settings = {}) {
|
|
287
|
+
async insert(schema, data, meta= {},settings = {}) {
|
|
255
288
|
try {
|
|
256
289
|
let doc_obj = await this._insert_pre_checks(schema, data, settings);
|
|
257
290
|
let new_rec = await this.db_api.insert(doc_obj);
|
|
@@ -370,6 +403,11 @@ class BeanBagDB {
|
|
|
370
403
|
|
|
371
404
|
//////// Helper method ////////
|
|
372
405
|
|
|
406
|
+
_generate_random_link(){
|
|
407
|
+
const dictionary = ['rain', 'mars', 'banana', 'earth', 'kiwi', 'mercury', 'fuji', 'hurricane', 'matterhorn', 'snow', 'saturn', 'jupiter', 'peach', 'wind', 'pluto', 'apple', 'k2', 'storm', 'venus', 'denali', 'cloud', 'sunshine', 'mango', 'drizzle', 'pineapple', 'aconcagua', 'gasherbrum', 'apricot', 'neptune', 'fog', 'orange', 'blueberry', 'kilimanjaro', 'uranus', 'grape', 'storm', 'montblanc', 'lemon', 'chooyu', 'raspberry', 'cherry', 'thunder', 'vinson', 'breeze', 'elbrus', 'everest', 'parbat', 'makalu', 'nanga', 'kangchenjunga', 'lightning', 'cyclone', 'comet', 'asteroid', 'pomegranate', 'nectarine', 'clementine', 'strawberry', 'tornado', 'avalanche', 'andes', 'rockies', 'himalayas', 'pyrenees', 'carpathians', 'cascade', 'etna', 'vesuvius', 'volcano', 'tundra', 'whirlwind', 'iceberg', 'eclipse', 'zephyr', 'tropic', 'monsoon', 'aurora'];
|
|
408
|
+
return Array.from({ length: 4 }, () => dictionary[Math.floor(Math.random() * dictionary.length)]).join('-');
|
|
409
|
+
}
|
|
410
|
+
|
|
373
411
|
_check_required_fields(requiredFields,obj){
|
|
374
412
|
for (const field of requiredFields) {
|
|
375
413
|
if (!obj[field]) {throw new Error(`${field} is required`);}
|
|
@@ -452,7 +490,8 @@ class BeanBagDB {
|
|
|
452
490
|
meta: {
|
|
453
491
|
createdOn: this._get_now_unix_timestamp(),
|
|
454
492
|
tags: [],
|
|
455
|
-
app :{}
|
|
493
|
+
app :{},
|
|
494
|
+
link : this._generate_random_link() // there is a link by default. overwrite this if user provided one but only before checking if it is unique
|
|
456
495
|
},
|
|
457
496
|
schema: schema_name,
|
|
458
497
|
};
|
|
@@ -527,7 +566,7 @@ class BeanBagDB {
|
|
|
527
566
|
* @param {Object} schema
|
|
528
567
|
* @param {Object} data
|
|
529
568
|
*/
|
|
530
|
-
async _insert_pre_checks(schema, data, settings = {}) {
|
|
569
|
+
async _insert_pre_checks(schema, data,meta={} ,settings = {}) {
|
|
531
570
|
// schema search
|
|
532
571
|
let sch_search = await this.search({
|
|
533
572
|
selector: { schema: "schema", "data.name": schema },
|
|
@@ -539,8 +578,24 @@ class BeanBagDB {
|
|
|
539
578
|
// validate data
|
|
540
579
|
this.validate_data(schemaDoc.schema, data);
|
|
541
580
|
|
|
581
|
+
// validate meta
|
|
582
|
+
this.validate_data(sys_sch.editable_metadata_schema, meta);
|
|
583
|
+
|
|
584
|
+
// duplicate meta.link check
|
|
585
|
+
if(meta.link){
|
|
586
|
+
let link_search = await this.search({ selector: {"meta.link":meta.link} });
|
|
587
|
+
console.log(link_search);
|
|
588
|
+
if (link_search.docs.length > 0) {
|
|
589
|
+
throw new Error("This link already exists in the database");
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
542
593
|
// special checks for special docs
|
|
543
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
|
+
}
|
|
544
599
|
// @TODO : check if single record setting is set to true
|
|
545
600
|
|
|
546
601
|
// duplicate check
|
package/src/system_schema.js
CHANGED
|
@@ -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:
|
|
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",
|
|
@@ -45,7 +48,7 @@ export const schema_schema = {
|
|
|
45
48
|
items: {
|
|
46
49
|
type: "string",
|
|
47
50
|
},
|
|
48
|
-
maxItems:
|
|
51
|
+
maxItems: 50,
|
|
49
52
|
},
|
|
50
53
|
encrypted_fields: {
|
|
51
54
|
type: "array",
|
|
@@ -53,7 +56,7 @@ export const schema_schema = {
|
|
|
53
56
|
items: {
|
|
54
57
|
type: "string",
|
|
55
58
|
},
|
|
56
|
-
maxItems:
|
|
59
|
+
maxItems: 50,
|
|
57
60
|
},
|
|
58
61
|
single_record: {
|
|
59
62
|
type: "boolean",
|
|
@@ -68,7 +71,7 @@ export const schema_schema = {
|
|
|
68
71
|
},
|
|
69
72
|
settings: {
|
|
70
73
|
primary_key: ["name"],
|
|
71
|
-
editable_fields: ["schema", "settings"],
|
|
74
|
+
editable_fields: ["schema", "settings","description"],
|
|
72
75
|
},
|
|
73
76
|
};
|
|
74
77
|
|
|
@@ -175,6 +178,12 @@ export const editable_metadata_schema = {
|
|
|
175
178
|
items:{type:"string"},
|
|
176
179
|
default:[],
|
|
177
180
|
maxItems: 40,
|
|
181
|
+
},
|
|
182
|
+
link:{
|
|
183
|
+
type:"string",
|
|
184
|
+
minLength:2,
|
|
185
|
+
maxLength:2000,
|
|
186
|
+
pattern: "^[a-zA-Z0-9-]+$"
|
|
178
187
|
}
|
|
179
188
|
}
|
|
180
189
|
}
|
package/test/init.test.js
CHANGED
|
@@ -1,83 +1,13 @@
|
|
|
1
|
-
// to test initialization of the BeanBagDB class
|
|
2
|
-
import
|
|
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,
|
package/test/operations.test.js
CHANGED
|
@@ -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
|
+
|
package/test/pouchdb.js
ADDED
|
@@ -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
|
+
})()
|