add: weather platform alpha version

pull/1/head
Artem-Darius Weber 1 year ago
parent cfeb5e7de2
commit 5e7d7766c1

BIN
.DS_Store vendored

Binary file not shown.

5
.idea/.gitignore vendored

@ -1,5 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

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

@ -1,6 +0,0 @@
<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>

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/kempt-kinkajou.iml" filepath="$PROJECT_DIR$/.idea/kempt-kinkajou.iml" />
</modules>
</component>
</project>

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

@ -1 +0,0 @@
Subproject commit 4f8ed19d5fd78029f3513a15381dbb8ab047f732

@ -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,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,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,167 @@
<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
cd apps/matrix-events-registry/docker && docker-compose up -d
```
```bash
cd apps/matrix-registry/docker && docker-compose up -d
```
```bash
cd apps/labs/docker && docker-compose up -d
```
```bash
cd apps/labs/docker && docker-compose up -d
```
[Matrix Registry Service](/apps/matrix-registry)
```bash
prisma db push --schema="./libs/prisma-clients/matrix-device-registry/prisma/schema.prisma"
```
```bash
prisma generate --schema="./libs/prisma-clients/matrix-device-registry/prisma/schema.prisma"
```
[Matrix Events Registry Service](/apps/matrix-events-registry)
```bash
prisma db push --schema="./libs/prisma-clients/matrix-events/prisma/schema.prisma"
```
```bash
prisma generate --schema="./libs/prisma-clients/matrix-events/prisma/schema.prisma"
```
```bash
prisma db push --schema="./libs/prisma-clients/labs/prisma/schema.prisma"
```
```bash
prisma generate --schema="./libs/prisma-clients/labs/prisma/schema.prisma"
```
```bash
nx run py-multy-agent-interpreter:serve
```
Run all services:
```bash
nx run-many --parallel --target=serve --projects=frontend,agw,matrix-registry,matrix-events-registry,labs
```
## Структура репозитория
Репозиторий содержит следующие основные каталоги и файлы:
- `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'})
let: number;
@ApiProperty({description: 'The agregator longitude'})
lng: number;
@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,134 @@
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;
let: number;
lng: number;
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,
};
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(
`🚀 Application 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,87 @@
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> {
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> {
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,46 @@
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/';
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,13 @@
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@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(
`🚀 Application 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,60 @@
import { Body, Controller, 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";
@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);
if (!res) {
check = true;
}
});
return check ? { code: '200' } : { code: '500' };
}
}

@ -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,78 @@
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 = (process.env.MEASURES_SERVICE_PROTOCOL || 'http://') +
(process.env.MEASURES_SERVICE_HOST || 'localhost') + ':' +
(process.env.MEASURES_SERVICE_PORT || 3000) +
'/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: MeasureCreateDTOClass = {
...data,
creatorUUID: '1',
}
const response = await this.httpService.post(this.MEASURES_SERVICE_URL + 'create', 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,46 @@
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 = (process.env.SENSORS_SERVICE_PROTOCOL || 'http://') +
(process.env.SENSORS_SERVICE_HOST || 'localhost') + ':' +
(process.env.SENSORS_SERVICE_PORT || 3000) +
'/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:3000",
"secure": false
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -0,0 +1,15 @@
import { render } from '@testing-library/react';
import App from './app';
describe('App', () => {
it('should render successfully', () => {
const { baseElement } = render(<App />);
expect(baseElement).toBeTruthy();
});
it('should have a greeting as the title', () => {
const { getByText } = render(<App />);
expect(getByText(/Welcome crud/gi)).toBeTruthy();
});
});

@ -0,0 +1,14 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import styles from './app.module.scss';
import NxWelcome from './nx-welcome';
export function App() {
return (
<div>
<NxWelcome title="crud" />
</div>
);
}
export default App;

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

Loading…
Cancel
Save