Compare commits

..

6 Commits

Author SHA1 Message Date
e433b9e212 3.1.17 2019-09-02 16:51:22 +02:00
bf3656f792 fix(core): update 2019-09-02 16:51:22 +02:00
7e9fc62ce7 3.1.16 2019-09-02 16:50:23 +02:00
670a0c63fb fix(core): update 2019-09-02 16:50:22 +02:00
64e76b3ed1 3.1.15 2019-09-02 16:42:30 +02:00
25803330de fix(core): update 2019-09-02 16:42:29 +02:00
10 changed files with 1020 additions and 615 deletions

24
.gitignore vendored
View File

@ -1,4 +1,22 @@
node_modules/
public/
coverage/
.nogit/
# artifacts
coverage/
public/
pages/
# installs
node_modules/
# caches
.yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_web/
dist_serve/
dist_ts_web/
# custom

View File

@ -1,5 +1,5 @@
# gitzone standard
image: hosttoday/ht-docker-node:npmci
# gitzone ci_default
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache:
paths:
@ -34,48 +34,11 @@ snyk:
- docker
- notpriv
sast:
stage: security
image: registry.gitlab.com/hosttoday/ht-docker-dbase:npmci
variables:
DOCKER_DRIVER: overlay2
allow_failure: true
services:
- docker:stable-dind
script:
- npmci npm prepare
- npmci npm install
- npmci command npm run build
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run
--env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}"
--volume "$PWD:/code"
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
artifacts:
reports:
sast: gl-sast-report.json
tags:
- docker
- priv
# ====================
# test stage
# ====================
testLTS:
stage: test
script:
- npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
testSTABLE:
testStable:
stage: test
script:
- npmci npm prepare
@ -85,12 +48,24 @@ testSTABLE:
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- priv
testBuild:
stage: test
script:
- npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
release:
stage: release
script:
- npmci node install stable
- npmci node install lts
- npmci npm publish
only:
- tags
@ -103,19 +78,11 @@ release:
# ====================
codequality:
stage: metadata
image: docker:stable
allow_failure: true
services:
- docker:stable-dind
script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
- npmci command npm install -g tslint typescript
- npmci npm install
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
tags:
- docker
- priv
@ -131,13 +98,15 @@ trigger:
- notpriv
pages:
image: hosttoday/ht-docker-node:npmci
image: hosttoday/ht-docker-dbase:npmci
services:
- docker:stable-dind
stage: metadata
script:
- npmci command npm install -g typedoc typescript
- npmci command npm install -g @gitzone/tsdoc
- npmci npm prepare
- npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/
- npmci command tsdoc
tags:
- docker
- notpriv

View File

