@digigov-oss/auditrecord-couchdb-engine
Version:
CouchDB storage database for use with audit mechanism of GSIS
168 lines (156 loc) • 4.94 kB
text/typescript
import Nano from "nano";
import { AuditRecord, AuditEngine, DatabaseSettings, PNRESETTYPES } from '@digigov-oss/gsis-audit-record-db';
/**
* @description AuditEngine implementation
* @note This class is used to implement the methods that must be implemented by the AuditEngine
* @class CouchDBEngine
* @implements AuditEngine
* @param {string} connectionString - connect to db via connection string `http://user:pass@$dbHost:dbPort`
* @param {DatabaseSettings} dbSettings - database settings (please note the tableName is actualy a DB name for couchdb)
*/
export class CouchDBEngine implements AuditEngine {
#dbname: string;
#connection:string;
#client: any;
#pnreset:PNRESETTYPES;
private async couch(): Promise<any> {
const nano = Nano(this.#connection);
const dbList = await nano.db.list(); // list all databases
try {
if (!dbList.includes(this.#dbname)) {
// create a new DB if database doesn't exist.
await nano.db.create(this.#dbname);
const db = nano.use(this.#dbname);
console.log("database created successfully");
return db;
} else {
const db = nano.use(this.#dbname);
return db;
}
} catch (err: any) {
throw new Error(err);
}
};
/**
* @description constructor
* @param {string} connectionString - connect to couchdb via connection string
* @param {DatabaseSettings} settings - settings for the database
* @memberof CouchDBEngine
*/
constructor(connectionString:string = "", dbSettings: DatabaseSettings={},pnreset:PNRESETTYPES="innumerable") {
this.#connection = connectionString!=""?connectionString:"http://admin:admin@localhost:5984";
this.#dbname = dbSettings.tableName || "audit_records"; //this is actualy a DB name
const init = async () => {
return await this.couch();
}
this.#client = init();
this.#pnreset = pnreset;
}
/**
* @description Store a record in the database
* @param {AuditRecord} record - record to be stored
* @returns {AuditRecord} - the record stored
* @memberof FileEngine
* @method put
*/
put(record: AuditRecord): AuditRecord {
return this.#client.then(async (db:any) => {
try {
const doc = {
_id: record.auditTransactionId,
...record
};
const _rdoc = await db.insert(doc);
return record;
} catch (error) {
throw error;
}
});
}
/**
* @description Get a record from the database
* @param auditTransactionId: string - transaction id
* @returns {AuditRecord}
* @memberof FileEngine
* @method get
*/
get(auditTransactionId: string): AuditRecord {
return this.#client.then(async (db:any) => {
try {
const rdoc = await db.get(auditTransactionId);
return rdoc;
} catch (error) {
throw error;
}
});
}
/**
* @description Generate a new sequence number
* @param path
* @returns number
* @memberof CouchDBEngine
* @method seq
*/
seq():number {
// from update_seq get the numeric part and add 1
return this.#client.then(async (db:any) => {
try {
const rdoc = await db.info();
//get integer part from 1-xxxx
const seq = parseInt(rdoc.update_seq.split("-")[0]);
return seq+1;
} catch (error) {
throw error;
}
});
}
/**
* @description Generate a new protocol number
* @param path
* @returns string
* @memberof CouchDBEngine
* @method protocol
*/
pn():string {
return this.#client.then(async (db:any) => {
const pnreset = this.#pnreset;
try {
let protocol_split = "aion";
let protocol_date = new Date().toISOString().split('T')[0];
switch(pnreset){
case "daily":
protocol_split = protocol_date;
break;
case "monthly":
protocol_split = protocol_date.split('-')[0]+"-"+protocol_date.split('-')[1];
break;
case "yearly":
protocol_split = protocol_date.split('-')[0];
break;
case "innumerable":
protocol_split = "aion";
break;
}
//Create indexes based on pnreset daily, monthly, yearly, innumerable
const seqName = "prot_"+protocol_split.replace(/-/g, '');
//create document in couchdb
let doc = {
_id: seqName,
rev: "1"
};
//get the document
try {
doc = await db.get(seqName);
} catch (error) {
//document doesn't exist
}
doc = await db.insert(doc);
const protocol = parseInt((doc as any)['rev'].split("-")[0]);
return protocol+"/"+protocol_date;
} catch (error) {
throw error;
}
});
}
}
export default CouchDBEngine;