box-nestjs-monorepo-init.md 16 KB

Box NestJS Monorepo - Initialization Guide

Complete setup guide for Box Management API monorepo from scratch

📋 Prerequisites

Before starting, ensure you have:

  • Node.js: v20+ installed
  • pnpm: v8+ installed (npm install -g pnpm)
  • MySQL: v8.0+ running
  • MongoDB: v6.0+ running
  • Git: For version control

🚀 Step 1: Initial PNPM Installation

1.1 Clone and Install Dependencies

# Navigate to monorepo root
cd box-nestjs-monorepo

# Install all dependencies for monorepo
# This will install dependencies for:
# - Root workspace
# - apps/box-mgnt-api
# - libs/common
# - libs/core
# - libs/db
pnpm install

What this does:

  • Installs all dependencies defined in package.json
  • Creates symlinks between workspace packages (@box/common, @box/core, @box/db)
  • Generates node_modules/ and pnpm-lock.yaml
  • Sets up Prisma client generators

Expected output:

Packages: +XXX
Progress: resolved XXX, reused XXX, downloaded 0, added XXX
Done in Xs

1.2 Verify Installation

# Check if NestJS CLI is available
pnpm nest --version

# Verify workspace structure
pnpm list --depth=0

🗄️ Step 2: Database Setup

2.1 Configure Environment Variables

Create .env.mgnt.dev in the monorepo root:

# Copy from template (if exists) or create new
touch .env.mgnt.dev

Minimum required configuration:

# Application Environment
APP_ENV=development

# MySQL Database Connection
MYSQL_URL="mysql://root:your_password@localhost:3306/box_admin"
# Optional: For migrations in development
# MYSQL_SHADOW_URL="mysql://root:your_password@localhost:3306/box_admin_shadow"

# MongoDB Connection
MONGO_URL="mongodb://admin:your_password@localhost:27017/box_admin?authSource=admin"

# Application Server
APP_HOST=0.0.0.0
APP_PORT=3300
APP_CORS_ORIGIN=*

# JWT Configuration
JWT_SECRET=047df8aaa3d17dc1173c5a9a3052ba66c2b0bd96937147eb643319a0c90d132f
JWT_ACCESS_TOKEN_TTL=43200

# 2FA Encryption
TWOFA_ENC_KEY=2q89JPacSKDmuU3hJCfKQhDg3sq74QScy0ShYBoQPgM=
APP_ISSUER=BOX-MGNT

# External APIs (optional for initial setup)
MGNT_API_URL=http://47.76.151.238:83
MGNT_API_TOKEN=
IMCHAT_API_URL=http://47.76.151.238:88
IMCHAT_API_TOKEN=
GAME_SERVER_ADMIN_API_URL=http://119.28.182.132:83
GAME_SERVER_TOKEN=

# Partner Integration (optional)
B_BASE_URL=https://wwapi.hxc1t.com
B_SIGN_SECRET=Z3VhbmNpbmV3ZWl4aWFvMTIzNDU2
PARTNER_MD5_KEY=160360904be3dd23bf4f1278a74196efdbf3f9b834ce883ef6ae09eb05c5c652
PARTNER_ITEMS_LIMIT=100
B_BASE_ORDER_ADD=/open/open/order/add
B_BASE_ORDER_UPDATE_STATUS=/open/open/order/updateStatus
B_BASE_CHAT_ADD=/open/order/chat/send

Generate secure secrets:

# Generate JWT_SECRET
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Generate TWOFA_ENC_KEY
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

2.2 Create Databases

MySQL:

# Connect to MySQL
mysql -u root -p

# Create database
CREATE DATABASE box_admin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# Optional: Create shadow database for migrations
CREATE DATABASE box_admin_shadow CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# Verify
SHOW DATABASES LIKE 'box_%';
exit;

MongoDB:

# Connect to MongoDB
mongosh -u admin -p

# Switch to box_admin database (auto-created on first use)
use box_admin

# Verify connection
db.stats()
exit

🔧 Step 3: Initial Database Migrations

3.1 Generate Prisma Clients

# Generate both MySQL and MongoDB Prisma clients
pnpm prisma:generate

