Compare commits
106 Commits
Author | SHA1 | Date | |
---|---|---|---|
72894e3ef1 | |||
bbe5f8c6a8 | |||
02af9f5c4b | |||
17de480272 | |||
776fd3ee4e | |||
3272bb7235 | |||
116dfbc3b0 | |||
3f714b1a33 | |||
e58fa57525 | |||
8e7ad5210f | |||
cea6c662ac | |||
6eb43a4b9f | |||
7f89cbeecd | |||
a042a589a0 | |||
75b5f6af08 | |||
e6a36f22ac | |||
246e3486f0 | |||
c1c4a29415 | |||
6448516aa0 | |||
24a7b2dbd3 | |||
afa7c2fe61 | |||
b768896fbe | |||
8d7d9adef1 | |||
ca6d3c60c0 | |||
38c1fcd53a | |||
e433b9e212 | |||
bf3656f792 | |||
7e9fc62ce7 | |||
670a0c63fb | |||
64e76b3ed1 | |||
25803330de | |||
c6cbff1308 | |||
3eeac7b936 | |||
761b742e21 | |||
e56def621c | |||
ab1799f4f2 | |||
9985b849d1 | |||
1800273b25 | |||
e715cc6d37 | |||
f7abc175aa | |||
bbcb3a614e | |||
941d2f0902 | |||
5c78f83a28 | |||
124f117352 | |||
f67da898ae | |||
3c8f70f77e | |||
3674d7d9a5 | |||
fe2a622488 | |||
f092eefbf3 | |||
8d0aa361f9 | |||
692a1223a8 | |||
ae7d101ab9 | |||
3825b15a65 | |||
3fc41678d2 | |||
39f1b7ada1 | |||
f763de2403 | |||
cba1d031b6 | |||
d31e6a5931 | |||
46514a2743 | |||
1cf02157c4 | |||
72efa14da8 | |||
a73c2084c0 | |||
5ed557a21a | |||
2b6c30ff55 | |||
12ef599333 | |||
191ea5d3c6 | |||
bdf33ed1ca | |||
1c76905dcd | |||
4d88cea69d | |||
8b4f7169ff | |||
2a1c45608f | |||
85a6444263 | |||
766ae1d1ff | |||
7630882312 | |||
4aec47f207 | |||
c2e3a1ae6e | |||
3d8f8646b1 | |||
aca9817c56 | |||
7e341f2b50 | |||
d2ca108ef8 | |||
e2d12f8c9c | |||
cfcd9ab386 | |||
3048035374 | |||
6c70cf05c4 | |||
04b0910883 | |||
3671fe4df4 | |||
bd30da1c4a | |||
05938bf2af | |||
cddb0caf1f | |||
1af51dd989 | |||
8101e49026 | |||
2d97ab9dc5 | |||
3ba2bc8446 | |||
5735ab8577 | |||
def671cbe4 | |||
14042151ba | |||
c74873d02c | |||
800cdd655a | |||
68c0ceeb14 | |||
154dc5c1b3 | |||
d5c027caf0 | |||
30776a7da0 | |||
fedc0bd8c8 | |||
7b78b47a1b | |||
a4acfc0f6e | |||
a934f3608f |
21
.gitignore
vendored
21
.gitignore
vendored
@ -1,5 +1,20 @@
|
||||
node_modules/
|
||||
test/data
|
||||
pages/
|
||||
.nogit/
|
||||
|
||||
# artifacts
|
||||
coverage/
|
||||
public/
|
||||
pages/
|
||||
|
||||
# installs
|
||||
node_modules/
|
||||
|
||||
# caches
|
||||
.yarn/
|
||||
.cache/
|
||||
.rpt2_cache
|
||||
|
||||
# builds
|
||||
dist/
|
||||
dist_*/
|
||||
|
||||
# custom
|
105
.gitlab-ci.yml
105
.gitlab-ci.yml
@ -1,72 +1,127 @@
|
||||
# gitzone standard
|
||||
image: hosttoday/ht-docker-node:npmci
|
||||
# gitzone ci_default
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
|
||||
cache:
|
||||
paths:
|
||||
- .yarn/
|
||||
key: "$CI_BUILD_STAGE"
|
||||
- .npmci_cache/
|
||||
key: '$CI_BUILD_STAGE'
|
||||
|
||||
stages:
|
||||
- test
|
||||
- release
|
||||
- trigger
|
||||
- pages
|
||||
- security
|
||||
- test
|
||||
- release
|
||||
- metadata
|
||||
|
||||
testLEGACY:
|
||||
stage: test
|
||||
# ====================
|
||||
# security stage
|
||||
# ====================
|
||||
mirror:
|
||||
stage: security
|
||||
script:
|
||||
- npmci test legacy
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
- npmci git mirror
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
allow_failure: true
|
||||
- notpriv
|
||||
|
||||
testLTS:
|
||||
audit:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci command npm install --ignore-scripts
|
||||
- npmci command npm config set registry https://registry.npmjs.org
|
||||
- npmci command npm audit --audit-level=high
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
# ====================
|
||||
# test stage
|
||||
# ====================
|
||||
|
||||
testStable:
|
||||
stage: test
|
||||
script:
|
||||
- npmci test lts
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci npm test
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
|
||||
testSTABLE:
|
||||
- priv
|
||||
|
||||
testBuild:
|
||||
stage: test
|
||||
script:
|
||||
- npmci test stable
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci command npm run build
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
release:
|
||||
stage: release
|
||||
script:
|
||||
- npmci publish
|
||||
- npmci node install stable
|
||||
- npmci npm publish
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
# ====================
|
||||
# metadata stage
|
||||
# ====================
|
||||
codequality:
|
||||
stage: metadata
|
||||
allow_failure: true
|
||||
script:
|
||||
- npmci command npm install -g tslint typescript
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- priv
|
||||
|
||||
trigger:
|
||||
stage: trigger
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci trigger
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
pages:
|
||||
image: hosttoday/ht-docker-node:npmci
|
||||
stage: pages
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci command yarn global add npmpage
|
||||
- npmci command npmpage
|
||||
- npmci node install lts
|
||||
- npmci command npm install -g @gitzone/tsdoc
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command tsdoc
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
only:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- public
|
||||
- public
|
||||
allow_failure: true
|
||||
|
29
.vscode/launch.json
vendored
Normal file
29
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "current file",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"${relativeFile}"
|
||||
],
|
||||
"runtimeArgs": ["-r", "@gitzone/tsrun"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
},
|
||||
{
|
||||
"name": "test.ts",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"test/test.ts"
|
||||
],
|
||||
"runtimeArgs": ["-r", "@gitzone/tsrun"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
}
|
||||
]
|
||||
}
|
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": ["/npmextra.json"],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"npmci": {
|
||||
"type": "object",
|
||||
"description": "settings for npmci"
|
||||
},
|
||||
"gitzone": {
|
||||
"type": "object",
|
||||
"description": "settings for gitzone",
|
||||
"properties": {
|
||||
"projectType": {
|
||||
"type": "string",
|
||||
"enum": ["website", "element", "service", "npm"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
105
README.md
105
README.md
@ -1,105 +0,0 @@
|
||||
# smartdata
|
||||
|
||||
> Note: Still in Beta
|
||||
|
||||
## Availabililty
|
||||
[](https://www.npmjs.com/package/smartdata)
|
||||
[](https://gitlab.com/pushrocks/smartdata)
|
||||
[](https://github.com/pushrocks/smartdata)
|
||||
[](https://pushrocks.gitlab.io/smartdata/)
|
||||
|
||||
## Status for master
|
||||
[](https://gitlab.com/pushrocks/smartdata/commits/master)
|
||||
[](https://gitlab.com/pushrocks/smartdata/commits/master)
|
||||
[](https://david-dm.org/pushrocks/smartdata)
|
||||
[](https://www.bithound.io/github/pushrocks/smartdata/master/dependencies/npm)
|
||||
[](https://www.bithound.io/github/pushrocks/smartdata)
|
||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
||||
[](http://standardjs.com/)
|
||||
|
||||
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.
|
||||
|
||||
[](https://push.rocks)
|
3
dist/index.d.ts
vendored
3
dist/index.d.ts
vendored
@ -1,3 +0,0 @@
|
||||
export * from './smartdata.classes.db';
|
||||
export * from './smartdata.classes.dbcollection';
|
||||
export * from './smartdata.classes.dbdoc';
|
9
dist/index.js
vendored
9
dist/index.js
vendored
@ -1,9 +0,0 @@
|
||||
"use strict";
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__export(require("./smartdata.classes.db"));
|
||||
__export(require("./smartdata.classes.dbcollection"));
|
||||
__export(require("./smartdata.classes.dbdoc"));
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUVBLDRDQUFzQztBQUN0QyxzREFBZ0Q7QUFDaEQsK0NBQXlDIn0=
|
27
dist/smartdata.classes.db.d.ts
vendored
27
dist/smartdata.classes.db.d.ts
vendored
@ -1,27 +0,0 @@
|
||||
import * as plugins from './smartdata.plugins';
|
||||
import { Objectmap } from 'lik';
|
||||
import { DbCollection } from './smartdata.classes.dbcollection';
|
||||
/**
|
||||
* interface - indicates the connection status of the db
|
||||
*/
|
||||
export declare type TConnectionStatus = 'disconnected' | 'connected' | 'failed';
|
||||
export declare class Db {
|
||||
dbUrl: string;
|
||||
db: plugins.mongodb.Db;
|
||||
status: TConnectionStatus;
|
||||
collections: Objectmap<DbCollection<any>>;
|
||||
constructor(dbUrlArg: string);
|
||||
/**
|
||||
* connects to the database that was specified during instance creation
|
||||
*/
|
||||
connect(): Promise<any>;
|
||||
/**
|
||||
* closes the connection to the databse
|
||||
*/
|
||||
close(): Promise<any>;
|
||||
/**
|
||||
* gets a collection by name: string
|
||||
*/
|
||||
getCollectionByName<T>(nameArg: string): Promise<DbCollection<T>>;
|
||||
addCollection(dbCollectionArg: DbCollection<any>): void;
|
||||
}
|
56
dist/smartdata.classes.db.js
vendored
56
dist/smartdata.classes.db.js
vendored
@ -1,56 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const plugins = require("./smartdata.plugins");
|
||||
const lik_1 = require("lik");
|
||||
class Db {
|
||||
constructor(dbUrlArg) {
|
||||
this.collections = new lik_1.Objectmap();
|
||||
this.dbUrl = dbUrlArg;
|
||||
}
|
||||
// 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 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 collection by name: string
|
||||
*/
|
||||
getCollectionByName(nameArg) {
|
||||
let done = plugins.smartq.defer();
|
||||
let resultCollection = this.collections.find((dbCollectionArg) => {
|
||||
return dbCollectionArg.name === nameArg;
|
||||
});
|
||||
if (resultCollection !== null) {
|
||||
done.resolve(resultCollection);
|
||||
}
|
||||
return done.promise;
|
||||
}
|
||||
addCollection(dbCollectionArg) {
|
||||
this.collections.add(dbCollectionArg);
|
||||
}
|
||||
}
|
||||
exports.Db = Db;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLCtDQUE4QztBQUM5Qyw2QkFBK0I7QUFTL0I7SUFNRSxZQUFhLFFBQWdCO1FBRjdCLGdCQUFXLEdBQUcsSUFBSSxlQUFTLEVBQXFCLENBQUE7UUFHOUMsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUE7SUFDdkIsQ0FBQztJQUVELHdFQUF3RTtJQUV4RTs7T0FFRztJQUNILE9BQU87UUFDTCxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ2pDLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDdEQsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBQUMsQ0FBQztZQUM3QixPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUE7WUFDL0IsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUE7WUFDWixPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUE7WUFDbkUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDdkIsQ0FBQyxDQUFDLENBQUE7UUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNqQyxJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ2YsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsK0JBQStCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFBO1FBQ2pFLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQTtRQUNkLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3JCLENBQUM7SUFFRCw0RUFBNEU7SUFFNUU7O09BRUc7SUFDSCxtQkFBbUIsQ0FBSSxPQUFlO1FBQ3BDLElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFxQixDQUFBO1FBQ3BELElBQUksZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxlQUFlO1lBQzNELE1BQU0sQ0FBQyxlQUFlLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQTtRQUN6QyxDQUFDLENBQUMsQ0FBQTtRQUNGLEVBQUUsQ0FBQyxDQUFDLGdCQUFnQixLQUFLLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDOUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO1FBQ2hDLENBQUM7UUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUNyQixDQUFDO0lBRUQsYUFBYSxDQUFFLGVBQWtDO1FBQy9DLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFBO0lBQ3ZDLENBQUM7Q0FFRjtBQTFERCxnQkEwREMifQ==
|
42
dist/smartdata.classes.dbcollection.d.ts
vendored
42
dist/smartdata.classes.dbcollection.d.ts
vendored
@ -1,42 +0,0 @@
|
||||
import * as plugins from './smartdata.plugins';
|
||||
import { Db } from './smartdata.classes.db';
|
||||
import { DbDoc } from './smartdata.classes.dbDoc';
|
||||
export interface IFindOptions {
|
||||
limit?: number;
|
||||
}
|
||||
export interface IDocValidation<T> {
|
||||
(doc: T): boolean;
|
||||
}
|
||||
export declare function Collection(db: Db): (constructor: any) => void;
|
||||
export declare class DbCollection<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>;
|
||||
objectValidation: IDocValidation<T>;
|
||||
name: string;
|
||||
db: Db;
|
||||
constructor(collectedClassArg: T & DbDoc<T>, dbArg: Db);
|
||||
/**
|
||||
* adds a validation function that all newly inserted and updated objects have to pass
|
||||
*/
|
||||
addDocValidation(funcArg: IDocValidation<T>): void;
|
||||
/**
|
||||
* finds an object in the DbCollection
|
||||
*/
|
||||
find(docMatchArg: T | any, optionsArg?: IFindOptions): Promise<T[]>;
|
||||
/**
|
||||
* inserts object into the DbCollection
|
||||
*/
|
||||
insertOne(docArg: T): Promise<void>;
|
||||
/**
|
||||
* inserts many objects at once into the DbCollection
|
||||
*/
|
||||
insertMany(docArrayArg: T[]): Promise<void>;
|
||||
/**
|
||||
* checks a Doc for constraints
|
||||
*/
|
||||
private checkDoc(docArg);
|
||||
}
|
95
dist/smartdata.classes.dbcollection.js
vendored
95
dist/smartdata.classes.dbcollection.js
vendored
@ -1,95 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const plugins = require("./smartdata.plugins");
|
||||
function Collection(db) {
|
||||
return function (constructor) {
|
||||
constructor['dbCollection'] = new DbCollection(constructor.name, db);
|
||||
};
|
||||
}
|
||||
exports.Collection = Collection;
|
||||
class DbCollection {
|
||||
constructor(collectedClassArg, dbArg) {
|
||||
this.objectValidation = null;
|
||||
// tell the collection where it belongs
|
||||
this.collectedClass = collectedClassArg;
|
||||
this.name = 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);
|
||||
}
|
||||
/**
|
||||
* adds a validation function that all newly inserted and updated objects have to pass
|
||||
*/
|
||||
addDocValidation(funcArg) {
|
||||
this.objectValidation = funcArg;
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
});
|
||||
return done.promise;
|
||||
}
|
||||
/**
|
||||
* inserts object into the DbCollection
|
||||
*/
|
||||
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'));
|
||||
});
|
||||
return done.promise;
|
||||
}
|
||||
/**
|
||||
* inserts many objects at once 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(); });
|
||||
});
|
||||
return done.promise;
|
||||
}
|
||||
/**
|
||||
* checks a Doc for constraints
|
||||
*/
|
||||
checkDoc(docArg) {
|
||||
let done = plugins.smartq.defer();
|
||||
let validationResult = true;
|
||||
if (this.objectValidation) {
|
||||
validationResult = this.objectValidation(docArg);
|
||||
}
|
||||
if (validationResult) {
|
||||
done.resolve();
|
||||
}
|
||||
else {
|
||||
done.reject('validation of object did not pass');
|
||||
}
|
||||
return done.promise;
|
||||
}
|
||||
}
|
||||
exports.DbCollection = DbCollection;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGJjb2xsZWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRkYXRhLmNsYXNzZXMuZGJjb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsK0NBQThDO0FBWTlDLG9CQUE0QixFQUFNO0lBQ2hDLE1BQU0sQ0FBQyxVQUFVLFdBQVc7UUFDMUIsV0FBVyxDQUFFLGNBQWMsQ0FBRSxHQUFHLElBQUksWUFBWSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUE7SUFDeEUsQ0FBQyxDQUFBO0FBQ0gsQ0FBQztBQUpELGdDQUlDO0FBRUQ7SUFXRSxZQUFhLGlCQUErQixFQUFFLEtBQVM7UUFKdkQscUJBQWdCLEdBQXNCLElBQUksQ0FBQTtRQUt4Qyx1Q0FBdUM7UUFDdkMsSUFBSSxDQUFDLGNBQWMsR0FBRyxpQkFBaUIsQ0FBQTtRQUN2QyxJQUFJLENBQUMsSUFBSSxHQUFHLGlCQUFpQixDQUFDLElBQUksQ0FBQTtRQUNsQyxJQUFJLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQTtRQUVmLCtCQUErQjtRQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUVoRCx3RkFBd0Y7UUFDeEYsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDN0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsZ0JBQWdCLENBQUUsT0FBMEI7UUFDMUMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLE9BQU8sQ0FBQTtJQUNqQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLENBQUUsV0FBb0IsRUFBRSxVQUF5QjtRQUNuRCxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBTyxDQUFBO1FBQ3RDLElBQUksVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBQ2xELEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFDZixFQUFFLENBQUMsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFBQyxVQUFVLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtZQUFDLENBQUM7UUFDNUQsQ0FBQztRQUNELFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSTtZQUMzQixFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNSLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBQ2hCLE1BQU0sR0FBRyxDQUFBO1lBQ1gsQ0FBQztZQUNELElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDcEIsQ0FBQyxDQUFDLENBQUE7UUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLENBQUUsTUFBUztRQUNsQixJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBUSxDQUFBO1FBQ3ZDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUN4QjtZQUNFLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztpQkFDOUIsSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDbkMsQ0FBQyxFQUNEO1lBQ0UsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDLENBQUE7UUFDaEUsQ0FBQyxDQUFDLENBQUE7UUFDSixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxVQUFVLENBQUUsV0FBZ0I7UUFDMUIsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQVEsQ0FBQTtRQUN2QyxJQUFJLG9CQUFvQixHQUFvQixFQUFFLENBQUE7UUFDOUMsR0FBRyxDQUFDLENBQUMsSUFBSSxNQUFNLElBQUksV0FBVyxDQUFDLENBQUMsQ0FBQztZQUMvQixvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFBO1FBQ2xELENBQUM7UUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ3JDLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQztpQkFDcEMsSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDbkMsQ0FBQyxDQUFDLENBQUE7UUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSyxRQUFRLENBQUUsTUFBUztRQUN6QixJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBUSxDQUFBO1FBQ3ZDLElBQUksZ0JBQWdCLEdBQUcsSUFBSSxDQUFBO1FBQzNCLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7WUFDMUIsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ2xELENBQUM7UUFDRCxFQUFFLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7WUFDckIsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ2hCLENBQUM7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsbUNBQW1DLENBQUMsQ0FBQTtRQUNsRCxDQUFDO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDckIsQ0FBQztDQUNGO0FBbEdELG9DQWtHQyJ9
|
39
dist/smartdata.classes.dbdoc.d.ts
vendored
39
dist/smartdata.classes.dbdoc.d.ts
vendored
@ -1,39 +0,0 @@
|
||||
import { Objectmap } from 'lik';
|
||||
import { DbCollection } from './smartdata.classes.dbcollection';
|
||||
export declare type TDocCreation = 'db' | 'new' | 'mixed';
|
||||
/**
|
||||
* saveable - saveable decorator to be used on class properties
|
||||
*/
|
||||
export declare function svDb(): (target: DbDoc<any>, key: string) => void;
|
||||
export declare class DbDoc<T> {
|
||||
/**
|
||||
* the collection object an Doc belongs to
|
||||
*/
|
||||
collection: DbCollection<T>;
|
||||
/**
|
||||
* how the Doc in memory was created, may prove useful later.
|
||||
*/
|
||||
creationType: TDocCreation;
|
||||
/**
|
||||
* an array of saveable properties of a doc
|
||||
*/
|
||||
saveableProperties: string[];
|
||||
/**
|
||||
* name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* class constructor
|
||||
*/
|
||||
constructor(nameArg: string);
|
||||
/**
|
||||
* saves this instance but not any connected items
|
||||
* may lead to data inconsistencies, but is faster
|
||||
*/
|
||||
save(): void;
|
||||
/**
|
||||
* also store any referenced objects to DB
|
||||
* better for data consistency
|
||||
*/
|
||||
saveDeep(savedMapArg?: Objectmap<DbDoc<any>>): void;
|
||||
}
|
61
dist/smartdata.classes.dbdoc.js
vendored
61
dist/smartdata.classes.dbdoc.js
vendored
@ -1,61 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const lik_1 = require("lik");
|
||||
/**
|
||||
* saveable - saveable decorator to be used on class properties
|
||||
*/
|
||||
function svDb() {
|
||||
return (target, key) => {
|
||||
console.log('called sva');
|
||||
if (!target.saveableProperties) {
|
||||
target.saveableProperties = [];
|
||||
}
|
||||
target.saveableProperties.push(key);
|
||||
};
|
||||
}
|
||||
exports.svDb = svDb;
|
||||
class DbDoc {
|
||||
/**
|
||||
* class constructor
|
||||
*/
|
||||
constructor(nameArg) {
|
||||
this.collection = this.constructor['dbCollection'];
|
||||
this.name = nameArg;
|
||||
}
|
||||
/**
|
||||
* saves this instance but not any connected items
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* also store any referenced objects to DB
|
||||
* better for data consistency
|
||||
*/
|
||||
saveDeep(savedMapArg = null) {
|
||||
if (!savedMapArg) {
|
||||
savedMapArg = new lik_1.Objectmap();
|
||||
}
|
||||
savedMapArg.add(this);
|
||||
this.save();
|
||||
for (let propertyKey in this) {
|
||||
let property = this[propertyKey];
|
||||
if (property instanceof DbDoc && !savedMapArg.checkForObject(property)) {
|
||||
property.saveDeep(savedMapArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.DbDoc = DbDoc;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGJEb2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYkRvYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLDZCQUErQjtBQU8vQjs7R0FFRztBQUNIO0lBQ0UsTUFBTSxDQUFDLENBQUMsTUFBa0IsRUFBRSxHQUFXO1FBQ3JDLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDekIsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDO1lBQUMsTUFBTSxDQUFDLGtCQUFrQixHQUFHLEVBQUUsQ0FBQTtRQUFDLENBQUM7UUFDbEUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUNyQyxDQUFDLENBQUE7QUFDSCxDQUFDO0FBTkQsb0JBTUM7QUFFRDtJQXNCRTs7T0FFRztJQUNILFlBQVksT0FBZTtRQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUUsY0FBYyxDQUFFLENBQUE7UUFDcEQsSUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUE7SUFDckIsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQUk7UUFDRixJQUFJLGNBQWMsR0FBUSxFQUFFLENBQUEsQ0FBQywrQ0FBK0M7UUFDNUUsR0FBRyxDQUFDLENBQUMsSUFBSSxrQkFBa0IsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDO1lBQ3ZELGNBQWMsQ0FBRSxrQkFBa0IsQ0FBRSxHQUFHLElBQUksQ0FBRSxrQkFBa0IsQ0FBRSxDQUFBO1FBQ25FLENBQUM7UUFDRCxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztZQUMxQixLQUFLLElBQUk7Z0JBQ1AsSUFBSSxDQUFDLFVBQVUsQ0FBQSxDQUFDLHFDQUFxQztnQkFDckQsS0FBSyxDQUFBO1lBQ1AsS0FBSyxLQUFLO2dCQUNSLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxDQUFBO1FBQzdDLENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsUUFBUSxDQUFDLGNBQXFDLElBQUk7UUFDaEQsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1lBQ2pCLFdBQVcsR0FBRyxJQUFJLGVBQVMsRUFBYyxDQUFBO1FBQzNDLENBQUM7UUFDRCxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3JCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNYLEdBQUcsQ0FBQyxDQUFDLElBQUksV0FBVyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDN0IsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFFLFdBQVcsQ0FBRSxDQUFBO1lBQ2xDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsWUFBWSxLQUFLLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdkUsUUFBUSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQTtZQUNoQyxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7Q0FDRjtBQWpFRCxzQkFpRUMifQ==
|
7
dist/smartdata.plugins.d.ts
vendored
7
dist/smartdata.plugins.d.ts
vendored
@ -1,7 +0,0 @@
|
||||
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 smartq from 'smartq';
|
||||
export { assert, beautylog, lodash, mongodb, smartq };
|
14
dist/smartdata.plugins.js
vendored
14
dist/smartdata.plugins.js
vendored
@ -1,14 +0,0 @@
|
||||
"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 smartq = require("smartq");
|
||||
exports.smartq = smartq;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDBCQUF1QjtBQUN2QixpQ0FBZ0M7QUFPNUIsd0JBQU07QUFOVix1Q0FBc0M7QUFPbEMsOEJBQVM7QUFOYixpQ0FBZ0M7QUFPNUIsd0JBQU07QUFOVixtQ0FBa0M7QUFPOUIsMEJBQU87QUFOWCxpQ0FBZ0M7QUFPNUIsd0JBQU0ifQ==
|
@ -1,19 +0,0 @@
|
||||
# smartdata
|
||||
|
||||
smartdata is a ODM that adheres to TypeScript practices and uses classes to organize data.
|
||||
It uses MongoDB as persistent storage.
|
||||
|
||||
## Intention
|
||||
There are many ODMs out there, however when we searched for a ODM that uses TypeScript,
|
||||
acts smart while still embracing an easy 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.DbConnection
|
||||
Collection | smartdata.DbCollection
|
||||
Document | smartdata.DbDoc
|
||||
|
||||
[](https://push.rocks)
|
@ -5,8 +5,19 @@
|
||||
"dockerSock": false
|
||||
},
|
||||
"npmci": {
|
||||
"globalNpmTools": [
|
||||
"npmts"
|
||||
]
|
||||
"npmGlobalTools": [],
|
||||
"npmAccessLevel": "public",
|
||||
"npmRegistryUrl": "registry.npmjs.org"
|
||||
},
|
||||
"gitzone": {
|
||||
"projectType": "npm",
|
||||
"module": {
|
||||
"githost": "gitlab.com",
|
||||
"gitscope": "pushrocks",
|
||||
"gitrepo": "smartdata",
|
||||
"shortDescription": "do more with data",
|
||||
"npmPackagename": "@pushrocks/smartdata",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5405
package-lock.json
generated
Normal file
5405
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
60
package.json
60
package.json
@ -1,13 +1,14 @@
|
||||
{
|
||||
"name": "smartdata",
|
||||
"version": "1.0.22",
|
||||
"name": "@pushrocks/smartdata",
|
||||
"version": "3.1.29",
|
||||
"private": false,
|
||||
"description": "do more with data",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
"scripts": {
|
||||
"test": "(npm run prepareMongo && npmts)",
|
||||
"test": "(tstest test/)",
|
||||
"testLocal": "(npmdocker)",
|
||||
"prepareMongo": "(rm -rf ./test/data && mkdir ./test/data/)"
|
||||
"build": "(tsbuild --web)"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -20,20 +21,39 @@
|
||||
},
|
||||
"homepage": "https://gitlab.com/pushrocks/smartdata#README",
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.66",
|
||||
"@types/mongodb": "^2.2.6",
|
||||
"beautylog": "^6.1.10",
|
||||
"lik": "^1.0.32",
|
||||
"lodash": "^4.17.4",
|
||||
"mongodb": "^2.2.28",
|
||||
"runtime-type-checks": "0.0.4",
|
||||
"smartq": "^1.1.1",
|
||||
"typings-global": "^1.0.17"
|
||||
"@pushrocks/lik": "^4.0.13",
|
||||
"@pushrocks/smartlog": "^2.0.35",
|
||||
"@pushrocks/smartpromise": "^3.0.6",
|
||||
"@pushrocks/smartstring": "^3.0.18",
|
||||
"@pushrocks/smartunique": "^3.0.3",
|
||||
"@types/lodash": "^4.14.155",
|
||||
"@types/mongodb": "^3.5.20",
|
||||
"lodash": "^4.17.15",
|
||||
"mongodb": "^3.5.8",
|
||||
"runtime-type-checks": "0.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/shelljs": "^0.7.2",
|
||||
"shelljs": "^0.7.8",
|
||||
"smartstring": "^2.0.24",
|
||||
"tapbundle": "^1.0.14"
|
||||
}
|
||||
"@gitzone/tsbuild": "^2.1.24",
|
||||
"@gitzone/tstest": "^1.0.33",
|
||||
"@pushrocks/qenv": "^4.0.10",
|
||||
"@pushrocks/tapbundle": "^3.2.1",
|
||||
"@types/mongodb-memory-server": "^2.3.0",
|
||||
"@types/node": "^14.0.13",
|
||||
"@types/shortid": "0.0.29",
|
||||
"mongodb-memory-server": "^6.6.1",
|
||||
"tslint": "^6.1.2",
|
||||
"tslint-config-prettier": "^1.18.0"
|
||||
},
|
||||
"files": [
|
||||
"ts/**/*",
|
||||
"ts_web/**/*",
|
||||
"dist/**/*",
|
||||
"dist_*/**/*",
|
||||
"dist_ts/**/*",
|
||||
"dist_ts_web/**/*",
|
||||
"assets/**/*",
|
||||
"cli.js",
|
||||
"npmextra.json",
|
||||
"readme.md"
|
||||
]
|
||||
}
|
||||
|
147
readme.md
Normal file
147
readme.md
Normal file
@ -0,0 +1,147 @@
|
||||
# @pushrocks/smartdata
|
||||
do more with data
|
||||
|
||||
## Availabililty and Links
|
||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartdata)
|
||||
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartdata)
|
||||
* [github.com (source mirror)](https://github.com/pushrocks/smartdata)
|
||||
* [docs (typedoc)](https://pushrocks.gitlab.io/smartdata/)
|
||||
|
||||
## Status for master
|
||||
|
||||
Status Category | Status Badge
|
||||
-- | --
|
||||
GitLab Pipelines | [](https://lossless.cloud)
|
||||
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
||||
npm | [](https://lossless.cloud)
|
||||
Snyk | [](https://lossless.cloud)
|
||||
TypeScript Support | [](https://lossless.cloud)
|
||||
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||
Code Style | [](https://lossless.cloud)
|
||||
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
||||
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
||||
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
||||
Platform support | [](https://lossless.cloud) [](https://lossless.cloud)
|
||||
|
||||
## 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:
|
||||
|
||||
| MongoDb term | smartdata class |
|
||||
| ------------ | ----------------------------- |
|
||||
| Database | smartdata.SmartdataDb |
|
||||
| Collection | smartdata.SmartdataCollection |
|
||||
| Document | smartdata.SmartadataDoc |
|
||||
|
||||
### class Db
|
||||
|
||||
represents a Database. Naturally it has .connect() etc. methods on it.
|
||||
|
||||
```typescript
|
||||
import * as smartdata from 'smartdata';
|
||||
|
||||
const smartdataDb = new smartdata.SmartdataDb({
|
||||
mongoDbUrl: '//someurl',
|
||||
mongoDbName: 'myDatabase',
|
||||
mongoDbPass: 'mypassword'
|
||||
});
|
||||
|
||||
smartdataDb.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
|
||||
|
||||
```typescript
|
||||
// continues from the block before...
|
||||
|
||||
@smartdata.Collection(smartdataDb)
|
||||
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() {
|
||||
super(); // the super call is important ;) But you probably know that.
|
||||
}
|
||||
}
|
||||
|
||||
// start to instantiate instances of classes from scratch or database
|
||||
|
||||
const localObject = new MyObject({
|
||||
property1: 'hi',
|
||||
property2: 2
|
||||
});
|
||||
localObject.save(); // saves the object to the database
|
||||
|
||||
// start retrieving instances
|
||||
|
||||
MyObject.getInstance<MyObject>({
|
||||
property: 'hi'
|
||||
}); // outputs a new instance of MyObject with the values from db assigned
|
||||
```
|
||||
|
||||
### class DbDoc
|
||||
|
||||
represents a individual document in a collection
|
||||
and thereby is ideally suited to extend the class you want to actually store.
|
||||
|
||||
### CRUD operations
|
||||
|
||||
smartdata supports full CRUD operations
|
||||
|
||||
**Store** or **Update** instances of classes to MongoDB:
|
||||
DbDoc extends your class with the following methods:
|
||||
|
||||
- async `.save()` will save (or update) the object you call it on only. Any referenced non-savable objects will not get stored.
|
||||
- async `.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
|
||||
|
||||
**Get** a new class instance from MongoDB:
|
||||
DbDoc exposes a static method that allows you specify a filter to retrieve a cloned class of the one you used to that doc at some point later in time:
|
||||
|
||||
- static async `.getInstance({ /* filter props here */ })` gets you an instance that has the data of the first matched document as properties.
|
||||
- static async `getInstances({ /* filter props here */ })` get you an array instances (one instance for every matched document).
|
||||
|
||||
**Delete** instances from MongoDb:
|
||||
smartdata extends your class with a method to easily delete the doucment from DB:
|
||||
|
||||
- async `.delete()`will delete the document from 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. You don't need to install any additional types for smartdata.
|
||||
|
||||
|
||||
## Contribution
|
||||
|
||||
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
|
||||
|
||||
For further information read the linked docs at the top of this readme.
|
||||
|
||||
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
||||
|
||||
[](https://maintainedby.lossless.com)
|
194
test/test.ts
194
test/test.ts
@ -1,81 +1,143 @@
|
||||
import { tap, expect } from 'tapbundle'
|
||||
import * as smartq from 'smartq'
|
||||
import { tap, expect } from '@pushrocks/tapbundle';
|
||||
import { Qenv } from '@pushrocks/qenv';
|
||||
|
||||
const 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';
|
||||
import * as smartunique from '@pushrocks/smartunique';
|
||||
|
||||
let mongoChildProcess
|
||||
let testDb: smartdata.Db
|
||||
import * as mongoPlugin from 'mongodb-memory-server';
|
||||
|
||||
interface ITestObject1 {
|
||||
value1: string
|
||||
value2?: number
|
||||
value3?: string
|
||||
// =======================================
|
||||
// Connecting to the database server
|
||||
// =======================================
|
||||
|
||||
let testDb: smartdata.SmartdataDb;
|
||||
let smartdataOptions: smartdata.ISmartdataOptions;
|
||||
let mongod: mongoPlugin.MongoMemoryServer;
|
||||
|
||||
tap.test('should create a testinstance as database', async () => {
|
||||
mongod = new mongoPlugin.MongoMemoryServer();
|
||||
smartdataOptions = {
|
||||
mongoDbName: await mongod.getDbName(),
|
||||
mongoDbPass: '',
|
||||
mongoDbUrl: await mongod.getConnectionString()
|
||||
};
|
||||
console.log(smartdataOptions);
|
||||
testDb = new smartdata.SmartdataDb(smartdataOptions);
|
||||
});
|
||||
|
||||
tap.test('should establish a connection to the rethink Db cluster', async () => {
|
||||
await testDb.init();
|
||||
});
|
||||
|
||||
// =======================================
|
||||
// The actual tests
|
||||
// =======================================
|
||||
|
||||
// ------
|
||||
// Collections
|
||||
// ------
|
||||
|
||||
@smartdata.Collection(() => {
|
||||
return testDb;
|
||||
})
|
||||
class Car extends smartdata.SmartDataDbDoc<Car, Car> {
|
||||
@smartdata.unI()
|
||||
public index: string = smartunique.shortId();
|
||||
|
||||
@smartdata.svDb()
|
||||
public color: string;
|
||||
|
||||
@smartdata.svDb()
|
||||
public brand: string;
|
||||
|
||||
constructor(colorArg: string, brandArg: string) {
|
||||
super();
|
||||
this.color = colorArg;
|
||||
this.brand = brandArg;
|
||||
}
|
||||
}
|
||||
|
||||
let testDbCollection: smartdata.DbCollection<ITestObject1>
|
||||
tap.test('should save the car to the db', async () => {
|
||||
const myCar = new Car('red', 'Volvo');
|
||||
await myCar.save();
|
||||
|
||||
tap.test('should establish a connection to mongodb', async () => {
|
||||
testDb = new smartdata.Db('mongodb://localhost:27017/smartdata')
|
||||
await testDb.connect()
|
||||
const myCar2 = new Car('red', 'Volvo');
|
||||
await myCar2.save();
|
||||
|
||||
const myCar3 = new Car('red', 'Renault');
|
||||
await myCar3.save();
|
||||
});
|
||||
|
||||
tap.test('expect to get instance of Car', async () => {
|
||||
const myCars = await Car.getInstances<Car>({
|
||||
brand: 'Volvo'
|
||||
});
|
||||
expect(myCars[0].color).to.equal('red');
|
||||
});
|
||||
|
||||
tap.test('expect to get instance of Car and update it', async () => {
|
||||
const myCar = await Car.getInstance<Car>({
|
||||
brand: 'Volvo'
|
||||
});
|
||||
expect(myCar.color).to.equal('red');
|
||||
myCar.color = 'blue';
|
||||
await myCar.save();
|
||||
});
|
||||
|
||||
tap.test('should be able to delete an instance of car', async () => {
|
||||
const myCar = await Car.getInstance<Car>({
|
||||
brand: 'Volvo'
|
||||
});
|
||||
expect(myCar.color).to.equal('blue');
|
||||
await myCar.delete();
|
||||
|
||||
const myCar2 = await Car.getInstance<Car>({
|
||||
brand: 'Volvo'
|
||||
});
|
||||
expect(myCar2.color).to.equal('red');
|
||||
});
|
||||
|
||||
// tslint:disable-next-line: max-classes-per-file
|
||||
@smartdata.Collection(() => {
|
||||
return testDb;
|
||||
})
|
||||
class Truck extends smartdata.SmartDataDbDoc<Car, Car> {
|
||||
@smartdata.unI()
|
||||
public id: string = smartunique.shortId();
|
||||
|
||||
tap.test('should insert a doc into the collection', async () => {
|
||||
await testDbCollection.insertOne({ value1: 'test' })
|
||||
})
|
||||
@smartdata.svDb()
|
||||
public color: string;
|
||||
|
||||
tap.test('should find all docs of testDbCollection', async () => {
|
||||
await testDbCollection.find({}).then(async (resultArray) => {
|
||||
console.log(resultArray)
|
||||
expect(resultArray[ 0 ].value1).equal('test')
|
||||
})
|
||||
})
|
||||
@smartdata.svDb()
|
||||
public brand: string;
|
||||
|
||||
tap.test('should insert many docs into the collection', async () => {
|
||||
await testDbCollection.insertMany([
|
||||
{ value1: 'test2' },
|
||||
{ value1: 'test', value2: 3, value3: 'hi' }
|
||||
])
|
||||
})
|
||||
|
||||
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 close the db Connection', async () => {
|
||||
testDb.close()
|
||||
})
|
||||
|
||||
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('TestCar')
|
||||
this.color = optionsArg.color
|
||||
}
|
||||
constructor(colorArg: string, brandArg: string) {
|
||||
super();
|
||||
this.color = colorArg;
|
||||
this.brand = brandArg;
|
||||
}
|
||||
let testCarInstance = new TestCar({
|
||||
color: 'red',
|
||||
property2: 2
|
||||
})
|
||||
}
|
||||
|
||||
expect(testCarInstance.saveableProperties[ 0 ]).equal('color')
|
||||
console.log(TestCar)
|
||||
expect(testCarInstance.collection).be.instanceof(smartdata.DbCollection)
|
||||
expect(testCarInstance).be.instanceof(smartdata.DbDoc)
|
||||
testCarInstance.save()
|
||||
})
|
||||
tap.test('should store a new Truck', async () => {
|
||||
const truck = new Truck('blue', 'MAN');
|
||||
await truck.save();
|
||||
const myTruck = await Truck.getInstance<Truck>({ color: 'blue' });
|
||||
myTruck.id = 'foo';
|
||||
await myTruck.save();
|
||||
const myTruck2 = await Truck.getInstance<Truck>({ color: 'blue' });
|
||||
console.log(myTruck2);
|
||||
});
|
||||
|
||||
tap.test('should get a collection for testCar', async () => {
|
||||
//
|
||||
})
|
||||
// =======================================
|
||||
// close the database connection
|
||||
// =======================================
|
||||
tap.test('should close the database connection', async tools => {
|
||||
await testDb.close();
|
||||
await mongod.stop();
|
||||
});
|
||||
|
||||
tap.start()
|
||||
tap.start({ throwOnError: true });
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from './smartdata.plugins'
|
||||
export * from './smartdata.classes.db';
|
||||
export * from './smartdata.classes.collection';
|
||||
export * from './smartdata.classes.doc';
|
||||
|
||||
export * from './smartdata.classes.db'
|
||||
export * from './smartdata.classes.dbcollection'
|
||||
export * from './smartdata.classes.dbdoc'
|
||||
export { IMongoDescriptor } from './interfaces';
|
||||
|
1
ts/interfaces/index.ts
Normal file
1
ts/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './mongodescriptor';
|
5
ts/interfaces/mongodescriptor.ts
Normal file
5
ts/interfaces/mongodescriptor.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface IMongoDescriptor {
|
||||
mongoDbName: string;
|
||||
mongoDbUrl: string;
|
||||
mongoDbPass: string;
|
||||
}
|
163
ts/smartdata.classes.collection.ts
Normal file
163
ts/smartdata.classes.collection.ts
Normal file
@ -0,0 +1,163 @@
|
||||
import * as plugins from './smartdata.plugins';
|
||||
import { SmartdataDb } from './smartdata.classes.db';
|
||||
import { SmartDataDbDoc } from './smartdata.classes.doc';
|
||||
|
||||
export interface IFindOptions {
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export interface IDocValidationFunc<T> {
|
||||
(doc: T): boolean;
|
||||
}
|
||||
|
||||
export type TDelayedDbCreation = () => SmartdataDb;
|
||||
|
||||
/**
|
||||
* This is a decorator that will tell the decorated class what dbTable to use
|
||||
* @param dbArg
|
||||
*/
|
||||
export function Collection(dbArg: SmartdataDb | TDelayedDbCreation) {
|
||||
return function(constructor) {
|
||||
if (dbArg instanceof SmartdataDb) {
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
constructor['smartdataCollection'] = new SmartdataCollection(constructor, dbArg);
|
||||
} else {
|
||||
constructor['smartdataDelayedCollection'] = () => {
|
||||
return new SmartdataCollection(constructor, dbArg());
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class SmartdataCollection<T> {
|
||||
/**
|
||||
* the collection that is used
|
||||
*/
|
||||
public mongoDbCollection: plugins.mongodb.Collection;
|
||||
public objectValidation: IDocValidationFunc<T> = null;
|
||||
public collectionName: string;
|
||||
public smartdataDb: SmartdataDb;
|
||||
public uniqueIndexes: string[] = [];
|
||||
|
||||
constructor(collectedClassArg: T & SmartDataDbDoc<T, unknown>, smartDataDbArg: SmartdataDb) {
|
||||
// tell the collection where it belongs
|
||||
this.collectionName = collectedClassArg.name;
|
||||
this.smartdataDb = smartDataDbArg;
|
||||
|
||||
// tell the db class about it (important since Db uses different systems under the hood)
|
||||
this.smartdataDb.addTable(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* makes sure a collection exists within MongoDb that maps to the SmartdataCollection
|
||||
*/
|
||||
public async init() {
|
||||
if (!this.mongoDbCollection) {
|
||||
// connect this instance to a MongoDB collection
|
||||
const availableMongoDbCollections = await this.smartdataDb.mongoDb.collections();
|
||||
const wantedCollection = availableMongoDbCollections.find(collection => {
|
||||
return collection.collectionName === this.collectionName;
|
||||
});
|
||||
if (!wantedCollection) {
|
||||
await this.smartdataDb.mongoDb.createCollection(this.collectionName);
|
||||
}
|
||||
this.mongoDbCollection = await this.smartdataDb.mongoDb.collection(this.collectionName);
|
||||
// console.log(`Successfully initiated Collection ${this.collectionName}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mark unique index
|
||||
*/
|
||||
public markUniqueIndexes(keyArrayArg: string[] = []) {
|
||||
for (const key of keyArrayArg) {
|
||||
if (!this.uniqueIndexes.includes(key)) {
|
||||
this.mongoDbCollection.createIndex(key, {
|
||||
unique: true
|
||||
});
|
||||
// make sure we only call this once and not for every doc we create
|
||||
this.uniqueIndexes.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a validation function that all newly inserted and updated objects have to pass
|
||||
*/
|
||||
public addDocValidation(funcArg: IDocValidationFunc<T>) {
|
||||
this.objectValidation = funcArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* finds an object in the DbCollection
|
||||
*/
|
||||
public async find(filterObject: any): Promise<any> {
|
||||
await this.init();
|
||||
const result = await this.mongoDbCollection.find(filterObject).toArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* create an object in the database
|
||||
*/
|
||||
public async insert(dbDocArg: T & SmartDataDbDoc<T, unknown>): Promise<any> {
|
||||
await this.init();
|
||||
await this.checkDoc(dbDocArg);
|
||||
this.markUniqueIndexes(dbDocArg.uniqueIndexes);
|
||||
const saveableObject = await dbDocArg.createSavableObject();
|
||||
const result = await this.mongoDbCollection.insertOne(saveableObject);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* inserts object into the DbCollection
|
||||
*/
|
||||
public async update(dbDocArg: T & SmartDataDbDoc<T, unknown>): Promise<any> {
|
||||
await this.init();
|
||||
await this.checkDoc(dbDocArg);
|
||||
const identifiableObject = await dbDocArg.createIdentifiableObject();
|
||||
const saveableObject = await dbDocArg.createSavableObject();
|
||||
const updateableObject: any = {};
|
||||
for (const key of Object.keys(saveableObject)) {
|
||||
if (identifiableObject[key]) {
|
||||
continue;
|
||||
}
|
||||
updateableObject[key] = saveableObject[key];
|
||||
}
|
||||
this.mongoDbCollection.updateOne(
|
||||
identifiableObject,
|
||||
{ $set: updateableObject },
|
||||
{ upsert: true }
|
||||
);
|
||||
}
|
||||
|
||||
public async delete(dbDocArg: T & SmartDataDbDoc<T, unknown>): Promise<any> {
|
||||
await this.init();
|
||||
await this.checkDoc(dbDocArg);
|
||||
const identifiableObject = await dbDocArg.createIdentifiableObject();
|
||||
await this.mongoDbCollection.deleteOne(identifiableObject, {
|
||||
w: 1
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* checks a Doc for constraints
|
||||
* if this.objectValidation is not set it passes.
|
||||
*/
|
||||
private checkDoc(docArg: T): Promise<void> {
|
||||
const done = plugins.smartq.defer<void>();
|
||||
let validationResult = true;
|
||||
if (this.objectValidation) {
|
||||
validationResult = this.objectValidation(docArg);
|
||||
}
|
||||
if (validationResult) {
|
||||
done.resolve();
|
||||
} else {
|
||||
done.reject('validation of object did not pass');
|
||||
}
|
||||
return done.promise;
|
||||
}
|
||||
}
|
@ -1,21 +1,43 @@
|
||||
import * as plugins from './smartdata.plugins'
|
||||
import { Objectmap } from 'lik'
|
||||
import * as plugins from './smartdata.plugins';
|
||||
import { ObjectMap } from '@pushrocks/lik';
|
||||
|
||||
import { DbCollection } from './smartdata.classes.dbcollection'
|
||||
import { SmartdataCollection } from './smartdata.classes.collection';
|
||||
|
||||
import * as mongoHelpers from './smartdata.mongohelpers';
|
||||
import { logger } from './smartdata.logging';
|
||||
|
||||
/**
|
||||
* 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
|
||||
status: TConnectionStatus
|
||||
collections = new Objectmap<DbCollection<any>>()
|
||||
export interface ISmartdataOptions {
|
||||
/**
|
||||
* the URL to connect to
|
||||
*/
|
||||
mongoDbUrl: string;
|
||||
|
||||
constructor (dbUrlArg: string) {
|
||||
this.dbUrl = dbUrlArg
|
||||
/**
|
||||
* the db to use for the project
|
||||
*/
|
||||
mongoDbName: string;
|
||||
|
||||
/**
|
||||
* an optional password that will be replace <PASSWORD> in the connection string
|
||||
*/
|
||||
mongoDbPass?: string;
|
||||
}
|
||||
|
||||
export class SmartdataDb {
|
||||
smartdataOptions: ISmartdataOptions;
|
||||
mongoDbClient: plugins.mongodb.MongoClient;
|
||||
mongoDb: plugins.mongodb.Db;
|
||||
status: TConnectionStatus;
|
||||
smartdataCollectionMap = new ObjectMap<SmartdataCollection<any>>();
|
||||
|
||||
constructor(smartdataOptions: ISmartdataOptions) {
|
||||
this.smartdataOptions = smartdataOptions;
|
||||
this.status = 'initial';
|
||||
}
|
||||
|
||||
// basic connection stuff ----------------------------------------------
|
||||
@ -23,47 +45,48 @@ 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
|
||||
public async init(): Promise<any> {
|
||||
let finalConnectionUrl = this.smartdataOptions.mongoDbUrl;
|
||||
if (this.smartdataOptions.mongoDbPass) {
|
||||
finalConnectionUrl = mongoHelpers.addPassword(
|
||||
this.smartdataOptions.mongoDbUrl,
|
||||
this.smartdataOptions.mongoDbPass
|
||||
);
|
||||
}
|
||||
console.log(`connection Url: ${finalConnectionUrl}`);
|
||||
this.mongoDbClient = await plugins.mongodb.MongoClient.connect(finalConnectionUrl, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true
|
||||
});
|
||||
this.mongoDb = this.mongoDbClient.db(this.smartdataOptions.mongoDbName);
|
||||
this.status = 'connected';
|
||||
console.log(`Connected to database ${this.smartdataOptions.mongoDbName}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
public async close(): Promise<any> {
|
||||
await this.mongoDbClient.close();
|
||||
this.status = 'disconnected';
|
||||
logger.log('info', `disconnected from database ${this.smartdataOptions.mongoDbName}`);
|
||||
}
|
||||
|
||||
// advanced communication with the database --------------------------------
|
||||
// handle table to class distribution
|
||||
|
||||
public addTable(SmartdataCollectionArg: SmartdataCollection<any>) {
|
||||
this.smartdataCollectionMap.add(SmartdataCollectionArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a collection by name: string
|
||||
* Gets a collection's name and returns a SmartdataCollection instance
|
||||
* @param nameArg
|
||||
* @returns DbTable
|
||||
*/
|
||||
getCollectionByName<T>(nameArg: string): Promise<DbCollection<T>> {
|
||||
let done = plugins.smartq.defer<DbCollection<any>>()
|
||||
let resultCollection = this.collections.find((dbCollectionArg) => {
|
||||
return dbCollectionArg.name === nameArg
|
||||
})
|
||||
if (resultCollection !== null) {
|
||||
done.resolve(resultCollection)
|
||||
}
|
||||
return done.promise
|
||||
public async getSmartdataCollectionByName<T>(nameArg: string): Promise<SmartdataCollection<T>> {
|
||||
const resultCollection = this.smartdataCollectionMap.find(dbTableArg => {
|
||||
return dbTableArg.collectionName === nameArg;
|
||||
});
|
||||
return resultCollection;
|
||||
}
|
||||
|
||||
addCollection (dbCollectionArg: DbCollection<any>) {
|
||||
this.collections.add(dbCollectionArg)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,117 +0,0 @@
|
||||
import * as plugins from './smartdata.plugins'
|
||||
import { Db } from './smartdata.classes.db'
|
||||
import { DbDoc } from './smartdata.classes.dbDoc'
|
||||
|
||||
export interface IFindOptions {
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export interface IDocValidation<T> {
|
||||
(doc: T): boolean
|
||||
}
|
||||
|
||||
export function Collection (db: Db) {
|
||||
return function (constructor) {
|
||||
constructor[ 'dbCollection' ] = new DbCollection(constructor.name, db)
|
||||
}
|
||||
}
|
||||
|
||||
export class DbCollection<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>
|
||||
objectValidation: IDocValidation<T> = null
|
||||
name: string
|
||||
db: Db
|
||||
|
||||
constructor (collectedClassArg: T & DbDoc<T>, dbArg: Db) {
|
||||
// tell the collection where it belongs
|
||||
this.collectedClass = collectedClassArg
|
||||
this.name = 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)
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a validation function that all newly inserted and updated objects have to pass
|
||||
*/
|
||||
addDocValidation (funcArg: IDocValidation<T>) {
|
||||
this.objectValidation = funcArg
|
||||
}
|
||||
|
||||
/**
|
||||
* finds an object in the DbCollection
|
||||
*/
|
||||
find (docMatchArg: T | any, optionsArg?: IFindOptions): Promise<T[]> {
|
||||
let done = plugins.smartq.defer<T[]>()
|
||||
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)
|
||||
})
|
||||
return done.promise
|
||||
}
|
||||
|
||||
/**
|
||||
* inserts object into the DbCollection
|
||||
*/
|
||||
insertOne (docArg: T): Promise<void> {
|
||||
let done = plugins.smartq.defer<void>()
|
||||
this.checkDoc(docArg).then(
|
||||
() => {
|
||||
this.collection.insertOne(docArg)
|
||||
.then(() => { done.resolve() })
|
||||
},
|
||||
() => {
|
||||
done.reject(new Error('one the docs did not pass validation'))
|
||||
})
|
||||
return done.promise
|
||||
}
|
||||
|
||||
/**
|
||||
* inserts many objects at once into the DbCollection
|
||||
*/
|
||||
insertMany (docArrayArg: T[]): Promise<void> {
|
||||
let done = plugins.smartq.defer<void>()
|
||||
let checkDocPromiseArray: Promise<void>[] = []
|
||||
for (let docArg of docArrayArg) {
|
||||
checkDocPromiseArray.push(this.checkDoc(docArg))
|
||||
}
|
||||
Promise.all(checkDocPromiseArray).then(() => {
|
||||
this.collection.insertMany(docArrayArg)
|
||||
.then(() => { done.resolve() })
|
||||
})
|
||||
return done.promise
|
||||
}
|
||||
|
||||
/**
|
||||
* checks a Doc for constraints
|
||||
*/
|
||||
private checkDoc (docArg: T): Promise<void> {
|
||||
let done = plugins.smartq.defer<void>()
|
||||
let validationResult = true
|
||||
if (this.objectValidation) {
|
||||
validationResult = this.objectValidation(docArg)
|
||||
}
|
||||
if (validationResult) {
|
||||
done.resolve()
|
||||
} else {
|
||||
done.reject('validation of object did not pass')
|
||||
}
|
||||
return done.promise
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
import * as plugins from './smartdata.plugins'
|
||||
|
||||
import { Objectmap } from 'lik'
|
||||
|
||||
import { Db } from './smartdata.classes.db'
|
||||
import { DbCollection } from './smartdata.classes.dbcollection'
|
||||
|
||||
export type TDocCreation = 'db' | 'new' | 'mixed'
|
||||
|
||||
/**
|
||||
* saveable - saveable decorator to be used on class properties
|
||||
*/
|
||||
export function svDb() {
|
||||
return (target: DbDoc<any>, key: string) => {
|
||||
console.log('called sva')
|
||||
if (!target.saveableProperties) { target.saveableProperties = [] }
|
||||
target.saveableProperties.push(key)
|
||||
}
|
||||
}
|
||||
|
||||
export class DbDoc<T> {
|
||||
|
||||
/**
|
||||
* the collection object an Doc belongs to
|
||||
*/
|
||||
collection: DbCollection<T>
|
||||
|
||||
/**
|
||||
* how the Doc in memory was created, may prove useful later.
|
||||
*/
|
||||
creationType: TDocCreation
|
||||
|
||||
/**
|
||||
* an array of saveable properties of a doc
|
||||
*/
|
||||
saveableProperties: string[]
|
||||
|
||||
/**
|
||||
* name
|
||||
*/
|
||||
name: string
|
||||
|
||||
/**
|
||||
* class constructor
|
||||
*/
|
||||
constructor(nameArg: string) {
|
||||
this.collection = this.constructor[ 'dbCollection' ]
|
||||
this.name = nameArg
|
||||
}
|
||||
|
||||
/**
|
||||
* saves this instance but not any connected items
|
||||
* may lead to data inconsistencies, but is faster
|
||||
*/
|
||||
save() {
|
||||
let saveableObject: any = {} // 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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* also store any referenced objects to DB
|
||||
* better for data consistency
|
||||
*/
|
||||
saveDeep(savedMapArg: Objectmap<DbDoc<any>> = null) {
|
||||
if (!savedMapArg) {
|
||||
savedMapArg = new Objectmap<DbDoc<any>>()
|
||||
}
|
||||
savedMapArg.add(this)
|
||||
this.save()
|
||||
for (let propertyKey in this) {
|
||||
let property = this[ propertyKey ]
|
||||
if (property instanceof DbDoc && !savedMapArg.checkForObject(property)) {
|
||||
property.saveDeep(savedMapArg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
188
ts/smartdata.classes.doc.ts
Normal file
188
ts/smartdata.classes.doc.ts
Normal file
@ -0,0 +1,188 @@
|
||||
import * as plugins from './smartdata.plugins';
|
||||
|
||||
import { ObjectMap } from '@pushrocks/lik';
|
||||
|
||||
import { SmartdataDb } from './smartdata.classes.db';
|
||||
import { SmartdataCollection } from './smartdata.classes.collection';
|
||||
|
||||
export type TDocCreation = 'db' | 'new' | 'mixed';
|
||||
|
||||
/**
|
||||
* saveable - saveable decorator to be used on class properties
|
||||
*/
|
||||
export function svDb() {
|
||||
return (target: SmartDataDbDoc<unknown, unknown>, key: string) => {
|
||||
console.log(`called svDb() on ${key}`);
|
||||
if (!target.saveableProperties) {
|
||||
target.saveableProperties = [];
|
||||
}
|
||||
target.saveableProperties.push(key);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* unique index - decorator to mark a unique index
|
||||
*/
|
||||
export function unI() {
|
||||
return (target: SmartDataDbDoc<unknown, unknown>, key: string) => {
|
||||
console.log('called unI');
|
||||
|
||||
// mark the index as unique
|
||||
if (!target.uniqueIndexes) {
|
||||
target.uniqueIndexes = [];
|
||||
}
|
||||
target.uniqueIndexes.push(key);
|
||||
|
||||
// and also save it
|
||||
if (!target.saveableProperties) {
|
||||
target.saveableProperties = [];
|
||||
}
|
||||
target.saveableProperties.push(key);
|
||||
};
|
||||
}
|
||||
|
||||
export class SmartDataDbDoc<T, TImplements> {
|
||||
/**
|
||||
* the collection object an Doc belongs to
|
||||
*/
|
||||
public collection: SmartdataCollection<T>;
|
||||
|
||||
/**
|
||||
* how the Doc in memory was created, may prove useful later.
|
||||
*/
|
||||
public creationStatus: TDocCreation = 'new';
|
||||
|
||||
/**
|
||||
* unique indexes
|
||||
*/
|
||||
public uniqueIndexes: string[];
|
||||
|
||||
/**
|
||||
* an array of saveable properties of a doc
|
||||
*/
|
||||
public saveableProperties: string[];
|
||||
|
||||
/**
|
||||
* name
|
||||
*/
|
||||
public name: string;
|
||||
|
||||
/**
|
||||
* primary id in the database
|
||||
*/
|
||||
public dbDocUniqueId: string;
|
||||
|
||||
/**
|
||||
* class constructor
|
||||
*/
|
||||
constructor() {
|
||||
this.name = this.constructor['name'];
|
||||
if (this.constructor['smartdataCollection']) {
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
this.collection = this.constructor['smartdataCollection'];
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
} else if (typeof this.constructor['smartdataDelayedCollection'] === 'function') {
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
this.collection = this.constructor['smartdataDelayedCollection']();
|
||||
} else {
|
||||
console.error('Could not determine collection for DbDoc');
|
||||
}
|
||||
}
|
||||
|
||||
public static async getInstances<T>(filterArg): Promise<T[]> {
|
||||
const self: any = this; // fool typesystem
|
||||
let referenceMongoDBCollection: SmartdataCollection<T>;
|
||||
|
||||
if (self.smartdataCollection) {
|
||||
referenceMongoDBCollection = self.smartdataCollection;
|
||||
} else if (self.smartdataDelayedCollection) {
|
||||
referenceMongoDBCollection = self.smartdataDelayedCollection();
|
||||
}
|
||||
const foundDocs = await referenceMongoDBCollection.find(filterArg);
|
||||
const returnArray = [];
|
||||
for (const item of foundDocs) {
|
||||
const newInstance = new this();
|
||||
newInstance.creationStatus = 'db';
|
||||
for (const key of Object.keys(item)) {
|
||||
newInstance[key] = item[key];
|
||||
}
|
||||
returnArray.push(newInstance);
|
||||
}
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
public static async getInstance<T>(filterArg): Promise<T> {
|
||||
const result = await this.getInstances<T>(filterArg);
|
||||
if (result && result.length > 0) {
|
||||
return result[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* saves this instance but not any connected items
|
||||
* may lead to data inconsistencies, but is faster
|
||||
*/
|
||||
public async save() {
|
||||
// tslint:disable-next-line: no-this-assignment
|
||||
const self: any = this;
|
||||
switch (this.creationStatus) {
|
||||
case 'db':
|
||||
await this.collection.update(self);
|
||||
break;
|
||||
case 'new':
|
||||
const writeResult = await this.collection.insert(self);
|
||||
this.creationStatus = 'db';
|
||||
break;
|
||||
default:
|
||||
console.error('neither new nor in db?');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a document from the database
|
||||
*/
|
||||
public async delete() {
|
||||
const self: any = this;
|
||||
await this.collection.delete(self);
|
||||
}
|
||||
|
||||
/**
|
||||
* also store any referenced objects to DB
|
||||
* better for data consistency
|
||||
*/
|
||||
public saveDeep(savedMapArg: ObjectMap<SmartDataDbDoc<any, any>> = null) {
|
||||
if (!savedMapArg) {
|
||||
savedMapArg = new ObjectMap<SmartDataDbDoc<any, any>>();
|
||||
}
|
||||
savedMapArg.add(this);
|
||||
this.save();
|
||||
for (const propertyKey of Object.keys(this)) {
|
||||
const property: any = this[propertyKey];
|
||||
if (property instanceof SmartDataDbDoc && !savedMapArg.checkForObject(property)) {
|
||||
property.saveDeep(savedMapArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a saveable object so the instance can be persisted as json in the database
|
||||
*/
|
||||
public async createSavableObject(): Promise<TImplements> {
|
||||
const saveableObject: unknown = {}; // is not exposed to outside, so any is ok here
|
||||
for (const propertyNameString of this.saveableProperties) {
|
||||
saveableObject[propertyNameString] = this[propertyNameString];
|
||||
}
|
||||
return saveableObject as TImplements;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates an identifiable object for operations that require filtering
|
||||
*/
|
||||
public async createIdentifiableObject() {
|
||||
const identifiableObject: any = {}; // is not exposed to outside, so any is ok here
|
||||
for (const propertyNameString of this.uniqueIndexes) {
|
||||
identifiableObject[propertyNameString] = this[propertyNameString];
|
||||
}
|
||||
return identifiableObject;
|
||||
}
|
||||
}
|
3
ts/smartdata.logging.ts
Normal file
3
ts/smartdata.logging.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import * as plugins from './smartdata.plugins';
|
||||
|
||||
export const logger = new plugins.smartlog.ConsoleLog();
|
7
ts/smartdata.mongohelpers.ts
Normal file
7
ts/smartdata.mongohelpers.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export const addUsername = (mongoUrlArg: string, usernameArg: string): string => {
|
||||
return mongoUrlArg.replace('<USERNAME>', usernameArg);
|
||||
};
|
||||
|
||||
export const addPassword = (mongoUrlArg: string, passwordArg: string): string => {
|
||||
return mongoUrlArg.replace('<PASSWORD>', passwordArg);
|
||||
};
|
@ -1,14 +1,9 @@
|
||||
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 smartq from 'smartq'
|
||||
import * as assert from 'assert';
|
||||
import * as smartlog from '@pushrocks/smartlog';
|
||||
import * as lodash from 'lodash';
|
||||
import * as mongodb from 'mongodb';
|
||||
import * as smartq from '@pushrocks/smartpromise';
|
||||
import * as smartstring from '@pushrocks/smartstring';
|
||||
import * as smartunique from '@pushrocks/smartunique';
|
||||
|
||||
export {
|
||||
assert,
|
||||
beautylog,
|
||||
lodash,
|
||||
mongodb,
|
||||
smartq
|
||||
}
|
||||
export { assert, smartlog, lodash, smartq, mongodb, smartstring, smartunique };
|
||||
|
@ -1,8 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"lib": [
|
||||
"es2015"
|
||||
]
|
||||
}
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"target": "es2017",
|
||||
"module": "commonjs"
|
||||
}
|
||||
}
|
18
tslint.json
18
tslint.json
@ -1,3 +1,17 @@
|
||||
{
|
||||
"extends": "tslint-config-standard"
|
||||
}
|
||||
"extends": ["tslint:latest", "tslint-config-prettier"],
|
||||
"rules": {
|
||||
"semicolon": [true, "always"],
|
||||
"no-console": false,
|
||||
"ordered-imports": false,
|
||||
"object-literal-sort-keys": false,
|
||||
"member-ordering": {
|
||||
"options":{
|
||||
"order": [
|
||||
"static-method"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultSeverity": "warning"
|
||||
}
|
||||
|
569
yarn.lock
569
yarn.lock
@ -1,569 +0,0 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/bson@*":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/bson/-/bson-1.0.3.tgz#6c26f0876bf9d8cbb06edd4019e29354bf3a03e0"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/chai-as-promised@0.0.29":
|
||||
version "0.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-0.0.29.tgz#43d52892aa998e185a3de3e2477edb8573be1d77"
|
||||
dependencies:
|
||||
"@types/chai" "*"
|
||||
"@types/promises-a-plus" "*"
|
||||
|
||||
"@types/chai-string@^1.1.30":
|
||||
version "1.1.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/chai-string/-/chai-string-1.1.30.tgz#4d8744b31a5a2295fc01c981ed1e2d4c8a070f0a"
|
||||
dependencies:
|
||||
"@types/chai" "*"
|
||||
|
||||
"@types/chai@*", "@types/chai@^3.4.35":
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.5.2.tgz#c11cd2817d3a401b7ba0f5a420f35c56139b1c1e"
|
||||
|
||||
"@types/lodash@^4.14.55", "@types/lodash@^4.14.62", "@types/lodash@^4.14.66":
|
||||
version "4.14.66"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.66.tgz#3dbb83477becf130611f8fac82a8fdb199805981"
|
||||
|
||||
"@types/minimatch@2.x.x":
|
||||
version "2.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a"
|
||||
|
||||
"@types/mongodb@^2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-2.2.6.tgz#cd7cb4c439219af1dfba5860d302eeaf2b0a13e4"
|
||||
dependencies:
|
||||
"@types/bson" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*", "@types/node@^7.0.29":
|
||||
version "7.0.31"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.31.tgz#80ea4d175599b2a00149c29a10a4eb2dff592e86"
|
||||
|
||||
"@types/promises-a-plus@*":
|
||||
version "0.0.27"
|
||||
resolved "https://registry.yarnpkg.com/@types/promises-a-plus/-/promises-a-plus-0.0.27.tgz#c64651134614c84b8f5d7114ce8901d36a609780"
|
||||
|
||||
"@types/q@1.x.x":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.0.1.tgz#dbccb01bd8f0f801a12a4604c7d7af59bb02ae2f"
|
||||
|
||||
"@types/shelljs@^0.6.0":
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.6.0.tgz#090b705c102ce7fc5c0c5ea9b524418ff15840df"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/shelljs@^0.7.2":
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.7.2.tgz#c2bdb3fe80cd7a3da08750ca898ae44c589671f3"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/which@^1.0.28":
|
||||
version "1.0.28"
|
||||
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
|
||||
|
||||
ansi-256-colors@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-256-colors/-/ansi-256-colors-1.1.0.tgz#910de50efcc7c09e3d82f2f87abd6b700c18818a"
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
|
||||
ansi-styles@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
||||
|
||||
assertion-error@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
|
||||
beautycolor@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/beautycolor/-/beautycolor-1.0.7.tgz#a4715738ac4c8221371e9cbeb5a6cc6d11ecbf7c"
|
||||
dependencies:
|
||||
ansi-256-colors "^1.1.0"
|
||||
typings-global "^1.0.14"
|
||||
|
||||
beautylog@^6.1.10:
|
||||
version "6.1.10"
|
||||
resolved "https://registry.yarnpkg.com/beautylog/-/beautylog-6.1.10.tgz#9c27e566937684cb689f9372d98cfa5415d50b72"
|
||||
dependencies:
|
||||
"@types/lodash" "^4.14.55"
|
||||
beautycolor "^1.0.7"
|
||||
figlet "^1.2.0"
|
||||
lodash "^4.17.4"
|
||||
ora "^1.1.0"
|
||||
smartenv "^2.0.0"
|
||||
smartq "^1.1.1"
|
||||
typings-global "^1.0.14"
|
||||
|
||||
bindings@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
bson@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.4.tgz#93c10d39eaa5b58415cbc4052f3e53e562b0b72c"
|
||||
|
||||
buffer-shims@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
|
||||
|
||||
chai-as-promised@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-6.0.0.tgz#1a02a433a6f24dafac63b9c96fa1684db1aa8da6"
|
||||
dependencies:
|
||||
check-error "^1.0.2"
|
||||
|
||||
chai-string@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/chai-string/-/chai-string-1.4.0.tgz#359140c051d36a4e4b1a5fc6b910152f438a8d49"
|
||||
|
||||
chai@^3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
|
||||
dependencies:
|
||||
assertion-error "^1.0.1"
|
||||
deep-eql "^0.1.3"
|
||||
type-detect "^1.0.0"
|
||||
|
||||
chalk@^1.0.0, chalk@^1.1.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
||||
dependencies:
|
||||
ansi-styles "^2.2.1"
|
||||
escape-string-regexp "^1.0.2"
|
||||
has-ansi "^2.0.0"
|
||||
strip-ansi "^3.0.0"
|
||||
supports-color "^2.0.0"
|
||||
|
||||
check-error@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
|
||||
|
||||
cli-cursor@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
|
||||
dependencies:
|
||||
restore-cursor "^2.0.0"
|
||||
|
||||
cli-spinners@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.0.0.tgz#ef987ed3d48391ac3dab9180b406a742180d6e6a"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
|
||||
deep-eql@^0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
|
||||
dependencies:
|
||||
type-detect "0.1.1"
|
||||
|
||||
early@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/early/-/early-2.1.1.tgz#841e23254ea5dc54d8afaeee82f5ab65c00ee23c"
|
||||
dependencies:
|
||||
beautycolor "^1.0.7"
|
||||
smartq "^1.1.1"
|
||||
typings-global "^1.0.16"
|
||||
|
||||
es6-error@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.0.2.tgz#eec5c726eacef51b7f6b73c20db6e1b13b069c98"
|
||||
|
||||
es6-promise@3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4"
|
||||
|
||||
escape-string-regexp@^1.0.2:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
|
||||
figlet@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.2.0.tgz#6c46537378fab649146b5a6143dda019b430b410"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
|
||||
glob@^7.0.0:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
has-ansi@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
|
||||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@~2.0.1:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
|
||||
interpret@^1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
|
||||
js-base64@^2.1.9:
|
||||
version "2.1.9"
|
||||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce"
|
||||
|
||||
leakage@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/leakage/-/leakage-0.3.0.tgz#15d698abdc76bbc6439601f4f3020e77e2d50c39"
|
||||
dependencies:
|
||||
es6-error "^4.0.2"
|
||||
left-pad "^1.1.3"
|
||||
memwatch-next "^0.3.0"
|
||||
minimist "^1.2.0"
|
||||
pretty-bytes "^4.0.2"
|
||||
|
||||
left-pad@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.1.3.tgz#612f61c033f3a9e08e939f1caebeea41b6f3199a"
|
||||
|
||||
lik@^1.0.32:
|
||||
version "1.0.32"
|
||||
resolved "https://registry.yarnpkg.com/lik/-/lik-1.0.32.tgz#41ee6c8edd483eaa11bd089775263955f5555060"
|
||||
dependencies:
|
||||
"@types/lodash" "^4.14.62"
|
||||
"@types/minimatch" "2.x.x"
|
||||
"@types/q" "1.x.x"
|
||||
lodash "^4.17.4"
|
||||
minimatch "^3.0.3"
|
||||
q "^1.5.0"
|
||||
rxjs "^5.3.0"
|
||||
smartq "^1.1.1"
|
||||
tapbundle "^1.0.14"
|
||||
typings-global "^1.0.14"
|
||||
|
||||
lodash@^4.17.4:
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
||||
|
||||
log-symbols@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
|
||||
dependencies:
|
||||
chalk "^1.0.0"
|
||||
|
||||
memwatch-next@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/memwatch-next/-/memwatch-next-0.3.0.tgz#2111050f9a906e0aa2d72a4ec0f0089c78726f8f"
|
||||
dependencies:
|
||||
bindings "^1.2.1"
|
||||
nan "^2.3.2"
|
||||
|
||||
mimic-fn@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
|
||||
|
||||
minimatch@^3.0.3, minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
|
||||
mongodb-core@2.1.12:
|
||||
version "2.1.12"
|
||||
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.12.tgz#1531192511bc16ef160ac6ae0cc46776ffd8451d"
|
||||
dependencies:
|
||||
bson "~1.0.4"
|
||||
require_optional "~1.0.0"
|
||||
|
||||
mongodb@^2.2.28:
|
||||
version "2.2.28"
|
||||
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.28.tgz#d8ff45754366e03973fa259bf4f11447858da657"
|
||||
dependencies:
|
||||
es6-promise "3.2.1"
|
||||
mongodb-core "2.1.12"
|
||||
readable-stream "2.2.7"
|
||||
|
||||
nan@^2.3.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
onetime@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
|
||||
dependencies:
|
||||
mimic-fn "^1.0.0"
|
||||
|
||||
ora@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ora/-/ora-1.3.0.tgz#80078dd2b92a934af66a3ad72a5b910694ede51a"
|
||||
dependencies:
|
||||
chalk "^1.1.1"
|
||||
cli-cursor "^2.1.0"
|
||||
cli-spinners "^1.0.0"
|
||||
log-symbols "^1.0.2"
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
|
||||
path-parse@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
|
||||
|
||||
pretty-bytes@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
|
||||
|
||||
process-nextick-args@~1.0.6:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
|
||||
|
||||
q@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1"
|
||||
|
||||
readable-stream@2.2.7:
|
||||
version "2.2.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1"
|
||||
dependencies:
|
||||
buffer-shims "~1.0.0"
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.1"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~1.0.6"
|
||||
string_decoder "~1.0.0"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
rechoir@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||
dependencies:
|
||||
resolve "^1.1.6"
|
||||
|
||||
reflect-metadata@^0.1.2:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.10.tgz#b4f83704416acad89988c9b15635d47e03b9344a"
|
||||
|
||||
require_optional@~1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e"
|
||||
dependencies:
|
||||
resolve-from "^2.0.0"
|
||||
semver "^5.1.0"
|
||||
|
||||
resolve-from@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
|
||||
|
||||
resolve@^1.1.6:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
restore-cursor@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
|
||||
dependencies:
|
||||
onetime "^2.0.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
runtime-type-checks@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/runtime-type-checks/-/runtime-type-checks-0.0.4.tgz#5682baf2ffe53f955fe3e065b40a0a09943845c8"
|
||||
dependencies:
|
||||
reflect-metadata "^0.1.2"
|
||||
|
||||
rxjs@^5.3.0:
|
||||
version "5.4.1"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.4.1.tgz#b62f757f279445d265a18a58fb0a70dc90e91626"
|
||||
dependencies:
|
||||
symbol-observable "^1.0.1"
|
||||
|
||||
safe-buffer@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
|
||||
|
||||
semver@^5.1.0, semver@^5.3.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
|
||||
|
||||
shelljs@^0.7.6, shelljs@^0.7.8:
|
||||
version "0.7.8"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
|
||||
dependencies:
|
||||
glob "^7.0.0"
|
||||
interpret "^1.0.0"
|
||||
rechoir "^0.6.2"
|
||||
|
||||
signal-exit@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
|
||||
smartchai@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/smartchai/-/smartchai-1.0.3.tgz#de6d010bb8b5aef24cb70b31a5f5334e8c41b72f"
|
||||
dependencies:
|
||||
"@types/chai" "^3.4.35"
|
||||
"@types/chai-as-promised" "0.0.29"
|
||||
"@types/chai-string" "^1.1.30"
|
||||
chai "^3.5.0"
|
||||
chai-as-promised "^6.0.0"
|
||||
chai-string "^1.3.0"
|
||||
|
||||
smartdelay@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/smartdelay/-/smartdelay-1.0.3.tgz#5fd44dad77262d110702f0293efa80c072cfb579"
|
||||
dependencies:
|
||||
smartq "^1.1.1"
|
||||
typings-global "^1.0.16"
|
||||
|
||||
smartenv@^2.0.0:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/smartenv/-/smartenv-2.0.6.tgz#b38c679b0c151b9af548f68c3a072c29d1417e8d"
|
||||
dependencies:
|
||||
lodash "^4.17.4"
|
||||
smartq "^1.1.1"
|
||||
typings-global "^1.0.14"
|
||||
|
||||
smartq@^1.1.0, smartq@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/smartq/-/smartq-1.1.1.tgz#efb358705260d41ae18aef7ffd815f7b6fe17dd3"
|
||||
dependencies:
|
||||
typed-promisify "^0.3.0"
|
||||
typings-global "^1.0.14"
|
||||
|
||||
smartshell@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/smartshell/-/smartshell-1.0.6.tgz#27b1c79029784abe72ac7e91fe698b7ebecc6629"
|
||||
dependencies:
|
||||
"@types/shelljs" "^0.6.0"
|
||||
"@types/which" "^1.0.28"
|
||||
shelljs "^0.7.6"
|
||||
smartq "^1.1.0"
|
||||
which "^1.2.12"
|
||||
|
||||
smartstring@^2.0.24:
|
||||
version "2.0.24"
|
||||
resolved "https://registry.yarnpkg.com/smartstring/-/smartstring-2.0.24.tgz#dc1c5efb738c10a2d7daeea3d800ad2ecc65a26c"
|
||||
dependencies:
|
||||
js-base64 "^2.1.9"
|
||||
typings-global "^1.0.14"
|
||||
|
||||
string_decoder@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.2.tgz#b29e1f4e1125fa97a10382b8a533737b7491e179"
|
||||
dependencies:
|
||||
safe-buffer "~5.0.1"
|
||||
|
||||
strip-ansi@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
||||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
supports-color@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
||||
|
||||
symbol-observable@^1.0.1:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
|
||||
|
||||
tapbundle@^1.0.14:
|
||||
version "1.0.14"
|
||||
resolved "https://registry.yarnpkg.com/tapbundle/-/tapbundle-1.0.14.tgz#75827e335fcb02216f0267a26a26d702ddc02e3c"
|
||||
dependencies:
|
||||
early "^2.1.1"
|
||||
leakage "^0.3.0"
|
||||
smartchai "^1.0.3"
|
||||
smartdelay "^1.0.3"
|
||||
smartq "^1.1.1"
|
||||
typings-global "^1.0.16"
|
||||
|
||||
type-detect@0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
|
||||
|
||||
type-detect@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
|
||||
|
||||
typed-promisify@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/typed-promisify/-/typed-promisify-0.3.0.tgz#1ba0af5e444c87d8047406f18ce49092a1191853"
|
||||
|
||||
typings-global@^1.0.14, typings-global@^1.0.16, typings-global@^1.0.17:
|
||||
version "1.0.17"
|
||||
resolved "https://registry.yarnpkg.com/typings-global/-/typings-global-1.0.17.tgz#41edc331ccec3168289adc8849e1e255efbe7152"
|
||||
dependencies:
|
||||
"@types/node" "^7.0.29"
|
||||
semver "^5.3.0"
|
||||
smartshell "^1.0.6"
|
||||
|
||||
util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
|
||||
which@^1.2.12:
|
||||
version "1.2.14"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
Reference in New Issue
Block a user