Architecture
Data Flow Design
Understanding Request Processing and Data Flow in NextJS Base
๐ฏ Overview
This document details the data flow process in NextJS Base, from user operations to database storage.
๐ Request Flow
Complete Request Chain
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ User Operation โ
โ (Click Button, Submit Form) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SmartCrudPage โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. Collect User Input โ โ
โ โ 2. Transform Search Params Based on fieldsConfig โ โ
โ โ 3. Call Corresponding Server Action โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ Call actions.getList(params)
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ wrapAction โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. Parse Action Name, Determine Permission Level โ โ
โ โ - pub* โ PUBLIC (No Login Required) โ โ
โ โ - auth* โ AUTH (Login Required) โ โ
โ โ - sys* โ SYSTEM (Admin Permission Required) โ โ
โ โ โ โ
โ โ 2. Execute Authentication Check โ โ
โ โ - Get Current Session โ โ
โ โ - Verify User Identity โ โ
โ โ โ โ
โ โ 3. Execute Permission Check (sys* prefix) โ โ
โ โ - Check Admin Access Permission โ โ
โ โ - Check RBAC Permission โ โ
โ โ โ โ
โ โ 4. Execute Business Logic โ โ
โ โ โ โ
โ โ 5. Record Operation Log โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ Execute handler(params, context)
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ BaseDAO โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. Build Query Conditions โ โ
โ โ - Parse whereJson (Search Conditions) โ โ
โ โ - Add Soft Delete Filter โ โ
โ โ - Build Sort Conditions โ โ
โ โ โ โ
โ โ 2. Execute Data Validation (create/update) โ โ
โ โ - Schema Validation โ โ
โ โ - Custom Validators โ โ
โ โ - Uniqueness Check โ โ
โ โ โ โ
โ โ 3. Execute Hooks โ โ
โ โ - beforeCreate / beforeUpdate / beforeDelete โ โ
โ โ โ โ
โ โ 4. Field Filtering โ โ
โ โ - Only Keep creatable/updatable Fields โ โ
โ โ โ โ
โ โ 5. Data Transformation (transforms) โ โ
โ โ - input Transform (Before Write) โ โ
โ โ - output Transform (After Read) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ Call Prisma Methods
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Prisma Client โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. Build SQL Query โ โ
โ โ 2. Execute Database Operation โ โ
โ โ 3. Return Result โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PostgreSQL โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ๐ Permission Check
Permission Levels
| Prefix | Level | Auth | RBAC | Log |
|---|---|---|---|---|
pub | PUBLIC | โ | โ | โ |
auth | AUTH | โ | โ | โ |
sys | SYSTEM | โ | โ | โ |
_ | PRIVATE | - | - | - |
Permission Check Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ wrapAction Permission Check โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโ
โ Parse Action Name โ
โ Determine Level โ
โโโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
โ pub* prefix โ โ auth* prefix โ โ sys* prefix โ
โ PUBLIC level โ โ AUTH level โ โ SYSTEM level โ
โโโโโโโโโฌโโโโโโโโ โโโโโโโโโฌโโโโโโโโ โโโโโโโโโฌโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
โ Optional Get โ โ Must Login โ โ Must Login โ
โ User Info โ โ โ โ โ
โโโโโโโโโฌโโโโโโโโ โโโโโโโโโฌโโโโโโโโ โโโโโโโโโฌโโโโโโโโ
โ โ โ
โ โ โผ
โ โ โโโโโโโโโโโโโโโโโ
โ โ โ Check Admin โ
โ โ โ Permission โ
โ โ โ hasBackendAccess โ
โ โ โโโโโโโโโฌโโโโโโโโ
โ โ โ
โ โ โผ
โ โ โโโโโโโโโโโโโโโโโ
โ โ โ RBAC Check โ
โ โ โ Check User โ
โ โ โ Roles Have โ
โ โ โ This Action โ
โ โ โโโโโโโโโฌโโโโโโโโ
โ โ โ
โโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโ
โ Execute Business โ
โ Logic โ
โโโโโโโโโโโโโโโโโโโโโโโโโRBAC Permission Check Details
// 1. Get User Roles
const user = await getUser(userId)
const roleIds = user.roles // ['role_id_1', 'role_id_2']
// 2. Get Role Permissions
const roles = await prisma.role.findMany({
where: { id: { in: roleIds }, enable: true }
})
// 3. Aggregate All Permission IDs
const permissionIds = roles.flatMap(role => role.permission)
// 4. Get Permission Details
const permissions = await prisma.permission.findMany({
where: { id: { in: permissionIds } }
})
// 5. Check if Action is in Permission List
const allActions = permissions.flatMap(p => p.actions)
const hasPermission = allActions.includes(actionName)๐ Data Transformation
Search Parameter Transformation
SmartCrudPage automatically transforms search parameters into Prisma query conditions based on search configuration in fieldsConfig:
// User Input
{
name: 'John',
status: 'active',
createdAt: ['2024-01-01', '2024-12-31']
}
// Transformed whereJson
{
name: { contains: 'John' }, // like mode
status: 'active', // exact mode
createdAt: { // range mode
gte: '2024-01-01T00:00:00.000Z',
lte: '2024-12-31T23:59:59.999Z'
}
}Search Mode Comparison
| Mode | User Input | Prisma Query |
|---|---|---|
like | "John" | { contains: "John" } |
exact | "active" | "active" |
in | ["a", "b"] | { in: ["a", "b"] } |
range | ["2024-01", "2024-12"] | { gte: ..., lte: ... } |
Data Output Transformation
BaseDAO automatically handles special types returned by Prisma:
// Prisma Returns
{
id: 'cuid123',
price: Decimal(99.99), // Prisma Decimal Type
count: BigInt(1000000), // BigInt Type
createdAt: Date(...) // Date Type
}
// After Transformation
{
id: 'cuid123',
price: 99.99, // Converted to number
count: 1000000, // Converted to number
createdAt: Date(...) // Keep Date (Next.js will serialize)
}๐ List Query Flow
Complete getList Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SmartCrudPage Request โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ params: { current, pageSize, sort, filter }
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Search Parameter Transformation โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ generateSearchTransform(fieldsConfig) โ โ
โ โ โ โ
โ โ Input: { name: 'John', status: 'active' } โ โ
โ โ Output: { whereJson: { name: { contains: 'John' }, ... } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ actions.getList(params) โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ params: { โ โ
โ โ page: 1, โ โ
โ โ pageSize: 20, โ โ
โ โ whereJson: { ... }, โ โ
โ โ sort: { createdAt: 'desc' } โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ BaseDAO.getList() โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 1. Build WHERE Conditions โ โ
โ โ - Merge whereJson โ โ
โ โ - Add Soft Delete Filter (deletedAt: null) โ โ
โ โ โ โ
โ โ 2. Build Sort Conditions โ โ
โ โ - Parse sort Parameter โ โ
โ โ - Apply Default Sort โ โ
โ โ โ โ
โ โ 3. Execute Query โ โ
โ โ - Query Data (findMany) โ โ
โ โ - Query Total (count) โ โ
โ โ โ โ
โ โ 4. Data Transformation โ โ
โ โ - serializeRecord (Handle Decimal/BigInt) โ โ
โ โ - output transform (Custom Transform) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Return Result โ
โ { โ
โ success: true, โ
โ data: { โ
โ list: [...], โ
โ total: 100, โ
โ page: 1, โ
โ pageSize: 20 โ
โ } โ
โ } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ๏ธ Create/Update Flow
Complete create/update Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SmartModalForm Submit โ
โ formData: { name: 'Test', enable: true, remark: 'Note' } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ actions.create(formData) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ wrapAction Processing โ
โ - Auth Check โ โ
โ - Permission Check โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ BaseDAO.create() โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Step 1: Field Filtering โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ Only Keep creatable Fields โ โ
โ โ { name: 'Test', enable: true, remark: 'Note' } โ โ
โ โ โ โ โ
โ โ { name: 'Test', enable: true, remark: 'Note' } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Step 2: Data Validation โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ - Schema Validation (required, maxLength, enum...) โ โ
โ โ - Custom Validators โ โ
โ โ - Uniqueness Check โ โ
โ โ โ โ
โ โ Validation Failed โ Throw ValidationError โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Step 3: Execute beforeCreate Hook โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ beforeCreate: async (data) => { โ โ
โ โ // Can Modify Data โ โ
โ โ data.code = data.code.toUpperCase() โ โ
โ โ return data โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Step 4: Execute input Transform โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ transforms: { โ โ
โ โ input: (data) => { โ โ
โ โ // Data Transform Before Write โ โ
โ โ return { ...data, updatedBy: userId } โ โ
โ โ } โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Step 5: Execute Prisma create โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ prisma.model.create({ data: filteredData }) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Step 6: Execute afterCreate Hook โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ afterCreate: async (record) => { โ โ
โ โ // Post-Create Operations, e.g., Send Notification โ โ
โ โ await sendNotification(record) โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Step 7: Execute output Transform โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ transforms: { โ โ
โ โ output: (record) => { โ โ
โ โ // Data Transform Before Return โ โ
โ โ return { ...record, displayName: `#${record.id}` } โ โ
โ โ } โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ wrapAction Log Record โ
โ { โ
โ action: 'sysCreateRole', โ
โ resource: 'role', โ
โ params: { name: 'Test' }, โ
โ result: { id: 'xxx' }, โ
โ success: true, โ
โ duration: 123 โ
โ } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Return Result โ
โ { success: true, data: { id: 'xxx', name: 'Test', ... } } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