2way-vtrc-api — Repository Map
บทนี้เป็นแผนที่ไฟล์ของ 2way-vtrc-api (branch: prod, ~158 tracked files) — Express monolith ที่ mount route ทีละไฟล์ ไม่มี NestJS module boundary
ชื่อ package คือ "express" (2way-vtrc-api/package.json:2) — ไม่ตรงกับชื่อ repo
แผนที่โฟลเดอร์ระดับ repo
2way-vtrc-api/ (branch: prod)
├── app.ts # entrypoint เดียว (~286 บรรทัด): Sentry, CORS, ~50 route mounts, socket.io
├── config.ts # LINE_CHANNEL_SECRET / LINE_CHANNEL / LINE_AUTH จาก process.env
├── package.json # name=express, start=ts-node app.ts
├── Dockerfile # node:18-alpine3.15, yarn, EXPOSE 3000 (ไม่ตรง listen 8001)
├── docker-compose.yml # ports 8001:8001, volume storage/2way
├── .env / .env.prod / .env.uat / .envdev
├── tsconfig.json / jest.config.js / .eslintrc.json
├── middleware/
│ ├── checkbypasstoken.ts # checkBypassTokenMiddleWare + checkApiKeyMiddleWare (+ "testnaja")
│ ├── checkByPassTokenLine.ts # LINE access-token verify (+ "testnaja")
│ ├── checkbypasswhenredirect.ts
│ ├── checkbypaasjwtOTP.ts # typo ในชื่อไฟล์: bypaas
│ ├── checkbypass.ts
│ ├── jwtpassport.ts # passport-jwt — always done(null, true)
│ ├── authologin.ts
│ └── validator/{createIncident,updateincident}.ts
├── model/ # Sequelize factories (MSSQL)
│ ├── announcement/, autoReply/, faqs/, feedback/, incident/, survey/
│ ├── userLine/{userLine,userProfile}.ts
│ ├── otp/otp.ts, token/token.ts
│ ├── login.ts, post.ts, commentpost.ts
│ └── mongo/chatSchema.ts # Mongoose schema (chat)
├── util/
│ ├── db.config.ts # Sequelize instance + model registry
│ ├── env.ts # MSSQL host/user/password hardcode (Prod block active)
│ ├── mongo.config.ts # Mongo URI hardcode (connection ปิดใน app.ts)
│ ├── jwt.config.ts # SECRET hardcode + jwtExpiration=60 (test values)
│ ├── helper/{empty,jwtdecode,transferData}.ts
│ ├── axiosinterceptors/{cdb,vtrc}.connector.ts
│ ├── emailtemplate/
│ └── line/
├── lib/
│ ├── Socket.func.ts / InsertChat.func.ts / InsertChatBot.func.ts
│ ├── Uploadimage.class.ts / Dateformat.class.ts / Emailsender.class.ts
│ ├── Usermanage.class.ts / Otp.ts / helper.ts / model.ts (syncModelToTable — ปิดใน app.ts)
├── routes/
│ ├── auth/{login,redirectbypass,refreshtoken}.ts
│ ├── secure/post.ts
│ ├── post.ts, commentpost.ts
│ ├── MeetingAPI/{user,index,mock}.ts # mock / JSONPlaceholder-style
│ ├── TwoWayAPI/
│ │ ├── index.ts # mock aggregator (~1849 บรรทัด)
│ │ ├── mock.ts
│ │ ├── announcement/ (8 files)
│ │ ├── autoReply/ (4)
│ │ ├── chatCenter/ (3) # mount ถูก comment ใน app.ts
│ │ ├── faqs/ (6)
│ │ ├── feedback/ (9)
│ │ ├── incident/ (9)
│ │ ├── survey/ (9)
│ │ ├── sso/ (5)
│ │ ├── userLine/ (5)
│ │ ├── userLineCu/ (4)
│ │ └── userLine_bk/ # legacy backup — อย่าลบโดยไม่ตรวจ
│ ├── WebHookApi/ # LINE OA หลัก (RC)
│ ├── WebHookCuApi/ # LINE OA ฝั่ง CU
│ └── Feedback/ # (ถ้ามี)
├── storage/2way/ # ไฟล์อัปโหลด — serve ที่ /2way/file
├── __test__/ / coverage/ / ut-report/
└── test-report.htmlBoot sequence — จาก yarn start ถึง listen
Production / container entry คือ ts-node app.ts (package.json:7). ลำดับใน app.ts:
1. import express, Sentry, Tracing
│ app.ts:2-4
▼
2. const port = 8001 (hardcode)
│ app.ts:8
▼
3. // require('./util/mongo.config.ts'); ← Mongo ปิด
│ app.ts:10
▼
4. app.disable('x-powered-by') / disable('Server')
│ app.ts:14-15
▼
5. Swagger UI ที่ /docs (title ยังเป็น JSONPlaceholder)
│ app.ts:20-51
▼
6. Sentry.init({ dsn: hardcode, tracesSampleRate: 1.0 })
│ app.ts:53-68
▼
7. dotenv.config({ path: ".env" })
│ app.ts:70-72
▼
8. Sentry request / tracing / error handlers
│ app.ts:74-77
▼
9. static /2way/file → storage/2way/
│ app.ts:80
▼
10. bodyParser json 50mb + urlencoded
│ app.ts:83-84
▼
11. CORS headers: Origin *, Credentials true
│ app.ts:87-99
▼
12. Mount ~50 routers (ดูตารางด้านล่าง)
│ app.ts:101-263
▼
13. // syncModelToTable(); ← schema sync ปิด
│ app.ts:265
▼
14. app.listen(8001)
│ app.ts:267
▼
15. socket.io แนบ HTTP server, cors origin:*
│ app.ts:270-282
▼
16. io.on("connection", chatHandler)
app.ts:277-282ข้อควรจำ: ไม่มี global auth guard — แต่ละ route ไฟล์เลือก middleware เอง หรือไม่ใส่เลย
Route registration pattern
app.ts mount router 1 ไฟล์ = 1 endpoint แบบ manual ไม่มี aggregator กลางสำหรับ production routes (ยกเว้น mock ที่ /2way/TwoWayAPI)
พบ comment เลขนับ endpoint ค้างอยู่ (//7, //14, //23, //32, //39, //43, //48, app.ts:132,147,167,197,212,221,232) — หลักฐานว่าทีมเพิ่ม endpoint ทีละตัวต่อเนื่องโดยไม่มี refactor เป็น controller group
Pattern ในแต่ละไฟล์ route โดยทั่วไป:
const route = express.Router();
route.post("/", checkBypassTokenMiddleWare, async (req, res) => { ... });
module.exports = route;แล้ว mount ใน app.ts เป็น app.use('/2way/somePath', require('./routes/...'))
Endpoint catalog — production mounts ใน app.ts
ตารางนี้รวบรวม path ที่ app.use จริงใน app.ts (branch: prod) พร้อมประเภท auth ที่ route handler ใช้
Legacy / scaffold / mock
| Mount path | ไฟล์ | Auth ที่ handler ใช้ |
|---|---|---|
/2way/post | routes/post.ts | ไม่ใช้ bypass middleware หลัก |
/2way/secure/post | routes/secure/post.ts | checkBypassTokenMiddleWare บน /checkauth |
/2way/login | routes/auth/login.ts | ผสม — บาง path มี bypass, บาง path ไม่มี |
/2way/commentpost | routes/commentpost.ts | บาง mutation มี bypass; GET หลายตัวไม่มี |
/2way/MeetingAPI | routes/MeetingAPI/user.ts | mock — ไม่ query DB จริง |
/2way/TwoWayAPI | routes/TwoWayAPI/index.ts | mock — ตอบข้อมูลปลอม |
/2way/WebHookApi | routes/WebHookApi/index.ts | LINE webhook (ไม่มี Bearer bypass) |
/2way/cu/webHookApi | routes/WebHookCuApi/index.ts | LINE webhook CU |
Incident (7 + 2 Line variants)
| Mount path | ไฟล์ | Auth |
|---|---|---|
/2way/getListIncident | incident/getListIncident.ts | checkBypassTokenMiddleWare |
/2way/addNewIncident | incident/createIncident.ts | checkBypassTokenMiddleWare + validator |
/2way/dropdownIncidentType | incident/dropdownIncidentType.ts | checkBypassTokenMiddleWare |
/2way/dropdownIncidentProgressStatus | incident/dropdownIncidentProgressStatus.ts | checkBypassTokenMiddleWare |
/2way/getAllAndCountProgressStatus | incident/getAllAndCountProgressStatus.ts | checkBypassTokenMiddleWare |
/2way/updateIncident | incident/updateIncident.ts | ไม่มี auth middleware — มีแค่ validatorUpdateIncident (updateIncident.ts:23) |
/2way/getListIncidentByUserID | incident/getListIncidentByUserID.ts | checkBypassTokenMiddleWare |
/2way/addNewIncidentLine | incident/createIncidentLine.ts | checkBypassTokenLineMiddleWare |
/2way/dropdownIncidentTypeLine | incident/dropdownIncidentTypeLine.ts | checkBypassTokenLineMiddleWare |
Feedback (7 + 2 Line)
| Mount path | ไฟล์ | Auth |
|---|---|---|
/2way/getListFeedback | feedback/getListFeedback.ts | bypass token |
/2way/dropdownFeedbackType | feedback/dropdownFeedbackType.ts | bypass token |
/2way/addNewFeedback | feedback/createFeedback.ts | bypass token |
/2way/updateIsNewFeedback | feedback/updateIsNewFeedback.ts | bypass token |
/2way/updateCallbackStatusFeedback | feedback/updateCallbackStatusFeedback.ts | bypass token |
/2way/getAllAndCountCallbackStatus | feedback/getAllAndCountCallbackStatus.ts | bypass token |
/2way/dropdownCallbackStatus | feedback/dropdownCallbackStatus.ts | bypass token |
/2way/dropdownFeedbackTypeLine | feedback/dropdownFeedbackTypeLine.ts | LINE bypass |
/2way/addNewFeedbackLine | feedback/createFeedbackLine.ts | LINE bypass |
Survey (9)
| Mount path | Auth |
|---|---|
/2way/getListSurvey | bypass token |
/2way/addNewSurvey | bypass token |
/2way/getUserByCondition | bypass token |
/2way/dropdownOrg / dropdownDivision / dropdownDepartment | bypass token |
/2way/updateSurvey | bypass token |
/2way/updateIsReadedSurvey | LINE bypass |
/2way/getListSurveyByUserID | LINE bypass |
UserLine RC + CU
| Mount path | ไฟล์ | Auth |
|---|---|---|
/2way/verifyUserLine | userLine/verifyUserLine.ts | ไม่มี middleware บน route.post (import bypass แต่ไม่ได้ใส่ใน chain — verifyUserLine.ts:28) |
/2way/verifyOTPUserLine | userLine/verifyOTPUserLine.ts | ไม่มี |
/2way/createUserLine | userLine/createUserLine.ts | checkBypassJWTMiddleWare |
/2way/verifyUserLine/cu | userLineCu/verifyUserLine.ts | ไม่มีบน chain |
/2way/verifyOTPUserLine/cu | userLineCu/verifyOTPUserLine.ts | ไม่มี |
/2way/createUserLine/cu | userLineCu/createUserLine.ts | checkBypassJWTMiddleWare |
/2way/getProfile | userLine/getProfile.ts | ไม่มี (auth comment ปิด) |
/2way/getProfile/cu | userLineCu/getProfile.ts | ไม่มี (auth comment ปิด) |
/2way/verifyToken | userLine/verifyToken.ts | checkBypassMiddleWare |
FAQs / Announcement / AutoReply / SSO
| กลุ่ม | Mount prefix ตัวอย่าง | Auth หลัก |
|---|---|---|
| FAQs | /2way/getListFAQs, addNewFAQs, updateFAQs, updateStatusFAQs, sendMessageLineFAQsStepYes, createQuestion | bypass token |
| Announcement | /2way/getListAnnouncement, addNewAnnouncement, …, getListAnnouncementByUserID, updateCountReadedAnnouncement, updateIsAcceptAnnouncement | admin = bypass token; user-facing = LINE bypass |
| AutoReply | /2way/getListAutoReply, addNewAutoReply, updateAutoReply, updateStatusAutoReply | bypass token |
| SSO | /2way/loginSSO, changePasswordSSO, verifyUserNonEmp, verifyOTPNonEmp, changePasswordNonEmpForget | ไม่มี auth middleware บน route.post("/") |
| Misc | /2way/redirectbypass | checkBypassWhenRedirectMiddleWare |
| Test | /2way/getListAnnouncementForTest | bypass token |
Commented-out mounts (มีไฟล์ แต่ไม่ live)
| Path ที่เคยตั้งใจ | ไฟล์ | สถานะใน app.ts |
|---|---|---|
/2way/getListChat | chatCenter/getListChat.ts | comment ปิด (app.ts:245-250) |
/2way/getChatMessageByID | chatCenter/getChildListChat.ts | comment ปิด |
/2way/updateReadedMessage | chatCenter/updateReadedMessage.ts | comment ปิด |
/2way/getUserEveryObject | survey | comment ปิด (app.ts:234-235) |
แม้ HTTP chat routes จะปิด socket.io ยัง bind chatHandler ที่ app.ts:277-282
Sequelize models ↔ โมดูลธุรกิจ
Registry ใน util/db.config.ts:29-40:
db1 key | ไฟล์ model | ใช้โดย |
|---|---|---|
post | model/post.ts | routes/post.ts, secure post |
login | model/login.ts | routes/auth/login.ts |
incident | model/incident/incident.ts | TwoWayAPI/incident/* |
feedback | model/feedback/feedback.ts | TwoWayAPI/feedback/* |
survey | model/survey/survey.ts | TwoWayAPI/survey/* |
userLine | model/userLine/userLine.ts | registration / profile |
userLineProfile | model/userLine/userProfile.ts | CU profile variants |
faqs | model/faqs/faqs.ts | FAQs |
announcement | model/announcement/announcement.ts | announcement |
autoReply | model/autoReply/autoReply.ts | auto-reply |
otp | model/otp/otp.ts | OTP SSO / LINE register |
token | model/token/token.ts | checkBypassTokenMiddleWare → Token.findOne |
Incident model exports
model/incident/incident.ts คืน object:
return { IncidentType, IncidentRunning, IncidentEdit, Attachment, AttachType, Incident, ProgressStatus, Remark };แหล่ง: 2way-vtrc-api/model/incident/incident.ts:336
Associations ที่ define ไว้ (ตัวอย่าง): Incident.belongsTo(IncidentType), Incident.hasMany(Attachment), Remark.belongsTo(Incident) (incident.ts:312-328)
UserLine fields
ตาราง userLine มี userID, identityCard, birthDate, lineID, userType (default 'RC'), richMenuID, isActive (model/userLine/userLine.ts:11-33)
Token fields
ตาราง token มี tokenTwoWay, profileKey, loginType, createDate (model/token/token.ts:11-23) — ใช้เทียบ Bearer กับแถวใน DB
Mongo chat schema
model/mongo/chatSchema.ts define collection "conversation" ด้วย channel, countNotRead, replyToken, updateDate, chat[] (chatSchema.ts:22-43)
Middleware inventory
| ไฟล์ | Export หลัก | พฤติกรรมสั้น ๆ |
|---|---|---|
checkbypasstoken.ts | checkBypassTokenMiddleWare, checkApiKeyMiddleWare | Bearer → decode JWT ด้วย SECRET_JWT_TWOWAY → Token.findOne; หรือ token == "testnaja"; API key เทียบ process.env.API_KEY |
checkByPassTokenLine.ts | checkBypassTokenLineMiddleWare | verify LINE access token → get profile → หา UserLine; หรือ "testnaja" |
jwtpassport.ts | requireJWTAuth | Strategy เรียก done(null, true) ทันที — ไม่เช็ค payload จริง (jwtpassport.ts:9-12) |
validator/createIncident.ts | validatorCreateIncident | express-validator ก่อน insert |
validator/updateincident.ts | validatorUpdateIncident | express-validator ก่อน update |
โค้ดตัวอย่าง / mock ที่ยัง mount ใน production path
/2way/TwoWayAPI — routes/TwoWayAPI/index.ts (~1849 บรรทัด)
Mount ที่ app.ts:112-113. Endpoints ตัวอย่าง:
| Method | Sub-path | พฤติกรรม |
|---|---|---|
| POST | /RegisterLineUser | ตรวจ isEmpty(body) แล้วตอบ Success — ไม่เขียน DB (index.ts:196-259) |
| POST | /NewIncident | mock |
| POST | /GetSurveyListByUser, /CreateSurvey, … | mock จาก ./mock |
| POST | /NewFeedback, /FeedbackList | mock |
| POST | /NewAnnouncement, /AnnouncementList, … | mock |
| GET | /debugsentry | debug Sentry (index.ts:1825) |
Swagger comment ในไฟล์ยังอ้าง "Retrieve a list of JSONPlaceholder users" (index.ts:217-218)
/2way/MeetingAPI — routes/MeetingAPI/user.ts
Mount ที่ app.ts:110-111. ชื่อ path มีคำว่า Meeting แต่ ไม่เกี่ยวกับ Meeting Platform group (meeting-vtrc-api / meeting-backoffice) — เป็นโค้ดตัวอย่างที่ตั้งชื่อ path ไว้
Lib helpers ที่ route พึ่งพา
| ไฟล์ | บทบาท |
|---|---|
lib/Uploadimage.class.ts | อัปโหลด base64 → storage/2way/ |
lib/Dateformat.class.ts | format วันที่ |
lib/Emailsender.class.ts | nodemailer (login/register flows) |
lib/Otp.ts | OTP generation/verify |
lib/Socket.func.ts | socket event sendMessage → Mongo Chat + LINE push |
lib/InsertChat.func.ts / InsertChatBot.func.ts | เขียน chat message |
lib/model.ts | syncModelToTable() — ปิดการเรียกใน app.ts:265 |
Tests / tooling
jest+ts-jest(package.json:10,64,68)__test__/test.spec.tsมีอยู่coverage/และtest-report.htmlcommit ค้างใน repo- ไม่มี Bitbucket/GitHub Actions pipeline ใน root ของ repo นี้ (ไม่มี
bitbucket-pipelines.ymlในรายการไฟล์ที่ตรวจ)
สิ่งที่อยู่นอกขอบเขตบทนี้
- Trace ทีละ request → 02-core-pipeline
- DB URL / LINE / SSO / centralize → 03-persistence-integrations
- Debt IDs → 04-scorecard