Skip to content

4.1 · Repository map

บทนี้เจาะโครงสร้างของ cu-central-api/main-api/src/ เพื่อให้อ่านและค้นหาโค้ดได้ง่ายขึ้น พร้อมทั้งระบุ typos และไฟล์ที่ไม่ได้ใช้แล้ว (dead files) ที่ต้องระมัดระวังเมื่อแก้ไขโค้ด


โครงสร้าง repo ระดับบน

cu-central-api/                          (independent git repo บน Bitbucket)
├── .gitignore
├── Dockerfile-nginx                     nginx proxy image
├── Dockerfile-redis                     redis image
├── docker-compose-dev.yml               dev compose
├── docker-compose.yml                   3x cu-cen-api replicas + redis + nginx
├── ecosystem.config.js                  PM2 config (legacy, ไม่ได้ใช้ใน prod)
├── package-lock.json
├── pm2Cmd.txt
├── database/                            legacy DB scripts
├── ldap/                                LDAP-related resources
├── nginx/                               nginx conf.d
├── redis-db/                            redis.conf + data volume
├── web-site/                            static nginx html
└── main-api/                            ★ service หลัก (Volume นี้ focus ที่นี่)
    ├── .dockerignore
    ├── .env.develop-test                UAT secrets (committed — Volume 9.5)
    ├── .env.example                     sanitized template
    ├── Dockerfile                       FROM node:12.18.3
    ├── index.js                         1-line entrypoint: import './src'
    ├── package.json
    ├── test/validator.js                test file เดียว (mocha)
    └── src/                             ★ application code

repo อยู่บน Bitbucket (bitbucket.org/i3dev/cu-central-api) ภายใต้ user i3wp — ต่างจาก repo อื่นที่อยู่บน GitHub ส่วนใหญ่


main-api/src/ top-level files

FileLOCหน้าที่
index.js119Apollo + Express bootstrap
config.js110env var destructuring
connector.js1966 Sequelize instances (รายละเอียดใน 4.2)
cron.js33node-schedule jobs (3 jobs, gated by APP_NO)
routes.js64REST routes (signin/signout/token/conicle)
testScript.js167dev-only scratch runner (gated by !IS_PRODUCTION)
directives/auth.js80@auth schema directive
directives/index.js6directive registry

main-api/src/ subdirectories

Directoryไฟล์หมายเหตุ
typeDefs/31 .js (29 root + 3 ใน hr/)hand-authored GraphQL SDL — รายละเอียดใน 4.6
resolvers/29 .js (26 root + 3 hr/ + 1 bank/)1,826 LOC total
models/6 subdirs + index.jsrecursive loader — รายละเอียดใน 4.2
lib/28 root .js + 31 subdirsbulk ของ business logic
directives/2 filesมีแค่ @auth
email-templates/requestResetPassword/nodemailer pug templates

lib/ subdirectories (31)

แบ่งตามหน้าที่

lib/
├── auth/                    LDAP + AD + JWT + apiKey + session
├── bank/                    book bank lookup
├── cache/                   Redis cache helper
├── childTuition/            child tuition allowance
├── class/                   employee class
├── conicle/                 Conicle SFTP integration
├── dataConverter/           data shape converter
├── finance/                 employee finance (★ typo: finanace.js)
├── his/                     HIS heal-card API
├── hr/                      HR mutations (taxes/address/phone)
├── hrPerProbation/          probation check
├── hrmi/                    HRMI HTTP API + leave/medical
├── mailer/                  nodemailer wrapper
├── masterData/              master data CRUD
├── notification/            SMS gateway
├── organization/            org unit lookup
├── otp/                     OTP generation + verify
├── personalProfile/         employee personal profile
├── phoneNumber/             phone change log
├── referenceData/           reference data
├── salaryCert/              salary certificate
├── session/                 Redis session store
├── sso/                     SSO integration (★ committed certs)
├── statLog/                 stat logging
├── studyLeaveRequest/       study leave
├── transferFile/            file transfer helper
├── twoWay/                  2-way employee sync
├── userIdGenerator/         userId mapping generator
├── userIdsMapping/          userIdsMapping table ops
├── userVerification/        user verification flow
└── verifyCode/              verify code flow

Typos ใน production code

Codebase มี typos หลายจุดที่ "ship แล้วเปลี่ยนไม่ได้" เพราะอยู่ใน GraphQL schema สาธารณะ

finanace (finance สะกดผิด)

ที่พบ 3 จุดที่ consistent กัน

ไฟล์รายละเอียด
lib/finance/finanace.jsชื่อไฟล์เอง
resolvers/finanace.jsresolver file (26 LOC)
typeDefs/finance.js:5,11type EmployeeFinanace + query employeeFinanceType

อ่านเจอครั้งแรกจะนึกว่ามี 2 files (finance + finanace) แต่แท้จริงแล้ว typeDef ใช้ชื่อโฟลเดอร์ที่สะกดถูก (finance/) แต่ชื่อไฟล์ข้างในสะกดผิด

