Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
c17789e92e | |||
0bf2ba554d | |||
5cbf1a222a | |||
f075530838 | |||
efb83853fb | |||
73300ca4d3 | |||
1e946cdceb | |||
608ff93a41 | |||
6211953f14 | |||
99e520b776 | |||
eda8297356 | |||
ffa52a5883 | |||
1e83f0a0ef | |||
0203eabdfd | |||
72894e3ef1 | |||
bbe5f8c6a8 | |||
02af9f5c4b | |||
17de480272 | |||
776fd3ee4e | |||
3272bb7235 | |||
116dfbc3b0 | |||
3f714b1a33 | |||
e58fa57525 | |||
8e7ad5210f | |||
cea6c662ac | |||
6eb43a4b9f | |||
7f89cbeecd | |||
a042a589a0 | |||
75b5f6af08 | |||
e6a36f22ac | |||
246e3486f0 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -15,8 +15,6 @@ node_modules/
|
||||
|
||||
# builds
|
||||
dist/
|
||||
dist_web/
|
||||
dist_serve/
|
||||
dist_ts_web/
|
||||
dist_*/
|
||||
|
||||
# custom
|
102
.gitlab-ci.yml
102
.gitlab-ci.yml
@ -3,14 +3,14 @@ image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
|
||||
cache:
|
||||
paths:
|
||||
- .npmci_cache/
|
||||
key: "$CI_BUILD_STAGE"
|
||||
- .npmci_cache/
|
||||
key: '$CI_BUILD_STAGE'
|
||||
|
||||
stages:
|
||||
- security
|
||||
- test
|
||||
- release
|
||||
- metadata
|
||||
- security
|
||||
- test
|
||||
- release
|
||||
- metadata
|
||||
|
||||
# ====================
|
||||
# security stage
|
||||
@ -18,21 +18,36 @@ stages:
|
||||
mirror:
|
||||
stage: security
|
||||
script:
|
||||
- npmci git mirror
|
||||
- npmci git mirror
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
snyk:
|
||||
auditProductionDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci command npm install -g snyk
|
||||
- npmci command npm install --ignore-scripts
|
||||
- npmci command snyk test
|
||||
- npmci command npm install --production --ignore-scripts
|
||||
- npmci command npm config set registry https://registry.npmjs.org
|
||||
- npmci command npm audit --audit-level=high --only=prod --production
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- docker
|
||||
|
||||
auditDevDependencies:
|
||||
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 --only=dev
|
||||
tags:
|
||||
- docker
|
||||
allow_failure: true
|
||||
|
||||
# ====================
|
||||
# test stage
|
||||
@ -41,37 +56,36 @@ snyk:
|
||||
testStable:
|
||||
stage: test
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci npm test
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci npm test
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- docker
|
||||
- priv
|
||||
- docker
|
||||
|
||||
testBuild:
|
||||
stage: test
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci node install lts
|
||||
- npmci npm install
|
||||
- npmci command npm run build
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci command npm run build
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- docker
|
||||
|
||||
release:
|
||||
stage: release
|
||||
script:
|
||||
- npmci node install lts
|
||||
- npmci npm publish
|
||||
- npmci node install stable
|
||||
- npmci npm publish
|
||||
only:
|
||||
- tags
|
||||
- tags
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
# ====================
|
||||
# metadata stage
|
||||
@ -79,35 +93,39 @@ release:
|
||||
codequality:
|
||||
stage: metadata
|
||||
allow_failure: true
|
||||
only:
|
||||
- tags
|
||||
script:
|
||||
- npmci command npm install -g tslint typescript
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
|
||||
tags:
|
||||
- docker
|
||||
- priv
|
||||
- lossless
|
||||
- docker
|
||||
- priv
|
||||
|
||||
trigger:
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci trigger
|
||||
- npmci trigger
|
||||
only:
|
||||
- tags
|
||||
- tags
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
pages:
|
||||
image: hosttoday/ht-docker-dbase:npmci
|
||||
services:
|
||||
- docker:stable-dind
|
||||
stage: metadata
|
||||
script:
|
||||
- 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:
|
||||
@ -115,5 +133,5 @@ pages:
|
||||
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", "wcc"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
"npmRegistryUrl": "registry.npmjs.org"
|
||||
},
|
||||
"gitzone": {
|
||||
"projectType": "npm",
|
||||
"module": {
|
||||
"githost": "gitlab.com",
|
||||
"gitscope": "pushrocks",
|
||||
|
11179
package-lock.json
generated
11179
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
58
package.json
58
package.json
@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "@pushrocks/smartdata",
|
||||
"version": "3.1.21",
|
||||
"version": "3.1.36",
|
||||
"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": "(tstest test/)",
|
||||
"testLocal": "(npmdocker)",
|
||||
"build": "(tsbuild)"
|
||||
"build": "(tsbuild --web)"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -21,38 +21,42 @@
|
||||
},
|
||||
"homepage": "https://gitlab.com/pushrocks/smartdata#README",
|
||||
"dependencies": {
|
||||
"@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",
|
||||
"@pushrocks/lik": "^4.0.17",
|
||||
"@pushrocks/smartlog": "^2.0.36",
|
||||
"@pushrocks/smartpromise": "^3.0.6",
|
||||
"@pushrocks/smartstring": "^3.0.18",
|
||||
"@pushrocks/smartunique": "^3.0.3",
|
||||
"@types/lodash": "^4.14.159",
|
||||
"@types/mongodb": "^3.5.26",
|
||||
"lodash": "^4.17.20",
|
||||
"mongodb": "^3.6.0",
|
||||
"runtime-type-checks": "0.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@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",
|
||||
"@gitzone/tsbuild": "^2.1.25",
|
||||
"@gitzone/tstest": "^1.0.44",
|
||||
"@pushrocks/qenv": "^4.0.10",
|
||||
"@pushrocks/tapbundle": "^3.2.9",
|
||||
"@types/mongodb-memory-server": "^2.3.0",
|
||||
"@types/node": "^14.6.0",
|
||||
"@types/shortid": "0.0.29",
|
||||
"mongodb-memory-server": "^5.2.0",
|
||||
"tslint": "^5.19.0",
|
||||
"mongodb-memory-server": "6.6.3",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-config-prettier": "^1.18.0"
|
||||
},
|
||||
"files": [
|
||||
"ts/*",
|
||||
"ts_web/*",
|
||||
"dist/*",
|
||||
"dist_web/*",
|
||||
"dist_ts_web/*",
|
||||
"assets/*",
|
||||
"ts/**/*",
|
||||
"ts_web/**/*",
|
||||
"dist/**/*",
|
||||
"dist_*/**/*",
|
||||
"dist_ts/**/*",
|
||||
"dist_ts_web/**/*",
|
||||
"assets/**/*",
|
||||
"cli.js",
|
||||
"npmextra.json",
|
||||
"readme.md"
|
||||
],
|
||||
"browserslist": [
|
||||
"last 1 chrome versions"
|
||||
]
|
||||
}
|
||||
|
@ -8,13 +8,20 @@ do more with data
|
||||
* [docs (typedoc)](https://pushrocks.gitlab.io/smartdata/)
|
||||
|
||||
## Status for master
|
||||
[](https://gitlab.com/pushrocks/smartdata/commits/master)
|
||||
[](https://gitlab.com/pushrocks/smartdata/commits/master)
|
||||
[](https://www.npmjs.com/package/@pushrocks/smartdata)
|
||||
[](https://snyk.io/test/npm/@pushrocks/smartdata)
|
||||
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||
[](https://prettier.io/)
|
||||
|
||||
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
|
||||
|
||||
@ -47,7 +54,7 @@ import * as smartdata from 'smartdata';
|
||||
const smartdataDb = new smartdata.SmartdataDb({
|
||||
mongoDbUrl: '//someurl',
|
||||
mongoDbName: 'myDatabase',
|
||||
mongoDbPass: 'mypassword'
|
||||
mongoDbPass: 'mypassword',
|
||||
});
|
||||
|
||||
smartdataDb.connect();
|
||||
@ -80,14 +87,14 @@ class MyObject extends smartdata.DbDoc<MyObject> {
|
||||
|
||||
const localObject = new MyObject({
|
||||
property1: 'hi',
|
||||
property2: 2
|
||||
property2: 2,
|
||||
});
|
||||
localObject.save(); // saves the object to the database
|
||||
|
||||
// start retrieving instances
|
||||
|
||||
MyObject.getInstance<MyObject>({
|
||||
property: 'hi'
|
||||
property: 'hi',
|
||||
}); // outputs a new instance of MyObject with the values from db assigned
|
||||
```
|
||||
|
||||
@ -97,6 +104,7 @@ 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:
|
||||
@ -111,16 +119,13 @@ DbDoc extends your class with the following methods:
|
||||
**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).
|
||||
- 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.
|
||||
|
||||
|
||||
|
||||
- async `.delete()`will delete the document from DB.
|
||||
|
||||
## TypeScript
|
||||
|
||||
@ -129,6 +134,10 @@ Since you define your classes in TypeScript and types flow through smartdata in
|
||||
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)
|
43
test/test.ts
43
test/test.ts
@ -15,29 +15,23 @@ import * as mongoPlugin from 'mongodb-memory-server';
|
||||
// =======================================
|
||||
|
||||
let testDb: smartdata.SmartdataDb;
|
||||
let smartdataOptions: smartdata.ISmartdataOptions;
|
||||
let smartdataOptions: smartdata.IMongoDescriptor;
|
||||
let mongod: mongoPlugin.MongoMemoryServer;
|
||||
|
||||
tap.test('should create a testinstance as database', async () => {
|
||||
mongod = new mongoPlugin.MongoMemoryServer();
|
||||
mongod = new mongoPlugin.MongoMemoryServer({
|
||||
autoStart: true,
|
||||
});
|
||||
smartdataOptions = {
|
||||
mongoDbName: await mongod.getDbName(),
|
||||
mongoDbPass: '',
|
||||
mongoDbUrl: await mongod.getConnectionString()
|
||||
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 () => {
|
||||
tap.test('should establish a connection to mongod', async () => {
|
||||
await testDb.init();
|
||||
});
|
||||
|
||||
@ -52,7 +46,7 @@ tap.test('should establish a connection to the rethink Db cluster', async () =>
|
||||
@smartdata.Collection(() => {
|
||||
return testDb;
|
||||
})
|
||||
class Car extends smartdata.SmartDataDbDoc<Car> {
|
||||
class Car extends smartdata.SmartDataDbDoc<Car, Car> {
|
||||
@smartdata.unI()
|
||||
public index: string = smartunique.shortId();
|
||||
|
||||
@ -82,14 +76,14 @@ tap.test('should save the car to the db', async () => {
|
||||
|
||||
tap.test('expect to get instance of Car', async () => {
|
||||
const myCars = await Car.getInstances<Car>({
|
||||
brand: 'Volvo'
|
||||
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'
|
||||
brand: 'Volvo',
|
||||
});
|
||||
expect(myCar.color).to.equal('red');
|
||||
myCar.color = 'blue';
|
||||
@ -98,24 +92,22 @@ tap.test('expect to get instance of Car and update it', async () => {
|
||||
|
||||
tap.test('should be able to delete an instance of car', async () => {
|
||||
const myCar = await Car.getInstance<Car>({
|
||||
brand: 'Volvo'
|
||||
brand: 'Volvo',
|
||||
});
|
||||
expect(myCar.color).to.equal('blue');
|
||||
await myCar.delete();
|
||||
|
||||
const myCar2 = await Car.getInstance<Car>({
|
||||
brand: 'Volvo'
|
||||
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> {
|
||||
class Truck extends smartdata.SmartDataDbDoc<Car, Car> {
|
||||
@smartdata.unI()
|
||||
public id: string = smartunique.shortId();
|
||||
|
||||
@ -135,16 +127,17 @@ class Truck extends smartdata.SmartDataDbDoc<Car> {
|
||||
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'});
|
||||
console.log(myTruck);
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
// =======================================
|
||||
// close the database connection
|
||||
// =======================================
|
||||
tap.test('should close the database connection', async tools => {
|
||||
tap.test('should close the database connection', async (tools) => {
|
||||
await testDb.close();
|
||||
await mongod.stop();
|
||||
});
|
||||
|
@ -1,5 +1,22 @@
|
||||
export interface IMongoDescriptor {
|
||||
mongoDbName: string;
|
||||
/**
|
||||
* the URL to connect to
|
||||
*/
|
||||
mongoDbUrl: string;
|
||||
mongoDbPass: string;
|
||||
|
||||
/**
|
||||
* the db to use for the project
|
||||
*/
|
||||
mongoDbName?: string;
|
||||
|
||||
/**
|
||||
* a username to use to connect to the database
|
||||
*/
|
||||
|
||||
mongoDbUser?: string;
|
||||
|
||||
/**
|
||||
* an optional password that will be replace <PASSWORD> in the connection string
|
||||
*/
|
||||
mongoDbPass?: string;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ export type TDelayedDbCreation = () => SmartdataDb;
|
||||
* @param dbArg
|
||||
*/
|
||||
export function Collection(dbArg: SmartdataDb | TDelayedDbCreation) {
|
||||
return function(constructor) {
|
||||
return function (constructor) {
|
||||
if (dbArg instanceof SmartdataDb) {
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
constructor['smartdataCollection'] = new SmartdataCollection(constructor, dbArg);
|
||||
@ -42,7 +42,7 @@ export class SmartdataCollection<T> {
|
||||
public smartdataDb: SmartdataDb;
|
||||
public uniqueIndexes: string[] = [];
|
||||
|
||||
constructor(collectedClassArg: T & SmartDataDbDoc<T>, smartDataDbArg: SmartdataDb) {
|
||||
constructor(collectedClassArg: T & SmartDataDbDoc<T, unknown>, smartDataDbArg: SmartdataDb) {
|
||||
// tell the collection where it belongs
|
||||
this.collectionName = collectedClassArg.name;
|
||||
this.smartdataDb = smartDataDbArg;
|
||||
@ -58,7 +58,7 @@ export class SmartdataCollection<T> {
|
||||
if (!this.mongoDbCollection) {
|
||||
// connect this instance to a MongoDB collection
|
||||
const availableMongoDbCollections = await this.smartdataDb.mongoDb.collections();
|
||||
const wantedCollection = availableMongoDbCollections.find(collection => {
|
||||
const wantedCollection = availableMongoDbCollections.find((collection) => {
|
||||
return collection.collectionName === this.collectionName;
|
||||
});
|
||||
if (!wantedCollection) {
|
||||
@ -76,7 +76,7 @@ export class SmartdataCollection<T> {
|
||||
for (const key of keyArrayArg) {
|
||||
if (!this.uniqueIndexes.includes(key)) {
|
||||
this.mongoDbCollection.createIndex(key, {
|
||||
unique: true
|
||||
unique: true,
|
||||
});
|
||||
// make sure we only call this once and not for every doc we create
|
||||
this.uniqueIndexes.push(key);
|
||||
@ -103,7 +103,7 @@ export class SmartdataCollection<T> {
|
||||
/**
|
||||
* create an object in the database
|
||||
*/
|
||||
public async insert(dbDocArg: T & SmartDataDbDoc<T>): Promise<any> {
|
||||
public async insert(dbDocArg: T & SmartDataDbDoc<T, unknown>): Promise<any> {
|
||||
await this.init();
|
||||
await this.checkDoc(dbDocArg);
|
||||
this.markUniqueIndexes(dbDocArg.uniqueIndexes);
|
||||
@ -115,13 +115,11 @@ export class SmartdataCollection<T> {
|
||||
/**
|
||||
* inserts object into the DbCollection
|
||||
*/
|
||||
public async update(dbDocArg: T & SmartDataDbDoc<T>): Promise<any> {
|
||||
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();
|
||||
console.log(identifiableObject);
|
||||
console.log(saveableObject);
|
||||
const updateableObject: any = {};
|
||||
for (const key of Object.keys(saveableObject)) {
|
||||
if (identifiableObject[key]) {
|
||||
@ -129,7 +127,6 @@ export class SmartdataCollection<T> {
|
||||
}
|
||||
updateableObject[key] = saveableObject[key];
|
||||
}
|
||||
console.log(updateableObject);
|
||||
this.mongoDbCollection.updateOne(
|
||||
identifiableObject,
|
||||
{ $set: updateableObject },
|
||||
@ -137,11 +134,13 @@ export class SmartdataCollection<T> {
|
||||
);
|
||||
}
|
||||
|
||||
public async delete(dbDocArg: T & SmartDataDbDoc<T>): Promise<any> {
|
||||
public async delete(dbDocArg: T & SmartDataDbDoc<T, unknown>): Promise<any> {
|
||||
await this.init();
|
||||
await this.checkDoc(dbDocArg);
|
||||
const identifiableObject = await dbDocArg.createIdentifiableObject();
|
||||
this.mongoDbCollection.deleteOne(identifiableObject);
|
||||
await this.mongoDbCollection.deleteOne(identifiableObject, {
|
||||
w: 1,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,40 +1,24 @@
|
||||
import * as plugins from './smartdata.plugins';
|
||||
import { Objectmap } from '@pushrocks/lik';
|
||||
import { ObjectMap } from '@pushrocks/lik';
|
||||
|
||||
import { SmartdataCollection } from './smartdata.classes.collection';
|
||||
|
||||
import * as mongoHelpers from './smartdata.mongohelpers';
|
||||
import { logger } from './smartdata.logging';
|
||||
import { IMongoDescriptor } from './interfaces';
|
||||
|
||||
/**
|
||||
* interface - indicates the connection status of the db
|
||||
*/
|
||||
export type TConnectionStatus = 'initial' | 'disconnected' | 'connected' | 'failed';
|
||||
|
||||
export interface ISmartdataOptions {
|
||||
/**
|
||||
* the URL to connect to
|
||||
*/
|
||||
mongoDbUrl: string;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
smartdataOptions: IMongoDescriptor;
|
||||
mongoDbClient: plugins.mongodb.MongoClient;
|
||||
mongoDb: plugins.mongodb.Db;
|
||||
status: TConnectionStatus;
|
||||
smartdataCollectionMap = new Objectmap<SmartdataCollection<any>>();
|
||||
smartdataCollectionMap = new ObjectMap<SmartdataCollection<any>>();
|
||||
|
||||
constructor(smartdataOptions: ISmartdataOptions) {
|
||||
constructor(smartdataOptions: IMongoDescriptor) {
|
||||
this.smartdataOptions = smartdataOptions;
|
||||
this.status = 'initial';
|
||||
}
|
||||
@ -45,16 +29,17 @@ export class SmartdataDb {
|
||||
* connects to the database that was specified during instance creation
|
||||
*/
|
||||
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}`);
|
||||
const finalConnectionUrl = this.smartdataOptions.mongoDbUrl
|
||||
.replace('<USERNAME>', this.smartdataOptions.mongoDbUser)
|
||||
.replace('<username>', this.smartdataOptions.mongoDbUser)
|
||||
.replace('<PASSWORD>', this.smartdataOptions.mongoDbPass)
|
||||
.replace('<password>', this.smartdataOptions.mongoDbPass)
|
||||
.replace('<DBNAME>', this.smartdataOptions.mongoDbName)
|
||||
.replace('<dbname>', this.smartdataOptions.mongoDbName);
|
||||
|
||||
this.mongoDbClient = await plugins.mongodb.MongoClient.connect(finalConnectionUrl, {
|
||||
useNewUrlParser: true
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
});
|
||||
this.mongoDb = this.mongoDbClient.db(this.smartdataOptions.mongoDbName);
|
||||
this.status = 'connected';
|
||||
@ -67,10 +52,7 @@ export class SmartdataDb {
|
||||
public async close(): Promise<any> {
|
||||
await this.mongoDbClient.close();
|
||||
this.status = 'disconnected';
|
||||
plugins.smartlog.defaultLogger.log(
|
||||
'info',
|
||||
`disconnected from database ${this.smartdataOptions.mongoDbName}`
|
||||
);
|
||||
logger.log('info', `disconnected from database ${this.smartdataOptions.mongoDbName}`);
|
||||
}
|
||||
|
||||
// handle table to class distribution
|
||||
@ -85,7 +67,7 @@ export class SmartdataDb {
|
||||
* @returns DbTable
|
||||
*/
|
||||
public async getSmartdataCollectionByName<T>(nameArg: string): Promise<SmartdataCollection<T>> {
|
||||
const resultCollection = this.smartdataCollectionMap.find(dbTableArg => {
|
||||
const resultCollection = this.smartdataCollectionMap.find((dbTableArg) => {
|
||||
return dbTableArg.collectionName === nameArg;
|
||||
});
|
||||
return resultCollection;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as plugins from './smartdata.plugins';
|
||||
|
||||
import { Objectmap } from '@pushrocks/lik';
|
||||
import { ObjectMap } from '@pushrocks/lik';
|
||||
|
||||
import { SmartdataDb } from './smartdata.classes.db';
|
||||
import { SmartdataCollection } from './smartdata.classes.collection';
|
||||
@ -11,7 +11,7 @@ export type TDocCreation = 'db' | 'new' | 'mixed';
|
||||
* saveable - saveable decorator to be used on class properties
|
||||
*/
|
||||
export function svDb() {
|
||||
return (target: SmartDataDbDoc<any>, key: string) => {
|
||||
return (target: SmartDataDbDoc<unknown, unknown>, key: string) => {
|
||||
console.log(`called svDb() on ${key}`);
|
||||
if (!target.saveableProperties) {
|
||||
target.saveableProperties = [];
|
||||
@ -24,7 +24,7 @@ export function svDb() {
|
||||
* unique index - decorator to mark a unique index
|
||||
*/
|
||||
export function unI() {
|
||||
return (target: SmartDataDbDoc<any>, key: string) => {
|
||||
return (target: SmartDataDbDoc<unknown, unknown>, key: string) => {
|
||||
console.log('called unI');
|
||||
|
||||
// mark the index as unique
|
||||
@ -41,7 +41,7 @@ export function unI() {
|
||||
};
|
||||
}
|
||||
|
||||
export class SmartDataDbDoc<T> {
|
||||
export class SmartDataDbDoc<T, TImplements> {
|
||||
/**
|
||||
* the collection object an Doc belongs to
|
||||
*/
|
||||
@ -89,7 +89,7 @@ export class SmartDataDbDoc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public static async getInstances<T>(filterArg): Promise<T[]> {
|
||||
public static async getInstances<T>(filterArg: Partial<T>): Promise<T[]> {
|
||||
const self: any = this; // fool typesystem
|
||||
let referenceMongoDBCollection: SmartdataCollection<T>;
|
||||
|
||||
@ -103,17 +103,15 @@ export class SmartDataDbDoc<T> {
|
||||
for (const item of foundDocs) {
|
||||
const newInstance = new this();
|
||||
newInstance.creationStatus = 'db';
|
||||
for (const key in item) {
|
||||
if (key !== 'id') {
|
||||
newInstance[key] = item[key];
|
||||
}
|
||||
for (const key of Object.keys(item)) {
|
||||
newInstance[key] = item[key];
|
||||
}
|
||||
returnArray.push(newInstance);
|
||||
}
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
public static async getInstance<T>(filterArg): Promise<T> {
|
||||
public static async getInstance<T>(filterArg: Partial<T>): Promise<T> {
|
||||
const result = await this.getInstances<T>(filterArg);
|
||||
if (result && result.length > 0) {
|
||||
return result[0];
|
||||
@ -152,9 +150,9 @@ export class SmartDataDbDoc<T> {
|
||||
* also store any referenced objects to DB
|
||||
* better for data consistency
|
||||
*/
|
||||
public saveDeep(savedMapArg: Objectmap<SmartDataDbDoc<any>> = null) {
|
||||
public saveDeep(savedMapArg: ObjectMap<SmartDataDbDoc<any, any>> = null) {
|
||||
if (!savedMapArg) {
|
||||
savedMapArg = new Objectmap<SmartDataDbDoc<any>>();
|
||||
savedMapArg = new ObjectMap<SmartDataDbDoc<any, any>>();
|
||||
}
|
||||
savedMapArg.add(this);
|
||||
this.save();
|
||||
@ -169,12 +167,12 @@ export class SmartDataDbDoc<T> {
|
||||
/**
|
||||
* creates a saveable object so the instance can be persisted as json in the database
|
||||
*/
|
||||
public async createSavableObject() {
|
||||
const saveableObject: any = {}; // is not exposed to outside, so any is ok here
|
||||
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;
|
||||
return saveableObject as TImplements;
|
||||
}
|
||||
|
||||
/**
|
||||
|
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();
|
@ -1,3 +0,0 @@
|
||||
export const addPassword = (mongoUrlArg: string, passwordArg: string): string => {
|
||||
return mongoUrlArg.replace('<PASSWORD>', passwordArg);
|
||||
};
|
Reference in New Issue
Block a user