Back to blog

TypeScript: Thiết Lập Project cho Node.js Backend

typescriptnodejsbackendproject-setupdeveloper-tools
TypeScript: Thiết Lập Project cho Node.js Backend

Bạn đã biết TypeScript. Bạn đã build frontend với nó. Giờ bạn muốn build backend — một API thực sự, không phải project chơi chơi. Nhưng rào cản đầu tiên không phải viết business logic. Mà là thiết lập project cho đúng.

Một setup tệ sẽ ám ảnh bạn hàng tháng trời: build chậm, lỗi import bí ẩn, không auto-format, và cái tsconfig.json copy từ Stack Overflow mà chẳng ai hiểu. Một setup tốt thì invisible — nó just works, bắt bug sớm, và để bạn focus vào chuyện quan trọng.

Hướng dẫn này sẽ walk through từ đầu một TypeScript backend setup production-ready. Mọi quyết định đều được giải thích để bạn thực sự hiểu configuration của chính mình.

Thời gian: 1-2 giờ
Điều kiện: TypeScript Giai Đoạn 1: Nền Tảng và kinh nghiệm Node.js cơ bản

Những Gì Bạn Sẽ Học

✅ Khởi tạo TypeScript project cho Node.js từ đầu
✅ Cấu hình tsconfig.json với mọi option được giải thích
✅ Thiết lập ESLint 9 + Prettier cho code nhất quán
✅ Development workflow với tsx (chạy TypeScript siêu nhanh)
✅ Build process với tsc, esbuild, và swc
✅ Best practices cấu trúc project cho backend scalable
✅ Environment variables với type-safe validation
✅ Path aliases hoạt động cả trong dev lẫn production


1. Khởi Tạo Project

Bắt đầu từ đầu:

mkdir my-api
cd my-api
npm init -y

Cài TypeScript và Node.js types:

npm install -D typescript @types/node

Tại sao cần @types/node? Node.js được viết bằng C++, không phải TypeScript. Package @types/node cung cấp TypeScript type definitions cho tất cả built-in modules của Node.js (fs, path, http, process, v.v.). Không có nó, TypeScript không biết process.env hay Buffer là gì.

Tạo tsconfig.json:

npx tsc --init

Lệnh này tạo file với mọi option bị comment out. Hãy thay nó bằng thứ chúng ta thực sự hiểu.


2. TypeScript Configuration (tsconfig.json)

Đây là configuration production-ready cho Node.js backend. Mọi option đều được giải thích:

