beanbagdb 0.0.1 → 0.0.5

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/index.js DELETED
@@ -1,544 +0,0 @@
1
- Ajv = require("ajv");
2
- class InfoDB {
3
- constructor(db_instance) {
4
- if (!db_instance["name"]) {
5
- throw new Error("Database name is required. None was provided");
6
- }
7
- this.init_class();
8
- this.db = db_instance.api
9
- }
10
- init_class() {
11
- // run from the constructor to initialize the class with required internal variables
12
- this.valid_system_settings = {
13
- db_system_log: {
14
- schema: {
15
- type: "object",
16
- properties: {
17
- logs: {
18
- type: "array",
19
- items: {
20
- type: "object",
21
- additionalProperties: true,
22
- },
23
- minItems: 0,
24
- },
25
- },
26
- },
27
- settings: {
28
- default_data: { logs: [] },
29
- editable_fields: ["logs"],
30
- },
31
- },
32
- tags: {
33
- schema: {
34
- type: "object",
35
- properties: {
36
- tags: {
37
- type: "array",
38
- maxItems: 100,
39
- minItems: 0,
40
- uniqueItems: true,
41
- items: {
42
- type: "object",
43
- properties: {
44
- name: {
45
- type: "string",
46
-
47
- maxLength: 500,
48
- pattern: "^[a-zA-Z][a-zA-Z0-9-_.]*$",
49
- },
50
- note: {
51
- type: "string",
52
- },
53
- },
54
- },
55
- },
56
- },
57
- },
58
- settings: {
59
- default_data: {
60
- tags: [],
61
- },
62
- editable_fields: ["tags"],
63
- },
64
- },
65
- web_settings: {
66
- schema: {
67
- type: "object",
68
- properties: {
69
- theme: {
70
- type: "string",
71
- enum: ["light", "dark"],
72
- default: "dark",
73
- },
74
- },
75
- },
76
- settings: {
77
- editable_fields: ["theme"],
78
- default_data: {
79
- theme: "dark",
80
- },
81
- },
82
- },
83
- };
84
- this.valid_schema_doc_schema = {
85
- name: "schema_doc",
86
- schema: {
87
- type: "object",
88
- additionalProperties: true,
89
- properties: {
90
- name: {
91
- type: "string",
92
- minLength: 5,
93
- maxLength: 50,
94
- pattern: "^[a-zA-Z][a-zA-Z0-9_]*$",
95
- },
96
- properties: {
97
- type: "object",
98
- additionalProperties: true,
99
- minProperties: 1,
100
- maxProperties: 20,
101
- },
102
- settings: {
103
- type: "object",
104
- additionalProperties: true,
105
- properties: {
106
- primary_key: {
107
- type: "array",
108
- default: [],
109
- items: {
110
- type: "string",
111
- },
112
- maxItems: 10,
113
- },
114
- editable_fields: {
115
- type: "array",
116
- default: [],
117
- items: {
118
- type: "string",
119
- },
120
- maxItems: 20,
121
- },
122
- single_record: {
123
- type: "boolean",
124
- default: false,
125
- description:
126
- "If set, only a single records with this schema will be allowed to insert in the database",
127
- },
128
- },
129
- },
130
- },
131
- required: ["name", "schema", "settings"],
132
- },
133
- settings: {
134
- primary_key: ["name"],
135
- editable_fields: ["schema", "settings"],
136
- },
137
- };
138
- this.sample_schema = {
139
- name: "my_contact",
140
- schema: {
141
- title: "People",
142
- type: "object",
143
- properties: {
144
- name: {
145
- type: "string",
146
- },
147
- emails: {
148
- type: "array",
149
- items: {
150
- type: "string",
151
- format: "email",
152
- },
153
- },
154
- phones: {
155
- type: "array",
156
- items: {
157
- type: "string",
158
- },
159
- },
160
- address: {
161
- type: "string",
162
- },
163
- notes: {
164
- type: "string",
165
- },
166
- birth_date: {
167
- type: "string",
168
- format: "date",
169
- },
170
- company: {
171
- type: "string",
172
- },
173
- website: {
174
- type: "string",
175
- format: "uri",
176
- },
177
- socialMedia: {
178
- type: "object",
179
- properties: {
180
- twitter: { type: "string" },
181
- facebook: { type: "string" },
182
- linkedin: { type: "string" },
183
- },
184
- },
185
- gender: {
186
- type: "string",
187
- enum: ["male", "female", "other"],
188
- },
189
- maritalStatus: {
190
- type: "string",
191
- enum: ["single", "married", "divorced", "widowed", "other"],
192
- },
193
- hobbies: {
194
- type: "array",
195
- items: {
196
- type: "string",
197
- },
198
- },
199
- languages: {
200
- type: "array",
201
- items: {
202
- type: "string",
203
- },
204
- },
205
- education: {
206
- type: "array",
207
- items: {
208
- type: "object",
209
- properties: {
210
- degree: { type: "string" },
211
- institution: { type: "string" },
212
- year: { type: "integer" },
213
- },
214
- required: ["degree", "institution", "year"],
215
- },
216
- },
217
- skills: {
218
- type: "array",
219
- items: {
220
- type: "string",
221
- },
222
- },
223
- },
224
- required: ["name"],
225
- },
226
- settings: {
227
- primary_key: ["name"],
228
- },
229
- };
230
- }
231
-
232
- async initialize_db() {
233
- try {
234
- await this.log({ message: "Database created" });
235
- await this.db.createIndex({
236
- index: { fields: ["schema", "data", "meta"] },
237
- });
238
- let tag_doc = await this.get_setting_doc("tags");
239
- let web_setting = await this.get_setting_doc("web_settings");
240
- let sample_schema = await this.insert("schema_doc", this.sample_schema);
241
- await this.log({ message: "Database initialized" });
242
- //let b = await this.db.allDocs({ include_docs: true });
243
- //console.log(b);
244
- } catch (error) {
245
- console.log(error);
246
- //let b = await this.db.allDocs({ include_docs: true });
247
- //console.log(b);
248
- throw error;
249
- }
250
- }
251
-
252
- async log(stuff) {
253
- let log_obj = await this.get_setting_doc("db_system_log");
254
- stuff["added_on"] = this.get_now_unix_timestamp();
255
- log_obj["data"]["logs"].push(stuff);
256
- let a = await this.update_data(
257
- log_obj["_id"],
258
- log_obj["_rev"],
259
- "setting",
260
- log_obj["data"]
261
- );
262
- }
263
-
264
- async get_setting_doc(setting_name) {
265
- try {
266
- if (Object.keys(this.valid_system_settings).indexOf(setting_name) == -1) {
267
- throw new Error(
268
- "Invalid setting name provided. Valid setting names are :" +
269
- Object.keys(this.valid_system_settings)
270
- );
271
- }
272
-
273
- let query = {
274
- selector: { schema: "setting", data: { name: setting_name } },
275
- };
276
- // console.log(query)
277
- let search = await this.db.search(query);
278
- if (search["docs"].length == 0) {
279
- // generate a new doc and return it
280
- let setting_details = this.valid_system_settings[setting_name];
281
- //console.log(setting_details);
282
- let blank_data = { ...setting_details["settings"]["default_data"] };
283
- blank_data["name"] = setting_name;
284
- let blank_record = this.get_blank_doc("setting");
285
- blank_record["data"] = blank_data;
286
- blank_record["meta"]["system"] = true;
287
- // console.log(blank_record);
288
- let new_id = await this.insert_doc(blank_record);
289
- let a = await this.get(new_id["id"]);
290
- return a;
291
- } else {
292
- return search["docs"][0];
293
- }
294
- } catch (error) {
295
- console.log(error);
296
- }
297
- }
298
-
299
- async get_schema_doc(schema_name, second = "") {
300
- // the schema_doc is of the forms : {schema,setting,name}
301
- const system_schemas = {
302
- setting: () => {
303
- if (second == "") {
304
- throw new Error(
305
- "when fetching setting schema, second argument (key name) is required "
306
- );
307
- }
308
- let s_data = this.valid_system_settings[second];
309
- s_data["name"] = "setting";
310
- s_data["schema"]["properties"]["name"] = {
311
- type: "string",
312
- minLength: 4,
313
- maxLength: 50,
314
- pattern: "^[a-zA-Z][a-zA-Z0-9_]*$",
315
- };
316
- s_data["schema"]["required"] = ["name"];
317
- s_data["settings"]["primary_key"] = ["name"];
318
- return s_data;
319
- },
320
- schema_doc: () => {
321
- return { ...this.valid_schema_doc_schema };
322
- },
323
- conflict_doc: () => {
324
- return;
325
- },
326
- };
327
-
328
- if (system_schemas[schema_name]) {
329
- return system_schemas[schema_name]();
330
- } else {
331
- let s_doc = await this.db.search({
332
- selector: { schema: "schema_doc", "data.name": schema_name },
333
- });
334
- if (s_doc["docs"].length == 0) {
335
- throw new Error("Schema not defined in the database");
336
- }
337
- return s_doc["docs"][0]["data"];
338
- }
339
- }
340
-
341
- validate_data(schema_obj, data_obj) {
342
- const ajv = new Ajv(); // options can be passed, e.g. {allErrors: true}
343
- const validate = ajv.compile(schema_obj);
344
- const valid = validate(data_obj);
345
- if (!valid) {
346
- console.log(validate.errors);
347
- throw new Error(validate.errors);
348
- }
349
- }
350
-
351
- async search(criteria) {
352
- if (!criteria["schema"]) {
353
- throw new Error("The search criteria must contain the schema");
354
- }
355
- }
356
-
357
- async duplicate_doc_check(schema_obj, data_obj) {
358
- let doc_obj = { schema: { $eq: schema_obj["name"] } };
359
- schema_obj["settings"]["primary_key"].forEach((element) => {
360
- doc_obj["data." + element] = { $eq: data_obj[element] };
361
- });
362
- let doc_check = { selector: doc_obj };
363
- let docs_found = await this.db.search(doc_check);
364
- console.log(doc_check, docs_found);
365
- if (docs_found["docs"].length > 0) {
366
- throw new Error("Document already exists");
367
- }
368
- }
369
- validate_new_schema_object(schema_name, record_data) {
370
- // check if the name is not from the system defined schemas , check the values of settings fields etc....
371
- // also editable_fields must not be blank
372
- return;
373
- }
374
-
375
- async insert_pre_check(schema_name, record_data) {
376
- // read schema
377
- let secondArg = "";
378
- if (schema_name == "setting") {
379
- secondArg = record_data["name"];
380
- }
381
- let opt = { allow: false, errors: [] };
382
- //console.log(secondArg);
383
- let schemaDoc = await this.get_schema_doc(schema_name, secondArg);
384
- // validate data
385
- // console.log(record_data);
386
- this.validate_data(schemaDoc["schema"], record_data);
387
- // todo generate a new doc with default values when validating obj
388
- if (schema_name == "schema_doc") {
389
- this.validate_new_schema_object(schema_name, record_data);
390
- }
391
- // check if already exists
392
- await this.duplicate_doc_check(schemaDoc, record_data);
393
- }
394
- async insert_doc(data) {
395
- try {
396
- await this.insert_pre_check(data["schema"], data["data"]);
397
- this.validate_doc_object(data);
398
- let new_rec = await this.db.insert(data);
399
- // console.log(new_rec)
400
- return { id: new_rec["id"] };
401
- } catch (error) {
402
- console.log(error);
403
- throw error;
404
- }
405
- }
406
- async insert(schema_name, data) {
407
- try {
408
- await this.insert_pre_check(schema_name, data);
409
- let new_record = this.get_blank_doc(schema_name);
410
- new_record["data"] = data;
411
- this.validate_doc_object(new_record);
412
- let new_rec = await this.db.insert(new_record);
413
- return { id: new_rec["id"] };
414
- } catch (error) {
415
- console.log(error);
416
- throw error;
417
- }
418
- }
419
-
420
-
421
-
422
- async get(doc_id) {
423
- let doc = await this.db.get(doc_id);
424
- return doc;
425
- }
426
-
427
- async load_doc(doc_id) {
428
- let d = await this.get(doc_id);
429
- let s = await this.get_schema_doc(d["schema"]);
430
- return {
431
- doc: d,
432
- schema: s,
433
- };
434
- }
435
-
436
- async load_editor_settings() {
437
- let tags = await this.get_setting_doc("tags");
438
-
439
- let schemas = await this.db.search({ selector: { schema: "schema_doc" } });
440
-
441
- return { tags: tags["data"], schemas: schemas["docs"] };
442
- }
443
-
444
- filterObject(obj, fields) {
445
- return fields.reduce((filteredObj, field) => {
446
- if (Object.prototype.hasOwnProperty.call(obj, field)) {
447
- filteredObj[field] = obj[field];
448
- }
449
- return filteredObj;
450
- }, {});
451
- }
452
-
453
- async update_data(
454
- doc_id,
455
- rev_id,
456
- schema_name,
457
- data_updates,
458
- save_conflict = true
459
- ) {
460
- // making a big assumption here : primary key fields cannot be edited
461
- // so updating the doc will not generate primary key conflicts
462
- let secondArg = "";
463
- if (schema_name == "setting") {
464
- secondArg = data_updates["name"];
465
- }
466
- let schema = await this.get_schema_doc(schema_name, secondArg);
467
- let full_doc = await this.get(doc_id);
468
- // generate a new object based on which fields are allowed to be updated
469
- // TODO what if no editable fields exists
470
- let allowed_updates = this.filterObject(
471
- data_updates,
472
- schema["settings"]["editable_fields"]
473
- );
474
- let updated_data = { ...full_doc["data"], ...allowed_updates };
475
- // validate the new data
476
- this.validate_data(schema["schema"], updated_data);
477
- full_doc["data"] = updated_data;
478
- // new data must be validated against the schema
479
- if (full_doc["_rev"] != rev_id) {
480
- // throw error , save conflicting doc separately by default
481
- if (save_conflict) {
482
- // save conflicting doc todo
483
- }
484
- }
485
- let up = await this.db.update(full_doc);
486
- return up;
487
- }
488
- async update_metadata(doc_id, rev_id, schema_name, meta_updates) {}
489
-
490
- async delete(doc_id) {}
491
-
492
- get_now_unix_timestamp() {
493
- const currentTimeMilliseconds = Date.now();
494
- return Math.floor(currentTimeMilliseconds / 1000);
495
- }
496
-
497
- get_blank_doc(schema_name) {
498
- let doc = {
499
- data: {},
500
- meta: {
501
- createdOn: this.get_now_unix_timestamp(),
502
- tags: [],
503
- },
504
- schema: schema_name,
505
- };
506
- return doc;
507
- }
508
- validate_doc_object(obj) {
509
- let doc_schema = {
510
- type: "object",
511
- required: ["schema", "data", "meta"],
512
- properties: {
513
- data: {
514
- type: "object",
515
- additionalProperties: true,
516
- },
517
- schema: {
518
- type: "string",
519
- },
520
- meta: {
521
- type: "object",
522
- additionalProperties: true,
523
- },
524
- },
525
- };
526
- const ajv = new Ajv(); // options can be passed, e.g. {allErrors: true}
527
- const validate = ajv.compile(doc_schema);
528
- const valid = validate(obj);
529
- if (!valid) {
530
- console.log(validate.errors);
531
- throw new Error(validate.errors);
532
- }
533
- return;
534
- }
535
- get_metadata_schema() {
536
- let records_meta_schema = {
537
- type: "object",
538
- title: "Doc metadata",
539
- properties: {},
540
- };
541
- }
542
- }
543
-
544
- module.exports.InfoDB = InfoDB;
package/test/test.js DELETED
@@ -1,7 +0,0 @@
1
- require('dotenv').config()
2
- const indodb = require("infodb-core")
3
- const db = new indodb(process.env.cdburl,process.env.cdbname)
4
-
5
- // db.get("7adeecc539479716cf35540d75000a8d").then(data=>{
6
- // console.log(data)
7
- // })