Merge remote-tracking branch 'origin/main'

pull/1/head
o.likhogub 1 year ago
commit 265da5aa19

BIN
.DS_Store vendored

Binary file not shown.

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CsvFileAttributes">
<option name="attributeMap">
<map>
<entry key="/weather_platform/apps/py-multy-agent-interpreter/examples/files/extracted_data.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
</map>
</option>
</component>
</project>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="ASK" />
<option name="description" value="" />
</component>
</project>

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="6cb4dca5-d93c-4b61-8425-4ba8b7c9b2ff" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/weather_platform/apps/py-tg-bot-weather-agent/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/weather_platform/apps/py-tg-bot-weather-agent/main.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="TypeScript File" />
</list>
</option>
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectId" id="2WQSJMtSztUrKlia6nQzkrUUqV2" />
<component name="ProjectLevelVcsManager">
<ConfirmationsSetting value="1" id="Add" />
</component>
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"WebServerToolWindowFactoryState": "false",
"last_opened_file_path": "/Users/darius/Desktop/ASC/CyberGarden/kempt-kinkajou/weather_platform/apps",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"ts.external.directory.path": "/Users/darius/Desktop/ASC/CyberGarden/kempt-kinkajou/weather_platform/node_modules/typescript/lib",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/weather_platform/apps" />
<recent name="$PROJECT_DIR$/weather_platform/ui-modules/src/lib/navbar" />
</key>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="6cb4dca5-d93c-4b61-8425-4ba8b7c9b2ff" name="Changes" comment="" />
<created>1696663237589</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1696663237589</updated>
<workItem from="1696663238626" duration="5030000" />
<workItem from="1696670312018" duration="20846000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
</project>

@ -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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 KiB

@ -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

@ -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

@ -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

@ -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": {}
}
]
}

@ -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

@ -0,0 +1,3 @@
# Add files here to ignore them from prettier formatting
/dist
/coverage

@ -0,0 +1,3 @@
{
"singleQuote": true
}

@ -0,0 +1,132 @@
<div style="display: flex; flex-direction: row; align-items: center; justify-content: center;">
<img style="border-radius: 1em; align-self: center;" src="https://git.djft.ru/avatars/9f5343fc9d97fdb7f08afabf3c472334?size=420" width="45">
<h1 style="text-align: center; margin-left: 10px; margin-top: 2px;">K-Lab | Cyber Garden Weather</h1>
</div>
<div style="display: flex; align-items: center; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">
<span style="font-size: 20px; margin-right: 10px;"></span>
<span style="font-size: 16px;">
Processing Platform monorepo
</span>
</div>
## Описание
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

@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

@ -0,0 +1,19 @@
/* eslint-disable */
export default {
displayName: 'agregators-service-e2e',
preset: '../../jest.preset.js',
globalSetup: '<rootDir>/src/support/global-setup.ts',
globalTeardown: '<rootDir>/src/support/global-teardown.ts',
setupFiles: ['<rootDir>/src/support/test-setup.ts'],
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': [
'ts-jest',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
},
],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/agregators-service-e2e',
};

@ -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}"]
}
}
}
}

@ -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' });
});
});

@ -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';
};

@ -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__);
};

