إنتقل إلى المحتوى الرئيسي

مرجع API

مرجع كامل لـ @powerduck/conf-patch يتضمن تواقيع جميع العناصر المصدّرة وقيمها الافتراضية.

تتوفر نقطتا دخول:

  • @powerduck/conf-patch — جميع الوظائف أدناه: الطبقة الأساسية والملفات والتحقق من OpenAPI والأدوات المساعدة.
  • @powerduck/conf-patch/core — الجزء المتوافق مع المتصفح فقط: patchContent وsetContentValue وdeleteContentValue وPatchContentOptions ودوال التحقق والأنواع ConfigFormat وJsonPatchOp وJsonPathSegment.

الطبقة الأساسية (متوافقة مع المتصفح)​

patchContent​

تطبّق مصفوفة عمليات تصحيح RFC 6902 على سلسلة إعدادات. دالة نقية لا تصل إلى نظام الملفات.

function patchContent(
content: string,
ops: JsonPatchOp[],
format: ConfigFormat,
options?: PatchContentOptions,
): string;
المعلمةالنوعالوصف
contentstringمحتوى الإعدادات الخام، ويجب أن يكون صالحًا وفق format المحدد.
opsJsonPatchOp[]العمليات المطلوب تطبيقها بالترتيب. تعيد المصفوفة الفارغة content دون تغيير.
formatConfigFormat"json" | "jsonc" | "yaml".
options.strictbooleanعند true، وهي القيمة الافتراضية، تؤدي العملية الفاشلة إلى استثناء. عند false تُتخطى العملية ويُسجّل تحذير عبر console.warn.

تُعيد: محتوى الإعدادات بعد التعديل (string).

الاستثناءات: TypeError إذا لم يكن content سلسلة أو كانت ops غير صالحة؛ وخطأ يصف العملية الفاشلة عندما تكون strict مساوية لـ true.

import { patchContent } from "@powerduck/conf-patch/core";

patchContent(
'{"name": "app"}',
[{ op: "add", path: ["version"], value: "1.0.0" }],
"json",
);
// => '{\n "name": "app",\n "version": "1.0.0"\n}'

setContentValue​

تعيّن قيمة واحدة أو تنشئها. تستدعي داخليًا patchContent بعملية add واحدة. وفق RFC 6902، تستبدل add خاصية كائن موجودة أو تُدرج عنصرًا عند فهرس مصفوفة.

function setContentValue(
content: string,
path: readonly (string | number)[],
value: unknown,
format: ConfigFormat,
): string;
المعلمةالنوعالوصف
contentstringمحتوى الإعدادات الخام.
pathreadonly (string | number)[]مسار مقسّم إلى مقاطع، مثل ["server", "port"]. لا يجوز أن يكون فارغًا.
valueunknownالقيمة المراد كتابتها.
formatConfigFormatتنسيق الإعدادات.

تُعيد: المحتوى المحدّث (string).

setContentValue("server:\n port: 3000\n", ["server", "port"], 8080, "yaml");

deleteContentValue​

تحذف مفتاحًا أو عنصر مصفوفة. تستدعي داخليًا patchContent بعملية remove واحدة. يجب أن يكون المسار موجودًا.

function deleteContentValue(
content: string,
path: readonly (string | number)[],
format: ConfigFormat,
): string;
deleteContentValue(
'{"name": "app", "legacy": true}',
["legacy"],
"json",
);

PatchContentOptions​

interface PatchContentOptions {
/** When true, failed operations throw. When false, they are skipped with a warning. Default: true */
strict?: boolean;
}

طبقة الملفات (Node.js / Electron فقط)​

readConfigFile​

تقرأ نص UTF-8 من مسار محلي أو عنوان file://.

function readConfigFile(filePath: string): Promise<string>;
المعلمةالنوعالوصف
filePathstringمسار مطلق أو نسبي أو عنوان file://. لا يجوز أن يكون فارغًا.

تُعيد: محتوى UTF-8 الخام (Promise<string>).

الاستثناءات: عند تعذر القراءة، خطأ يتضمن إخفاق نظام الملفات الأساسي.


writeConfigFile​

تكتب المحتوى ذرّيًا باستخدام ملف مؤقت ثم إعادة تسميته، مع قفل ملف حصري افتراضيًا. تُنشأ المجلدات الأب قبل الحصول على القفل.

