في Bun، YAML هو مواطن من الدرجة الأولى جنبًا إلى جنب مع JSON و TOML. يمكنك:
- تحليل سلاسل YAML مع
Bun.YAML.parse importوrequireملفات YAML كوحدات في وقت التشغيل (بما في ذلك دعم إعادة التحميل الساخن ووضع المراقبة)importوrequireملفات YAML في تطبيقات الواجهة الأمامية عبر مجمع bun
المطابقة
محلل YAML في Bun يمرر حاليًا أكثر من 90% من مجموعة اختبارات YAML الرسمية. بينما نعمل بنشاط للوصول إلى 100% من المطابقة، يغطي التنفيذ الحالي الغالبية العظمى من حالات الاستخدام الواقعية. تم كتابة المحلل في Zig للحصول على أداء مثالي ويتم تحسينه باستمرار.
واجهة برمجة التطبيقات في وقت التشغيل
Bun.YAML.parse()
تحليل سلسلة YAML إلى كائن JavaScript.
import { YAML } from "bun";
const text = `
name: John Doe
age: 30
email: john@example.com
hobbies:
- reading
- coding
- hiking
`;
const data = YAML.parse(text);
console.log(data);
// {
// name: "John Doe",
// age: 30,
// email: "john@example.com",
// hobbies: ["reading", "coding", "hiking"]
// }YAML متعدد المستندات
عند تحليل YAML مع مستندات متعددة (مفصولة بـ ---)، ترجع Bun.YAML.parse() مصفوفة:
const multiDoc = `
---
name: Document 1
---
name: Document 2
---
name: Document 3
`;
const docs = Bun.YAML.parse(multiDoc);
console.log(docs);
// [
// { name: "Document 1" },
// { name: "Document 2" },
// { name: "Document 3" }
// ]ميزات YAML المدعومة
محلل YAML في Bun يدعم مواصفات YAML 1.2 الكاملة، بما في ذلك:
- القياسات: السلاسل، الأرقام، القيم المنطقية، قيم null
- المجموعات: المتتابعات (مصفوفات) والتعيينات (كائنات)
- المراسي والمراجع: عقد قابلة لإعادة الاستخدام مع
&و* - العلامات: تلميحات النوع مثل
!!str،!!int،!!float،!!bool،!!null - سلاسل متعددة الأسطر: حرفية (
|) ومطوية (>) - التعليقات: باستخدام
# - التوجيهات:
%YAMLو%TAG
const yaml = `
# سجل الموظف
employee: &emp
name: Jane Smith
department: Engineering
skills:
- JavaScript
- TypeScript
- React
manager: *emp # مرجع إلى employee
config: !!str 123 # نوع سلسلة صريح
description: |
هذا سلسلة حرفية
متعددة الأسطر تحافظ على
فواصل الأسطر والمسافات.
summary: >
هذه سلسلة مطوية
تربط الأسطر بمسافات
ما لم تكن هناك أسطر فارغة.
`;
const data = Bun.YAML.parse(yaml);معالجة الأخطاء
ترمي Bun.YAML.parse() خطأ SyntaxError إذا كان YAML غير صالح:
try {
Bun.YAML.parse("invalid: yaml: content:");
} catch (error) {
console.error("فشل تحليل YAML:", error.message);
}استيراد الوحدة النمطية
وحدات ES
يمكنك استيراد ملفات YAML مباشرة كوحدات ES. يتم تحليل محتوى YAML وجعله متاحًا كصادرات افتراضية ومسماة:
database:
host: localhost
port: 5432
name: myapp
redis:
host: localhost
port: 6379
features:
auth: true
rateLimit: true
analytics: falseالاستيراد الافتراضي
import config from "./config.yaml";
console.log(config.database.host); // "localhost"
console.log(config.redis.port); // 6379الاستيراد المسمى
يمكنك إزالة خصائص YAML على المستوى العلوي كواردات مسماة:
import { database, redis, features } from "./config.yaml";
console.log(database.host); // "localhost"
console.log(redis.port); // 6379
console.log(features.auth); // trueأو الجمع بين الاثنين:
import config, { database, features } from "./config.yaml";
// استخدام كائن config الكامل
console.log(config);
// أو استخدام أجزاء محددة
if (features.rateLimit) {
setupRateLimiting(database);
}CommonJS
يمكن أيضًا طلب ملفات YAML في CommonJS:
const config = require("./config.yaml");
console.log(config.database.name); // "myapp"
// إزالة الهيكلية تعمل أيضًا
const { database, redis } = require("./config.yaml");
console.log(database.port); // 5432إعادة التحميل الساخن مع YAML
واحدة من أقوى ميزات دعم YAML في Bun هي إعادة التحميل الساخن. عند تشغيل تطبيقك مع bun --hot، يتم اكتشاف التغييرات في ملفات YAML تلقائيًا وإعادة تحميلها بدون إغلاق الاتصالات
إعادة تحميل التكوين الساخن
server:
port: 3000
host: localhost
features:
debug: true
verbose: falseimport { server, features } from "./config.yaml";
console.log(`Starting server on ${server.host}:${server.port}`);
if (features.debug) {
console.log("Debug mode enabled");
}
// كود الخادم الخاص بك هنا
Bun.serve({
port: server.port,
hostname: server.host,
fetch(req) {
if (features.verbose) {
console.log(`${req.method} ${req.url}`);
}
return new Response("Hello World");
},
});تشغيل مع إعادة التحميل الساخن:
bun --hot server.tsالآن عند تعديل config.yaml، يتم عكس التغييرات على الفور في تطبيقك قيد التشغيل. هذا مثالي لـ:
- ضبط التكوين أثناء التطوير
- اختبار إعدادات مختلفة بدون إعادة تشغيل
- تصحيح الأخطاء المباشر مع تغييرات التكوين
- تبديل علم الميزة
إدارة التكوين
التكوين القائم على البيئة
يتفوق YAML في إدارة التكوين عبر بيئات مختلفة:
defaults: &defaults
timeout: 5000
retries: 3
cache:
enabled: true
ttl: 3600
development:
<<: *defaults
api:
url: http://localhost:4000
key: dev_key_12345
logging:
level: debug
pretty: true
staging:
<<: *defaults
api:
url: https://staging-api.example.com
key: ${STAGING_API_KEY}
logging:
level: info
pretty: false
production:
<<: *defaults
api:
url: https://api.example.com
key: ${PROD_API_KEY}
cache:
enabled: true
ttl: 86400
logging:
level: error
pretty: falseimport configs from "./config.yaml";
const env = process.env.NODE_ENV || "development";
const config = configs[env];
// يمكن استيفاء متغيرات البيئة في قيم YAML
function interpolateEnvVars(obj: any): any {
if (typeof obj === "string") {
return obj.replace(/\${(\w+)}/g, (_, key) => process.env[key] || "");
}
if (typeof obj === "object") {
for (const key in obj) {
obj[key] = interpolateEnvVars(obj[key]);
}
}
return obj;
}
export default interpolateEnvVars(config);تكوين علم الميزة
features:
newDashboard:
enabled: true
rolloutPercentage: 50
allowedUsers:
- admin@example.com
- beta@example.com
experimentalAPI:
enabled: false
endpoints:
- /api/v2/experimental
- /api/v2/beta
darkMode:
enabled: true
default: auto # auto, light, darkimport { features } from "./features.yaml";
export function isFeatureEnabled(featureName: string, userEmail?: string): boolean {
const feature = features[featureName];
if (!feature?.enabled) {
return false;
}
// التحقق من نسبة النشر
if (feature.rolloutPercentage < 100) {
const hash = hashCode(userEmail || "anonymous");
if (hash % 100 >= feature.rolloutPercentage) {
return false;
}
}
// التحقق من المستخدمين المسموح لهم
if (feature.allowedUsers && userEmail) {
return feature.allowedUsers.includes(userEmail);
}
return true;
}
// استخدم مع إعادة التحميل الساخن لتبديل الميزات في الوقت الفعلي
if (isFeatureEnabled("newDashboard", user.email)) {
renderNewDashboard();
} else {
renderLegacyDashboard();
}تكوين قاعدة البيانات
connections:
primary:
type: postgres
host: ${DB_HOST:-localhost}
port: ${DB_PORT:-5432}
database: ${DB_NAME:-myapp}
username: ${DB_USER:-postgres}
password: ${DB_PASS}
pool:
min: 2
max: 10
idleTimeout: 30000
cache:
type: redis
host: ${REDIS_HOST:-localhost}
port: ${REDIS_PORT:-6379}
password: ${REDIS_PASS}
db: 0
analytics:
type: clickhouse
host: ${ANALYTICS_HOST:-localhost}
port: 8123
database: analytics
migrations:
autoRun: ${AUTO_MIGRATE:-false}
directory: ./migrations
seeds:
enabled: ${SEED_DB:-false}
directory: ./seedsimport { connections, migrations } from "./database.yaml";
import { createConnection } from "./database-driver";
// تحليل متغيرات البيئة مع القيم الافتراضية
function parseConfig(config: any) {
return JSON.parse(
JSON.stringify(config).replace(
/\${([^:-]+)(?::([^}]+))?}/g,
(_, key, defaultValue) => process.env[key] || defaultValue || "",
),
);
}
const dbConfig = parseConfig(connections);
export const db = await createConnection(dbConfig.primary);
export const cache = await createConnection(dbConfig.cache);
export const analytics = await createConnection(dbConfig.analytics);
// تشغيل الترحيلات تلقائيًا إذا تم تكوينها
if (parseConfig(migrations).autoRun === "true") {
await runMigrations(db, migrations.directory);
}تكامل المجمع
عند استيراد ملفات YAML في تطبيقك وتجميعه مع Bun، يتم تحليل YAML في وقت البناء وتضمينه كوحدة نمطية JavaScript:
bun build app.ts --outdir=distهذا يعني:
- لا نفقات عامة لتحليل YAML في وقت التشغيل في الإنتاج
- أحجام حزم أصغر
- دعم اهتزاز الشجرة للتكوين غير المستخدم (الواردات المسماة)
الواردات الديناميكية
يمكن استيراد ملفات YAML بشكل ديناميكي، مفيدة لتحميل التكوين عند الطلب:
const env = process.env.NODE_ENV || "development";
const config = await import(`./configs/${env}.yaml`);
// تحميل إعدادات خاصة بالمستخدم
async function loadUserSettings(userId: string) {
try {
const settings = await import(`./users/${userId}/settings.yaml`);
return settings.default;
} catch {
return await import("./users/default-settings.yaml");
}
}