@ -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}`;
};

@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"esModuleInterop": true
}
}

@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": ["jest.config.ts", "src/**/*.ts"]
}

@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

@ -0,0 +1,11 @@
/* eslint-disable */
export default {
displayName: 'agregators-service',
preset: '../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/apps/agregators-service',
};

@ -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": []
}

@ -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;
}

@ -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;
}

@ -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;
}

@ -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>(AppController);
expect(appController.getData()).toEqual({ message: 'Hello API' });
});
});
});

@ -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<Agregator[]> {
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<Agregator> {
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<Agregator> {
const { data, where } = params;
const agregator: Agregator = await this.appService.update({
where,
data,
});
return agregator;
}
}

@ -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 {}

@ -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>(AppService);
});
describe('getData', () => {
it('should return "Hello API"', () => {
expect(service.getData()).toEqual({ message: 'Hello API' });
});
});
});

@ -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<Agregator> {
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<Agregator[]> {
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<Agregator> {
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<Agregator> {
try {
return this.prisma.agregator.update({
where: {
uuid: uuid,
},
data: {
isDeleted: true,
},
});
} catch (e) {
console.log(e.code);
console.log(e.message);
}
}
}

@ -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();

@ -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"]
}

@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"esModuleInterop": true
}
}

@ -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"
]
}

@ -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;
});

@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

@ -0,0 +1,19 @@
/* eslint-disable */
export default {
displayName: 'agw-e2e',
preset: '../../jest.preset.js',
globalSetup: '<rootDir>/src/support/global-setup.ts',
globalTeardown: '<rootDir>/src/support/global-teardown.ts',
setupFiles: ['<rootDir>/src/support/test-setup.ts'],
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': [
'ts-jest',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
},
],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/agw-e2e',
};

@ -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}"]
}
}
}
}

@ -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' });
});
});

@ -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';
};

@ -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__);
};

@ -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}`;
};

@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"esModuleInterop": true
}
}

@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": ["jest.config.ts", "src/**/*.ts"]
}

@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

@ -0,0 +1,11 @@
/* eslint-disable */
export default {
displayName: 'agw',
preset: '../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/apps/agw',
};

@ -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": []
}

@ -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>(AgregatorController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

@ -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<Partial<Agregator[]> | 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<Partial<Agregator> | 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<Partial<Agregator> | null> {
return await this.agregatorService.update(params);
}
}

@ -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 {}

@ -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>(AgregatorService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

@ -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<Partial<Agregator[]> | 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<Partial<Agregator> | 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<Partial<Agregator> | 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;
}
}
}

@ -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>(AppController);
expect(appController.getData()).toEqual({ message: 'Hello API' });
});
});
});

@ -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();
}
}

@ -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 {}

@ -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>(AppService);
});
describe('getData', () => {
it('should return "Hello API"', () => {
expect(service.getData()).toEqual({ message: 'Hello API' });
});
});
});

@ -0,0 +1,8 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getData(): { message: string } {
return { message: 'Hello API' };
}
}

@ -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();

@ -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;
}

@ -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>(MeasuresController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

@ -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<Partial<MeasuresCreateSuccessResponse> | 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<Partial<Measures[]> | 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;
}
}

@ -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 {}

@ -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>(MeasuresService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

@ -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<Partial<Measures[]> | 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<Partial<Measures> | 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<Partial<Measures> | 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;
}
}
}

@ -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>(SensorsController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

@ -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<Partial<Sensor[]> | 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<Partial<Sensor> | null> {
return await this.sensorsService.create(sectionData);
}
}

@ -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 {}

@ -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>(SensorsService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

@ -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<Partial<Sensor[]> | 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<Partial<Sensor> | 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<Partial<Sensor> | 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;
}
}
}

@ -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"]
}

@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"esModuleInterop": true
}
}

@ -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"
]
}

@ -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;
});

@ -0,0 +1,10 @@
{
"extends": ["plugin:cypress/recommended", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
}
]
}

@ -0,0 +1,8 @@
import { defineConfig } from 'cypress';
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
export default defineConfig({
e2e: nxE2EPreset(__dirname, {
bundler: 'vite',
}),
});

@ -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"]
}

@ -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');
});
});

@ -0,0 +1,4 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io"
}

@ -0,0 +1 @@
export const getGreeting = () => cy.get('h1');

@ -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<Subject> {
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) => { ... })

@ -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';

@ -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"]
}

@ -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": {}
}
]
}

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Crud</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="stylesheet" href="/src/styles.scss" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

@ -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: {},
},
};

@ -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": []
}

@ -0,0 +1,6 @@
{
"/api": {
"target": "http://localhost:8045",
"secure": false
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save