Skip to content

في 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.

ts
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() مصفوفة:

ts
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
ts
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 غير صالح:

ts
try {
  Bun.YAML.parse("invalid: yaml: content:");
} catch (error) {
  console.error("فشل تحليل YAML:", error.message);
}

استيراد الوحدة النمطية

وحدات ES

يمكنك استيراد ملفات YAML مباشرة كوحدات ES. يتم تحليل محتوى YAML وجعله متاحًا كصادرات افتراضية ومسماة:

yaml
database:
  host: localhost
  port: 5432
  name: myapp

redis:
  host: localhost
  port: 6379

features:
  auth: true
  rateLimit: true
  analytics: false

الاستيراد الافتراضي

ts
import config from "./config.yaml";

console.log(config.database.host); // "localhost"
console.log(config.redis.port); // 6379

الاستيراد المسمى

يمكنك إزالة خصائص YAML على المستوى العلوي كواردات مسماة:

ts
import { database, redis, features } from "./config.yaml";

console.log(database.host); // "localhost"
console.log(redis.port); // 6379
console.log(features.auth); // true

أو الجمع بين الاثنين:

ts
import config, { database, features } from "./config.yaml";

// استخدام كائن config الكامل
console.log(config);

// أو استخدام أجزاء محددة
if (features.rateLimit) {
  setupRateLimiting(database);
}

CommonJS

يمكن أيضًا طلب ملفات YAML في CommonJS:

ts
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 تلقائيًا وإعادة تحميلها بدون إغلاق الاتصالات

إعادة تحميل التكوين الساخن

yaml
server:
  port: 3000
  host: localhost

features:
  debug: true
  verbose: false
ts
import { 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");
  },
});

تشغيل مع إعادة التحميل الساخن:

bash
bun --hot server.ts

الآن عند تعديل config.yaml، يتم عكس التغييرات على الفور في تطبيقك قيد التشغيل. هذا مثالي لـ:

  • ضبط التكوين أثناء التطوير
  • اختبار إعدادات مختلفة بدون إعادة تشغيل
  • تصحيح الأخطاء المباشر مع تغييرات التكوين
  • تبديل علم الميزة

إدارة التكوين

التكوين القائم على البيئة

يتفوق 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: false
ts
import 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);

تكوين علم الميزة

yaml
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, dark
ts
import { 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();
}

تكوين قاعدة البيانات

yaml
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: ./seeds
ts
import { 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:

bash
bun build app.ts --outdir=dist

هذا يعني:

  • لا نفقات عامة لتحليل YAML في وقت التشغيل في الإنتاج
  • أحجام حزم أصغر
  • دعم اهتزاز الشجرة للتكوين غير المستخدم (الواردات المسماة)

الواردات الديناميكية

يمكن استيراد ملفات YAML بشكل ديناميكي، مفيدة لتحميل التكوين عند الطلب:

ts
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");
  }
}

Bun بواسطة www.bunjs.com.cn تحرير