function writeConfigFile(
filePath: string,
content: string,
options?: WriteConfigOptions,
): Promise<void>;
المعلمةالنوعالوصف
filePathstringمسار ملف الإعدادات.
contentstringالمحتوى المراد كتابته، ويجب أن يكون سلسلة.
optionsWriteConfigOptionsانظر أدناه.

الاستثناءات: TypeError للمدخلات غير الصالحة؛ وتُغلّف أخطاء نظام الملفات عند الكتابة.

WriteConfigOptions​

الخيارالنوعالقيمة الافتراضيةالوصف
lockbooleantrueتفعيل قفل الملف أثناء الكتابة.
lockTimeoutMsnumberالقيمة الافتراضية لـ withFileLock ‏(10 ثوانٍ)أقصى انتظار للحصول على القفل، بالملّي ثانية.
lockRetryDelayMsnumberالقيمة الافتراضية لـ withFileLock ‏(25 ملّي ثانية)التأخير الأولي بين المحاولات، بالملّي ثانية، قبل الزيادة الأُسّية.
lockStaleThresholdMsnumberالقيمة الافتراضية لـ withFileLockعمر القفل بالملّي ثانية الذي يسمح بعده باستعادته.
allowStaleRecoverybooleanfalseالسماح باسترداد الأقفال القديمة تلقائيًا.
import { writeConfigFile } from "@powerduck/conf-patch";

await writeConfigFile("config.json", '{"name": "app"}');

patchConfigFile​

المعاملة الأساسية لطبقة الملفات: تقرأ داخل القفل، وتطبّق patchContent، وتكتب ذرّيًا فقط إذا تغيّر المحتوى. إذا لم تُحدّد options.format، يُكتشف التنسيق من الامتداد.

function patchConfigFile(
filePath: string,
ops: JsonPatchOp[],
options?: PatchConfigOptions,
): Promise<void>;
المعلمةالنوعالوصف
filePathstringمسار ملف الإعدادات. لا يجوز أن يكون فارغًا.
opsJsonPatchOp[]العمليات المراد تطبيقها. تعود المصفوفة الفارغة دون قراءة أو كتابة.
optionsPatchConfigOptionsانظر أدناه.

الاستثناءات: TypeError إذا كانت filePath فارغة أو خيارات القفل غير صالحة أو تعذر اكتشاف التنسيق دون تحديد format؛ وخطأ العملية عندما تكون strict مساوية لـ true.

PatchConfigOptions​

الخيارالنوعالقيمة الافتراضيةالوصف
formatConfigFormatاكتشاف تلقائيتنسيق محدد صراحةً، له الأولوية على الاكتشاف من الامتداد.
strictbooleantrueتؤدي العمليات الفاشلة إلى استثناءات.
lockbooleantrueتفعيل قفل الملفات.
lockTimeoutMsnumber10 ثوانٍقيمة غير سالبة. أقصى انتظار للقفل.
lockRetryDelayMsnumber25 ملّي ثانيةقيمة موجبة. التأخير الأولي لإعادة المحاولة.
lockStaleThresholdMsnumberمحسوبةقيمة موجبة. عمر القفل المطلوب لاستعادة القفل القديم.
allowStaleRecoverybooleanfalseاسترداد الأقفال القديمة تلقائيًا.
await patchConfigFile("config.json", [
{ op: "replace", path: ["server", "host"], value: "0.0.0.0" },
{ op: "add", path: ["server", "ssl"], value: true },
{ op: "remove", path: ["legacySection"] },
]);

setConfigValue​

تضيف قيمة متداخلة في ملف أو تستبدلها. تفوّض عملية add واحدة إلى patchConfigFile.

function setConfigValue(
filePath: string,
path: readonly (string | number)[],
value: unknown,
options?: PatchConfigOptions,
): Promise<void>;
await setConfigValue("config.yaml", ["database", "port"], 5432);

deleteConfigValue​

تحذف قيمة متداخلة موجودة من ملف. تفوّض عملية remove واحدة إلى patchConfigFile.

function deleteConfigValue(
filePath: string,
path: readonly (string | number)[],
options?: PatchConfigOptions,
): Promise<void>;
await deleteConfigValue("config.json", ["features", "betaPreview"]);

withFileLock​

