diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..a23aa5f
Binary files /dev/null and b/.DS_Store differ
diff --git a/.idea/csv-editor.xml b/.idea/csv-editor.xml
new file mode 100644
index 0000000..15988f7
--- /dev/null
+++ b/.idea/csv-editor.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/discord.xml b/.idea/discord.xml
new file mode 100644
index 0000000..30bab2a
--- /dev/null
+++ b/.idea/discord.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..03d9549
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..984764e
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1696663237589
+
+
+ 1696663237589
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..571b182
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+# K-Lab Weather Platform
+
+## Hardware
+
+![Screenshot 2023-10-07 at 19.07.30.png](assets%2FScreenshot%202023-10-07%20at%2019.07.30.png)
+
+## Software Platform
+
+![Screenshot 2023-10-07 at 19.08.07.png](assets%2FScreenshot%202023-10-07%20at%2019.08.07.png)
+
+## Telegram Bot with AI
+
+![Screenshot 2023-10-07 at 19.08.53.png](assets%2FScreenshot%202023-10-07%20at%2019.08.53.png)
\ No newline at end of file
diff --git a/assets/Screenshot 2023-10-07 at 19.07.30.png b/assets/Screenshot 2023-10-07 at 19.07.30.png
new file mode 100644
index 0000000..a5f654e
Binary files /dev/null and b/assets/Screenshot 2023-10-07 at 19.07.30.png differ
diff --git a/assets/Screenshot 2023-10-07 at 19.08.07.png b/assets/Screenshot 2023-10-07 at 19.08.07.png
new file mode 100644
index 0000000..ab66cfe
Binary files /dev/null and b/assets/Screenshot 2023-10-07 at 19.08.07.png differ
diff --git a/assets/Screenshot 2023-10-07 at 19.08.53.png b/assets/Screenshot 2023-10-07 at 19.08.53.png
new file mode 100644
index 0000000..c46e8eb
Binary files /dev/null and b/assets/Screenshot 2023-10-07 at 19.08.53.png differ
diff --git a/weather_platform/.editorconfig b/weather_platform/.editorconfig
new file mode 100644
index 0000000..6e87a00
--- /dev/null
+++ b/weather_platform/.editorconfig
@@ -0,0 +1,13 @@
+# Editor configuration, see http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/weather_platform/.env b/weather_platform/.env
new file mode 100644
index 0000000..6ea5b18
--- /dev/null
+++ b/weather_platform/.env
@@ -0,0 +1,8 @@
+AGW_PORT=8045
+SENSORS_SERVICE_PORT=8046
+AGREGATORS_SERVICE_PORT=8047
+MEASURES_SERVICE_PORT=8048
+PORT=8080
+AGREGATORS_SOURCE_URL=postgresql://user2235:atlantium@localhost:5441/agregators
+SENSORS_SOURCE_URL=postgresql://user2235:atlantium@localhost:5440/sensors
+MEASURES_SOURCE_URL=postgresql://user2235:atlantium@localhost:5442/measures
diff --git a/weather_platform/.env.example b/weather_platform/.env.example
new file mode 100644
index 0000000..57c7868
--- /dev/null
+++ b/weather_platform/.env.example
@@ -0,0 +1,7 @@
+AGW_PORT=8045
+SENSORS_SERVICE_PORT=8046
+AGREGATORS_SERVICE_PORT=8047
+MEASURES_SERVICE_PORT=8048
+AGREGATORS_SOURCE_URL=postgresql://user2235:atlantium@localhost:5441/agregators
+SENSORS_SOURCE_URL=postgresql://user2235:atlantium@localhost:5440/sensors
+MEASURES_SOURCE_URL=postgresql://user2235:atlantium@localhost:5442/measures
diff --git a/weather_platform/.eslintignore b/weather_platform/.eslintignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/weather_platform/.eslintignore
@@ -0,0 +1 @@
+node_modules
diff --git a/weather_platform/.eslintrc.json b/weather_platform/.eslintrc.json
new file mode 100644
index 0000000..fd85475
--- /dev/null
+++ b/weather_platform/.eslintrc.json
@@ -0,0 +1,40 @@
+{
+ "root": true,
+ "ignorePatterns": ["**/*"],
+ "plugins": ["@nx"],
+ "overrides": [
+ {
+ "files": "*.json",
+ "parser": "jsonc-eslint-parser",
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {
+ "@nx/enforce-module-boundaries": [
+ "error",
+ {
+ "enforceBuildableLibDependency": true,
+ "allow": [],
+ "depConstraints": [
+ {
+ "sourceTag": "*",
+ "onlyDependOnLibsWithTags": ["*"]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "extends": ["plugin:@nx/typescript"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "extends": ["plugin:@nx/javascript"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/weather_platform/.gitignore b/weather_platform/.gitignore
new file mode 100644
index 0000000..0016c21
--- /dev/null
+++ b/weather_platform/.gitignore
@@ -0,0 +1,43 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+dist
+tmp
+/out-tsc
+
+# dependencies
+node_modules
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+yarn-error.log
+testem.log
+/typings
+
+# System Files
+.DS_Store
+Thumbs.db
+
+data_db_agregators
+data_db_measures
+data_db_sensors
diff --git a/weather_platform/.prettierignore b/weather_platform/.prettierignore
new file mode 100644
index 0000000..9481e77
--- /dev/null
+++ b/weather_platform/.prettierignore
@@ -0,0 +1,3 @@
+# Add files here to ignore them from prettier formatting
+/dist
+/coverage
\ No newline at end of file
diff --git a/weather_platform/.prettierrc b/weather_platform/.prettierrc
new file mode 100644
index 0000000..544138b
--- /dev/null
+++ b/weather_platform/.prettierrc
@@ -0,0 +1,3 @@
+{
+ "singleQuote": true
+}
diff --git a/weather_platform/README.md b/weather_platform/README.md
new file mode 100644
index 0000000..a39eab0
--- /dev/null
+++ b/weather_platform/README.md
@@ -0,0 +1,132 @@
+
+
+
K-Lab | Cyber Garden Weather
+
+
+
+
+
+ ✨
+
+ Processing Platform monorepo
+
+
+
+
+## Описание
+https://www.notion.so/sorrythisdomainisnotavailable/CyberGarden-k-Lab-docs-01392e46510e4d5c80c0a198c037d768?pvs=4
+
+
+
+## Сервисы
+- [frontend (ReactJS)](/apps/crud)
+- [frontend e2e](/apps/crud-e2e)
+
+## Dev
+### Backend
+#### Prisma Types
+```bash
+nx g prisma-generator
+```
+
+### Frontend
+#### Create a new Layout
+```bash
+nx g @nx/react:component NAME --project site-layouts
+```
+#### Create a new Page
+```bash
+nx g @nx/react:component NAME --project site-pages
+```
+#### Create a new Component
+Like navbar, footer, login card, delete modal alert and et.
+```bash
+nx g @nx/react:component NAME --project ui-modules
+```
+#### Create a new UI Component
+Like nav_link, cta_button, username_input and et.
+```bash
+nx g @nx/react:component NAME --project ui
+```
+
+
+## Развертывание
+
+To start the development server run `nx serve frontend`. Open your browser and navigate to http://localhost:4200/. Happy coding!
+```bash
+npm i -g prisma nx
+```
+
+```bash
+yarn install
+```
+
+```bash
+copy .env.example .env
+```
+
+```bash
+docker-compose up -d
+```
+
+Run all services:
+```bash
+nx run-many --parallel --target=serve --projects=crud,agw,agregators-service,measures-service,sensors-service
+```
+
+```bash
+nx run py-tg-bot-weather-agent:serve
+```
+
+
+## Структура репозитория
+Репозиторий содержит следующие основные каталоги и файлы:
+- `apps` - приложения
+- `libs` - библиотеки и генераторы
+- `tools` - Nx workspaces tools
+- `docs` - документация
+
+
+## Коммиты
+Используемые префиксы:
+- **feat:** (от "feature") - новая функциональность или добавление нового компонента.
+- **fix:** - исправление ошибок или дефектов.
+- **docs:** - изменения, связанные с документацией, например, обновление README или документации в коде.
+- **style:** - изменения внешнего вида кода, форматирование, пробелы, отступы и т.д., которые не влияют на его поведение.
+- **refactor:** - рефакторинг кода без исправления ошибок или добавления новых функций.
+- **test:** - добавление или исправление тестов.
+- **chore:** - изменения в сборочных скриптах, настройках инструментов, обновление зависимостей и т.д.
+- **perf:** - изменения, связанные с оптимизацией производительности.
+- **revert:** - отмена предыдущего коммита.
+- **merge:** - коммит, созданный при слиянии веток.
+- **release:** - коммит, связанный с выпуском новой версии.
+- **require:** - коммит, связанный с установкой новой библиотеки
+---
+# Any NX comands log
+- npx create-nx-workspace@latest --preset=react
+- npm install -D @nrwl/nest
+- nx g @nrwl/nest:app agw --frontendProject crud
+- nx g @nx/react:setup-tailwind --project=crud
+- nx g @nx/react:lib ui
+- nx g @nx/react:component navbar --project ui
+- nx run-many --parallel --target=serve --projects=agw,auth,crud
+### Creating Prisma generator tool
+- nx g plugin
+- prisma-generator
+- nx generate @nx/plugin:generator prisma-generator --project=prisma-generator
+#### Run
+- nx generate prisma-generator
+#### Migrations
+- prisma db push --schema="./libs/prisma-clients/Agregators/prisma/schema.prisma"
+- prisma generate --schema="./libs/prisma-clients/Agregators/prisma/schema.prisma"
+- prisma db push --schema="./libs/prisma-clients/Measures/prisma/schema.prisma"
+- prisma generate --schema="./libs/prisma-clients/Measures/prisma/schema.prisma"
+- prisma db push --schema="./libs/prisma-clients/Sensors/prisma/schema.prisma"
+- prisma generate --schema="./libs/prisma-clients/Sensors/prisma/schema.prisma"
+### Crud Pages
+- nx generate @nrwl/react:lib site-pages --template=typescript
+- nx g @nx/react:component NAME --project site-pages
+- nx build site-pages
+### Crud Layout
+- nx generate @nrwl/react:lib site-layouts --template=typescript
+- nx g @nx/react:component NAME --project site-layouts
diff --git a/weather_platform/apps/agregators-service-e2e/.eslintrc.json b/weather_platform/apps/agregators-service-e2e/.eslintrc.json
new file mode 100644
index 0000000..9d9c0db
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/weather_platform/apps/agregators-service-e2e/jest.config.ts b/weather_platform/apps/agregators-service-e2e/jest.config.ts
new file mode 100644
index 0000000..638f3b3
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/jest.config.ts
@@ -0,0 +1,19 @@
+/* eslint-disable */
+export default {
+ displayName: 'agregators-service-e2e',
+ preset: '../../jest.preset.js',
+ globalSetup: '/src/support/global-setup.ts',
+ globalTeardown: '/src/support/global-teardown.ts',
+ setupFiles: ['/src/support/test-setup.ts'],
+ testEnvironment: 'node',
+ transform: {
+ '^.+\\.[tj]s$': [
+ 'ts-jest',
+ {
+ tsconfig: '/tsconfig.spec.json',
+ },
+ ],
+ },
+ moduleFileExtensions: ['ts', 'js', 'html'],
+ coverageDirectory: '../../coverage/agregators-service-e2e',
+};
diff --git a/weather_platform/apps/agregators-service-e2e/project.json b/weather_platform/apps/agregators-service-e2e/project.json
new file mode 100644
index 0000000..b321fd6
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/project.json
@@ -0,0 +1,23 @@
+{
+ "name": "agregators-service-e2e",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "implicitDependencies": ["agregators-service"],
+ "projectType": "application",
+ "targets": {
+ "e2e": {
+ "executor": "@nx/jest:jest",
+ "outputs": ["{workspaceRoot}/coverage/{e2eProjectRoot}"],
+ "options": {
+ "jestConfig": "apps/agregators-service-e2e/jest.config.ts",
+ "passWithNoTests": true
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["apps/agregators-service-e2e/**/*.{js,ts}"]
+ }
+ }
+ }
+}
diff --git a/weather_platform/apps/agregators-service-e2e/src/agregators-service/agregators-service.spec.ts b/weather_platform/apps/agregators-service-e2e/src/agregators-service/agregators-service.spec.ts
new file mode 100644
index 0000000..e8ac2a6
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/src/agregators-service/agregators-service.spec.ts
@@ -0,0 +1,10 @@
+import axios from 'axios';
+
+describe('GET /api', () => {
+ it('should return a message', async () => {
+ const res = await axios.get(`/api`);
+
+ expect(res.status).toBe(200);
+ expect(res.data).toEqual({ message: 'Hello API' });
+ });
+});
diff --git a/weather_platform/apps/agregators-service-e2e/src/support/global-setup.ts b/weather_platform/apps/agregators-service-e2e/src/support/global-setup.ts
new file mode 100644
index 0000000..c1f5144
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/src/support/global-setup.ts
@@ -0,0 +1,10 @@
+/* eslint-disable */
+var __TEARDOWN_MESSAGE__: string;
+
+module.exports = async function () {
+ // Start services that that the app needs to run (e.g. database, docker-compose, etc.).
+ console.log('\nSetting up...\n');
+
+ // Hint: Use `globalThis` to pass variables to global teardown.
+ globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n';
+};
diff --git a/weather_platform/apps/agregators-service-e2e/src/support/global-teardown.ts b/weather_platform/apps/agregators-service-e2e/src/support/global-teardown.ts
new file mode 100644
index 0000000..32ea345
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/src/support/global-teardown.ts
@@ -0,0 +1,7 @@
+/* eslint-disable */
+
+module.exports = async function () {
+ // Put clean up logic here (e.g. stopping services, docker-compose, etc.).
+ // Hint: `globalThis` is shared between setup and teardown.
+ console.log(globalThis.__TEARDOWN_MESSAGE__);
+};
diff --git a/weather_platform/apps/agregators-service-e2e/src/support/test-setup.ts b/weather_platform/apps/agregators-service-e2e/src/support/test-setup.ts
new file mode 100644
index 0000000..07f2870
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/src/support/test-setup.ts
@@ -0,0 +1,10 @@
+/* eslint-disable */
+
+import axios from 'axios';
+
+module.exports = async function () {
+ // Configure axios for tests to use.
+ const host = process.env.HOST ?? 'localhost';
+ const port = process.env.PORT ?? '3000';
+ axios.defaults.baseURL = `http://${host}:${port}`;
+};
diff --git a/weather_platform/apps/agregators-service-e2e/tsconfig.json b/weather_platform/apps/agregators-service-e2e/tsconfig.json
new file mode 100644
index 0000000..ed633e1
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ],
+ "compilerOptions": {
+ "esModuleInterop": true
+ }
+}
diff --git a/weather_platform/apps/agregators-service-e2e/tsconfig.spec.json b/weather_platform/apps/agregators-service-e2e/tsconfig.spec.json
new file mode 100644
index 0000000..d7f9cf2
--- /dev/null
+++ b/weather_platform/apps/agregators-service-e2e/tsconfig.spec.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "commonjs",
+ "types": ["jest", "node"]
+ },
+ "include": ["jest.config.ts", "src/**/*.ts"]
+}
diff --git a/weather_platform/apps/agregators-service/.eslintrc.json b/weather_platform/apps/agregators-service/.eslintrc.json
new file mode 100644
index 0000000..9d9c0db
--- /dev/null
+++ b/weather_platform/apps/agregators-service/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/weather_platform/apps/agregators-service/jest.config.ts b/weather_platform/apps/agregators-service/jest.config.ts
new file mode 100644
index 0000000..1f404a9
--- /dev/null
+++ b/weather_platform/apps/agregators-service/jest.config.ts
@@ -0,0 +1,11 @@
+/* eslint-disable */
+export default {
+ displayName: 'agregators-service',
+ preset: '../../jest.preset.js',
+ testEnvironment: 'node',
+ transform: {
+ '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
+ },
+ moduleFileExtensions: ['ts', 'js', 'html'],
+ coverageDirectory: '../../coverage/apps/agregators-service',
+};
diff --git a/weather_platform/apps/agregators-service/project.json b/weather_platform/apps/agregators-service/project.json
new file mode 100644
index 0000000..ca72973
--- /dev/null
+++ b/weather_platform/apps/agregators-service/project.json
@@ -0,0 +1,64 @@
+{
+ "name": "agregators-service",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "apps/agregators-service/src",
+ "projectType": "application",
+ "targets": {
+ "build": {
+ "executor": "@nx/webpack:webpack",
+ "outputs": ["{options.outputPath}"],
+ "defaultConfiguration": "production",
+ "options": {
+ "target": "node",
+ "compiler": "tsc",
+ "outputPath": "dist/apps/agregators-service",
+ "main": "apps/agregators-service/src/main.ts",
+ "tsConfig": "apps/agregators-service/tsconfig.app.json",
+ "assets": ["apps/agregators-service/src/assets"],
+ "isolatedConfig": true,
+ "webpackConfig": "apps/agregators-service/webpack.config.js"
+ },
+ "configurations": {
+ "development": {},
+ "production": {}
+ }
+ },
+ "serve": {
+ "executor": "@nx/js:node",
+ "defaultConfiguration": "development",
+ "options": {
+ "buildTarget": "agregators-service:build"
+ },
+ "configurations": {
+ "development": {
+ "buildTarget": "agregators-service:build:development"
+ },
+ "production": {
+ "buildTarget": "agregators-service:build:production"
+ }
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["apps/agregators-service/**/*.ts"]
+ }
+ },
+ "test": {
+ "executor": "@nx/jest:jest",
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
+ "options": {
+ "jestConfig": "apps/agregators-service/jest.config.ts",
+ "passWithNoTests": true
+ },
+ "configurations": {
+ "ci": {
+ "ci": true,
+ "codeCoverage": true
+ }
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/weather_platform/apps/agregators-service/src/DTO/AgregatorCreateDTOClass.dto.ts b/weather_platform/apps/agregators-service/src/DTO/AgregatorCreateDTOClass.dto.ts
new file mode 100644
index 0000000..903ba50
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/DTO/AgregatorCreateDTOClass.dto.ts
@@ -0,0 +1,24 @@
+import { ApiProperty } from "@nestjs/swagger";
+
+export class AgregatorCreateDTOClass {
+ @ApiProperty({description: 'The date when the was sent'})
+ sendedInDate: string;
+ @ApiProperty({description: 'The UUID of the creator'})
+ creatorUUID: string;
+ @ApiProperty({description: 'The agregator name'})
+ name: string;
+ @ApiProperty({description: 'The agregator latitude'})
+ lat: string;
+ @ApiProperty({description: 'The agregator longitude'})
+ lng: string;
+ @ApiProperty({description: 'The agregator height from the ground'})
+ height: number;
+ @ApiProperty({description: 'The agregator country'})
+ country: string;
+ @ApiProperty({description: 'The agregator city'})
+ city: string;
+ @ApiProperty({description: 'The agregator region'})
+ region: string;
+ @ApiProperty({description: 'The agregator street'})
+ street: string;
+}
diff --git a/weather_platform/apps/agregators-service/src/DTO/AgregatorGetDTOClass.dto.ts b/weather_platform/apps/agregators-service/src/DTO/AgregatorGetDTOClass.dto.ts
new file mode 100644
index 0000000..ce20027
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/DTO/AgregatorGetDTOClass.dto.ts
@@ -0,0 +1,15 @@
+import { ApiProperty } from "@nestjs/swagger";
+import { Prisma } from "@weather-platform/prisma-clients/Agregators";
+
+export class AgregatorGetDTOClass {
+ @ApiProperty({description: 'The number of items to skip'})
+ skip?: number;
+ @ApiProperty({description: 'The number of items to take'})
+ take?: number;
+ @ApiProperty({description: 'The cursor'})
+ cursor?: Prisma.AgregatorWhereUniqueInput;
+ @ApiProperty({description: 'The where'})
+ where?: Prisma.AgregatorWhereInput;
+ @ApiProperty({description: 'The orderBy'})
+ orderBy?: Prisma.AgregatorOrderByWithRelationInput;
+}
diff --git a/weather_platform/apps/agregators-service/src/DTO/AgregatorUpdateDTOClass.dto.ts b/weather_platform/apps/agregators-service/src/DTO/AgregatorUpdateDTOClass.dto.ts
new file mode 100644
index 0000000..d3d6788
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/DTO/AgregatorUpdateDTOClass.dto.ts
@@ -0,0 +1,13 @@
+import { ApiProperty } from "@nestjs/swagger";
+import { Prisma } from "@weather-platform/prisma-clients/Agregators";
+
+type AgregatorUpdateDTO = {
+ where: Prisma.AgregatorWhereUniqueInput;
+ data: Prisma.AgregatorUpdateInput;
+};
+export class AgregatorUpdateDTOClass implements AgregatorUpdateDTO {
+ @ApiProperty({description: 'The where'})
+ where: Prisma.AgregatorWhereUniqueInput;
+ @ApiProperty({description: 'The data'})
+ data: Prisma.AgregatorUpdateInput;
+}
diff --git a/weather_platform/apps/agregators-service/src/app/app.controller.spec.ts b/weather_platform/apps/agregators-service/src/app/app.controller.spec.ts
new file mode 100644
index 0000000..de8007e
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/app/app.controller.spec.ts
@@ -0,0 +1,22 @@
+import { Test, TestingModule } from '@nestjs/testing';
+
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+
+describe('AppController', () => {
+ let app: TestingModule;
+
+ beforeAll(async () => {
+ app = await Test.createTestingModule({
+ controllers: [AppController],
+ providers: [AppService],
+ }).compile();
+ });
+
+ describe('getData', () => {
+ it('should return "Hello API"', () => {
+ const appController = app.get(AppController);
+ expect(appController.getData()).toEqual({ message: 'Hello API' });
+ });
+ });
+});
diff --git a/weather_platform/apps/agregators-service/src/app/app.controller.ts b/weather_platform/apps/agregators-service/src/app/app.controller.ts
new file mode 100644
index 0000000..d24ddfd
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/app/app.controller.ts
@@ -0,0 +1,136 @@
+import { Body, Controller, Get, Post } from "@nestjs/common";
+import { AgregatorsClient } from '@weather-platform/prisma-clients';
+import { AppService } from './app.service';
+import { Agregator, Prisma } from '@weather-platform/prisma-clients/Agregators';
+import { v4 as uuidv4 } from 'uuid';
+import {
+ ApiInternalServerErrorResponse,
+ ApiNotFoundResponse,
+ ApiOkResponse,
+ ApiOperation, ApiProperty,
+ ApiResponse,
+ ApiTags,
+} from '@nestjs/swagger';
+import { AgregatorCreateDTOClass } from "../DTO/AgregatorCreateDTOClass.dto";
+import { AgregatorGetDTOClass } from "../DTO/AgregatorGetDTOClass.dto";
+import { AgregatorUpdateDTOClass } from "../DTO/AgregatorUpdateDTOClass.dto";
+
+export type AgregatorGetDTO = {
+ skip?: number;
+ take?: number;
+ cursor?: Prisma.AgregatorWhereUniqueInput;
+ where?: Prisma.AgregatorWhereInput;
+ orderBy?: Prisma.AgregatorOrderByWithRelationInput;
+};
+
+export type AgregatorCreateDTO = {
+ sendedInDate: string;
+ creatorUUID: string;
+ name: string;
+ lat: string;
+ lng: string;
+ height: number;
+ country: string;
+ city: string;
+ region: string;
+ street: string;
+};
+
+@ApiTags('Agregators')
+@Controller()
+export class AppController {
+ constructor(private readonly appService: AppService) {}
+
+ @ApiOperation({
+ summary: 'Get agregator with Prisma params',
+ })
+ @ApiResponse({ status: 200, type: AgregatorGetDTOClass })
+ @ApiResponse({ status: 500, type: Error })
+ @ApiOkResponse({
+ description: 'Retrieved agregator successfully',
+ type: AgregatorGetDTOClass,
+ })
+ @ApiNotFoundResponse({
+ description: 'No agregator found for this request',
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error',
+ })
+ @Post('get-with-params')
+ async getAgregators(
+ @Body() params: AgregatorGetDTO,
+ ): Promise {
+
+ const { skip, take, cursor, where, orderBy } = params;
+
+ const updatedWhere: Prisma.AgregatorWhereInput = {
+ ...where,
+ isDeleted: false,
+ };
+
+ const res = this.appService.get({
+ skip,
+ take,
+ cursor,
+ where: updatedWhere,
+ orderBy,
+ });
+ return res;
+ }
+
+ @ApiOperation({ summary: 'Create Agregator' })
+ @ApiResponse({ status: 200, type: AgregatorCreateDTOClass })
+ @ApiOkResponse({
+ description: 'Retrieved to create a new agregator successfully',
+ type: AgregatorCreateDTOClass,
+ })
+ @ApiNotFoundResponse({
+ description: 'The agregator is not created successfully',
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error',
+ })
+ @Post('create')
+ async createAgregator(
+ @Body() sectionData: AgregatorCreateDTO,
+ ): Promise {
+
+ const { uuid } = uuidv4();
+
+ const updatedWhere: Prisma.AgregatorCreateInput = {
+ ...sectionData,
+ uuid: uuid,
+ };
+
+ console.log(updatedWhere);
+
+ const agregator = await this.appService.create(updatedWhere);
+ return agregator;
+ }
+
+ @ApiOperation({ summary: 'Update Agregator' })
+ @ApiResponse({ status: 200, type: AgregatorUpdateDTOClass })
+ @ApiOkResponse({
+ description: 'Retrieved agregator successfully',
+ type: AgregatorUpdateDTOClass,
+ })
+ @ApiNotFoundResponse({
+ description: 'No Sensor found for this request',
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error',
+ })
+ @Post('update')
+ async updateAgregator(
+ @Body() params: AgregatorUpdateDTOClass,
+ ): Promise {
+ const { data, where } = params;
+
+ const agregator: Agregator = await this.appService.update({
+ where,
+ data,
+ });
+
+ return agregator;
+ }
+}
diff --git a/weather_platform/apps/agregators-service/src/app/app.module.ts b/weather_platform/apps/agregators-service/src/app/app.module.ts
new file mode 100644
index 0000000..6a9bc16
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/app/app.module.ts
@@ -0,0 +1,11 @@
+import { Module } from '@nestjs/common';
+
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+
+@Module({
+ imports: [],
+ controllers: [AppController],
+ providers: [AppService],
+})
+export class AppModule {}
diff --git a/weather_platform/apps/agregators-service/src/app/app.service.spec.ts b/weather_platform/apps/agregators-service/src/app/app.service.spec.ts
new file mode 100644
index 0000000..42cf0a2
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/app/app.service.spec.ts
@@ -0,0 +1,21 @@
+import { Test } from '@nestjs/testing';
+
+import { AppService } from './app.service';
+
+describe('AppService', () => {
+ let service: AppService;
+
+ beforeAll(async () => {
+ const app = await Test.createTestingModule({
+ providers: [AppService],
+ }).compile();
+
+ service = app.get(AppService);
+ });
+
+ describe('getData', () => {
+ it('should return "Hello API"', () => {
+ expect(service.getData()).toEqual({ message: 'Hello API' });
+ });
+ });
+});
diff --git a/weather_platform/apps/agregators-service/src/app/app.service.ts b/weather_platform/apps/agregators-service/src/app/app.service.ts
new file mode 100644
index 0000000..5d28009
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/app/app.service.ts
@@ -0,0 +1,79 @@
+import { Injectable } from '@nestjs/common';
+import { AgregatorsClient } from '@weather-platform/prisma-clients';
+import { Agregator, Prisma } from "@weather-platform/prisma-clients/Agregators";
+
+@Injectable()
+export class AppService {
+ private prisma: AgregatorsClient;
+ constructor() {
+ this.prisma = new AgregatorsClient()
+ }
+
+ async create(data: Prisma.AgregatorCreateInput): Promise {
+ try {
+ this.prisma.$connect();
+ const Agregator = await this.prisma.agregator.create({
+ data,
+ });
+ this.prisma.$disconnect();
+ return Agregator;
+ } catch (e: any) {
+ console.log(e.code);
+ console.log(e.message);
+ }
+ }
+
+ async get(params: {
+ skip?: number;
+ take?: number;
+ cursor?: Prisma.AgregatorWhereUniqueInput;
+ where?: Prisma.AgregatorWhereInput;
+ orderBy?: Prisma.AgregatorOrderByWithRelationInput;
+ }): Promise {
+ try {
+ const { skip, take, cursor, where, orderBy } = params;
+ return this.prisma.agregator.findMany({
+ skip,
+ take,
+ cursor,
+ where,
+ orderBy,
+ });
+ } catch (e) {
+ console.log(e.code);
+ console.log(e.message);
+ }
+ }
+
+ async update(params: {
+ where: Prisma.AgregatorWhereUniqueInput;
+ data: Prisma.AgregatorUpdateInput;
+ }): Promise {
+ try {
+ const { where, data } = params;
+ return this.prisma.agregator.update({
+ data,
+ where,
+ });
+ } catch (e) {
+ console.log(e.code);
+ console.log(e.message);
+ }
+ }
+
+ async delete(uuid: string): Promise {
+ try {
+ return this.prisma.agregator.update({
+ where: {
+ uuid: uuid,
+ },
+ data: {
+ isDeleted: true,
+ },
+ });
+ } catch (e) {
+ console.log(e.code);
+ console.log(e.message);
+ }
+ }
+}
diff --git a/weather_platform/apps/agregators-service/src/assets/.gitkeep b/weather_platform/apps/agregators-service/src/assets/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/weather_platform/apps/agregators-service/src/main.ts b/weather_platform/apps/agregators-service/src/main.ts
new file mode 100644
index 0000000..fff2934
--- /dev/null
+++ b/weather_platform/apps/agregators-service/src/main.ts
@@ -0,0 +1,34 @@
+/**
+ * This is not a production server yet!
+ * This is only a minimal backend to get started.
+ */
+
+import { Logger } from '@nestjs/common';
+import { NestFactory } from '@nestjs/core';
+
+import { AppModule } from './app/app.module';
+import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
+
+async function bootstrap() {
+ const app = await NestFactory.create(AppModule);
+ const globalPrefix = 'api';
+ app.setGlobalPrefix(globalPrefix);
+ const port = process.env.AGREGATORS_SERVICE_PORT || 3000;
+
+ const config = new DocumentBuilder()
+ .setTitle('CyberGarden Weather Agregators Service')
+ .setDescription('This api need for store agregators data')
+ .setVersion('1.0')
+ .addTag('Agregators Service')
+ .build();
+ const document = SwaggerModule.createDocument(app, config);
+ SwaggerModule.setup('api', app, document);
+
+ app.enableCors();
+ await app.listen(port);
+ Logger.log(
+ `🚀 Agregators Service is running on: http://localhost:${port}/${globalPrefix}`
+ );
+}
+
+bootstrap();
diff --git a/weather_platform/apps/agregators-service/tsconfig.app.json b/weather_platform/apps/agregators-service/tsconfig.app.json
new file mode 100644
index 0000000..a2ce765
--- /dev/null
+++ b/weather_platform/apps/agregators-service/tsconfig.app.json
@@ -0,0 +1,12 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "commonjs",
+ "types": ["node"],
+ "emitDecoratorMetadata": true,
+ "target": "es2021"
+ },
+ "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
+ "include": ["src/**/*.ts"]
+}
diff --git a/weather_platform/apps/agregators-service/tsconfig.json b/weather_platform/apps/agregators-service/tsconfig.json
new file mode 100644
index 0000000..c1e2dd4
--- /dev/null
+++ b/weather_platform/apps/agregators-service/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ],
+ "compilerOptions": {
+ "esModuleInterop": true
+ }
+}
diff --git a/weather_platform/apps/agregators-service/tsconfig.spec.json b/weather_platform/apps/agregators-service/tsconfig.spec.json
new file mode 100644
index 0000000..9b2a121
--- /dev/null
+++ b/weather_platform/apps/agregators-service/tsconfig.spec.json
@@ -0,0 +1,14 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "commonjs",
+ "types": ["jest", "node"]
+ },
+ "include": [
+ "jest.config.ts",
+ "src/**/*.test.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/weather_platform/apps/agregators-service/webpack.config.js b/weather_platform/apps/agregators-service/webpack.config.js
new file mode 100644
index 0000000..81db92b
--- /dev/null
+++ b/weather_platform/apps/agregators-service/webpack.config.js
@@ -0,0 +1,8 @@
+const { composePlugins, withNx } = require('@nx/webpack');
+
+// Nx plugins for webpack.
+module.exports = composePlugins(withNx(), (config) => {
+ // Update the webpack config as needed here.
+ // e.g. `config.plugins.push(new MyPlugin())`
+ return config;
+});
diff --git a/weather_platform/apps/agw-e2e/.eslintrc.json b/weather_platform/apps/agw-e2e/.eslintrc.json
new file mode 100644
index 0000000..9d9c0db
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/weather_platform/apps/agw-e2e/jest.config.ts b/weather_platform/apps/agw-e2e/jest.config.ts
new file mode 100644
index 0000000..89d5d3a
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/jest.config.ts
@@ -0,0 +1,19 @@
+/* eslint-disable */
+export default {
+ displayName: 'agw-e2e',
+ preset: '../../jest.preset.js',
+ globalSetup: '/src/support/global-setup.ts',
+ globalTeardown: '/src/support/global-teardown.ts',
+ setupFiles: ['/src/support/test-setup.ts'],
+ testEnvironment: 'node',
+ transform: {
+ '^.+\\.[tj]s$': [
+ 'ts-jest',
+ {
+ tsconfig: '/tsconfig.spec.json',
+ },
+ ],
+ },
+ moduleFileExtensions: ['ts', 'js', 'html'],
+ coverageDirectory: '../../coverage/agw-e2e',
+};
diff --git a/weather_platform/apps/agw-e2e/project.json b/weather_platform/apps/agw-e2e/project.json
new file mode 100644
index 0000000..dde9b33
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/project.json
@@ -0,0 +1,23 @@
+{
+ "name": "agw-e2e",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "implicitDependencies": ["agw"],
+ "projectType": "application",
+ "targets": {
+ "e2e": {
+ "executor": "@nx/jest:jest",
+ "outputs": ["{workspaceRoot}/coverage/{e2eProjectRoot}"],
+ "options": {
+ "jestConfig": "apps/agw-e2e/jest.config.ts",
+ "passWithNoTests": true
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["apps/agw-e2e/**/*.{js,ts}"]
+ }
+ }
+ }
+}
diff --git a/weather_platform/apps/agw-e2e/src/agw/agw.spec.ts b/weather_platform/apps/agw-e2e/src/agw/agw.spec.ts
new file mode 100644
index 0000000..e8ac2a6
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/src/agw/agw.spec.ts
@@ -0,0 +1,10 @@
+import axios from 'axios';
+
+describe('GET /api', () => {
+ it('should return a message', async () => {
+ const res = await axios.get(`/api`);
+
+ expect(res.status).toBe(200);
+ expect(res.data).toEqual({ message: 'Hello API' });
+ });
+});
diff --git a/weather_platform/apps/agw-e2e/src/support/global-setup.ts b/weather_platform/apps/agw-e2e/src/support/global-setup.ts
new file mode 100644
index 0000000..c1f5144
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/src/support/global-setup.ts
@@ -0,0 +1,10 @@
+/* eslint-disable */
+var __TEARDOWN_MESSAGE__: string;
+
+module.exports = async function () {
+ // Start services that that the app needs to run (e.g. database, docker-compose, etc.).
+ console.log('\nSetting up...\n');
+
+ // Hint: Use `globalThis` to pass variables to global teardown.
+ globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n';
+};
diff --git a/weather_platform/apps/agw-e2e/src/support/global-teardown.ts b/weather_platform/apps/agw-e2e/src/support/global-teardown.ts
new file mode 100644
index 0000000..32ea345
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/src/support/global-teardown.ts
@@ -0,0 +1,7 @@
+/* eslint-disable */
+
+module.exports = async function () {
+ // Put clean up logic here (e.g. stopping services, docker-compose, etc.).
+ // Hint: `globalThis` is shared between setup and teardown.
+ console.log(globalThis.__TEARDOWN_MESSAGE__);
+};
diff --git a/weather_platform/apps/agw-e2e/src/support/test-setup.ts b/weather_platform/apps/agw-e2e/src/support/test-setup.ts
new file mode 100644
index 0000000..07f2870
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/src/support/test-setup.ts
@@ -0,0 +1,10 @@
+/* eslint-disable */
+
+import axios from 'axios';
+
+module.exports = async function () {
+ // Configure axios for tests to use.
+ const host = process.env.HOST ?? 'localhost';
+ const port = process.env.PORT ?? '3000';
+ axios.defaults.baseURL = `http://${host}:${port}`;
+};
diff --git a/weather_platform/apps/agw-e2e/tsconfig.json b/weather_platform/apps/agw-e2e/tsconfig.json
new file mode 100644
index 0000000..ed633e1
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ],
+ "compilerOptions": {
+ "esModuleInterop": true
+ }
+}
diff --git a/weather_platform/apps/agw-e2e/tsconfig.spec.json b/weather_platform/apps/agw-e2e/tsconfig.spec.json
new file mode 100644
index 0000000..d7f9cf2
--- /dev/null
+++ b/weather_platform/apps/agw-e2e/tsconfig.spec.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "commonjs",
+ "types": ["jest", "node"]
+ },
+ "include": ["jest.config.ts", "src/**/*.ts"]
+}
diff --git a/weather_platform/apps/agw/.eslintrc.json b/weather_platform/apps/agw/.eslintrc.json
new file mode 100644
index 0000000..9d9c0db
--- /dev/null
+++ b/weather_platform/apps/agw/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/weather_platform/apps/agw/jest.config.ts b/weather_platform/apps/agw/jest.config.ts
new file mode 100644
index 0000000..84e001c
--- /dev/null
+++ b/weather_platform/apps/agw/jest.config.ts
@@ -0,0 +1,11 @@
+/* eslint-disable */
+export default {
+ displayName: 'agw',
+ preset: '../../jest.preset.js',
+ testEnvironment: 'node',
+ transform: {
+ '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
+ },
+ moduleFileExtensions: ['ts', 'js', 'html'],
+ coverageDirectory: '../../coverage/apps/agw',
+};
diff --git a/weather_platform/apps/agw/project.json b/weather_platform/apps/agw/project.json
new file mode 100644
index 0000000..7036fcc
--- /dev/null
+++ b/weather_platform/apps/agw/project.json
@@ -0,0 +1,64 @@
+{
+ "name": "agw",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "apps/agw/src",
+ "projectType": "application",
+ "targets": {
+ "build": {
+ "executor": "@nx/webpack:webpack",
+ "outputs": ["{options.outputPath}"],
+ "defaultConfiguration": "production",
+ "options": {
+ "target": "node",
+ "compiler": "tsc",
+ "outputPath": "dist/apps/agw",
+ "main": "apps/agw/src/main.ts",
+ "tsConfig": "apps/agw/tsconfig.app.json",
+ "assets": ["apps/agw/src/assets"],
+ "isolatedConfig": true,
+ "webpackConfig": "apps/agw/webpack.config.js"
+ },
+ "configurations": {
+ "development": {},
+ "production": {}
+ }
+ },
+ "serve": {
+ "executor": "@nx/js:node",
+ "defaultConfiguration": "development",
+ "options": {
+ "buildTarget": "agw:build"
+ },
+ "configurations": {
+ "development": {
+ "buildTarget": "agw:build:development"
+ },
+ "production": {
+ "buildTarget": "agw:build:production"
+ }
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["apps/agw/**/*.ts"]
+ }
+ },
+ "test": {
+ "executor": "@nx/jest:jest",
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
+ "options": {
+ "jestConfig": "apps/agw/jest.config.ts",
+ "passWithNoTests": true
+ },
+ "configurations": {
+ "ci": {
+ "ci": true,
+ "codeCoverage": true
+ }
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/weather_platform/apps/agw/src/agregator/agregator.controller.spec.ts b/weather_platform/apps/agw/src/agregator/agregator.controller.spec.ts
new file mode 100644
index 0000000..0631ce4
--- /dev/null
+++ b/weather_platform/apps/agw/src/agregator/agregator.controller.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { AgregatorController } from './agregator.controller';
+
+describe('AgregatorController', () => {
+ let controller: AgregatorController;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ controllers: [AgregatorController],
+ }).compile();
+
+ controller = module.get(AgregatorController);
+ });
+
+ it('should be defined', () => {
+ expect(controller).toBeDefined();
+ });
+});
diff --git a/weather_platform/apps/agw/src/agregator/agregator.controller.ts b/weather_platform/apps/agw/src/agregator/agregator.controller.ts
new file mode 100644
index 0000000..b60a2f1
--- /dev/null
+++ b/weather_platform/apps/agw/src/agregator/agregator.controller.ts
@@ -0,0 +1,89 @@
+import { Body, Controller, Post } from "@nestjs/common";
+import { AgregatorService } from "./agregator.service";
+import {
+ ApiInternalServerErrorResponse,
+ ApiNotFoundResponse,
+ ApiOkResponse,
+ ApiOperation,
+ ApiResponse, ApiTags
+} from "@nestjs/swagger";
+import { Agregator, Prisma } from "@weather-platform/prisma-clients/Agregators";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import { AgregatorCreateDTO, AgregatorGetDTO } from "../../../agregators-service/src/app/app.controller";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import { AgregatorCreateDTOClass } from "../../../agregators-service/src/DTO/AgregatorCreateDTOClass.dto";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import { AgregatorGetDTOClass } from "../../../agregators-service/src/DTO/AgregatorGetDTOClass.dto";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import { AgregatorUpdateDTOClass } from "../../../agregators-service/src/DTO/AgregatorUpdateDTOClass.dto";
+import { Sensor } from "@weather-platform/prisma-clients/Sensors";
+
+@ApiTags('Agregators')
+@Controller('agregator')
+export class AgregatorController {
+ constructor(
+ private readonly agregatorService: AgregatorService,
+ ) {}
+
+ @ApiOperation({
+ summary: 'Get agregator with Prisma params', tags: ['Agregators'], description: 'Get agregator with Prisma params', operationId: 'getWithParams',
+ })
+ @ApiResponse({ status: 200, type: AgregatorGetDTOClass, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, description: 'The found agregator', content: { 'application/json': { schema: { '$ref': '#/components/schemas/AgregatorGetDTOClass' } } }, })
+ @ApiResponse({ status: 500, type: Error, description: 'Internal server error', headers: { 'X-Request-Id': { schema: { type: 'string' } } }, })
+ @ApiOkResponse({
+ description: 'Retrieved agregator successfully',
+ type: AgregatorGetDTOClass, status: 200, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiNotFoundResponse({
+ description: 'No agreagator found for this request', type: Error, status: 404, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error', status: 500, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, type: Error,
+ })
+ @Post('get-with-params')
+ async getAgregators(
+ @Body() params: AgregatorGetDTO,
+ ): Promise | null> {
+ console.log(params);
+ return await this.agregatorService.get(params);
+ }
+
+ @ApiOperation({ summary: 'Create Agregator', description: 'Create Agregator', operationId: 'create', tags: ['Agregators'], })
+ @ApiResponse({ status: 200, type: AgregatorCreateDTOClass, description: 'The found agregator', content: { 'application/json': { schema: { '$ref': '#/components/schemas/AgregatorCreateDTOClass' } } }, })
+ @ApiOkResponse({
+ description: 'Retrieved to create a new agregator successfully',
+ type: AgregatorCreateDTOClass, status: 200, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiNotFoundResponse({
+ description: 'The agregator is not created successfully', type: Error, status: 404, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error', status: 500, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, type: Error,
+ })
+ @Post('create')
+ async createAgregator(
+ @Body() sectionData: AgregatorCreateDTO,
+ ): Promise | null> {
+ console.log(sectionData);
+ return await this.agregatorService.create(sectionData);
+ }
+
+ @ApiOperation({ summary: 'Update Agregator', description: 'Update Agregator', operationId: 'update', tags: ['Agregators'], })
+ @ApiResponse({ status: 200, type: AgregatorUpdateDTOClass })
+ @ApiOkResponse({
+ description: 'Retrieved agregator successfully',
+ type: AgregatorUpdateDTOClass, status: 200, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiNotFoundResponse({
+ description: 'No Sensor found for this request', status: 404, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error', status: 500, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, type: Error,
+ })
+ @Post('update')
+ async updateAgregator(
+ @Body() params: AgregatorUpdateDTOClass,
+ ): Promise | null> {
+ return await this.agregatorService.update(params);
+ }
+}
diff --git a/weather_platform/apps/agw/src/agregator/agregator.module.ts b/weather_platform/apps/agw/src/agregator/agregator.module.ts
new file mode 100644
index 0000000..f084520
--- /dev/null
+++ b/weather_platform/apps/agw/src/agregator/agregator.module.ts
@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { AgregatorService } from './agregator.service';
+import { AgregatorController } from './agregator.controller';
+import { HttpModule } from "@nestjs/axios";
+
+@Module({
+ imports: [HttpModule],
+ providers: [AgregatorService],
+ controllers: [AgregatorController],
+ exports: [AgregatorService],
+})
+export class AgregatorModule {}
diff --git a/weather_platform/apps/agw/src/agregator/agregator.service.spec.ts b/weather_platform/apps/agw/src/agregator/agregator.service.spec.ts
new file mode 100644
index 0000000..bcb5ed2
--- /dev/null
+++ b/weather_platform/apps/agw/src/agregator/agregator.service.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { AgregatorService } from './agregator.service';
+
+describe('AgregatorService', () => {
+ let service: AgregatorService;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ providers: [AgregatorService],
+ }).compile();
+
+ service = module.get(AgregatorService);
+ });
+
+ it('should be defined', () => {
+ expect(service).toBeDefined();
+ });
+});
diff --git a/weather_platform/apps/agw/src/agregator/agregator.service.ts b/weather_platform/apps/agw/src/agregator/agregator.service.ts
new file mode 100644
index 0000000..79ce706
--- /dev/null
+++ b/weather_platform/apps/agw/src/agregator/agregator.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from '@nestjs/common';
+import { HttpService } from "@nestjs/axios";
+import { Agregator, Prisma } from "@weather-platform/prisma-clients/Agregators";
+
+@Injectable()
+export class AgregatorService {
+ constructor(private readonly httpService: HttpService) {}
+
+ // AGREGATOR_SERVICE_URL = (process.env.AGREGATOR_SERVICE_PROTOCOL || 'http://') +
+ // (process.env.AGREGATOR_SERVICE_HOST || 'localhost') + ':' +
+ // (process.env.AGREGATOR_SERVICE_PORT || 3000) +
+ // '/api/';
+
+ AGREGATOR_SERVICE_URL = 'http://localhost:8047/api/';
+
+ async get(data: Prisma.AgregatorFindManyArgs): Promise | null> {
+ try {
+ const response = await this.httpService.post(this.AGREGATOR_SERVICE_URL + 'get-with-params', data).toPromise();
+ return response.data;
+ } catch (error) {
+ console.log(error);
+ throw error;
+ }
+ }
+
+ async create(data: Prisma.AgregatorCreateInput): Promise | null> {
+ // eslint-disable-next-line no-useless-catch
+ try {
+ const response = await this.httpService.post(this.AGREGATOR_SERVICE_URL + 'create', data).toPromise();
+ return response.data;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async update(data: {
+ where: Prisma.AgregatorWhereUniqueInput;
+ data: Prisma.AgregatorUpdateInput;
+ }): Promise | null> {
+ // eslint-disable-next-line no-useless-catch
+ try {
+ const response = await this.httpService.post(this.AGREGATOR_SERVICE_URL + 'update', data).toPromise();
+ return response.data;
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/weather_platform/apps/agw/src/app/app.controller.spec.ts b/weather_platform/apps/agw/src/app/app.controller.spec.ts
new file mode 100644
index 0000000..de8007e
--- /dev/null
+++ b/weather_platform/apps/agw/src/app/app.controller.spec.ts
@@ -0,0 +1,22 @@
+import { Test, TestingModule } from '@nestjs/testing';
+
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+
+describe('AppController', () => {
+ let app: TestingModule;
+
+ beforeAll(async () => {
+ app = await Test.createTestingModule({
+ controllers: [AppController],
+ providers: [AppService],
+ }).compile();
+ });
+
+ describe('getData', () => {
+ it('should return "Hello API"', () => {
+ const appController = app.get(AppController);
+ expect(appController.getData()).toEqual({ message: 'Hello API' });
+ });
+ });
+});
diff --git a/weather_platform/apps/agw/src/app/app.controller.ts b/weather_platform/apps/agw/src/app/app.controller.ts
new file mode 100644
index 0000000..8daf270
--- /dev/null
+++ b/weather_platform/apps/agw/src/app/app.controller.ts
@@ -0,0 +1,36 @@
+import { Controller, Get } from '@nestjs/common';
+
+import { AppService } from './app.service';
+import {AgregatorService} from "../agregator/agregator.service";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import {AgregatorCreateDTOClass} from "../../../agregators-service/src/DTO/AgregatorCreateDTOClass.dto";
+
+@Controller()
+export class AppController {
+ constructor(private readonly appService: AppService,
+ private readonly agregatorService: AgregatorService,
+ ) {}
+
+ @Get('/seed/test/data')
+ setSeedTestData() {
+ const data: AgregatorCreateDTOClass = {
+ sendedInDate: new Date().toISOString(),
+ creatorUUID: "test",
+ name: "agregator 1",
+ lat: "45",
+ lng: "76",
+ height: 1,
+ country: "russia",
+ city: "taganrog",
+ region: "rostov",
+ street: "street",
+ }
+ this.agregatorService.create(data);
+ return "success";
+ }
+
+ @Get()
+ getData() {
+ return this.appService.getData();
+ }
+}
diff --git a/weather_platform/apps/agw/src/app/app.module.ts b/weather_platform/apps/agw/src/app/app.module.ts
new file mode 100644
index 0000000..6761bbc
--- /dev/null
+++ b/weather_platform/apps/agw/src/app/app.module.ts
@@ -0,0 +1,15 @@
+import { Module } from '@nestjs/common';
+
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+import { MeasuresModule } from "../measures/measures.module";
+import { SensorsModule } from "../sensors/sensors.module";
+import { AgregatorModule } from "../agregator/agregator.module";
+import { HttpModule } from "@nestjs/axios";
+
+@Module({
+ imports: [HttpModule, MeasuresModule, AgregatorModule, SensorsModule],
+ controllers: [AppController],
+ providers: [AppService],
+})
+export class AppModule {}
diff --git a/weather_platform/apps/agw/src/app/app.service.spec.ts b/weather_platform/apps/agw/src/app/app.service.spec.ts
new file mode 100644
index 0000000..42cf0a2
--- /dev/null
+++ b/weather_platform/apps/agw/src/app/app.service.spec.ts
@@ -0,0 +1,21 @@
+import { Test } from '@nestjs/testing';
+
+import { AppService } from './app.service';
+
+describe('AppService', () => {
+ let service: AppService;
+
+ beforeAll(async () => {
+ const app = await Test.createTestingModule({
+ providers: [AppService],
+ }).compile();
+
+ service = app.get(AppService);
+ });
+
+ describe('getData', () => {
+ it('should return "Hello API"', () => {
+ expect(service.getData()).toEqual({ message: 'Hello API' });
+ });
+ });
+});
diff --git a/weather_platform/apps/agw/src/app/app.service.ts b/weather_platform/apps/agw/src/app/app.service.ts
new file mode 100644
index 0000000..cd8cede
--- /dev/null
+++ b/weather_platform/apps/agw/src/app/app.service.ts
@@ -0,0 +1,8 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class AppService {
+ getData(): { message: string } {
+ return { message: 'Hello API' };
+ }
+}
diff --git a/weather_platform/apps/agw/src/assets/.gitkeep b/weather_platform/apps/agw/src/assets/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/weather_platform/apps/agw/src/main.ts b/weather_platform/apps/agw/src/main.ts
new file mode 100644
index 0000000..9f172be
--- /dev/null
+++ b/weather_platform/apps/agw/src/main.ts
@@ -0,0 +1,34 @@
+/**
+ * This is not a production server yet!
+ * This is only a minimal backend to get started.
+ */
+
+import { Logger } from '@nestjs/common';
+import { NestFactory } from '@nestjs/core';
+import {DocumentBuilder, SwaggerModule} from "@nestjs/swagger";
+
+import { AppModule } from './app/app.module';
+
+async function bootstrap() {
+ const app = await NestFactory.create(AppModule);
+ const globalPrefix = 'api/v1';
+ app.setGlobalPrefix(globalPrefix);
+
+ const config = new DocumentBuilder()
+ .setTitle('CyberGarden Weather AGW')
+ .setDescription('This api need for control weather processing store platform')
+ .setVersion('1.0')
+ .addTag('AGW Agregators Sensors')
+ .build();
+ const document = SwaggerModule.createDocument(app, config);
+ SwaggerModule.setup('api', app, document);
+
+ const port = process.env.AGW_PORT || 3000;
+ app.enableCors();
+ await app.listen(port);
+ Logger.log(
+ `🚀 AGW is running on: http://localhost:${port}/${globalPrefix}`
+ );
+}
+
+bootstrap();
diff --git a/weather_platform/apps/agw/src/measures/DTO/CreateMeasuresClass.dto.ts b/weather_platform/apps/agw/src/measures/DTO/CreateMeasuresClass.dto.ts
new file mode 100644
index 0000000..54b06cc
--- /dev/null
+++ b/weather_platform/apps/agw/src/measures/DTO/CreateMeasuresClass.dto.ts
@@ -0,0 +1,45 @@
+import { ApiProperty } from "@nestjs/swagger";
+
+type MeasuresData = {
+ uuid: string;
+ agregator_uuid: string;
+ sensor_uuid: string;
+ msg_type: string;
+ msg_value: string;
+ sendedInDate: string;
+ math_time: string;
+}
+
+type MeasuresCreateDTO = {
+ sendedInDate: string;
+ measuresDataList: [MeasuresData];
+}
+
+export class MeasuresDataClass implements MeasuresData {
+ @ApiProperty({description: 'The uuid of the measure'})
+ uuid: string;
+ @ApiProperty({description: 'The agregator uuid'})
+ agregator_uuid: string;
+ @ApiProperty({description: 'The sensor uuid'})
+ sensor_uuid: string;
+ @ApiProperty({description: 'The type of the measure'})
+ msg_type: string;
+ @ApiProperty({description: 'The value of the measure'})
+ msg_value: string;
+ @ApiProperty({description: 'The date when the was sent'})
+ sendedInDate: string;
+ @ApiProperty({description: 'The time that sensor was sent the measure'})
+ math_time: string;
+}
+
+export class MeasuresCreateDTOClass implements MeasuresCreateDTO {
+ @ApiProperty({description: 'The date when the was sent'})
+ sendedInDate: string;
+ @ApiProperty({description: 'The measures data list'})
+ measuresDataList: [MeasuresDataClass];
+}
+
+export class MeasuresCreateSuccessResponse {
+ @ApiProperty({description: 'The measures registred successfully'})
+ code: string;
+}
diff --git a/weather_platform/apps/agw/src/measures/measures.controller.spec.ts b/weather_platform/apps/agw/src/measures/measures.controller.spec.ts
new file mode 100644
index 0000000..4e3a8fb
--- /dev/null
+++ b/weather_platform/apps/agw/src/measures/measures.controller.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { MeasuresController } from './measures.controller';
+
+describe('MeasuresController', () => {
+ let controller: MeasuresController;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ controllers: [MeasuresController],
+ }).compile();
+
+ controller = module.get(MeasuresController);
+ });
+
+ it('should be defined', () => {
+ expect(controller).toBeDefined();
+ });
+});
diff --git a/weather_platform/apps/agw/src/measures/measures.controller.ts b/weather_platform/apps/agw/src/measures/measures.controller.ts
new file mode 100644
index 0000000..eea0443
--- /dev/null
+++ b/weather_platform/apps/agw/src/measures/measures.controller.ts
@@ -0,0 +1,106 @@
+import {Body, Controller, Get, Post} from "@nestjs/common";
+import { MeasureCreateDTOLocalClass, MeasuresService } from "./measures.service";
+import {
+ ApiInternalServerErrorResponse,
+ ApiNotFoundResponse,
+ ApiOkResponse,
+ ApiOperation,
+ ApiResponse
+} from "@nestjs/swagger";
+import {
+ MeasuresCreateDTOClass,
+ MeasuresCreateSuccessResponse,
+ MeasuresDataClass
+} from "./DTO/CreateMeasuresClass.dto";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import {AgregatorGetDTO} from "../../../agregators-service/src/app/app.controller";
+import {Measures} from "@weather-platform/prisma-clients/Measures";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import {MeasureGetDTOClass} from "../../../measures-service/src/DTO/MeasureGetDTOClass.dto";
+
+@Controller('measures')
+export class MeasuresController {
+ constructor(
+ private readonly measuresService: MeasuresService,
+ ) {}
+
+ @ApiOperation({ summary: 'Register Measure', description: 'Create Measure using ASC_WEATHER_RGM', operationId: 'create', tags: ['Measures StorePackages'], })
+ @ApiResponse({ status: 200, type: MeasuresCreateSuccessResponse, description: 'The found measures', })
+ @ApiOkResponse({
+ description: 'Retrieved to register a new measures successfully',
+ type: MeasuresCreateDTOClass, status: 200, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiNotFoundResponse({
+ description: 'The measures is not registered successfully', type: Error, status: 404, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error', status: 500, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, type: Error,
+ })
+ @Post('register')
+ async createMeasuresPack(
+ @Body() packages: MeasuresCreateDTOClass,
+ ): Promise | null> {
+
+ let check = true;
+
+ packages.measuresDataList.map(async (measure: MeasuresDataClass) => {
+ const measure_create_data: MeasureCreateDTOLocalClass = {
+ sendedInDate: measure.sendedInDate,
+ sensor_uuid: measure.sensor_uuid,
+ agregator_uuid: measure.agregator_uuid,
+ time: measure.math_time,
+ type: measure.msg_type,
+ value: measure.msg_value,
+ };
+
+ const res = await this.measuresService.create(measure_create_data);
+
+ console.log(res);
+
+ if (!res) {
+ check = true;
+ }
+ });
+
+ return check ? { code: '200' } : { code: '500' };
+ }
+
+
+
+ @ApiOperation({
+ summary: 'Get measures data with Prisma params', tags: ['Measures'], description: 'Get measures with Prisma params', operationId: 'getWithParams',
+ })
+ @ApiResponse({ status: 200, type: MeasureGetDTOClass, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, description: 'The found measure', })
+ @ApiResponse({ status: 500, type: Error, description: 'Internal server error', headers: { 'X-Request-Id': { schema: { type: 'string' } } }, })
+ @ApiOkResponse({
+ description: 'Retrieved measures successfully',
+ type: MeasureGetDTOClass, status: 200, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiNotFoundResponse({
+ description: 'No measures found for this request', type: Error, status: 404, headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error', status: 500, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, type: Error,
+ })
+ @Post('get-with-params')
+ async getAgregators(
+ @Body() params: MeasureGetDTOClass,
+ ): Promise | null> {
+ return await this.measuresService.get(params);
+ }
+
+
+
+ @Get('get-for-ai')
+ async getAgregatorsForAI() {
+ const res = await this.measuresService.get({});
+ const newArray = res.map(item => ({
+ sensor_uuid: item.sensor_uuid,
+ agregator_uuid: item.agregator_uuid,
+ type: item.type,
+ value: item.value,
+ time: item.time
+ }));
+ return newArray;
+ }
+}
diff --git a/weather_platform/apps/agw/src/measures/measures.module.ts b/weather_platform/apps/agw/src/measures/measures.module.ts
new file mode 100644
index 0000000..cb47a51
--- /dev/null
+++ b/weather_platform/apps/agw/src/measures/measures.module.ts
@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { MeasuresController } from './measures.controller';
+import { MeasuresService } from './measures.service';
+import { HttpModule } from "@nestjs/axios";
+
+@Module({
+ imports: [HttpModule],
+ controllers: [MeasuresController],
+ providers: [MeasuresService],
+ exports: [MeasuresService],
+})
+export class MeasuresModule {}
diff --git a/weather_platform/apps/agw/src/measures/measures.service.spec.ts b/weather_platform/apps/agw/src/measures/measures.service.spec.ts
new file mode 100644
index 0000000..da78a7a
--- /dev/null
+++ b/weather_platform/apps/agw/src/measures/measures.service.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { MeasuresService } from './measures.service';
+
+describe('MeasuresService', () => {
+ let service: MeasuresService;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ providers: [MeasuresService],
+ }).compile();
+
+ service = module.get(MeasuresService);
+ });
+
+ it('should be defined', () => {
+ expect(service).toBeDefined();
+ });
+});
diff --git a/weather_platform/apps/agw/src/measures/measures.service.ts b/weather_platform/apps/agw/src/measures/measures.service.ts
new file mode 100644
index 0000000..1afb94c
--- /dev/null
+++ b/weather_platform/apps/agw/src/measures/measures.service.ts
@@ -0,0 +1,75 @@
+import { Injectable } from '@nestjs/common';
+import { HttpService } from "@nestjs/axios";
+import { Measures, Prisma } from "@weather-platform/prisma-clients/Measures";
+import { ApiProperty } from "@nestjs/swagger";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import { MeasureCreateDTOClass } from "../../../measures-service/src/DTO/MeasureCreateDTOClass.dto";
+
+type MeasureCreateLocalDTO = {
+ sendedInDate: string;
+ sensor_uuid: string;
+ agregator_uuid: string;
+ time: string;
+ type: string;
+ value: string;
+};
+
+export class MeasureCreateDTOLocalClass implements MeasureCreateLocalDTO {
+ @ApiProperty({description: 'The date when the was sent'})
+ sendedInDate: string;
+ @ApiProperty({description: 'The UUID of the creator'})
+ sensor_uuid: string;
+ @ApiProperty({description: 'The agregator uuid'})
+ agregator_uuid: string;
+ @ApiProperty({description: 'The time that sensor was sent the measure'})
+ time: string;
+ @ApiProperty({description: 'The type of the measure'})
+ type: string;
+ @ApiProperty({description: 'The value of the measure'})
+ value: string;
+}
+
+
+@Injectable()
+export class MeasuresService {
+ constructor(private readonly httpService: HttpService) {}
+
+ MEASURES_SERVICE_URL = "http://localhost:8048/api/"
+
+ async get(data: Prisma.MeasuresFindManyArgs): Promise | null> {
+ try {
+ const response = await this.httpService.post(this.MEASURES_SERVICE_URL + 'get-with-params', data).toPromise();
+ return response.data;
+ } catch (error) {
+ console.log(error);
+ throw error;
+ }
+ }
+
+ async create(data: MeasureCreateDTOLocalClass): Promise | null> {
+ // eslint-disable-next-line no-useless-catch
+ try {
+ const updated_data: any = {
+ ...data,
+ };
+ console.log(updated_data);
+ const response = await this.httpService.post(this.MEASURES_SERVICE_URL + 'create', updated_data).toPromise();
+ return response.data;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async update(data: {
+ where: Prisma.MeasuresWhereUniqueInput;
+ data: Prisma.MeasuresUpdateInput;
+ }): Promise | null> {
+ // eslint-disable-next-line no-useless-catch
+ try {
+ const response = await this.httpService.post(this.MEASURES_SERVICE_URL + 'update', data).toPromise();
+ return response.data;
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/weather_platform/apps/agw/src/sensors/sensors.controller.spec.ts b/weather_platform/apps/agw/src/sensors/sensors.controller.spec.ts
new file mode 100644
index 0000000..02a9874
--- /dev/null
+++ b/weather_platform/apps/agw/src/sensors/sensors.controller.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { SensorsController } from './sensors.controller';
+
+describe('SensorsController', () => {
+ let controller: SensorsController;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ controllers: [SensorsController],
+ }).compile();
+
+ controller = module.get(SensorsController);
+ });
+
+ it('should be defined', () => {
+ expect(controller).toBeDefined();
+ });
+});
diff --git a/weather_platform/apps/agw/src/sensors/sensors.controller.ts b/weather_platform/apps/agw/src/sensors/sensors.controller.ts
new file mode 100644
index 0000000..e64c272
--- /dev/null
+++ b/weather_platform/apps/agw/src/sensors/sensors.controller.ts
@@ -0,0 +1,75 @@
+import { Body, Controller, Post } from "@nestjs/common";
+import {
+ ApiInternalServerErrorResponse,
+ ApiNotFoundResponse,
+ ApiOkResponse,
+ ApiOperation,
+ ApiResponse,
+ ApiTags
+} from "@nestjs/swagger";
+import { SensorsService } from "./sensors.service";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import { SensorGetDTOClass } from "../../../sensors-service/src/DTO/SensorGetDTOClass.dto";
+import { Prisma, Sensor } from "@weather-platform/prisma-clients/Sensors";
+// eslint-disable-next-line @nx/enforce-module-boundaries
+import { SensorCreateDTOClass } from "../../../sensors-service/src/DTO/SensorCreateDTOClass.dto";
+
+@ApiTags('Sensors')
+@Controller('sensors')
+export class SensorsController {
+ constructor(
+ private readonly sensorsService: SensorsService,
+ ) {}
+
+ @ApiOperation({ summary: 'Get sensor with Prisma params',
+ description: 'Get sensor with Prisma params',
+ operationId: 'getWithParams',
+ tags: ['Sensors'] })
+ @ApiResponse(
+ { status: 200,
+ type: SensorGetDTOClass,
+ description: 'The found sensor',
+ content: { 'application/json': { schema: { '$ref': '#/components/schemas/SensorGetDTOClass' } } },
+ headers: { 'X-Request-Id': { schema: { type: 'string' } } }
+ })
+ @ApiResponse({ status: 500, type: Error })
+ @ApiOkResponse({
+ description: 'Retrieved sensor successfully',
+ type: SensorGetDTOClass,
+ headers: { 'X-Request-Id': { schema: { type: 'string' } } },
+ status: 200
+ })
+ @ApiNotFoundResponse({
+ description: 'No sensor found for this request', status: 404, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, type: Error,
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error', status: 500, headers: { 'X-Request-Id': { schema: { type: 'string' } } }, type: Error,
+ })
+ @Post('get-with-params')
+ async getSensors(
+ @Body() params: SensorGetDTOClass,
+ ): Promise | null> {
+ return await this.sensorsService.get(params);
+ }
+
+
+
+ @ApiOperation({ summary: 'Create Sensor' })
+ @ApiResponse({ status: 200, type: SensorCreateDTOClass })
+ @ApiOkResponse({
+ description: 'Retrieved to create a new sensor successfully',
+ type: SensorCreateDTOClass,
+ })
+ @ApiNotFoundResponse({
+ description: 'The sensor is not created successfully',
+ })
+ @ApiInternalServerErrorResponse({
+ description: 'Internal server error',
+ })
+ @Post('create')
+ async createMatrix(
+ @Body() sectionData: SensorCreateDTOClass,
+ ): Promise | null> {
+ return await this.sensorsService.create(sectionData);
+ }
+}
diff --git a/weather_platform/apps/agw/src/sensors/sensors.module.ts b/weather_platform/apps/agw/src/sensors/sensors.module.ts
new file mode 100644
index 0000000..3572baf
--- /dev/null
+++ b/weather_platform/apps/agw/src/sensors/sensors.module.ts
@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { SensorsService } from './sensors.service';
+import { SensorsController } from './sensors.controller';
+import { HttpModule } from "@nestjs/axios";
+
+@Module({
+ imports: [HttpModule],
+ providers: [SensorsService],
+ controllers: [SensorsController],
+ exports: [SensorsService],
+})
+export class SensorsModule {}
diff --git a/weather_platform/apps/agw/src/sensors/sensors.service.spec.ts b/weather_platform/apps/agw/src/sensors/sensors.service.spec.ts
new file mode 100644
index 0000000..6e1fd15
--- /dev/null
+++ b/weather_platform/apps/agw/src/sensors/sensors.service.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { SensorsService } from './sensors.service';
+
+describe('SensorsService', () => {
+ let service: SensorsService;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ providers: [SensorsService],
+ }).compile();
+
+ service = module.get(SensorsService);
+ });
+
+ it('should be defined', () => {
+ expect(service).toBeDefined();
+ });
+});
diff --git a/weather_platform/apps/agw/src/sensors/sensors.service.ts b/weather_platform/apps/agw/src/sensors/sensors.service.ts
new file mode 100644
index 0000000..18884ce
--- /dev/null
+++ b/weather_platform/apps/agw/src/sensors/sensors.service.ts
@@ -0,0 +1,43 @@
+import { Injectable } from '@nestjs/common';
+import { HttpService } from "@nestjs/axios";
+import { Sensor, Prisma } from "@weather-platform/prisma-clients/Sensors";
+
+@Injectable()
+export class SensorsService {
+ constructor(private readonly httpService: HttpService) {}
+
+ SENSORS_SERVICE_URL = 'http://localhost:8046/api/';
+
+ async get(data: Prisma.SensorFindManyArgs): Promise | null> {
+ try {
+ const response = await this.httpService.post(this.SENSORS_SERVICE_URL + 'get-with-params', data).toPromise();
+ return response.data;
+ } catch (error) {
+ console.log(error);
+ throw error;
+ }
+ }
+
+ async create(data: Prisma.SensorCreateInput): Promise | null> {
+ // eslint-disable-next-line no-useless-catch
+ try {
+ const response = await this.httpService.post(this.SENSORS_SERVICE_URL + 'create', data).toPromise();
+ return response.data;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async update(data: {
+ where: Prisma.SensorWhereUniqueInput;
+ data: Prisma.SensorUpdateInput;
+ }): Promise | null> {
+ // eslint-disable-next-line no-useless-catch
+ try {
+ const response = await this.httpService.post(this.SENSORS_SERVICE_URL + 'update', data).toPromise();
+ return response.data;
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/weather_platform/apps/agw/tsconfig.app.json b/weather_platform/apps/agw/tsconfig.app.json
new file mode 100644
index 0000000..a2ce765
--- /dev/null
+++ b/weather_platform/apps/agw/tsconfig.app.json
@@ -0,0 +1,12 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "commonjs",
+ "types": ["node"],
+ "emitDecoratorMetadata": true,
+ "target": "es2021"
+ },
+ "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
+ "include": ["src/**/*.ts"]
+}
diff --git a/weather_platform/apps/agw/tsconfig.json b/weather_platform/apps/agw/tsconfig.json
new file mode 100644
index 0000000..c1e2dd4
--- /dev/null
+++ b/weather_platform/apps/agw/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ],
+ "compilerOptions": {
+ "esModuleInterop": true
+ }
+}
diff --git a/weather_platform/apps/agw/tsconfig.spec.json b/weather_platform/apps/agw/tsconfig.spec.json
new file mode 100644
index 0000000..9b2a121
--- /dev/null
+++ b/weather_platform/apps/agw/tsconfig.spec.json
@@ -0,0 +1,14 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "commonjs",
+ "types": ["jest", "node"]
+ },
+ "include": [
+ "jest.config.ts",
+ "src/**/*.test.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/weather_platform/apps/agw/webpack.config.js b/weather_platform/apps/agw/webpack.config.js
new file mode 100644
index 0000000..81db92b
--- /dev/null
+++ b/weather_platform/apps/agw/webpack.config.js
@@ -0,0 +1,8 @@
+const { composePlugins, withNx } = require('@nx/webpack');
+
+// Nx plugins for webpack.
+module.exports = composePlugins(withNx(), (config) => {
+ // Update the webpack config as needed here.
+ // e.g. `config.plugins.push(new MyPlugin())`
+ return config;
+});
diff --git a/weather_platform/apps/crud-e2e/.eslintrc.json b/weather_platform/apps/crud-e2e/.eslintrc.json
new file mode 100644
index 0000000..696cb8b
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/.eslintrc.json
@@ -0,0 +1,10 @@
+{
+ "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/weather_platform/apps/crud-e2e/cypress.config.ts b/weather_platform/apps/crud-e2e/cypress.config.ts
new file mode 100644
index 0000000..a45b4fd
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/cypress.config.ts
@@ -0,0 +1,8 @@
+import { defineConfig } from 'cypress';
+import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
+
+export default defineConfig({
+ e2e: nxE2EPreset(__dirname, {
+ bundler: 'vite',
+ }),
+});
diff --git a/weather_platform/apps/crud-e2e/project.json b/weather_platform/apps/crud-e2e/project.json
new file mode 100644
index 0000000..0d0c310
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/project.json
@@ -0,0 +1,33 @@
+{
+ "name": "crud-e2e",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "apps/crud-e2e/src",
+ "projectType": "application",
+ "targets": {
+ "e2e": {
+ "executor": "@nx/cypress:cypress",
+ "options": {
+ "cypressConfig": "apps/crud-e2e/cypress.config.ts",
+ "devServerTarget": "crud:serve:development",
+ "testingType": "e2e"
+ },
+ "configurations": {
+ "production": {
+ "devServerTarget": "crud:serve:production"
+ },
+ "ci": {
+ "devServerTarget": "crud:serve-static"
+ }
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["apps/crud-e2e/**/*.{js,ts}"]
+ }
+ }
+ },
+ "tags": [],
+ "implicitDependencies": ["crud"]
+}
diff --git a/weather_platform/apps/crud-e2e/src/e2e/app.cy.ts b/weather_platform/apps/crud-e2e/src/e2e/app.cy.ts
new file mode 100644
index 0000000..70d7f37
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/src/e2e/app.cy.ts
@@ -0,0 +1,13 @@
+import { getGreeting } from '../support/app.po';
+
+describe('crud', () => {
+ beforeEach(() => cy.visit('/'));
+
+ it('should display welcome message', () => {
+ // Custom command example, see `../support/commands.ts` file
+ cy.login('my-email@something.com', 'myPassword');
+
+ // Function helper example, see `../support/app.po.ts` file
+ getGreeting().contains('Welcome crud');
+ });
+});
diff --git a/weather_platform/apps/crud-e2e/src/fixtures/example.json b/weather_platform/apps/crud-e2e/src/fixtures/example.json
new file mode 100644
index 0000000..294cbed
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/src/fixtures/example.json
@@ -0,0 +1,4 @@
+{
+ "name": "Using fixtures to represent data",
+ "email": "hello@cypress.io"
+}
diff --git a/weather_platform/apps/crud-e2e/src/support/app.po.ts b/weather_platform/apps/crud-e2e/src/support/app.po.ts
new file mode 100644
index 0000000..3293424
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/src/support/app.po.ts
@@ -0,0 +1 @@
+export const getGreeting = () => cy.get('h1');
diff --git a/weather_platform/apps/crud-e2e/src/support/commands.ts b/weather_platform/apps/crud-e2e/src/support/commands.ts
new file mode 100644
index 0000000..310f1fa
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/src/support/commands.ts
@@ -0,0 +1,33 @@
+// ***********************************************
+// This example commands.js shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+
+// eslint-disable-next-line @typescript-eslint/no-namespace
+declare namespace Cypress {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ interface Chainable {
+ login(email: string, password: string): void;
+ }
+}
+//
+// -- This is a parent command --
+Cypress.Commands.add('login', (email, password) => {
+ console.log('Custom command example: Login', email, password);
+});
+//
+// -- This is a child command --
+// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This will overwrite an existing command --
+// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
diff --git a/weather_platform/apps/crud-e2e/src/support/e2e.ts b/weather_platform/apps/crud-e2e/src/support/e2e.ts
new file mode 100644
index 0000000..3d469a6
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/src/support/e2e.ts
@@ -0,0 +1,17 @@
+// ***********************************************************
+// This example support/index.js is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands';
diff --git a/weather_platform/apps/crud-e2e/tsconfig.json b/weather_platform/apps/crud-e2e/tsconfig.json
new file mode 100644
index 0000000..cc509a7
--- /dev/null
+++ b/weather_platform/apps/crud-e2e/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "sourceMap": false,
+ "outDir": "../../dist/out-tsc",
+ "allowJs": true,
+ "types": ["cypress", "node"]
+ },
+ "include": ["src/**/*.ts", "src/**/*.js", "cypress.config.ts"]
+}
diff --git a/weather_platform/apps/crud/.eslintrc.json b/weather_platform/apps/crud/.eslintrc.json
new file mode 100644
index 0000000..a39ac5d
--- /dev/null
+++ b/weather_platform/apps/crud/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["plugin:@nx/react", "../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/weather_platform/apps/crud/index.html b/weather_platform/apps/crud/index.html
new file mode 100644
index 0000000..f4a96ee
--- /dev/null
+++ b/weather_platform/apps/crud/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Crud
+
+
+
+
+
+
+
+
+
+
+
diff --git a/weather_platform/apps/crud/postcss.config.js b/weather_platform/apps/crud/postcss.config.js
new file mode 100644
index 0000000..c72626d
--- /dev/null
+++ b/weather_platform/apps/crud/postcss.config.js
@@ -0,0 +1,15 @@
+const { join } = require('path');
+
+// Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build
+// option from your application's configuration (i.e. project.json).
+//
+// See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries
+
+module.exports = {
+ plugins: {
+ tailwindcss: {
+ config: join(__dirname, 'tailwind.config.js'),
+ },
+ autoprefixer: {},
+ },
+};
diff --git a/weather_platform/apps/crud/project.json b/weather_platform/apps/crud/project.json
new file mode 100644
index 0000000..f9813d2
--- /dev/null
+++ b/weather_platform/apps/crud/project.json
@@ -0,0 +1,79 @@
+{
+ "name": "crud",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "apps/crud/src",
+ "projectType": "application",
+ "targets": {
+ "build": {
+ "executor": "@nx/vite:build",
+ "outputs": ["{options.outputPath}"],
+ "defaultConfiguration": "production",
+ "options": {
+ "outputPath": "dist/apps/crud"
+ },
+ "configurations": {
+ "development": {
+ "mode": "development"
+ },
+ "production": {
+ "mode": "production"
+ }
+ }
+ },
+ "serve": {
+ "executor": "@nx/vite:dev-server",
+ "defaultConfiguration": "development",
+ "options": {
+ "buildTarget": "crud:build",
+ "proxyConfig": "apps/crud/proxy.conf.json"
+ },
+ "configurations": {
+ "development": {
+ "buildTarget": "crud:build:development",
+ "hmr": true
+ },
+ "production": {
+ "buildTarget": "crud:build:production",
+ "hmr": false
+ }
+ }
+ },
+ "preview": {
+ "executor": "@nx/vite:preview-server",
+ "defaultConfiguration": "development",
+ "options": {
+ "buildTarget": "crud:build"
+ },
+ "configurations": {
+ "development": {
+ "buildTarget": "crud:build:development"
+ },
+ "production": {
+ "buildTarget": "crud:build:production"
+ }
+ }
+ },
+ "test": {
+ "executor": "@nx/vite:test",
+ "outputs": ["{options.reportsDirectory}"],
+ "options": {
+ "passWithNoTests": true,
+ "reportsDirectory": "../../coverage/apps/crud"
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["apps/crud/**/*.{ts,tsx,js,jsx}"]
+ }
+ },
+ "serve-static": {
+ "executor": "@nx/web:file-server",
+ "options": {
+ "buildTarget": "crud:build"
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/weather_platform/apps/crud/proxy.conf.json b/weather_platform/apps/crud/proxy.conf.json
new file mode 100644
index 0000000..98ef58c
--- /dev/null
+++ b/weather_platform/apps/crud/proxy.conf.json
@@ -0,0 +1,6 @@
+{
+ "/api": {
+ "target": "http://localhost:8045",
+ "secure": false
+ }
+}
diff --git a/weather_platform/apps/crud/public/favicon.ico b/weather_platform/apps/crud/public/favicon.ico
new file mode 100644
index 0000000..317ebcb
Binary files /dev/null and b/weather_platform/apps/crud/public/favicon.ico differ
diff --git a/weather_platform/apps/crud/src/app/app.module.scss b/weather_platform/apps/crud/src/app/app.module.scss
new file mode 100644
index 0000000..7b88fba
--- /dev/null
+++ b/weather_platform/apps/crud/src/app/app.module.scss
@@ -0,0 +1 @@
+/* Your styles goes here. */
diff --git a/weather_platform/apps/crud/src/app/app.spec.tsx b/weather_platform/apps/crud/src/app/app.spec.tsx
new file mode 100644
index 0000000..8bb4e39
--- /dev/null
+++ b/weather_platform/apps/crud/src/app/app.spec.tsx
@@ -0,0 +1,15 @@
+import { render } from '@testing-library/react';
+
+import App from './app';
+
+describe('App', () => {
+ it('should render successfully', () => {
+ const { baseElement } = render();
+ expect(baseElement).toBeTruthy();
+ });
+
+ it('should have a greeting as the title', () => {
+ const { getByText } = render();
+ expect(getByText(/Welcome crud/gi)).toBeTruthy();
+ });
+});
diff --git a/weather_platform/apps/crud/src/app/app.tsx b/weather_platform/apps/crud/src/app/app.tsx
new file mode 100644
index 0000000..fbb7f1c
--- /dev/null
+++ b/weather_platform/apps/crud/src/app/app.tsx
@@ -0,0 +1,20 @@
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import styles from './app.module.scss';
+import {BrowserRouter as Router, Route, Routes} from 'react-router-dom';
+
+import NxWelcome from './nx-welcome';
+import {AgregatorsPage, Dashboard, SensorPage} from "@weather-platform/pages";
+
+export function App() {
+ return (
+
+
+ } />
+ } />
+ } />
+
+
+ );
+}
+
+export default App;
diff --git a/weather_platform/apps/crud/src/app/nx-welcome.tsx b/weather_platform/apps/crud/src/app/nx-welcome.tsx
new file mode 100644
index 0000000..f0cd657
--- /dev/null
+++ b/weather_platform/apps/crud/src/app/nx-welcome.tsx
@@ -0,0 +1,845 @@
+/*
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ This is a starter component and can be deleted.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ Delete this file and get started with your project!
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
+export function NxWelcome({ title }: { title: string }) {
+ return (
+ <>
+