Merge branch 'develop' into adiDev

This commit is contained in:
AdisakKanthawilang 2025-04-01 13:38:34 +07:00
commit 26ef28f5cf
12 changed files with 1658 additions and 81 deletions

View file

@ -67,40 +67,40 @@ jobs:
docker compose pull docker compose pull
docker compose up -d docker compose up -d
echo "${{ steps.gen_ver.outputs.image_ver }}"> success echo "${{ steps.gen_ver.outputs.image_ver }}"> success
# - name: Notify Discord Success - name: Notify Discord Success
# if: success() if: success()
# run: | run: |
# curl -H "Content-Type: application/json" \ curl -H "Content-Type: application/json" \
# -X POST \ -X POST \
# -d '{ -d '{
# "embeds": [{ "embeds": [{
# "title": "✅ Deployment Success!", "title": "✅ Deployment Success!",
# "description": "**Details:**\n- Image: `${{env.IMAGE_NAME}}`\n- Version: `${{ steps.gen_ver.outputs.image_ver }}`\n- Deployed by: `${{github.actor}}`", "description": "**Details:**\n- Image: `${{env.IMAGE_NAME}}`\n- Version: `${{ steps.gen_ver.outputs.image_ver }}`\n- Deployed by: `${{github.actor}}`",
# "color": 3066993, "color": 3066993,
# "footer": { "footer": {
# "text": "Release Notification", "text": "Release Notification",
# "icon_url": "https://example.com/success-icon.png" "icon_url": "https://example.com/success-icon.png"
# }, },
# "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'" "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
# }] }]
# }' \ }' \
# ${{ secrets.DISCORD_WEBHOOK }} ${{ secrets.DISCORD_WEBHOOK }}
# - name: Notify Discord Failure - name: Notify Discord Failure
# if: failure() if: failure()
# run: | run: |
# curl -H "Content-Type: application/json" \ curl -H "Content-Type: application/json" \
# -X POST \ -X POST \
# -d '{ -d '{
# "embeds": [{ "embeds": [{
# "title": "❌ Deployment Failed!", "title": "❌ Deployment Failed!",
# "description": "**Details:**\n- Image: `${{env.IMAGE_NAME}}`\n- Version: `${{ steps.gen_ver.outputs.image_ver }}`\n- Attempted by: `${{github.actor}}`", "description": "**Details:**\n- Image: `${{env.IMAGE_NAME}}`\n- Version: `${{ steps.gen_ver.outputs.image_ver }}`\n- Attempted by: `${{github.actor}}`",
# "color": 15158332, "color": 15158332,
# "footer": { "footer": {
# "text": "Release Notification", "text": "Release Notification",
# "icon_url": "https://example.com/failure-icon.png" "icon_url": "https://example.com/failure-icon.png"
# }, },
# "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'" "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
# }] }]
# }' \ }' \
# ${{ secrets.DISCORD_WEBHOOK }} ${{ secrets.DISCORD_WEBHOOK }}

230
package-lock.json generated
View file

