Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(CustomPersistance): Added custom persistance #127

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions src/JsonDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,37 @@ type DataPath = Array<string>


export type FindCallback = (entry: any, index: number | string) => boolean
export type SaveCallback = (data: KeyValue) => void

export class JsonDB {
private loaded: boolean = false
private data: KeyValue = {}
private readonly config : JsonDBConfig
private readonly saveCallback?: SaveCallback


/**
* JSONDB Constructor
* JsonDB Constructor
* @param filename where to save the "DB". Can also be used to give the whole configuration
* @param saveOnPush save the database at each push command into the json file
* @param humanReadable the JSON file will be readable easily by a human
* @param separator what to use as separator
*/
constructor(filename: string | Config, saveOnPush: boolean = true, humanReadable: boolean = false, separator: string = '/') {

constructor(filename: string | Config | null, saveOnPush: boolean = true, humanReadable: boolean = false, separator: string = '/', saveCallback?: SaveCallback) {
if(filename instanceof Config) {
this.config = filename
} else {
this.config = new Config(filename, saveOnPush, humanReadable, separator)
}

if (!FS.existsSync(this.config.filename)) {
if (this.config.filename !== null && !FS.existsSync(this.config.filename)) {
const dirname = path.dirname(this.config.filename)
mkdirp.sync(dirname)
this.save(true)
this.loaded = true
}

this.saveCallback = saveCallback;
}

/**
Expand Down Expand Up @@ -132,11 +135,11 @@ export class JsonDB {
}

/**
* Get the wanted data
* Get the wanted data. No path will return the full data
* @param dataPath
*/
public getData(dataPath: string): any {
const path = this.processDataPath(dataPath)
public getData(dataPath?: string): any {
const path = this.processDataPath(dataPath !== undefined ? dataPath : "/")
return this.retrieveData(path, false)
}

Expand Down Expand Up @@ -289,8 +292,8 @@ export class JsonDB {
}

/**
* Only use this if you know what you're doing.
* It reset the full data of the database.
* Only use this if you know what you're doing
* It resets the full data of the database
* @param data
*/
public resetData(data: any): void {
Expand All @@ -313,6 +316,13 @@ export class JsonDB {
if (this.loaded) {
return
}

if (this.config.filename === null) {
this.data = {}
this.loaded = true
return
}

try {
const data = FS.readFileSync(this.config.filename, 'utf8')
this.data = JSON.parse(data)
Expand All @@ -329,6 +339,15 @@ export class JsonDB {
* @param force force the save of the database
*/
public save(force?: boolean): void {
if (this.config.filename === null) {
if (this.saveCallback) {
this.saveCallback(this.data)
return
}
const error = new DatabaseError("Can't save the database. Undefined saveCallback", 2)
throw error
}

force = force || false
if (!force && !this.loaded) {
throw new DatabaseError("DataBase not loaded. Can't write", 7)
Expand Down
8 changes: 4 additions & 4 deletions src/lib/JsonDBConfig.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import * as path from "path";

export interface JsonDBConfig {
filename: string,
filename: string | null,
saveOnPush: boolean,
humanReadable: boolean,
separator: string
}

export class Config implements JsonDBConfig {
filename: string
filename: string | null
humanReadable: boolean
saveOnPush: boolean
separator: string


constructor(filename: string, saveOnPush: boolean = true, humanReadable: boolean = false, separator: string = '/') {
constructor(filename: string | null, saveOnPush: boolean = true, humanReadable: boolean = false, separator: string = '/') {
this.filename = filename

// Force json if no extension
if (path.extname(filename) === "") {
if (filename !== null && path.extname(filename) === "") {
this.filename += ".json"
}

Expand Down
51 changes: 51 additions & 0 deletions test/05-persistance.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { JsonDB } from '../src/JsonDB'
import { KeyValue } from '../src/lib/Utils'
import { DatabaseError } from '../src/lib/Errors'

describe('JsonDB', () => {

describe('no save at all', () => {
const db = new JsonDB(null, false, true)

test('should ignore persistance', () => {
db.push('/test', 'abc')
const data = db.getData()
expect(data).toHaveProperty('test')
})
})

describe('custom saving method', () => {
let saved: KeyValue;

const db = new JsonDB(null, true, true, '/', data => {
// custom saving method
saved = data
})

test('should execute a custom saving method on push', () => {
db.push('/automatic', 'abc')
expect(saved).toHaveProperty('automatic')
})

test('should trigger the custom saving method', () => {
db.push('/manual', 'abc')
db.save()
expect(saved).toHaveProperty('manual')
})
})

test('should throw an error when trying to save without a custom saving method', () => {
const db = new JsonDB(null, false, true)

try {
(function () {
db.save()
})()

throw Error('Function did not throw')
} catch (e) {
expect(e).toBeInstanceOf(DatabaseError)
expect(e).toHaveProperty('id', 2)
}
})
})