{
  "compilerOptions": {
    // === Output ===
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./src",
 
    // === Strictness ===
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "forceConsistentCasingInFileNames": true,
 
    // === Module Features ===
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
 
    // === Quality of Life ===
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "skipLibCheck": true,
 
    // === Path Aliases ===
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
}

Giải Thích Các Option Quan Trọng

target: "ES2022" — JavaScript version để compile ra. ES2022 cho bạn top-level await, Array.at(), Object.hasOwn(), và class fields. Node.js 18+ support tất cả ES2022 features natively.

module: "NodeNext" + moduleResolution: "NodeNext" — Cặp này báo TypeScript theo cách resolve module native của Node.js. Support cả ESM (import) và CJS (require) dựa vào field "type" trong package.json. Đây là setting recommended cho Node.js projects từ 2025 trở đi.

strict: true — Bật tất cả strict type-checking options cùng lúc. Non-negotiable cho professional code. Bao gồm strictNullChecks, strictFunctionTypes, strictBindCallApply, v.v.

noUncheckedIndexedAccess: true — Viên ngọc ẩn. Khi bạn access array element hay object property bằng index, kết quả bao gồm undefined:

const items = ["a", "b", "c"];
const first = items[0]; // string | undefined (không chỉ string)
 
// Buộc bạn handle edge case
if (first !== undefined) {
  console.log(first.toUpperCase()); // safe
}

esModuleInterop: true — Cho phép import express from 'express' thay vì import * as express from 'express'. Hầu hết npm packages là CommonJS, flag này giúp chúng hoạt động clean với ES import syntax.

resolveJsonModule: true — Cho phép import config from './config.json' với full type inference. TypeScript đọc JSON structure và cung cấp typed access.

isolatedModules: true — Đảm bảo mỗi file có thể transpile độc lập. Bắt buộc nếu bạn dùng esbuild, swc, hoặc bất kỳ tool nào compile files riêng lẻ (hầu hết các tools đều vậy).

skipLibCheck: true — Bỏ qua type-checking cho .d.ts files từ node_modules. Tăng tốc compilation đáng kể. Gần như lúc nào cũng nên bật — nếu types của library bị lỗi, đó là problem của họ.

ESM vs CJS: Chọn Cái Nào?

Thêm vào package.json cho ESM:

{
  "type": "module"
}

ESM (recommended):

  • Top-level await
  • import/export syntax
  • Tree-shakeable
  • Standard cho tương lai

CJS (legacy):

  • require()/module.exports
  • Tương thích rộng hơn với packages cũ
  • Không có top-level await

Lời khuyên thực tế: Dùng ESM cho project mới. Nếu gặp compatibility issues với package cũ, bạn có thể dynamically import() nó hoặc dùng compatibility wrapper.


3. ESLint 9 + Prettier Setup

Cài Dependencies

# ESLint 9 với TypeScript support
npm install -D eslint @eslint/js typescript-eslint
 
# Prettier
npm install -D prettier eslint-config-prettier

ESLint Configuration (eslint.config.mjs)

ESLint 9 dùng flat config format mới:

// eslint.config.mjs
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import eslintConfigPrettier from "eslint-config-prettier";
 
export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.recommendedTypeChecked,
  eslintConfigPrettier,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
    rules: {
      // Rules thực tế cho backend development
      "@typescript-eslint/no-unused-vars": [
        "error",
        { argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
      ],
      "@typescript-eslint/no-floating-promises": "error",
      "@typescript-eslint/no-misused-promises": "error",
      "@typescript-eslint/prefer-nullish-coalescing": "warn",
      "@typescript-eslint/prefer-optional-chain": "warn",
    },
  },
  {
    ignores: ["dist/", "node_modules/", "*.js"],
  }
);

Tại Sao Các Rules Này Quan Trọng

no-floating-promises: "error" — Đây là rule quan trọng nhất cho backend development. Floating promise là promise bạn quên await:

// BUG: Error bị nuốt im lặng
app.get("/users", (req, res) => {
  fetchUsers(); // Quên await! Không error handling!
  res.json({ ok: true }); // Gửi response trước khi data sẵn sàng
});
 
// FIXED: ESLint bắt được lỗi này
app.get("/users", async (req, res) => {
  const users = await fetchUsers(); // Giờ chúng ta chờ
  res.json(users);
});

no-misused-promises: "error" — Bắt async functions truyền vào chỗ cần sync callbacks. Đây là nguồn phổ biến gây unhandled rejections.

Prettier Configuration (.prettierrc)

{
  "semi": true,
  "trailingComma": "all",
  "singleQuote": false,
  "printWidth": 100,
  "tabWidth": 2
}

Thêm Scripts vào package.json

{
  "scripts": {
    "lint": "eslint src/",
    "lint:fix": "eslint src/ --fix",
    "format": "prettier --write 'src/**/*.ts'"
  }
}

4. Development Workflow

Bạn cần cách chạy TypeScript trong lúc dev mà không phải manually compile mỗi lần. Đây là ba lựa chọn, từ đơn giản nhất đến configurable nhất.

tsx là TypeScript executor siêu nhanh chạy bằng esbuild. It just works — không config, không rắc rối:

npm install -D tsx
{
  "scripts": {
    "dev": "tsx watch src/index.ts"
  }
}

Tại sao tsx?

  • Zero config — không cần tsconfig.json riêng để chạy (vẫn tôn trọng config của bạn)
  • Built-in watch mode với tsx watch
  • Handle ESM và CJS mượt mà
  • Nhanh hơn ts-node ~10 lần
  • Support path aliases out of the box