@ -29,6 +29,7 @@
"querystring": "^0.2.1", "querystring": "^0.2.1",
"redis": "^3.1.2", "redis": "^3.1.2",
"reflect-metadata": "^0.2.1", "reflect-metadata": "^0.2.1",
"socket.io": "^4.8.1",
"swagger-ui-express": "^5.0.0", "swagger-ui-express": "^5.0.0",
"tsoa": "^6.0.1", "tsoa": "^6.0.1",
"typeorm": "^0.3.19", "typeorm": "^0.3.19",
@ -347,6 +348,12 @@
"node": ">=14" "node": ">=14"
} }
}, },
"node_modules/@socket.io/component-emitter": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
"license": "MIT"
},
"node_modules/@sqltools/formatter": { "node_modules/@sqltools/formatter": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz",
@ -468,7 +475,6 @@
"version": "2.8.17", "version": "2.8.17",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
"integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
"dev": true,
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
} }
@ -873,6 +879,15 @@
} }
] ]
}, },
"node_modules/base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
"license": "MIT",
"engines": {
"node": "^4.5.0 || >= 5.9"
}
},
"node_modules/bignumber.js": { "node_modules/bignumber.js": {
"version": "9.0.0", "version": "9.0.0",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
@ -1626,6 +1641,88 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/engine.io": {
"version": "6.6.4",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz",
"integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==",
"license": "MIT",
"dependencies": {
"@types/cors": "^2.8.12",
"@types/node": ">=10.0.0",
"accepts": "~1.3.4",
"base64id": "2.0.0",
"cookie": "~0.7.2",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1"
},
"engines": {
"node": ">=10.2.0"
}
},
"node_modules/engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/engine.io/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/engine.io/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/engine.io/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/engine.io/node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/es-abstract": { "node_modules/es-abstract": {
"version": "1.22.3", "version": "1.22.3",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
@ -4153,6 +4250,137 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/socket.io": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
"integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.4",
"base64id": "~2.0.0",
"cors": "~2.8.5",
"debug": "~4.3.2",
"engine.io": "~6.6.0",
"socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.2.0"
}
},
"node_modules/socket.io-adapter": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz",
"integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==",
"license": "MIT",
"dependencies": {
"debug": "~4.3.4",
"ws": "~8.17.1"
}
},
"node_modules/socket.io-adapter/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/socket.io-adapter/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/socket.io-adapter/node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/socket.io-parser/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/socket.io/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/socket.io/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",

View file

@ -49,6 +49,7 @@
"querystring": "^0.2.1", "querystring": "^0.2.1",
"redis": "^3.1.2", "redis": "^3.1.2",
"reflect-metadata": "^0.2.1", "reflect-metadata": "^0.2.1",
"socket.io": "^4.8.1",
"swagger-ui-express": "^5.0.0", "swagger-ui-express": "^5.0.0",
"tsoa": "^6.0.1", "tsoa": "^6.0.1",
"typeorm": "^0.3.19", "typeorm": "^0.3.19",

View file

@ -14,12 +14,12 @@ import logMiddleware from "./middlewares/logs";
import { CommandController } from "./controllers/CommandController"; import { CommandController } from "./controllers/CommandController";
import { ProfileSalaryController } from "./controllers/ProfileSalaryController"; import { ProfileSalaryController } from "./controllers/ProfileSalaryController";
// import { initWebSocket } from "./services/webSocket"; import { initWebSocket } from "./services/webSocket";
async function main() { async function main() {
await AppDataSource.initialize(); await AppDataSource.initialize();
// initWebSocket(); initWebSocket();
const app = express(); const app = express();

View file

@ -3065,6 +3065,9 @@ export class CommandController extends Controller {
commandCode?: string | null; commandCode?: string | null;
commandName?: string | null; commandName?: string | null;
remark: string | null; remark: string | null;
positionTypeNew?: string | null;
positionLevelNew?: string | null;
positionNameNew?: string | null;
}[]; }[];
}, },
) { ) {
@ -3145,6 +3148,9 @@ export class CommandController extends Controller {
profile.leaveRemark = _null; profile.leaveRemark = _null;
profile.leaveDate = _null; profile.leaveDate = _null;
profile.leaveType = _null; profile.leaveType = _null;
profile.position = item.positionNameNew ?? _null;
profile.posTypeId = item.positionTypeNew ?? _null;
profile.posLevelId = item.positionLevelNew ?? _null
} }
let userKeycloakId; let userKeycloakId;
const checkUser = await getUserByUsername(profile.citizenId); const checkUser = await getUserByUsername(profile.citizenId);

View file

