beanbagdb 0.6.4 → 0.6.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beanbagdb",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
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",
package/src/index.js CHANGED
@@ -407,7 +407,7 @@ export class BeanBagDB {
407
407
  throw new DocCreationError(`${v_errors.join(",")}.`)
408
408
  }
409
409
 
410
- if(input.schema=="setting_edge"){throw new DocCreationError("This type of record can only be created through the create_edge api")}
410
+ // if(input.schema=="system_edge"){throw new DocCreationError("This type of record can only be created through the create_edge api")}
411
411
  if(Object.keys(input.data).length==0){throw new DocCreationError(`No data provided`)}
412
412
  try {
413
413
  let doc_obj = await this._insert_pre_checks(input.schema, input.data,input?.meta||{}, input?.settings||{});
@@ -564,6 +564,10 @@ export class BeanBagDB {
564
564
  // todo : what if additionalField are allowed ??
565
565
  let updated_data = { ...full_doc.data, ...allowed_updates };
566
566
 
567
+ if(full_doc.schema=="system_edge"){
568
+ // extra checks required. if everything is correct
569
+ updated_data = await this._create_edge(updated_data)
570
+ }
567
571
  updated_data = this.util_validate_data({schema:schema.schema,data: updated_data});
568
572
 
569
573
  // primary key check if multiple records can be created
@@ -622,8 +626,6 @@ export class BeanBagDB {
622
626
  }
623
627
 
624
628
 
625
-
626
-
627
629
  /**
628
630
  * Deletes a document from the database by its ID.
629
631
  *
@@ -721,6 +723,21 @@ export class BeanBagDB {
721
723
  return schemas
722
724
  }
723
725
 
726
+ },
727
+ schema_icons: async (criteria)=>{
728
+ let schemaSearch = await this.db_api.search({
729
+ selector: { schema: "schema" },
730
+ });
731
+ // console.log(schemaSearch)
732
+ if (schemaSearch.docs.length == 0) {
733
+ throw new DocNotFoundError(BeanBagDB.error_codes.schema_not_found);
734
+ }else{
735
+ let schemas = {}
736
+ schemaSearch.docs.map(doc=>{
737
+ schemas[doc.data.name] = doc.data.settings.svg_icon25||""
738
+ })
739
+ return schemas
740
+ }
724
741
  }
725
742
  }
726
743
  if(!input.type){throw new ValidationError("No type provided. Must be: "+Object.keys(fetch_docs).join(","))}
@@ -821,21 +838,31 @@ export class BeanBagDB {
821
838
  * @param {object} node1
822
839
  * @param {object} node2
823
840
  * @param {string} edge_name
824
- * @param {*} edge_label
841
+ * @param {string} note
825
842
  * @returns {Object}
826
843
  */
827
- async create_edge(input){
828
- const {node1,node2,edge_name,edge_label=""} = input
844
+ async _create_edge(input){
845
+ console.log(input)
846
+ let {node1,node2,edge_name,note=""} = input
829
847
  this._check_ready_to_use();
830
848
  if(!edge_name){throw new ValidationError("edge_name required")}
831
- if(Object.keys(node1)==0){throw new ValidationError("node1 required")}
832
- if(Object.keys(node2)==0){throw new ValidationError("node2 required")}
833
-
849
+ if(!node1|| Object.keys(node1).length==0){throw new ValidationError("node1 required")}
850
+ if(!node2|| Object.keys(node2).length==0){throw new ValidationError("node2 required")}
851
+ // if nodes are of type string, they are assumed to be ids since they are stored in the DB as ids
852
+ if(typeof(node1)=="string"){node1 = {_id:node1}}
853
+ if(typeof(node2)=="string"){node2 = {_id:node2}}
834
854
  let n1 = await this.read(node1)
835
855
  let n2 = await this.read(node2)
856
+ if(n1.doc._id==n2.doc._id){
857
+ throw new ValidationError("Both nodes cannot be the same")
858
+ }
859
+ if(n1.doc.schema=="system_edge"|| n2.doc.schema=="system_edge"){
860
+ throw new ValidationError("A node cannot be an existing edge document")
861
+ }
836
862
  let edges_constraint
837
863
 
838
864
  try {
865
+ // check if edge_name has a related edge_constraint
839
866
  let d = await this.read({schema:"system_edge_constraint",data:{name:edge_name}})
840
867
  edges_constraint = d["doc"]["data"]
841
868
  let errors = []
@@ -850,7 +877,7 @@ async create_edge(input){
850
877
  node2id = n1.doc._id
851
878
  }
852
879
  }else{
853
- this.errors.push("Invalid nodes.This config of nodes not allowed")
880
+ errors.push("Invalid nodes.This config of nodes not allowed")
854
881
  }
855
882
 
856
883
  let records = await this.search({selector:{schema:"system_edge","data.edge_name":edge_name}})
@@ -870,18 +897,17 @@ async create_edge(input){
870
897
  }
871
898
 
872
899
  if(errors.length==0){
873
- let edge = await this.create({schema:"system_edge",data:{node1: node1id , node2: node1id ,edge_name:edge_name }})
874
- return edge
900
+ // let edge = await this.create({schema:"system_edge",data:})
901
+ return {node1: node1id , node2: node2id ,edge_name:edge_name ,note:note}
875
902
  }else{
876
903
  throw new RelationError(errors)
877
904
  }
878
905
 
879
906
  } catch (error) {
880
907
  if(error instanceof DocNotFoundError){
881
- let doc = {node1:"*",node2:"*",name:edge_name,label:edge_label}
908
+ let doc = {node1:"*",node2:"*",name:edge_name,note:note}
882
909
  let new_doc = await this.create({schema:"system_edge_constraint",data:doc})
883
- let edge = await this.create({schema:"system_edge",data:{node1: n1.doc._id,node2: n2.doc._id,edge_name:edge_name }})
884
- return edge
910
+ return {node1: n1.doc._id,node2: n2.doc._id,edge_name:edge_name ,note:note}
885
911
  }else{
886
912
  throw error
887
913
  }
@@ -1142,7 +1168,10 @@ async _upgrade_schema_in_bulk(schemas,log_upgrade=false,log_message="Schema Upgr
1142
1168
  // validate data
1143
1169
  if(!schemaDoc.active){throw new DocCreationError(`The schema "${schema}" is not active`)}
1144
1170
 
1145
- let new_data = this.util_validate_data({schema:schemaDoc.schema, data});
1171
+ let new_data
1172
+ if(schema!="system_edge"){
1173
+ new_data = this.util_validate_data({schema:schemaDoc.schema, data});
1174
+ }
1146
1175
 
1147
1176
  // validate meta
1148
1177
  if(Object.keys(meta).length>0){
@@ -1161,6 +1190,9 @@ async _upgrade_schema_in_bulk(schemas,log_upgrade=false,log_message="Schema Upgr
1161
1190
  if (schema == "schema") {
1162
1191
  //more checks are required
1163
1192
  this.util_validate_schema_object(new_data);
1193
+ }else if(schema == "system_edge"){
1194
+ let create_edge_after_checks = await this._create_edge(data)
1195
+ new_data = create_edge_after_checks
1164
1196
  }
1165
1197
  // @TODO : check if single record setting is set to true
1166
1198
  //console.log(schemaDoc)
@@ -11,7 +11,7 @@ export const default_app = {
11
11
  active: true,
12
12
  description: "Meta-schema or the schema for defining other schemas",
13
13
  system_generated: true,
14
- version: 0.88,
14
+ version: 1,
15
15
  title: "Schema document",
16
16
  schema: {
17
17
  type: "object",
@@ -127,6 +127,13 @@ export const default_app = {
127
127
  description:
128
128
  "Describes how this schema was installed in database. This is determined by the system. By default the value is human. Possible value: name of the app , where it was cloned from etc...",
129
129
  },
130
+ svg_icon25: {
131
+ type: "string",
132
+ title: "SVG Icon for schema",
133
+ default: "human",
134
+ description:
135
+ "The height and width should be 25px",
136
+ }
130
137
  },
131
138
  required: [
132
139
  "primary_keys",
@@ -142,11 +149,12 @@ export const default_app = {
142
149
  non_editable_fields: ["system_generated"],
143
150
  encrypted_fields: [],
144
151
  display_fields: ["name", "version", "description", "title", "active"],
152
+ svg_icon25:"<svg xmlns='http://www.w3.org/2000/svg' width='25' height='16' fill='currentColor' class='bi bi-database-fill-gear' viewBox='0 0 16 16'><path d='M8 1c-1.573 0-3.022.289-4.096.777C2.875 2.245 2 2.993 2 4s.875 1.755 1.904 2.223C4.978 6.711 6.427 7 8 7s3.022-.289 4.096-.777C13.125 5.755 14 5.007 14 4s-.875-1.755-1.904-2.223C11.022 1.289 9.573 1 8 1'/><path d='M2 7v-.839c.457.432 1.004.751 1.49.972C4.722 7.693 6.318 8 8 8s3.278-.307 4.51-.867c.486-.22 1.033-.54 1.49-.972V7c0 .424-.155.802-.411 1.133a4.51 4.51 0 0 0-4.815 1.843A12 12 0 0 1 8 10c-1.573 0-3.022-.289-4.096-.777C2.875 8.755 2 8.007 2 7m6.257 3.998L8 11c-1.682 0-3.278-.307-4.51-.867-.486-.22-1.033-.54-1.49-.972V10c0 1.007.875 1.755 1.904 2.223C4.978 12.711 6.427 13 8 13h.027a4.55 4.55 0 0 1 .23-2.002m-.002 3L8 14c-1.682 0-3.278-.307-4.51-.867-.486-.22-1.033-.54-1.49-.972V13c0 1.007.875 1.755 1.904 2.223C4.978 15.711 6.427 16 8 16c.536 0 1.058-.034 1.555-.097a4.5 4.5 0 0 1-1.3-1.905m3.631-4.538c.18-.613 1.048-.613 1.229 0l.043.148a.64.64 0 0 0 .921.382l.136-.074c.561-.306 1.175.308.87.869l-.075.136a.64.64 0 0 0 .382.92l.149.045c.612.18.612 1.048 0 1.229l-.15.043a.64.64 0 0 0-.38.921l.074.136c.305.561-.309 1.175-.87.87l-.136-.075a.64.64 0 0 0-.92.382l-.045.149c-.18.612-1.048.612-1.229 0l-.043-.15a.64.64 0 0 0-.921-.38l-.136.074c-.561.305-1.175-.309-.87-.87l.075-.136a.64.64 0 0 0-.382-.92l-.148-.045c-.613-.18-.613-1.048 0-1.229l.148-.043a.64.64 0 0 0 .382-.921l-.074-.136c-.306-.561.308-1.175.869-.87l.136.075a.64.64 0 0 0 .92-.382zM14 12.5a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0'/></svg>"
145
153
  },
146
154
  },
147
155
  {
148
156
  system_generated: true,
149
- version: 0.63,
157
+ version: 1,
150
158
  description:
151
159
  "To store user defined key. this can include anything like API tokens etc. There is a special method to fetch this. The values are encrypted",
152
160
  name: "system_key",
@@ -181,10 +189,11 @@ export const default_app = {
181
189
  primary_keys: ["name"],
182
190
  encrypted_fields: ["value"],
183
191
  non_editable_fields: [],
192
+ svg_icon25:`<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-key-fill" viewBox="0 0 16 16"><path d="M3.5 11.5a3.5 3.5 0 1 1 3.163-5H14L15.5 8 14 9.5l-1-1-1 1-1-1-1 1-1-1-1 1H6.663a3.5 3.5 0 0 1-3.163 2M2.5 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2"/></svg>`
184
193
  },
185
194
  },
186
195
  {
187
- version: 0.67,
196
+ version: 1,
188
197
  system_generated: true,
189
198
  description:
190
199
  "The system relies on these settings for proper functioning or enabling optional features.",
@@ -211,6 +220,7 @@ export const default_app = {
211
220
  primary_keys: ["name"],
212
221
  non_editable_fields: ["name"],
213
222
  encrypted_fields: [],
223
+ svg_icon25:`<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-gear-fill" viewBox="0 0 16 16"><path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"/></svg>`
214
224
  },
215
225
  },
216
226
  {
@@ -218,7 +228,7 @@ export const default_app = {
218
228
  title: "Edge constraint",
219
229
  system_generated: true,
220
230
  active: true,
221
- version: 0.60,
231
+ version: 1,
222
232
  description:
223
233
  "To define edge constraints for simple directed graph of records.",
224
234
  schema: {
@@ -268,6 +278,7 @@ export const default_app = {
268
278
  primary_keys: ["name"],
269
279
  non_editable_fields: ["name"],
270
280
  encrypted_fields: [],
281
+ svg_icon25:`<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-node-plus-fill" viewBox="0 0 16 16"><path d="M11 13a5 5 0 1 0-4.975-5.5H4A1.5 1.5 0 0 0 2.5 6h-1A1.5 1.5 0 0 0 0 7.5v1A1.5 1.5 0 0 0 1.5 10h1A1.5 1.5 0 0 0 4 8.5h2.025A5 5 0 0 0 11 13m.5-7.5v2h2a.5.5 0 0 1 0 1h-2v2a.5.5 0 0 1-1 0v-2h-2a.5.5 0 0 1 0-1h2v-2a.5.5 0 0 1 1 0"/></svg>`
271
282
  },
272
283
  },
273
284
  {
@@ -275,12 +286,12 @@ export const default_app = {
275
286
  title: "Edge in the system graph",
276
287
  active: true,
277
288
  system_generated: true,
278
- version: 0.52,
289
+ version: 1,
279
290
  description: "To define edges in the simple directed graph of records.",
280
291
  schema: {
281
292
  type: "object",
282
293
  additionalProperties: true,
283
- required: ["node1", "node2", "edge_type"],
294
+ required: ["node1", "node2", "edge_name"],
284
295
  properties: {
285
296
  node1: {
286
297
  type: "string",
@@ -291,12 +302,17 @@ export const default_app = {
291
302
  edge_name: {
292
303
  type: "string",
293
304
  },
305
+ note:{
306
+ type:"string",
307
+ default:" "
308
+ }
294
309
  },
295
310
  },
296
311
  settings: {
297
- primary_keys: ["node1", "node2", "edge_type"],
312
+ primary_keys: ["node1", "node2", "edge_name"],
298
313
  non_editable_fields: ["edge_type"],
299
314
  encrypted_fields: [],
315
+ svg_icon25:`<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-diagram-2-fill" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M6 3.5A1.5 1.5 0 0 1 7.5 2h1A1.5 1.5 0 0 1 10 3.5v1A1.5 1.5 0 0 1 8.5 6v1H11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 5 7h2.5V6A1.5 1.5 0 0 1 6 4.5zm-3 8A1.5 1.5 0 0 1 4.5 10h1A1.5 1.5 0 0 1 7 11.5v1A1.5 1.5 0 0 1 5.5 14h-1A1.5 1.5 0 0 1 3 12.5zm6 0a1.5 1.5 0 0 1 1.5-1.5h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1A1.5 1.5 0 0 1 9 12.5z"/></svg>`
300
316
  },
301
317
  },
302
318
  {
@@ -304,7 +320,7 @@ export const default_app = {
304
320
  title: "Media content",
305
321
  active: true,
306
322
  system_generated: true,
307
- version: 0.62,
323
+ version: 1,
308
324
  description: "To store images as Base64",
309
325
  schema: {
310
326
  type: "object",
@@ -329,6 +345,7 @@ export const default_app = {
329
345
  primary_keys: ["caption"],
330
346
  non_editable_fields: [],
331
347
  encrypted_fields: [],
348
+ svg_icon25:`<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-file-image" viewBox="0 0 16 16"><path d="M8.002 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0"/><path d="M12 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8l-2.083-2.083a.5.5 0 0 0-.76.063L8 11 5.835 9.7a.5.5 0 0 0-.611.076L3 12z"/></svg>`
332
349
  },
333
350
  },
334
351
  {
@@ -336,7 +353,7 @@ export const default_app = {
336
353
  system_generated: true,
337
354
  title: "System log",
338
355
  active: true,
339
- version: 0.52,
356
+ version: 1,
340
357
  description: "To define edges in the simple directed graph of records.",
341
358
  schema: {
342
359
  type: "object",
@@ -362,6 +379,7 @@ export const default_app = {
362
379
  primary_keys: [],
363
380
  non_editable_fields: [],
364
381
  encrypted_fields: [],
382
+ svg_icon25:`<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-clock-history" viewBox="0 0 16 16"><path d="M8.515 1.019A7 7 0 0 0 8 1V0a8 8 0 0 1 .589.022zm2.004.45a7 7 0 0 0-.985-.299l.219-.976q.576.129 1.126.342zm1.37.71a7 7 0 0 0-.439-.27l.493-.87a8 8 0 0 1 .979.654l-.615.789a7 7 0 0 0-.418-.302zm1.834 1.79a7 7 0 0 0-.653-.796l.724-.69q.406.429.747.91zm.744 1.352a7 7 0 0 0-.214-.468l.893-.45a8 8 0 0 1 .45 1.088l-.95.313a7 7 0 0 0-.179-.483m.53 2.507a7 7 0 0 0-.1-1.025l.985-.17q.1.58.116 1.17zm-.131 1.538q.05-.254.081-.51l.993.123a8 8 0 0 1-.23 1.155l-.964-.267q.069-.247.12-.501m-.952 2.379q.276-.436.486-.908l.914.405q-.24.54-.555 1.038zm-.964 1.205q.183-.183.35-.378l.758.653a8 8 0 0 1-.401.432z"/><path d="M8 1a7 7 0 1 0 4.95 11.95l.707.707A8.001 8.001 0 1 1 8 0z"/><path d="M7.5 3a.5.5 0 0 1 .5.5v5.21l3.248 1.856a.5.5 0 0 1-.496.868l-3.5-2A.5.5 0 0 1 7 9V3.5a.5.5 0 0 1 .5-.5"/></svg>`
365
383
  },
366
384
  },
367
385
  {
@@ -369,7 +387,7 @@ export const default_app = {
369
387
  system_generated: true,
370
388
  title: "Executable script",
371
389
  active: true,
372
- version: 0.2,
390
+ version: 1,
373
391
  description: "To create scripts that implement some logic. Can run both on browser and client.",
374
392
  schema: {
375
393
  type: "object",
@@ -409,6 +427,7 @@ export const default_app = {
409
427
  primary_keys: ["name"],
410
428
  non_editable_fields: [],
411
429
  encrypted_fields: [],
430
+ svg_icon25:`<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-braces-asterisk" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1.114 8.063V7.9c1.005-.102 1.497-.615 1.497-1.6V4.503c0-1.094.39-1.538 1.354-1.538h.273V2h-.376C2.25 2 1.49 2.759 1.49 4.352v1.524c0 1.094-.376 1.456-1.49 1.456v1.299c1.114 0 1.49.362 1.49 1.456v1.524c0 1.593.759 2.352 2.372 2.352h.376v-.964h-.273c-.964 0-1.354-.444-1.354-1.538V9.663c0-.984-.492-1.497-1.497-1.6M14.886 7.9v.164c-1.005.103-1.497.616-1.497 1.6v1.798c0 1.094-.39 1.538-1.354 1.538h-.273v.964h.376c1.613 0 2.372-.759 2.372-2.352v-1.524c0-1.094.376-1.456 1.49-1.456v-1.3c-1.114 0-1.49-.362-1.49-1.456V4.352C14.51 2.759 13.75 2 12.138 2h-.376v.964h.273c.964 0 1.354.444 1.354 1.538V6.3c0 .984.492 1.497 1.497 1.6M7.5 11.5V9.207l-1.621 1.621-.707-.707L6.792 8.5H4.5v-1h2.293L5.172 5.879l.707-.707L7.5 6.792V4.5h1v2.293l1.621-1.621.707.707L9.208 7.5H11.5v1H9.207l1.621 1.621-.707.707L8.5 9.208V11.5z"/></svg>`
412
431
  },
413
432
  },
414
433
  ],
@@ -464,7 +483,12 @@ export const app_data_schema = {
464
483
  default_setting:{
465
484
  type: "object",
466
485
  additionalProperties:true,
467
- default : {}
486
+ default : {
487
+ primary_keys: [],
488
+ non_editable_fields: [],
489
+ encrypted_fields: [],
490
+ svg_icon25:`<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-file-earmark" viewBox="0 0 16 16"><path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5z"/></svg>`
491
+ }
468
492
  }
469
493
  },
470
494
  };
package/test/couchdb.js CHANGED
@@ -1,9 +1,9 @@
1
- // const crypto = require('crypto');
1
+ import {BeanBagDB} from '../src/index.js';
2
+ import crypto from 'crypto'
2
3
  // const SDB = require("beanbagdb")
3
4
 
4
5
  import Ajv from 'ajv';
5
6
  import nano from "nano";
6
- import BeanBagDB from '../src/index.js';
7
7
 
8
8
  export class BeanBagDB_CouchDB extends BeanBagDB {
9
9
  constructor(db_url,db_name,encryption_key){
@@ -41,30 +41,87 @@ export class BeanBagDB_CouchDB extends BeanBagDB {
41
41
  }
42
42
  },
43
43
  utils:{
44
- encrypt: async (text,encryptionKey)=>{
45
- const key = crypto.scryptSync(encryptionKey, 'salt', 32); // Derive a 256-bit key
46
- const iv = crypto.randomBytes(16); // Initialization vector
47
- const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
48
- let encrypted = cipher.update(text, 'utf8', 'hex');
49
- encrypted += cipher.final('hex');
50
- return iv.toString('hex') + ':' + encrypted; // Prepend the IV for later use
44
+ encrypt: async (text, encryptionKey) => {
45
+ const encoder = new TextEncoder();
46
+ const data = encoder.encode(text); // Encode the text into bytes
47
+
48
+ // Ensure the encryption key is of valid length (16, 24, or 32 bytes for AES-GCM)
49
+ const keyBytes = encoder.encode(encryptionKey);
50
+ if (
51
+ keyBytes.length !== 16 &&
52
+ keyBytes.length !== 24 &&
53
+ keyBytes.length !== 32
54
+ ) {
55
+ throw new Error("Encryption key must be 16, 24, or 32 bytes long.");
56
+ }
57
+
58
+ // Convert encryptionKey to CryptoKey
59
+ const key = await crypto.subtle.importKey(
60
+ "raw",
61
+ keyBytes,
62
+ { name: "AES-GCM" },
63
+ false,
64
+ ["encrypt"]
65
+ );
66
+
67
+ // Create a random initialization vector (IV)
68
+ const iv = crypto.getRandomValues(new Uint8Array(12)); // 12 bytes for AES-GCM
69
+
70
+ // Encrypt the data
71
+ const encrypted = await crypto.subtle.encrypt(
72
+ { name: "AES-GCM", iv: iv },
73
+ key,
74
+ data
75
+ );
76
+
77
+ // Convert encrypted data and IV to base64 for storage
78
+ const encryptedArray = new Uint8Array(encrypted);
79
+ const encryptedText = btoa(String.fromCharCode(...encryptedArray));
80
+ const ivText = btoa(String.fromCharCode(...iv));
81
+
82
+ return ivText + ":" + encryptedText; // Store IV and encrypted text together
51
83
  },
52
- decrypt : async (encryptedText, encryptionKey)=>{
53
- const key = crypto.scryptSync(encryptionKey, 'salt', 32); // Derive a 256-bit key
54
- const [iv, encrypted] = encryptedText.split(':').map(part => Buffer.from(part, 'hex'));
55
- const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
56
- let decrypted = decipher.update(encrypted, 'hex', 'utf8');
57
- decrypted += decipher.final('utf8');
58
- return decrypted;
84
+ decrypt: async (encryptedText, encryptionKey) => {
85
+ const [ivText, encryptedData] = encryptedText.split(":");
86
+
87
+ // Convert IV and encrypted data from base64 to byte arrays
88
+ const iv = Uint8Array.from(atob(ivText), (c) => c.charCodeAt(0));
89
+ const encryptedArray = Uint8Array.from(atob(encryptedData), (c) =>
90
+ c.charCodeAt(0)
91
+ );
92
+
93
+ const encoder = new TextEncoder();
94
+
95
+ // Convert encryptionKey to CryptoKey
96
+ const key = await crypto.subtle.importKey(
97
+ "raw",
98
+ encoder.encode(encryptionKey),
99
+ { name: "AES-GCM" },
100
+ false,
101
+ ["decrypt"]
102
+ );
103
+
104
+ // Decrypt the data
105
+ const decrypted = await crypto.subtle.decrypt(
106
+ { name: "AES-GCM", iv: iv },
107
+ key,
108
+ encryptedArray
109
+ );
110
+
111
+ // Convert decrypted data back to a string
112
+ const decoder = new TextDecoder();
113
+ return decoder.decode(decrypted);
59
114
  },
60
115
  ping : ()=>{
61
116
  // @TODO ping the database to check connectivity when class is ready to use
62
117
  },
63
118
  validate_schema: (schema_obj, data_obj)=>{
64
- const ajv = new Ajv({code: {esm: true}}) // options can be passed, e.g. {allErrors: true}
119
+ const ajv = new Ajv({code: {esm: true},strict:false,useDefaults:true}) // options can be passed, e.g. {allErrors: true}
120
+ const data_copy = {...data_obj}
65
121
  const validate = ajv.compile(schema_obj);
66
- const valid = validate(data_obj);
67
- return {valid,validate}
122
+ const valid = validate(data_copy);
123
+
124
+ return {valid,validate,data:data_copy}
68
125
  }
69
126
  }
70
127
  }