Option 2: ts-node (Legacy)

TypeScript executor đầu tiên. Vẫn dùng rộng rãi nhưng chậm hơn:

npm install -D ts-node
{
  "scripts": {
    "dev": "ts-node --esm --watch src/index.ts"
  }
}

Khi nào dùng ts-node: Nếu bạn cần full TypeScript type-checking khi chạy (tsx bỏ qua type-checking để nhanh hơn). Với hầu hết workflow, type-checking trong IDE + tsc --noEmit trong CI là đủ rồi.

Option 3: nodemon + tsx

Khi bạn muốn kiểm soát nhiều hơn những gì trigger restart:

npm install -D nodemon tsx

Tạo nodemon.json:

{
  "watch": ["src"],
  "ext": "ts,json",
  "ignore": ["src/**/*.test.ts"],
  "exec": "tsx src/index.ts"
}
{
  "scripts": {
    "dev": "nodemon"
  }
}

File Khởi Đầu

Tạo src/index.ts để verify mọi thứ hoạt động:

// src/index.ts
console.log("Hello from TypeScript backend!");
console.log(`Node.js ${process.version}`);
console.log(`Running in ${process.env.NODE_ENV ?? "development"} mode`);
npm run dev
# Output:
# Hello from TypeScript backend!
# Node.js v22.x.x
# Running in development mode

5. Build Process

Development dùng tsx cho nhanh (không cần compilation step). Production cần JavaScript đã compiled. Đây là ba cách tiếp cận.

Option 1: tsc (Standard)

TypeScript compiler chính thống. Đơn giản, đáng tin, officially supported:

{
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  }
}

Ưu điểm: Full type-checking khi build, tạo declaration files, source maps Nhược điểm: Chậm hơn các lựa chọn khác (5-10 lần)

Option 2: esbuild (Nhanh)

Bundler siêu nhanh viết bằng Go:

npm install -D esbuild
{
  "scripts": {
    "build": "esbuild src/index.ts --bundle --platform=node --outdir=dist --format=esm --packages=external",
    "start": "node dist/index.js"
  }
}

Các flags quan trọng:

  • --bundle: Bundle tất cả code thành ít files hơn
  • --platform=node: Target Node.js (không phải browser)
  • --packages=external: Giữ node_modules là external imports (không bundle dependencies)
  • --format=esm: Output ESM format

Ưu điểm: Nhanh hơn tsc 10-100 lần, bundle code, tree-shake dead code Nhược điểm: Không type-check (kết hợp với tsc --noEmit trong CI)

Option 3: swc (Nhanh + Configurable)

Compiler viết bằng Rust, được dùng bởi Next.js:

npm install -D @swc/cli @swc/core

Tạo .swcrc:

{
  "$schema": "https://swc.rs/schema.json",
  "module": {
    "type": "es6"
  },
  "jsc": {
    "target": "es2022",
    "parser": {
      "syntax": "typescript",
      "decorators": true
    },
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
{
  "scripts": {
    "build": "swc src -d dist --strip-leading-paths",
    "start": "node dist/index.js"
  }
}

Kết hợp cả hai thế giới — build nhanh với type safety:

{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc --noEmit && esbuild src/index.ts --bundle --platform=node --outdir=dist --format=esm --packages=external",
    "start": "node dist/index.js",
    "typecheck": "tsc --noEmit"
  }
}

Chạy type-checking (tsc --noEmit) trước, rồi build với esbuild nếu types pass. Bạn được cả safety lẫn speed.


6. Cấu Trúc Project

Cấu trúc project tổ chức tốt là critical cho maintainability. Đây là layout đã được thực chiến cho backend projects:

my-api/
├── src/
│   ├── index.ts              # Entry point - khởi động server
│   ├── app.ts                # Express/Fastify app setup
│   ├── config/
│   │   └── env.ts            # Environment variable validation
│   ├── routes/
│   │   ├── index.ts          # Route aggregator
│   │   ├── users.ts          # /api/users routes
│   │   └── posts.ts          # /api/posts routes
│   ├── controllers/
│   │   ├── user.controller.ts
│   │   └── post.controller.ts
│   ├── services/
│   │   ├── user.service.ts
│   │   └── post.service.ts
│   ├── repositories/
│   │   ├── user.repository.ts
│   │   └── post.repository.ts
│   ├── middleware/
│   │   ├── auth.ts           # Authentication middleware
│   │   ├── error-handler.ts  # Global error handler
│   │   └── validate.ts       # Request validation
│   ├── types/
│   │   ├── index.ts          # Shared types
│   │   └── express.d.ts      # Express type extensions
│   └── utils/
│       ├── logger.ts         # Logging utility
│       └── errors.ts         # Custom error classes
├── tests/
│   ├── unit/
│   └── integration/
├── .env                      # Local environment variables
├── .env.example              # Template cho environment variables
├── .gitignore
├── .prettierrc
├── eslint.config.mjs
├── nodemon.json
├── package.json
└── tsconfig.json

Kiến Trúc Phân Lớp

Cấu trúc này theo pattern Controller → Service → Repository:

Routes — Định nghĩa endpoints và kết nối với controllers. Không có business logic ở đây.

Controllers — Xử lý HTTP concerns (parse request, gửi response). Delegate cho services.

Services — Business logic sống ở đây. Framework-agnostic. Testable riêng biệt.

Repositories — Database access layer. SQL queries, ORM calls. Services không biết gì về SQL.

Ví dụ cách chúng kết nối:

// src/routes/users.ts
import { Router } from "express";
import { UserController } from "@/controllers/user.controller.js";
 
const router = Router();
const controller = new UserController();
 
router.get("/", controller.getAll);
router.get("/:id", controller.getById);
router.post("/", controller.create);
 
export default router;
// src/controllers/user.controller.ts
import type { Request, Response, NextFunction } from "express";
import { UserService } from "@/services/user.service.js";
 
export class UserController {
  private service = new UserService();
 
  getAll = async (_req: Request, res: Response, next: NextFunction) => {
    try {
      const users = await this.service.findAll();
      res.json(users);
    } catch (error) {
      next(error);
    }
  };
 
  getById = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const user = await this.service.findById(req.params.id!);
      if (!user) {
        res.status(404).json({ error: "User not found" });
        return;
      }
      res.json(user);
    } catch (error) {
      next(error);
    }
  };
 
  create = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const user = await this.service.create(req.body);
      res.status(201).json(user);
    } catch (error) {
      next(error);
    }
  };
}
// src/services/user.service.ts
import { UserRepository } from "@/repositories/user.repository.js";
 
export class UserService {
  private repository = new UserRepository();
 
  async findAll() {
    return this.repository.findMany();
  }
 
  async findById(id: string) {
    return this.repository.findById(id);
  }
 
  async create(data: { name: string; email: string }) {
    // Business logic: validate, check duplicates, v.v.
    const existing = await this.repository.findByEmail(data.email);
    if (existing) {
      throw new Error("Email already exists");
    }
    return this.repository.create(data);
  }
}

Tại Sao Sự Phân Tách Này Quan Trọng

Bạn có thể nghĩ đây là overkill cho project nhỏ. Đây là lý do nó đáng giá:

  1. Testing: Services test được không cần HTTP, repositories test được không cần business logic
  2. Swapping: Thay Express bằng Fastify? Chỉ routes và controllers thay đổi
  3. Readability: Developer mới biết chính xác tìm gì ở đâu
  4. Scaling: Khi file quá lớn, ranh giới đã được vạch sẵn

7. Environment Variables

Không bao giờ hardcode secrets. Không bao giờ tin process.env mà không validate.

Vấn Đề với process.env Thô

// BAD: Không validation, không types, crash khi runtime
const port = process.env.PORT; // string | undefined
const dbUrl = process.env.DATABASE_URL; // có thể không tồn tại!
 