@ -5626,6 +5626,9 @@ export class OrganizationController extends Controller {
const data = await this.orgRootRepository.find({ const data = await this.orgRootRepository.find({
where: { orgRevisionId: orgRevisionActive.id }, where: { orgRevisionId: orgRevisionActive.id },
order: {
orgRootOrder: "ASC",
},
}); });
return new HttpSuccess(data.map((x) => x.id)); return new HttpSuccess(data.map((x) => x.id));
} }
@ -5647,6 +5650,9 @@ export class OrganizationController extends Controller {
const data = await this.orgRootRepository.find({ const data = await this.orgRootRepository.find({
where: { orgRevisionId: orgRevisionActive.id }, where: { orgRevisionId: orgRevisionActive.id },
order: {
orgRootOrder: "ASC",
},
}); });
return new HttpSuccess(data); return new HttpSuccess(data);
} }
@ -5686,6 +5692,7 @@ export class OrganizationController extends Controller {
"orgChild1s.orgChild2s.orgChild3s.orgChild4s", "orgChild1s.orgChild2s.orgChild3s.orgChild4s",
], ],
order: { order: {
orgRootOrder: "ASC",
orgChild1s: { orgChild1s: {
orgChild1Order: "ASC", orgChild1Order: "ASC",
orgChild2s: { orgChild2s: {

View file

@ -198,4 +198,22 @@ export class ProfileAssistanceController extends Controller {
return new HttpSuccess(); return new HttpSuccess();
} }
@Post("status")
public async editStatusProfileAssistance(
@Body() body: { status: string; refId: string },
@Request() req: RequestWithUser,
) {
const record = await this.profileAssistanceRepo.findOneBy({ refId: body.refId });
if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
record.status = body.status.trim().toLocaleUpperCase();
record.lastUpdateUserId = req.user.sub;
record.lastUpdateFullName = req.user.name;
record.lastUpdatedAt = new Date();
this.profileAssistanceRepo.save(record);
return new HttpSuccess();
}
} }

View file

@ -15,6 +15,13 @@ export class ProfileAssistance extends EntityBase {
}) })
profileId: string; profileId: string;
@Column({
comment: "สถานะ",
default: "PENDING",
length: 20,
})
status: string;
@Column({ @Column({
nullable: true, nullable: true,
comment: "หน่วยงานที่ให้ช่วยราชการ", comment: "หน่วยงานที่ให้ช่วยราชการ",

View file

@ -464,10 +464,20 @@ export type LogSequence = {
}; };
export function setLogDataDiff(req: RequestWithUser, data: DataDiff) { export function setLogDataDiff(req: RequestWithUser, data: DataDiff) {
req.app.locals.logData.dataDiff = { // Check if data.before and data.after are valid objects
before: JSON.stringify(data.before), if (
after: JSON.stringify(data.after), data.before &&
}; typeof data.before === "object" &&
data.after &&
typeof data.after === "object"
) {
req.app.locals.logData.dataDiff = {
before: JSON.stringify(data.before),
after: JSON.stringify(data.after),
};
} else {
console.error("Invalid data provided: both before and after must be valid objects.");
}
} }
export function addLogSequence(req: RequestWithUser, data: LogSequence) { export function addLogSequence(req: RequestWithUser, data: LogSequence) {

File diff suppressed because one or more lines are too long

View file

@ -24,6 +24,7 @@ import { Position } from "../entities/Position";
import { In, Not } from "typeorm"; import { In, Not } from "typeorm";
import { PosMasterAct } from "../entities/PosMasterAct"; import { PosMasterAct } from "../entities/PosMasterAct";
import { PermissionOrg } from "../entities/PermissionOrg"; import { PermissionOrg } from "../entities/PermissionOrg";
import { sendWebSocket } from "./webSocket";
export let sendToQueue: (payload: any) => void; export let sendToQueue: (payload: any) => void;
export let sendToQueueOrg: (payload: any) => void; export let sendToQueueOrg: (payload: any) => void;
@ -122,6 +123,15 @@ async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
relations: ["commandType", "commandRecives"], relations: ["commandType", "commandRecives"],
}); });
if (!command) return true; if (!command) return true;
sendWebSocket(
"send-command-notification",
{
success: true,
message: `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543}`,
payload: command,
},
{ userId: user.sub },
).catch(console.error);
const path = commandTypePath(command.commandType.code); const path = commandTypePath(command.commandType.code);
if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ"); if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
return await new CallAPI() return await new CallAPI()
@ -156,11 +166,30 @@ async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
console.log("[AMQ] Excecute Command Success"); console.log("[AMQ] Excecute Command Success");
Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt }); Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt });
const result = await repo.save(command).catch((e) => console.log(e)); const result = await repo.save(command).catch((e) => console.log(e));
if (result) return true;
return false; sendWebSocket(
"send-command-notification",
{
success: true,
message: `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} เสร็จสิ้น`,
payload: command,
},
{ userId: user.sub },
).catch(console.error);
return !!result;
}) })
.catch((e) => { .catch((e) => {
console.error(e); console.error(e);
sendWebSocket(
"send-command-notification",
{
success: false,
message: `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} ผิดพลาด`,
payload: command,
},
{ userId: user.sub },
).catch(console.error);
return false; return false;
}); });
} }