typos อื่น ๆ ใน GraphQL schema

Type / Queryควรเป็นไฟล์
EmployeeFinanaceEmployeeFinancetypeDefs/finance.js:5
OrgazationAddressOrganizationAddresstypeDefs/organization.js
SubscribtionSubscriptiontypeDefs/root.js
hrPerProbationNotApprove(lowercase — เป็น query name)typeDefs/hrPerProbation.js
salaryCert(lowercase — เป็น query name)typeDefs/salaryCert.js
nonEmpSSO(lowercase)typeDefs/sso.js
employeeFor2way(lowercase + numeric)typeDefs/twoWay.js

GraphQL schema เป็น contract สาธารณะ — เปลี่ยนชื่อไม่ได้ถ้าไม่ break client ทั้งหมด


Dead files และ legacy artifacts

typeDefs/payrollSlip_removed.js (112 LOC)

1:1:main-api/src/typeDefs/payrollSlip_removed.js
// ไฟล์นี้ไม่ถูก import โดย typeDefs/index.js — dead SDL
  • เป็นเวอร์ชันเก่าของ payrollSlip.js ที่ใช้ empCode เป็น parameter แทน profileKey (ที่ใช้ในปัจจุบัน)
  • ไม่ถูก import โดย typeDefs/index.js — จึงไม่ปรากฏใน live schema
  • แต่ยังอยู่ใน repo เพราะเป็น "schema archaeology" reference

src/testScript.js (167 LOC)

20:22:main-api/src/index.js
if (!IS_PRODUCTION) {
  testScript()
}

เป็น scratch IIFE ที่ใช้สำหรับรัน one-off data-fix scripts (เช่น สร้าง AD user จำนวนมาก, mask ID card) ที่ผ่านมาในแต่ละเดือน/ปี

  • gated โดย NODE_ENV !== 'production'
  • แต่ top-level IIFE ยัง fire ทุกครั้งที่ boot ใน UAT/dev
  • testScript.js:16 เรียก checkAdAuthenConnection() ซ้ำกับ boot-time check ใน index.js:92

connector.js debug comment

172:192:main-api/src/connector.js
// const dbHRMI_test = new Sequelize("dbHRMI_test", "root", "1q2w3e4r00", {
//   host: "localhost",
//   port: 3303,
//   dialect: "mariadb",

Comment ทิ้ง local-dev config พร้อม plaintext password 1q2w3e4r00 — pattern เดียวกับ vtrc-api/api/.env.example

dbHRMI_test connection (dead weight)

117:142:main-api/src/connector.js
const dbHRMI_test = new Sequelize("dbHRMI_test", DB_USERNAME, DB_PASSWORD, {
  host: DB_HOST,
  port: DB_PORT,
  dialect: DB_SCHEMA,
  // ...
})
  • database name "dbHRMI_test" เป็น hardcoded literal (ไม่ได้มาจาก env)
  • exported ที่บรรทัด 195 แต่ model loader (models/index.js:95-105) commented out
  • ผล — connection pool เปิดขึ้นทุก boot แต่ไม่มี model ผูก ทำให้เปลือง MSSQL connection

SSO certificates committed

lib/sso/
├── DigiCert_Global_Root_CA.cer       root CA
├── TPRDWSSOWEB01.crt                  prod SSO cert
└── TUATWSSOWEB01.crt                  UAT SSO cert

certificate ของ SSO service (ทั้ง prod และ UAT) commit อยู่ใน repo — เป็น public cert ไม่ใช่ private key จึงไม่ใช่ secret leak แต่เป็น anti-pattern ที่ควร fetch จาก secret manager หรือ truststore แทน


สรุปขนาด codebase

ส่วนขนาด
SDL (typeDefs)2,629 LOC
Resolvers1,826 LOC
index.js (bootstrap)119 LOC
connector.js (DB)196 LOC
lib/ (business logic)~10,000+ LOC (31 subdirs)
Models~50+ files (6 subdirs)
รวมประมาณ~15,000 LOC

เล็กกว่า vtrc-api (routes.js อย่างเดียว 77 KB) แต่มี complexity ของตัวเอง — โดยเฉพาะ multi-tenant sharding ในบท 4.5


ทำไมถึงมี typos และ dead code มาก

  • อ่านจากประวัติ — codebase นี้ port มาจาก HRMI leave-management system เก่า (hrmi.js เป็น SDL ที่ใหญ่สุด, ทุก type มีพารามิเตอร์ sourceDb ซึ่งบ่งบอกว่าออกแบบมาให้ใช้กับหลาย shard) เมื่อ migrate หลายรอบโดยไม่มี lint ที่เข้มงวด (มี dep standard แต่ไม่มี lint script) — typo และ dead file จึงสะสม

ใน Wave 1 modernization (Volume 15) lint ที่ลบ no-dupe-keys, no-unused-vars จะ catch ปัญหาพวกนี้ตอน commit


อ่านต่อ → 4.2 Bootstrap + 6 DB connections