json-repo
v1.2.4
Published
Read and write data to JSON files using the repository pattern.
Downloads
6
Maintainers
Readme
Json File Repository - IoT Shaman
In-memory repository with Json file persistence.
Sometimes as developers we have the need to store and retrieve persistent data, but dont need all the power that comes with a traditional data persistence solution. The Json File Repository (json-repo) is an in-memory data repository that conveniently persists data to a Json file, anywhere on the host device. This allows applications to receive the benefits of a repository abstraction, without having to model, provision and connect to, say, a SQL database. When you initialize an implementation of the repository, it will load any data located in the provided file path (if it exists), and when you make changes to the repository simply call "saveChanges()" to persist the data into the Json file.
Requirements
- Node JS
- Typescript
Installation
npm install json-repo --save
Quick Start
Getting started with json-repo is really quick and simple. First, create an a model to provide types for the data we are going to store: For example:
//file: foo.ts
export class Foo {
bar: string;
}
Next, we need to create an implementation of the base "RepositoryContext" class:
//file: sample-context.ts
import { RepositoryContext, Repository } from 'json-repo';
import { Foo } from './foo';
export class SampleDataContext extends RepositoryContext {
constructor(dataPath: string) { super(dataPath); }
models = {
baz: new Repository<Foo>()
}
}
Finally, we need to initialize the context in our application:
import * as path from 'path';
import { SampleDataContext } from './sample-context';
import { Foo } from './foo';
const jsonFilePath = path.join(__dirname, 'db.json');
let context = new SampleDataContext(jsonFilePath);
context.initialize().then(_ => {
//you can now use the context
let foo = new Foo(); foo.bar = 'baz';
context.models.baz.add('1', foo);
return context.saveChanges();
});
API Reference
The below information describes how to use the built-in features of json-repo.
RepositoryContext
The "RepositoryContext" is an abstract class that allows you to communicate with various repositories. All repositories in a given implementation will store their data in the same JSON file. The RepositoryContext takes 2 optional arguments in its constructor, that allow you to configure its behavior.
//provided from the repository-context.d.ts file
export declare abstract class RepositoryContext {
abstract models: {
[key: string]: IRepository<any>;
};
constructor(dataPath?: string, entityNodeService?: IEntityNodeService);
initialize: () => Promise<void>;
saveChanges: () => Promise<void>;
}
models: the models property stores a collection of repository objects. These repository objects represent your domain objects. Each value in models is a key value pair, with the key being the common name of the domain object, and the value being an implementation of the Repository class, with the generic argument set to the typed class of your domain model.
constructor: the dataPath argument, when provided, tells the repository context where the data file is; when not provided, the repository context will be in-memory only, and as such will not persist the data. The entityNodeService object allows you to provide a custom implementation of IEntityNodeService, which gives you additional control over how and where you persist data; to use the built-in JSON file persistence, do not provide a value for entityNodeService.
initialize: the initialize method will look for any data in the persistent storage layer and load it into memory. If no data is found, the repository context will initialize each repository with a blank array. If a new repository was added and does not yet exist in persistent storage, that repository will be initialized with a blank array.
saveChanges: saveChanges will ask the persistent storage layer to store the contents of the repository. If there was no data path provided to the constructor, or nothing has changed in the repositories, this will be a noop.
Repository
The "Repository" interface is defined as a generic, with the type argument representing a domain object. Some built-in methods are provided to manage and query the repository. The default implementation of IRepository is Repository, and can also be extended if you wish to provide additional functionality.
//provided from the repository.d.ts file
export declare class Repository<T> {
get state(): string;
protected _state: string;
protected data: {
[key: string]: T;
};
load: (data: EntityNode[]) => void;
extract: () => EntityNode[];
find: (key: string) => T;
filter: (filter: (item: T) => boolean) => T[];
add: (key: string, item: T) => void;
addRange: (items: [{key: string, item: T}]) => void;
update: (key: string, action: (item: T) => T) => void;
delete: (key: string) => void;
markCurrent: () => void;
}
EntityNode
An "EntityNode" is the core persistent storage block of a repository. When files are written to and read from the persistent storage layer, EntityNode objects are what is used. Entity nodes are simply key value pairs, where the key represents a unique key to store and retrieve data, and a value which contains the concrete domain object. For most implementations, you will never use the EntityNode object, but it can be useful if you are extending the repository class, or needing to wipe or reload the entire repository.
//provided from the entity-node.d.ts file
export declare class EntityNode {
key: string;
value: any;
}
IEntityNodeService
The implementation of "IEntityNodeService" acts as the persistent storage layer, reading to and writing from some storage mechanism. The built-in implementation of IEntityNodeService is calls "JsonFileService", and is provided by default to all "RepositoryContext" objects. If you wish to provide a custom data persistence solution, you can achieve this by creating a custom implementation of IEntityNodeService.
//provided from the entity-node-service.d.ts file
export interface IEntityNodeService {
getEntityNodes(path: string): Promise<{[model: string]: EntityNode[];}>;
persistEntityNodes<T>(path: string, data: T): Promise<void>;
}