View file

@ -1,43 +1,72 @@
// import { WebSocketServer } from "ws"; import { Server } from "socket.io";
// let wss: WebSocketServer; let io: Server;
// export function initWebSocket() { export function initWebSocket() {
// wss = new WebSocketServer({ port: 13002, path: "/api/v1/org-socket" }); if (io) return;
// // การจัดการคำขออัปเกรดจาก HTTP เป็น WebSocket io = new Server({ cors: { origin: "*" }, path: "/api/v1/org-socket" });
// wss.on("upgrade", (request: any, socket: any, head: any) => {
// console.log("🔹 Handling upgrade request...");
// wss.handleUpgrade(request, socket, head, (ws: any) => {
// console.log("🔹 WebSocket connection established");
// wss.emit("connection", ws, request);
// });
// });
// wss.on("connection", (ws: any) => { io.use(async (socket, next) => {
// console.log("✅ Client connected to WebSocket"); const token = socket.handshake.auth.token;
// ws.on("close", () => { const res = await fetch(`${process.env.AUTH_REALM_URL}/protocol/openid-connect/userinfo`, {
// console.log("❌ Client disconnected"); headers: { authorization: `Bearer ${token}` },
// }); }).catch((e) => console.error(e));
// ws.on("error", (error: any) => { if (res?.ok) {
// console.error("WebSocket error:", error); socket.data.user = await res.json();
// }); }
// });
// }
// export async function sendWebSocket(data: any) { next();
// if (!wss) initWebSocket(); });
// wss.clients.forEach((client: any) => {
// if (client.readyState === WebSocket.OPEN) { io.on("connection", (ws) => {
// const message = JSON.stringify(data); console.log("✅ Client connected to WebSocket");
// console.log("📤 Sending data to client:", message);
// client.send(message, (err: any) => { ws.on("close", () => {
// if (err) { console.log("❌ Client disconnected");
// console.error("❌ Error sending message:", err); });
// }
// }); ws.on("error", (error: any) => {
// } console.error("WebSocket error:", error);
// }); });
// } });
io.listen(13002);
}
export async function sendWebSocket(
event: string,
data: any,
opts?: {
roles?: string | string[];
userId?: string | string[];
},
) {
if (!io) initWebSocket();
for (let [id, session] of io.of("/").sockets) {
const user: {
sub: string;
name: string;
given_name: string;
family_name: string;
preferred_username: string;
email: string;
role: string[];
} = session.data.user;
if (!user) continue;
if (typeof opts?.roles === "string") opts.roles = [opts.roles];
if (typeof opts?.userId === "string") opts.userId = [opts.userId];
if (
user.role?.some((v) => opts?.roles?.includes(v)) ||
opts?.userId?.some((v) => user.sub === v)
) {
io.to(id).emit(event, JSON.stringify(data));
}
}
}