// App khởi động, connect tới... hư không. Crash sau 5 phút
// khi database query đầu tiên chạy.

Environment Type-Safe với Zod

Cài Zod:

npm install zod

Tạo src/config/env.ts:

// src/config/env.ts
import { z } from "zod";
 
const envSchema = z.object({
  // Server
  PORT: z.coerce.number().default(3000),
  NODE_ENV: z
    .enum(["development", "production", "test"])
    .default("development"),
  HOST: z.string().default("0.0.0.0"),
 
  // Database
  DATABASE_URL: z.string().url("DATABASE_URL phải là URL hợp lệ"),
 
  // Auth
  JWT_SECRET: z.string().min(32, "JWT_SECRET phải ít nhất 32 ký tự"),
  JWT_EXPIRES_IN: z.string().default("7d"),
 
  // External services (optional trong development)
  REDIS_URL: z.string().url().optional(),
  SMTP_HOST: z.string().optional(),
  SMTP_PORT: z.coerce.number().optional(),
});
 
// Validate khi import — fail fast nếu env sai
const parsed = envSchema.safeParse(process.env);
 
if (!parsed.success) {
  console.error("❌ Invalid environment variables:");
  console.error(parsed.error.flatten().fieldErrors);
  process.exit(1);
}
 
export const env = parsed.data;
 
// Type tự động được infer:
// {
//   PORT: number;
//   NODE_ENV: "development" | "production" | "test";
//   HOST: string;
//   DATABASE_URL: string;
//   JWT_SECRET: string;
//   JWT_EXPIRES_IN: string;
//   REDIS_URL?: string;
//   SMTP_HOST?: string;
//   SMTP_PORT?: number;
// }

Sử Dụng Trong Toàn App

// src/index.ts
import { env } from "@/config/env.js";
 
// Fully typed! IDE autocomplete hoạt động.
console.log(`Starting server on port ${env.PORT}`);
console.log(`Environment: ${env.NODE_ENV}`);
// env.PORT là number (không phải string!)
// env.NODE_ENV là "development" | "production" | "test" (không phải string)

Tạo .env.example

# .env.example — Copy thành .env và điền giá trị
PORT=3000
NODE_ENV=development
HOST=0.0.0.0
 
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
 
JWT_SECRET=your-secret-key-at-least-32-characters-long
JWT_EXPIRES_IN=7d
 
# Optional
REDIS_URL=redis://localhost:6379

Đừng Quên .gitignore

# Environment
.env
.env.local
.env.*.local
 
# Build output
dist/
 
# Dependencies
node_modules/
 
# IDE
.vscode/
.idea/
 
# OS
.DS_Store

8. Path Aliases

Path aliases thay thế import đường dẫn dài bằng đường dẫn gọn:

// KHÔNG CÓ aliases (đau đầu)
import { UserService } from "../../../services/user.service.js";
import { env } from "../../../../config/env.js";
 
// CÓ aliases (sạch sẽ)
import { UserService } from "@/services/user.service.js";
import { env } from "@/config/env.js";

Bước 1: Cấu Hình TypeScript

Đã làm trong tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Bước 2: Làm Cho Nó Chạy Được Lúc Runtime

TypeScript hiểu path aliases cho type-checking, nhưng Node.js thì không. Bạn cần runtime resolver.

Cho development (tsx): Path aliases hoạt động out of the box. Không cần config thêm.

Cho production (compiled JS): Bạn có hai options.

Option A: tsc-alias (sau compile)

npm install -D tsc-alias
{
  "scripts": {
    "build": "tsc && tsc-alias"
  }
}

tsc-alias rewrite import paths trong compiled .js files từ @/ thành relative paths.

Option B: esbuild tự xử lý

Nếu bạn dùng esbuild để build, nó resolve path aliases trong quá trình bundling. Không cần bước thêm — chỉ trỏ tới tsconfig.json:

{
  "scripts": {
    "build": "esbuild src/index.ts --bundle --platform=node --outdir=dist --format=esm --packages=external --tsconfig=tsconfig.json"
  }
}