@ -14,7 +14,7 @@ do more with data
[![Known Vulnerabilities](https://snyk.io/test/npm/@pushrocks/smartdata/badge.svg)](https://snyk.io/test/npm/@pushrocks/smartdata)
[![TypeScript](https://img.shields.io/badge/TypeScript->=%203.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-prettier-ff69b4.svg)](https://prettier.io/)
## Usage
@ -118,6 +118,6 @@ So you don't need to install any additional types when importing smartdata.
For further information read the linked docs at the top of this readme.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
[![repo-footer](https://pushrocks.gitlab.io/assets/repo-footer.svg)](https://maintainedby.lossless.com)
[![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com)

1315
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "@pushrocks/smartdata",
"version": "3.1.14",
"version": "3.1.17",
"private": false,
"description": "do more with data",
"main": "dist/index.js",
@ -21,26 +21,38 @@
},
"homepage": "https://gitlab.com/pushrocks/smartdata#README",
"dependencies": {
"@pushrocks/lik": "^3.0.4",
"@pushrocks/smartlog": "^2.0.9",
"@pushrocks/smartpromise": "^2.0.5",
"@pushrocks/smartstring": "^3.0.5",
"@types/lodash": "^4.14.119",
"@types/mongodb": "^3.1.18",
"lodash": "^4.17.11",
"mongodb": "^3.1.10",
"@pushrocks/lik": "^3.0.11",
"@pushrocks/smartlog": "^2.0.19",
"@pushrocks/smartpromise": "^3.0.2",
"@pushrocks/smartstring": "^3.0.10",
"@pushrocks/smartunique": "^3.0.1",
"@types/lodash": "^4.14.138",
"@types/mongodb": "^3.3.1",
"lodash": "^4.17.15",
"mongodb": "^3.3.2",
"runtime-type-checks": "0.0.4"
},
"devDependencies": {
"@gitzone/tsbuild": "^2.1.4",
"@gitzone/tstest": "^1.0.18",
"@pushrocks/qenv": "^3.0.2",
"@pushrocks/tapbundle": "^3.0.7",
"@types/node": "^10.12.18",
"@gitzone/tsbuild": "^2.1.17",
"@gitzone/tstest": "^1.0.24",
"@pushrocks/qenv": "^4.0.4",
"@pushrocks/tapbundle": "^3.0.13",
"@types/mongodb-memory-server": "^1.8.0",
"@types/node": "^12.7.3",
"@types/shortid": "0.0.29",
"mongodb-memory-server": "^2.9.1",
"shortid": "^2.2.14",
"tslint": "^5.12.0",
"tslint-config-prettier": "^1.17.0"
}
"mongodb-memory-server": "^5.2.0",
"tslint": "^5.19.0",
"tslint-config-prettier": "^1.18.0"
},
"files": [
"ts/*",
"ts_web/*",
"dist/*",
"dist_web/*",
"dist_ts_web/*",
"assets/*",
"cli.js",
"npmextra.json",
"readme.md"
]
}

View File

@ -1,22 +1,40 @@
import { tap, expect } from '@pushrocks/tapbundle';
import * as smartpromise from '@pushrocks/smartpromise';
import { Qenv } from '@pushrocks/qenv';
let testQenv = new Qenv(process.cwd(), process.cwd() + '/.nogit/');
const testQenv = new Qenv(process.cwd(), process.cwd() + '/.nogit/');
// the tested module
import * as smartdata from '../ts/index';
import { smartstring } from '../ts/smartdata.plugins';
import * as shortid from 'shortid';
import * as smartunique from '@pushrocks/smartunique';
import * as mongoPlugin from 'mongodb-memory-server';
// =======================================
// Connecting to the database server
// =======================================
let testDb = new smartdata.SmartdataDb({
mongoDbName: process.env.MONGO_DBNAME,
mongoDbUrl: process.env.MONGO_URL,
mongoDbPass: process.env.MONGO_PASS
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.skip.test('should create a smartdb', async () => {
testDb = new smartdata.SmartdataDb({
mongoDbName: testQenv.getEnvVarOnDemand('MONGO_DBNAME'),
mongoDbUrl: testQenv.getEnvVarOnDemand('MONGO_URL'),
mongoDbPass: testQenv.getEnvVarOnDemand('MONGO_PASS')
});
});
tap.test('should establish a connection to the rethink Db cluster', async () => {
@ -31,11 +49,19 @@ tap.test('should establish a connection to the rethink Db cluster', async () =>
// Collections
// ------
@smartdata.Collection(testDb)
@smartdata.Collection(() => {
return testDb;
})
class Car extends smartdata.SmartDataDbDoc<Car> {
@smartdata.unI() index: string = shortid();
@smartdata.svDb() color: string;
@smartdata.svDb() brand: string;
@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;
@ -46,20 +72,37 @@ class Car extends smartdata.SmartDataDbDoc<Car> {
tap.test('should save the car to the db', async () => {
const myCar = new Car('red', 'Volvo');
await myCar.save();
const myCar2 = new Car('red', 'Renault');
await myCar2.save();
});
tap.test('expect to get instance of Car', async () => {
let myCars = await Car.getInstances<Car>({
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 update an instance of car', async () => {});
tap.test('should be able to delete an instance of car', async () => {});
// =======================================
// close the database connection
// =======================================
tap.test('should close the database connection', async tools => {
await testDb.close();
await mongod.stop();
});
tap.start({ throwOnError: true });

View File

@ -36,11 +36,11 @@ export class SmartdataCollection<T> {
/**
* the collection that is used
*/
mongoDbCollection: plugins.mongodb.Collection;
objectValidation: IDocValidationFunc<T> = null;
collectionName: string;
smartdataDb: SmartdataDb;
uniqueIndexes: string[] = [];
public mongoDbCollection: plugins.mongodb.Collection;
public objectValidation: IDocValidationFunc<T> = null;
public collectionName: string;
public smartdataDb: SmartdataDb;
public uniqueIndexes: string[] = [];
constructor(collectedClassArg: T & SmartDataDbDoc<T>, smartDataDbArg: SmartdataDb) {
// tell the collection where it belongs
@ -54,7 +54,7 @@ export class SmartdataCollection<T> {
/**
* makes sure a collection exists within MongoDb that maps to the SmartdataCollection
*/
async init() {
public async init() {
if (!this.mongoDbCollection) {
// connect this instance to a MongoDB collection
const availableMongoDbCollections = await this.smartdataDb.mongoDb.collections();
@ -65,15 +65,15 @@ export class SmartdataCollection<T> {
await this.smartdataDb.mongoDb.createCollection(this.collectionName);
}
this.mongoDbCollection = await this.smartdataDb.mongoDb.collection(this.collectionName);
console.log(`Successfully initiated Collection ${this.collectionName}`);
// console.log(`Successfully initiated Collection ${this.collectionName}`);
}
}
/**
* mark unique index
*/
markUniqueIndexes(keyArrayArg: string[] = []) {
for (let key of keyArrayArg) {
public markUniqueIndexes(keyArrayArg: string[] = []) {
for (const key of keyArrayArg) {
if (!this.uniqueIndexes.includes(key)) {
this.mongoDbCollection.createIndex(key, {
unique: true
@ -87,14 +87,14 @@ export class SmartdataCollection<T> {
/**
* adds a validation function that all newly inserted and updated objects have to pass
*/
addDocValidation(funcArg: IDocValidationFunc<T>) {
public addDocValidation(funcArg: IDocValidationFunc<T>) {
this.objectValidation = funcArg;
}
/**
* finds an object in the DbCollection
*/
async find(filterObject: any): Promise<any> {
public async find(filterObject: any): Promise<any> {
await this.init();
const result = await this.mongoDbCollection.find(filterObject).toArray();
return result;
@ -103,7 +103,7 @@ export class SmartdataCollection<T> {
/**
* create an object in the database
*/
async insert(dbDocArg: T & SmartDataDbDoc<T>): Promise<any> {
public async insert(dbDocArg: T & SmartDataDbDoc<T>): Promise<any> {
await this.init();
await this.checkDoc(dbDocArg);
this.markUniqueIndexes(dbDocArg.uniqueIndexes);
@ -120,7 +120,21 @@ export class SmartdataCollection<T> {
await this.checkDoc(dbDocArg);
const identifiableObject = await dbDocArg.createIdentifiableObject();
const saveableObject = await dbDocArg.createSavableObject();
this.mongoDbCollection.updateOne(identifiableObject, saveableObject);
console.log(identifiableObject);
console.log(saveableObject);
const updateableObject: any = {};
for (const key of Object.keys(saveableObject)) {
if (identifiableObject[key]) {
continue;
}
updateableObject[key] = saveableObject[key];
}
console.log(updateableObject);
this.mongoDbCollection.updateOne(
identifiableObject,
{ $set: updateableObject },
{ upsert: true }
);
}
public async delete(dbDocArg: T & SmartDataDbDoc<T>): Promise<any> {

View File

@ -44,7 +44,7 @@ export class SmartdataDb {
/**
* connects to the database that was specified during instance creation
*/
async init(): Promise<any> {
public async init(): Promise<any> {
let finalConnectionUrl = this.smartdataOptions.mongoDbUrl;
if (this.smartdataOptions.mongoDbPass) {
finalConnectionUrl = mongoHelpers.addPassword(
@ -52,7 +52,7 @@ export class SmartdataDb {
this.smartdataOptions.mongoDbPass
);
}
console.log(finalConnectionUrl);
console.log(`connection Url: ${finalConnectionUrl}`);
this.mongoDbClient = await plugins.mongodb.MongoClient.connect(finalConnectionUrl, {
useNewUrlParser: true
});
@ -64,7 +64,7 @@ export class SmartdataDb {
/**
* closes the connection to the databse
*/
async close(): Promise<any> {
public async close(): Promise<any> {
await this.mongoDbClient.close();
this.status = 'disconnected';
plugins.smartlog.defaultLogger.log(
@ -75,7 +75,7 @@ export class SmartdataDb {
// handle table to class distribution
addTable(SmartdataCollectionArg: SmartdataCollection<any>) {
public addTable(SmartdataCollectionArg: SmartdataCollection<any>) {
this.smartdataCollectionMap.add(SmartdataCollectionArg);
}
@ -84,8 +84,8 @@ export class SmartdataDb {
* @param nameArg
* @returns DbTable
*/
async getSmartdataCollectionByName<T>(nameArg: string): Promise<SmartdataCollection<T>> {
let resultCollection = this.smartdataCollectionMap.find(dbTableArg => {
public async getSmartdataCollectionByName<T>(nameArg: string): Promise<SmartdataCollection<T>> {
const resultCollection = this.smartdataCollectionMap.find(dbTableArg => {
return dbTableArg.collectionName === nameArg;
});
return resultCollection;

View File

@ -45,32 +45,32 @@ export class SmartDataDbDoc<T> {
/**
* the collection object an Doc belongs to
*/
collection: SmartdataCollection<T>;
public collection: SmartdataCollection<T>;
/**
* how the Doc in memory was created, may prove useful later.
*/
creationStatus: TDocCreation = 'new';
public creationStatus: TDocCreation = 'new';
/**
* unique indexes
*/
uniqueIndexes: string[];
public uniqueIndexes: string[];
/**
* an array of saveable properties of a doc
*/
saveableProperties: string[];
public saveableProperties: string[];
/**
* name
*/
name: string;
public name: string;
/**
* primary id in the database
*/
dbDocUniqueId: string;
public dbDocUniqueId: string;
/**
* class constructor
@ -89,8 +89,8 @@ export class SmartDataDbDoc<T> {
}
}
static async getInstances<T>(filterArg): Promise<T[]> {
let self: any = this; // fool typesystem
public static async getInstances<T>(filterArg): Promise<T[]> {
const self: any = this; // fool typesystem
let referenceMongoDBCollection: SmartdataCollection<T>;
if (self.smartdataCollection) {
@ -100,9 +100,10 @@ export class SmartDataDbDoc<T> {
}
const foundDocs = await referenceMongoDBCollection.find(filterArg);
const returnArray = [];
for (let item of foundDocs) {
let newInstance = new this();
for (let key in item) {
for (const item of foundDocs) {
const newInstance = new this();
newInstance.creationStatus = 'db';
for (const key in item) {
if (key !== 'id') {
newInstance[key] = item[key];
}
@ -113,7 +114,7 @@ export class SmartDataDbDoc<T> {
}
static async getInstance<T>(filterArg): Promise<T> {
let result = await this.getInstances<T>(filterArg);
const result = await this.getInstances<T>(filterArg);
if (result && result.length > 0) {
return result[0];
}
@ -123,15 +124,15 @@ export class SmartDataDbDoc<T> {
* saves this instance but not any connected items
* may lead to data inconsistencies, but is faster
*/
async save() {
public async save() {
// tslint:disable-next-line: no-this-assignment
let self: any = this;
const self: any = this;
switch (this.creationStatus) {
case 'db':
await this.collection.update(self);
break;
case 'new':
let writeResult = await this.collection.insert(self);
const writeResult = await this.collection.insert(self);
this.creationStatus = 'db';
break;
default:
@ -142,20 +143,20 @@ export class SmartDataDbDoc<T> {
/**
* deletes a document from the database
*/
async delete() {}
public async delete() {}
/**
* also store any referenced objects to DB
* better for data consistency
*/
saveDeep(savedMapArg: Objectmap<SmartDataDbDoc<any>> = null) {
public saveDeep(savedMapArg: Objectmap<SmartDataDbDoc<any>> = null) {
if (!savedMapArg) {
savedMapArg = new Objectmap<SmartDataDbDoc<any>>();
}
savedMapArg.add(this);
this.save();
for (let propertyKey in this) {
let property: any = this[propertyKey];
for (const propertyKey of Object.keys(this)) {
const property: any = this[propertyKey];
if (property instanceof SmartDataDbDoc && !savedMapArg.checkForObject(property)) {
property.saveDeep(savedMapArg);
}

View File

@ -4,5 +4,6 @@ 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, smartlog, lodash, smartq, mongodb, smartstring };
export { assert, smartlog, lodash, smartq, mongodb, smartstring, smartunique };