01 · Repository map — vtrc-common
แผนที่โครงสร้าง repo บน branch prod (58 tracked files ไม่รวม node_modules / .git) — ใช้เป็นจุดเริ่มเมื่อต้องหา module, entity, หรือ libs ที่ copy มาจาก template กลาง
อ้างอิง branch: prod
Tree
vtrc-common/
├── config/
│ └── configuration.ts port, jwtSecretKey, db.* (connection 'main')
├── docs/
│ └── document.config.ts Swagger DocumentBuilder
├── libs/ boilerplate เดียวกับ chat-center-api / job-scheduler-api
│ ├── common/
│ │ ├── base64-to-file.ts helper แปลง base64 → ไฟล์ (ไม่ถูกเรียกจาก FileService ปัจจุบัน)
│ │ └── validator-date.ts custom date validator
│ ├── exception/
│ │ └── http-exception.filter.ts
│ ├── jwt/
│ │ ├── jwt-auth.guard.ts JwtAuthGuard + @Public() decorator
│ │ └── jwt.strategy.ts passport-jwt Strategy
│ ├── log/
│ │ └── logs.middleware.ts I3GatewayLogger
│ └── utils/
│ └── address.util.ts map entity → DTO + in-memory cache อำเภอ
├── sql/
│ ├── common_20230214_Initial_Structure_Table.sql MariaDB schema + seed จังหวัด
│ ├── common_20230313_Convert_MariaDB_To_MsSql.sql หลักฐาน migrate → MSSQL
│ └── common_20230313_Master_Data.sql master data เพิ่มเติม
├── bitbucket-pipelines.yml CI → GCR (branch cicd/develop/uat/prod/master)
├── docker-compose.yml dev/prod + MariaDB local (legacy)
├── Dockerfile multi-stage node:18-alpine
├── package.json name: vtrc-common-v1
├── src/
│ ├── main.ts entry point
│ ├── app.module.ts TypeORM 'main' + Address/File/Bank modules
│ ├── app.controller.ts @ApiTags('Root') — ไม่มี route
│ ├── app.service.ts ว่าง
│ ├── dto/
│ │ ├── address/ province, aumphur(+req), tumbol(+req)
│ │ ├── bank/bank.req.dto.ts
│ │ └── file.dto.ts MultipleSaveFileDto, PkFileDto
│ ├── entities/
│ │ ├── base.entity.ts
│ │ ├── m_province.entity.ts
│ │ ├── m_aumphur.entity.ts
│ │ ├── m_tumbol.entity.ts
│ │ ├── m_zipcode.entity.ts
│ │ ├── bank.entity.ts
│ │ └── file.entity.ts
│ └── modules/
│ ├── address/ controller + service + repository + specs
│ ├── bank/ controller + service
│ └── file/ controller + service
└── test/ e2e scaffold (jest-e2e)Root และ config
package.json
| Field | ค่า | หลักฐาน |
|---|---|---|
name | vtrc-common-v1 | vtrc-common/package.json (branch: prod):2 |
private | true | :6 |
start:prod | node dist/src/main | :18 |
| Nest deps | @nestjs/* ^9 | :27-33 |
| ORM | typeorm ^0.3.11 + mssql ^9.1.1 | :40,47 |
ไม่มี main / exports / files สำหรับ publish เป็น npm library — ยืนยันว่า artifact หลักคือ Nest app ที่ build เป็น dist/ แล้วรันด้วย start:prod
config/configuration.ts
export const configuration = () => ({
port: process.env.PORT,
jwtSecretKey: process.env.SECRET_KEY,
db: {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
databaseName: process.env.DB_NAME,
},
});แหล่ง: vtrc-common/config/configuration.ts (branch: prod):1-11
โหลดผ่าน ConfigModule.forRoot({ load: [configuration], isGlobal: true }) ใน AppModule (vtrc-common/src/app.module.ts (branch: prod):14-17)
.env keys (ค่า secret ไม่ paste เต็มในคู่มือ)
| Key | บทบาท | บรรทัด |
|---|---|---|
BASE_PATH | nginx path prefix vtrc-common/ | vtrc-common/.env (branch: prod):3 |
PORT | 9310 | :5 |
DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_NAME | MSSQL vtrc_common | :8-12 |
MULTER_DEST | ./uploads (ประกาศไว้ แต่ FileService ใช้ process.cwd()/uploads โดยตรง) | :14 |
CENTRALIZE_SERVER | vestigial — ไม่พบการอ้างอิงใน src/ | :16 |
SECRET_KEY | JWT secretOrKey | :18 |
AppModule — module ที่ export / mount
vtrc-common/src/app.module.ts (branch: prod):12-45 import เฉพาะ 3 feature module:
| Module | Path | Providers | Controllers |
|---|---|---|---|
AddressModule | src/modules/address/ | AddressService, AddressRepository | AddressController |
FileModule | src/modules/file/ | FileService | FileController |
BankModule | src/modules/bank/ | BankService | BankController |
JwtStrategy ลงทะเบียนเป็น provider ที่ root (:43) — จำเป็นสำหรับ passport strategy ชื่อ 'jwt' ที่ JwtAuthGuard ใช้
ไม่มี Nest dynamic module export สำหรับให้ service อื่น imports: [AddressModule] — อีกหลักฐานว่าไม่ใช่ library ที่ import ข้าม process
Module breakdown — HTTP surface
Prefix จริง = {BASE_PATH}api/v1 = vtrc-common/api/v1 (vtrc-common/src/main.ts (branch: prod):21-23)
AddressModule
| Method + Path | Handler | @Public() | หลักฐาน |
|---|---|---|---|
GET /address/listAllProvince | fetchListAllProvince | ใช่ | address.controller.ts:14-18 |
GET /address/listAumphur?provCode= | fetchListAumphur | ใช่ | :20-24 |
GET /address/listTumbol?provCode=&hCode= | fetchListTumbol | ใช่ | :26-30 |
GET /address/testTumbol | testTumbol → service V2 (native SQL) | ใช่ | :32-36 |
GET /address/testTumbol2 | testTumbol2 → service V3 (QueryBuilder) | ใช่ | :38-42 |
GET /address/listSubDistrictByProvCodeAndDistrictCode | raw SQL อีกเส้น | ใช่ | :44-48 |
ไฟล์หลัก:
- Controller:
vtrc-common/src/modules/address/address.controller.ts (branch: prod):1-49 - Service:
address.service.ts:1-99— มีfetchListTumbolV4ที่ ไม่มี route ผูก (:81-87) - Repository:
address.repository.ts:1-131— มีทั้ง TypeORM find, QueryBuilder (ปลอดภัย), และ raw SQL (injection) - Util cache:
libs/utils/address.util.ts:8-61 - Specs:
address.controller.spec.ts,address.service.spec.ts
BankModule
| Method + Path | Handler | @Public() | หลักฐาน |
|---|---|---|---|
POST /bank/getBankList | รายชื่อธนาคาร HQ (bankBranch='0000', ยกเว้น code 001) | ใช่ | bank.controller.ts:13-17, bank.service.ts:16-49 |
POST /bank/getBankBranchList | สาขาตาม bankCode ใน body | ใช่ | bank.controller.ts:19-23, bank.service.ts:51-81 |
DTO: GetBankBranchListReqDto — field เดียว bankCode (vtrc-common/src/dto/bank/bank.req.dto.ts (branch: prod):4-8)
FileModule
| Method + Path | Handler | @Public() | หลักฐาน |
|---|---|---|---|
POST /file/save | รับ array base64 → เขียน disk + insert file | ใช่ | file.controller.ts:18-22 |
POST /file/delete | soft-delete isCancel=1 | ใช่ | :24-28 |
GET /file/:id | stream ไฟล์ | ไม่ | :30-33 |
POST /file/getFileArray | metadata ตาม id array | ไม่ | :35-38 |
DTO: MultipleSaveFileDto / PkFileDto (vtrc-common/src/dto/file.dto.ts (branch: prod):4-42) — validate @IsBase64(), @ArrayMinSize(1), @IsNumber({}, { each: true })
Entities map
| Entity class | Table | ความสัมพันธ์ | หลักฐาน |
|---|---|---|---|
BaseEntity | — (abstract columns) | id, createdDate/By, updatedDate/By | base.entity.ts:3-18 |
MProvince | m_province | OneToMany → MAumphur | m_province.entity.ts:5-21 |
MAumphur | m_aumphur | ManyToOne province, OneToMany tumbol | m_aumphur.entity.ts:6-26 |
MTumbol | m_tumbol | ManyToOne aumphur, OneToOne zipcode | m_tumbol.entity.ts:6-26 |
MZipcode | m_zipcode | OneToOne tumbol; column code ← zip_code | m_zipcode.entity.ts:5-16 |
BankEntity | bank | ไม่มี relation | bank.entity.ts:4-20 |
FileEntity | file | ไม่มี relation; soft-delete ผ่าน isCancel | file.entity.ts:4-26 |
หมายเหตุ naming — address tables ใช้ snake_case column (province_code) ส่วน bank / file ใช้ camelCase column (bankCode, filePath) — สะท้อนช่วงเวลา migrate คนละชุด
libs/ — shared boilerplate (copy-paste ไม่ใช่ package)
| Path | หน้าที่ | หมายเหตุ |
|---|---|---|
libs/jwt/jwt-auth.guard.ts | global guard + @Public() | เหมือน chat-center-api / job-scheduler-api ไบต์ต่อไบต์ในโครงสร้างหลัก (:15-24 bypass เมื่อ isPublic) |
libs/jwt/jwt.strategy.ts | secretOrKey จาก jwtSecretKey | validate คืน payload ทั้งก้อนโดยไม่ตรวจ field (:18-22) |
libs/exception/http-exception.filter.ts | flatten Nest exception message | :15-18 |
libs/log/logs.middleware.ts | I3GatewayLogger | ใช้ใน service หลายตัว |
libs/utils/address.util.ts | cache อำเภอ in-process Map | ไม่มี TTL / ไม่ invalidate — process restart เท่านั้นถึงจะ refresh |
libs/common/base64-to-file.ts | helper แยก | FileService เขียน fs.writeFileSync เอง ไม่เรียกไฟล์นี้ |
Deploy / CI ไฟล์ที่ควรรู้จักก่อนแก้
| ไฟล์ | ทำไมสำคัญ |
|---|---|
Dockerfile:19 | bake .env เข้า production image |
docker-compose.yml:30-43 | มี MariaDB service ใน compose ทั้งที่ runtime ใช้ MSSQL — สับสนเมื่อ onboard คนใหม่ |
bitbucket-pipelines.yml:17 | yarn test ถูก comment → CI ไม่รัน unit/e2e |
sql/common_20230313_Convert_MariaDB_To_MsSql.sql | หลักฐานว่า DB เคยอยู่ MariaDB |
address.repository.ts:82-94,117-130 | SQL injection (SEC-COMMON-02) |
สิ่งที่ไม่มีใน repo
- ไม่มี Nest schedule / cron / queue library ใน
package.json - ไม่มี outbound HTTP client ไป service อื่นใน
src/(มีaxiosใน dependencies แต่ไม่พบการใช้งานใน module หลัก) - ไม่มี publish script / private registry config สำหรับ npm package
AppController/AppServiceว่าง — ไม่มี health check endpoint ในโค้ดที่ตรวจแล้ว