9. package.json Hoàn Chỉnh

Đây là package.json đầy đủ kết nối mọi thứ:

{
  "name": "my-api",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc --noEmit && esbuild src/index.ts --bundle --platform=node --outdir=dist --format=esm --packages=external --tsconfig=tsconfig.json",
    "start": "node dist/index.js",
    "typecheck": "tsc --noEmit",
    "lint": "eslint src/",
    "lint:fix": "eslint src/ --fix",
    "format": "prettier --write 'src/**/*.ts'"
  },
  "devDependencies": {
    "@eslint/js": "^9.0.0",
    "@swc/cli": "^0.5.0",
    "@swc/core": "^1.9.0",
    "@types/node": "^22.0.0",
    "esbuild": "^0.24.0",
    "eslint": "^9.0.0",
    "eslint-config-prettier": "^10.0.0",
    "prettier": "^3.4.0",
    "tsx": "^4.19.0",
    "typescript": "^5.7.0",
    "typescript-eslint": "^8.0.0"
  },
  "dependencies": {
    "zod": "^3.24.0"
  }
}

10. Kiểm Tra: Hello World API

Hãy verify mọi thứ hoạt động end-to-end với một Express server tối thiểu:

npm install express
npm install -D @types/express
// src/index.ts
import express from "express";
import { env } from "@/config/env.js";
 
const app = express();
 
app.use(express.json());
 
app.get("/", (_req, res) => {
  res.json({
    message: "Hello from TypeScript!",
    environment: env.NODE_ENV,
    timestamp: new Date().toISOString(),
  });
});
 
app.get("/health", (_req, res) => {
  res.json({ status: "ok" });
});
 
app.listen(env.PORT, env.HOST, () => {
  console.log(`Server running at http://${env.HOST}:${env.PORT}`);
  console.log(`Environment: ${env.NODE_ENV}`);
});

Tạo file .env:

PORT=3000
NODE_ENV=development
HOST=0.0.0.0
DATABASE_URL=postgresql://localhost:5432/mydb
JWT_SECRET=my-development-secret-key-at-least-32-chars

Chạy thử:

npm run dev
 
# Output:
# Server running at http://0.0.0.0:3000
# Environment: development

Test:

curl http://localhost:3000
# {"message":"Hello from TypeScript!","environment":"development","timestamp":"2026-03-01T..."}
 
curl http://localhost:3000/health
# {"status":"ok"}

Build và chạy production:

npm run build
npm start

Tổng Kết

Đây là những gì chúng ta đã setup và tại sao:

Thành phầnToolLý do
TypeScript configtsconfig.jsonStrict types, ES2022, NodeNext modules
LintingESLint 9 + typescript-eslintBắt async bugs, enforce consistency
FormattingPrettierCode style nhất quán, không tranh cãi
Dev runnertsx watchChạy nhanh, auto-reload, zero config
Buildtsc --noEmit + esbuildType safety + bundling nhanh
Env varsZod validationFail fast, typed config, không surprise
Path aliases@/* → ./src/*Import sạch, không ../../../
StructureController/Service/RepositorySeparation of concerns, testable layers

Tiếp Theo

Setup này là nền tảng cho mọi thứ tiếp theo. Trong bài tiếp, chúng ta sẽ build REST API hoàn chỉnh trên nền tảng này:

  • Express.js routing với type-safe request/response
  • Input validation với Zod
  • Error handling middleware
  • Controller/Service/Repository pattern thực chiến
  • API documentation với Swagger

Series: TypeScript Full-Stack Development
Trước: TypeScript Full-Stack Monorepo
Tiếp: TypeScript: Xây Dựng REST API với Express.js

📬 Đăng ký nhận bản tin

Nhận những bài viết mới nhất qua email mỗi tuần. Không spam, hủy đăng ký bất cứ lúc nào.

Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất cứ lúc nào.

💬 Comments

Đăng nhập để bình luận

Chúng tôi sẽ không đăng bất cứ điều gì mà không có sự cho phép của bạn.