تنفّذ دالة استدعاء راجع غير متزامنة عبر طابور داخل العملية وقفل ملف حصري (<file>.confedit.lock). تستخدم الأقفال رموز ملكية. لا يُستعاد القفل القديم إلا إذا كانت allowStaleRecovery مساوية لـ true وتجاوز عمره staleThresholdMs. لا تُفحص معرّفات PID عمدًا لأنها قد تُستخدم مجددًا.

function withFileLock<T>(
filePath: string,
callback: () => Promise<T>,
options?: FileLockOptions,
): Promise<T>;
المعلمةالنوعالوصف
filePathstringالملف المراد قفله.
callback() => Promise<T>العمل المطلوب تنفيذه أثناء الاحتفاظ بالقفل.
optionsFileLockOptionsانظر أدناه.

تُعيد: نتيجة callback ‏(Promise<T>). يُحرَّر القفل دائمًا في كتلة finally، حتى إذا أدت الدالة إلى استثناء.

FileLockOptions​

الخيارالنوعالقيمة الافتراضيةالوصف
timeoutMsnumber10000أقصى انتظار للقفل بالملّي ثانية. يجب أن يكون غير سالب.
retryDelayMsnumber25التأخير الأولي بالملّي ثانية. يجب أن يكون موجبًا. يزداد بمقدار 1.5 مرة حتى حد أقصى قدره 1000 ملّي ثانية.
staleThresholdMsnumbermax(timeoutMs * 2, 60000)عمر القفل الذي يسمح بالاستعادة، بالملّي ثانية. يجب أن يكون موجبًا.
allowStaleRecoverybooleanfalseاسترداد الأقفال القديمة تلقائيًا. معطّل افتراضيًا للعملية الرئيسية الواحدة في Electron لتجنب مقاطعة المعاملات النشطة.
import { withFileLock } from "@powerduck/conf-patch";

await withFileLock("state.json", async () => {
// ... read, modify, write ...
}, { timeoutMs: 5000 });

releaseAllLocalLocks​

تحذف جميع ملفات القفل التي تملكها العملية الحالية. استخدمها عند إغلاق التطبيق بعد اكتمال معاملات الملفات النشطة. للتنظيف غير المتزامن في Electron، امنع حدث الخروج الأول ثم استأنف الخروج بعد التنظيف، كما في الأمثلة. تُتجاهل إخفاقات الأقفال الفردية.

function releaseAllLocalLocks(): Promise<void>;

التحقق من OpenAPI​

validateOpenAPISpec​

تتحقق من محتوى OpenAPI/Swagger الخام بصيغة JSON أو YAML. يُعامل الإدخال بوصفه محتوى افتراضيًا، ولا يُفسَّر كمسار إلا عند inputKind: "file". يُفوّض التحقق إلى @powerduck/openapi-parser، وتضيف هذه الدالة ضوابط أمان لمعالجة الإدخال.

function validateOpenAPISpec(
input: string,
options?: ValidateOpenApiOptions,
): Promise<AnyOpenAPIDocument>;
المعلمةالنوعالوصف
inputstringمحتوى المواصفة الخام، أو مسار ملف عند inputKind: "file".
optionsValidateOpenApiOptionsانظر أدناه.

تُعيد: المستند الذي اجتاز التحقق عند النجاح (Promise<AnyOpenAPIDocument>).

الاستثناءات: TypeError للإدخال الفارغ أو غير النصي؛ وOpenApiValidationError للخيارات غير الصالحة أو فشل التحقق.


validateOpenAPIFile​

دالة مساعدة تستدعي validateOpenAPISpec مع inputKind: "file" وتضبط baseFilePath على المسار المعطى. تتطلب allowedRootDirectory.

function validateOpenAPIFile(
filePath: string,
options?: ValidateOpenApiOptions,
): Promise<AnyOpenAPIDocument>;
import { validateOpenAPIFile } from "@powerduck/conf-patch";

const doc = await validateOpenAPIFile("./configs/openapi.yaml", {
allowedRootDirectory: "./configs",
});

ValidateOpenApiOptions​

