ElysiaJS + Bun: بناء واجهة برمجة تطبيقات REST آمنة الأنواع من طرف إلى طرف

ElysiaJS + Bun: بناء واجهة برمجة تطبيقات REST آمنة الأنواع من طرف إلى طرف
إذا كنت تبني واجهات برمجة التطبيقات باستخدام Express أو Fastify، فقد حان الوقت للتعرف على ElysiaJS — إطار عمل ويب أصلي لـ Bun يوفر أمان الأنواع من طرف إلى طرف، وتوثيق OpenAPI تلقائي، وأداء ينافس أطر عمل Go و Rust.
بينما يركز Hono على قابلية النقل عبر بيئات التشغيل المتعددة، يذهب ElysiaJS بالكامل نحو أداء Bun ونظام أنواع TypeScript. النتيجة؟ إطار عمل API حيث تتشارك معالجات المسارات ومخططات التحقق وحتى عميل الواجهة الأمامية مصدراً واحداً للأنواع — بدون أي توليد للكود.
لماذا ElysiaJS؟
إليك ما يميز ElysiaJS في مجال واجهات برمجة تطبيقات TypeScript:
- أمان الأنواع من طرف إلى طرف: تنتقل الأنواع من تعريف المسار إلى التحقق إلى العميل — بدون
any، بدون تحويل أنواع - أداء أصلي لـ Bun: مبني خصيصاً لـ Bun، مستفيداً من خادم HTTP الداخلي السريع
- OpenAPI/Swagger تلقائي: كل مسار محقق منه يولد توثيق OpenAPI 3.0 تلقائياً
- Eden Treaty: عميل آمن الأنواع يستنتج الأنواع مباشرة من خادمك — بدون حاجة لتوليد الكود
- نظام إضافات: مصادقة Bearer، CORS، JWT، GraphQL، والمزيد كإضافات رسمية
- تحقق تصريحي: تحقق من المخططات بناءً على TypeBox يعمل أيضاً كأنواع TypeScript
المتطلبات الأساسية
قبل البدء، تأكد من توفر:
- Bun 1.1+ مثبت (bun.sh)
- معرفة أساسية بـ TypeScript
- إلمام بمفاهيم REST API
- محرر كود (يُنصح بـ VS Code)
يستخدم هذا الدليل ElysiaJS 1.2+ و Bun 1.1+. إذا كنت قادماً من Express أو Hono، ستجد أنماطاً مألوفة مع إضافات قوية.
ما الذي ستبنيه
سنبني واجهة برمجة تطبيقات إدارة المهام كاملة مع:
- عمليات CRUD كاملة للمهام
- تحقق من المدخلات مع مخططات آمنة الأنواع
- مصادقة بتوكن Bearer
- تجميع المسارات والحراسات
- توثيق Swagger تلقائي
- عميل آمن الأنواع باستخدام Eden Treaty
الخطوة 1: إعداد المشروع
أنشئ مشروع ElysiaJS جديداً باستخدام أداة Bun المدمجة:
bun create elysia task-api
cd task-apiهذا ينشئ هيكل مشروع بسيط. لنثبت الإضافات التي نحتاجها:
bun add @elysiajs/swagger @elysiajs/bearer @elysiajs/corsهيكل المشروع يجب أن يبدو هكذا:
task-api/
├── src/
│ └── index.ts
├── package.json
├── tsconfig.json
└── bun.lock
لننظمه لواجهة برمجة تطبيقات حقيقية:
mkdir -p src/{routes,models,plugins,middleware}الهيكل المحدث:
task-api/
├── src/
│ ├── routes/
│ │ └── tasks.ts
│ ├── models/
│ │ └── task.model.ts
│ ├── plugins/
│ │ └── auth.ts
│ ├── middleware/
│ └── index.ts
├── package.json
└── tsconfig.json
الخطوة 2: تعريف نماذج البيانات
يستخدم ElysiaJS مكتبة TypeBox (t) لمخططات التحقق. الجمال في أن هذه المخططات هي في نفس الوقت:
- محققات وقت التشغيل (مثل Zod)
- أنواع TypeScript (عبر الاستنتاج)
- تعريفات مخطط OpenAPI
أنشئ src/models/task.model.ts:
import { Elysia, t } from 'elysia'
// تعريف مخططات المهام كإضافة Elysia لإعادة الاستخدام
export const taskModel = new Elysia({ name: 'Model.Task' })
.model({
// مخطط إنشاء مهمة
'task.create': t.Object({
title: t.String({ minLength: 1, maxLength: 200 }),
description: t.Optional(t.String({ maxLength: 1000 })),
priority: t.Optional(
t.Union([
t.Literal('low'),
t.Literal('medium'),
t.Literal('high')
], { default: 'medium' })
),
dueDate: t.Optional(t.String({ format: 'date' }))
}),
// مخطط تحديث مهمة
'task.update': t.Object({
title: t.Optional(t.String({ minLength: 1, maxLength: 200 })),
description: t.Optional(t.String({ maxLength: 1000 })),
priority: t.Optional(
t.Union([
t.Literal('low'),
t.Literal('medium'),
t.Literal('high')
])
),
completed: t.Optional(t.Boolean()),
dueDate: t.Optional(t.String({ format: 'date' }))
}),
// مخطط استجابة المهمة
'task.response': t.Object({
id: t.String(),
title: t.String(),
description: t.Nullable(t.String()),
priority: t.Union([
t.Literal('low'),
t.Literal('medium'),
t.Literal('high')
]),
completed: t.Boolean(),
dueDate: t.Nullable(t.String()),
createdAt: t.String(),
updatedAt: t.String()
}),
// معاملات مشتركة
'task.params': t.Object({
id: t.String()
})
})بتغليف النماذج في إضافة Elysia، تحصل على إكمال تلقائي عند الإشارة إلى أسماء النماذج في معالجات المسارات. لا أخطاء نصية — المترجم يكتشفها.
الخطوة 3: بناء مخزن البيانات في الذاكرة
لهذا الدليل، سنستخدم مخزناً بسيطاً في الذاكرة. في الإنتاج، ستستبدله بقاعدة بيانات (SQLite عبر Bun، أو Drizzle ORM، أو Prisma، إلخ).
أنشئ src/models/store.ts:
export interface Task {
id: string
title: string
description: string | null
priority: 'low' | 'medium' | 'high'
completed: boolean
dueDate: string | null
createdAt: string
updatedAt: string
}
// مخزن بسيط في الذاكرة
class TaskStore {
private tasks: Map<string, Task> = new Map()
create(data: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>): Task {
const id = crypto.randomUUID()
const now = new Date().toISOString()
const task: Task = {
id,
...data,
createdAt: now,
updatedAt: now
}
this.tasks.set(id, task)
return task
}
getAll(): Task[] {
return Array.from(this.tasks.values())
}
getById(id: string): Task | undefined {
return this.tasks.get(id)
}
update(id: string, data: Partial<Omit<Task, 'id' | 'createdAt'>>): Task | undefined {
const task = this.tasks.get(id)
if (!task) return undefined
const updated: Task = {
...task,
...data,
updatedAt: new Date().toISOString()
}
this.tasks.set(id, updated)
return updated
}
delete(id: string): boolean {
return this.tasks.delete(id)
}
filter(predicate: (task: Task) => boolean): Task[] {
return this.getAll().filter(predicate)
}
}
export const taskStore = new TaskStore()الخطوة 4: إنشاء مسارات المهام
الآن للجوهر الأساسي لواجهة برمجة التطبيقات. أنشئ src/routes/tasks.ts:
import { Elysia, t } from 'elysia'
import { taskModel } from '../models/task.model'
import { taskStore } from '../models/store'
export const taskRoutes = new Elysia({ prefix: '/tasks' })
.use(taskModel)
// GET /tasks - عرض جميع المهام مع تصفية اختيارية
.get('/', ({ query }) => {
let tasks = taskStore.getAll()
if (query.completed !== undefined) {
tasks = tasks.filter(t => t.completed === (query.completed === 'true'))
}
if (query.priority) {
tasks = tasks.filter(t => t.priority === query.priority)
}
return {
data: tasks,
total: tasks.length
}
}, {
query: t.Object({
completed: t.Optional(t.String()),
priority: t.Optional(
t.Union([
t.Literal('low'),
t.Literal('medium'),
t.Literal('high')
])
)
}),
detail: {
tags: ['Tasks'],
summary: 'عرض جميع المهام'
}
})
// GET /tasks/:id - الحصول على مهمة واحدة
.get('/:id', ({ params, status }) => {
const task = taskStore.getById(params.id)
if (!task) {
return status(404, {
error: 'المهمة غير موجودة',
id: params.id
})
}
return task
}, {
params: 'task.params',
detail: {
tags: ['Tasks'],
summary: 'الحصول على مهمة بالمعرف'
}
})
// POST /tasks - إنشاء مهمة جديدة
.post('/', ({ body }) => {
const task = taskStore.create({
title: body.title,
description: body.description ?? null,
priority: body.priority ?? 'medium',
completed: false,
dueDate: body.dueDate ?? null
})
return task
}, {
body: 'task.create',
response: 'task.response',
detail: {
tags: ['Tasks'],
summary: 'إنشاء مهمة جديدة'
}
})
// PATCH /tasks/:id - تحديث مهمة
.patch('/:id', ({ params, body, status }) => {
const task = taskStore.update(params.id, {
...(body.title !== undefined && { title: body.title }),
...(body.description !== undefined && { description: body.description }),
...(body.priority !== undefined && { priority: body.priority }),
...(body.completed !== undefined && { completed: body.completed }),
...(body.dueDate !== undefined && { dueDate: body.dueDate })
})
if (!task) {
return status(404, {
error: 'المهمة غير موجودة',
id: params.id
})
}
return task
}, {
params: 'task.params',
body: 'task.update',
detail: {
tags: ['Tasks'],
summary: 'تحديث مهمة'
}
})
// DELETE /tasks/:id - حذف مهمة
.delete('/:id', ({ params, status }) => {
const deleted = taskStore.delete(params.id)
if (!deleted) {
return status(404, {
error: 'المهمة غير موجودة',
id: params.id
})
}
return { success: true, id: params.id }
}, {
params: 'task.params',
detail: {
tags: ['Tasks'],
summary: 'حذف مهمة'
}
})لاحظ كيف يستخدم كل معالج مسار أسماء النماذج ('task.create'، 'task.params'، إلخ) بدلاً من المخططات المضمنة. هذا يبقي المسارات نظيفة ويضمن الاتساق.
الخطوة 5: إضافة المصادقة مع الحراسات
تتيح لك حراسات ElysiaJS حماية مجموعات من المسارات بتحقق مشترك وخطافات. أنشئ src/plugins/auth.ts:
import { Elysia } from 'elysia'
import { bearer } from '@elysiajs/bearer'
// في الإنتاج، استخدم مكتبة JWT مناسبة وقاعدة بيانات
const VALID_TOKENS = new Set([
'demo-token-2026'
])
export const authPlugin = new Elysia({ name: 'Plugin.Auth' })
.use(bearer())
.derive(({ bearer }) => {
return {
isAuthenticated: bearer ? VALID_TOKENS.has(bearer) : false
}
})
.macro({
requireAuth(enabled: boolean) {
if (!enabled) return
return {
beforeHandle({ isAuthenticated, status, set }) {
if (!isAuthenticated) {
set.headers['WWW-Authenticate'] = 'Bearer realm="task-api"'
return status(401, {
error: 'غير مصرح',
message: 'يلزم توكن Bearer صالح'
})
}
}
}
}
})التوكن المشفر أعلاه للتوضيح فقط. في الإنتاج، استخدم توكنات JWT مع توقيع وانتهاء صلاحية مناسبين وقاعدة بيانات مستخدمين حقيقية.
الآن حدّث src/routes/tasks.ts لاستخدام إضافة المصادقة لعمليات الكتابة. أضف إضافة المصادقة واحمِ المسارات المعدلة:
import { Elysia, t } from 'elysia'
import { taskModel } from '../models/task.model'
import { taskStore } from '../models/store'
import { authPlugin } from '../plugins/auth'
export const taskRoutes = new Elysia({ prefix: '/tasks' })
.use(taskModel)
.use(authPlugin)
// مسارات GET تبقى عامة (بدون requireAuth)
.get('/', ({ query }) => {
// ... نفس الكود السابق
}, {
// ... نفس الإعدادات
})
.get('/:id', ({ params, status }) => {
// ... نفس الكود السابق
}, {
// ... نفس الإعدادات
})
// POST، PATCH، DELETE تحتاج مصادقة الآن
.post('/', ({ body }) => {
// ... نفس المعالج
}, {
body: 'task.create',
response: 'task.response',
requireAuth: true, // محمي!
detail: {
tags: ['Tasks'],
summary: 'إنشاء مهمة جديدة',
security: [{ bearer: [] }]
}
})
.patch('/:id', ({ params, body, status }) => {
// ... نفس المعالج
}, {
params: 'task.params',
body: 'task.update',
requireAuth: true, // محمي!
detail: {
tags: ['Tasks'],
summary: 'تحديث مهمة',
security: [{ bearer: [] }]
}
})
.delete('/:id', ({ params, status }) => {
// ... نفس المعالج
}, {
params: 'task.params',
requireAuth: true, // محمي!
detail: {
tags: ['Tasks'],
summary: 'حذف مهمة',
security: [{ bearer: [] }]
}
})الماكرو requireAuth: true يفصل منطق المصادقة بشكل نظيف عن منطق الأعمال. لا سلاسل middleware، لا next() — مجرد إعداد تصريحي.
الخطوة 6: ربط كل شيء معاً
حدّث src/index.ts لتجميع كل القطع:
import { Elysia } from 'elysia'
import { swagger } from '@elysiajs/swagger'
import { cors } from '@elysiajs/cors'
import { taskRoutes } from './routes/tasks'
const app = new Elysia()
// إضافات عامة
.use(cors())
.use(swagger({
documentation: {
info: {
title: 'واجهة برمجة تطبيقات إدارة المهام',
version: '1.0.0',
description: 'واجهة برمجة تطبيقات REST آمنة الأنواع مبنية بـ ElysiaJS و Bun'
},
tags: [
{ name: 'Tasks', description: 'عمليات CRUD للمهام' },
{ name: 'Health', description: 'فحوصات صحة API' }
],
components: {
securitySchemes: {
bearer: {
type: 'http',
scheme: 'bearer'
}
}
}
}
}))
// فحص الصحة
.get('/health', () => ({
status: 'ok',
timestamp: new Date().toISOString(),
runtime: 'bun',
version: '1.0.0'
}), {
detail: {
tags: ['Health'],
summary: 'فحص صحة API'
}
})
// تركيب مجموعات المسارات
.use(taskRoutes)
// معالج أخطاء عام
.onError(({ code, error }) => {
if (code === 'VALIDATION') {
return {
error: 'خطأ في التحقق',
message: error.message
}
}
return {
error: 'خطأ داخلي في الخادم',
message: 'حدث خطأ ما'
}
})
.listen(3000)
console.log(`🦊 واجهة برمجة تطبيقات المهام تعمل على ${app.server?.hostname}:${app.server?.port}`)
console.log(`📚 توثيق Swagger على http://localhost:3000/swagger`)
// تصدير نوع التطبيق لـ Eden Treaty
export type App = typeof appالسطر الأخير — export type App = typeof app — هو المكون السحري. يستنتج ElysiaJS نوع API الكامل من تعريفات المسارات، ويستخدم Eden Treaty هذا النوع على جانب العميل.
الخطوة 7: اختبار واجهة برمجة التطبيقات
شغّل الخادم:
bun run src/index.tsالآن اختبر كل نقطة نهاية:
# فحص الصحة
curl http://localhost:3000/health
# إنشاء مهمة (مع مصادقة)
curl -X POST http://localhost:3000/tasks \
-H "Content-Type: application/json" \
-H "Authorization: Bearer demo-token-2026" \
-d '{"title": "تعلم ElysiaJS", "priority": "high"}'
# عرض جميع المهام (عام)
curl http://localhost:3000/tasks
# تصفية حسب الأولوية
curl "http://localhost:3000/tasks?priority=high"
# تحديث مهمة
curl -X PATCH http://localhost:3000/tasks/<task-id> \
-H "Content-Type: application/json" \
-H "Authorization: Bearer demo-token-2026" \
-d '{"completed": true}'
# حذف مهمة
curl -X DELETE http://localhost:3000/tasks/<task-id> \
-H "Authorization: Bearer demo-token-2026"
# محاولة بدون مصادقة (يجب أن تحصل على 401)
curl -X POST http://localhost:3000/tasks \
-H "Content-Type: application/json" \
-d '{"title": "يجب أن يفشل"}'افتح http://localhost:3000/swagger في متصفحك لرؤية التوثيق التفاعلي المولد تلقائياً.
الخطوة 8: إضافة عميل Eden Treaty
هنا يتألق ElysiaJS حقاً. يمنحك Eden Treaty عميل HTTP آمن الأنواع بالكامل يستنتج الأنواع مباشرة من كود خادمك — بدون توليد كود، بدون ملفات مخطط منفصلة.
ثبّت Eden:
bun add @elysiajs/edenأنشئ src/client.ts:
import { treaty } from '@elysiajs/eden'
import type { App } from './index'
// إنشاء عميل آمن الأنواع
const api = treaty<App>('localhost:3000')
async function demo() {
// ✅ إكمال تلقائي كامل للمسار والجسم والاستجابة
const { data: tasks } = await api.tasks.get({
query: { priority: 'high' }
})
console.log('المهام عالية الأولوية:', tasks)
// ✅ TypeScript يعرف شكل الجسم
const { data: newTask } = await api.tasks.post({
title: 'شحن الميزة',
priority: 'high'
}, {
headers: {
authorization: 'Bearer demo-token-2026'
}
})
console.log('المهمة المنشأة:', newTask)
// ✅ TypeScript يعرف أن هذا يرجع Task | error
if (newTask) {
const { data: updated } = await api.tasks({ id: newTask.id }).patch({
completed: true
}, {
headers: {
authorization: 'Bearer demo-token-2026'
}
})
console.log('المهمة المحدثة:', updated)
}
}
demo()الفكرة الأساسية: إذا غيرت نوع استجابة مسار على الخادم، يشير TypeScript فوراً إلى كل استدعاء عميل يعتمد على النوع القديم. لا مفاجآت وقت التشغيل، ولا حاجة لاختبار تكامل لاكتشاف عدم التطابق.
الخطوة 9: خطافات دورة الحياة والمنطق المخصص
يوفر ElysiaJS نظام دورة حياة غني للاهتمامات العابرة للمحاور. إليك أمثلة عملية:
تسجيل الطلبات
import { Elysia } from 'elysia'
export const loggerPlugin = new Elysia({ name: 'Plugin.Logger' })
.onRequest(({ request }) => {
console.log(`→ ${request.method} ${new URL(request.url).pathname}`)
})
.onAfterResponse(({ request, set }) => {
console.log(`← ${request.method} ${new URL(request.url).pathname} ${set.status ?? 200}`)
})تحديد معدل الطلبات
import { Elysia } from 'elysia'
const requestCounts = new Map<string, { count: number; resetAt: number }>()
export const rateLimitPlugin = new Elysia({ name: 'Plugin.RateLimit' })
.derive(({ request }) => {
const ip = request.headers.get('x-forwarded-for') ?? 'unknown'
return { clientIp: ip }
})
.onBeforeHandle(({ clientIp, status, set }) => {
const now = Date.now()
const window = 60_000 // دقيقة واحدة
const limit = 100
let entry = requestCounts.get(clientIp)
if (!entry || now > entry.resetAt) {
entry = { count: 0, resetAt: now + window }
requestCounts.set(clientIp, entry)
}
entry.count++
set.headers['X-RateLimit-Limit'] = String(limit)
set.headers['X-RateLimit-Remaining'] = String(Math.max(0, limit - entry.count))
if (entry.count > limit) {
set.headers['Retry-After'] = String(Math.ceil((entry.resetAt - now) / 1000))
return status(429, { error: 'طلبات كثيرة جداً' })
}
})الخطوة 10: الاختبار مع مشغل اختبارات Bun المدمج
يتضمن Bun مشغل اختبارات — لا حاجة لتبعيات إضافية. أنشئ src/__tests__/tasks.test.ts:
import { describe, it, expect, beforeAll } from 'bun:test'
import { treaty } from '@elysiajs/eden'
import { Elysia } from 'elysia'
import { taskRoutes } from '../routes/tasks'
// إنشاء نسخة اختبار
const app = new Elysia()
.use(taskRoutes)
const api = treaty(app)
describe('واجهة برمجة تطبيقات المهام', () => {
let taskId: string
it('يجب أن ينشئ مهمة', async () => {
const { data, status } = await api.tasks.post({
title: 'مهمة اختبار',
priority: 'high'
}, {
headers: {
authorization: 'Bearer demo-token-2026'
}
})
expect(status).toBe(200)
expect(data?.title).toBe('مهمة اختبار')
expect(data?.priority).toBe('high')
expect(data?.completed).toBe(false)
taskId = data!.id
})
it('يجب أن يعرض المهام', async () => {
const { data } = await api.tasks.get()
expect(data?.total).toBeGreaterThan(0)
})
it('يجب أن يحذف مهمة', async () => {
const { data } = await api.tasks({ id: taskId }).delete(undefined, {
headers: {
authorization: 'Bearer demo-token-2026'
}
})
expect(data?.success).toBe(true)
})
})شغّل الاختبارات:
bun testلاحظ كيف استخدمنا treaty(app) مباشرة مع نسخة Elysia بدلاً من إجراء طلبات HTTP. يعالج ElysiaJS هذا داخلياً، مما يجعل الاختبارات سريعة وبسيطة — لا حاجة لتشغيل الخادم.
ElysiaJS مقابل Hono مقابل Express: متى تختار ماذا
| الميزة | ElysiaJS | Hono | Express |
|---|---|---|---|
| بيئة التشغيل | Bun أولاً | متعدد البيئات | Node.js |
| أمان الأنواع | من طرف لطرف (Eden) | مستوى المسار | يدوي |
| التحقق | مدمج (TypeBox) | محول Zod | يدوي/Joi |
| OpenAPI | مولد تلقائياً | يدوي/إضافة | swagger-jsdoc |
| الأداء | سريع جداً | سريع | متوسط |
| النظام البيئي | ينمو | ينمو | ضخم |
| منحنى التعلم | متوسط | منخفض | منخفض |
اختر ElysiaJS عندما: تريد أقصى أمان للأنواع، وتستخدم Bun بالفعل، وتقدر توثيق API التلقائي.
اختر Hono عندما: تحتاج دعم بيئات تشغيل متعددة (Cloudflare Workers، Deno) أو تفضل إطار عمل أخف.
اختر Express عندما: تحتاج أكبر نظام بيئي ولا تمانع إعداد الأنواع يدوياً.
استكشاف الأخطاء وإصلاحها
المشاكل الشائعة وحلولها:
"Cannot find module '@elysiajs/swagger'"
تأكد أنك ثبتّ بـ bun add، وليس npm install. إضافات ElysiaJS محسنة لـ Bun.
أخطاء الأنواع مع مراجع النماذج
تأكد من استدعاء .use(taskModel) قبل الإشارة إلى أسماء النماذج. يحل ElysiaJS الأنواع من خلال ترتيب تركيب الإضافات.
أخطاء "VALIDATION" على مدخلات صالحة
تحقق من أن رأس Content-Type: application/json مضبوط. يتحقق ElysiaJS بصرامة من أنواع محتوى الطلبات.
الخطوات التالية
الآن بعد أن لديك أساس متين، إليك طرق لتوسيع هذا المشروع:
- إضافة قاعدة بيانات: استبدل المخزن في الذاكرة بـ SQLite (مدمج في Bun) أو استخدم Drizzle ORM
- مصادقة JWT: استبدل توكنات Bearer بتوقيع JWT مناسب باستخدام
@elysiajs/jwt - دعم WebSocket: لدى ElysiaJS دعم WebSocket من الدرجة الأولى — أضف تحديثات المهام في الوقت الحقيقي
- رفع الملفات: تعامل مع نماذج multipart بالدعم المدمج
- النشر في الإنتاج: ElysiaJS يعمل بشكل ممتاز على Fly.io أو Railway أو أي مضيف Docker يشغل Bun
الخلاصة
يمثل ElysiaJS نهجاً جديداً لبناء واجهات برمجة تطبيقات TypeScript. بدلاً من إضافة أمان الأنواع على إطار عمل موجود، تم تصميمه من الألف إلى الياء لجعل الأنواع تتدفق بشكل طبيعي من تعريفات المسارات عبر التحقق إلى العميل.
الجمع بين سرعة Bun الخام، وتحقق TypeBox، وتوليد OpenAPI التلقائي، وعميل Eden Treaty الآمن الأنواع يخلق تجربة تطوير حيث يكتشف المترجم أخطاء التكامل قبل وصولها للإنتاج. هذه هي القوة الحقيقية لأمان الأنواع من طرف إلى طرف — ليس مجرد فحص أنواع الدوال الفردية، بل ضمان صحة سلسلة الطلب/الاستجابة بالكامل في وقت الترجمة.
إذا كنت تبدأ مشروع Bun جديداً وتقدر أمان الأنواع، فإن ElysiaJS يستحق اهتماماً جاداً.
ناقش مشروعك معنا
نحن هنا للمساعدة في احتياجات تطوير الويب الخاصة بك. حدد موعدًا لمناقشة مشروعك وكيف يمكننا مساعدتك.
دعنا نجد أفضل الحلول لاحتياجاتك.
مقالات ذات صلة

بناء واجهات REST API باستخدام Hono و Bun: البديل العصري لـ Express
تعلم كيفية بناء واجهات برمجية سريعة وآمنة باستخدام إطار Hono وبيئة تشغيل Bun. دليل شامل من الإعداد حتى النشر مع أمثلة عملية.

AI SDK 4.0: الميزات الجديدة وحالات الاستخدام
اكتشف الميزات الجديدة وحالات الاستخدام لـ AI SDK 4.0، بما في ذلك دعم PDF واستخدام الكمبيوتر والمزيد.

بناء أداة استخراج بيانات ذكية من الويب باستخدام Playwright و Claude API في TypeScript
تعلّم كيف تبني أداة استخراج بيانات ذكية تستخدم Playwright للتحكم بالمتصفح وClaude AI لفهم صفحات الويب واستخراج بيانات منظّمة — بدون محددات CSS هشّة.