dataorm
Version:
A Javascript ORM
145 lines (106 loc) • 3 kB
text/typescript
import { snakeCase } from 'change-case';
import Pluralize from 'pluralize';
import { Model } from '../models';
type StorageAdapter = {
LocalStorage: 'LocalStorage';
AsyncStorage: 'AsyncStorage';
};
interface DbConfig {
name: string;
storage: keyof StorageAdapter;
}
interface DbConfigOptions {
name?: string;
storage?: keyof StorageAdapter;
}
export class Database {
private static instance: InstanceType<typeof Database> | null = null;
private initialized: boolean = false;
private store: any = {};
private entities: any = [];
// private schemas: any = {};
private dbConfig: DbConfig = {
name: 'db',
storage: 'LocalStorage',
};
collection(entity: string): any[] {
return this.store[this.dbConfig.name][entity];
}
setCollection(entity: string, collection: any[]) {
console.log(collection, 'collection');
this.store[this.dbConfig.name][entity] = collection;
}
constructor() {
this.setStore(this.dbConfig);
}
private generateConfig(config: any) {
const newConfig: any = this.dbConfig;
Object.keys(this.dbConfig).forEach((key: string) => {
newConfig[key] = config[key];
});
return newConfig;
}
private checkModelTypeMappingCapabilities(model: any): any {
if (model.prototype instanceof Model === false) {
throw new Error('Invalid Model Bindings');
}
const instance = new model();
if (
instance.entity &&
this.entities.find((entity: any) => entity.name == instance.entity)
) {
throw new Error(`Duplicate entity name for ${model.name}`);
}
}
private createModelBinding(model: any): any {
Object.defineProperty(model, 'store', {
value: this.store,
});
const instance = new model();
return {
name: instance.entity ?? snakeCase(Pluralize.plural(model.name)),
model,
};
}
private createSchema() {
this.entities.forEach((entity: any): void => {
this.registerSchema(entity);
});
}
private registerSchema(entity: any): void {
if (!this.store[this.dbConfig.name].hasOwnProperty(entity.name)) {
this.store[this.dbConfig.name][entity.name] = [];
}
}
private setStore(dbConfig: DbConfigOptions) {
this.dbConfig = this.generateConfig(dbConfig);
this.store = {
[this.dbConfig.name]: {},
};
}
static getInstance() {
if (this.instance === null) {
this.instance = new Database();
return this.instance;
}
return this.instance;
}
config(dbConfig: DbConfigOptions = this.dbConfig) {
if (this.initialized) {
throw new Error('Database already initialized');
}
this.setStore(dbConfig);
return this;
}
register(model: any) {
this.checkModelTypeMappingCapabilities(model);
const entity = this.createModelBinding(model);
this.entities.push(entity);
return this;
}
start() {
this.createSchema();
this.initialized = true;
}
}
export const DB = Database.getInstance();