الخيارالنوعالقيمة الافتراضيةالوصف
inputKind"content" | "file""content"كيفية تفسير input.
baseFilePathstring—المسار الأساسي لسياق حل المراجع.
allowedRootDirectorystring—المجلد الجذر لملفات الإدخال. مطلوب عندما تكون inputKind مساوية لـ "file".
timeoutMsnumber15000المهلة القصوى للعملية، بالملّي ثانية.
maxInputBytesnumber5242880 ‏(5 ميغابايت)أقصى حجم للإدخال الخام، بالبايت.
maxDocumentNodesnumber100000أقصى عدد لعُقد المستند المحلّل، للحماية من حجب الخدمة.
maxDocumentDepthnumber100أقصى عمق للتداخل، للحماية من حجب الخدمة.
maxValidationErrorsnumber50أقصى عدد للأخطاء المضمّنة في الرسالة.
maxErrorMessageLengthnumber1000أقصى عدد للأحرف لكل خطأ تحقق.
signalAbortSignal—إشارة إلغاء اختيارية.

OpenApiValidationError​

خطأ منظم عند فشل التحقق. حوّل الأخطاء عند حدود التطبيق قبل إعادتها إلى العميل؛ فقد تحتوي الرسائل والأسباب على مسارات محلية أو تفاصيل المستند.

class OpenApiValidationError extends Error {
readonly code: string;
readonly cause?: unknown;
constructor(code: string, message: string, cause?: unknown);
}
الخاصيةالنوعالوصف
codestringرمز خطأ قابل للمعالجة برمجيًا؛ انظر الجدول أدناه.
messagestringتفاصيل مقروءة للمستخدم.
causeunknownخطأ أساسي اختياري.

رموز الأخطاء​

الرمزالمعنى
INVALID_OPTIONقُدّمت قيمة خيار غير صالحة.
INPUT_TOO_LARGEيتجاوز المحتوى الخام maxInputBytes.
INPUT_FILE_TOO_LARGEيتجاوز ملف الإدخال حد الحجم.
FILE_INPUT_FORBIDDENاستُخدم إدخال ملف دون allowedRootDirectory.
PATH_OUTSIDE_ROOTيقع مسار الملف بعد حله خارج allowedRootDirectory.
PARSE_ERRORتعذر تحليل محتوى JSON/YAML.
INVALID_DOCUMENT_SHAPEالمستند ليس كائن JSON.
UNSUPPORTED_VERSIONلا يعلن المستند إصدار OpenAPI/Swagger مدعومًا؛ تُقبل الإصدارات الرئيسية 2 و3 فقط.
DOCUMENT_TOO_DEEPيتجاوز عمق التداخل maxDocumentDepth.
DOCUMENT_TOO_LARGEيتجاوز عدد العُقد maxDocumentNodes.
SPEC_VALIDATION_FAILEDلم تجتز المواصفة التحقق من OpenAPI.
OPERATION_TIMEOUTتجاوزت العملية timeoutMs.
OPERATION_ABORTEDأُلغيت العملية عبر signal.
UNKNOWN_ERRORخطأ غير متوقع.

الأدوات المساعدة​

detectFormat​

تكتشف ConfigFormat من امتداد مسار الملف أو عنوان file://.

function detectFormat(filePath: string): ConfigFormat;
الامتدادالنتيجة
.json"json"
.jsonc"jsonc"
.yaml, .yml"yaml"
أي امتداد آخرينتج خطأ

normalizeFilePath​

تحوّل مسارًا محليًا أو عنوان file: إلى مسار مطلق بصيغة النظام، وتحافظ على المسافات الصالحة وأسماء الملفات بترميز Unicode.

function normalizeFilePath(filePath: string): string;

يُفك عنوان file: باستخدام fileURLToPath؛ ويُعاد المسار المطلق كما هو؛ ويُحل المسار النسبي بالاستناد إلى process.cwd().


دوال التحقق من الشروط​

تُعاد تصدير هذه الدوال للاستخدام المتقدم والوحدات الداخلية. نادرًا ما تحتاج شيفرة التطبيق إلى استدعائها مباشرةً.

assertNonEmptyString​

function assertNonEmptyString(value: unknown, label: string): asserts value is string;

تؤدي إلى TypeError ما لم تكن value سلسلة غير فارغة.

assertPatchPath​

function assertPatchPath(
path: readonly (string | number)[],
label?: string, // default "path"
): void;

تؤدي إلى استثناء ما لم تكن path مصفوفة غير فارغة تتكون مقاطعها من سلاسل غير فارغة أو أعداد صحيحة آمنة غير سالبة.

assertPatchOperations​

function assertPatchOperations(ops: JsonPatchOp[]): void;

