From 3189aa687972a4931f13a26a3a2f03ff8bc40a9c Mon Sep 17 00:00:00 2001 From: Matteo Juen Date: Mon, 9 Sep 2024 23:09:14 +0200 Subject: [PATCH 1/8] docs: readme --- readme.md | 86 +------------------------------------------------------ 1 file changed, 1 insertion(+), 85 deletions(-) diff --git a/readme.md b/readme.md index c997880..6909ca6 100644 --- a/readme.md +++ b/readme.md @@ -1,85 +1 @@ -

- Nest Logo -

- -[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 -[circleci-url]: https://circleci.com/gh/nestjs/nest - -

A progressive Node.js framework for building efficient and scalable server-side applications.

-

-NPM Version -Package License -NPM Downloads -CircleCI -Coverage -Discord -Backers on Open Collective -Sponsors on Open Collective - Donate us - Support us - Follow us on Twitter -

- - -## Description - -[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. - -## Project setup - -```bash -$ npm install -``` - -## Compile and run the project - -```bash -# development -$ npm run start - -# watch mode -$ npm run start:dev - -# production mode -$ npm run start:prod -``` - -## Run tests - -```bash -# unit tests -$ npm run test - -# e2e tests -$ npm run test:e2e - -# test coverage -$ npm run test:cov -``` - -## Resources - -Check out a few resources that may come in handy when working with NestJS: - -- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework. -- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy). -- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/). -- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com). -- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com). -- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs). -- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com). - -## Support - -Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). - -## Stay in touch - -- Author - [Kamil Myƛliwiec](https://twitter.com/kammysliwiec) -- Website - [https://nestjs.com](https://nestjs.com/) -- Twitter - [@nestframework](https://twitter.com/nestframework) - -## License - -Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). +### working on it... From 299074a6653c2a9c2d825e30d907201a6d7e6fba Mon Sep 17 00:00:00 2001 From: Matteo Juen Date: Tue, 10 Sep 2024 19:06:40 +0200 Subject: [PATCH 2/8] chore: mongoose --- package-lock.json | 217 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 + 2 files changed, 218 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 586f331..74d894f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@nestjs/common": "^10.4.1", "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", + "@nestjs/mongoose": "^10.0.10", "@nestjs/platform-express": "^10.0.0", "@nestjs/schedule": "^4.1.0", "@nestjs/swagger": "^7.4.0", @@ -19,6 +20,7 @@ "class-validator": "^0.14.1", "joi": "^17.13.3", "modbus-serial": "^8.0.17", + "mongoose": "^8.6.1", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" }, @@ -1582,6 +1584,15 @@ "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==", "license": "MIT" }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@nestjs/cli": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.5.tgz", @@ -1741,6 +1752,18 @@ } } }, + "node_modules/@nestjs/mongoose": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@nestjs/mongoose/-/mongoose-10.0.10.tgz", + "integrity": "sha512-3Ff60ock8nwlAJC823TG91Qy+Qc6av+ddIb6n6wlFsTK0akDF/aTcagX8cF8uI8mWxCWjEwEsgv99vo6p0yJ+w==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0", + "mongoose": "^6.0.2 || ^7.0.0 || ^8.0.0", + "rxjs": "^7.0.0" + } + }, "node_modules/@nestjs/platform-express": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.1.tgz", @@ -2464,6 +2487,21 @@ "integrity": "sha512-w0URwf7BQb0rD/EuiG12KP0bailHKHP5YVviJG9zw3ykAokL0TuxU2TUqMB7EwZ59bDHYdeTIvjI5m0S7qHfOA==", "license": "MIT" }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -3333,6 +3371,15 @@ "node-int64": "^0.4.0" } }, + "node_modules/bson": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", + "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -6315,6 +6362,15 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6503,6 +6559,12 @@ "node": ">= 4.0.0" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -6647,6 +6709,145 @@ "serialport": "^12.0.0" } }, + "node_modules/mongodb": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", + "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "license": "MIT", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mongoose": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.1.tgz", + "integrity": "sha512-dppGcYqvsdg+VcnqXR5b467V4a+iNhmvkfYNpEPi6AjaUxnz6ioEDmrMLOi+sOWjvoHapuwPOigV4f2l7HC6ag==", + "license": "MIT", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "6.8.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "license": "MIT", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -7228,7 +7429,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -7830,6 +8030,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", + "license": "MIT" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -7885,6 +8091,15 @@ "node": ">=0.10.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/package.json b/package.json index cb053fc..bea53bd 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@nestjs/common": "^10.4.1", "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", + "@nestjs/mongoose": "^10.0.10", "@nestjs/platform-express": "^10.0.0", "@nestjs/schedule": "^4.1.0", "@nestjs/swagger": "^7.4.0", @@ -30,6 +31,7 @@ "class-validator": "^0.14.1", "joi": "^17.13.3", "modbus-serial": "^8.0.17", + "mongoose": "^8.6.1", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" }, From adb7d65cdf72a67f081967c3cbcaa124582f2d8c Mon Sep 17 00:00:00 2001 From: Matteo Juen Date: Tue, 10 Sep 2024 19:06:51 +0200 Subject: [PATCH 3/8] chore: compose mongo ports --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index dd58544..542dd91 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,8 +25,8 @@ services: command: - --config - /etc/mongo/mongo.conf - expose: - - 27017 + ports: + - 27017:27017 healthcheck: test: [ From 3640c96a060bc495460dcb119935e3790172ec4f Mon Sep 17 00:00:00 2001 From: Matteo Juen Date: Tue, 10 Sep 2024 19:07:15 +0200 Subject: [PATCH 4/8] feat: mongo schema - servince and controller --- src/app.module.ts | 5 +- src/config/configuration.ts | 7 +- .../database/mongo/config/config.module.ts | 29 +++++++ .../database/mongo/config/config.service.ts | 41 ++++++++++ .../database/mongo/config/configuration.ts | 9 +++ .../mongo/provider/mongo-provider.module.ts | 14 ++++ src/dto/create-energy-entry.dto.ts | 15 ++++ src/dto/update-energy-entry.dto.ts | 40 ++++++++++ .../energy-entry/energy-entry.controller.ts | 80 +++++++++++++++++++ .../energy-entry/energy-entry.module.ts | 23 ++++++ .../energy-entry/energy-entry.service.ts | 70 ++++++++++++++++ .../modbus-reader/modbus-reader.controller.ts | 12 --- .../modbus-reader/modbus-reader.module.ts | 8 +- ...der.service.ts => modbus-reder.service.ts} | 0 src/schemas/energy-entry.schema.ts | 27 +++++++ 15 files changed, 358 insertions(+), 22 deletions(-) create mode 100644 src/config/database/mongo/config/config.module.ts create mode 100644 src/config/database/mongo/config/config.service.ts create mode 100644 src/config/database/mongo/config/configuration.ts create mode 100644 src/config/database/mongo/provider/mongo-provider.module.ts create mode 100644 src/dto/create-energy-entry.dto.ts create mode 100644 src/dto/update-energy-entry.dto.ts create mode 100644 src/modules/energy-entry/energy-entry.controller.ts create mode 100644 src/modules/energy-entry/energy-entry.module.ts create mode 100644 src/modules/energy-entry/energy-entry.service.ts delete mode 100644 src/modules/modbus-reader/modbus-reader.controller.ts rename src/modules/modbus-reader/{modbus-reader.service.ts => modbus-reder.service.ts} (100%) create mode 100644 src/schemas/energy-entry.schema.ts diff --git a/src/app.module.ts b/src/app.module.ts index 0ab0eff..b4fbc3c 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,11 +1,12 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; -import { ModbusReaderModule } from './modules/modbus-reader/modbus-reader.module'; import { AppConfigModule } from './config/config.module'; +import { MongoDatabaseProviderModule } from './config/database/mongo/provider/mongo-provider.module'; +import { ModbusReaderModule } from './modules/modbus-reader/modbus-reader.module'; @Module({ - imports: [ModbusReaderModule, AppConfigModule], + imports: [AppConfigModule, MongoDatabaseProviderModule, ModbusReaderModule], controllers: [AppController], providers: [AppService], }) diff --git a/src/config/configuration.ts b/src/config/configuration.ts index f173491..907496a 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -2,8 +2,7 @@ import { registerAs } from '@nestjs/config'; export default registerAs('app', () => ({ port: process.env.APP_PORT, - botToken: process.env.BOT_TOKEN, - publicKey: process.env.APP_PUBLIC_KEY, - clientId: process.env.CLIENT_ID, - serverId: process.env.SERVER_ID, + url: process.env.APP_URL, + name: process.env.APP_NAME, + env: process.env.NODE_ENV, })); diff --git a/src/config/database/mongo/config/config.module.ts b/src/config/database/mongo/config/config.module.ts new file mode 100644 index 0000000..79f924e --- /dev/null +++ b/src/config/database/mongo/config/config.module.ts @@ -0,0 +1,29 @@ +import * as Joi from 'joi'; +import { Module } from '@nestjs/common'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import configuration from './configuration'; +import { MongoConfigService } from './config.service'; +/** + * Import and provide app configuration related classes. + * + * @module + */ +const ENV = process.env.NODE_ENV; +@Module({ + imports: [ + ConfigModule.forRoot({ + load: [configuration], + envFilePath: !ENV ? '.env' : `.env.${ENV}`, + validationSchema: Joi.object({ + MONGO_URI: Joi.string().default('localhost'), + MONGO_PORT: Joi.number().default(27017), + MONGO_USERNAME: Joi.string(), + MONGO_PASSWORD: Joi.string(), + MONGO_DATABASE: Joi.string().default(null), + }), + }), + ], + providers: [ConfigService, MongoConfigService], + exports: [ConfigService, MongoConfigService], +}) +export class MongoConfigModule {} diff --git a/src/config/database/mongo/config/config.service.ts b/src/config/database/mongo/config/config.service.ts new file mode 100644 index 0000000..4aaf177 --- /dev/null +++ b/src/config/database/mongo/config/config.service.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { + MongooseOptionsFactory, + MongooseModuleOptions, +} from '@nestjs/mongoose'; +/** + * Service dealing with app config based operations. + * + * @class + */ +@Injectable() +export class MongoConfigService implements MongooseOptionsFactory { + constructor(private configService: ConfigService) {} + + createMongooseOptions(): MongooseModuleOptions { + if (this.username && this.password) { + return { + uri: + `mongodb://${this.username}:${this.password}@${this.uri}` + + (this.database ? `/?authSource=${this.database}` : ''), + dbName: this.database, + }; + } else { + return { uri: this.uri }; + } + } + + get uri(): string { + return this.configService.get('mongo.uri'); + } + get username(): string { + return this.configService.get('mongo.username'); + } + get password(): string { + return this.configService.get('mongo.password'); + } + get database(): string { + return this.configService.get('mongo.database'); + } +} diff --git a/src/config/database/mongo/config/configuration.ts b/src/config/database/mongo/config/configuration.ts new file mode 100644 index 0000000..5a66724 --- /dev/null +++ b/src/config/database/mongo/config/configuration.ts @@ -0,0 +1,9 @@ +import { registerAs } from '@nestjs/config'; + +export default registerAs('mongo', () => ({ + uri: process.env.MONGO_URI, + port: process.env.MONGO_PORT, + username: process.env.MONGO_USERNAME, + password: process.env.MONGO_PASSWORD, + database: process.env.MONGO_DATABASE, +})); diff --git a/src/config/database/mongo/provider/mongo-provider.module.ts b/src/config/database/mongo/provider/mongo-provider.module.ts new file mode 100644 index 0000000..4710d53 --- /dev/null +++ b/src/config/database/mongo/provider/mongo-provider.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { MongooseModule, MongooseModuleAsyncOptions } from '@nestjs/mongoose'; +import { MongoConfigModule } from '../config/config.module'; +import { MongoConfigService } from '../config/config.service'; + +@Module({ + imports: [ + MongooseModule.forRootAsync({ + imports: [MongoConfigModule], + useExisting: MongoConfigService, + } as MongooseModuleAsyncOptions), + ], +}) +export class MongoDatabaseProviderModule {} diff --git a/src/dto/create-energy-entry.dto.ts b/src/dto/create-energy-entry.dto.ts new file mode 100644 index 0000000..1879872 --- /dev/null +++ b/src/dto/create-energy-entry.dto.ts @@ -0,0 +1,15 @@ +import { ApiProperty, OmitType } from '@nestjs/swagger'; +import { IsNotEmpty } from 'class-validator'; +import { UpdateEnergyEntryDto } from './update-energy-entry.dto'; + +export class CreateEnergyEntryDto extends OmitType(UpdateEnergyEntryDto, [ + '_id', + 'batteryLevel', +] as const) { + @ApiProperty({ + description: 'The battery level', + example: 100, + }) + @IsNotEmpty() + batteryLevel: number; +} diff --git a/src/dto/update-energy-entry.dto.ts b/src/dto/update-energy-entry.dto.ts new file mode 100644 index 0000000..4f2c3ea --- /dev/null +++ b/src/dto/update-energy-entry.dto.ts @@ -0,0 +1,40 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsOptional } from 'class-validator'; +import { ObjectId } from 'mongoose'; + +export class UpdateEnergyEntryDto { + @ApiProperty({ + description: 'The mongo id', + example: '2318931289123890', + }) + @IsNotEmpty() + _id: ObjectId; + + @ApiProperty({ + description: 'The battery level', + example: 100, + }) + @IsOptional() + batteryLevel: number; + + @ApiProperty({ + description: 'The battery level in percent', + example: '45%', + }) + @IsOptional() + batteryPercent: string; + + @ApiProperty({ + description: 'The battery voltage', + example: '5V', + }) + @IsOptional() + batteryVoltage: string; + + @ApiProperty({ + description: 'The battery status', + example: 'charging', + }) + @IsOptional() + batteryStatus: string; +} diff --git a/src/modules/energy-entry/energy-entry.controller.ts b/src/modules/energy-entry/energy-entry.controller.ts new file mode 100644 index 0000000..a648ed4 --- /dev/null +++ b/src/modules/energy-entry/energy-entry.controller.ts @@ -0,0 +1,80 @@ +import { + Body, + ClassSerializerInterceptor, + Controller, + Get, + Inject, + Param, + Post, + Put, + UseInterceptors, + UsePipes, + ValidationPipe, +} from '@nestjs/common'; +import { ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; +import { EnergyEntryService } from './energy-entry.service'; +import { CreateEnergyEntryDto } from '../../dto/create-energy-entry.dto'; +import { ReS } from '../../common/res.model'; +import { UpdateEnergyEntryDto } from '../../dto/update-energy-entry.dto'; +import { ObjectId } from 'mongoose'; + +@Controller('energy-data') +@ApiTags('energy-data') +export class EnergyEntryController { + constructor( + @Inject(EnergyEntryService) + private readonly modbusReaderService: EnergyEntryService, + ) {} + + @Post('/') + @UseInterceptors(ClassSerializerInterceptor) + @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) + @ApiOperation({ + summary: 'create enery entry', + description: 'create a new energy entry', + }) + async create(@Body() createDto: CreateEnergyEntryDto) { + return ReS.FromData(await this.modbusReaderService.create(createDto)); + } + + @Put('/') + @UseInterceptors(ClassSerializerInterceptor) + @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) + @ApiOperation({ + summary: 'update enery entry', + description: 'update a new energy entry', + }) + async update(@Body() updateDto: UpdateEnergyEntryDto) { + return ReS.FromData(await this.modbusReaderService.update(updateDto)); + } + + @Get('/') + @UseInterceptors(ClassSerializerInterceptor) + @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) + @ApiOperation({ + summary: 'get all data', + description: 'get all data from mongo', + }) + async getAll() { + return ReS.FromData(await this.modbusReaderService.getAll()); + } + + @Get('/:id') + @ApiParam({ + name: 'id', + description: 'The mongo id', + allowEmptyValue: false, + example: '222222222222222222222222', + required: true, + format: 'string', + }) + @UseInterceptors(ClassSerializerInterceptor) + @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) + @ApiOperation({ + summary: 'get data by id', + description: 'get data by id from mongo', + }) + async get(@Param('id') id: string | ObjectId) { + return ReS.FromData(await this.modbusReaderService.get(id)); + } +} diff --git a/src/modules/energy-entry/energy-entry.module.ts b/src/modules/energy-entry/energy-entry.module.ts new file mode 100644 index 0000000..f909ae7 --- /dev/null +++ b/src/modules/energy-entry/energy-entry.module.ts @@ -0,0 +1,23 @@ +import { Module } from '@nestjs/common'; +import { EnergyEntryService } from './energy-entry.service'; +import { EnergyEntryController } from './energy-entry.controller'; +import { MongooseModule } from '@nestjs/mongoose'; +import { + EnergyEntry, + EnergyEntrySchema, +} from '../../schemas/energy-entry.schema'; + +@Module({ + imports: [ + MongooseModule.forFeature([ + { + name: EnergyEntry.name, + schema: EnergyEntrySchema, + }, + ]), + ], // Add any imported modules here + controllers: [EnergyEntryController], // Add any controllers here + providers: [EnergyEntryService], + exports: [EnergyEntryService], // Add any providers (services) here +}) +export class EnergyEntryModule {} diff --git a/src/modules/energy-entry/energy-entry.service.ts b/src/modules/energy-entry/energy-entry.service.ts new file mode 100644 index 0000000..2a301f7 --- /dev/null +++ b/src/modules/energy-entry/energy-entry.service.ts @@ -0,0 +1,70 @@ +import { Injectable, UnprocessableEntityException } from '@nestjs/common'; +import { + EnergyEntry, + EnergyEntryDocument, +} from '../../schemas/energy-entry.schema'; +import { InjectModel } from '@nestjs/mongoose'; +import { Model, ObjectId } from 'mongoose'; +import { CreateEnergyEntryDto } from '../../dto/create-energy-entry.dto'; +import { UpdateEnergyEntryDto } from '../../dto/update-energy-entry.dto'; + +@Injectable() +export class EnergyEntryService { + constructor( + @InjectModel(EnergyEntry.name) + private readonly energyEntryModel: Model, + ) {} + + async create(createDto: CreateEnergyEntryDto): Promise { + try { + return await this.energyEntryModel.create({ + batteryLevel: createDto.batteryLevel, + batteryPercent: createDto.batteryPercent, + batteryVoltage: createDto.batteryVoltage, + batteryStatus: createDto.batteryStatus, + occuredAt: new Date(), + }); + } catch (error) { + throw new UnprocessableEntityException(error); + } + } + + async update(updateDto: UpdateEnergyEntryDto): Promise { + try { + return await this.energyEntryModel.findOneAndUpdate( + { + _id: updateDto._id, + }, + { + batteryLevel: updateDto.batteryLevel, + batteryPercent: updateDto.batteryPercent, + batteryVoltage: updateDto.batteryVoltage, + batteryStatus: updateDto.batteryStatus, + }, + { + new: true, + }, + ); + } catch (error) { + throw new UnprocessableEntityException(error); + } + } + + async get(id: ObjectId | string): Promise { + try { + return await this.energyEntryModel.findOne({ + _id: id, + }); + } catch (error) { + throw new UnprocessableEntityException(error); + } + } + + async getAll(): Promise { + try { + return await this.energyEntryModel.find(); + } catch (error) { + throw new UnprocessableEntityException(error); + } + } +} diff --git a/src/modules/modbus-reader/modbus-reader.controller.ts b/src/modules/modbus-reader/modbus-reader.controller.ts deleted file mode 100644 index ba7b558..0000000 --- a/src/modules/modbus-reader/modbus-reader.controller.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Controller, Inject } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; -import { ModbusReaderService } from './modbus-reader.service'; - -@Controller('modbus-reader') -@ApiTags('modbus-reader') -export class ModbusReaderController { - constructor( - @Inject(ModbusReaderService) - private readonly modbusReaderService: ModbusReaderService, - ) {} -} diff --git a/src/modules/modbus-reader/modbus-reader.module.ts b/src/modules/modbus-reader/modbus-reader.module.ts index f6f17db..cef8a68 100644 --- a/src/modules/modbus-reader/modbus-reader.module.ts +++ b/src/modules/modbus-reader/modbus-reader.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common'; -import { ModbusReaderService } from './modbus-reader.service'; -import { ModbusReaderController } from './modbus-reader.controller'; +import { ModbusReaderService } from './modbus-reder.service'; +import { EnergyEntryModule } from '../energy-entry/energy-entry.module'; @Module({ - imports: [], // Add any imported modules here - controllers: [ModbusReaderController], // Add any controllers here + imports: [EnergyEntryModule], // Add any imported modules here + controllers: [], // Add any controllers here providers: [ModbusReaderService], exports: [ModbusReaderService], // Add any providers (services) here }) diff --git a/src/modules/modbus-reader/modbus-reader.service.ts b/src/modules/modbus-reader/modbus-reder.service.ts similarity index 100% rename from src/modules/modbus-reader/modbus-reader.service.ts rename to src/modules/modbus-reader/modbus-reder.service.ts diff --git a/src/schemas/energy-entry.schema.ts b/src/schemas/energy-entry.schema.ts new file mode 100644 index 0000000..09c34c0 --- /dev/null +++ b/src/schemas/energy-entry.schema.ts @@ -0,0 +1,27 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; + +@Schema() +export class EnergyEntry { + @Prop({ required: true }) + batteryLevel: number; + + @Prop({ required: false }) + batteryPercent: string; + + @Prop({ required: false }) + batteryVoltage: string; + + @Prop({ required: false }) + batteryStatus: string; + + @Prop({ required: true }) + occuredAt: Date; + + constructor(data) { + Object.assign(this, data); + } +} + +export type EnergyEntryDocument = EnergyEntry & Document; + +export const EnergyEntrySchema = SchemaFactory.createForClass(EnergyEntry); From 90dc29546c5141043ff37380c7e2428a9320359e Mon Sep 17 00:00:00 2001 From: Matteo Juen Date: Tue, 10 Sep 2024 20:01:20 +0200 Subject: [PATCH 5/8] feat: env --- .env | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..9ad46ef --- /dev/null +++ b/.env @@ -0,0 +1,7 @@ +APP_PORT=9000 +APP_ENV=development + +MONGO_URI=localhost +MONGO_PORT=27017 +MONGO_USERNAME=matteo +MONGO_PASSWORD=matteo From ebc65760293b4e51743a261eebeff4bdc80f423f Mon Sep 17 00:00:00 2001 From: Matteo Juen Date: Tue, 10 Sep 2024 21:04:18 +0200 Subject: [PATCH 6/8] fix: interceptor --- src/modules/energy-entry/energy-entry.controller.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/modules/energy-entry/energy-entry.controller.ts b/src/modules/energy-entry/energy-entry.controller.ts index a648ed4..715ecc0 100644 --- a/src/modules/energy-entry/energy-entry.controller.ts +++ b/src/modules/energy-entry/energy-entry.controller.ts @@ -1,13 +1,11 @@ import { Body, - ClassSerializerInterceptor, Controller, Get, Inject, Param, Post, Put, - UseInterceptors, UsePipes, ValidationPipe, } from '@nestjs/common'; @@ -27,7 +25,6 @@ export class EnergyEntryController { ) {} @Post('/') - @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) @ApiOperation({ summary: 'create enery entry', @@ -38,7 +35,6 @@ export class EnergyEntryController { } @Put('/') - @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) @ApiOperation({ summary: 'update enery entry', @@ -49,7 +45,6 @@ export class EnergyEntryController { } @Get('/') - @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) @ApiOperation({ summary: 'get all data', @@ -68,7 +63,6 @@ export class EnergyEntryController { required: true, format: 'string', }) - @UseInterceptors(ClassSerializerInterceptor) @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) @ApiOperation({ summary: 'get data by id', From f473f318882fc08ec4ae2387b16dd88c7efc63a4 Mon Sep 17 00:00:00 2001 From: Matteo Juen Date: Wed, 11 Sep 2024 17:44:21 +0200 Subject: [PATCH 7/8] feat: app port --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 9ad46ef..6b1b274 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -APP_PORT=9000 +APP_PORT=3000 APP_ENV=development MONGO_URI=localhost From b8924a987b9ad28f0db445d4f3f9414339e48eaa Mon Sep 17 00:00:00 2001 From: Matteo Juen Date: Wed, 11 Sep 2024 17:58:00 +0200 Subject: [PATCH 8/8] fix: sort for graph --- src/modules/energy-entry/energy-entry.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/energy-entry/energy-entry.service.ts b/src/modules/energy-entry/energy-entry.service.ts index 2a301f7..3604e76 100644 --- a/src/modules/energy-entry/energy-entry.service.ts +++ b/src/modules/energy-entry/energy-entry.service.ts @@ -62,7 +62,7 @@ export class EnergyEntryService { async getAll(): Promise { try { - return await this.energyEntryModel.find(); + return await this.energyEntryModel.find().sort({ occuredAt: 1 }); } catch (error) { throw new UnprocessableEntityException(error); }