واجهة المستخدم المدفوعة بالخادم (SDUI) في NestJS: إدارة CRUD بدون كود فرونت إند
ما هي واجهة المستخدم المدفوعة بالخادم؟
Server-Driven UI أو SDUI هي نمط معماري يتحكم فيه الخادم بالكامل في هيكل الواجهة وسلوكها. بدلاً من أن يقرر الفرونت إند كيف تبدو الصفحة، يرسل الخادم وصفاً JSON كاملاً للمكونات — الحقول، الأزرار، الجداول — ويقوم الكلاينت بتصييرها تلقائياً. النتيجة: تغيير كامل في واجهة الإدارة دون لمس كود الفرونت إند.
لماذا NestJS مثالية لتطبيق SDUI؟
يتميز NestJS بهيكله المعياري القائم على TypeScript، مما يجعله مثالياً لبناء APIs تُعيد وصفاً منظماً للواجهة. يمكنك تعريف Decorators خاصة تُولّد تعريف الحقول تلقائياً من الـ Entity مباشرة.
بناء نظام SDUI-CRUD خطوة بخطوة
1. تعريف الـ Entity مع Metadata للواجهة
@Entity()
export class Product {
@UIField({ label: 'اسم المنتج', type: 'text', required: true })
@Column()
name: string;
@UIField({ label: 'السعر', type: 'number', required: true })
@Column('decimal')
price: number;
@UIField({ label: 'الحالة', type: 'select', options: ['active','inactive'] })
@Column()
status: string;
}
2. بناء الـ Decorator المخصص UIField
export const UI_FIELD_KEY = 'ui:field';
export function UIField(config: UIFieldConfig) {
return Reflect.metadata(UI_FIELD_KEY, config);
}
export interface UIFieldConfig {
label: string;
type: 'text' | 'number' | 'select' | 'date' | 'boolean';
required?: boolean;
options?: string[];
}
3. الـ Schema Generator Service
@Injectable()
export class SchemaGeneratorService {
generateSchema(entityClass: Function) {
const instance = new (entityClass as any)();
const fields = [];
for (const key of Object.keys(instance)) {
const config = Reflect.getMetadata(UI_FIELD_KEY, entityClass.prototype, key);
if (config) fields.push({ field: key, ...config });
}
return { entity: entityClass.name, fields, actions: ['create','read','update','delete'] };
}
}
4. الـ SDUI Controller
@Controller('admin/sdui')
export class SduiController {
@Get(':entity/schema')
getSchema(@Param('entity') entity: string) {
const entityClass = this.entityRegistry.get(entity);
return this.schemaGenerator.generateSchema(entityClass);
}
@Get(':entity')
findAll(@Param('entity') entity: string, @Query() query: PaginationDto) {
return this.entityRegistry.getRepository(entity)
.findAndCount({ skip: query.skip, take: query.take });
}
@Post(':entity')
create(@Param('entity') entity: string, @Body() body: Record) {
return this.entityRegistry.getRepository(entity).save(body);
}
}
5. الاستجابة JSON للفرونت إند
{
"entity": "Product",
"fields": [
{ "field": "name", "label": "اسم المنتج", "type": "text", "required": true },
{ "field": "price", "label": "السعر", "type": "number", "required": true },
{ "field": "status", "label": "الحالة", "type": "select", "options": ["active","inactive"] }
],
"actions": ["create","read","update","delete"]
}
فوائد هذا النمط
إضافة حقل جديد تعني إضافة Decorator واحد فقط في الباك إند — الواجهة تتحدث نفسها. هذا يقلل وقت التسليم ويلغي التنسيق المتكرر بين فرقي الفرونت والباك إند.
متى تستخدم SDUI ومتى تتجنبه؟
SDUI مثالي لـ: لوحات الإدارة الداخلية، أنظمة CMS، وواجهات Back-office. ليس الخيار الأفضل للواجهات التي تتطلب تفاعلاً بصرياً معقداً أو تجربة مستخدم مخصصة جداً.
يمكنك قراءة المقال الأصلي على Medium.
هل تواجه نفس هذه المشكلات في مشروعك؟
المهندس عبدالرحمن جاهز لتقديم مراجعة كود مجانية.
Keywords & SEO Tags
Technical Standards Met
- ✔️ GCC payment gate check
- ✔️ Web security standards compliance
- ✔️ ACID transaction isolation level
- ✔️ Compound SQL indexing