تتحقق من كل عملية: يجب أن تكون op إحدى "add" | "replace" | "remove"، وأن تجتاز path فحص assertPatchPath، وأن تملك add/replace خاصية ذاتية باسم value.

assertConfigFormat​

function assertConfigFormat(format: ConfigFormat): void;

تؤدي إلى استثناء ما لم تكن format إحدى "json" أو "jsonc" أو "yaml".

getErrorMessage​

function getErrorMessage(error: unknown): string;

تُعيد error.message لمثيلات Error، وإلا فتُعيد String(error).

createError​

function createError(message: string, cause: unknown): Error;

تنشئ Error وتضيف خاصية cause باستخدام Object.defineProperty، مع بديل لبيئات التشغيل القديمة.


الأنواع​

ConfigFormat​

type ConfigFormat = "json" | "jsonc" | "yaml";

JsonPathSegment​

type JsonPathSegment = string | number;

JsonPatchOp​

interface JsonPatchOp {
op: "add" | "replace" | "remove";
path: JsonPathSegment[];
/** Required for "add" and "replace". */
value?: unknown;
}
حذر

تُدعم "add" و"replace" و"remove" فقط. استُبعدت "move" و"copy" و"test" عمدًا.

PatchConfigOptions​

interface PatchConfigOptions {
format?: ConfigFormat;
strict?: boolean;
lock?: boolean;
lockTimeoutMs?: number;
lockRetryDelayMs?: number;
lockStaleThresholdMs?: number;
/** Whether stale locks can be automatically reclaimed. Defaults to false. */
allowStaleRecovery?: boolean;
}

FileLockOptions​

interface FileLockOptions {
/** Max time to wait for a lock. Defaults to 10 seconds. */
timeoutMs?: number;
/** Initial retry delay. Defaults to 25ms. */
retryDelayMs?: number;
/** Explicit lock age after which recovery is allowed. */
staleThresholdMs?: number;
/** Whether stale locks can be automatically reclaimed. Defaults to false. */
allowStaleRecovery?: boolean;
}

WriteConfigOptions​

interface WriteConfigOptions {
lock?: boolean;
lockTimeoutMs?: number;
lockRetryDelayMs?: number;
lockStaleThresholdMs?: number;
allowStaleRecovery?: boolean;
}

PatchContentOptions​

interface PatchContentOptions {
strict?: boolean;
}

OpenApiInputKind​

type OpenApiInputKind = "content" | "file";

AnyOpenAPIDocument​

اتحاد بُنى مستندات OpenAPI/Swagger المدعومة التي يعيدها التحقق:

type AnyOpenAPIDocument =
| OpenAPIV2.Document // Swagger 2.0
| OpenAPIV3.Document // OpenAPI 3.0.x
| OpenAPIV3_1.Document // OpenAPI 3.1.x
| OpenAPIV3_2Document; // OpenAPI 3.2 (permissive structural type)

OpenAPIV3_2Document نوع بنيوي مرن:

interface OpenAPIV3_2Document {
openapi: string;
info: Record<string, unknown>;
paths?: Record<string, unknown>;
[key: string]: unknown;
}

ملخص الصادرات​

الرمزالمدخل الرئيسيالمسار الفرعي الأساسيالفئة
patchContent✓✓دالة
setContentValue✓✓دالة
deleteContentValue✓✓دالة
PatchContentOptions✓✓نوع
assertNonEmptyString✓✓دالة
assertPatchPath✓✓دالة
assertPatchOperations✓✓دالة
assertConfigFormat✓✓دالة
getErrorMessage✓✓دالة
createError✓✓دالة
ConfigFormat✓✓نوع
JsonPatchOp✓✓نوع
JsonPathSegment✓✓نوع
readConfigFile✓—دالة
writeConfigFile✓—دالة
WriteConfigOptions✓—نوع
patchConfigFile✓—دالة
setConfigValue✓—دالة
deleteConfigValue✓—دالة
withFileLock✓—دالة
releaseAllLocalLocks✓—دالة
PatchConfigOptions✓—نوع
FileLockOptions✓—نوع
detectFormat✓—دالة
normalizeFilePath✓—دالة
validateOpenAPISpec✓—دالة
validateOpenAPIFile✓—دالة
OpenApiValidationError✓—صنف
ValidateOpenApiOptions✓—نوع
OpenApiInputKind✓—نوع
AnyOpenAPIDocument✓—نوع