Backend Development
Node.js, Express, MariaDB, PrismaORM, Zod, Redis, GraphQL Client
Router: The router is responsible for managing the incoming requests and determining which route should handle them based on the request's URL and HTTP method. It acts as a traffic director, effectively routing requests to the designated controller for further processing.
Middleware: Middleware functions play an important role in the route handling process. Middleware intercepts the incoming request before it reaches the controller and performs pre-processing tasks such as authentication, logging, data parsing, or handling CORS (Cross-Origin Resource Sharing) issues. Middleware can be applied globally to all routes or selectively to specific routes, providing a flexible way to execute common tasks.
Route (HTTP Methods): Routes are the specific endpoints defined within the router. They are associated with different HTTP methods, such as POST, GET, PUT, DELETE, etc. Each HTTP method represents a specific action that the client wants to perform on the server.
Controller: The controller is the intermediary layer that receives the request from the router after the route selection. It contains the application's business logic and is responsible for processing the data received from the client through the route. The controller communicates with the service layer to perform various operations, such as data validation, retrieval, manipulation, and business-specific tasks.
Service: The service layer handles data manipulation, database interactions, and external API calls. It abstracts the data access logic from the controller, providing a clean and modular interface for the controller to perform its tasks. The service layer ensures separation of concerns, making the codebase more organized and maintainable.
Configuring the backend:
Constants: From there, you can configure your environment variables, links, urls, etc
Located in: src/config/constants.tsRouter: Is configured in main index.ts for the app where we refering the base route towards routes
Located in: src/index.tsapp.use("/", routes)
Routes: There you can setup your route and refer to your controller related to devices.
Located in: src/routes/routes.tsrouter.get('/devices', getDevices);
Controllers: There you can create logic for your route and refer to the service you want to use to process the data for your controller.
Located in: src/controllers/Services: Here you can add service for your controller and data manipulation
Located in: src/services/Types: The place where you can extend your request/response context or any type of data/interface/type.
Example: We extended Express Request to have Prisma inside each request.
Located in: src/types/Utils: Is the place where you can place your utils functions, such as auth, token functions, etc
Located in: src/utils/Zod-schema: The place where you can define the data validation schema using ZOD library
Located in: src/zod-schema/Interfaces: The place where you can define your global interfaces/types/enums etc for TypeScript
Located in: src/interfaces/Helpers: The place where you can define your helper functions you using globally
Located in: src/helpers/Middlewares: The place where you can define your intercepring logic for each request, mostly used to upload files, validate token, cookies and everything related to Request context
Located in: src/middlewares/Deploy-builder: The place we used to place the logic to help us export configured backend for deployment in order to prevent mistakes by manually configure docker related files and deploy configuration.
Usage: npm run deploy-config will start config builder and export docker-compose.yml, Dockerfile, runSettings.json in the root of the project.
Configuring deploy-config can be done by modifying script part inside package json:"deploy-config": "set APP_NAME=siconapp-template && set VENDOR=siconeco && ts-node src/deploy-builder/index.ts"
where the APP_NAME is your docker container name you want to create, VENDOR is publisher related to internal environment name in the SICON OS.
Note: If you want to modify docker instructions, add or remove something, edit ts files in the deploy-builder directory. Make sure you escaped problematic symbols to satisfy the TypeScript engine.
Located in: src/deploy-builder/Config-wizzard: The place we used to place the logic to help us export configured backend for deployment in order to prevent mistakes by manually configure docker related files and deploy configuration.
Project configuration: After you enter npm run config config wizzard builder will start and ask what do you want to be configured. Accepted answers are y or yes, and at the end, wizzard will export next files:
docker-compose.yml, Dockerfile, runSettings.json in the root of the project.
Note: If you want to modify docker instructions, add or remove something, edit mjs files in the config-wizzard directory.
Located in: src/config-wizzard/
Configuring Prisma
Prisma: Prisma directory is in root of the project. Here we can define our database schema inside schema.prisma
Prisma-client: The place where you can define end export Prisma constructor to be used globally in the project.
Located in: src/prisma-client/
Configuring redis
Redis-client: The place where you can define end export Redis client connection which can be used globally in the project.
Located in: src/redis-client/
GraphQL from backend:
Main GraphQL function/driver:
Located in: src/services/graphql.service.tsSetup new GraphQL Query:
Located in: src/services/graphql.service.ts
Prepare you query string and register the const variable inside queries object on line 34Usage:
First argument is req from your controller, second is “deviceInstanceQuery” - name of the query registered, and last argument is GraphQL variable object.
Tip: You can use wrapper function as we does and just call it from code in one line if variable are unchanged/static like in our case.