From a28398259c4ddc2e90c65fbe25c61a39e0c8f117 Mon Sep 17 00:00:00 2001 From: SathishKannaa-HexrFactory Date: Wed, 22 Jan 2025 16:59:14 +0530 Subject: [PATCH] Initial --- .env | 4 + .gitignore | 1 + compose.yaml | 50 +++ package.json | 33 ++ serviceFile.ts | 50 +++ src/api-server/Dockerfile | 35 ++ src/api-server/Routes/camera-Routes.ts | 11 + src/api-server/Routes/environments-Routes.ts | 9 + src/api-server/Routes/flooritem-Routes.ts | 10 + src/api-server/Routes/lines-Routes.ts | 14 + src/api-server/Routes/share-Routes.ts | 11 + src/api-server/Routes/user-Routes.ts | 10 + src/api-server/Routes/wallItems-Routes.ts | 11 + src/api-server/app.ts | 31 ++ .../controller/assets/flooritem-Controller.ts | 68 +++ .../controller/assets/wallitem-Controller.ts | 80 ++++ .../controller/camera/camera-Controlle.ts | 89 ++++ .../environments/environments-controller.ts | 50 +++ .../controller/lines/line-Controller.ts | 125 ++++++ .../controller/share/share-Controller.ts | 43 ++ src/api-server/controller/user-Controller.ts | 103 +++++ src/api-server/main.ts | 19 + src/shared/connect/mongoose.ts | 47 ++ src/shared/model/assets/flooritems-Model.ts | 57 +++ src/shared/model/assets/wallitems-Model.ts | 46 ++ src/shared/model/camera/camera-Model.ts | 87 ++++ .../model/environments/environments-Model.ts | 38 ++ src/shared/model/lines/lines-Model.ts | 43 ++ src/shared/model/user-Model.ts | 69 +++ src/shared/security/Hasing.ts | 24 + src/shared/security/token.ts | 38 ++ src/socket-server/Dockerfile | 35 ++ src/socket-server/index.ts | 22 + .../services/assets/flooritem-Controller.ts | 53 +++ .../services/assets/wallitem-Controller.ts | 60 +++ .../services/camera/camera-Controller.ts | 31 ++ .../environments/environments-controller.ts | 33 ++ .../services/lines/line-Controller.ts | 100 +++++ .../services/users/user-controller.ts | 97 ++++ src/socket-server/socket/events.ts | 45 ++ src/socket-server/socket/socketManager.ts | 421 ++++++++++++++++++ tsconfig.json | 110 +++++ 42 files changed, 2313 insertions(+) create mode 100644 .env create mode 100644 .gitignore create mode 100644 compose.yaml create mode 100644 package.json create mode 100644 serviceFile.ts create mode 100644 src/api-server/Dockerfile create mode 100644 src/api-server/Routes/camera-Routes.ts create mode 100644 src/api-server/Routes/environments-Routes.ts create mode 100644 src/api-server/Routes/flooritem-Routes.ts create mode 100644 src/api-server/Routes/lines-Routes.ts create mode 100644 src/api-server/Routes/share-Routes.ts create mode 100644 src/api-server/Routes/user-Routes.ts create mode 100644 src/api-server/Routes/wallItems-Routes.ts create mode 100644 src/api-server/app.ts create mode 100644 src/api-server/controller/assets/flooritem-Controller.ts create mode 100644 src/api-server/controller/assets/wallitem-Controller.ts create mode 100644 src/api-server/controller/camera/camera-Controlle.ts create mode 100644 src/api-server/controller/environments/environments-controller.ts create mode 100644 src/api-server/controller/lines/line-Controller.ts create mode 100644 src/api-server/controller/share/share-Controller.ts create mode 100644 src/api-server/controller/user-Controller.ts create mode 100644 src/api-server/main.ts create mode 100644 src/shared/connect/mongoose.ts create mode 100644 src/shared/model/assets/flooritems-Model.ts create mode 100644 src/shared/model/assets/wallitems-Model.ts create mode 100644 src/shared/model/camera/camera-Model.ts create mode 100644 src/shared/model/environments/environments-Model.ts create mode 100644 src/shared/model/lines/lines-Model.ts create mode 100644 src/shared/model/user-Model.ts create mode 100644 src/shared/security/Hasing.ts create mode 100644 src/shared/security/token.ts create mode 100644 src/socket-server/Dockerfile create mode 100644 src/socket-server/index.ts create mode 100644 src/socket-server/services/assets/flooritem-Controller.ts create mode 100644 src/socket-server/services/assets/wallitem-Controller.ts create mode 100644 src/socket-server/services/camera/camera-Controller.ts create mode 100644 src/socket-server/services/environments/environments-controller.ts create mode 100644 src/socket-server/services/lines/line-Controller.ts create mode 100644 src/socket-server/services/users/user-controller.ts create mode 100644 src/socket-server/socket/events.ts create mode 100644 src/socket-server/socket/socketManager.ts create mode 100644 tsconfig.json diff --git a/.env b/.env new file mode 100644 index 0000000..740971d --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +MONGO_URI=mongodb://127.0.0.1:27017/ +# MONGO_URI=mongodb://mongo/ +API_PORT=3503 +SOCKET_PORT=1059 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..fb6ca2c --- /dev/null +++ b/compose.yaml @@ -0,0 +1,50 @@ + +services: + api-server: + build: # Assuming Dockerfile for API is in the root directory + context: ./ # Root directory context + dockerfile: src/api-server/Dockerfile + container_name: DwinzoApi_end + environment: + NODE_ENV: development + ports: + - "50013:3503" # Host port 50013 mapped to container's port 3503 + expose: + - 3503 + depends_on: + - mongo + networks: + - DwinzoMajor + + socket-server: + build: # Assuming Dockerfile for Socket server is in the root directory + context: ./ # Root directory context + dockerfile: src/socket-server/Dockerfile + container_name: DwinzoSocket_end + environment: + NODE_ENV: development + ports: + - "50014:1059" # Changed host port to avoid conflict with API server + expose: + - 1059 + depends_on: + - mongo + networks: + - DwinzoMajor # Socket server on the same network as the API server + + mongo: + image: mongo:latest + container_name: mongo-Dwinzocontainer + ports: + - "3502:27017" + volumes: + - mongo-data:/data/db + networks: + - DwinzoMajor # Mongo is now on the same network + +volumes: + mongo-data: # Persistent volume for MongoDB data + +networks: + DwinzoMajor: + driver: bridge diff --git a/package.json b/package.json new file mode 100644 index 0000000..b1d318a --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "dwinzo_major", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start:api": "nodemon --exec ts-node src/api-server/main.ts", + "start:socket": "nodemon --exec ts-node src/socket-server/index.ts" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "bcryptjs": "^2.4.3", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.21.1", + "http": "^0.0.1-security", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.8.1", + "socket.io": "^4.8.1" + }, + "devDependencies": { + "@types/cors": "^2.8.17", + "@types/express": "^5.0.0", + "@types/jsonwebtoken": "^9.0.7", + "@types/node": "^22.9.0", + "nodemon": "^3.1.7", + "ts-node": "^10.9.2", + "typescript": "^5.6.3" + } +} diff --git a/serviceFile.ts b/serviceFile.ts new file mode 100644 index 0000000..2b4324f --- /dev/null +++ b/serviceFile.ts @@ -0,0 +1,50 @@ +let url_Backend_dwinzoMajor = "http://192.168.0.110:3503"; +//Login Api +export const createCamera = async (userId:string, position:Object) => { + try { + const response = await fetch(`${url_Backend_dwinzoMajor}/api/v1/createCamera`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ userId, position }), + }); + + if (!response.ok) { + throw new Error("Failed to create Camera"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); // Now TypeScript knows `error` is an instance of `Error` + } else { + throw new Error("An unknown error occurred"); + } + } + }; + + export const getCamera = async (userId:string) => { + try { + const response = await fetch(`${url_Backend_dwinzoMajor}/api/v1/getCamera/${userId}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("Failed to get Camera"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); // Now TypeScript knows `error` is an instance of `Error` + } else { + throw new Error("An unknown error occurred"); + } + } + }; \ No newline at end of file diff --git a/src/api-server/Dockerfile b/src/api-server/Dockerfile new file mode 100644 index 0000000..bc4a711 --- /dev/null +++ b/src/api-server/Dockerfile @@ -0,0 +1,35 @@ +ARG NODE_VERSION=lts + +FROM node:${NODE_VERSION}-alpine AS development +# Use production node environment by default. + +ENV NODE_ENV development + +WORKDIR /usr/src/app + +RUN npm install -g npm + +COPY package.json /usr/src/app/package.json + + +# COPY package-lock.json /usr/src/app/package-lock.json + + +RUN npm install + +# Run the application as a non-root user. +USER root + +# Copy the rest of the source files into the image. + + +COPY . . +# Expose the port that the application listens on. + +EXPOSE 3503 + + +# Run the application. + + +CMD ["npm", "run", "start:api"] \ No newline at end of file diff --git a/src/api-server/Routes/camera-Routes.ts b/src/api-server/Routes/camera-Routes.ts new file mode 100644 index 0000000..0003973 --- /dev/null +++ b/src/api-server/Routes/camera-Routes.ts @@ -0,0 +1,11 @@ +import express from 'express'; +import { camera } from '../controller/camera/camera-Controlle'; + +const router = express.Router(); + +router.post('/setCamera',camera.createCamera) +router.get('/getCamera/:organization/:userId',camera.getCamera) +router.get('/activeCameras/:organization',camera.onlineActiveDatas) + + +export default router; diff --git a/src/api-server/Routes/environments-Routes.ts b/src/api-server/Routes/environments-Routes.ts new file mode 100644 index 0000000..8dfba1c --- /dev/null +++ b/src/api-server/Routes/environments-Routes.ts @@ -0,0 +1,9 @@ +import express from 'express'; +import { environment } from '../controller/environments/environments-controller'; + +const router = express.Router(); +router.post('/setEvironments',environment.setEnvironment) +router.get('/findEnvironments/:organization/:userId',environment.getEnvironment) + + +export default router; \ No newline at end of file diff --git a/src/api-server/Routes/flooritem-Routes.ts b/src/api-server/Routes/flooritem-Routes.ts new file mode 100644 index 0000000..43e3aec --- /dev/null +++ b/src/api-server/Routes/flooritem-Routes.ts @@ -0,0 +1,10 @@ +import express from 'express'; +import { floorItems } from '../controller/assets/flooritem-Controller'; + +const router = express.Router(); +router.post('/setfloorItems',floorItems.setFloorItems) +router.get('/findfloorItems/:organization',floorItems.getFloorItems) +router.delete('/deletefloorItem',floorItems.deleteFloorItems) + + +export default router; \ No newline at end of file diff --git a/src/api-server/Routes/lines-Routes.ts b/src/api-server/Routes/lines-Routes.ts new file mode 100644 index 0000000..97c3847 --- /dev/null +++ b/src/api-server/Routes/lines-Routes.ts @@ -0,0 +1,14 @@ +import express from 'express'; +import { lines } from '../controller/lines/line-Controller'; + + +const router = express.Router(); +router.post('/setLine',lines.setLines) +router.post('/updatePoint',lines.updateLines) +router.get('/findLines/:organization',lines.getLines) +router.delete('/deleteLine',lines.deleteLineItems) +router.delete('/deletePoint',lines.deleteLinPoiteItems) +router.post('/deleteLayer',lines.deleteLayer) + + +export default router; \ No newline at end of file diff --git a/src/api-server/Routes/share-Routes.ts b/src/api-server/Routes/share-Routes.ts new file mode 100644 index 0000000..8ada476 --- /dev/null +++ b/src/api-server/Routes/share-Routes.ts @@ -0,0 +1,11 @@ +import express from 'express'; +import { share } from '../controller/share/share-Controller'; + + +const router = express.Router(); + +router.post('/shareUser',share.shareUser) +router.get('/findshareUsers',share.findshareUser) + + +export default router; \ No newline at end of file diff --git a/src/api-server/Routes/user-Routes.ts b/src/api-server/Routes/user-Routes.ts new file mode 100644 index 0000000..c110913 --- /dev/null +++ b/src/api-server/Routes/user-Routes.ts @@ -0,0 +1,10 @@ +import express from 'express'; +import { user } from '../controller/user-Controller'; + +const router = express.Router(); + +router.post('/signup',user.signup) +router.post('/login',user.login) + + +export default router; diff --git a/src/api-server/Routes/wallItems-Routes.ts b/src/api-server/Routes/wallItems-Routes.ts new file mode 100644 index 0000000..4ffbc52 --- /dev/null +++ b/src/api-server/Routes/wallItems-Routes.ts @@ -0,0 +1,11 @@ +import express from 'express'; +import { wallItems } from '../controller/assets/wallitem-Controller'; + + +const router = express.Router(); +router.post('/setWallItems',wallItems.setWallItems) +router.get('/findWallItems/:organization',wallItems.getWallItems) +router.delete('/deleteWallItem',wallItems.deleteWallItems) + + +export default router; \ No newline at end of file diff --git a/src/api-server/app.ts b/src/api-server/app.ts new file mode 100644 index 0000000..0969d18 --- /dev/null +++ b/src/api-server/app.ts @@ -0,0 +1,31 @@ +import express from 'express'; +import cors from 'cors'; +import connectDB from '../shared/connect/mongoose'; +import dotenv from 'dotenv'; +import cameraRoutes from './Routes/camera-Routes' +import environmentsRoutes from './Routes/environments-Routes' +import linesRoutes from './Routes/lines-Routes' +import flooritemRoutes from './Routes/flooritem-Routes' +import WallitemRoutes from './Routes/wallItems-Routes' +import userRoutes from './Routes/user-Routes' +import shareRoutes from './Routes/share-Routes' + +const app = express(); +app.use(cors()); +app.use(express.json()); +dotenv.config(); +app.get('/', (req, res) => { + res.send('Hello, I am Major-Dwinzo API!'); + }); +// connectDB(); +app.get('/health',(req,res)=>{ + res.status(200).json({ message: 'Server is running' }); +}) +app.use('/api/v1', cameraRoutes); +app.use('/api/v1', environmentsRoutes); +app.use('/api/v1', linesRoutes); +app.use('/api/v1', flooritemRoutes); +app.use('/api/v1', WallitemRoutes); +app.use('/api/v1', userRoutes); +app.use('/api/v1', shareRoutes); +export default app; diff --git a/src/api-server/controller/assets/flooritem-Controller.ts b/src/api-server/controller/assets/flooritem-Controller.ts new file mode 100644 index 0000000..a45a5ad --- /dev/null +++ b/src/api-server/controller/assets/flooritem-Controller.ts @@ -0,0 +1,68 @@ +import { Request, Response } from "express"; +import floorItemsModel from "../../../shared/model/assets/flooritems-Model"; + + +export class floorItems { + static async setFloorItems(req: Request, res: Response) { + try { + const { modeluuid, modelname, position, modelfileID,rotation,isLocked,isVisible,organization } = req.body + + + const findvalue = await floorItemsModel(organization).findOne({ modeluuid: modeluuid,modelname:modelname }) + + if (findvalue) { + + const updatevalue = await floorItemsModel(organization).findOneAndUpdate( + { modeluuid: modeluuid,modelname:modelname }, { position: position, rotation: rotation,isVisible:isVisible,isLocked:isLocked }, { new: true }); + res.status(201).json(updatevalue); + + + } else { + + const newValue = await floorItemsModel(organization).create({ modeluuid, modelfileID,modelname, position, rotation,isLocked,isVisible, }); + + + res.status(201).json(newValue); + + } + + // Send response with the created document + } catch (error) { + console.error('Error creating flooritems:', error); + res.status(500).json({ message: "Failed to create flooritems" }); + } + } + static async getFloorItems(req: Request, res: Response) { + try { + const { organization } = req.params; + // console.log('req.params: ', req.params); + + const findValue = await floorItemsModel(organization).find() + if (!findValue) { + res.status(200).json("floorItems not found"); + } else { + + res.status(201).json(findValue); + } + } catch (error) { + console.error('Error get flooritems:', error); + res.status(500).json({ error: "Failed to get flooritems" }); + } + } + static async deleteFloorItems(req: Request, res: Response) { + try { + const { modeluuid,modelname,organization } = req.body; + + const findValue = await floorItemsModel(organization).findOneAndDelete({modeluuid:modeluuid,modelname:modelname}) + if (!findValue) { + res.status(200).json("user not found"); + } else { + + res.status(201).json(findValue); + } + } catch (error) { + console.error('Error get flooritems:', error); + res.status(500).json({ error: "Failed to get flooritems" }); + } + } +} diff --git a/src/api-server/controller/assets/wallitem-Controller.ts b/src/api-server/controller/assets/wallitem-Controller.ts new file mode 100644 index 0000000..8ab2558 --- /dev/null +++ b/src/api-server/controller/assets/wallitem-Controller.ts @@ -0,0 +1,80 @@ +import { Request, Response } from "express"; +import wallItenmModel from "../../../shared/model/assets/wallitems-Model"; + + +export class wallItems { + static async setWallItems(req: Request, res: Response) { + try { + const { modeluuid, modelname, position, type, csgposition,csgscale,quaternion,scale,organization } = req.body + + + const findvalue = await wallItenmModel(organization).findOne({ modeluuid: modeluuid}) + + if (findvalue) { + const updatevalue = await wallItenmModel(organization).findOneAndUpdate( + { modeluuid: modeluuid }, + { + modelname, + position, + type, + csgposition, + csgscale, + quaternion, + scale, + }, + { new: true } // Return the updated document + ); + res.status(201).json(updatevalue); + + + } else { + const newValue = await wallItenmModel(organization).create({ modeluuid,modelname, position, type, csgposition,csgscale,quaternion,scale }); + + + res.status(201).json(newValue); + + } + + // Send response with the created document + } catch (error) { + console.error('Error creating wallitems:', error); + res.status(500).json({ message: "Failed to create wallitems" }); + } + } + static async getWallItems(req: Request, res: Response) { + try { + const { organization } = req.params; + + + const findValue = await wallItenmModel +(organization).find() + if (!findValue) { + res.status(200).json("wallitems not found"); + } else { + + res.status(201).json(findValue); + } + } catch (error) { + console.error('Error get wallitems:', error); + res.status(500).json({ error: "Failed to get wallitems" }); + } + } + static async deleteWallItems(req: Request, res: Response) { + try { + const { modeluuid,modelname,organization } = req.body; + + + const findValue = await wallItenmModel +(organization).findOneAndDelete({modeluuid:modeluuid,modelname:modelname}) + if (!findValue) { + res.status(200).json("user not found"); + } else { + + res.status(201).json(findValue); + } + } catch (error) { + console.error('Error get wallitems:', error); + res.status(500).json({ error: "Failed to get wallitems" }); + } + } +} diff --git a/src/api-server/controller/camera/camera-Controlle.ts b/src/api-server/controller/camera/camera-Controlle.ts new file mode 100644 index 0000000..94b5f79 --- /dev/null +++ b/src/api-server/controller/camera/camera-Controlle.ts @@ -0,0 +1,89 @@ +import { Request, Response } from "express"; +import cameraModel from "../../../shared/model/camera/camera-Model"; +import userModel from "../../../shared/model/user-Model"; + +export class camera { + static async createCamera(req: Request, res: Response) { + try { + const { userId, position, target, rotation,organization } = req.body + + + const findCamera = await cameraModel(organization).findOne({ userId: userId }) + + if (findCamera) { + const updateCamera = await cameraModel(organization).findOneAndUpdate( + { userId: userId }, { position: position, target: target,rotation:rotation }, { new: true }); + res.status(201).json(updateCamera); + + } else { + const newCamera = await cameraModel(organization).create({ userId, position, target,rotation }); + + res.status(201).json(newCamera); + + } + + // Send response with the created document + } catch (error) { + console.error('Error creating camera:', error); + res.status(500).json({message:"Failed to create camera"}); + } + } + static async getCamera(req: Request, res: Response) { + try { + const { userId, organization } = req.params; + +// if (!userId) { +// res.status(201).json("User data is insufficient"); +// } + const findCamera = await cameraModel(organization).findOne({ userId: userId }) + if (!findCamera) { + res.status(200).json("user not found"); + } else { + + res.status(201).json(findCamera); + } + } catch (error) { + console.error('Error get camera:', error); + res.status(500).json({ error: "Failed to get camera" }); + } + } + + static async onlineActiveDatas(req: Request, res: Response) { + const {organization } = req.params; + try { + const findactiveUsers = await userModel(organization).find({activeStatus:"online"}) + + + const cameraDataPromises = findactiveUsers.map(async (activeUser) => { + const cameraData = await cameraModel(organization) + .findOne({ userId: activeUser._id }) + .select("position target rotation -_id"); + + if (cameraData) { + return { + position: cameraData.position, + target: cameraData.target, + rotation:cameraData.rotation, + userData: { + _id: activeUser._id, + userName: activeUser.userName, + email: activeUser.email, + activeStatus: activeUser.activeStatus, + }, + }; + } + + // Return null if no camera data is found for the user + return null; + }); + + const cameraDatas = (await Promise.all(cameraDataPromises)).filter((singledata:any) => singledata !== null); + + + res.status(200).send({ cameraDatas }); + + } catch (error:any) { + res.status(500).send(error); + } + } +} diff --git a/src/api-server/controller/environments/environments-controller.ts b/src/api-server/controller/environments/environments-controller.ts new file mode 100644 index 0000000..80d8162 --- /dev/null +++ b/src/api-server/controller/environments/environments-controller.ts @@ -0,0 +1,50 @@ +import { Request, Response } from "express"; +import environmentModel from "../../../shared/model/environments/environments-Model"; + +export class environment { + static async setEnvironment(req: Request, res: Response) { + try { + const { userId,roofVisibility,wallVisibility, organization } = req.body + + + const findvalue = await environmentModel(organization).findOne({ userId: userId }) + + if (findvalue) { + + const updatevalue = await environmentModel(organization).findOneAndUpdate( + { userId: userId }, { roofVisibility:roofVisibility,wallVisibility:wallVisibility }, { new: true }); + res.status(201).json(updatevalue); + + + } else { + const newValue = await environmentModel(organization).create({ userId, roofVisibility, wallVisibility }); + + + res.status(201).json(newValue); + + } + + // Send response with the created document + } catch (error) { + console.error('Error creating environments:', error); + res.status(500).json({message:"Failed to create environments"}); + } + } + static async getEnvironment(req: Request, res: Response) { + try { + const { userId, organization } = req.params; + + + const findValue = await environmentModel(organization).findOne({ userId: userId }) + if (!findValue) { + res.status(200).json("user not found"); + } else { + + res.status(201).json(findValue); + } + } catch (error) { + console.error('Error get environments:', error); + res.status(500).json({ error: "Failed to get environments" }); + } + } +} diff --git a/src/api-server/controller/lines/line-Controller.ts b/src/api-server/controller/lines/line-Controller.ts new file mode 100644 index 0000000..25b6253 --- /dev/null +++ b/src/api-server/controller/lines/line-Controller.ts @@ -0,0 +1,125 @@ +import { Request, Response } from "express"; +import lineModel from "../../../shared/model/lines/lines-Model"; + +export class lines { + static async setLines(req: Request, res: Response) { + try { + const {organization,layer,line,type}=req.body + const newLine = await lineModel(organization).create({ layer,line,type }); + + + res.status(201).json(newLine); + + // Send response with the created document + } catch (error) { + console.error('Error creating Lines:', error); + res.status(500).json({message:"Failed to create Lines"}); + } + } + static async updateLines(req: Request, res: Response) { + try { + const {organization,uuid,position,}=req.body + // const findLine = await lineModel(organization).find({ 'line.uuid': uuid }); + // Update the position of the line matching the uuid + const updateResult = await lineModel(organization).updateMany( + { 'line.uuid': uuid }, // Filter: Find the line with the given uuid + { $set: { 'line.$.position': position } } // Update the position and type + ); + + res.status(201).json(updateResult); + + // Send response with the created document + } catch (error) { + console.error('Error creating Lines:', error); + res.status(500).json({message:"Failed to create Lines"}); + } + } + static async getLines(req: Request, res: Response) { + try { + const { organization } = req.params; + + + const findValue = await lineModel(organization).find() + if (!findValue) { + res.status(200).json("user not found"); + } else { + + res.status(201).json(findValue); + } + } catch (error) { + console.error('Error get Lines:', error); + res.status(500).json({ error: "Failed to get Lines" }); + } + } + static async deleteLineItems(req: Request, res: Response) { + try { + const {organization,layer,line,type}=req.body + + const inputUuids = line.map((item: any) => item.uuid); + + + // const findValue = await lineModel(organization).findOneAndDelete({ + + // line: { $elemMatch: { uuid: { $in: inputUuids } } }, + // }); + const findValue = await lineModel(organization).findOneAndDelete({ + "line.uuid": { $all: inputUuids } // Ensure all UUIDs are present in the `line` key + }); + + if (!findValue) { + res.status(200).json("data not found"); + } else { + + res.status(201).json(findValue); + } + } catch (error) { + console.error('Error delete Lines:', error); + res.status(500).json({ error: "Failed to delete Lines" }); + } + } + static async deleteLinPoiteItems(req: Request, res: Response) { + try { + const {organization,layer,uuid,type}=req.body + + const findValue = await lineModel(organization).deleteMany({ 'line.uuid': uuid }) + + if (!findValue) { + res.status(200).json("data not found"); + } else { + + res.status(201).json(findValue); + } + } catch (error) { + console.error('Error delete Lines:', error); + res.status(500).json({ error: "Failed to delete Lines" }); + } + } + + static async deleteLayer(req: Request, res: Response) { + try { + const {organization,layer}=req.body + + // Fetch the documents with the specified layer value + const findValue = await lineModel(organization).find({ layer: layer }); + + if (!findValue) { + res.status(200).json("data not found"); + } else { + await lineModel(organization).deleteMany({ layer: layer }); + // console.log(`Documents with layer ${layer} have been deleted.`); + + // Update documents with layer greater than -1 + const updateResult = await lineModel(organization).updateMany( + { layer: { $gt:layer} }, + { $inc: { layer: -1 } } // Example operation: decrementing layer by 1 + ); + + + res.status(201).json(updateResult); + } + } catch (error) { + console.error('Error delete Lines:', error); + res.status(500).json({ error: "Failed to delete Lines" }); + } + } +} diff --git a/src/api-server/controller/share/share-Controller.ts b/src/api-server/controller/share/share-Controller.ts new file mode 100644 index 0000000..573eb35 --- /dev/null +++ b/src/api-server/controller/share/share-Controller.ts @@ -0,0 +1,43 @@ +import { Request, Response } from "express"; +import userModel from "../../../shared/model/user-Model"; + + +export class share { + static async shareUser(req: Request, res: Response) { + try { + const { email, isShare, organization } = req.body + + + const findValue = await userModel(organization).findOneAndUpdate({email:email},{isShare:isShare},{new:true}) + + res.status(201).json({message:"scene shared successfully",data:findValue}); + if (!findValue) { + res.status(404).json({message:"Not found"}) + } + // Send response with the created document + } catch (error) { + console.error('Error creating Share:', error); + res.status(500).json({message:"Failed to create Share"}); + } + } + + static async findshareUser(req: Request, res: Response) { + try { + const organization = req.query.organization as string; + + + const findValue = await userModel(organization).find({}).select("isShare email userName -_id") + // console.log('findValue: ', findValue); + + res.status(201).json({message:"scene shared datas",data:findValue}); + if (!findValue) { + res.status(404).json({message:"Not found"}) + } + // Send response with the created document + } catch (error) { + console.error('Error Share:', error); + res.status(500).json({message:"Failed to Share datas "}); + } + } + +} diff --git a/src/api-server/controller/user-Controller.ts b/src/api-server/controller/user-Controller.ts new file mode 100644 index 0000000..365f8b7 --- /dev/null +++ b/src/api-server/controller/user-Controller.ts @@ -0,0 +1,103 @@ +import { Request, Response } from "express"; +import { Server } from 'http'; +import userModel from "../../shared/model/user-Model"; +import { isSharedArrayBuffer } from "util/types"; +const {hashGenerate,hashValidator} = require("../../shared/security/Hasing.ts") +// import {hashGenerate} from '../security/Hasing' + +let serverAlive = true; +export class user { + static async signup(req: Request, res: Response) { + try { + let role; + const { userName, email, password,organization,profilePicture } = req.body; + const caseChange = email.toLowerCase(); + const emailcheck = await userModel(organization).findOne({ email: caseChange }); + if (emailcheck!==null) { + res.json({ + message:"User already exists" + }); + } else { + const hashpassword=await hashGenerate(password) + const userCount = await userModel(organization).countDocuments({}); + role = userCount === 0 ? "Admin" : "User"; + const isShare = role === "Admin" ? "true" : "false"; + const newuser = await userModel(organization).create({ + userName: userName, + email: caseChange, + isShare:isShare, + password: hashpassword, + role:role, + profilePicture:profilePicture + }); + newuser.save(); + res.status(200).json({ + message:"New User created" + }); + } + } catch (error:any) { + res.status(500).send(error); + } + } + static async login(req: Request, res: Response) { + try { + let role; + const { email, password,organization } = req.body; + // console.log(' req.body: ', req.body); + + const existingMail = await userModel(organization).findOne({ + email:email + }); + + if (existingMail === null || !existingMail) { + res.status(404).json({ message: "User Not Found!!! Kindly signup..." }); + } else { + const hashedpassword= existingMail.password + const checkpassword = await hashValidator( + password, + hashedpassword + ) + // console.log('checkpassword: ', checkpassword); + if (checkpassword) { + // const tokenValidation=await tokenGenerator(existingMail.email) + res.status(200).send({ + message: "login successfull", + email: existingMail.email, + name: existingMail.userName, + userId: existingMail._id, + isShare:existingMail.isShare, + // token:tokenValidation + + }); + } else { + res.status(404).json({message:"email & password is invalid...Check the credentials"}) + } + } + } catch (error:any) { + res.status(500).send(error); + } + } + + // static async checkserverHealth(server:Server,organization: string){ + // try { + // if (server.listening) { + // console.log('Server is running'); + // serverAlive = true; + // // Update all users to online status + // } else { + // // await userModel(organization).updateMany({}, { activeStatus: "offline" }); // Replace `activeStatus` with your actual field + // throw new Error('Server is not running'); + // } + // } catch (error:any) { + // console.error('Server health check failed:', error.message); + // serverAlive = false; + + // // Update all users to offline status + // // await userModel(organization).updateMany({}, { activeStatus: "offline" }); + // } + // } + +} +// export const startHealthCheck = (server: Server, organization: string) => { +// setInterval(() => user.checkserverHealth(server, organization), 5000); +// }; diff --git a/src/api-server/main.ts b/src/api-server/main.ts new file mode 100644 index 0000000..78e45fb --- /dev/null +++ b/src/api-server/main.ts @@ -0,0 +1,19 @@ +import app from './app'; +import http from 'http'; +// import { startHealthCheck } from './controller/user-Controller'; + +const server = http.createServer(app); + + + +const organization = process.env.ORGANIZATION_NAME || 'defaultOrganization'; // Replace with your logic + +if (!organization) { + throw new Error('ORGANIZATION_NAME is not defined in the environment'); +} + +const PORT = process.env.API_PORT +server.listen(PORT, () => { + console.log(`API-Server running on port ${PORT}`); + // startHealthCheck(server, organization); +}); diff --git a/src/shared/connect/mongoose.ts b/src/shared/connect/mongoose.ts new file mode 100644 index 0000000..585e827 --- /dev/null +++ b/src/shared/connect/mongoose.ts @@ -0,0 +1,47 @@ +import mongoose, { Schema, Connection, Model } from "mongoose"; + +interface ConnectionCache { + [key: string]: Connection; +} + +const connections: ConnectionCache = {}; + +const MainModel = ( + db: string, + modelName: string, + schema: Schema, + collectionName: string +): Model => { + const db1_url = `${process.env.MONGO_URI}${db}`; + + // Check if the connection already exists + if (connections[db]) { + return connections[db].model(modelName, schema, collectionName); + } + + try { + const db1 = mongoose.createConnection(db1_url, { + maxPoolSize: 50, + }); + + // Cache the connection + connections[db] = db1; + + // Log connection success or handle errors + db1.on("connected", () => { + console.log(`Connected to MongoDB database: ${db}`); + }); + + db1.on("error", (err) => { + console.error(`MongoDB connection error for database ${db}:`, err.message); + }); + + return db1.model(modelName, schema, collectionName); + } catch (error) { + console.error("Database connection error:", (error as Error).message); + throw error; + } +}; + +export default MainModel; + diff --git a/src/shared/model/assets/flooritems-Model.ts b/src/shared/model/assets/flooritems-Model.ts new file mode 100644 index 0000000..56cb068 --- /dev/null +++ b/src/shared/model/assets/flooritems-Model.ts @@ -0,0 +1,57 @@ +import mongoose, { Document, Schema } from 'mongoose'; +import MainModel from '../../connect/mongoose'; + +// Interface for TypeScript with PascalCase +export interface floorItenms extends Document { + modeluuid: string; + modelfileID: string; + modelname: string + isLocked:boolean + isVisible:boolean + position: [] + rotation: { + x: number; + y: number; + z: number; + }; + + +} + +// Define the Mongoose Schema +const floorItemsSchema: Schema = new Schema({ + modeluuid: { type: String }, + modelfileID: { type: String }, + modelname: { type: String }, + position: { type: Array}, + isLocked:{type:Boolean}, + isVisible:{type:Boolean}, + rotation: { + x: { type: Number, required: true }, + y: { type: Number, required: true }, + z: { type: Number, required: true } + } +}); + +// Model for MongoDB collection +// const cameraModel = model("Camera", cameraSchema); + +// export default cameraModel; +// const floorItemsModel = (db: string) => { +// const mongoUrl = process.env.MONGO_URI || ''; +// if (!mongoUrl) { +// throw new Error('MONGO_URI environment variable is not set'); +// } +// // Connect to the database +// const dbConnection = mongoose.createConnection(mongoUrl, { +// dbName: db, // Specify the database name here +// serverSelectionTimeoutMS: 30000, +// }); +// return dbConnection.model('floorItenms', floorItenmsSchema,`floorItenms`); +// } + +// export default floorItemsModel; +const floorItemsModel = (db:string) => { + return MainModel(db, "floorItems", floorItemsSchema, "floorItems") +}; +export default floorItemsModel; \ No newline at end of file diff --git a/src/shared/model/assets/wallitems-Model.ts b/src/shared/model/assets/wallitems-Model.ts new file mode 100644 index 0000000..80895aa --- /dev/null +++ b/src/shared/model/assets/wallitems-Model.ts @@ -0,0 +1,46 @@ +import mongoose, { Document, Schema } from 'mongoose'; +import MainModel from '../../connect/mongoose'; +// Interface for TypeScript with PascalCase +export interface wallitems extends Document { + modeluuid: string; + modelname: string + type: string + csgposition: [] + csgscale: [] + position: [] + quaternion: [] + scale: [] + + +} + +// Define the Mongoose Schema +const wallItemsSchema: Schema = new Schema({ + modeluuid: { type: String,unique:true }, + modelname: { type: String}, + type: { type: String }, + csgposition: { type: Array}, + csgscale: { type: Array,}, + position: { type: Array }, + quaternion: { type: Array}, + scale: { type: Array} +}); + +// const wallItenmModel = (db: string) => { +// const mongoUrl = process.env.MONGO_URI || ''; +// if (!mongoUrl) { +// throw new Error('MONGO_URI environment variable is not set'); +// } +// // Connect to the database +// const dbConnection = mongoose.createConnection(mongoUrl, { +// dbName: db, // Specify the database name here +// serverSelectionTimeoutMS: 30000, +// }); +// return dbConnection.model('wallitenms', wallItenmsSchema, `wallitenms`); +// } + +// export default wallItenmModel; +const wallItenmModel = (db:string) => { + return MainModel(db, "wallitems", wallItemsSchema, "wallitems") + }; + export default wallItenmModel; \ No newline at end of file diff --git a/src/shared/model/camera/camera-Model.ts b/src/shared/model/camera/camera-Model.ts new file mode 100644 index 0000000..82366a2 --- /dev/null +++ b/src/shared/model/camera/camera-Model.ts @@ -0,0 +1,87 @@ +import mongoose, { Document, Schema } from 'mongoose'; +import MainModel from '../../connect/mongoose'; + +// Interface for TypeScript with PascalCase +export interface Camera extends Document { + userId: string; + position: { + x: number; + y: number; + z: number; + } + target: { + x: { type: Number, required: true }, + y: { type: Number, required: true }, + z: { type: Number, required: true } + } + rotation: { + x: { type: Number, required: true }, + y: { type: Number, required: true }, + z: { type: Number, required: true } + } +} + +// Define the Mongoose Schema +const cameraSchema: Schema = new Schema({ + userId: { type: String, unique: true }, + position: { + x: { type: Number, required: true }, + y: { type: Number, required: true }, + z: { type: Number, required: true } + }, + target: { + x: { type: Number, required: true }, + y: { type: Number, required: true }, + z: { type: Number, required: true } + }, + rotation: { + x: { type: Number, required: true }, + y: { type: Number, required: true }, + z: { type: Number, required: true } + } +}); + +// Model for MongoDB collection +// const cameraModel = model("Camera", cameraSchema); + +// export default cameraModel; +// const cameraModel = (db: string) => { +// const mongoUrl = process.env.MONGO_URI || ''; +// if (!mongoUrl) { +// throw new Error('MONGO_URI environment variable is not set'); +// } +// // Connect to the database +// const dbConnection = mongoose.createConnection(mongoUrl, { +// dbName: db, // Specify the database name here +// serverSelectionTimeoutMS: 30000, +// }); +// return dbConnection.model('Camera', cameraSchema,`Camera`); +// } + +// export default cameraModel; +// const cameraModel = (db: string) => { +// const mongoUrl = process.env.MONGO_URI || ''; +// if (!mongoUrl) { +// throw new Error('MONGO_URI environment variable is not set'); +// } + +// const dbConnection = mongoose.createConnection(mongoUrl, { +// dbName: db, +// serverSelectionTimeoutMS: 60000, // Increased timeout +// }); + +// dbConnection.on('error', (err) => { +// console.error(`MongoDB connection error for database ${db}:`, err); +// }); + +// dbConnection.once('open', () => { +// console.log(`Connected to MongoDB database: ${db}`); +// }); + +// return dbConnection.model('Camera', cameraSchema, 'Camera'); +// }; +// export default cameraModel +const cameraModel = (db:string) => { + return MainModel(db, "Camera", cameraSchema, "Camera") +}; +export default cameraModel; \ No newline at end of file diff --git a/src/shared/model/environments/environments-Model.ts b/src/shared/model/environments/environments-Model.ts new file mode 100644 index 0000000..27d3b70 --- /dev/null +++ b/src/shared/model/environments/environments-Model.ts @@ -0,0 +1,38 @@ +import mongoose, { Document, Schema } from 'mongoose'; +import MainModel from '../../connect/mongoose'; +// Interface for TypeScript with PascalCase +export interface environment extends Document { + userId: string; + roofVisibility:boolean + wallVisibility:boolean +} + +// Define the Mongoose Schema +const environmentSchema: Schema = new Schema({ + userId: { type: String, unique: true }, + roofVisibility: { type: Boolean ,default:false}, + wallVisibility: { type: Boolean ,default:false}, +}); + +// Model for MongoDB collection +// const cameraModel = model("Camera", cameraSchema); + +// export default cameraModel; +// const environmentModel = (db: string) => { +// const mongoUrl = process.env.MONGO_URI || ''; +// if (!mongoUrl) { +// throw new Error('MONGO_URI environment variable is not set'); +// } +// // Connect to the database +// const dbConnection = mongoose.createConnection(mongoUrl, { +// dbName: db, // Specify the database name here +// serverSelectionTimeoutMS: 30000, +// }); +// return dbConnection.model('environments', environmentSchema,`environments`); +// } + +// export default environmentModel; +const environmentModel = (db:string) => { + return MainModel(db, "environments", environmentSchema, "environments") +}; +export default environmentModel; \ No newline at end of file diff --git a/src/shared/model/lines/lines-Model.ts b/src/shared/model/lines/lines-Model.ts new file mode 100644 index 0000000..14beabc --- /dev/null +++ b/src/shared/model/lines/lines-Model.ts @@ -0,0 +1,43 @@ +import mongoose, { Document, Schema } from "mongoose"; +import MainModel from "../../connect/mongoose"; +const positionSchema = new mongoose.Schema({ + x: { type: Number, }, // Optional position fields + y: { type: Number, }, + z: { type: Number}, + }); + + // Define a schema for the individual line + const Vector3 = new mongoose.Schema({ + position: { type: positionSchema, required: false }, // Optional position + uuid: { type: String, required: false }, // Optional uuid + }); + + // Define the main schema + const LineSchema = new mongoose.Schema({ + layer: { type: Number, required: true }, // Layer is mandatory + line: { type: [Vector3], required: true }, // Array of line objects + type: { type: String, required: false }, // Optional type + }); + +// Database connection and model creation +// const lineModel = (db: string) => { +// const mongoUrl = process.env.MONGO_URI || ""; +// if (!mongoUrl) { +// throw new Error("MONGO_URI environment variable is not set"); +// } + +// // Connect to the database +// const dbConnection = mongoose.createConnection(mongoUrl, { +// dbName: db, // Specify the database name here +// serverSelectionTimeoutMS: 30000, +// }); + +// // Return the model +// return dbConnection.model("lines", LineSchema, "lines"); +// }; + +// export default lineModel; +const lineModel = (db:string) => { + return MainModel(db, "lines", LineSchema, "lines") +}; +export default lineModel; \ No newline at end of file diff --git a/src/shared/model/user-Model.ts b/src/shared/model/user-Model.ts new file mode 100644 index 0000000..f4d40af --- /dev/null +++ b/src/shared/model/user-Model.ts @@ -0,0 +1,69 @@ +import mongoose, { Document, Schema } from "mongoose"; +import MainModel from "../connect/mongoose"; +export interface User extends Document { + userName: String; + email: String; + password: String; + + role: String; + profilePicture: String; + isShare:Boolean, + activeStatus:string + +} +const signupschema: Schema = new Schema({ + userName: { + type: String, + required: true, + }, + email: { + type: String, + unique: true, + required: true, + }, + password: { + type: String, + min: 8, + required: true, + }, + role: { + type: String, + default: "User", + enum: ["User", "Admin", "Project Manager", "Manager", "Owner"], + }, + profilePicture: { + type: String, + // default: "default-profile-picture.jpg" + }, + isShare:{ + type:Boolean, + default:false + }, + activeStatus:{ + type:String, + enum: ["online", "offline"], + default: "offline" + } + +}); +// const userModel = (db: string) => { +// const mongoUrl = process.env.MONGO_URI || ""; +// if (!mongoUrl) { +// throw new Error("MONGO_URI environment variable is not set"); +// } + +// // Connect to the database +// const dbConnection = mongoose.createConnection(mongoUrl, { +// dbName: db, // Specify the database name here +// serverSelectionTimeoutMS: 30000, +// }); + +// // Return the model +// return dbConnection.model("Users", signupschema, "Users"); +// }; + +// export default userModel; +const userModel = (db:string) => { + return MainModel(db, "Users", signupschema, "Users") +}; +export default userModel; \ No newline at end of file diff --git a/src/shared/security/Hasing.ts b/src/shared/security/Hasing.ts new file mode 100644 index 0000000..d5690d2 --- /dev/null +++ b/src/shared/security/Hasing.ts @@ -0,0 +1,24 @@ +const bcrypt = require("bcryptjs"); +const saltRounds = 10; +const hashGenerate = async (Password:String) => { + try { + const salt = await bcrypt.genSalt(saltRounds); + const hash = await bcrypt.hash(Password, salt); + + return hash; + } catch (error) { + return error; + } +}; +const hashValidator = async (password:String, hashedPassword:String) => { + + try { + const result = await bcrypt.compare(password, hashedPassword); + + return result; + } catch (error) { + return false; + } +}; +module.exports.hashGenerate = hashGenerate; +module.exports.hashValidator = hashValidator; \ No newline at end of file diff --git a/src/shared/security/token.ts b/src/shared/security/token.ts new file mode 100644 index 0000000..09588bd --- /dev/null +++ b/src/shared/security/token.ts @@ -0,0 +1,38 @@ +import { Request, Response, NextFunction } from 'express'; +import * as Jwt from 'jsonwebtoken'; // Correct way to import jsonwebtoken + +// Define a new interface extending Request +interface AuthenticatedRequest extends Request { + user?: { + email: string; + // Add more fields as needed based on your JWT payload + }; +} +const tokenGenerator = (email: string) => { + const token = Jwt.sign({ email: email }, "Milestone", { + expiresIn: "3hours", + }); + return token; + }; + +const tokenValidator = (req: AuthenticatedRequest, res: Response, next: NextFunction): void => { + const token: string | undefined = req.headers.token as string | undefined; + if (!token) { + res.status(403).json({ + msg: "No token present", + }); + return; // Make sure to return after sending a response + } + + try { + const decoded = Jwt.verify(token,"Milestone") as { email: string }; // adjust if your JWT payload has more fields + req.user = decoded; + next(); + } catch (err) { + res.status(401).json({ + msg: "Invalid Token", + }); + } +}; + +export { tokenValidator,tokenGenerator }; diff --git a/src/socket-server/Dockerfile b/src/socket-server/Dockerfile new file mode 100644 index 0000000..ea6ed17 --- /dev/null +++ b/src/socket-server/Dockerfile @@ -0,0 +1,35 @@ +ARG NODE_VERSION=lts + +FROM node:${NODE_VERSION}-alpine AS development +# Use production node environment by default. + +ENV NODE_ENV development + +WORKDIR /usr/src/app + +RUN npm install -g npm + +COPY package.json /usr/src/app/package.json + + +# COPY package-lock.json /usr/src/app/package-lock.json + + +RUN npm install + +# Run the application as a non-root user. +USER root + +# Copy the rest of the source files into the image. + + +COPY . . +# Expose the port that the application listens on. + +EXPOSE 1059 + + +# Run the application. + + +CMD ["npm", "run", "start:socket"] \ No newline at end of file diff --git a/src/socket-server/index.ts b/src/socket-server/index.ts new file mode 100644 index 0000000..79341d2 --- /dev/null +++ b/src/socket-server/index.ts @@ -0,0 +1,22 @@ + +import express from "express" +import { Response, Request } from "express"; +import http from "http"; +import dotenv from "dotenv"; // Import dotenv + +dotenv.config(); + +import { initSocketServer } from "./socket/socketManager"; + +const app = express(); +const PORT = process.env.SOCKET_PORT; +const server = http.createServer(app); + +app.get('/', (req: Request, res: Response) => { + res.send('Hello, I am Major-Dwinzo RealTime!'); +}); + +initSocketServer(server); +server.listen(PORT, () => { + console.log(`socket-Server is running on http://localhost:${PORT}`); +}); diff --git a/src/socket-server/services/assets/flooritem-Controller.ts b/src/socket-server/services/assets/flooritem-Controller.ts new file mode 100644 index 0000000..4b3ff67 --- /dev/null +++ b/src/socket-server/services/assets/flooritem-Controller.ts @@ -0,0 +1,53 @@ +import { Request, Response } from "express"; +import floorItemsModel from "../../../shared/model/assets/flooritems-Model"; + +export const setFloorItems = async (data: any) => { + try { + const { modelfileID,modeluuid, modelname, position, rotation,isLocked,isVisible, organization } = data + + + + const findvalue = await floorItemsModel(organization).findOne({ modeluuid: modeluuid, modelname: modelname }) + + if (findvalue) { + + const updatevalue = await floorItemsModel(organization).findOneAndUpdate( + { modeluuid: modeluuid, modelname: modelname }, { position: position, rotation: rotation ,isVisible:isVisible,isLocked:isLocked}, { new: true }); + return { success: true, message: 'flooritems updated', data: updatevalue,organization:organization } + + + } else { + + const newValue = await floorItemsModel(organization).create({ modeluuid, modelname, modelfileID,position, rotation,isLocked,isVisible }); + + + return { success: true, message: 'flooritem created', data: newValue,organization:organization } + + } + + // Send response with the created document + } catch (error) { + console.error('Error creating flooritems:', error); + return { success: false, message: 'Error creating or updating camera', error } + } +} + + export const deleteFloorItems = async (data: any)=>{ + try { + const { modeluuid,modelname,organization } = data; + + const findValue = await floorItemsModel(organization).findOneAndDelete({modeluuid:modeluuid,modelname:modelname}) + if (!findValue) { + return { success: false, message: 'model not found',organization:organization } + + } else { + + return { success: true, message: 'flooritem deleted', data: findValue,organization:organization } + } + } catch (error) { + console.error('Error get flooritems:', error); + return { success: false, message: 'Failed to delete flooritems', error } + + } + } + diff --git a/src/socket-server/services/assets/wallitem-Controller.ts b/src/socket-server/services/assets/wallitem-Controller.ts new file mode 100644 index 0000000..d665bf7 --- /dev/null +++ b/src/socket-server/services/assets/wallitem-Controller.ts @@ -0,0 +1,60 @@ +import { Request, Response } from "express"; +import wallItenmModel from "../../../shared/model/assets/wallitems-Model"; + + +export const setWallItems = async (data: any) => { + try { + const { modeluuid, modelname, position, type, csgposition, csgscale, quaternion, scale, organization } = data + + + const findvalue = await wallItenmModel(organization).findOne({ modeluuid: modeluuid }) + if (findvalue) { + + const updatevalue = await wallItenmModel(organization).findOneAndUpdate( + { modeluuid: modeluuid }, + { + modelname, + position, + type, + csgposition, + csgscale, + quaternion, + scale, + }, + { new: true } // Return the updated document + ); + return { success: true, message: 'wallIitem updated', data: updatevalue, organization: organization } + + + } else { + + const newValue = await wallItenmModel(organization).create({ modeluuid, modelname, position, type, csgposition, csgscale, quaternion, scale }); + return { success: true, message: 'wallIitem created', data: newValue, organization: organization } + } + + // Send response with the created document + } catch (error) { + console.error('Error creating wallIitem:', error); + return { success: false, message: 'Error creating or updating camera', error } + } +} + +export const deleteWallItems = async (data: any) => { + try { + const { modeluuid, modelname, organization } = data; + + + const findValue = await wallItenmModel(organization).findOneAndDelete({ modeluuid: modeluuid, modelname: modelname }) + if (!findValue) { + return { success: false, message: 'model not found', organization: organization } + + } else { + + return { success: true, message: 'wallitem deleted', data: findValue, organization: organization } + } + } catch (error) { + console.error('Error get wallitem:', error); + return { success: false, message: 'Failed to delete wallitem', error } + + } +} diff --git a/src/socket-server/services/camera/camera-Controller.ts b/src/socket-server/services/camera/camera-Controller.ts new file mode 100644 index 0000000..3975c0d --- /dev/null +++ b/src/socket-server/services/camera/camera-Controller.ts @@ -0,0 +1,31 @@ +import { Request, Response } from "express"; +import { Socket } from "socket.io"; +import cameraModel from "../../../shared/model/camera/camera-Model"; + +export const createCamera = async (data: any,) => { + try { + + const { userId, position, target, organization,rotation } = data + + const findCamera = await cameraModel(organization).findOne({ userId: userId }) + if (findCamera) { + const updateCamera = await cameraModel(organization).findOneAndUpdate( + { userId: userId }, { position: position, target: target,rotation:rotation }, { new: true }); + // io.emit('cameraUpdateResponse', { success: true, message: 'Camera updated', data: updateCamera }); + return { success: true, message: 'Camera updated', data: updateCamera,organization:organization} + + } + else { + const newCamera = await cameraModel(organization).create({ userId, position, target,rotation }) + + return { success: false, message: 'Camera created' ,data:newCamera,organization:organization} + + } + + // Send response with the created document + } catch (error) { + console.error('Error creating camera:', error); + return { success: false, message: 'Error creating or updating camera', error, } + } +} + diff --git a/src/socket-server/services/environments/environments-controller.ts b/src/socket-server/services/environments/environments-controller.ts new file mode 100644 index 0000000..ebadce7 --- /dev/null +++ b/src/socket-server/services/environments/environments-controller.ts @@ -0,0 +1,33 @@ +import { Request, Response } from "express"; +import environmentModel from "../../../shared/model/environments/environments-Model"; + + + +export const setEnvironment = async (data: any,) => { + try { + const { userId,roofVisibility,wallVisibility,shadowVisibility, organization } = data + + const findvalue = await environmentModel(organization).findOne({ userId: userId }) + if (findvalue) { + const updatevalue = await environmentModel(organization).findOneAndUpdate( + { userId: userId }, { roofVisibility:roofVisibility,wallVisibility:wallVisibility,shadowVisibility:shadowVisibility }, { new: true }); + // res.status(201).json(updatevalue); + return { success: true, message: 'evironments updated', data: updatevalue,organization:organization } + + } else { + const newValue = await environmentModel(organization).create({ userId, roofVisibility, wallVisibility,shadowVisibility }); + + return { success: true, message: 'evironments created', data: newValue,organization:organization } + // res.status(201).json(newValue); + + } + + + + // Send response with the created document + } catch (error) { + console.error('Error creating evironments:', error); + return { success: false, message: 'Error creating or updating evironments', error } + } +} + diff --git a/src/socket-server/services/lines/line-Controller.ts b/src/socket-server/services/lines/line-Controller.ts new file mode 100644 index 0000000..17b66ce --- /dev/null +++ b/src/socket-server/services/lines/line-Controller.ts @@ -0,0 +1,100 @@ +import { Request, Response } from "express"; +import lineModel from "../../../shared/model/lines/lines-Model"; + + +export const createLineItems = async (data: any)=>{ + try { + const {organization,layer,line,type}=data + const newLine = await lineModel(organization).create({ layer,line,type }); + return { success: true, message: 'line create', data: newLine,organization:organization } + + // Send response with the created document + } catch (error) { + + return { success: false, message: 'Error create line', error } + + } + } +export const updateLineItems = async (data: any)=>{ + try { + const {organization,uuid,position,}=data + // const findLine = await lineModel(organization).find({ 'line.uuid': uuid }); + // Update the position of the line matching the uuid + const updateResult = await lineModel(organization).updateMany( + { 'line.uuid': uuid }, // Filter: Find the line with the given uuid + { $set: { 'line.$.position': position } } // Update the position and type + ); + return { success: true, message: 'line updated', data: {uuid:uuid,position:position},organization:organization } + + // Send response with the created document + } catch (error) { + console.error('Error creating Lines:', error); + return { success: false, message: 'Error updating line', error } + } + } + + export const deleteLineItems = async (data: any)=>{ + try { + const {organization,line}=data + + const inputUuids = line.map((item: any) => item.uuid); + + // const findValue = await lineModel(organization).findOneAndDelete({ + + // line: { $elemMatch: { uuid: { $in: inputUuids } } }, + // }); + const findValue = await lineModel(organization).findOneAndDelete({ + "line.uuid": { $all: inputUuids } // Ensure all UUIDs are present in the `line` key + }); + + if (!findValue) { + return { success: false, message: 'line not found',organization:organization } + } else { + return { success: true, message: 'line deleted', data: findValue,organization:organization } + } + } catch (error) { + console.error('Error delete Lines:', error); + return { success: false, message: 'Failed to delete line', error } + } + } + export const deleteLayer = async (data: any)=>{ + try { + const {organization,layer}=data + + const findValue = await lineModel(organization).find({ layer: layer }); + + if (!findValue) { + return { success: false, message: 'layer not found' } + } else { + await lineModel(organization).deleteMany({ layer: layer }); + + // Update documents with layer greater than -1 + const updateResult = await lineModel(organization).updateMany( + { layer: { $gt:layer} }, + { $inc: { layer: -1 } } // Example operation: decrementing layer by 1 + ); + return { success: true, message: 'layer deleted', data: layer,organization:organization } + } + } catch (error) { + console.error('Error delete layer:', error); + return { success: false, message: 'Failed to delete layer', error } + } + } + export const deleteLinPoiteItems = async (data: any)=>{ + try { + const {organization,uuid}=data + + + const findValue = await lineModel(organization).deleteMany({ 'line.uuid': uuid }) + + if (!findValue) { + return { success: false, message: 'line not found',organization:organization } + } else { + + return { success: true, message: 'point deleted', data: uuid ,organization:organization} + } + } catch (error) { + console.error('Error delete Lines:', error); + return { success: false, message: 'Failed to delete point', error } + } + } diff --git a/src/socket-server/services/users/user-controller.ts b/src/socket-server/services/users/user-controller.ts new file mode 100644 index 0000000..c75ff9d --- /dev/null +++ b/src/socket-server/services/users/user-controller.ts @@ -0,0 +1,97 @@ +import cameraModel from "../../../shared/model/camera/camera-Model" +import userModel from "../../../shared/model/user-Model" + +export const activeUsers = async (data: any) => { + try { + if (data && data.email) { + + const email = data.email + const organization = email.split("@")[1].split(".")[0] + + const findUser = await userModel(organization).findOne({email}) + + if (findUser) { + const updateActiveStatus = await userModel(organization).findOneAndUpdate({email:findUser.email},{activeStatus:"online"},{new:true}) + + if (updateActiveStatus) { + const cameraDatas=await cameraModel(organization).findOne({userId:updateActiveStatus._id}) + .select("position target rotation -_id"); + + if (cameraDatas) { + const result = { + position: cameraDatas.position, + target: cameraDatas.target, + rotation: cameraDatas.rotation, + userData: { + _id: updateActiveStatus._id, + userName: updateActiveStatus.userName, + email: updateActiveStatus.email, + }, + }; + + + + return { success: true, message: 'user connect ', data: result,organization:organization } + // return result; + } + } + + } + }else { + console.error('Invalid data or missing email:', data); + // Handle the error or return a default value + // Example: Return an error response if the email is invalid + + return { success: false, message: 'Email is missing or invalid', } + // return res.status(400).send({ message: 'Email is missing or invalid' }); + } + + + // // return []; + } catch (error) { + + return { success: false, message:error} + } +} + +export const activeUserOffline = async (data: any) => { + try { + + const email = data.email + const organization = email.split("@")[1].split(".")[0] + + const findUsers = await userModel(organization).findOne({email}) + // console.log('findUsers: ', findUsers); + if (findUsers) { + const updateActiveStatus = await userModel(organization).findOneAndUpdate({email:email},{activeStatus:"offline"},{new:true}) + // console.log('updateActiveStatus: ',updateActiveStatus); + if (updateActiveStatus) { + const cameraDatas=await cameraModel(organization).findOne({userId:updateActiveStatus._id}) + .select("position target rotation -_id"); + // console.log('cameraDatas: ', cameraDatas); + if (cameraDatas) { + const result = { + position: cameraDatas.position, + target: cameraDatas.target, + rotation: cameraDatas.rotation, + userData: { + _id: updateActiveStatus._id, + userName: updateActiveStatus.userName, + email: updateActiveStatus.email, + }, + }; + + // console.log("Formatted Result:", result); + + + // return result; + return { success: true, message: 'user disconnect', data: result,organization:organization } + } + } + } + // // return []; + } catch (error) { + + return { success: false, message: error} + } +} diff --git a/src/socket-server/socket/events.ts b/src/socket-server/socket/events.ts new file mode 100644 index 0000000..3ace75c --- /dev/null +++ b/src/socket-server/socket/events.ts @@ -0,0 +1,45 @@ +export const EVENTS = { + connection: "connection", + disconnect:"disconnect", + //userActiveStatus + userConnect:"userConnectRespones", + userDisConnect:"userDisConnectRespones", + // Room management events + joinRoom: 'joinRoom', + createroom: "createRoom", // When a client joins a room + leaveRoom: 'leaveRoom', // When a client leaves a room + roomCreated: 'roomCreated', // When a new room is created + roomDeleted: 'roomDeleted', // When a room is deleted + + // Camera //response + setCamera: 'v1:Camera:set', + cameraCreateResponse: "cameraCreateResponse", // Response for camera creation + cameraUpdateResponse: "cameraUpdateResponse", // Response for camera update + cameraError: "cameraError", + //Environment + setenvironment: "v1:Environment:set", + EnvironmentUpdateResponse: "EnvironmentUpdateResponse", + //FloorItems + setFloorItems: "v1:FloorItems:set", + FloorItemsUpdateResponse: "FloorItemsUpdateResponse", + deleteFloorItems: "v1:FloorItems:delete", + FloorItemsDeleteResponse: "FloorItemsDeleteResponse", + floorItemError: "floorItemError", + //WALLItems + setWallItems: "v1:wallItems:set", + wallItemsUpdateResponse: "wallItemsUpdateResponse", + deleteWallItems: "v1:wallItems:delete", + wallItemsDeleteResponse: "wallItemsDeleteResponse", + wallItemError: "wallItemError", + //Lines + createLine:"v1:Line:create", + createLineResponse:"Line:response:create", + updateLine:"v1:Line:update", + updateLineResponse:"Line:response:update", + deleteLine:"v1:Line:delete", + deleteLineResponse:"Line:response:delete", + deletePoint:"v1:Line:delete:point", + deletePointResponse:"Line:response:delete:point", + deleteLineLayer:"v1:Line:delete:layer", + deleteLineLayerResponse:"Line:response:delete:layer", +} \ No newline at end of file diff --git a/src/socket-server/socket/socketManager.ts b/src/socket-server/socket/socketManager.ts new file mode 100644 index 0000000..caa5c3d --- /dev/null +++ b/src/socket-server/socket/socketManager.ts @@ -0,0 +1,421 @@ +import { Server, Socket } from 'socket.io'; +import { EVENTS } from './events'; +import { createCamera } from '../services/camera/camera-Controller'; +import { setEnvironment } from '../services/environments/environments-controller'; +import { deleteFloorItems, setFloorItems } from '../services/assets/flooritem-Controller'; +import { deleteWallItems, setWallItems } from '../services/assets/wallitem-Controller'; +import { deleteLineItems, deleteLinPoiteItems, updateLineItems ,createLineItems, deleteLayer} from '../services/lines/line-Controller'; +import { activeUserOffline, activeUsers } from '../services/users/user-controller'; + + + + + +const cameraHandleEvent =async (event: string, socket: Socket, data: any,io:any) => { + switch (event) { + + case EVENTS.setCamera: + const result = await createCamera(data,); + // console.log('result: ', result); + if (result.success) { + // console.log('result.success: ', result.success); + // if (result.message === 'Camera updated') { + // Emit update response + + io.emit(EVENTS.cameraUpdateResponse, { + success: true, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + }); + } else if (result.message === 'Camera created') { + // Emit create response + io.emit(EVENTS.cameraCreateResponse, { + success: true, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + }); + // } + } else { + // Emit error response + socket.emit(EVENTS.cameraError, { + success: false, + message: result.message, + error: result.error, + socketId: socket.id, + organization:result.organization + }); + } + break; + // case EVENTS.updataControlle_iot: + // updateControlle(data); + break; + // case EVENTS.deleteControlle_iot: + // deleteControlle(data); + break; + + + default: + // console.error(`Unhandled event type: ${event}`); + } +} +const EnvironmentHandleEvent =async (event: string, socket: Socket, data: any,io:any) => { + switch (event) { + + case EVENTS.setenvironment: + const result = await setEnvironment(data,); + // console.log('result: ', result); + if (result.success) { + // if (result.message === 'Camera updated') { + // Emit update response + + io.emit(EVENTS.EnvironmentUpdateResponse, { + success: true, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + }); + // } else if (result.message === 'evironments created') { + // // Emit create response + // io.emit(EVENTS.cameraCreateResponse, { + // success: true, + // message: result.message, + // data: result.data, + // }); + // } + } else { + // Emit error response + socket.emit(EVENTS.cameraError, { + success: false, + message: result.message, + error: result.error, + socketId: socket.id, + organization:result.organization + }); + } + break; + // case EVENTS.updataControlle_iot: + // updateControlle(data); + break; + // case EVENTS.deleteControlle_iot: + // deleteControlle(data); + break; + + + default: +// console.error(`Unhandled event type: ${event}`); + } +} +const floorItemsHandleEvent =async (event: string, socket: Socket, data: any,io:any) => { + switch (event) { + + case EVENTS.setFloorItems:{ + const result = await setFloorItems(data); + // console.log('result: ', result); + if (result.success) { + io.emit(EVENTS.FloorItemsUpdateResponse, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + }); + + } else { + // Emit error response + socket.emit(EVENTS.floorItemError, { + success: false, + message: result.message, + error: result.error, + socketId: socket.id, + organization:result.organization + }); + } + break;} + case EVENTS.deleteFloorItems:{ + const result = await deleteFloorItems(data); + // console.log('result: ', result); + if (result.success) { + + + io.emit(EVENTS.FloorItemsDeleteResponse, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + }); + + } else { + // Emit error response + socket.emit(EVENTS.floorItemError, { + success: false, + message: result.message, + error: result.error, + socketId: socket.id, + organization:result.organization + }); + } + break;} + + default: +// console.error(`Unhandled event type: ${event}`); + } +} +const wallItemsHandleEvent =async (event: string, socket: Socket, data: any,io:any) => { + switch (event) { + + case EVENTS.setWallItems:{ + const result = await setWallItems(data); + // console.log('result: ', result); + if (result.success) { + io.emit(EVENTS.wallItemsUpdateResponse, { + success: true, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + }); + + } else { + // Emit error response + socket.emit(EVENTS.wallItemError, { + success: false, + message: result.message, + error: result.error, + }); + } + break; + } + case EVENTS.deleteWallItems:{ + const result = await deleteWallItems(data); + // console.log('result: ', result); + if (result.success) { + + + io.emit(EVENTS.wallItemsDeleteResponse, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + }); + + } else { + // Emit error response + socket.emit(EVENTS.wallItemError, { + success: false, + message: result.message, + error: result.error, + }); + } + break; +} + + default: +// console.error(`Unhandled event type: ${event}`); + } +} +const lineHandleEvent =async (event: string, socket: Socket, data: any,io:any) => { + switch (event) { + case EVENTS.createLine:{ + const result = await createLineItems(data); + // console.log('result: ', result); + if (result.success) { + + + io.emit(EVENTS.createLineResponse, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + }); + + } else { + // Emit error response + // socket.emit(EVENTS.wallItemError, { + // success: false, + // message: result.message, + // error: result.error, + // }); + } + break; + } + case EVENTS.updateLine: { + const result = await updateLineItems(data); + // console.log('result: ', result); + if (result.success) { + + + io.emit(EVENTS.updateLineResponse, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization: result.organization + + }); + + } + break; + } + case EVENTS.deleteLine:{ + const result = await deleteLineItems(data); + // console.log('result: ', result); + if (result.success) { + + + io.emit(EVENTS.deleteLineResponse, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + }); + + } else { + // Emit error response + // socket.emit(EVENTS.wallItemError, { + // success: false, + // message: result.message, + // error: result.error, + // }); + } + break; +} +case EVENTS.deletePoint:{ + const result = await deleteLinPoiteItems(data); + // console.log('result: ', result); + if (result.success) { + + io.emit(EVENTS.deletePointResponse, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + }); + +} else { + // Emit error response + // socket.emit(EVENTS.wallItemError, { + // success: false, + // message: result.message, + // error: result.error, + // }); +} + break; +} +case EVENTS.deleteLineLayer:{ + const result = await deleteLayer(data); + // console.log('result: ', result); + if (result.success) { + + io.emit(EVENTS.deleteLineLayerResponse, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + }); + +} else { + // Emit error response + // socket.emit(EVENTS.wallItemError, { + // success: false, + // message: result.message, + // error: result.error, + // }); +} + break; +} + + default: +// console.error(`Unhandled event type: ${event}`); + } +} +const userStatus =async (event: string, socket: Socket, data: any,io:any) => { + switch (event) { + case EVENTS.connection: { + // console.log('EVENTS.connection: ', EVENTS.connection); + // console.log('event: ', event); + const result = await activeUsers(data); + if (result?.success) { + // console.log('result.success: ', result.success) + + io.emit(EVENTS.userConnect, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + });} + break; + } + case EVENTS.disconnect: { + // console.log('EVENTS.disconnect: ', EVENTS.connection); + // console.log('event: ', event); + const result = await activeUserOffline(data); + if (result?.success) { + // console.log('result.success: ', result.success) + + io.emit(EVENTS.userDisConnect, { + success: true || false, + message: result.message, + data: result.data, + socketId: socket.id, + organization:result.organization + + });} + break; + } + } +} +export const initSocketServer = (httpServer: any) => { + const io = new Server(httpServer, { + cors: { + origin: '*', // Allow CORS for all origins (adjust in production) + methods: ['GET', 'POST'], + }, + }); + + // Listen for new connections + io.on(EVENTS.connection, (socket: Socket) => { + // console.log(`New client connected: ${socket.id}`); +// console.log(socket.handshake.auth); +userStatus(EVENTS.connection, socket, socket.handshake.auth,io); + + // Handle all incoming events with the handleEvent function + socket.onAny((event: string, data: any,) => { + cameraHandleEvent(event, socket, data,io); + EnvironmentHandleEvent(event, socket, data,io); + floorItemsHandleEvent(event, socket, data,io); + wallItemsHandleEvent(event, socket, data,io); + lineHandleEvent(event, socket, data,io); + + + }); + socket.on(EVENTS.disconnect, (reason: string) => { + // console.log(`Client disconnected: ${socket.id}, Reason: ${reason}`); + // console.log(socket.handshake.auth); + userStatus(EVENTS.disconnect, socket, socket.handshake.auth,io); + // Perform cleanup or other necessary actions + }); + }); + + return io; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..56a8ab8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,110 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}