Commits (16)
......@@ -11,28 +11,13 @@ stages:
- release
- trigger
- pages
testLEGACY:
stage: test
script:
- npmci test legacy
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
allow_failure: true
testLTS:
stage: test
script:
- npmci test lts
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
testSTABLE:
stage: test
script:
- npmci test stable
- npmci node install stable
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
......@@ -40,7 +25,8 @@ testSTABLE:
release:
stage: release
script:
- npmci publish
- npmci npm prepare
- npmci npm publish
only:
- tags
tags:
......
# smartdata
do more with data
do more with data and RethinkDB
## Availabililty
[![npm](https://pushrocks.gitlab.io/assets/repo-button-npm.svg)](https://www.npmjs.com/package/smartdata)
......@@ -14,6 +14,7 @@ do more with data
[![Dependency Status](https://david-dm.org/pushrocks/smartdata.svg)](https://david-dm.org/pushrocks/smartdata)
[![bitHound Dependencies](https://www.bithound.io/github/pushrocks/smartdata/badges/dependencies.svg)](https://www.bithound.io/github/pushrocks/smartdata/master/dependencies/npm)
[![bitHound Code](https://www.bithound.io/github/pushrocks/smartdata/badges/code.svg)](https://www.bithound.io/github/pushrocks/smartdata)
[![Known Vulnerabilities](https://snyk.io/test/npm/smartdata/badge.svg)](https://snyk.io/test/npm/smartdata)
[![TypeScript](https://img.shields.io/badge/TypeScript-2.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%206.x.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
......@@ -21,6 +22,90 @@ do more with data
## Usage
Use TypeScript for best in class instellisense.
smartdata is an ODM that adheres to TypeScript practices and uses classes to organize data.
It uses RethinkDB as persistent storage.
## Intention
There are many ODMs out there, however when we searched for an ODM that uses TypeScript,
acts smart while still embracing the NoSQL idea we didn't find a matching solution.
This is why we started smartdata.
How RethinkDB's terms map to the ones of smartdata:
RethinkDB term | smartdata class
--- | ---
Database | smartdata.Db
Table | smartdata.DbTable
Document | smartdata.DbDoc
### class Db
represents a Database. Naturally it has .connect() etc. methods on it.
```javascript
import * as smartdata from 'smartdata'
let myRethinkDb1 = new smartdata.Db({
// rethinkDb connection options here
})
myDb1.connect()
```
### class DbCollection
represents a collection of objects.
A collection is defined by the object class (that is extending smartdata.dbdoc) it respresents
So to get to get access to a specific collection you document
```javascript
// continues from the block before...
@Collection(myRethinkDb1)
class MyObject extends smartdata.DbDoc<myObject> { // read the next block about DbDoc
@smartdata.svDb() property1: string // @smartdata.svDb() marks the property for db save
property2: number // this one is not marked, so it won't be save upon calling this.save()
constructor(optionsArg:{
property1: string,
property2: number
}) {
super()
}
}
let myCollection = myRethinkDb1.getCollectionByName<myObject>(myObject)
// start to instantiate instances of classes from scratch or database
let localObject = new MyObject({
property1: 'hi',
property2: 2
})
localObject.save() // saves the object to the database
```
> Alert: You NEVER instantiate a collection.
This is done for you!!!
### class DbDoc
represents a individual document in a collection
and thereby is ideally suited to extend the class you want to actually store.
DbDoc extends your class with the following methods:
* `.save()` will save (or update) the object you call it on only. Any referenced non-savable objects will not get stored.
* `.saveDeep()` does the same like `.save()`.
In addition it will look for properties that reference an object
that extends DbDoc as well and call .saveDeep() on them as well.
Loops are prevented
So now we can **store** instances of classes to Db...
How do we **get** a new class instance from a Doc in the DB?
## TypeScript
How does TypeScript play into this?
Since you define your classes in TypeScript and types flow through smartdata in a generic way
you should get all the Intellisense and type checking you love when using smartdata.
smartdata itself also bundles typings.
So you don't need to install any additional types when importing smartdata.
For further information read the linked docs at the top of this README.
> MIT licensed | **&copy;** [Lossless GmbH](https://lossless.gmbh)
......
import * as plugins from './smartdata.plugins';
import { Objectmap } from 'lik';
import { DbCollection } from './smartdata.classes.dbcollection';
import { DbTable } from './smartdata.classes.dbcollection';
import { ConnectionOptions } from 'rethinkdb';
/**
* interface - indicates the connection status of the db
*/
export declare type TConnectionStatus = 'disconnected' | 'connected' | 'failed';
export declare type TConnectionStatus = 'initial' | 'disconnected' | 'connected' | 'failed';
export declare class Db {
dbUrl: string;
db: plugins.mongodb.Db;
dbName: string;
connectionOptions: plugins.rethinkDb.ConnectionOptions;
dbConnection: plugins.rethinkDb.Connection;
status: TConnectionStatus;
classCollections: Objectmap<DbCollection<any>>;
objectCollections: Objectmap<DbCollection<any>>;
constructor(dbUrlArg: string);
dbTablesMap: Objectmap<DbTable<any>>;
constructor(connectionOptionsArg: ConnectionOptions);
/**
* supply additional SSl options
*/
setSsl(certificateStringArg: string, formatArg: 'base64' | 'clearText'): void;
/**
* connects to the database that was specified during instance creation
*/
......@@ -21,12 +26,10 @@ export declare class Db {
*/
close(): Promise<any>;
/**
* gets a class based collection by name: string
*/
getClassCollectionByName<T>(nameArg: string): Promise<DbCollection<T>>;
/**
* gets an object collection by name
* Gets a table's name and returns smartdata's DbTable class
* @param nameArg
* @returns DbTable
*/
getObjectCollectionByName<T>(nameArg: string, dbArg: Db, makeNewArg?: boolean): Promise<DbCollection<T>>;
addCollection(dbCollectionArg: DbCollection<any>): void;
getDbTableByName<T>(nameArg: string): Promise<DbTable<T>>;
addTable(dbCollectionArg: DbTable<any>): void;
}
......@@ -10,72 +10,67 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
Object.defineProperty(exports, "__esModule", { value: true });
const plugins = require("./smartdata.plugins");
const lik_1 = require("lik");
const smartdata_classes_dbobjectdoc_1 = require("./smartdata.classes.dbobjectdoc");
class Db {
constructor(dbUrlArg) {
this.classCollections = new lik_1.Objectmap();
this.objectCollections = new lik_1.Objectmap();
this.dbUrl = dbUrlArg;
constructor(connectionOptionsArg) {
this.dbTablesMap = new lik_1.Objectmap();
this.dbName = connectionOptionsArg.db;
this.connectionOptions = connectionOptionsArg;
this.status = 'initial';
}
/**
* supply additional SSl options
*/
setSsl(certificateStringArg, formatArg) {
let certificateString;
if (formatArg = 'base64') {
certificateString = plugins.smartstring.base64.decode(certificateStringArg);
}
else {
certificateString = certificateStringArg;
}
this.connectionOptions['ssl'] = {
ca: Buffer.from(certificateString)
};
}
// basic connection stuff ----------------------------------------------
/**
* connects to the database that was specified during instance creation
*/
connect() {
let done = plugins.smartq.defer();
plugins.mongodb.MongoClient.connect(this.dbUrl, (err, db) => {
if (err) {
console.log(err);
}
plugins.assert.equal(null, err);
this.db = db;
plugins.beautylog.success(`connected to database at ${this.dbUrl}`);
done.resolve(this.db);
return __awaiter(this, void 0, void 0, function* () {
this.dbConnection = yield plugins.rethinkDb.connect(this.connectionOptions);
this.dbConnection.use(this.dbName);
this.status = 'connected';
plugins.beautylog.ok(`Connected to database ${this.dbName}`);
});
return done.promise;
}
/**
* closes the connection to the databse
*/
close() {
let done = plugins.smartq.defer();
this.db.close();
plugins.beautylog.ok(`disconnected to database at ${this.dbUrl}`);
done.resolve();
return done.promise;
}
// advanced communication with the database --------------------------------
/**
* gets a class based collection by name: string
*/
getClassCollectionByName(nameArg) {
return __awaiter(this, void 0, void 0, function* () {
let resultCollection = this.classCollections.find((dbCollectionArg) => {
return dbCollectionArg.name === nameArg;
});
return resultCollection;
yield this.dbConnection.close();
this.status = 'disconnected';
plugins.beautylog.ok(`disconnected from database ${this.dbName}`);
});
}
// handle table to class distribution
/**
* gets an object collection by name
* Gets a table's name and returns smartdata's DbTable class
* @param nameArg
* @returns DbTable
*/
getObjectCollectionByName(nameArg, dbArg, makeNewArg = false) {
getDbTableByName(nameArg) {
return __awaiter(this, void 0, void 0, function* () {
let resultCollection = this.objectCollections.find((dbCollectionArg) => {
return dbCollectionArg.name === nameArg;
let resultCollection = this.dbTablesMap.find((dbCollectionArg) => {
return dbCollectionArg.tableName === nameArg;
});
if (!resultCollection && makeNewArg) {
resultCollection = smartdata_classes_dbobjectdoc_1.getObjectDoc(nameArg, this).collection;
return resultCollection;
}
else {
return resultCollection;
}
return resultCollection;
});
}
addCollection(dbCollectionArg) {
this.classCollections.add(dbCollectionArg);
addTable(dbCollectionArg) {
this.dbTablesMap.add(dbCollectionArg);
}
}
exports.Db = Db;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEsK0NBQThDO0FBQzlDLDZCQUErQjtBQUcvQixtRkFBOEQ7QUFPOUQ7SUFPRSxZQUFhLFFBQWdCO1FBSDdCLHFCQUFnQixHQUFHLElBQUksZUFBUyxFQUFxQixDQUFBO1FBQ3JELHNCQUFpQixHQUFHLElBQUksZUFBUyxFQUFxQixDQUFBO1FBR3BELElBQUksQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFBO0lBQ3ZCLENBQUM7SUFFRCx3RUFBd0U7SUFFeEU7O09BRUc7SUFDSCxPQUFPO1FBQ0wsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNqQyxPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQ3RELEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUFDLENBQUM7WUFDN0IsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFBO1lBQy9CLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFBO1lBQ1osT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsNEJBQTRCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFBO1lBQ25FLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ3ZCLENBQUMsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDckIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSztRQUNILElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDakMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNmLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLCtCQUErQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQTtRQUNqRSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUE7UUFDZCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUNyQixDQUFDO0lBRUQsNEVBQTRFO0lBRTVFOztPQUVHO0lBQ0csd0JBQXdCLENBQUssT0FBZTs7WUFDaEQsSUFBSSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZTtnQkFDaEUsTUFBTSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEtBQUssT0FBTyxDQUFBO1lBQ3pDLENBQUMsQ0FBQyxDQUFBO1lBQ0YsTUFBTSxDQUFDLGdCQUFnQixDQUFBO1FBQ3pCLENBQUM7S0FBQTtJQUVEOztPQUVHO0lBQ0cseUJBQXlCLENBQUssT0FBZSxFQUFFLEtBQVMsRUFBRyxhQUFzQixLQUFLOztZQUMxRixJQUFJLGdCQUFnQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxlQUFlO2dCQUNqRSxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksS0FBSyxPQUFPLENBQUE7WUFDekMsQ0FBQyxDQUFDLENBQUE7WUFDRixFQUFFLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUM7Z0JBQ3BDLGdCQUFnQixHQUFHLDRDQUFZLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQTtnQkFDekQsTUFBTSxDQUFDLGdCQUFnQixDQUFBO1lBQ3pCLENBQUM7WUFBQyxJQUFJLENBQUMsQ0FBQztnQkFDTixNQUFNLENBQUMsZ0JBQWdCLENBQUE7WUFDekIsQ0FBQztRQUNILENBQUM7S0FBQTtJQUVELGFBQWEsQ0FBRSxlQUFrQztRQUMvQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFBO0lBQzVDLENBQUM7Q0FFRjtBQXRFRCxnQkFzRUMifQ==
\ No newline at end of file
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEsK0NBQThDO0FBQzlDLDZCQUErQjtBQVcvQjtJQU9FLFlBQVksb0JBQXVDO1FBRm5ELGdCQUFXLEdBQUcsSUFBSSxlQUFTLEVBQWdCLENBQUE7UUFHekMsSUFBSSxDQUFDLE1BQU0sR0FBRyxvQkFBb0IsQ0FBQyxFQUFFLENBQUE7UUFDckMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLG9CQUFvQixDQUFBO1FBQzdDLElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFBO0lBQ3pCLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBRSxvQkFBNEIsRUFBRSxTQUFpQztRQUNyRSxJQUFJLGlCQUF5QixDQUFBO1FBQzdCLEVBQUUsQ0FBQSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQ3hCLGlCQUFpQixHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFBO1FBQzdFLENBQUM7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNOLGlCQUFpQixHQUFHLG9CQUFvQixDQUFBO1FBQzFDLENBQUM7UUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEdBQUc7WUFDOUIsRUFBRSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUM7U0FDbkMsQ0FBQTtJQUNILENBQUM7SUFFRCx3RUFBd0U7SUFFeEU7O09BRUc7SUFDRyxPQUFPOztZQUNYLElBQUksQ0FBQyxZQUFZLEdBQUcsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQTtZQUMzRSxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDbEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxXQUFXLENBQUE7WUFDekIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMseUJBQXlCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQzlELENBQUM7S0FBQTtJQUVEOztPQUVHO0lBQ0csS0FBSzs7WUFDVCxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUE7WUFDL0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxjQUFjLENBQUE7WUFDNUIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsOEJBQThCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQ25FLENBQUM7S0FBQTtJQUVELHFDQUFxQztJQUVyQzs7OztPQUlHO0lBQ0csZ0JBQWdCLENBQUksT0FBZTs7WUFDdkMsSUFBSSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLGVBQWUsRUFBRSxFQUFFO2dCQUMvRCxNQUFNLENBQUMsZUFBZSxDQUFDLFNBQVMsS0FBSyxPQUFPLENBQUE7WUFDOUMsQ0FBQyxDQUFDLENBQUE7WUFDRixNQUFNLENBQUMsZ0JBQWdCLENBQUE7UUFDekIsQ0FBQztLQUFBO0lBRUQsUUFBUSxDQUFFLGVBQTZCO1FBQ3JDLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFBO0lBQ3ZDLENBQUM7Q0FDRjtBQWxFRCxnQkFrRUMifQ==
\ No newline at end of file
import * as plugins from './smartdata.plugins';
import { Db } from './smartdata.classes.db';
import { DbDoc } from './smartdata.classes.dbdoc';
import { WriteResult, Cursor } from 'rethinkdb';
export interface IFindOptions {
limit?: number;
}
......@@ -8,17 +9,17 @@ export interface IDocValidation<T> {
(doc: T): boolean;
}
export declare function Collection(db: Db): (constructor: any) => void;
export declare class DbCollection<T> {
export declare class DbTable<T> {
/**
* the collection that is used, defaults to mongodb collection,
* can be nedb datastore (sub api of mongodb)
*/
collection: plugins.mongodb.Collection;
collectedClass: T & DbDoc<T>;
table: plugins.rethinkDb.Table;
objectValidation: IDocValidation<T>;
name: string;
tableName: string;
db: Db;
constructor(collectedClassArg: T & DbDoc<T>, dbArg: Db);
init(): Promise<void>;
/**
* adds a validation function that all newly inserted and updated objects have to pass
*/
......@@ -26,17 +27,19 @@ export declare class DbCollection<T> {
/**
* finds an object in the DbCollection
*/
find(docMatchArg: T | any, optionsArg?: IFindOptions): Promise<T[]>;
find(): Promise<Cursor>;
/**
* inserts object into the DbCollection
* create an object in the database
*/
insertOne(docArg: T): Promise<void>;
insert(dbDocArg: T & DbDoc<T>): Promise<WriteResult>;
/**
* inserts many objects at once into the DbCollection
* inserts object into the DbCollection
*/
insertMany(docArrayArg: T[]): Promise<void>;
update(dbDocArg: T & DbDoc<T>): Promise<WriteResult>;
/**
* checks a Doc for constraints
* if this.objectValidation is not set it passes.
*/
private checkDoc(docArg);
extractKey(writeResult: WriteResult): void;
}
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const plugins = require("./smartdata.plugins");
function Collection(db) {
return function (constructor) {
constructor['dbCollection'] = new DbCollection(constructor, db);
constructor['dbCollection'] = new DbTable(constructor, db);
};
}
exports.Collection = Collection;
class DbCollection {
class DbTable {
constructor(collectedClassArg, dbArg) {
this.objectValidation = null;
// tell the collection where it belongs
this.collectedClass = collectedClassArg;
this.name = collectedClassArg.name;
this.tableName = collectedClassArg.name;
this.db = dbArg;
// make sure it actually exists
this.collection = dbArg.db.collection(this.name);
// tell the db class about it (important since Db uses different systems under the hood)
this.db.addCollection(this);
this.db.addTable(this);
}
init() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.table) {
// connect this instance to a RethinkDB table
const availableTables = yield plugins.rethinkDb
.db(this.db.dbName)
.tableList()
.run(this.db.dbConnection);
if (availableTables.indexOf(this.tableName)) {
yield plugins.rethinkDb
.db(this.db.dbName)
.tableCreate(this.tableName)
.run(this.db.dbConnection);
}
}
this.table = plugins.rethinkDb.table(this.tableName);
});
}
/**
* adds a validation function that all newly inserted and updated objects have to pass
......@@ -28,53 +51,36 @@ class DbCollection {
/**
* finds an object in the DbCollection
*/
find(docMatchArg, optionsArg) {
let done = plugins.smartq.defer();
let findCursor = this.collection.find(docMatchArg);
if (optionsArg) {
if (optionsArg.limit) {
findCursor = findCursor.limit(1);
}
}
findCursor.toArray((err, docs) => {
if (err) {
done.reject(err);
throw err;
}
done.resolve(docs);
find() {
return __awaiter(this, void 0, void 0, function* () {
yield this.init();
return yield plugins.rethinkDb.table(this.tableName).filter({}).run(this.db.dbConnection);
});
return done.promise;
}
/**
* inserts object into the DbCollection
* create an object in the database
*/
insertOne(docArg) {
let done = plugins.smartq.defer();
this.checkDoc(docArg).then(() => {
this.collection.insertOne(docArg)
.then(() => { done.resolve(); });
}, () => {
done.reject(new Error('one the docs did not pass validation'));
insert(dbDocArg) {
return __awaiter(this, void 0, void 0, function* () {
yield this.init();
yield this.checkDoc(dbDocArg);
return yield plugins.rethinkDb.table(this.tableName).insert(dbDocArg.createSavableObject()).run(this.db.dbConnection);
});
return done.promise;
}
/**
* inserts many objects at once into the DbCollection
* inserts object into the DbCollection
*/
insertMany(docArrayArg) {
let done = plugins.smartq.defer();
let checkDocPromiseArray = [];
for (let docArg of docArrayArg) {
checkDocPromiseArray.push(this.checkDoc(docArg));
}
Promise.all(checkDocPromiseArray).then(() => {
this.collection.insertMany(docArrayArg)
.then(() => { done.resolve(); });
update(dbDocArg) {
return __awaiter(this, void 0, void 0, function* () {
yield this.init();
yield this.checkDoc(dbDocArg);
console.log(this.tableName, dbDocArg.createSavableObject());
return yield plugins.rethinkDb.table(this.tableName).update(dbDocArg.createSavableObject()).run(this.db.dbConnection);
});
return done.promise;
}
/**
* checks a Doc for constraints
* if this.objectValidation is not set it passes.
*/
checkDoc(docArg) {
let done = plugins.smartq.defer();
......@@ -90,6 +96,8 @@ class DbCollection {
}
return done.promise;
}
extractKey(writeResult) {
}
}
exports.DbCollection = DbCollection;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGJjb2xsZWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRkYXRhLmNsYXNzZXMuZGJjb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsK0NBQThDO0FBWTlDLG9CQUE0QixFQUFNO0lBQ2hDLE1BQU0sQ0FBQyxVQUFVLFdBQVc7UUFDMUIsV0FBVyxDQUFFLGNBQWMsQ0FBRSxHQUFHLElBQUksWUFBWSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUNuRSxDQUFDLENBQUE7QUFDSCxDQUFDO0FBSkQsZ0NBSUM7QUFFRDtJQVdFLFlBQWEsaUJBQStCLEVBQUUsS0FBUztRQUp2RCxxQkFBZ0IsR0FBc0IsSUFBSSxDQUFBO1FBS3hDLHVDQUF1QztRQUN2QyxJQUFJLENBQUMsY0FBYyxHQUFHLGlCQUFpQixDQUFBO1FBQ3ZDLElBQUksQ0FBQyxJQUFJLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFBO1FBQ2xDLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxDQUFBO1FBRWYsK0JBQStCO1FBQy9CLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRWhELHdGQUF3RjtRQUN4RixJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUM3QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxnQkFBZ0IsQ0FBRSxPQUEwQjtRQUMxQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsT0FBTyxDQUFBO0lBQ2pDLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksQ0FBRSxXQUFvQixFQUFFLFVBQXlCO1FBQ25ELElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFPLENBQUE7UUFDdEMsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FB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
\ No newline at end of file
exports.DbTable = DbTable;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGJjb2xsZWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRkYXRhLmNsYXNzZXMuZGJjb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSwrQ0FBOEM7QUFlOUMsb0JBQTRCLEVBQU07SUFDaEMsTUFBTSxDQUFDLFVBQVUsV0FBVztRQUMxQixXQUFXLENBQUUsY0FBYyxDQUFFLEdBQUcsSUFBSSxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFBO0lBQzlELENBQUMsQ0FBQTtBQUNILENBQUM7QUFKRCxnQ0FJQztBQUVEO0lBVUUsWUFBYSxpQkFBK0IsRUFBRSxLQUFTO1FBSnZELHFCQUFnQixHQUFzQixJQUFJLENBQUE7UUFLeEMsdUNBQXVDO1FBQ3ZDLElBQUksQ0FBQyxTQUFTLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFBO1FBQ3ZDLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxDQUFBO1FBRWYsd0ZBQXdGO1FBQ3hGLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ3hCLENBQUM7SUFFSyxJQUFJOztZQUNSLEVBQUUsQ0FBQSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQ2YsNkNBQTZDO2dCQUM3QyxNQUFNLGVBQWUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxTQUFTO3FCQUM1QyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUM7cUJBQ2xCLFNBQVMsRUFBRTtxQkFDWCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQTtnQkFDNUIsRUFBRSxDQUFBLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUMzQyxNQUFNLE9BQU8sQ0FBQyxTQUFTO3lCQUN0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
\ No newline at end of file
import { Objectmap } from 'lik';
import { DbCollection } from './smartdata.classes.dbcollection';
import { DbTable } from './smartdata.classes.dbcollection';
export declare type TDocCreation = 'db' | 'new' | 'mixed';
/**
* saveable - saveable decorator to be used on class properties
......@@ -9,11 +9,11 @@ export declare class DbDoc<T> {
/**
* the collection object an Doc belongs to
*/
collection: DbCollection<T>;
collection: DbTable<T>;
/**
* how the Doc in memory was created, may prove useful later.
*/
creationType: TDocCreation;
creationStatus: TDocCreation;
/**
* an array of saveable properties of a doc
*/
......@@ -22,6 +22,10 @@ export declare class DbDoc<T> {
* name
*/
name: string;
/**
* primary id in the database
*/
dbId: string;
/**
* class constructor
*/
......@@ -30,10 +34,11 @@ export declare class DbDoc<T> {
* saves this instance but not any connected items
* may lead to data inconsistencies, but is faster
*/
save(): void;
save(): Promise<void>;
/**
* also store any referenced objects to DB
* better for data consistency
*/
saveDeep(savedMapArg?: Objectmap<DbDoc<any>>): void;
createSavableObject(): any;
}
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const lik_1 = require("lik");
/**
......@@ -19,6 +27,10 @@ class DbDoc {
* class constructor
*/
constructor() {
/**
* how the Doc in memory was created, may prove useful later.
*/
this.creationStatus = 'new';
this.name = this.constructor['name'];
this.collection = this.constructor['dbCollection'];
}
......@@ -27,17 +39,20 @@ class DbDoc {
* may lead to data inconsistencies, but is faster
*/
save() {
let saveableObject = {}; // is not exposed to outside, so any is ok here
for (let propertyNameString of this.saveableProperties) {
saveableObject[propertyNameString] = this[propertyNameString];
}
switch (this.creationType) {
case 'db':
this.collection; // TODO implement collection.update()
break;
case 'new':
this.collection.insertOne(saveableObject);
}
return __awaiter(this, void 0, void 0, function* () {
let self = this;
switch (this.creationStatus) {
case 'db':
yield this.collection.update(self);
break;
case 'new':
let writeResult = yield this.collection.insert(self);
this.creationStatus = 'db';
break;
default:
console.error('neither new nor in db?');
}
});
}
/**
* also store any referenced objects to DB
......@@ -56,6 +71,13 @@ class DbDoc {
}
}
}
createSavableObject() {
let saveableObject = {}; // is not exposed to outside, so any is ok here
for (let propertyNameString of this.saveableProperties) {
saveableObject[propertyNameString] = this[propertyNameString];
}
return saveableObject;
}
}
exports.DbDoc = DbDoc;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGJkb2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYmRvYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLDZCQUErQjtBQU8vQjs7R0FFRztBQUNIO0lBQ0UsTUFBTSxDQUFDLENBQUMsTUFBa0IsRUFBRSxHQUFXO1FBQ3JDLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDekIsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDO1lBQUMsTUFBTSxDQUFDLGtCQUFrQixHQUFHLEVBQUUsQ0FBQTtRQUFDLENBQUM7UUFDbEUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUNyQyxDQUFDLENBQUE7QUFDSCxDQUFDO0FBTkQsb0JBTUM7QUFFRDtJQXNCRTs7T0FFRztJQUNIO1FBQ0UsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ3BDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBRSxjQUFjLENBQUUsQ0FBQTtJQUN0RCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBSTtRQUNGLElBQUksY0FBYyxHQUFRLEVBQUUsQ0FBQSxDQUFDLCtDQUErQztRQUM1RSxHQUFHLENBQUMsQ0FBQyxJQUFJLGtCQUFrQixJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7WUFDdkQsY0FBYyxDQUFFLGtCQUFrQixDQUFFLEdBQUcsSUFBSSxDQUFFLGtCQUFrQixDQUFFLENBQUE7UUFDbkUsQ0FBQztRQUNELE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQzFCLEtBQUssSUFBSTtnQkFDUCxJQUFJLENBQUMsVUFBVSxDQUFBLENBQUMscUNBQXFDO2dCQUNyRCxLQUFLLENBQUE7WUFDUCxLQUFLLEtBQUs7Z0JBQ1IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLENBQUE7UUFDN0MsQ0FBQztJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxRQUFRLENBQUMsY0FBcUMsSUFBSTtRQUNoRCxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFDakIsV0FBVyxHQUFHLElBQUksZUFBUyxFQUFjLENBQUE7UUFDM0MsQ0FBQztRQUNELFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDckIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ1gsR0FBRyxDQUFDLENBQUMsSUFBSSxXQUFXLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQztZQUM3QixJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUUsV0FBVyxDQUFFLENBQUE7WUFDbEMsRUFBRSxDQUFDLENBQUMsUUFBUSxZQUFZLEtBQUssSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN2RSxRQUFRLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1lBQ2hDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBakVELHNCQWlFQyJ9
\ No newline at end of file
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGJkb2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYmRvYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBRUEsNkJBQStCO0FBTy9COztHQUVHO0FBQ0g7SUFDRSxNQUFNLENBQUMsQ0FBQyxNQUFrQixFQUFFLEdBQVcsRUFBRSxFQUFFO1FBQ3pDLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDekIsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDO1lBQUMsTUFBTSxDQUFDLGtCQUFrQixHQUFHLEVBQUUsQ0FBQTtRQUFDLENBQUM7UUFDbEUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUNyQyxDQUFDLENBQUE7QUFDSCxDQUFDO0FBTkQsb0JBTUM7QUFFRDtJQTJCRTs7T0FFRztJQUNIO1FBdkJBOztXQUVHO1FBQ0gsbUJBQWMsR0FBaUIsS0FBSyxDQUFBO1FBcUJsQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDcEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFFLGNBQWMsQ0FBRSxDQUFBO0lBQ3RELENBQUM7SUFFRDs7O09BR0c7SUFDRyxJQUFJOztZQUNSLElBQUksSUFBSSxHQUFRLElBQUksQ0FBQTtZQUNwQixNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztnQkFDNUIsS0FBSyxJQUFJO29CQUNQLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUE7b0JBQ2xDLEtBQUssQ0FBQTtnQkFDUCxLQUFLLEtBQUs7b0JBQ1IsSUFBSSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQTtvQkFDcEQsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUE7b0JBQzFCLEtBQUssQ0FBQztnQkFDUjtvQkFDRSxPQUFPLENBQUMsS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUE7WUFDM0MsQ0FBQztRQUNILENBQUM7S0FBQTtJQUVEOzs7T0FHRztJQUNILFFBQVEsQ0FBRSxjQUFxQyxJQUFJO1FBQ2pELEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztZQUNqQixXQUFXLEdBQUcsSUFBSSxlQUFTLEVBQWMsQ0FBQTtRQUMzQyxDQUFDO1FBQ0QsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNyQixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUE7UUFDWCxHQUFHLENBQUMsQ0FBQyxJQUFJLFdBQVcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzdCLElBQUksUUFBUSxHQUFRLElBQUksQ0FBRSxXQUFXLENBQUUsQ0FBQTtZQUN2QyxFQUFFLENBQUMsQ0FBQyxRQUFRLFlBQVksS0FBSyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZFLFFBQVEsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUE7WUFDaEMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsbUJBQW1CO1FBQ2pCLElBQUksY0FBYyxHQUFRLEVBQUUsQ0FBQSxDQUFDLCtDQUErQztRQUM1RSxHQUFHLENBQUMsQ0FBQyxJQUFJLGtCQUFrQixJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7WUFDdkQsY0FBYyxDQUFFLGtCQUFrQixDQUFFLEdBQUcsSUFBSSxDQUFFLGtCQUFrQixDQUFFLENBQUE7UUFDbkUsQ0FBQztRQUNELE1BQU0sQ0FBQyxjQUFjLENBQUE7SUFDdkIsQ0FBQztDQUNGO0FBL0VELHNCQStFQyJ9
\ No newline at end of file
import { Db } from './smartdata.classes.db';
import { DbDoc } from './smartdata.classes.dbdoc';
export declare let getObjectDoc: (nameArg: any, dbArg: Db) => DbDoc<{}>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const smartdata_classes_dbdoc_1 = require("./smartdata.classes.dbdoc");
const smartdata_classes_dbcollection_1 = require("./smartdata.classes.dbcollection");
exports.getObjectDoc = (nameArg, dbArg) => {
let objectDoc = new smartdata_classes_dbdoc_1.DbDoc();
objectDoc.name = nameArg;
objectDoc.collection = new smartdata_classes_dbcollection_1.DbCollection(objectDoc, dbArg);
return objectDoc;
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGJvYmplY3Rkb2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYm9iamVjdGRvYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUdBLHVFQUFpRDtBQUNqRCxxRkFBK0Q7QUFFcEQsUUFBQSxZQUFZLEdBQUcsQ0FBQyxPQUFPLEVBQUMsS0FBUztJQUMxQyxJQUFJLFNBQVMsR0FBRyxJQUFJLCtCQUFLLEVBQUUsQ0FBQTtJQUMzQixTQUFTLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQTtJQUN4QixTQUFTLENBQUMsVUFBVSxHQUFHLElBQUksNkNBQVksQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFDekQsTUFBTSxDQUFDLFNBQVMsQ0FBQTtBQUNsQixDQUFDLENBQUEifQ==
\ No newline at end of file
import 'typings-global';
import * as assert from 'assert';
import * as beautylog from 'beautylog';
import * as lodash from 'lodash';
import * as mongodb from 'mongodb';
import * as rethinkDb from 'rethinkdb';
import * as smartq from 'smartq';
export { assert, beautylog, lodash, mongodb, smartq };
import * as smartstring from 'smartstring';
export { assert, beautylog, lodash, smartq, rethinkDb, smartstring };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("typings-global");
const assert = require("assert");
exports.assert = assert;
const beautylog = require("beautylog");
exports.beautylog = beautylog;
const lodash = require("lodash");
exports.lodash = lodash;
const mongodb = require("mongodb");
exports.mongodb = mongodb;
const rethinkDb = require("rethinkdb");
exports.rethinkDb = rethinkDb;
const smartq = require("smartq");
exports.smartq = smartq;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDBCQUF1QjtBQUN2QixpQ0FBZ0M7QUFPNUIsd0JBQU07QUFOVix1Q0FBc0M7QUFPbEMsOEJBQVM7QUFOYixpQ0FBZ0M7QUFPNUIsd0JBQU07QUFOVixtQ0FBa0M7QUFPOUIsMEJBQU87QUFOWCxpQ0FBZ0M7QUFPNUIsd0JBQU0ifQ==
\ No newline at end of file
const smartstring = require("smartstring");
exports.smartstring = smartstring;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFnQztBQVE1Qix3QkFBTTtBQVBWLHVDQUFzQztBQVFsQyw4QkFBUztBQVBiLGlDQUFnQztBQVE1Qix3QkFBTTtBQVBWLHVDQUFzQztBQVNsQyw4QkFBUztBQVJiLGlDQUFnQztBQU81Qix3QkFBTTtBQU5WLDJDQUEwQztBQVF0QyxrQ0FBVyJ9
\ No newline at end of file
......@@ -18,93 +18,6 @@ do more with data
[![node](https://img.shields.io/badge/node->=%206.x.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
## Usage
Use TypeScript for best in class instellisense.
smartdata is an ODM that adheres to TypeScript practices and uses classes to organize data.
It uses MongoDB or NeDb as persistent storage.
## Intention
There are many ODMs out there, however when we searched for an ODM that uses TypeScript,
acts smart while still embracing the NoSQL idea we didn't find a matching solution.
This is why we started smartdata.
How MongoDB terms map to smartdata classes
MongoDB term | smartdata class
--- | ---
Database | smartdata.Db
Collection | smartdata.DbCollection
Document | smartdata.DbDoc
### class Db
represents a Database. Naturally it has .connect() etc. methods on it.
Since it is a class you can have multiple DBs defined.
```javascript
import * as smartdata from 'smartdata'
// mongodb
let myDb1 = new smartdata.Db('someConnectionUrl')
let myDb2 = new smartdata.Db('someConnectionUrl')
// nedb
let myDb3 = new smartdata('/some/path/for/persistence', 'nedb') // you may set first argument to null for just in memory db
myDb1.connect()
myDb2.connect()
// continues in next block...
```
### class DbCollection
represents a collection of objects.
A collection is defined by the object class (that is extending smartdata.dbdoc) it respresents
So to get to get access to a specific collection you document
```javascript
// continues from the block before...
@Collection(myDb1)
class myObject extends smartdata.DbDoc<myObject> { // read the next block about DbDoc
@smartdata.svDb() property1: string // @smartdata.svDb() marks the property for db save
property2: number // this one is not marked, so it won't be save upon calling this.save()
constructor(optionsArg:{
property1: string,
property2: number
}) {
super()
}
}
let myCollection = myDb1.getCollectionByName<myObject>(myObject)
// start to instantiate classes from scratch or database
```
> Alert: You NEVER instantiate a collection.
This is done for you!!!
### class DbDoc
represents a individual document in a collection
and thereby is ideally suited to extend the class you want to actually store.
DbDoc extends your class with the following methods:
* `.save()` will save (or update) the object you call it on only. Any referenced non-savable objects will not get stored.
* `.saveDeep()` does the same like `.save()`.
In addition it will look for properties that reference an object
that extends DbDoc as well and call .saveDeep() on them as well.
Loops are prevented
So now we can **store** instances of classes to Db...
How do we **get** a new class instance from a Doc in the DB?
## TypeScript
How does TypeScript play into this?
Since you define your classes in TypeScript and types flow through smartdata in a generic way
you should get all the Intellisense and type checking you love when using smartdata.
smartdata itself also bundles typings.
So you don't need to install any additional types when importing smartdata.
For further information read the linked docs at the top of this README.
> MIT licensed | **&copy;** [Lossless GmbH](https://lossless.gmbh)
......
......@@ -5,7 +5,7 @@
"dockerSock": false
},
"npmci": {
"globalNpmTools": [
"npmGlobalTools": [
"npmts"
]
},
......
{
"name": "smartdata",
"version": "2.0.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/lodash": {
"version": "4.14.92",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.92.tgz",
"integrity": "sha512-cdvY1fyUGYgG7/i07a/sR5PnD6+Z+ljUrD0CNVf0qj645VvEdLNtZPjvCp4siPy3rQ/KRXMfUATIqi3+9x57Sw=="
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA=="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"conventional-commit-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-2.2.0.tgz",
"integrity": "sha1-XblXOdbCEqy+e29lahG5QLqmiUY=",
"dev": true
},
"cz-conventional-changelog": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-2.1.0.tgz",
"integrity": "sha1-L0vHOQ4yROTfKT5ro1Hkx0Cnx2Q=",
"dev": true,
"requires": {
"conventional-commit-types": "2.2.0",
"lodash.map": "4.6.0",
"longest": "1.0.1",
"right-pad": "1.0.1",
"word-wrap": "1.2.3"
}
},
"define-properties": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
"integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
"requires": {
"foreach": "2.0.5",
"object-keys": "1.0.11"
}
},
"es-abstract": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz",
"integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==",
"requires": {
"es-to-primitive": "1.1.1",
"function-bind": "1.1.1",
"has": "1.0.1",
"is-callable": "1.1.3",
"is-regex": "1.0.4"
}
},
"es-to-primitive": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
"integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
"requires": {
"is-callable": "1.1.3",
"is-date-object": "1.0.1",
"is-symbol": "1.0.1"
}
},
"foreach": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"has": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
"integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
"requires": {
"function-bind": "1.1.1"
}
},
"is-callable": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
"integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI="
},
"is-date-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
},
"is-regex": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
"requires": {
"has": "1.0.1"
}
},
"is-symbol": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
"integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI="
},
"lik": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lik/-/lik-2.0.2.tgz",
"integrity": "sha512-xdNrvQqVLMNkU25Z6tNrJXyOhn0hugZvWZCIPb315M5J4fK2OzgpLacp68J5bYWydRWX4L3Tl/i69BNWHsvcXg==",
"requires": {
"@types/lodash": "4.14.92",
"@types/minimatch": "3.0.3",
"lodash": "4.17.4",
"minimatch": "3.0.4",
"smartq": "1.1.6",
"symbol-tree": "3.2.2",
"typings-global": "1.0.28"
},
"dependencies": {
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
},
"smartq": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/smartq/-/smartq-1.1.6.tgz",
"integrity": "sha512-W7vTj4kSqN8kHVq+Q6BJTr/UGc36TnO0pzKNU8B4cr7TXG4N98eyubWaaCHPSjCUqDgmUPPru929WXzetai97A==",
"requires": {
"typings-global": "1.0.28",
"util.promisify": "1.0.0"
}
}
}
},
"lodash.map": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
"integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=",
"dev": true
},
"longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
"dev": true
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "1.1.8"
}
},
"object-keys": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
"integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0="
},
"object.getownpropertydescriptors": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
"integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
"requires": {
"define-properties": "1.1.2",
"es-abstract": "1.10.0"
}
},
"right-pad": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/right-pad/-/right-pad-1.0.1.tgz",
"integrity": "sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA=",
"dev": true
},
"symbol-tree": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
"integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY="
},
"typings-global": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/typings-global/-/typings-global-1.0.28.tgz",
"integrity": "sha512-6VOwJWEY2971HOMHu/7sURzUXiD4/LiMJPsMAOqkHHAtS3MVpLFE5gzTiHilsH9KY5VE1mBQirWIgWFsDuo90A=="
},
"util.promisify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
"integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
"requires": {
"define-properties": "1.1.2",
"object.getownpropertydescriptors": "2.0.3"
}
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"dev": true
}
}
}
{
"name": "smartdata",
"version": "1.0.27",
"version": "2.0.2",
"description": "do more with data",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
......@@ -19,21 +19,27 @@
},
"homepage": "https://gitlab.com/pushrocks/smartdata#README",
"dependencies": {
"@types/lodash": "^4.14.69",
"@types/mongodb": "^2.2.7",
"@types/lodash": "^4.14.92",
"@types/rethinkdb": "^2.3.8",
"beautylog": "^6.1.10",
"lik": "^1.0.38",
"lik": "^2.0.2",
"lodash": "^4.17.4",
"mongodb": "^2.2.30",
"rethinkdb": "^2.3.3",
"runtime-type-checks": "0.0.4",
"smartq": "^1.1.6",
"typings-global": "^1.0.19"
"smartstring": "^2.0.28"
},
"devDependencies": {
"@types/shelljs": "^0.7.2",
"@types/node": "^8.5.7",
"@types/shelljs": "^0.7.4",
"cz-conventional-changelog": "^2.1.0",
"qenv": "^1.1.7",
"shelljs": "^0.7.8",
"smartstring": "^2.0.24",
"tapbundle": "^1.1.1"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
vars:
- MONGO_USER
- MONGO_PASS
- MONGO_DATABASE
- RDB_DB
- RDB_HOST
- RDB_USER
- RDB_PASS
- RDB_PORT
- RDB_CERT
import { tap, expect } from 'tapbundle'
import * as smartq from 'smartq'
import { Qenv } from 'qenv'
let testQenv = new Qenv(process.cwd(), process.cwd() + '/.nogit/')
// the tested module
import * as smartdata from '../dist/index'
let mongoChildProcess
let testDb: smartdata.Db
tap.test('should establish a connection to mongodb', async () => {
testDb = new smartdata.Db(`mongodb://${process.env.MONGO_USER}:${process.env.MONGO_PASS}@sandbox-shard-00-00-uyw7y.mongodb.net:27017,sandbox-shard-00-01-uyw7y.mongodb.net:27017,sandbox-shard-00-02-uyw7y.mongodb.net:27017/${process.env.MONGO_DATABASE}?ssl=true&replicaSet=sandbox-shard-0&authSource=admin`)
await testDb.connect()
})
let testCarInstance
tap.test('should create an extended class', async () => {
@smartdata.Collection(testDb)
class TestCar extends smartdata.DbDoc<TestCar> {
@smartdata.svDb()
color: string
constructor (optionsArg: {
color: string,
property2: number
}) {
super()
this.color = optionsArg.color
}
}
testCarInstance = new TestCar({
color: 'red',
property2: 2
})
expect(testCarInstance.name).to.equal('TestCar')
expect(testCarInstance.saveableProperties[ 0 ]).equal('color')
expect(testCarInstance.collection).be.instanceof(smartdata.DbCollection)
expect(testCarInstance).be.instanceof(smartdata.DbDoc)
if (!process.env.CI) { console.log(TestCar) }
})
tap.test('should save testCar', async () => {
await testCarInstance.save()
})
tap.test('should close the db Connection', async () => {
await testDb.close()
})
tap.start()
......@@ -5,19 +5,24 @@ import { Qenv } from 'qenv'
let testQenv = new Qenv(process.cwd(), process.cwd() + '/.nogit/')
// the tested module
import * as smartdata from '../dist/index'
import * as smartdata from '../ts/index'
import { smartstring } from '../ts/smartdata.plugins';
let mongoChildProcess
let testDb: smartdata.Db
// =======================================
// Connecting to the database server
// =======================================
interface ITestObject1 {
value1: string
value2?: number
value3?: string
}
let testDb = new smartdata.Db({
db: process.env.RDB_DB,
host: process.env.RDB_HOST,
user: process.env.RDB_USER,
password: process.env.RDB_PASS,
port: parseInt(process.env.RDB_PORT)
})
testDb.setSsl(process.env.RDB_CERT, 'base64')
tap.test('should establish a connection to mongodb', async () => {
testDb = new smartdata.Db(`mongodb://${process.env.MONGO_USER}:${process.env.MONGO_PASS}@sandbox-shard-00-00-uyw7y.mongodb.net:27017,sandbox-shard-00-01-uyw7y.mongodb.net:27017,sandbox-shard-00-02-uyw7y.mongodb.net:27017/${process.env.MONGO_DATABASE}?ssl=true&replicaSet=sandbox-shard-0&authSource=admin`)
tap.test('should establish a connection to the rethink Db cluster', async () => {
await testDb.connect()
})
......@@ -25,40 +30,31 @@ tap.test('should establish a connection to mongodb', async () => {
// The actual tests
// =======================================
let testDbCollection: smartdata.DbCollection<ITestObject1>
tap.test('should give me a collection', async () => {
testDbCollection = await testDb.getObjectCollectionByName<ITestObject1>('TestValue', testDb, true)
})
tap.test('should insert a doc into the collection', async () => {
await testDbCollection.insertOne({ value1: 'test' })
})
tap.test('should find all docs of testDbCollection', async () => {
await testDbCollection.find({}).then(async (resultArray) => {
console.log(resultArray)
expect(resultArray[ 0 ].value1).equal('test')
})
})
tap.test('should insert many docs into the collection', async () => {
await testDbCollection.insertMany([
{ value1: 'test2' },
{ value1: 'test', value2: 3, value3: 'hi' }
])
})
// ------
// Collections
// ------
@smartdata.Collection(testDb)
class Car extends smartdata.DbDoc<Car> {
@smartdata.svDb() color: string
@smartdata.svDb() brand: string
constructor (colorArg: string, brandArg: string) {
super()
this.color = colorArg
this.brand = brandArg
}
}
tap.test('should find a specified doc', async () => {
await testDbCollection.find({ 'value3': { '$exists': true } }).then((resultArray) => {
console.log(resultArray)
expect(resultArray[ 0 ].value3).equal('hi')
})
tap.test('should save the car to the db', async () => {
const myCar = new Car('red','Volvo')
await myCar.save()
})
tap.test('should close the db Connection', async () => {
// =======================================
// close the database connection
// =======================================
tap.test('should close the database connection', async (tools) => {
await testDb.close()
})
......
import * as plugins from './smartdata.plugins'
import { Objectmap } from 'lik'
import { DbCollection } from './smartdata.classes.dbcollection'
import { getObjectDoc } from './smartdata.classes.dbobjectdoc'
import { DbTable } from './smartdata.classes.dbcollection'
import { Connection as dbConnection, ConnectionOptions } from 'rethinkdb'
/**
* interface - indicates the connection status of the db
*/
export type TConnectionStatus = 'disconnected' | 'connected' | 'failed'
export type TConnectionStatus = 'initial' | 'disconnected' | 'connected' | 'failed'
export class Db {
dbUrl: string
db: plugins.mongodb.Db
dbName: string
connectionOptions: plugins.rethinkDb.ConnectionOptions
dbConnection: plugins.rethinkDb.Connection
status: TConnectionStatus
classCollections = new Objectmap<DbCollection<any>>()
objectCollections = new Objectmap<DbCollection<any>>()
dbTablesMap = new Objectmap<DbTable<any>>()
constructor (dbUrlArg: string) {
this.dbUrl = dbUrlArg
constructor(connectionOptionsArg: ConnectionOptions) {
this.dbName = connectionOptionsArg.db
this.connectionOptions = connectionOptionsArg
this.status = 'initial'
}
/**
* supply additional SSl options
*/
setSsl (certificateStringArg: string, formatArg: 'base64' | 'clearText') {
let certificateString: string
if(formatArg = 'base64') {
certificateString = plugins.smartstring.base64.decode(certificateStringArg)
} else {
certificateString = certificateStringArg
}
this.connectionOptions['ssl'] = {
ca: Buffer.from(certificateString)
}
}
// basic connection stuff ----------------------------------------------
......@@ -25,58 +43,37 @@ export class Db {
/**
* connects to the database that was specified during instance creation
*/
connect (): Promise<any> {
let done = plugins.smartq.defer()
plugins.mongodb.MongoClient.connect(this.dbUrl, (err, db) => {
if (err) { console.log(err) }
plugins.assert.equal(null, err)
this.db = db
plugins.beautylog.success(`connected to database at ${this.dbUrl}`)
done.resolve(this.db)
})
return done.promise
async connect (): Promise<any> {
this.dbConnection = await plugins.rethinkDb.connect(this.connectionOptions)
this.dbConnection.use(this.dbName)
this.status = 'connected'
plugins.beautylog.ok(`Connected to database ${this.dbName}`)
}
/**
* closes the connection to the databse
*/
close (): Promise<any> {
let done = plugins.smartq.defer()
this.db.close()
plugins.beautylog.ok(`disconnected to database at ${this.dbUrl}`)
done.resolve()
return done.promise
async close (): Promise<any> {
await this.dbConnection.close()
this.status = 'disconnected'
plugins.beautylog.ok(`disconnected from database ${this.dbName}`)
}
// advanced communication with the database --------------------------------
// handle table to class distribution
/**
* gets a class based collection by name: string
* Gets a table's name and returns smartdata's DbTable class
* @param nameArg
* @returns DbTable
*/
async getClassCollectionByName<T> (nameArg: string): Promise<DbCollection<T>> {
let resultCollection = this.classCollections.find((dbCollectionArg) => {
return dbCollectionArg.name === nameArg
async getDbTableByName<T>(nameArg: string): Promise<DbTable<T>> {
let resultCollection = this.dbTablesMap.find((dbCollectionArg) => {
return dbCollectionArg.tableName === nameArg
})
return resultCollection
}
/**
* gets an object collection by name
*/
async getObjectCollectionByName<T> (nameArg: string, dbArg: Db , makeNewArg: boolean = false): Promise<DbCollection<T>> {
let resultCollection = this.objectCollections.find((dbCollectionArg) => {
return dbCollectionArg.name === nameArg
})
if (!resultCollection && makeNewArg) {
resultCollection = getObjectDoc(nameArg, this).collection
return resultCollection
} else {
return resultCollection
}
}
addCollection (dbCollectionArg: DbCollection<any>) {
this.classCollections.add(dbCollectionArg)
addTable (dbCollectionArg: DbTable<any>) {
this.dbTablesMap.add(dbCollectionArg)
}
}
......@@ -2,6 +2,9 @@ import * as plugins from './smartdata.plugins'
import { Db } from './smartdata.classes.db'
import { DbDoc } from './smartdata.classes.dbdoc'
// RethinkDb Interfaces
import { WriteResult, Cursor } from 'rethinkdb'
export interface IFindOptions {
limit?: number
}
......@@ -12,32 +15,44 @@ export interface IDocValidation<T> {
export function Collection (db: Db) {
return function (constructor) {
constructor[ 'dbCollection' ] = new DbCollection(constructor, db)
constructor[ 'dbCollection' ] = new DbTable(constructor, db)
}
}
export class DbCollection<T> {
export class DbTable<T> {<