# Or generate separately:
pnpm prisma:generate:mysql
pnpm prisma:generate:mongo

What this does:

  • Reads schema files from prisma/mysql/schema/*.prisma
  • Reads schema files from prisma/mongo/schema/*.prisma
  • Generates TypeScript client at node_modules/@prisma/mysql/client
  • Generates TypeScript client at node_modules/@prisma/mongo/client

Expected output:

✔ Generated Prisma Client (MySQL) to ./node_modules/@prisma/mysql/client
✔ Generated Prisma Client (MongoDB) to ./node_modules/@prisma/mongo/client

3.2 Run MySQL Migrations

# Run all migrations and create database schema
pnpm prisma:migrate:dev:mysql

What this does:

  • Creates all tables defined in prisma/mysql/schema/*.prisma
  • Applies migration from prisma/mysql/migrations/20251121082348_init_db/
  • Creates migration history in _prisma_migrations table

Tables created:

  • sys_user - User accounts
  • sys_role - User roles
  • sys_menu - Menu/permission structure
  • sys_api_permission - API endpoint permissions
  • sys_user_role - User-role relationships
  • sys_role_menu - Role-menu relationships
  • sys_role_api_permission - Role-API permission relationships
  • sys_login_log - Login activity logs
  • sys_operation_log - Operation audit logs
  • sys_quota_log - User quota tracking

Verify migration:

# Check tables were created
mysql -u root -p box_admin -e "SHOW TABLES;"

# Check migration history
mysql -u root -p box_admin -e "SELECT * FROM _prisma_migrations;"

3.3 MongoDB Collections

MongoDB collections are created dynamically when first used. Schema is defined in:

  • prisma/mongo/schema/*.prisma

Collections:

  • adsModule - Advertisement module types
  • ads - Advertisement content
  • category - Content categories
  • channel - Distribution channels
  • home - Homepage configurations
  • systemParam - System parameters
  • tag - Content tags
  • videoMedia - Video media metadata

🌱 Step 4: Initial Mongo Admin Seeding

4.1 Run Seed Script

# Seed Mongo `box_admin` collections with admin data
pnpm prisma:seed:box-admin:admin

What this seeds:

  1. Admin User (sys_user in Mongo)

    • Username: admin
    • Password: a123456 (hashed)
    • Email: admin@box.com
    • With 2FA disabled by default
  2. Roles (sys_role)

    • Super Admin
    • Marketing Manager
    • Content Manager
    • Customer Support
    • Finance Manager
    • Operations Manager
  3. Menus (sys_menu)

    • Complete menu hierarchy (~120+ menu items)
    • Marketing Center, Content Management, User Management, etc.
    • Directory, Menu, and Button types
  4. API Permissions (sys_api_permission)

    • ~250+ API endpoints
    • Mapped to modules and methods
  5. Role Associations

    • Admin assigned Super Admin role
    • Role-menu relationships
    • Role-API permission relationships

Expected output:

🌱 Seeding database...
✓ Created 1 users
✓ Created 6 roles
✓ Created 120+ menus
✓ Created 250+ API permissions
✓ Created user-role associations
✓ Created role-menu associations
✓ Created role-API permission associations
✅ Database seeded successfully!

4.2 Verify Seeded Data

# Check user was created
mysql -u root -p box_admin -e "SELECT id, username, nickname, email FROM sys_user;"

# Check roles
mysql -u root -p box_admin -e "SELECT id, name, code FROM sys_role;"

# Check menus (top-level)
mysql -u root -p box_admin -e "SELECT id, title, name, path FROM sys_menu WHERE parent_id IS NULL;"

# Verify admin has roles
mysql -u root -p box_admin -e "
  SELECT u.username, r.name
  FROM sys_user u
  JOIN sys_user_role ur ON u.id = ur.user_id
  JOIN sys_role r ON ur.role_id = r.id
  WHERE u.username = 'admin';
"

4.3 Seed MongoDB (Manual)

For MongoDB collections, refer to mongo-db-seeds.md for sample data:

# Connect to MongoDB
mongosh -u admin -p box_admin

# Example: Seed adsModule collection
db.adsModule.insertMany([
  { adsModule: "启动页(10:21)" },
  { adsModule: "轮播(2:1)" },
  { adsModule: "弹窗-图标(1:1)" },
  { adsModule: "弹窗-图片(2:3)" },
  { adsModule: "弹窗-官方(2:3)" },
  { adsModule: "瀑布流-图标(1:1)" },
  { adsModule: "瀑布流-文字" },
  { adsModule: "布流-视频(8:5)" },
  { adsModule: "悬浮-底部(1:1)" },
  { adsModule: "悬浮-边缘(1:1)" },
  { adsModule: "banner(4:1)" },
  { adsModule: "片头(8:5)" },
  { adsModule: "暂停(2:1)" }
])

# Verify
db.adsModule.find()

Note: Full MongoDB seeding scripts are in mongo-db-seeds.md. Implement as needed for your environment.


🔄 Step 5: Quick Setup (All-in-One)

For convenience, run the MySQL migration plus the Mongo admin seed in one command:

pnpm prisma:migrate:dev:mysql && pnpm prisma:seed:box-admin:admin

✅ Step 6: Verify Installation

6.1 Start Development Server

# Start Box Management API in watch mode
pnpm dev:mgnt

Expected output:

[Nest] INFO [NestFactory] Starting Nest application...
[Nest] INFO [InstanceLoader] AppModule dependencies initialized
[Nest] INFO [RoutesResolver] AuthController {/mgnt/auth}
[Nest] INFO [RoutesResolver] UserController {/mgnt/user}
...
[Nest] INFO [NestApplication] Nest application successfully started
🚀 Server running on http://0.0.0.0:3300
📚 API Documentation: http://0.0.0.0:3300/api-docs

6.2 Test API Endpoints

Health Check:

curl http://localhost:3300/health

Login with seeded admin:

curl -X POST http://localhost:3300/mgnt/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "admin",
    "password": "a123456"
  }'

Expected response:

{
  "success": true,
  "code": "OK",
  "message": "success",
  "data": {
    "account": "admin",
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "avatar": null,
    "nickname": "Administrator",
    "email": "admin@box.com",
    ...
  },
  "timestamp": "2025-11-23T12:34:56.789Z"
}

6.3 Access Swagger Documentation

Open browser: http://localhost:3300/api-docs


🔄 Future: Adding New MySQL Migrations

When to Create a Migration

  • Adding new tables
  • Modifying existing table columns
  • Adding/removing indexes
  • Changing relationships
  • Any schema changes

Migration Workflow

1. Modify Prisma Schema

Edit files in prisma/mysql/schema/:

// Example: Add new field to user.prisma
model SysUser {
  id              Int       @id @default(autoincrement())
  username        String    @unique @db.VarChar(50)
  // ... existing fields ...

  // NEW: Add phone number field
  phone           String?   @db.VarChar(20)

  @@map("sys_user")
}

2. Create Migration

# Generate migration with descriptive name
pnpm prisma:migrate:dev:mysql
# When prompted, enter migration name: add_user_phone_field

What happens:

  • Prisma detects schema changes
  • Creates new migration file in prisma/mysql/migrations/XXXXXXXXXXXXXX_add_user_phone_field/
  • Contains SQL DDL statements
  • Applies migration to database
  • Updates _prisma_migrations table
  • Regenerates Prisma Client

3. Review Generated Migration

# Check the generated SQL
cat prisma/mysql/migrations/XXXXXXXXXXXXXX_add_user_phone_field/migration.sql

Example output:

-- AlterTable
ALTER TABLE `sys_user` ADD COLUMN `phone` VARCHAR(20) NULL;

4. Update Seed Data (if needed)

If your migration requires seed data updates:

// prisma/mysql/seed.ts
const adminUser = {
  username: 'admin',
  password: await bcrypt.hash('a123456', 10),
  phone: '+1234567890', // Add new field
  // ... other fields
};

5. Verify Migration

# Check database schema
mysql -u root -p box_admin -e "DESCRIBE sys_user;"

# Check migration history
mysql -u root -p box_admin -e "
  SELECT migration_name, finished_at, applied_steps_count
  FROM _prisma_migrations
  ORDER BY finished_at DESC
  LIMIT 5;
"

Migration Best Practices

✅ DO:

  • Use descriptive migration names
  • Test migrations in development first
  • Back up production database before migrating
  • Review generated SQL before applying
  • Keep migrations atomic (one logical change)
  • Commit migration files to version control

❌ DON'T:

  • Edit migration files after they're applied
  • Delete migration files
  • Skip migrations
  • Apply migrations manually without Prisma
  • Mix MySQL and MongoDB changes in same migration

Common Migration Commands

# Create new migration without applying
pnpm exec dotenv -e .env.mgnt.dev -- prisma migrate dev --create-only --schema=prisma/mysql/schema

# Apply pending migrations
pnpm prisma:migrate:dev:mysql

# Reset database (⚠️ DESTRUCTIVE - deletes all data)
pnpm prisma:migrate:reset:mysql

# Check migration status
pnpm exec dotenv -e .env.mgnt.dev -- prisma migrate status --schema=prisma/mysql/schema

# Generate client only (after schema changes)
pnpm prisma:generate:mysql

Handling Migration Conflicts

If multiple developers create migrations:

# 1. Pull latest changes
git pull origin main

# 2. Check for migration conflicts
pnpm exec dotenv -e .env.mgnt.dev -- prisma migrate status --schema=prisma/mysql/schema

# 3. If conflicts exist, reset and re-migrate
pnpm prisma:migrate:reset:mysql
pnpm prisma:migrate:dev:mysql

Production Migration Strategy

# 1. Test migration in staging
pnpm exec dotenv -e .env.staging -- prisma migrate deploy --schema=prisma/mysql/schema

# 2. Backup production database
mysqldump -u root -p box_admin > backup_$(date +%Y%m%d_%H%M%S).sql

# 3. Apply to production
pnpm exec dotenv -e .env.production -- prisma migrate deploy --schema=prisma/mysql/schema

# 4. Verify
pnpm exec dotenv -e .env.production -- prisma migrate status --schema=prisma/mysql/schema

🛠️ Troubleshooting

Issue: pnpm install fails

# Clear cache and retry
pnpm store prune
rm -rf node_modules pnpm-lock.yaml
pnpm install

Issue: Prisma Client not found

# Regenerate clients
pnpm prisma:generate

Issue: Migration fails

# Check database connection
mysql -u root -p -e "SELECT 1"

# Reset and retry (development only)
pnpm prisma:migrate:reset:mysql
pnpm prisma:setup:mysql

Issue: Port 3300 already in use

# Change port in .env.mgnt.dev
APP_PORT=3301

# Or kill existing process
lsof -ti:3300 | xargs kill -9

Issue: MongoDB connection fails

# Check MongoDB is running
systemctl status mongod

# Test connection
mongosh -u admin -p --authenticationDatabase admin

📚 Additional Resources

  • Architecture: See ARCHITECTURE_FLOW.md
  • Developer Guide: See DEVELOPER_GUIDE.md
  • Deployment: See DEPLOYMENT_CHECKLIST.md
  • Refactor Summary: See REFACTOR_SUMMARY.md
  • MongoDB Seeds: See mongo-db-seeds.md

🎯 Quick Reference

Task Command
Install dependencies pnpm install
Generate Prisma clients pnpm prisma:generate
Run migrations pnpm prisma:migrate:dev:mysql
Seed admin data pnpm prisma:seed:box-admin:admin
Seed ad modules pnpm prisma:seed:box-admin
Full setup pnpm prisma:migrate:dev:mysql && pnpm prisma:seed:box-admin:admin
Start dev server pnpm dev:mgnt
Build production pnpm build:mgnt
Start production pnpm start:mgnt
Type check pnpm typecheck
Lint code pnpm lint
Run all tests pnpm test

✨ Default Credentials

After seeding, login with:

  • Username: admin
  • Password: a123456
  • Email: admin@box.com

⚠️ IMPORTANT: Change the default password in production!


Last Updated: November 23, 2025
Prisma Version: 5.15.0
NestJS Version: 10.3.8
Node Version: 20+

🧭 Ads stats hints (box-stats-api)

  • POST /stats/api/v1/stats/ad-click accepts optional ipv4 (must be valid IPv4); the backend uses it when present and falls back to extracted client IP otherwise.